thread.rs (3998B)
1 use crate::{ 2 actionbar::NoteAction, 3 notes_holder::{NotesHolder, NotesHolderStorage}, 4 thread::Thread, 5 ui::note::NoteOptions, 6 }; 7 8 use nostrdb::{Ndb, Transaction}; 9 use notedeck::{ImageCache, MuteFun, NoteCache, UnknownIds}; 10 use tracing::error; 11 12 use super::timeline::TimelineTabView; 13 14 pub struct ThreadView<'a> { 15 threads: &'a mut NotesHolderStorage<Thread>, 16 ndb: &'a Ndb, 17 note_cache: &'a mut NoteCache, 18 unknown_ids: &'a mut UnknownIds, 19 img_cache: &'a mut ImageCache, 20 selected_note_id: &'a [u8; 32], 21 textmode: bool, 22 id_source: egui::Id, 23 } 24 25 impl<'a> ThreadView<'a> { 26 #[allow(clippy::too_many_arguments)] 27 pub fn new( 28 threads: &'a mut NotesHolderStorage<Thread>, 29 ndb: &'a Ndb, 30 note_cache: &'a mut NoteCache, 31 unknown_ids: &'a mut UnknownIds, 32 img_cache: &'a mut ImageCache, 33 selected_note_id: &'a [u8; 32], 34 textmode: bool, 35 ) -> Self { 36 let id_source = egui::Id::new("threadscroll_threadview"); 37 ThreadView { 38 threads, 39 ndb, 40 note_cache, 41 unknown_ids, 42 img_cache, 43 selected_note_id, 44 textmode, 45 id_source, 46 } 47 } 48 49 pub fn id_source(mut self, id: egui::Id) -> Self { 50 self.id_source = id; 51 self 52 } 53 54 pub fn ui(&mut self, ui: &mut egui::Ui, is_muted: &MuteFun) -> Option<NoteAction> { 55 let txn = Transaction::new(self.ndb).expect("txn"); 56 57 let selected_note_key = 58 if let Ok(key) = self.ndb.get_notekey_by_id(&txn, self.selected_note_id) { 59 key 60 } else { 61 // TODO: render 404 ? 62 return None; 63 }; 64 65 ui.label( 66 egui::RichText::new("Threads ALPHA! It's not done. Things will be broken.") 67 .color(egui::Color32::RED), 68 ); 69 70 egui::ScrollArea::vertical() 71 .id_salt(self.id_source) 72 .animated(false) 73 .auto_shrink([false, false]) 74 .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysVisible) 75 .show(ui, |ui| { 76 let note = if let Ok(note) = self.ndb.get_note_by_key(&txn, selected_note_key) { 77 note 78 } else { 79 return None; 80 }; 81 82 let root_id = { 83 let cached_note = self 84 .note_cache 85 .cached_note_or_insert(selected_note_key, ¬e); 86 87 cached_note 88 .reply 89 .borrow(note.tags()) 90 .root() 91 .map_or_else(|| self.selected_note_id, |nr| nr.id) 92 }; 93 94 let thread = self 95 .threads 96 .notes_holder_mutated(self.ndb, self.note_cache, &txn, root_id, is_muted) 97 .get_ptr(); 98 99 // TODO(jb55): skip poll if ThreadResult is fresh? 100 101 // poll for new notes and insert them into our existing notes 102 match thread.poll_notes_into_view(&txn, self.ndb, is_muted) { 103 Ok(action) => { 104 action.process_action(&txn, self.ndb, self.unknown_ids, self.note_cache) 105 } 106 Err(err) => error!("{err}"), 107 }; 108 109 // This is threadview. We are not the universe view... 110 let is_universe = false; 111 let mut note_options = NoteOptions::new(is_universe); 112 note_options.set_textmode(self.textmode); 113 114 TimelineTabView::new( 115 thread.view(), 116 true, 117 note_options, 118 &txn, 119 self.ndb, 120 self.note_cache, 121 self.img_cache, 122 ) 123 .show(ui) 124 }) 125 .inner 126 } 127 }