aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs113
1 files changed, 103 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs
index d583293..8e38e7b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,6 +2,7 @@ use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
+use std::sync::Arc;
use iced::futures::{SinkExt, Stream, StreamExt};
use iced::widget::button::Status;
@@ -15,12 +16,13 @@ use iced::{stream, Color, Element, Subscription, Task, Theme};
use indexmap::{indexmap, IndexMap};
use jid::JID;
use keyring::Entry;
-use login_modal::LoginModal;
+use login_modal::{Creds, LoginModal};
use luz::chat::{Chat, Message as ChatMessage};
use luz::presence::{Offline, Presence};
use luz::CommandMessage;
use luz::{roster::Contact, user::User, LuzHandle, UpdateMessage};
use serde::{Deserialize, Serialize};
+use thiserror::Error;
use tokio::sync::{mpsc, oneshot};
use tokio_stream::wrappers::ReceiverStream;
use tracing::{error, info};
@@ -58,11 +60,6 @@ pub struct OpenChat {
pub struct NewChat;
-pub struct Creds {
- jid: String,
- password: String,
-}
-
impl Macaw {
pub fn new(client: Option<Client>, config: Config) -> Self {
let account;
@@ -112,11 +109,60 @@ impl Deref for Client {
}
}
-fn main() -> iced::Result {
+#[tokio::main]
+async fn main() -> iced::Result {
tracing_subscriber::fmt::init();
let cfg = confy::load("macaw", None).unwrap();
- let client: Option<(JID, LuzHandle, mpsc::Receiver<UpdateMessage>)> = None;
+ let entry = Entry::new("macaw", "macaw");
+ let mut client_creation_error: Option<Error> = None;
+ let mut creds: Option<Creds> = None;
+
+ match entry {
+ Ok(e) => {
+ let result = e.get_password();
+ match result {
+ Ok(c) => {
+ let result = toml::from_str(&c);
+ match result {
+ Ok(c) => creds = Some(c),
+ Err(e) => {
+ client_creation_error =
+ Some(Error::CredentialsLoad(CredentialsLoadError::Toml(e.into())))
+ }
+ }
+ }
+ Err(e) => match e {
+ keyring::Error::NoEntry => {}
+ _ => {
+ client_creation_error = Some(Error::CredentialsLoad(
+ CredentialsLoadError::Keyring(e.into()),
+ ))
+ }
+ },
+ }
+ }
+ Err(e) => {
+ client_creation_error = Some(Error::CredentialsLoad(CredentialsLoadError::Keyring(
+ e.into(),
+ )))
+ }
+ }
+
+ let mut client: Option<(JID, LuzHandle, mpsc::Receiver<UpdateMessage>)> = None;
+ if let Some(creds) = creds {
+ let jid = creds.jid.parse::<JID>();
+ match jid {
+ Ok(jid) => {
+ let luz = LuzHandle::new(jid.clone(), creds.password.to_string(), "macaw.db").await;
+ match luz {
+ Ok((handle, recv)) => client = Some((jid.as_bare(), handle, recv)),
+ Err(e) => client_creation_error = Some(Error::ClientCreation(e)),
+ }
+ }
+ Err(e) => client_creation_error = Some(Error::CredentialsLoad(e.into())),
+ }
+ }
if let Some((jid, luz_handle, update_recv)) = client {
let stream = ReceiverStream::new(update_recv);
@@ -137,8 +183,13 @@ fn main() -> iced::Result {
)
})
} else {
- iced::application("Macaw", Macaw::update, Macaw::view)
- .run_with(|| (Macaw::new(None, cfg), Task::none()))
+ if let Some(e) = client_creation_error {
+ iced::application("Macaw", Macaw::update, Macaw::view)
+ .run_with(|| (Macaw::new(None, cfg), Task::done(Message::Error(e))))
+ } else {
+ iced::application("Macaw", Macaw::update, Macaw::view)
+ .run_with(|| (Macaw::new(None, cfg), Task::none()))
+ }
}
}
@@ -156,6 +207,47 @@ pub enum Message {
CloseChat(JID),
MessageCompose(String),
SendMessage(JID, String),
+ Error(Error),
+}
+
+#[derive(Debug, Error, Clone)]
+pub enum Error {
+ #[error("failed to create Luz client: {0}")]
+ ClientCreation(#[from] luz::error::DatabaseError),
+ #[error("failed to save credentials: {0}")]
+ CredentialsSave(CredentialsSaveError),
+ #[error("failed to load credentials: {0}")]
+ CredentialsLoad(CredentialsLoadError),
+}
+
+#[derive(Debug, Error, Clone)]
+pub enum CredentialsSaveError {
+ #[error("keyring: {0}")]
+ Keyring(Arc<keyring::Error>),
+ #[error("toml serialisation: {0}")]
+ Toml(#[from] toml::ser::Error),
+}
+
+impl From<keyring::Error> for CredentialsSaveError {
+ fn from(e: keyring::Error) -> Self {
+ Self::Keyring(Arc::new(e))
+ }
+}
+
+#[derive(Debug, Error, Clone)]
+pub enum CredentialsLoadError {
+ #[error("keyring: {0}")]
+ Keyring(Arc<keyring::Error>),
+ #[error("toml serialisation: {0}")]
+ Toml(#[from] toml::de::Error),
+ #[error("invalid jid: {0}")]
+ JID(#[from] jid::ParseError),
+}
+
+impl From<keyring::Error> for CredentialsLoadError {
+ fn from(e: keyring::Error) -> Self {
+ Self::Keyring(Arc::new(e))
+ }
}
impl Macaw {
@@ -358,6 +450,7 @@ impl Macaw {
)
.discard()
}
+ Message::Error(error) => todo!("error notification toasts, logging?"),
}
}