From dd9f41b04a5f9170a9f3935f708e857097b6b128 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Mon, 29 Jul 2024 11:24:55 -0500 Subject: [PATCH] threads: ensure we always handle bar results We were not handling it in ThreadView, now we do. Signed-off-by: William Casarin --- src/actionbar.rs | 36 ++++++++++++++++++++++++++++++++++-- src/app.rs | 15 ++++++++++++--- src/ui/thread.rs | 14 ++++++++++---- src/ui/timeline.rs | 25 +++++++++++++++---------- 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/actionbar.rs b/src/actionbar.rs index 576c50f..254bb51 100644 --- a/src/actionbar.rs +++ b/src/actionbar.rs @@ -14,8 +14,13 @@ pub enum BarAction { OpenThread, } +pub struct NewThreadNotes { + pub root_id: NoteId, + pub notes: Vec, +} + pub enum BarResult { - NewThreadNotes(Vec), + NewThreadNotes(NewThreadNotes), } /// open_thread is called when a note is selected and we need to navigate @@ -44,13 +49,22 @@ fn open_thread( let (thread, result) = match thread_res { ThreadResult::Stale(thread) => { let notes = Thread::new_notes(&thread.view.notes, root_id, txn, &app.ndb); + let br = if notes.is_empty() { + None + } else { + Some(BarResult::new_thread_notes( + notes, + NoteId::new(root_id.to_owned()), + )) + }; + // // we can't insert and update the VirtualList now, because we // are already borrowing it mutably. Let's pass it as a // result instead // // thread.view.insert(¬es); - (thread, Some(BarResult::NewThreadNotes(notes))) + (thread, br) } ThreadResult::Fresh(thread) => (thread, None), @@ -109,3 +123,21 @@ impl BarAction { } } } + +impl BarResult { + pub fn new_thread_notes(notes: Vec, root_id: NoteId) -> Self { + BarResult::NewThreadNotes(NewThreadNotes::new(notes, root_id)) + } +} + +impl NewThreadNotes { + pub fn new(notes: Vec, root_id: NoteId) -> Self { + NewThreadNotes { notes, root_id } + } + + /// Simple helper for processing a NewThreadNotes result. It simply + /// inserts/merges the notes into the thread cache + pub fn process(&self, thread: &mut Thread) { + thread.view.insert(&self.notes); + } +} diff --git a/src/app.rs b/src/app.rs index 3f270b2..fff2506 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,4 +1,5 @@ use crate::account_manager::AccountManager; +use crate::actionbar::BarResult; use crate::app_creation::setup_cc; use crate::app_style::user_requested_visuals_change; use crate::draft::Drafts; @@ -885,8 +886,6 @@ fn thread_unsubscribe(app: &mut Damus, id: &[u8; 32]) { let txn = Transaction::new(&app.ndb).expect("txn"); let root_id = crate::note::root_note_id_from_selected_id(app, &txn, id); - debug!("thread unsubbing from root_id {}", hex::encode(root_id)); - let thread = app.threads.thread_mut(&app.ndb, &txn, root_id).get_ptr(); let unsub = thread.decrement_sub(); @@ -958,7 +957,17 @@ fn render_nav(routes: Vec, timeline_ind: usize, app: &mut Damus, ui: &mut Route::Thread(id) => { let app = &mut app_ctx.borrow_mut(); - ui::ThreadView::new(app, timeline_ind, id.bytes()).ui(ui); + let result = ui::ThreadView::new(app, timeline_ind, id.bytes()).ui(ui); + + if let Some(bar_result) = result { + match bar_result { + BarResult::NewThreadNotes(new_notes) => { + let thread = app.threads.thread_expected_mut(new_notes.root_id.bytes()); + new_notes.process(thread); + } + } + } + None } diff --git a/src/ui/thread.rs b/src/ui/thread.rs index f1414e2..7ed4b89 100644 --- a/src/ui/thread.rs +++ b/src/ui/thread.rs @@ -1,4 +1,4 @@ -use crate::{timeline::TimelineSource, ui, Damus}; +use crate::{actionbar::BarResult, timeline::TimelineSource, ui, Damus}; use nostrdb::{NoteKey, Transaction}; use std::collections::HashSet; use tracing::warn; @@ -18,8 +18,9 @@ impl<'a> ThreadView<'a> { } } - pub fn ui(&mut self, ui: &mut egui::Ui) { + pub fn ui(&mut self, ui: &mut egui::Ui) -> Option { let txn = Transaction::new(&self.app.ndb).expect("txn"); + let mut result: Option = None; let selected_note_key = if let Ok(key) = self .app @@ -30,7 +31,7 @@ impl<'a> ThreadView<'a> { key } else { // TODO: render 404 ? - return; + return None; }; let scroll_id = egui::Id::new(( @@ -118,7 +119,10 @@ impl<'a> ThreadView<'a> { .show(ui); if let Some(action) = resp.action { - action.execute(self.app, self.timeline, note.id(), &txn); + let br = action.execute(self.app, self.timeline, note.id(), &txn); + if br.is_some() { + result = br; + } } }); @@ -128,5 +132,7 @@ impl<'a> ThreadView<'a> { 1 }); }); + + result } } diff --git a/src/ui/timeline.rs b/src/ui/timeline.rs index a6af4d8..8ea6af2 100644 --- a/src/ui/timeline.rs +++ b/src/ui/timeline.rs @@ -57,6 +57,13 @@ fn timeline_ui(ui: &mut egui::Ui, app: &mut Damus, timeline: usize, reversed: bo let view = app.timelines[timeline].current_view(); let len = view.notes.len(); let mut bar_result: Option = None; + let txn = if let Ok(txn) = Transaction::new(&app.ndb) { + txn + } else { + warn!("failed to create transaction"); + return 0; + }; + view.list .clone() .borrow_mut() @@ -72,13 +79,6 @@ fn timeline_ui(ui: &mut egui::Ui, app: &mut Damus, timeline: usize, reversed: bo let note_key = app.timelines[timeline].current_view().notes[ind].key; - let txn = if let Ok(txn) = Transaction::new(&app.ndb) { - txn - } else { - warn!("failed to create transaction for {:?}", note_key); - return 0; - }; - let note = if let Ok(note) = app.ndb.get_note_by_key(&txn, note_key) { note } else { @@ -111,12 +111,17 @@ fn timeline_ui(ui: &mut egui::Ui, app: &mut Damus, timeline: usize, reversed: bo if let Some(br) = bar_result { match br { // update the thread for next render if we have new notes - BarResult::NewThreadNotes(notes) => { - let view = app.timelines[timeline].current_view_mut(); - view.insert(¬es); + BarResult::NewThreadNotes(new_notes) => { + let thread = app + .threads + .thread_mut(&app.ndb, &txn, new_notes.root_id.bytes()) + .get_ptr(); + new_notes.process(thread); } } } + + 1 }); }