feat: add archive

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2024-05-09 17:02:06 +02:00
parent 9ceaa4cd38
commit 56a63dbb7d
Signed by: kjuulh
GPG Key ID: 57B6E1465221F912
6 changed files with 56 additions and 10 deletions

View File

@ -25,6 +25,10 @@ pub enum Command {
description: String, description: String,
state: ItemState, state: ItemState,
}, },
ToggleItem {
root: String,
path: Vec<String>,
},
Move { Move {
root: String, root: String,
src: Vec<String>, src: Vec<String>,
@ -81,6 +85,9 @@ impl Commander {
&src.iter().map(|p| p.as_str()).collect::<Vec<_>>(), &src.iter().map(|p| p.as_str()).collect::<Vec<_>>(),
&dest.iter().map(|p| p.as_str()).collect::<Vec<_>>(), &dest.iter().map(|p| p.as_str()).collect::<Vec<_>>(),
)?, )?,
Command::ToggleItem { root, path } => self
.engine
.toggle_item(&root, &path.iter().map(|p| p.as_str()).collect::<Vec<_>>())?,
} }
self.storage.store(&self.engine)?; self.storage.store(&self.engine)?;

View File

@ -2,7 +2,7 @@ use std::{collections::BTreeMap, fmt::Display};
use anyhow::{anyhow, Context}; use anyhow::{anyhow, Context};
use crate::log::{Graph, GraphItem}; use crate::log::{Graph, GraphItem, ItemState};
#[derive(Default)] #[derive(Default)]
pub struct Engine { pub struct Engine {
@ -129,6 +129,22 @@ impl Engine {
.map(|_| ()) .map(|_| ())
.ok_or(anyhow!("item was not found")) .ok_or(anyhow!("item was not found"))
} }
pub fn toggle_item(&mut self, root: &str, path: &[&str]) -> anyhow::Result<()> {
if let Some(item) = self.get_mut(root, path) {
match item {
GraphItem::Item { state, .. } => match state {
ItemState::NotDone => *state = ItemState::Done,
ItemState::Done => *state = ItemState::NotDone,
},
_ => {
anyhow::bail!("{}.{:?} is not an item", root, path)
}
}
}
Ok(())
}
} }
impl Display for Engine { impl Display for Engine {

View File

@ -43,4 +43,10 @@ impl SharedEngine {
.unwrap() .unwrap()
.section_move(root, src_path, dest_path) .section_move(root, src_path, dest_path)
} }
pub fn toggle_item(&self, root: &str, path: &[&str]) -> anyhow::Result<()> {
self.inner.write().unwrap().toggle_item(root, path)?;
Ok(())
}
} }

View File

@ -63,12 +63,15 @@ impl<'a> App<'a> {
graph_explorer: GraphExplorer<'a>, graph_explorer: GraphExplorer<'a>,
) -> Self { ) -> Self {
Self { Self {
state,
root: root.into(), root: root.into(),
mode: Mode::View,
dialog: None, dialog: None,
command: None, command: None,
state,
graph_explorer, graph_explorer,
mode: Mode::View,
focus: AppFocus::Graph, focus: AppFocus::Graph,
} }
} }
@ -109,6 +112,7 @@ impl<'a> App<'a> {
} }
if command.is_quit() { if command.is_quit() {
self.focus = AppFocus::Graph;
self.dialog = None; self.dialog = None;
} }
} }
@ -138,6 +142,7 @@ impl<'a> App<'a> {
let root = self.root.clone(); let root = self.root.clone();
let path = self.graph_explorer.get_current_path(); let path = self.graph_explorer.get_current_path();
self.focus = AppFocus::Dialog;
self.dialog = Some(Dialog::CreateItem { self.dialog = Some(Dialog::CreateItem {
state: CreateItemState::new(root, path), state: CreateItemState::new(root, path),
}); });
@ -151,7 +156,7 @@ impl<'a> Widget for &mut App<'a> {
Self: Sized, Self: Sized,
{ {
StatefulWidget::render( StatefulWidget::render(
GraphExplorer::new(self.state.clone()), GraphExplorer::new(self.root.clone(), self.state.clone()),
area, area,
buf, buf,
&mut self.graph_explorer.inner, &mut self.graph_explorer.inner,

View File

@ -5,7 +5,7 @@ use hyperlog_core::log::GraphItem;
use itertools::Itertools; use itertools::Itertools;
use ratatui::{prelude::*, widgets::*}; use ratatui::{prelude::*, widgets::*};
use crate::{command_parser::Commands, state::SharedState}; use crate::{command_parser::Commands, commands::Command, state::SharedState};
pub struct GraphExplorer<'a> { pub struct GraphExplorer<'a> {
state: SharedState, state: SharedState,
@ -14,17 +14,20 @@ pub struct GraphExplorer<'a> {
} }
pub struct GraphExplorerState<'a> { pub struct GraphExplorerState<'a> {
root: String,
current_path: Option<&'a str>, current_path: Option<&'a str>,
current_position: Vec<usize>, current_position: Vec<usize>,
graph: Option<GraphItem>, graph: Option<GraphItem>,
} }
impl GraphExplorer<'_> { impl<'a> GraphExplorer<'a> {
pub fn new(state: SharedState) -> Self { pub fn new(root: String, state: SharedState) -> Self {
Self { Self {
state, state,
inner: GraphExplorerState::<'_> { inner: GraphExplorerState::<'a> {
root,
current_path: None, current_path: None,
current_position: Vec::new(), current_position: Vec::new(),
graph: None, graph: None,
@ -151,6 +154,13 @@ impl GraphExplorer<'_> {
pub(crate) fn interact(&mut self) -> anyhow::Result<()> { pub(crate) fn interact(&mut self) -> anyhow::Result<()> {
if !self.get_current_path().is_empty() { if !self.get_current_path().is_empty() {
tracing::info!("toggling state of items"); tracing::info!("toggling state of items");
self.state
.commander
.execute(hyperlog_core::commander::Command::ToggleItem {
root: self.inner.root.to_string(),
path: self.get_current_path(),
})?;
} }
Ok(()) Ok(())

View File

@ -39,10 +39,12 @@ pub async fn execute(state: State) -> Result<()> {
} }
fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: SharedState) -> Result<()> { fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: SharedState) -> Result<()> {
let mut graph_explorer = GraphExplorer::new(state.clone()); let root = "kjuulh".to_string();
let mut graph_explorer = GraphExplorer::new(root.clone(), state.clone());
graph_explorer.update_graph()?; graph_explorer.update_graph()?;
let mut app = App::new("kjuulh", state.clone(), graph_explorer); let mut app = App::new(&root, state.clone(), graph_explorer);
loop { loop {
terminal.draw(|f| render_app(f, &mut app))?; terminal.draw(|f| render_app(f, &mut app))?;