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