Skip to content

Commit

Permalink
Fix editor to save note on vim modal changes, (#57)
Browse files Browse the repository at this point in the history
Update core notebook state root to handle UpdateNoteContent event, not only in vim normal mode inner state.
Add note id field to UpdateNoteContent event.
Update tui to dispatch UpdateNoteContent event after user stops editing and escape the insert mode.
  • Loading branch information
panarch authored Nov 19, 2024
1 parent 28a83c8 commit 826a7b4
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 58 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions core/src/event.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::{
data::{Directory, Note},
types::DirectoryId,
types::{DirectoryId, NoteId},
},
strum_macros::Display,
};
Expand Down Expand Up @@ -64,7 +64,7 @@ pub enum NotebookEvent {
EditNote,
ViewNote,

UpdateNoteContent(String),
UpdateNoteContent { note_id: NoteId, content: String },

CloseEntryDialog,
}
Expand Down
10 changes: 5 additions & 5 deletions core/src/state/notebook/consume/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
data::{Directory, Note},
db::Db,
state::notebook::{DirectoryItem, InnerState, NotebookState, SelectedItem, VimNormalState},
types::NoteId,
Error, NotebookTransition, Result,
};

Expand Down Expand Up @@ -122,16 +123,15 @@ pub async fn view(state: &mut NotebookState) -> Result<NotebookTransition> {

pub async fn update_content(
db: &mut Db,
state: &mut NotebookState,
note_id: NoteId,
content: String,
) -> Result<NotebookTransition> {
let id = state.get_editing()?.id.clone();
let current = db.fetch_note_content(id.clone()).await?;
let current = db.fetch_note_content(note_id.clone()).await?;

if current == content {
Ok(NotebookTransition::None)
} else {
db.update_note_content(id, content).await?;
Ok(NotebookTransition::UpdateNoteContent)
db.update_note_content(note_id.clone(), content).await?;
Ok(NotebookTransition::UpdateNoteContent(note_id))
}
}
10 changes: 9 additions & 1 deletion core/src/state/notebook/inner_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ mod note_more_actions;
mod note_selected;
mod note_tree_number;

use crate::{db::Db, state::notebook::NotebookState, Event, NotebookTransition, Result};
use crate::{
db::Db,
state::notebook::{note, NotebookState},
Event, NotebookEvent, NotebookTransition, Result,
};
pub use editing_normal_mode::VimNormalState;
pub use editing_visual_mode::VimVisualState;

Expand All @@ -30,6 +34,10 @@ pub async fn consume(
) -> Result<NotebookTransition> {
use InnerState::*;

if let Event::Notebook(NotebookEvent::UpdateNoteContent { note_id, content }) = event {
return note::update_content(db, note_id, content).await;
}

match &state.inner_state {
NoteSelected => note_selected::consume(db, state, event).await,
DirectorySelected => directory_selected::consume(db, state, event).await,
Expand Down
66 changes: 24 additions & 42 deletions core/src/state/notebook/inner_state/editing_normal_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,29 @@ pub async fn consume(
event: Event,
) -> Result<NotebookTransition> {
match vim_state {
VimNormalState::Idle => consume_idle(db, state, event).await,
VimNormalState::Idle => consume_idle(state, event).await,
VimNormalState::Toggle => consume_toggle(db, state, event).await,
VimNormalState::Numbering(n) => consume_numbering(db, state, n, event).await,
VimNormalState::Gateway => consume_gateway(db, state, event).await,
VimNormalState::Yank(n) => consume_yank(db, state, n, event).await,
VimNormalState::Yank2(n1, n2) => consume_yank2(db, state, n1, n2, event).await,
VimNormalState::Delete(n) => consume_delete(db, state, n, event).await,
VimNormalState::Delete2(n1, n2) => consume_delete2(db, state, n1, n2, event).await,
VimNormalState::DeleteInside(n) => consume_delete_inside(db, state, n, event).await,
VimNormalState::Change(n) => consume_change(db, state, n, event).await,
VimNormalState::Change2(n1, n2) => consume_change2(db, state, n1, n2, event).await,
VimNormalState::ChangeInside(n) => consume_change_inside(db, state, n, event).await,
VimNormalState::Numbering(n) => consume_numbering(state, n, event).await,
VimNormalState::Gateway => consume_gateway(state, event).await,
VimNormalState::Yank(n) => consume_yank(state, n, event).await,
VimNormalState::Yank2(n1, n2) => consume_yank2(state, n1, n2, event).await,
VimNormalState::Delete(n) => consume_delete(state, n, event).await,
VimNormalState::Delete2(n1, n2) => consume_delete2(state, n1, n2, event).await,
VimNormalState::DeleteInside(n) => consume_delete_inside(state, n, event).await,
VimNormalState::Change(n) => consume_change(state, n, event).await,
VimNormalState::Change2(n1, n2) => consume_change2(state, n1, n2, event).await,
VimNormalState::ChangeInside(n) => consume_change_inside(state, n, event).await,
}
}

async fn consume_idle(
db: &mut Db,
state: &mut NotebookState,
event: Event,
) -> Result<NotebookTransition> {
async fn consume_idle(state: &mut NotebookState, event: Event) -> Result<NotebookTransition> {
use Event::*;
use NormalModeTransition::*;
use NotebookEvent as NE;

match event {
Notebook(NE::SelectNote(note)) => note::select(state, note),
Notebook(NE::SelectDirectory(directory)) => directory::select(state, directory),
Notebook(NE::UpdateNoteContent(content)) => note::update_content(db, state, content).await,
Key(KeyEvent::N) => {
state.inner_state = InnerState::NoteSelected;

Expand Down Expand Up @@ -189,14 +184,13 @@ async fn consume_toggle(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_numbering(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
Expand Down Expand Up @@ -292,17 +286,13 @@ async fn consume_numbering(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_gateway(
db: &mut Db,
state: &mut NotebookState,
event: Event,
) -> Result<NotebookTransition> {
async fn consume_gateway(state: &mut NotebookState, event: Event) -> Result<NotebookTransition> {
use Event::*;
use NormalModeTransition::*;

Expand All @@ -320,14 +310,13 @@ async fn consume_gateway(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_yank(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
Expand All @@ -354,14 +343,13 @@ async fn consume_yank(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_yank2(
db: &mut Db,
state: &mut NotebookState,
n1: usize,
n2: usize,
Expand Down Expand Up @@ -390,14 +378,13 @@ async fn consume_yank2(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_delete(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
Expand Down Expand Up @@ -440,14 +427,13 @@ async fn consume_delete(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_delete2(
db: &mut Db,
state: &mut NotebookState,
n1: usize,
n2: usize,
Expand Down Expand Up @@ -482,14 +468,13 @@ async fn consume_delete2(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_delete_inside(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
Expand All @@ -506,14 +491,13 @@ async fn consume_delete_inside(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_change(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
Expand Down Expand Up @@ -560,14 +544,13 @@ async fn consume_change(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_change2(
db: &mut Db,
state: &mut NotebookState,
n1: usize,
n2: usize,
Expand Down Expand Up @@ -620,14 +603,13 @@ async fn consume_change2(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
}

async fn consume_change_inside(
db: &mut Db,
state: &mut NotebookState,
n: usize,
event: Event,
Expand All @@ -644,7 +626,7 @@ async fn consume_change_inside(
event @ Key(_) => {
state.inner_state = InnerState::EditingNormalMode(VimNormalState::Idle);

consume_idle(db, state, event).await
consume_idle(state, event).await
}
_ => Err(Error::Wip("todo: Notebook::consume".to_owned())),
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub enum NotebookTransition {

SelectNote(Note),
SelectDirectory(Directory),
UpdateNoteContent,
UpdateNoteContent(NoteId),

Alert(String),

Expand Down
1 change: 1 addition & 0 deletions tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ tui-big-text = "0.7.0"
tui-textarea = "0.7.0"
home = "0.5.9"
tokio = { version = "1.41.0", features = ["macros", "rt-multi-thread"] }
throbber-widgets-tui = "0.8.0"
17 changes: 17 additions & 0 deletions tui/src/context/notebook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub struct NotebookContext {
pub struct EditorTab {
pub note: Note,
pub editor: TextArea<'static>,
pub dirty: bool,
}

impl Default for NotebookContext {
Expand Down Expand Up @@ -128,6 +129,21 @@ impl NotebookContext {
.editor
}

pub fn mark_dirty(&mut self) {
if let Some(tab) = self.tab_index.and_then(|i| self.tabs.get_mut(i)) {
tab.dirty = true;
}
}

pub fn mark_clean(&mut self, note_id: &NoteId) {
for tab in self.tabs.iter_mut() {
if &tab.note.id == note_id {
tab.dirty = false;
break;
}
}
}

pub fn close_tab(&mut self, note_id: &NoteId) {
self.tabs.retain(|tab| &tab.note.id != note_id);
}
Expand Down Expand Up @@ -198,6 +214,7 @@ impl NotebookContext {
let tab = EditorTab {
note,
editor: TextArea::from(content.lines()),
dirty: false,
};
self.tabs.push(tab);
self.tab_index = Some(self.tabs.len() - 1);
Expand Down
1 change: 1 addition & 0 deletions tui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ impl App {
self.handle_transition(transition).await;
}

self.save().await;
continue;
}

Expand Down
Loading

0 comments on commit 826a7b4

Please sign in to comment.