Merge tagging fixes from kernel

Fixes the following:
1. space added after mention
2. can scroll the mention picker
3. don't lose focus of textedit after mention selection

kernelkind (6):
      rename `SearchResultsView` => `MentionPickerView`
      fix scroll regression
      mention-picker: re-add spacing from inner_margin
      mentions: don't lose focus after select mention
      TMP: update egui for better TextInputState handling
      insert space after mention selection

Fixes: https://github.com/damus-io/notedeck/issues/985
Fixes: https://github.com/damus-io/notedeck/issues/728
Fixes: https://github.com/damus-io/notedeck/issues/986

Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
William Casarin
2025-07-30 16:22:16 -07:00
7 changed files with 136 additions and 62 deletions

33
Cargo.lock generated
View File

@@ -1392,17 +1392,17 @@ checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
[[package]] [[package]]
name = "ecolor" name = "ecolor"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"emath 0.31.1 (git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc)", "emath 0.31.1 (git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd)",
"serde", "serde",
] ]
[[package]] [[package]]
name = "eframe" name = "eframe"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"ahash", "ahash",
"bytemuck", "bytemuck",
@@ -1438,24 +1438,25 @@ dependencies = [
[[package]] [[package]]
name = "egui" name = "egui"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"ahash", "ahash",
"backtrace", "backtrace",
"bitflags 2.9.1", "bitflags 2.9.1",
"emath 0.31.1 (git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc)", "emath 0.31.1 (git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd)",
"epaint", "epaint",
"log", "log",
"nohash-hasher", "nohash-hasher",
"profiling", "profiling",
"serde", "serde",
"similar",
] ]
[[package]] [[package]]
name = "egui-wgpu" name = "egui-wgpu"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"ahash", "ahash",
"bytemuck", "bytemuck",
@@ -1474,7 +1475,7 @@ dependencies = [
[[package]] [[package]]
name = "egui-winit" name = "egui-winit"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"ahash", "ahash",
"arboard", "arboard",
@@ -1492,7 +1493,7 @@ dependencies = [
[[package]] [[package]]
name = "egui_extras" name = "egui_extras"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"ahash", "ahash",
"egui", "egui",
@@ -1509,7 +1510,7 @@ dependencies = [
[[package]] [[package]]
name = "egui_glow" name = "egui_glow"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"ahash", "ahash",
"bytemuck", "bytemuck",
@@ -1588,7 +1589,7 @@ checksum = "9e4cadcff7a5353ba72b7fea76bf2122b5ebdbc68e8155aa56dfdea90083fe1b"
[[package]] [[package]]
name = "emath" name = "emath"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"serde", "serde",
@@ -1686,13 +1687,13 @@ dependencies = [
[[package]] [[package]]
name = "epaint" name = "epaint"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"ahash", "ahash",
"bytemuck", "bytemuck",
"ecolor", "ecolor",
"emath 0.31.1 (git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc)", "emath 0.31.1 (git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd)",
"epaint_default_fonts", "epaint_default_fonts",
"log", "log",
"nohash-hasher", "nohash-hasher",
@@ -1704,7 +1705,7 @@ dependencies = [
[[package]] [[package]]
name = "epaint_default_fonts" name = "epaint_default_fonts"
version = "0.31.1" version = "0.31.1"
source = "git+https://github.com/damus-io/egui?rev=041d4d18b16cf8be97e0d7ef5892c87436352dfc#041d4d18b16cf8be97e0d7ef5892c87436352dfc" source = "git+https://github.com/damus-io/egui?rev=a67ab901e197ce13948ff7d00aa6e07e31a68ccd#a67ab901e197ce13948ff7d00aa6e07e31a68ccd"
[[package]] [[package]]
name = "equator" name = "equator"
@@ -5348,6 +5349,12 @@ dependencies = [
"quote", "quote",
] ]
[[package]]
name = "similar"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
[[package]] [[package]]
name = "simplecss" name = "simplecss"
version = "0.2.2" version = "0.2.2"

View File

@@ -101,12 +101,12 @@ strip = true # Strip symbols from binary*
#egui_extras = { path = "/home/jb55/dev/github/emilk/egui/crates/egui_extras" } #egui_extras = { path = "/home/jb55/dev/github/emilk/egui/crates/egui_extras" }
#epaint = { path = "/home/jb55/dev/github/emilk/egui/crates/epaint" } #epaint = { path = "/home/jb55/dev/github/emilk/egui/crates/epaint" }
egui = { git = "https://github.com/damus-io/egui", rev = "041d4d18b16cf8be97e0d7ef5892c87436352dfc" } egui = { git = "https://github.com/damus-io/egui", rev = "a67ab901e197ce13948ff7d00aa6e07e31a68ccd" }
eframe = { git = "https://github.com/damus-io/egui", rev = "041d4d18b16cf8be97e0d7ef5892c87436352dfc" } eframe = { git = "https://github.com/damus-io/egui", rev = "a67ab901e197ce13948ff7d00aa6e07e31a68ccd" }
egui-winit = { git = "https://github.com/damus-io/egui", rev = "041d4d18b16cf8be97e0d7ef5892c87436352dfc" } egui-winit = { git = "https://github.com/damus-io/egui", rev = "a67ab901e197ce13948ff7d00aa6e07e31a68ccd" }
egui-wgpu = { git = "https://github.com/damus-io/egui", rev = "041d4d18b16cf8be97e0d7ef5892c87436352dfc" } egui-wgpu = { git = "https://github.com/damus-io/egui", rev = "a67ab901e197ce13948ff7d00aa6e07e31a68ccd" }
egui_extras = { git = "https://github.com/damus-io/egui", rev = "041d4d18b16cf8be97e0d7ef5892c87436352dfc" } egui_extras = { git = "https://github.com/damus-io/egui", rev = "a67ab901e197ce13948ff7d00aa6e07e31a68ccd" }
epaint = { git = "https://github.com/damus-io/egui", rev = "041d4d18b16cf8be97e0d7ef5892c87436352dfc" } epaint = { git = "https://github.com/damus-io/egui", rev = "a67ab901e197ce13948ff7d00aa6e07e31a68ccd" }
puffin = { git = "https://github.com/jb55/puffin", package = "puffin", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" } puffin = { git = "https://github.com/jb55/puffin", package = "puffin", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" }
puffin_egui = { git = "https://github.com/jb55/puffin", package = "puffin_egui", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" } puffin_egui = { git = "https://github.com/jb55/puffin", package = "puffin_egui", rev = "c6a6242adaf90b6292c0f462d2acd34d96d224d2" }
#winit = { git = "https://github.com/damus-io/winit", rev = "14d61a74bee0c9863abe7ef28efae2c4d8bd3743" } #winit = { git = "https://github.com/damus-io/winit", rev = "14d61a74bee0c9863abe7ef28efae2c4d8bd3743" }

View File

@@ -1,4 +1,8 @@
use egui::{text::LayoutJob, TextBuffer, TextFormat}; use egui::{
text::{CCursor, CCursorRange, LayoutJob},
text_edit::TextEditOutput,
TextBuffer, TextEdit, TextFormat,
};
use enostr::{FullKeypair, Pubkey}; use enostr::{FullKeypair, Pubkey};
use nostrdb::{Note, NoteBuilder, NoteReply}; use nostrdb::{Note, NoteBuilder, NoteReply};
use std::{ use std::{
@@ -270,6 +274,36 @@ impl Default for PostBuffer {
} }
} }
/// New cursor index (indexed by characters) after operation is performed
#[must_use = "must call MentionSelectedResponse::process"]
pub struct MentionSelectedResponse {
pub next_cursor_index: usize,
}
impl MentionSelectedResponse {
pub fn process(&self, ctx: &egui::Context, text_edit_output: &TextEditOutput) {
let text_edit_id = text_edit_output.response.id;
let Some(mut before_state) = TextEdit::load_state(ctx, text_edit_id) else {
return;
};
let mut new_cursor = text_edit_output
.galley
.from_ccursor(CCursor::new(self.next_cursor_index));
new_cursor.ccursor.prefer_next_row = true;
before_state
.cursor
.set_char_range(Some(CCursorRange::one(CCursor::new(
self.next_cursor_index,
))));
ctx.memory_mut(|mem| mem.request_focus(text_edit_id));
TextEdit::store_state(ctx, text_edit_id, before_state);
}
}
impl PostBuffer { impl PostBuffer {
pub fn get_new_mentions_key(&mut self) -> usize { pub fn get_new_mentions_key(&mut self) -> usize {
let prev = self.mentions_key; let prev = self.mentions_key;
@@ -319,15 +353,21 @@ impl PostBuffer {
mention_key: usize, mention_key: usize,
full_name: &str, full_name: &str,
pk: Pubkey, pk: Pubkey,
) { ) -> Option<MentionSelectedResponse> {
if let Some(info) = self.mentions.get(&mention_key) { let Some(info) = self.mentions.get(&mention_key) else {
let text_start_index = info.start_index + 1;
self.delete_char_range(text_start_index..info.end_index);
self.insert_text(full_name, text_start_index);
self.select_full_mention(mention_key, pk);
} else {
error!("Error selecting mention for index: {mention_key}. Have the following mentions: {:?}", self.mentions); error!("Error selecting mention for index: {mention_key}. Have the following mentions: {:?}", self.mentions);
} return None;
};
let text_start_index = info.start_index + 1; // increment by one to exclude the mention indicator, '@'
self.delete_char_range(text_start_index..info.end_index);
let text_chars_inserted = self.insert_text(full_name, text_start_index);
self.select_full_mention(mention_key, pk);
let space_chars_inserted = self.insert_text(" ", text_start_index + text_chars_inserted);
Some(MentionSelectedResponse {
next_cursor_index: text_start_index + text_chars_inserted + space_chars_inserted,
})
} }
pub fn delete_mention(&mut self, mention_key: usize) { pub fn delete_mention(&mut self, mention_key: usize) {
@@ -917,9 +957,9 @@ mod tests {
assert_eq!(buf.mentions.len(), 1); assert_eq!(buf.mentions.len(), 1);
assert_eq!(buf.mentions.get(&0).unwrap().bounds(), 0..3); assert_eq!(buf.mentions.get(&0).unwrap().bounds(), 0..3);
buf.select_mention_and_replace_name(0, "jb55", JB55()); buf.select_mention_and_replace_name(0, "jb55", JB55());
assert_eq!(buf.as_str(), "@jb55"); assert_eq!(buf.as_str(), "@jb55 ");
buf.insert_text(" test", 5); buf.insert_text("test", 6);
assert_eq!(buf.as_str(), "@jb55 test"); assert_eq!(buf.as_str(), "@jb55 test");
assert_eq!(buf.mentions.len(), 1); assert_eq!(buf.mentions.len(), 1);
@@ -1201,16 +1241,20 @@ mod tests {
buf.insert_text("@jb", 0); buf.insert_text("@jb", 0);
buf.select_mention_and_replace_name(0, "jb55", JB55()); buf.select_mention_and_replace_name(0, "jb55", JB55());
buf.insert_text(" test ", 5); buf.insert_text("test ", 6);
assert_eq!(buf.as_str(), "@jb55 test ");
buf.insert_text("@kernel", 11); buf.insert_text("@kernel", 11);
buf.select_mention_and_replace_name(1, "KernelKind", KK()); buf.select_mention_and_replace_name(1, "KernelKind", KK());
buf.insert_text(" test", 22); assert_eq!(buf.as_str(), "@jb55 test @KernelKind ");
buf.insert_text("test", 23);
assert_eq!(buf.as_str(), "@jb55 test @KernelKind test"); assert_eq!(buf.as_str(), "@jb55 test @KernelKind test");
assert_eq!(buf.mentions.len(), 2); assert_eq!(buf.mentions.len(), 2);
buf.insert_text(" ", 5);
buf.insert_text("@els", 6); buf.insert_text("@els", 6);
assert_eq!(buf.as_str(), "@jb55 @elstest @KernelKind test");
assert_eq!(buf.mentions.len(), 3); assert_eq!(buf.mentions.len(), 3);
assert_eq!(buf.mentions.get(&2).unwrap().bounds(), 6..10); assert_eq!(buf.mentions.get(&2).unwrap().bounds(), 6..10);
buf.select_mention_and_replace_name(2, "elsat", JB55()); buf.select_mention_and_replace_name(2, "elsat", JB55());

View File

@@ -11,19 +11,21 @@ use notedeck_ui::{
}; };
use tracing::error; use tracing::error;
pub struct SearchResultsView<'a> { /// Displays user profiles for the user to pick from.
/// Useful for manually typing a username and selecting the profile desired
pub struct MentionPickerView<'a> {
ndb: &'a Ndb, ndb: &'a Ndb,
txn: &'a Transaction, txn: &'a Transaction,
img_cache: &'a mut Images, img_cache: &'a mut Images,
results: &'a Vec<&'a [u8; 32]>, results: &'a Vec<&'a [u8; 32]>,
} }
pub enum SearchResultsResponse { pub enum MentionPickerResponse {
SelectResult(Option<usize>), SelectResult(Option<usize>),
DeleteMention, DeleteMention,
} }
impl<'a> SearchResultsView<'a> { impl<'a> MentionPickerView<'a> {
pub fn new( pub fn new(
img_cache: &'a mut Images, img_cache: &'a mut Images,
ndb: &'a Ndb, ndb: &'a Ndb,
@@ -38,8 +40,8 @@ impl<'a> SearchResultsView<'a> {
} }
} }
fn show(&mut self, ui: &mut egui::Ui, width: f32) -> SearchResultsResponse { fn show(&mut self, ui: &mut egui::Ui, width: f32) -> MentionPickerResponse {
let mut search_results_selection = None; let mut selection = None;
ui.vertical(|ui| { ui.vertical(|ui| {
for (i, res) in self.results.iter().enumerate() { for (i, res) in self.results.iter().enumerate() {
let profile = match self.ndb.get_profile_by_pubkey(self.txn, res) { let profile = match self.ndb.get_profile_by_pubkey(self.txn, res) {
@@ -54,16 +56,16 @@ impl<'a> SearchResultsView<'a> {
.add(user_result(&profile, self.img_cache, i, width)) .add(user_result(&profile, self.img_cache, i, width))
.clicked() .clicked()
{ {
search_results_selection = Some(i) selection = Some(i)
} }
} }
}); });
SearchResultsResponse::SelectResult(search_results_selection) MentionPickerResponse::SelectResult(selection)
} }
pub fn show_in_rect(&mut self, rect: egui::Rect, ui: &mut egui::Ui) -> SearchResultsResponse { pub fn show_in_rect(&mut self, rect: egui::Rect, ui: &mut egui::Ui) -> MentionPickerResponse {
let widget_id = ui.id().with("search_results"); let widget_id = ui.id().with("mention_results");
let area_resp = egui::Area::new(widget_id) let area_resp = egui::Area::new(widget_id)
.order(egui::Order::Foreground) .order(egui::Order::Foreground)
.fixed_pos(rect.left_top()) .fixed_pos(rect.left_top())
@@ -72,10 +74,10 @@ impl<'a> SearchResultsView<'a> {
let inner_margin_size = 8.0; let inner_margin_size = 8.0;
egui::Frame::NONE egui::Frame::NONE
.fill(ui.visuals().panel_fill) .fill(ui.visuals().panel_fill)
.inner_margin(inner_margin_size)
.show(ui, |ui| { .show(ui, |ui| {
let width = rect.width() - (2.0 * inner_margin_size); let width = rect.width() - (2.0 * inner_margin_size);
ui.allocate_space(vec2(ui.available_width(), inner_margin_size));
let close_button_resp = { let close_button_resp = {
let close_button_size = 16.0; let close_button_size = 16.0;
let (close_section_rect, _) = ui.allocate_exact_size( let (close_section_rect, _) = ui.allocate_exact_size(
@@ -95,16 +97,16 @@ impl<'a> SearchResultsView<'a> {
.inner .inner
}; };
ui.add_space(8.0); ui.allocate_space(vec2(ui.available_width(), inner_margin_size));
let scroll_resp = ScrollArea::vertical() let scroll_resp = ScrollArea::vertical()
.max_width(width) .max_width(rect.width())
.auto_shrink(Vec2b::FALSE) .auto_shrink(Vec2b::FALSE)
.show(ui, |ui| self.show(ui, width)); .show(ui, |ui| self.show(ui, width));
ui.advance_cursor_after_rect(rect); ui.advance_cursor_after_rect(rect);
if close_button_resp { if close_button_resp {
SearchResultsResponse::DeleteMention MentionPickerResponse::DeleteMention
} else { } else {
scroll_resp.inner scroll_resp.inner
} }
@@ -128,7 +130,18 @@ fn user_result<'a>(
let spacing = 8.0; let spacing = 8.0;
let body_font_size = get_font_size(ui.ctx(), &NotedeckTextStyle::Body); let body_font_size = get_font_size(ui.ctx(), &NotedeckTextStyle::Body);
let helper = AnimationHelper::new(ui, ("user_result", index), vec2(width, max_image)); let animation_rect = {
let max_width = ui.available_width();
let extra_width = (max_width - width) / 2.0;
let left = ui.cursor().left();
let (rect, _) =
ui.allocate_exact_size(vec2(width + extra_width, max_image), egui::Sense::click());
let (_, right) = rect.split_left_right_at_x(left + extra_width);
right
};
let helper = AnimationHelper::new_from_rect(ui, ("user_result", index), animation_rect);
let icon_rect = { let icon_rect = {
let r = helper.get_animation_rect(); let r = helper.get_animation_rect();

View File

@@ -5,13 +5,13 @@ pub mod column;
pub mod configure_deck; pub mod configure_deck;
pub mod edit_deck; pub mod edit_deck;
pub mod images; pub mod images;
pub mod mentions_picker;
pub mod note; pub mod note;
pub mod post; pub mod post;
pub mod preview; pub mod preview;
pub mod profile; pub mod profile;
pub mod relay; pub mod relay;
pub mod search; pub mod search;
pub mod search_results;
pub mod settings; pub mod settings;
pub mod side_panel; pub mod side_panel;
pub mod support; pub mod support;

View File

@@ -2,7 +2,7 @@ use crate::draft::{Draft, Drafts, MentionHint};
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
use crate::media_upload::{nostrbuild_nip96_upload, MediaPath}; use crate::media_upload::{nostrbuild_nip96_upload, MediaPath};
use crate::post::{downcast_post_buffer, MentionType, NewPost}; use crate::post::{downcast_post_buffer, MentionType, NewPost};
use crate::ui::search_results::SearchResultsView; use crate::ui::mentions_picker::MentionPickerView;
use crate::ui::{self, Preview, PreviewConfig}; use crate::ui::{self, Preview, PreviewConfig};
use crate::Result; use crate::Result;
@@ -218,6 +218,7 @@ impl<'a, 'd> PostView<'a, 'd> {
out.response out.response
} }
// Displays the mention picker and handles when one is selected.
fn show_mention_hints( fn show_mention_hints(
&mut self, &mut self,
txn: &nostrdb::Transaction, txn: &nostrdb::Transaction,
@@ -273,7 +274,7 @@ impl<'a, 'd> PostView<'a, 'd> {
return; return;
}; };
let resp = SearchResultsView::new( let resp = MentionPickerView::new(
self.note_context.img_cache, self.note_context.img_cache,
self.note_context.ndb, self.note_context.ndb,
txn, txn,
@@ -281,26 +282,35 @@ impl<'a, 'd> PostView<'a, 'd> {
) )
.show_in_rect(hint_rect, ui); .show_in_rect(hint_rect, ui);
let mut selection_made = None;
match resp { match resp {
ui::search_results::SearchResultsResponse::SelectResult(selection) => { ui::mentions_picker::MentionPickerResponse::SelectResult(selection) => {
if let Some(hint_index) = selection { if let Some(hint_index) = selection {
if let Some(pk) = res.get(hint_index) { if let Some(pk) = res.get(hint_index) {
let record = self.note_context.ndb.get_profile_by_pubkey(txn, pk); let record = self.note_context.ndb.get_profile_by_pubkey(txn, pk);
if let Some(made_selection) =
self.draft.buffer.select_mention_and_replace_name( self.draft.buffer.select_mention_and_replace_name(
mention.index, mention.index,
get_display_name(record.ok().as_ref()).name(), get_display_name(record.ok().as_ref()).name(),
Pubkey::new(**pk), Pubkey::new(**pk),
); )
{
selection_made = Some(made_selection);
}
self.draft.cur_mention_hint = None; self.draft.cur_mention_hint = None;
} }
} }
} }
ui::search_results::SearchResultsResponse::DeleteMention => { ui::mentions_picker::MentionPickerResponse::DeleteMention => {
self.draft.buffer.delete_mention(mention.index) self.draft.buffer.delete_mention(mention.index)
} }
} }
if let Some(selection) = selection_made {
selection.process(ui.ctx(), textedit_output);
}
} }
fn focused(&self, ui: &egui::Ui) -> bool { fn focused(&self, ui: &egui::Ui) -> bool {

View File

@@ -19,7 +19,7 @@ mod state;
pub use state::{FocusState, SearchQueryState, SearchState}; pub use state::{FocusState, SearchQueryState, SearchState};
use super::search_results::{SearchResultsResponse, SearchResultsView}; use super::mentions_picker::{MentionPickerResponse, MentionPickerView};
pub struct SearchView<'a, 'd> { pub struct SearchView<'a, 'd> {
query: &'a mut SearchQueryState, query: &'a mut SearchQueryState,
@@ -76,7 +76,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
break 's; break 's;
}; };
let search_res = SearchResultsView::new( let search_res = MentionPickerView::new(
self.note_context.img_cache, self.note_context.img_cache,
self.note_context.ndb, self.note_context.ndb,
self.txn, self.txn,
@@ -85,7 +85,7 @@ impl<'a, 'd> SearchView<'a, 'd> {
.show_in_rect(ui.available_rect_before_wrap(), ui); .show_in_rect(ui.available_rect_before_wrap(), ui);
search_action = match search_res { search_action = match search_res {
SearchResultsResponse::SelectResult(Some(index)) => { MentionPickerResponse::SelectResult(Some(index)) => {
let Some(pk_bytes) = results.get(index) else { let Some(pk_bytes) = results.get(index) else {
break 's; break 's;
}; };
@@ -103,8 +103,8 @@ impl<'a, 'd> SearchView<'a, 'd> {
new_search_text: format!("@{username}"), new_search_text: format!("@{username}"),
}) })
} }
SearchResultsResponse::DeleteMention => Some(SearchAction::CloseMention), MentionPickerResponse::DeleteMention => Some(SearchAction::CloseMention),
SearchResultsResponse::SelectResult(None) => break 's, MentionPickerResponse::SelectResult(None) => break 's,
}; };
} }
SearchState::PerformSearch(search_type) => { SearchState::PerformSearch(search_type) => {