ui: fix quote repost hitbox
The response from the wide rendered note was incorrect, leading to and incorrectly sized hitbox. This fixes that. Additionally, we include note options and note parent into the hitbox key, as this may influence the size of the note. Before: https://cdn.jb55.com/s/b2464c22a65adb12.png After: https://cdn.jb55.com/s/52545564d98d278e.png Fixes: https://github.com/damus-io/notedeck/issues/519 Closes: https://github.com/damus-io/notedeck/pull/537 Changelog-Fixed: Fix broken quote repost hitbox Signed-off-by: William Casarin <jb55@jb55.com>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1193,7 +1193,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "egui_nav"
|
name = "egui_nav"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/damus-io/egui-nav?rev=956338a90e09c7cda951d554626483e0cdbc7825#956338a90e09c7cda951d554626483e0cdbc7825"
|
source = "git+https://github.com/damus-io/egui-nav?rev=fd0900bdff4be35709372e921f2b49f68b261469#fd0900bdff4be35709372e921f2b49f68b261469"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"egui",
|
"egui",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ eframe = { workspace = true }
|
|||||||
egui_extras = { workspace = true }
|
egui_extras = { workspace = true }
|
||||||
ehttp = "0.2.0"
|
ehttp = "0.2.0"
|
||||||
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", branch = "egui-0.28" }
|
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", branch = "egui-0.28" }
|
||||||
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "956338a90e09c7cda951d554626483e0cdbc7825" }
|
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "fd0900bdff4be35709372e921f2b49f68b261469" }
|
||||||
egui_virtual_list = { git = "https://github.com/jb55/hello_egui", branch = "egui-0.28", package = "egui_virtual_list" }
|
egui_virtual_list = { git = "https://github.com/jb55/hello_egui", branch = "egui-0.28", package = "egui_virtual_list" }
|
||||||
reqwest = { version = "0.12.4", default-features = false, features = [ "rustls-tls-native-roots" ] }
|
reqwest = { version = "0.12.4", default-features = false, features = [ "rustls-tls-native-roots" ] }
|
||||||
image = { version = "0.25", features = ["jpeg", "png", "webp"] }
|
image = { version = "0.25", features = ["jpeg", "png", "webp"] }
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ pub fn render_note_preview(
|
|||||||
img_cache: &mut ImageCache,
|
img_cache: &mut ImageCache,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
id: &[u8; 32],
|
id: &[u8; 32],
|
||||||
_id_str: &str,
|
parent: NoteKey,
|
||||||
) -> NoteResponse {
|
) -> NoteResponse {
|
||||||
#[cfg(feature = "profiling")]
|
#[cfg(feature = "profiling")]
|
||||||
puffin::profile_function!();
|
puffin::profile_function!();
|
||||||
@@ -117,6 +117,7 @@ pub fn render_note_preview(
|
|||||||
.wide(true)
|
.wide(true)
|
||||||
.note_previews(false)
|
.note_previews(false)
|
||||||
.options_button(true)
|
.options_button(true)
|
||||||
|
.parent(parent)
|
||||||
.show(ui)
|
.show(ui)
|
||||||
})
|
})
|
||||||
.inner
|
.inner
|
||||||
@@ -213,8 +214,8 @@ fn render_note_contents(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let note_action = if let Some((id, block_str)) = inline_note {
|
let note_action = if let Some((id, _block_str)) = inline_note {
|
||||||
render_note_preview(ui, ndb, note_cache, img_cache, txn, id, block_str).action
|
render_note_preview(ui, ndb, note_cache, img_cache, txn, id, note_key).action
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ pub struct NoteView<'a> {
|
|||||||
ndb: &'a Ndb,
|
ndb: &'a Ndb,
|
||||||
note_cache: &'a mut NoteCache,
|
note_cache: &'a mut NoteCache,
|
||||||
img_cache: &'a mut ImageCache,
|
img_cache: &'a mut ImageCache,
|
||||||
|
parent: Option<NoteKey>,
|
||||||
note: &'a nostrdb::Note<'a>,
|
note: &'a nostrdb::Note<'a>,
|
||||||
flags: NoteOptions,
|
flags: NoteOptions,
|
||||||
}
|
}
|
||||||
@@ -195,10 +196,12 @@ impl<'a> NoteView<'a> {
|
|||||||
note: &'a nostrdb::Note<'a>,
|
note: &'a nostrdb::Note<'a>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let flags = NoteOptions::actionbar | NoteOptions::note_previews;
|
let flags = NoteOptions::actionbar | NoteOptions::note_previews;
|
||||||
|
let parent: Option<NoteKey> = None;
|
||||||
Self {
|
Self {
|
||||||
ndb,
|
ndb,
|
||||||
note_cache,
|
note_cache,
|
||||||
img_cache,
|
img_cache,
|
||||||
|
parent,
|
||||||
note,
|
note,
|
||||||
flags,
|
flags,
|
||||||
}
|
}
|
||||||
@@ -257,6 +260,11 @@ impl<'a> NoteView<'a> {
|
|||||||
&mut self.flags
|
&mut self.flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent(mut self, parent: NoteKey) -> Self {
|
||||||
|
self.parent = Some(parent);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn textmode_ui(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
fn textmode_ui(&mut self, ui: &mut egui::Ui) -> egui::Response {
|
||||||
let note_key = self.note.key().expect("todo: implement non-db notes");
|
let note_key = self.note.key().expect("todo: implement non-db notes");
|
||||||
let txn = self.note.txn().expect("todo: implement non-db notes");
|
let txn = self.note.txn().expect("todo: implement non-db notes");
|
||||||
@@ -440,8 +448,9 @@ impl<'a> NoteView<'a> {
|
|||||||
let mut note_action: Option<NoteAction> = None;
|
let mut note_action: Option<NoteAction> = None;
|
||||||
let mut selected_option: Option<NoteContextSelection> = None;
|
let mut selected_option: Option<NoteContextSelection> = None;
|
||||||
|
|
||||||
|
let hitbox_id = note_hitbox_id(note_key, self.options(), self.parent);
|
||||||
let profile = self.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
let profile = self.ndb.get_profile_by_pubkey(txn, self.note.pubkey());
|
||||||
let maybe_hitbox = maybe_note_hitbox(ui, note_key);
|
let maybe_hitbox = maybe_note_hitbox(ui, hitbox_id);
|
||||||
let container_right = {
|
let container_right = {
|
||||||
let r = ui.available_rect_before_wrap();
|
let r = ui.available_rect_before_wrap();
|
||||||
let x = r.max.x;
|
let x = r.max.x;
|
||||||
@@ -571,14 +580,11 @@ impl<'a> NoteView<'a> {
|
|||||||
.response
|
.response
|
||||||
};
|
};
|
||||||
|
|
||||||
note_action = check_note_hitbox(
|
let note_action = if note_hitbox_clicked(ui, hitbox_id, &response.rect, maybe_hitbox) {
|
||||||
ui,
|
Some(NoteAction::OpenThread(NoteId::new(*self.note.id())))
|
||||||
self.note.id(),
|
} else {
|
||||||
note_key,
|
note_action
|
||||||
&response,
|
};
|
||||||
maybe_hitbox,
|
|
||||||
note_action,
|
|
||||||
);
|
|
||||||
|
|
||||||
NoteResponse::new(response)
|
NoteResponse::new(response)
|
||||||
.with_action(note_action)
|
.with_action(note_action)
|
||||||
@@ -610,16 +616,18 @@ fn get_reposted_note<'a>(ndb: &Ndb, txn: &'a Transaction, note: &Note) -> Option
|
|||||||
note.filter(|note| note.kind() == 1)
|
note.filter(|note| note.kind() == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn note_hitbox_id(note_key: NoteKey) -> egui::Id {
|
fn note_hitbox_id(
|
||||||
Id::new(("note_size", note_key))
|
note_key: NoteKey,
|
||||||
|
note_options: NoteOptions,
|
||||||
|
parent: Option<NoteKey>,
|
||||||
|
) -> egui::Id {
|
||||||
|
Id::new(("note_size", note_key, note_options, parent))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_note_hitbox(ui: &mut egui::Ui, note_key: NoteKey) -> Option<Response> {
|
fn maybe_note_hitbox(ui: &mut egui::Ui, hitbox_id: egui::Id) -> Option<Response> {
|
||||||
ui.ctx()
|
ui.ctx()
|
||||||
.data_mut(|d| d.get_persisted(note_hitbox_id(note_key)))
|
.data_mut(|d| d.get_persisted(hitbox_id))
|
||||||
.map(|note_size: Vec2| {
|
.map(|note_size: Vec2| {
|
||||||
let id = ui.make_persistent_id(("hitbox_interact", note_key));
|
|
||||||
|
|
||||||
// The hitbox should extend the entire width of the
|
// The hitbox should extend the entire width of the
|
||||||
// container. The hitbox height was cached last layout.
|
// container. The hitbox height was cached last layout.
|
||||||
let container_rect = ui.max_rect();
|
let container_rect = ui.max_rect();
|
||||||
@@ -628,28 +636,31 @@ fn maybe_note_hitbox(ui: &mut egui::Ui, note_key: NoteKey) -> Option<Response> {
|
|||||||
max: pos2(container_rect.max.x, container_rect.min.y + note_size.y),
|
max: pos2(container_rect.max.x, container_rect.min.y + note_size.y),
|
||||||
};
|
};
|
||||||
|
|
||||||
ui.interact(rect, id, egui::Sense::click())
|
let response = ui.interact(rect, hitbox_id, egui::Sense::click());
|
||||||
|
|
||||||
|
response
|
||||||
|
.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Other, true, "hitbox"));
|
||||||
|
|
||||||
|
response
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_note_hitbox(
|
fn note_hitbox_clicked(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
note_id: &[u8; 32],
|
hitbox_id: egui::Id,
|
||||||
note_key: NoteKey,
|
note_rect: &Rect,
|
||||||
note_response: &Response,
|
|
||||||
maybe_hitbox: Option<Response>,
|
maybe_hitbox: Option<Response>,
|
||||||
prior_action: Option<NoteAction>,
|
) -> bool {
|
||||||
) -> Option<NoteAction> {
|
|
||||||
// Stash the dimensions of the note content so we can render the
|
// Stash the dimensions of the note content so we can render the
|
||||||
// hitbox in the next frame
|
// hitbox in the next frame
|
||||||
ui.ctx().data_mut(|d| {
|
ui.ctx().data_mut(|d| {
|
||||||
d.insert_persisted(note_hitbox_id(note_key), note_response.rect.size());
|
d.insert_persisted(hitbox_id, note_rect.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
// If there was an hitbox and it was clicked open the thread
|
// If there was an hitbox and it was clicked open the thread
|
||||||
match maybe_hitbox {
|
match maybe_hitbox {
|
||||||
Some(hitbox) if hitbox.clicked() => Some(NoteAction::OpenThread(NoteId::new(*note_id))),
|
Some(hitbox) => hitbox.clicked(),
|
||||||
_ => prior_action,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ impl<'a> PostView<'a> {
|
|||||||
self.img_cache,
|
self.img_cache,
|
||||||
txn,
|
txn,
|
||||||
id.bytes(),
|
id.bytes(),
|
||||||
"",
|
nostrdb::NoteKey::new(0),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user