diff --git a/crates/notedeck_columns/src/draft.rs b/crates/notedeck_columns/src/draft.rs index 0bbf0afb..6ee7aed1 100644 --- 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, pub uploaded_media: Vec, // media uploads to include pub uploading_media: Vec>>, // promises that aren't ready yet diff --git a/crates/notedeck_columns/src/post.rs b/crates/notedeck_columns/src/post.rs index 20f3b6ee..9003644f 100644 --- 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, mentions_key: MentionKey, + pub selected_mention: bool, // the start index of a mention is inclusive pub mention_starts: BTreeMap, // 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) -> Option> { diff --git a/crates/notedeck_columns/src/ui/note/post.rs b/crates/notedeck_columns/src/ui/note/post.rs index d57f7c6a..c5fc5a9e 100644 --- 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); }