use eframe::{egui, epi}; use crate::{ matrix::{self, Session}, sync, }; pub mod login; pub mod session; /// Application state #[derive(Debug, Default)] pub struct App { view: View, } impl epi::App for App { fn name(&self) -> &str { "retrix" } fn setup( &mut self, _ctx: &egui::CtxRef, _frame: &epi::Frame, storage: Option<&dyn epi::Storage>, ) { let client = match Session::from_fs().and_then(Session::restore) { Ok(session) => session, _ => return, }; let view = self.view.make_main(client); if let Some(storage) = storage { storage .get_string("rooms") .and_then(|s| ron::from_str(&s).ok()) .map(|list| view.room_list = dbg!(list)); storage .get_string("entry") .and_then(|s| ron::from_str(&s).ok()) .map(|entry| view.entry = entry); } } fn save(&mut self, storage: &mut dyn epi::Storage) { match self.view { View::Login(ref login) => { if let Ok(login) = ron::to_string(login) { storage.set_string("login", login); } } View::Main(ref main) => { if let Ok(rooms) = ron::to_string(&main.room_list) { storage.set_string("rooms", rooms) } if let Ok(entry) = ron::to_string(&main.entry) { storage.set_string("entry", entry) } } } } fn on_exit(&mut self) { match self.view { View::Main(ref mut main) => { main.request.quit(); main.sync_handle.take().map(|t| t.join()); } _ => (), }; } fn update(&mut self, ctx: &egui::CtxRef, _frame: &epi::Frame) { match self.view { View::Login(ref mut login) => { if login.update(ctx) { let client = match matrix::login(&login.homeserver, &login.user, &login.password) { Ok(client) => client, Err(e) => { login.error = Some(e.to_string()); return; } }; self.view.make_main(client); } } View::Main(ref mut view) => view.update(ctx), }; } } /// Which view is currectly open #[derive(Debug)] pub enum View { Login(login::Login), Main(session::App), } impl View { pub fn make_main(&mut self, client: matrix_sdk::Client) -> &mut session::App { let (req_tx, req_rx) = tokio::sync::mpsc::unbounded_channel(); let (res_tx, res_rx) = crossbeam_channel::bounded(128); let client2 = client.clone(); let handle = std::thread::spawn(move || { sync::run(client2, req_rx, res_tx); }); let view = session::App::new(client, req_tx, res_rx, handle); for room in view.client.rooms() { view.request.room_name(room.room_id().clone()); } *self = View::Main(view); match *self { View::Main(ref mut main) => main, _ => unreachable!(), } } } impl Default for View { fn default() -> Self { View::Login(login::Login::default()) } } /// Named ID's for widgets that need one. #[derive(Debug, Clone, Copy, Hash)] pub enum Id { /// Side panel with the room list. RoomPanel, /// Top panel with room name an such. RoomSummary, /// Panel with members of a room. MemberList, /// Message entry. MessageEntry, /// Error message. ErrorPanel, /// Panel showing verification requests. VerificationPanel, /// Window for a SAS verification session. SasVerification, /// Window for a QR verification session. QrVerification, }