mentions: don't lose focus after select mention

Closes: https://github.com/damus-io/notedeck/issues/728

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-07-27 10:10:24 -04:00
parent 31ec21ea02
commit 173972f920
2 changed files with 62 additions and 14 deletions

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 nostrdb::{Note, NoteBuilder, NoteReply};
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 {
pub fn get_new_mentions_key(&mut self) -> usize {
let prev = self.mentions_key;
@@ -319,15 +353,19 @@ impl PostBuffer {
mention_key: usize,
full_name: &str,
pk: Pubkey,
) {
if let Some(info) = self.mentions.get(&mention_key) {
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 {
) -> Option<MentionSelectedResponse> {
let Some(info) = self.mentions.get(&mention_key) else {
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);
Some(MentionSelectedResponse {
next_cursor_index: text_start_index + text_chars_inserted,
})
}
pub fn delete_mention(&mut self, mention_key: usize) {

View File

@@ -218,6 +218,7 @@ impl<'a, 'd> PostView<'a, 'd> {
out.response
}
// Displays the mention picker and handles when one is selected.
fn show_mention_hints(
&mut self,
txn: &nostrdb::Transaction,
@@ -281,17 +282,22 @@ impl<'a, 'd> PostView<'a, 'd> {
)
.show_in_rect(hint_rect, ui);
let mut selection_made = None;
match resp {
ui::mentions_picker::MentionPickerResponse::SelectResult(selection) => {
if let Some(hint_index) = selection {
if let Some(pk) = res.get(hint_index) {
let record = self.note_context.ndb.get_profile_by_pubkey(txn, pk);
self.draft.buffer.select_mention_and_replace_name(
mention.index,
get_display_name(record.ok().as_ref()).name(),
Pubkey::new(**pk),
);
if let Some(made_selection) =
self.draft.buffer.select_mention_and_replace_name(
mention.index,
get_display_name(record.ok().as_ref()).name(),
Pubkey::new(**pk),
)
{
selection_made = Some(made_selection);
}
self.draft.cur_mention_hint = None;
}
}
@@ -301,6 +307,10 @@ impl<'a, 'd> PostView<'a, 'd> {
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 {