diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 113 |
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?"), } } |