notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 21f21eaa60b7c07c1d5e48c6d955ae7f7aaaa22d
parent 1c3bec5a2402c6365c2423dc06fd910c4ae2a9f4
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 27 Feb 2026 07:06:09 -0800

fix: clear async load tracking when popping timeline routes

When navigating back from a profile (or any timeline route), the
timeline was removed from the cache but its entry in
loaded_timeline_loads was kept. This prevented the async loader
from re-populating the timeline on subsequent visits, resulting
in an empty note list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Diffstat:
Mcrates/notedeck_columns/src/app.rs | 4++--
Mcrates/notedeck_columns/src/nav.rs | 2++
Mcrates/notedeck_columns/src/route.rs | 7+++++++
Mcrates/notedeck_columns/src/toolbar.rs | 2++
4 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/crates/notedeck_columns/src/app.rs b/crates/notedeck_columns/src/app.rs @@ -54,9 +54,9 @@ pub struct Damus { /// Background loader for initial timeline scans. timeline_loader: TimelineLoader, /// Timelines currently loading initial notes. - inflight_timeline_loads: HashSet<TimelineKind>, + pub inflight_timeline_loads: HashSet<TimelineKind>, /// Timelines that have completed their initial load. - loaded_timeline_loads: HashSet<TimelineKind>, + pub loaded_timeline_loads: HashSet<TimelineKind>, //frame_history: crate::frame_history::FrameHistory, diff --git a/crates/notedeck_columns/src/nav.rs b/crates/notedeck_columns/src/nav.rs @@ -285,6 +285,8 @@ fn process_nav_resp( &mut app.view_state, ctx.ndb, &mut ctx.remote.scoped_subs(ctx.accounts), + &mut app.loaded_timeline_loads, + &mut app.inflight_timeline_loads, return_type, col, ); diff --git a/crates/notedeck_columns/src/route.rs b/crates/notedeck_columns/src/route.rs @@ -5,6 +5,7 @@ use notedeck::{ tr, Localization, NoteZapTargetOwned, ReplacementType, ReportTarget, RootNoteIdBuf, Router, ScopedSubApi, WalletType, }; +use std::collections::HashSet; use std::ops::Range; use crate::{ @@ -803,6 +804,8 @@ pub fn cleanup_popped_route( view_state: &mut ViewState, ndb: &mut Ndb, scoped_subs: &mut ScopedSubApi, + loaded_timeline_loads: &mut HashSet<TimelineKind>, + inflight_timeline_loads: &mut HashSet<TimelineKind>, return_type: ReturnType, col_index: usize, ) { @@ -811,6 +814,10 @@ pub fn cleanup_popped_route( if let Err(err) = timeline_cache.pop(kind, ndb, scoped_subs) { tracing::error!("popping timeline had an error: {err} for {:?}", kind); } + // Allow the async loader to re-populate this timeline if + // it is opened again later. + loaded_timeline_loads.remove(kind); + inflight_timeline_loads.remove(kind); } Route::Thread(selection) => { threads.close(ndb, scoped_subs, selection, return_type, col_index); diff --git a/crates/notedeck_columns/src/toolbar.rs b/crates/notedeck_columns/src/toolbar.rs @@ -104,6 +104,8 @@ fn pop_to_root(app: &mut Damus, ctx: &mut AppContext, col_index: usize) { &mut app.view_state, ctx.ndb, &mut ctx.remote.scoped_subs(ctx.accounts), + &mut app.loaded_timeline_loads, + &mut app.inflight_timeline_loads, ReturnType::Click, col_index, );