fix: no longer make the scroll position jump oddly

only allow front insert in profile when body is fully obstructed

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

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-09-13 14:36:59 -04:00
parent 563fbb9c4b
commit 559e9577fc
2 changed files with 40 additions and 14 deletions

View File

@@ -133,6 +133,7 @@ impl TimelineTab {
ndb: &Ndb,
txn: &Transaction,
reversed: bool,
use_front_insert: bool,
) -> Option<UnknownPks<'a>> {
if payloads.is_empty() {
return None;
@@ -158,7 +159,11 @@ impl TimelineTab {
debug!("spliced when inserting {num_refs} new notes, resetting virtual list",);
list.reset();
}
MergeKind::FrontInsert => {
MergeKind::FrontInsert => 's: {
if !use_front_insert {
break 's;
}
// only run this logic if we're reverse-chronological
// reversed in this case means chronological, since the
// default is reverse-chronological. yeah it's confusing.
@@ -210,6 +215,7 @@ pub struct Timeline {
pub selected_view: usize,
pub subscription: TimelineSub,
pub enable_front_insert: bool,
}
impl Timeline {
@@ -271,12 +277,16 @@ impl Timeline {
let subscription = TimelineSub::default();
let selected_view = 0;
// by default, disabled for profiles since they contain widgets above the list items
let enable_front_insert = !matches!(kind, TimelineKind::Profile(_));
Timeline {
kind,
filter,
views,
subscription,
selected_view,
enable_front_insert,
}
}
@@ -402,7 +412,9 @@ impl Timeline {
match view.filter {
ViewFilter::NotesAndReplies => {
let res: Vec<&NotePayload<'_>> = payloads.iter().collect();
if let Some(res) = view.insert(res, ndb, txn, reversed) {
if let Some(res) =
view.insert(res, ndb, txn, reversed, self.enable_front_insert)
{
res.process(unknown_ids, ndb, txn);
}
}
@@ -418,7 +430,13 @@ impl Timeline {
}
}
if let Some(res) = view.insert(filtered_payloads, ndb, txn, reversed) {
if let Some(res) = view.insert(
filtered_payloads,
ndb,
txn,
reversed,
self.enable_front_insert,
) {
res.process(unknown_ids, ndb, txn);
}
}

View File

@@ -39,6 +39,11 @@ pub enum ProfileViewAction {
Follow(Pubkey),
}
struct ProfileScrollResponse {
body_end_pos: f32,
action: Option<ProfileViewAction>,
}
impl<'a, 'd> ProfileView<'a, 'd> {
#[allow(clippy::too_many_arguments)]
pub fn new(
@@ -65,9 +70,13 @@ impl<'a, 'd> ProfileView<'a, 'd> {
pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<ProfileViewAction> {
let scroll_id = ProfileView::scroll_id(self.col_id, self.pubkey);
let scroll_area = ScrollArea::vertical().id_salt(scroll_id);
let scroll_area = ScrollArea::vertical().id_salt(scroll_id).animated(false);
let output = scroll_area.show(ui, |ui| 's: {
let profile_timeline = self
.timeline_cache
.get_mut(&TimelineKind::Profile(*self.pubkey))?;
let output = scroll_area.show(ui, |ui| {
let mut action = None;
let txn = Transaction::new(self.note_context.ndb).expect("txn");
let profile = self
@@ -82,13 +91,6 @@ impl<'a, 'd> ProfileView<'a, 'd> {
action = Some(profile_view_action);
}
let Some(profile_timeline) = self
.timeline_cache
.get_mut(&TimelineKind::Profile(*self.pubkey))
else {
break 's action;
};
let tabs_resp = tabs_ui(
ui,
self.note_context.i18n,
@@ -121,10 +123,16 @@ impl<'a, 'd> ProfileView<'a, 'd> {
action = Some(ProfileViewAction::Note(note_action));
}
action
ProfileScrollResponse {
body_end_pos: tabs_resp.response.rect.bottom(),
action,
}
});
output.inner
// only allow front insert when the profile body is fully obstructed
profile_timeline.enable_front_insert = output.inner.body_end_pos < ui.clip_rect().top();
output.inner.action
}
}