use enostr::NoteId; use std::fmt::{self}; use crate::{ account_manager::AccountsRoute, timeline::{TimelineId, TimelineRoute}, }; /// App routing. These describe different places you can go inside Notedeck. #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum Route { Timeline(TimelineRoute), Accounts(AccountsRoute), Relays, } impl Route { pub fn timeline(timeline_id: TimelineId) -> Self { Route::Timeline(TimelineRoute::Timeline(timeline_id)) } pub fn timeline_id(&self) -> Option<&TimelineId> { if let Route::Timeline(TimelineRoute::Timeline(tid)) = self { Some(tid) } else { None } } pub fn relays() -> Self { Route::Relays } pub fn thread(thread_root: NoteId) -> Self { Route::Timeline(TimelineRoute::Thread(thread_root)) } pub fn reply(replying_to: NoteId) -> Self { Route::Timeline(TimelineRoute::Reply(replying_to)) } pub fn accounts() -> Self { Route::Accounts(AccountsRoute::Accounts) } pub fn add_account() -> Self { Route::Accounts(AccountsRoute::AddAccount) } } // TODO: add this to egui-nav so we don't have to deal with returning // and navigating headaches #[derive(Clone)] pub struct Router { routes: Vec, pub returning: bool, pub navigating: bool, } impl Router { pub fn new(routes: Vec) -> Self { if routes.is_empty() { panic!("routes can't be empty") } let returning = false; let navigating = false; Router { routes, returning, navigating, } } pub fn route_to(&mut self, route: R) { self.navigating = true; self.routes.push(route); } /// Go back, start the returning process pub fn go_back(&mut self) -> Option { if self.returning || self.routes.len() == 1 { return None; } self.returning = true; self.routes.get(self.routes.len() - 2).cloned() } /// Pop a route, should only be called on a NavRespose::Returned reseponse pub fn pop(&mut self) -> Option { if self.routes.len() == 1 { return None; } self.returning = false; self.routes.pop() } pub fn top(&self) -> &R { self.routes.last().expect("routes can't be empty") } pub fn routes(&self) -> &Vec { &self.routes } } impl fmt::Display for Route { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Route::Timeline(tlr) => match tlr { TimelineRoute::Timeline(name) => write!(f, "{}", name), TimelineRoute::Thread(_id) => write!(f, "Thread"), TimelineRoute::Reply(_id) => write!(f, "Reply"), }, Route::Relays => write!(f, "Relays"), Route::Accounts(amr) => match amr { AccountsRoute::Accounts => write!(f, "Accounts"), AccountsRoute::AddAccount => write!(f, "Add Account"), }, } } }