thread.rs (4710B)
1 use crate::{actionbar::BarResult, timeline::TimelineSource, ui, Damus}; 2 use nostrdb::{NoteKey, Transaction}; 3 use tracing::{error, warn}; 4 5 pub struct ThreadView<'a> { 6 app: &'a mut Damus, 7 timeline: usize, 8 selected_note_id: &'a [u8; 32], 9 } 10 11 impl<'a> ThreadView<'a> { 12 pub fn new(app: &'a mut Damus, timeline: usize, selected_note_id: &'a [u8; 32]) -> Self { 13 ThreadView { 14 app, 15 timeline, 16 selected_note_id, 17 } 18 } 19 20 pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<BarResult> { 21 let txn = Transaction::new(&self.app.ndb).expect("txn"); 22 let mut result: Option<BarResult> = None; 23 24 let selected_note_key = if let Ok(key) = self 25 .app 26 .ndb 27 .get_notekey_by_id(&txn, self.selected_note_id) 28 .map(NoteKey::new) 29 { 30 key 31 } else { 32 // TODO: render 404 ? 33 return None; 34 }; 35 36 let scroll_id = egui::Id::new(( 37 "threadscroll", 38 self.app.timelines[self.timeline].selected_view, 39 self.timeline, 40 selected_note_key, 41 )); 42 43 ui.label( 44 egui::RichText::new("Threads ALPHA! It's not done. Things will be broken.") 45 .color(egui::Color32::RED), 46 ); 47 48 egui::ScrollArea::vertical() 49 .id_source(scroll_id) 50 .animated(false) 51 .auto_shrink([false, false]) 52 .scroll_bar_visibility(egui::scroll_area::ScrollBarVisibility::AlwaysVisible) 53 .show(ui, |ui| { 54 let note = if let Ok(note) = self.app.ndb.get_note_by_key(&txn, selected_note_key) { 55 note 56 } else { 57 return; 58 }; 59 60 let root_id = { 61 let cached_note = self 62 .app 63 .note_cache_mut() 64 .cached_note_or_insert(selected_note_key, ¬e); 65 66 cached_note 67 .reply 68 .borrow(note.tags()) 69 .root() 70 .map_or_else(|| self.selected_note_id, |nr| nr.id) 71 }; 72 73 // poll for new notes and insert them into our existing notes 74 if let Err(e) = TimelineSource::Thread(root_id).poll_notes_into_view(&txn, self.app) 75 { 76 error!("Thread::poll_notes_into_view: {e}"); 77 } 78 79 let (len, list) = { 80 let thread = self 81 .app 82 .threads 83 .thread_mut(&self.app.ndb, &txn, root_id) 84 .get_ptr(); 85 86 let len = thread.view.notes.len(); 87 (len, &mut thread.view.list) 88 }; 89 90 list.clone() 91 .borrow_mut() 92 .ui_custom_layout(ui, len, |ui, start_index| { 93 ui.spacing_mut().item_spacing.y = 0.0; 94 ui.spacing_mut().item_spacing.x = 4.0; 95 96 let ind = len - 1 - start_index; 97 let note_key = { 98 let thread = self 99 .app 100 .threads 101 .thread_mut(&self.app.ndb, &txn, root_id) 102 .get_ptr(); 103 thread.view.notes[ind].key 104 }; 105 106 let note = if let Ok(note) = self.app.ndb.get_note_by_key(&txn, note_key) { 107 note 108 } else { 109 warn!("failed to query note {:?}", note_key); 110 return 0; 111 }; 112 113 ui::padding(8.0, ui, |ui| { 114 let textmode = self.app.textmode; 115 let resp = ui::NoteView::new(self.app, ¬e) 116 .note_previews(!textmode) 117 .show(ui); 118 119 if let Some(action) = resp.action { 120 let br = action.execute(self.app, self.timeline, note.id(), &txn); 121 if br.is_some() { 122 result = br; 123 } 124 } 125 }); 126 127 ui::hline(ui); 128 //ui.add(egui::Separator::default().spacing(0.0)); 129 130 1 131 }); 132 }); 133 134 result 135 } 136 }