column.rs (4824B)
1 use crate::{ 2 actionbar::TimelineOpenResult, 3 route::{Route, Router}, 4 timeline::{Timeline, TimelineCache, TimelineKind}, 5 }; 6 use enostr::RelayPool; 7 use nostrdb::{Ndb, Transaction}; 8 use notedeck::NoteCache; 9 use std::iter::Iterator; 10 use tracing::warn; 11 12 #[derive(Clone, Debug)] 13 pub struct Column { 14 router: Router<Route>, 15 } 16 17 impl Column { 18 pub fn new(routes: Vec<Route>) -> Self { 19 let router = Router::new(routes); 20 Column { router } 21 } 22 23 pub fn router(&self) -> &Router<Route> { 24 &self.router 25 } 26 27 pub fn router_mut(&mut self) -> &mut Router<Route> { 28 &mut self.router 29 } 30 } 31 32 #[derive(Default, Debug)] 33 pub struct Columns { 34 /// Columns are simply routers into settings, timelines, etc 35 columns: Vec<Column>, 36 37 /// The selected column for key navigation 38 selected: i32, 39 } 40 41 impl Columns { 42 pub fn new() -> Self { 43 Columns::default() 44 } 45 46 pub fn add_new_timeline_column( 47 &mut self, 48 timeline_cache: &mut TimelineCache, 49 txn: &Transaction, 50 ndb: &Ndb, 51 note_cache: &mut NoteCache, 52 pool: &mut RelayPool, 53 kind: &TimelineKind, 54 ) -> Option<TimelineOpenResult> { 55 self.columns 56 .push(Column::new(vec![Route::timeline(kind.to_owned())])); 57 timeline_cache.open(ndb, note_cache, txn, pool, kind) 58 } 59 60 pub fn new_column_picker(&mut self) { 61 self.add_column(Column::new(vec![Route::AddColumn( 62 crate::ui::add_column::AddColumnRoute::Base, 63 )])); 64 } 65 66 pub fn insert_intermediary_routes( 67 &mut self, 68 timeline_cache: &mut TimelineCache, 69 intermediary_routes: Vec<IntermediaryRoute>, 70 ) { 71 let routes = intermediary_routes 72 .into_iter() 73 .map(|r| match r { 74 IntermediaryRoute::Timeline(timeline) => { 75 let route = Route::timeline(timeline.kind.clone()); 76 timeline_cache 77 .timelines 78 .insert(timeline.kind.clone(), timeline); 79 route 80 } 81 IntermediaryRoute::Route(route) => route, 82 }) 83 .collect(); 84 85 self.columns.push(Column::new(routes)); 86 } 87 88 pub fn add_column_at(&mut self, column: Column, index: u32) { 89 self.columns.insert(index as usize, column); 90 } 91 92 pub fn add_column(&mut self, column: Column) { 93 self.columns.push(column); 94 } 95 96 pub fn columns_mut(&mut self) -> &mut Vec<Column> { 97 &mut self.columns 98 } 99 100 pub fn num_columns(&self) -> usize { 101 self.columns.len() 102 } 103 104 // Get the first router in the columns if there are columns present. 105 // Otherwise, create a new column picker and return the router 106 pub fn get_first_router(&mut self) -> &mut Router<Route> { 107 if self.columns.is_empty() { 108 self.new_column_picker(); 109 } 110 self.columns[0].router_mut() 111 } 112 113 pub fn column(&self, ind: usize) -> &Column { 114 &self.columns[ind] 115 } 116 117 pub fn columns(&self) -> &[Column] { 118 &self.columns 119 } 120 121 pub fn selected(&mut self) -> &mut Column { 122 &mut self.columns[self.selected as usize] 123 } 124 125 pub fn column_mut(&mut self, ind: usize) -> &mut Column { 126 &mut self.columns[ind] 127 } 128 129 pub fn select_down(&mut self) { 130 warn!("todo: implement select_down"); 131 } 132 133 pub fn select_up(&mut self) { 134 warn!("todo: implement select_up"); 135 } 136 137 pub fn select_left(&mut self) { 138 if self.selected - 1 < 0 { 139 return; 140 } 141 self.selected -= 1; 142 } 143 144 pub fn select_right(&mut self) { 145 if self.selected + 1 >= self.columns.len() as i32 { 146 return; 147 } 148 self.selected += 1; 149 } 150 151 #[must_use = "you must call timeline_cache.pop() for each returned value"] 152 pub fn delete_column(&mut self, index: usize) -> Vec<TimelineKind> { 153 let mut kinds_to_pop: Vec<TimelineKind> = vec![]; 154 for route in self.columns[index].router().routes() { 155 if let Route::Timeline(kind) = route { 156 kinds_to_pop.push(kind.clone()); 157 } 158 } 159 160 self.columns.remove(index); 161 162 if self.columns.is_empty() { 163 self.new_column_picker(); 164 } 165 166 kinds_to_pop 167 } 168 169 pub fn move_col(&mut self, from_index: usize, to_index: usize) { 170 if from_index == to_index 171 || from_index >= self.columns.len() 172 || to_index >= self.columns.len() 173 { 174 return; 175 } 176 177 self.columns.swap(from_index, to_index); 178 } 179 } 180 181 pub enum IntermediaryRoute { 182 Timeline(Timeline), 183 Route(Route), 184 } 185 186 pub enum ColumnsAction { 187 Switch(usize, usize), // from Switch.0 to Switch.1, 188 Remove(usize), 189 }