mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-17 08:44:20 +01:00
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:
33
Cargo.lock
generated
33
Cargo.lock
generated
@@ -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"
|
||||||
|
|||||||
12
Cargo.toml
12
Cargo.toml
@@ -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" }
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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();
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
self.draft.buffer.select_mention_and_replace_name(
|
if let Some(made_selection) =
|
||||||
mention.index,
|
self.draft.buffer.select_mention_and_replace_name(
|
||||||
get_display_name(record.ok().as_ref()).name(),
|
mention.index,
|
||||||
Pubkey::new(**pk),
|
get_display_name(record.ok().as_ref()).name(),
|
||||||
);
|
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 {
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user