My personal-knowledge-system, with deeply integrated task tracking and long term goal planning capabilities.
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Layouts for zk page

+85 -13
+19 -2
src/main.rs
··· 4 4 5 5 use std::{process, sync::Arc}; 6 6 7 - use crate::{cli::Cli, gui::FilViz, tui::TuiApp}; 7 + use crate::{ 8 + cli::Cli, 9 + config::Config, 10 + gui::FilViz, 11 + tui::TuiApp, 12 + types::{Kasten, KastenHandle, Workspace}, 13 + }; 8 14 use clap::Parser; 15 + use tokio::sync::RwLock; 16 + use tracing::{debug, info}; 9 17 10 18 mod cli; 11 19 mod gui; ··· 30 38 return rt.block_on(async { command.process().await }); 31 39 } 32 40 41 + // create the kasten handle 42 + let kh: KastenHandle = rt.block_on(async { 43 + let cfg = Config::parse()?; 44 + let ws = Workspace::instansiate(cfg.app_config.workspace).await?; 45 + Ok::<KastenHandle, color_eyre::Report>(Arc::new(RwLock::new(Kasten::index(ws).await?))) 46 + })?; 47 + 48 + debug!("{kh:#?}"); 49 + 33 50 // then we spawn the tui on its own thread 34 51 let tui_handle = std::thread::spawn({ 35 52 // arc stuff ··· 39 56 move || -> color_eyre::Result<()> { 40 57 // block the tui on the same runtime as above 41 58 tui_rt.block_on(async { 42 - let mut tui = TuiApp::new(args.tick_rate, args.frame_rate)?; 59 + let mut tui = TuiApp::new(args.tick_rate, args.frame_rate, kh)?; 43 60 tui.run().await?; 44 61 // just close everything as soon as the tui is done running 45 62 process::exit(0);
+5 -2
src/tui/app.rs
··· 11 11 use crate::{ 12 12 config::Config, 13 13 tui::{Event, Tui, components::Zk}, 14 + types::KastenHandle, 14 15 }; 15 16 16 17 use super::{components::Component, signal::Signal}; ··· 25 26 #[allow(dead_code)] 26 27 region: Region, 27 28 last_tick_key_events: Vec<KeyEvent>, 29 + kh: KastenHandle, 28 30 signal_tx: UnboundedSender<Signal>, 29 31 signal_rx: UnboundedReceiver<Signal>, 30 32 } ··· 43 45 44 46 impl App { 45 47 /// Construct a new `App` instance. 46 - pub fn new(tick_rate: f64, frame_rate: f64) -> Result<Self> { 48 + pub fn new(tick_rate: f64, frame_rate: f64, kh: KastenHandle) -> Result<Self> { 47 49 let (signal_tx, signal_rx) = mpsc::unbounded_channel(); 48 50 49 51 Ok(Self { 50 52 tick_rate, 51 53 frame_rate, 52 - components: vec![Box::new(Zk::new())], 54 + components: vec![Box::new(Zk::new(kh.clone()))], 53 55 should_quit: false, 54 56 should_suspend: false, 55 57 config: Config::parse()?, 56 58 region: Region::default(), 57 59 last_tick_key_events: Vec::new(), 60 + kh, 58 61 signal_tx, 59 62 signal_rx, 60 63 })
+56 -7
src/tui/components/zk/mod.rs
··· 1 1 use async_trait::async_trait; 2 - use color_eyre::eyre::Result; 3 - use ratatui::widgets::Paragraph; 2 + use color_eyre::{eyre::Result, owo_colors::colors::Red}; 3 + use ratatui::{prelude::*, widgets::Block}; 4 4 use tokio::sync::mpsc::UnboundedSender; 5 5 6 - use crate::tui::{Signal, components::Component}; 6 + use crate::{ 7 + tui::{Signal, components::Component}, 8 + types::KastenHandle, 9 + }; 7 10 8 11 mod zettel; 9 12 10 13 pub struct Zk { 11 14 signal_tx: Option<UnboundedSender<Signal>>, 15 + kh: KastenHandle, 16 + layouts: Layouts, 17 + } 18 + 19 + struct Layouts { 20 + left_right: Layout, 21 + search_zl: Layout, 22 + z_preview: Layout, 23 + } 24 + 25 + impl Default for Layouts { 26 + fn default() -> Self { 27 + Self { 28 + left_right: Layout::horizontal(vec![ 29 + Constraint::Percentage(50), 30 + Constraint::Percentage(50), 31 + ]), 32 + search_zl: Layout::vertical(vec![ 33 + Constraint::Percentage(15), 34 + Constraint::Percentage(85), 35 + ]), 36 + z_preview: Layout::vertical(vec![ 37 + Constraint::Percentage(30), 38 + Constraint::Percentage(70), 39 + ]), 40 + } 41 + } 12 42 } 13 43 14 44 impl Zk { 15 - pub const fn new() -> Self { 16 - Self { signal_tx: None } 45 + pub fn new(kh: KastenHandle) -> Self { 46 + Self { 47 + signal_tx: None, 48 + kh, 49 + layouts: Layouts::default(), 50 + } 17 51 } 18 52 } 19 53 ··· 45 79 frame: &mut ratatui::Frame, 46 80 area: ratatui::prelude::Rect, 47 81 ) -> color_eyre::Result<()> { 48 - let hello = Paragraph::new("Hello Surendra"); 49 - frame.render_widget(hello, area); 82 + let (search_layout, zettel_list_layout, zettel_layout, preview_layout) = { 83 + let rects = self.layouts.left_right.split(area); 84 + 85 + let (left, right) = (rects[0], rects[1]); 86 + 87 + let l_rects = self.layouts.search_zl.split(left); 88 + 89 + let r_rects = self.layouts.z_preview.split(right); 90 + 91 + (l_rects[0], l_rects[1], r_rects[0], r_rects[1]) 92 + }; 93 + 94 + frame.render_widget(Block::new().bg(Color::Red), search_layout); 95 + frame.render_widget(Block::new().bg(Color::Blue), zettel_list_layout); 96 + frame.render_widget(Block::new().bg(Color::Green), zettel_layout); 97 + frame.render_widget(Block::new().bg(Color::Yellow), preview_layout); 98 + 50 99 Ok(()) 51 100 } 52 101 }
+4 -1
src/types/kasten.rs
··· 6 6 petgraph::{Directed, graph::NodeIndex, prelude::StableGraph}, 7 7 }; 8 8 use rayon::iter::{ParallelBridge as _, ParallelIterator as _}; 9 - use std::{cmp::max, collections::HashMap}; 9 + use std::{cmp::max, collections::HashMap, sync::Arc}; 10 + use tokio::sync::RwLock; 10 11 11 12 use crate::types::Workspace; 12 13 ··· 34 35 const GRAPH_MIN_NODES: usize = 128; 35 36 /// Arbitrarily chosen minimum number of edges 36 37 const GRAPH_MIN_EDGES: usize = GRAPH_MIN_NODES * 3; 38 + 39 + pub type KastenHandle = Arc<RwLock<Kasten>>; 37 40 38 41 impl Kasten { 39 42 /// Indexes the `Workspace` and constructs a `Kasten`
+1 -1
src/types/mod.rs
··· 25 25 pub use link::Link; 26 26 27 27 mod kasten; 28 - #[expect(unused_imports)] 29 28 pub use kasten::Kasten; 29 + pub use kasten::KastenHandle; 30 30 31 31 mod frontmatter; 32 32 pub use frontmatter::FrontMatter;