refactor scrolling for post, reply & quote views

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-07-23 21:01:38 -06:00
parent b05d39cc81
commit 0bc32272d2
4 changed files with 75 additions and 74 deletions

View File

@@ -631,27 +631,22 @@ fn render_nav_body(
return None; return None;
}; };
let id = egui::Id::new(("post", col, note.key().unwrap()));
let poster = ctx.accounts.selected_filled()?; let poster = ctx.accounts.selected_filled()?;
let action = { let action = {
let draft = app.drafts.reply_mut(note.id()); let draft = app.drafts.reply_mut(note.id());
let response = egui::ScrollArea::vertical() let response = ui::PostReplyView::new(
.show(ui, |ui| { &mut note_context,
ui::PostReplyView::new( poster,
&mut note_context, draft,
poster, &note,
draft, inner_rect,
&note, app.note_options,
inner_rect, &mut app.jobs,
app.note_options, col,
&mut app.jobs, )
) .show(ui);
.id_source(id)
.show(ui)
})
.inner;
response.action response.action
}; };
@@ -672,26 +667,20 @@ fn render_nav_body(
return None; return None;
}; };
let id = egui::Id::new(("post", col, note.key().unwrap()));
let poster = ctx.accounts.selected_filled()?; let poster = ctx.accounts.selected_filled()?;
let draft = app.drafts.quote_mut(note.id()); let draft = app.drafts.quote_mut(note.id());
let response = egui::ScrollArea::vertical() let response = crate::ui::note::QuoteRepostView::new(
.show(ui, |ui| { &mut note_context,
crate::ui::note::QuoteRepostView::new( poster,
&mut note_context, draft,
poster, &note,
draft, inner_rect,
&note, app.note_options,
inner_rect, &mut app.jobs,
app.note_options, col,
&mut app.jobs, )
) .show(ui);
.id_source(id)
.show(ui)
})
.inner;
response.action.map(Into::into) response.action.map(Into::into)
} }

View File

@@ -35,7 +35,6 @@ pub struct PostView<'a, 'd> {
draft: &'a mut Draft, draft: &'a mut Draft,
post_type: PostType, post_type: PostType,
poster: FilledKeypair<'a>, poster: FilledKeypair<'a>,
id_source: Option<egui::Id>,
inner_rect: egui::Rect, inner_rect: egui::Rect,
note_options: NoteOptions, note_options: NoteOptions,
jobs: &'a mut JobsCache, jobs: &'a mut JobsCache,
@@ -112,12 +111,10 @@ impl<'a, 'd> PostView<'a, 'd> {
note_options: NoteOptions, note_options: NoteOptions,
jobs: &'a mut JobsCache, jobs: &'a mut JobsCache,
) -> Self { ) -> Self {
let id_source: Option<egui::Id> = None;
PostView { PostView {
note_context, note_context,
draft, draft,
poster, poster,
id_source,
post_type, post_type,
inner_rect, inner_rect,
note_options, note_options,
@@ -125,9 +122,12 @@ impl<'a, 'd> PostView<'a, 'd> {
} }
} }
pub fn id_source(mut self, id_source: impl std::hash::Hash) -> Self { fn id() -> egui::Id {
self.id_source = Some(egui::Id::new(id_source)); egui::Id::new("post")
self }
pub fn scroll_id() -> egui::Id {
PostView::id().with("scroll")
} }
fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response { fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response {
@@ -213,7 +213,8 @@ impl<'a, 'd> PostView<'a, 'd> {
let focused = out.response.has_focus(); let focused = out.response.has_focus();
ui.ctx().data_mut(|d| d.insert_temp(self.id(), focused)); ui.ctx()
.data_mut(|d| d.insert_temp(PostView::id(), focused));
out.response out.response
} }
@@ -305,11 +306,7 @@ impl<'a, 'd> PostView<'a, 'd> {
fn focused(&self, ui: &egui::Ui) -> bool { fn focused(&self, ui: &egui::Ui) -> bool {
ui.ctx() ui.ctx()
.data(|d| d.get_temp::<bool>(self.id()).unwrap_or(false)) .data(|d| d.get_temp::<bool>(PostView::id()).unwrap_or(false))
}
fn id(&self) -> egui::Id {
self.id_source.unwrap_or_else(|| egui::Id::new("post"))
} }
pub fn outer_margin() -> i8 { pub fn outer_margin() -> i8 {
@@ -321,6 +318,13 @@ impl<'a, 'd> PostView<'a, 'd> {
} }
pub fn ui(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse { pub fn ui(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
ScrollArea::vertical()
.id_salt(PostView::scroll_id())
.show(ui, |ui| self.ui_no_scroll(txn, ui))
.inner
}
pub fn ui_no_scroll(&mut self, txn: &Transaction, ui: &mut egui::Ui) -> PostResponse {
let focused = self.focused(ui); let focused = self.focused(ui);
let stroke = if focused { let stroke = if focused {
ui.visuals().selection.stroke ui.visuals().selection.stroke

View File

@@ -4,6 +4,7 @@ use crate::{
ui::{self}, ui::{self},
}; };
use egui::ScrollArea;
use enostr::{FilledKeypair, NoteId}; use enostr::{FilledKeypair, NoteId};
use notedeck::NoteContext; use notedeck::NoteContext;
use notedeck_ui::{jobs::JobsCache, NoteOptions}; use notedeck_ui::{jobs::JobsCache, NoteOptions};
@@ -13,7 +14,7 @@ pub struct QuoteRepostView<'a, 'd> {
poster: FilledKeypair<'a>, poster: FilledKeypair<'a>,
draft: &'a mut Draft, draft: &'a mut Draft,
quoting_note: &'a nostrdb::Note<'a>, quoting_note: &'a nostrdb::Note<'a>,
id_source: Option<egui::Id>, scroll_id: egui::Id,
inner_rect: egui::Rect, inner_rect: egui::Rect,
note_options: NoteOptions, note_options: NoteOptions,
jobs: &'a mut JobsCache, jobs: &'a mut JobsCache,
@@ -29,22 +30,36 @@ impl<'a, 'd> QuoteRepostView<'a, 'd> {
inner_rect: egui::Rect, inner_rect: egui::Rect,
note_options: NoteOptions, note_options: NoteOptions,
jobs: &'a mut JobsCache, jobs: &'a mut JobsCache,
col: usize,
) -> Self { ) -> Self {
let id_source: Option<egui::Id> = None;
QuoteRepostView { QuoteRepostView {
note_context, note_context,
poster, poster,
draft, draft,
quoting_note, quoting_note,
id_source, scroll_id: QuoteRepostView::scroll_id(col, quoting_note.id()),
inner_rect, inner_rect,
note_options, note_options,
jobs, jobs,
} }
} }
fn id(col: usize, note_id: &[u8; 32]) -> egui::Id {
egui::Id::new(("quote_repost", col, note_id))
}
pub fn scroll_id(col: usize, note_id: &[u8; 32]) -> egui::Id {
QuoteRepostView::id(col, note_id).with("scroll")
}
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse { pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
let id = self.id(); ScrollArea::vertical()
.id_salt(self.scroll_id)
.show(ui, |ui| self.show_internal(ui))
.inner
}
fn show_internal(&mut self, ui: &mut egui::Ui) -> PostResponse {
let quoting_note_id = self.quoting_note.id(); let quoting_note_id = self.quoting_note.id();
let post_resp = ui::PostView::new( let post_resp = ui::PostView::new(
@@ -56,18 +71,7 @@ impl<'a, 'd> QuoteRepostView<'a, 'd> {
self.note_options, self.note_options,
self.jobs, self.jobs,
) )
.id_source(id) .ui_no_scroll(self.quoting_note.txn().unwrap(), ui);
.ui(self.quoting_note.txn().unwrap(), ui);
post_resp post_resp
} }
pub fn id_source(mut self, id: egui::Id) -> Self {
self.id_source = Some(id);
self
}
pub fn id(&self) -> egui::Id {
self.id_source
.unwrap_or_else(|| egui::Id::new("quote-repost-view"))
}
} }

View File

@@ -4,7 +4,7 @@ use crate::ui::{
note::{PostAction, PostResponse, PostType}, note::{PostAction, PostResponse, PostType},
}; };
use egui::{Rect, Response, Ui}; use egui::{Rect, Response, ScrollArea, Ui};
use enostr::{FilledKeypair, NoteId}; use enostr::{FilledKeypair, NoteId};
use notedeck::NoteContext; use notedeck::NoteContext;
use notedeck_ui::jobs::JobsCache; use notedeck_ui::jobs::JobsCache;
@@ -15,7 +15,7 @@ pub struct PostReplyView<'a, 'd> {
poster: FilledKeypair<'a>, poster: FilledKeypair<'a>,
draft: &'a mut Draft, draft: &'a mut Draft,
note: &'a nostrdb::Note<'a>, note: &'a nostrdb::Note<'a>,
id_source: Option<egui::Id>, scroll_id: egui::Id,
inner_rect: egui::Rect, inner_rect: egui::Rect,
note_options: NoteOptions, note_options: NoteOptions,
jobs: &'a mut JobsCache, jobs: &'a mut JobsCache,
@@ -31,31 +31,37 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
inner_rect: egui::Rect, inner_rect: egui::Rect,
note_options: NoteOptions, note_options: NoteOptions,
jobs: &'a mut JobsCache, jobs: &'a mut JobsCache,
col: usize,
) -> Self { ) -> Self {
let id_source: Option<egui::Id> = None;
PostReplyView { PostReplyView {
note_context, note_context,
poster, poster,
draft, draft,
note, note,
id_source, scroll_id: PostReplyView::scroll_id(col, note.id()),
inner_rect, inner_rect,
note_options, note_options,
jobs, jobs,
} }
} }
pub fn id_source(mut self, id: egui::Id) -> Self { fn id(col: usize, note_id: &[u8; 32]) -> egui::Id {
self.id_source = Some(id); egui::Id::new(("reply_view", col, note_id))
self
} }
pub fn id(&self) -> egui::Id { pub fn scroll_id(col: usize, note_id: &[u8; 32]) -> egui::Id {
self.id_source PostReplyView::id(col, note_id).with("scroll")
.unwrap_or_else(|| egui::Id::new("post-reply-view"))
} }
pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse { pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
ScrollArea::vertical()
.id_salt(self.scroll_id)
.show(ui, |ui| self.show_internal(ui))
.inner
}
// no scroll
fn show_internal(&mut self, ui: &mut egui::Ui) -> PostResponse {
ui.vertical(|ui| { ui.vertical(|ui| {
let avail_rect = ui.available_rect_before_wrap(); let avail_rect = ui.available_rect_before_wrap();
@@ -81,7 +87,6 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
}) })
.inner; .inner;
let id = self.id();
let replying_to = self.note.id(); let replying_to = self.note.id();
let rect_before_post = ui.min_rect(); let rect_before_post = ui.min_rect();
@@ -95,8 +100,7 @@ impl<'a, 'd> PostReplyView<'a, 'd> {
self.note_options, self.note_options,
self.jobs, self.jobs,
) )
.id_source(id) .ui_no_scroll(self.note.txn().unwrap(), ui)
.ui(self.note.txn().unwrap(), ui)
}; };
post_response.action = post_response post_response.action = post_response