notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 0e21611645016b560f294386f2f279b2505531f1
parent bc8ed2c6428277f38608e8220dc617ebef62e3a2
Author: kernelkind <kernelkind@gmail.com>
Date:   Wed,  5 Feb 2025 16:55:00 -0500

cache LayoutJob

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck_columns/src/draft.rs | 2++
Mcrates/notedeck_columns/src/post.rs | 15+++++++++++++++
Mcrates/notedeck_columns/src/ui/note/post.rs | 23+++++++++++++++++++++--
3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/crates/notedeck_columns/src/draft.rs b/crates/notedeck_columns/src/draft.rs @@ -1,3 +1,4 @@ +use egui::text::LayoutJob; use poll_promise::Promise; use crate::{media_upload::Nip94Event, post::PostBuffer, ui::note::PostType, Error}; @@ -6,6 +7,7 @@ use std::collections::HashMap; #[derive(Default)] pub struct Draft { pub buffer: PostBuffer, + pub cur_layout: Option<(String, LayoutJob)>, // `PostBuffer::text_buffer` to current `LayoutJob` pub cur_mention_hint: Option<MentionHint>, pub uploaded_media: Vec<Nip94Event>, // media uploads to include pub uploading_media: Vec<Promise<Result<Nip94Event, Error>>>, // promises that aren't ready yet diff --git a/crates/notedeck_columns/src/post.rs b/crates/notedeck_columns/src/post.rs @@ -247,6 +247,7 @@ pub struct PostBuffer { pub mention_indicator: char, pub mentions: HashMap<MentionKey, MentionInfo>, mentions_key: MentionKey, + pub selected_mention: bool, // the start index of a mention is inclusive pub mention_starts: BTreeMap<usize, MentionKey>, // maps the mention start index with the correct `MentionKey` @@ -260,6 +261,7 @@ impl Default for PostBuffer { Self { mention_indicator: '@', mentions_key: 0, + selected_mention: false, text_buffer: Default::default(), mentions: Default::default(), mention_starts: Default::default(), @@ -306,6 +308,7 @@ impl PostBuffer { pub fn select_full_mention(&mut self, mention_key: usize, pk: Pubkey) { if let Some(info) = self.mentions.get_mut(&mention_key) { info.mention_type = MentionType::Finalized(pk); + self.selected_mention = true; } else { error!("Error selecting mention for index: {mention_key}. Have the following mentions: {:?}", self.mentions); } @@ -402,6 +405,18 @@ impl PostBuffer { job } + + pub fn need_new_layout(&self, cache: Option<&(String, LayoutJob)>) -> bool { + if let Some((text, _)) = cache { + if self.selected_mention { + return true; + } + + self.text_buffer != *text + } else { + true + } + } } fn char_indices_to_byte(text: &str, char_range: Range<usize>) -> Option<Range<usize>> { diff --git a/crates/notedeck_columns/src/ui/note/post.rs b/crates/notedeck_columns/src/ui/note/post.rs @@ -130,13 +130,28 @@ impl<'a> PostView<'a> { ); } + let mut updated_layout = false; let mut layouter = |ui: &egui::Ui, buf: &dyn TextBuffer, wrap_width: f32| { - let mut layout_job = if let Some(post_buffer) = downcast_post_buffer(buf) { - post_buffer.to_layout_job(ui) + if let Some(post_buffer) = downcast_post_buffer(buf) { + let maybe_job = if post_buffer.need_new_layout(self.draft.cur_layout.as_ref()) { + Some(post_buffer.to_layout_job(ui)) + } else { + None + }; + + if let Some(job) = maybe_job { + self.draft.cur_layout = Some((post_buffer.text_buffer.clone(), job)); + updated_layout = true; + } + }; + + let mut layout_job = if let Some((_, job)) = &self.draft.cur_layout { + job.clone() } else { error!("Failed to get custom mentions layouter"); text_edit_default_layout(ui, buf.as_str().to_owned(), wrap_width) }; + layout_job.wrap.max_width = wrap_width; ui.fonts(|f| f.layout_job(layout_job)) }; @@ -149,6 +164,10 @@ impl<'a> PostView<'a> { let out = textedit.show(ui); + if updated_layout { + self.draft.buffer.selected_mention = false; + } + if let Some(cursor_index) = get_cursor_index(&out.state.cursor.char_range()) { self.show_mention_hints(txn, ui, cursor_index, &out); }