aboutsummaryrefslogblamecommitdiffstats
path: root/src/login_modal.rs
blob: f4e556ef208fce47ef585984fab9abe405f08c74 (plain) (tree)


















































































































































                                                                                                 
use iced::{
    futures::StreamExt,
    widget::{button, checkbox, column, container, text, text_input},
    Element, Task,
};
use jid::JID;
use luz::{
    presence::{Offline, Presence},
    LuzHandle,
};
use tokio_stream::wrappers::ReceiverStream;
use tracing::info;

use crate::Client;

#[derive(Default)]
pub struct LoginModal {
    jid: String,
    password: String,
    remember_me: bool,
    error: Option<Error>,
}

#[derive(Debug, Clone)]
pub enum Message {
    JID(String),
    Password(String),
    RememberMe,
    Submit,
    Error(Error),
}

#[derive(Debug, Clone)]
pub enum Error {
    InvalidJID(String),
    DatabaseConnection,
}

pub enum Action {
    None,
    ClientCreated(Task<crate::Message>),
}

impl LoginModal {
    pub fn update(&mut self, message: Message) -> Action {
        match message {
            Message::JID(j) => {
                self.jid = j;
                Action::None
            }
            Message::Password(p) => {
                self.password = p;
                Action::None
            }
            Message::RememberMe => {
                self.remember_me = !self.remember_me;
                Action::None
            }
            Message::Submit => {
                info!("submitting login");
                let jid_str = self.jid.clone();
                let password = self.password.clone();
                Action::ClientCreated(
                    Task::future(async move {
                        let jid: Result<JID, _> = jid_str.parse();
                        match jid {
                            Ok(j) => {
                                let result =
                                    LuzHandle::new(j.clone(), password.to_string(), "macaw.db")
                                        .await;
                                match result {
                                    Ok((luz_handle, receiver)) => {
                                        let stream = ReceiverStream::new(receiver);
                                        let stream =
                                            stream.map(|message| crate::Message::Luz(message));
                                        vec![
                                            Task::done(crate::Message::ClientCreated(Client {
                                                client: luz_handle,
                                                jid: j,
                                                connection_status: Presence::Offline(
                                                    Offline::default(),
                                                ),
                                            })),
                                            Task::stream(stream),
                                        ]
                                    }
                                    Err(_e) => {
                                        tracing::error!("error (database probably)");
                                        return vec![Task::done(crate::Message::LoginModal(
                                            Message::Error(Error::DatabaseConnection),
                                        ))];
                                    }
                                }
                            }
                            Err(_) => {
                                tracing::error!("parsing jid");
                                return vec![Task::done(crate::Message::LoginModal(
                                    Message::Error(Error::InvalidJID(jid_str.to_string())),
                                ))];
                            }
                        }
                    })
                    .then(|tasks| Task::batch(tasks)),
                )
            }
            Message::Error(error) => {
                self.error = Some(error);
                Action::None
            }
        }
    }

    pub fn view(&self) -> Element<Message> {
        container(
            column![
                text("Log In").size(24),
                column![
                    column![
                        text("JID").size(12),
                        text_input("berry@macaw.chat", &self.jid)
                            .on_input(|j| Message::JID(j))
                            .on_submit(Message::Submit)
                            .padding(5),
                    ]
                    .spacing(5),
                    column![
                        text("Password").size(12),
                        text_input("", &self.password)
                            .on_input(|p| Message::Password(p))
                            .on_submit(Message::Submit)
                            .secure(true)
                            .padding(5),
                    ]
                    .spacing(5),
                    checkbox("remember me", self.remember_me).on_toggle(|_| Message::RememberMe),
                    button(text("Submit")).on_press(Message::Submit),
                ]
                .spacing(10)
            ]
            .spacing(20),
        )
        .width(300)
        .padding(10)
        .style(container::rounded_box)
        .into()
    }
}