notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

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 }