-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
1,264 additions
and
480 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,145 @@ | ||
use crate::{route::Route, Damus}; | ||
use crate::{ | ||
note::NoteRef, | ||
route::Route, | ||
thread::{Thread, ThreadResult}, | ||
Damus, | ||
}; | ||
use enostr::NoteId; | ||
use nostrdb::Transaction; | ||
use tracing::{info, warn}; | ||
|
||
#[derive(Debug, Eq, PartialEq, Copy, Clone)] | ||
pub enum BarAction { | ||
Reply, | ||
OpenThread, | ||
} | ||
|
||
pub struct NewThreadNotes { | ||
pub root_id: NoteId, | ||
pub notes: Vec<NoteRef>, | ||
} | ||
|
||
pub enum BarResult { | ||
NewThreadNotes(NewThreadNotes), | ||
} | ||
|
||
/// open_thread is called when a note is selected and we need to navigate | ||
/// to a thread It is responsible for managing the subscription and | ||
/// making sure the thread is up to date. In a sense, it's a model for | ||
/// the thread view. We don't have a concept of model/view/controller etc | ||
/// in egui, but this is the closest thing to that. | ||
fn open_thread( | ||
app: &mut Damus, | ||
txn: &Transaction, | ||
timeline: usize, | ||
selected_note: &[u8; 32], | ||
) -> Option<BarResult> { | ||
{ | ||
let timeline = &mut app.timelines[timeline]; | ||
timeline | ||
.routes | ||
.push(Route::Thread(NoteId::new(selected_note.to_owned()))); | ||
timeline.navigating = true; | ||
} | ||
|
||
let root_id = crate::note::root_note_id_from_selected_id(app, txn, selected_note); | ||
let thread_res = app.threads.thread_mut(&app.ndb, txn, root_id); | ||
|
||
// The thread is stale, let's update it | ||
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, br) | ||
} | ||
|
||
ThreadResult::Fresh(thread) => (thread, None), | ||
}; | ||
|
||
// only start a subscription on nav and if we don't have | ||
// an active subscription for this thread. | ||
if thread.subscription().is_none() { | ||
*thread.subscription_mut() = app.ndb.subscribe(Thread::filters(root_id)).ok(); | ||
|
||
match thread.subscription() { | ||
Some(_sub) => { | ||
thread.subscribers += 1; | ||
info!( | ||
"Locally subscribing to thread. {} total active subscriptions, {} on this thread", | ||
app.ndb.subscription_count(), | ||
thread.subscribers, | ||
); | ||
} | ||
None => warn!( | ||
"Error subscribing locally to selected note '{}''s thread", | ||
hex::encode(selected_note) | ||
), | ||
} | ||
} else { | ||
thread.subscribers += 1; | ||
info!( | ||
"Re-using existing thread subscription. {} total active subscriptions, {} on this thread", | ||
app.ndb.subscription_count(), | ||
thread.subscribers, | ||
) | ||
} | ||
|
||
result | ||
} | ||
|
||
impl BarAction { | ||
pub fn execute(self, app: &mut Damus, timeline: usize, replying_to: &[u8; 32]) { | ||
pub fn execute( | ||
self, | ||
app: &mut Damus, | ||
timeline: usize, | ||
replying_to: &[u8; 32], | ||
txn: &Transaction, | ||
) -> Option<BarResult> { | ||
match self { | ||
BarAction::Reply => { | ||
let timeline = &mut app.timelines[timeline]; | ||
timeline | ||
.routes | ||
.push(Route::Reply(NoteId::new(replying_to.to_owned()))); | ||
timeline.navigating = true; | ||
None | ||
} | ||
|
||
BarAction::OpenThread => { | ||
let timeline = &mut app.timelines[timeline]; | ||
timeline | ||
.routes | ||
.push(Route::Thread(NoteId::new(replying_to.to_owned()))); | ||
timeline.navigating = true; | ||
} | ||
BarAction::OpenThread => open_thread(app, txn, timeline, replying_to), | ||
} | ||
} | ||
} | ||
|
||
impl BarResult { | ||
pub fn new_thread_notes(notes: Vec<NoteRef>, root_id: NoteId) -> Self { | ||
BarResult::NewThreadNotes(NewThreadNotes::new(notes, root_id)) | ||
} | ||
} | ||
|
||
impl NewThreadNotes { | ||
pub fn new(notes: Vec<NoteRef>, 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) { | ||
// threads are chronological, ie reversed from reverse-chronological, the default. | ||
let reversed = true; | ||
thread.view.insert(&self.notes, reversed); | ||
} | ||
} |
Oops, something went wrong.