adwaita: make the channel refresh button respond while a tab load is in flight #6

Merged
salix merged 2 commits from fix/adwaita-refresh-button into main 2026-10-18 03:10:18 +02:00
Owner

Problem

On a subscribed channel the header's refresh button could feel completely dead: ChannelPage::refresh bailed out whenever a tab fetch was still in flight (refreshing || loading), with no feedback of any kind. On a slow or challenge-gated instance the initial tab fetch routinely runs 30s+, so a click during that window was silently swallowed — and even after the load finished, a refresh itself could take minutes with zero indication anything was happening.

Fix

  • A click now always takes effect. refresh() no longer refuses while loading: it cancels any in-flight tab fetch the same way select_tab does (generation bump + flag reset, which the method already did). A tab fetch that races the refresh (e.g. Load more clicked mid-refresh) is cancelled in the completion handler before the forced tab reload, and its discarded result re-anchors the cursor via the fresh first page.
  • Progress on the button. The refresh icon swaps to a gtk::Spinner (and the button goes insensitive) while the refresh runs, restoring the idle icon when it lands — including when the refresh is superseded. This matches the macOS shell, which shows a ProgressView and disables the button.

Verification

Reproduced against a scripted slow local instance (10s per request):

  • before: clicking refresh during the initial tab load produced no requests at all (verified in the core log);
  • after: the click during the load kicks off the full refresh chain (feed refresh → channel meta → forced tab reload), the button spins and is insensitive for the duration, repeat clicks don't stack, and the idle icon is restored afterwards.

cargo test: 302 passed; the two failures (playback::tests::enabled_tor_surfaces_bootstrap_failure, ui::stats::tests::selected_period_has_a_compact_readable_label) also fail/pass on main independent of this change.

## Problem On a subscribed channel the header's refresh button could feel completely dead: `ChannelPage::refresh` bailed out whenever a tab fetch was still in flight (`refreshing || loading`), with no feedback of any kind. On a slow or challenge-gated instance the initial tab fetch routinely runs 30s+, so a click during that window was silently swallowed — and even after the load finished, a refresh itself could take minutes with zero indication anything was happening. ## Fix - **A click now always takes effect.** `refresh()` no longer refuses while `loading`: it cancels any in-flight tab fetch the same way `select_tab` does (generation bump + flag reset, which the method already did). A tab fetch that races the refresh (e.g. Load more clicked mid-refresh) is cancelled in the completion handler before the forced tab reload, and its discarded result re-anchors the cursor via the fresh first page. - **Progress on the button.** The refresh icon swaps to a `gtk::Spinner` (and the button goes insensitive) while the refresh runs, restoring the idle icon when it lands — including when the refresh is superseded. This matches the macOS shell, which shows a `ProgressView` and disables the button. ## Verification Reproduced against a scripted slow local instance (10s per request): - before: clicking refresh during the initial tab load produced no requests at all (verified in the core log); - after: the click during the load kicks off the full refresh chain (feed refresh → channel meta → forced tab reload), the button spins and is insensitive for the duration, repeat clicks don't stack, and the idle icon is restored afterwards. `cargo test`: 302 passed; the two failures (`playback::tests::enabled_tor_surfaces_bootstrap_failure`, `ui::stats::tests::selected_period_has_a_compact_readable_label`) also fail/pass on `main` independent of this change.
Clicking refresh during the initial tab fetch silently did nothing: the
handler bailed out on the loading flag, and on a slow or challenge-gated
instance that window is most of a minute, so the button felt dead.
Cancel the in-flight fetch instead (the same way a tab switch cancels
one), and cancel any fetch that races the refresh before the forced tab
reload.

Also show progress on the button itself — a spinner while the refresh
runs, insensitive to further clicks — since a refresh over a slow
instance can take a while and previously gave no feedback at all.
A refresh is two network phases: the header re-render, then the forced
tab reload. The spinner previously stopped at the re-render, so the
reload — which on a slow instance runs tens of seconds longer — played
out with no indication that anything was still happening. Key the
spinner to the generation of the reload fetch instead: it stays up
until that fetch lands, and any path that supersedes it (new visit, tab
switch, another refresh click) drops it back to the idle icon rather
than spinning forever.
salix merged commit 54b4d18888 into main 2026-10-18 03:10:18 +02:00
salix deleted branch fix/adwaita-refresh-button 2026-10-18 03:10:19 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
salix/invio!6
No description provided.