Skip to content

Apply refresh-rate modes app-wide and target a real 60 Hz mode - #320

Merged
ultraelectronica merged 3 commits into
mainfrom
versionF
Oct 17, 2026
Merged

ultraelectronica merged 3 commits into
mainfrom
versionF

Conversation

@ultraelectronica

Copy link
Copy Markdown
Member

Summary

Finishes the refresh-rate work from 0.22.2-beta.4: one app-wide controller applies the selected mode immediately, the 60 Hz option means ~60 Hz instead of the panel's lowest rate, and saved modes survive preference loading and Android window recreation.

App-wide application

  • Removes DisplayModeWrapper from every screen (albums, artists, favorites, folders, menu, recap, player, settings, songs and more) and relies on the single DisplayModeController mounted above the app.
  • A change made in Settings now applies immediately instead of waiting for the next wrapped screen to mount, and screens no longer each re-apply the mode on mount, resume, and background changes.
  • AppPreferencesNotifier exposes a loaded future, and setRefreshRateMode waits for persisted values before comparing or writing, so startup defaults can no longer overwrite an explicitly chosen mode.

60 Hz selection

  • standard now picks the advertised mode closest to 60 Hz at the current resolution (within 5 Hz, so 59.94 Hz panels match) instead of the lowest rate, which could be a 10 Hz low-power mode.
  • If the panel advertises no ~60 Hz mode, Flick follows the system instead of forcing an arbitrary rate. adaptive and high behave as before.

Restore and reapplication

  • A forced mode is skipped only when the current window actually prefers it (FlutterDisplayMode.preferred), not merely because Flick requested it earlier — Android can recreate a window without restarting Dart.
  • The controller waits for preferences to load, then reapplies the saved mode on startup and after window recreation.
  • Returning to the foreground reapplies the mode; background/closing windows can run at a lower rate without being treated as a rejected request.

Verification correctness

  • Replaces the Future.delayed verification with a cancellable timer guarded by a request token, foreground state, and platform support, so superseded lookups cannot overwrite a newer selection.
  • Verification is cancelled while backgrounded, preventing low-power background rates from triggering the session fallback.
  • An explicit user selection clears the forced-mode suppression, so retrying after a firmware rejection (Fairphone 6, [BUG] [UI] Scrolling is sluggish #210) is possible; an accepted mode still gets verified when it was already preferred.

Release notes

  • Updates CHANGELOG.md, docs/RELEASE_0.22.2-beta.4.md, and the in-app changelog with the real-60 Hz behavior, immediate application, and restore-on-reopen.

Related issue

Related to #210 (Fairphone 6 refresh-rate fallback)

Checklist

  • flutter analyze passes
  • flutter test passes
  • Rust changes: cargo test --manifest-path rust/Cargo.toml passes
  • Built and ran the app if the change touches a playback path (flutter run --flavor full)
  • Generated code regenerated and committed if bridge/drift/freezed models changed
  • CHANGELOG.md updated for user-facing changes
  • No secrets, keys, tokens, or machine-local files committed
  • One change per PR; no unrelated reformatting in the same diff
  • Hardware tested if the Rust audio engine or USB/DAC output changed

Replace the per-screen refresh-rate wrapper with a single controller
mounted above the app. It applies the stored preference after loading,
reacts to preference changes, and re-applies on resume so changes made
in Settings take effect immediately.
- Standard mode now picks the advertised mode nearest 60 Hz
  instead of the panel's lowest rate.
- Apply mode changes immediately app-wide, restore the saved
  mode after window recreation, and avoid false rejections while
  backgrounded.
Replace the per-screen DisplayModeWrapper with a single
DisplayModeController wrapping the app, and make the display mode
service restore and re-apply the saved refresh rate on startup and
window recreation. Screen-agnostic reapplication removes redundant
per-mount, resume, and background-change requests.

Also expose app preferences load completion so display mode changes
wait for persisted settings, and document the refresh-rate fixes in
the changelog.
@ultraelectronica ultraelectronica self-assigned this Oct 17, 2026
@ultraelectronica
ultraelectronica merged commit eb0e849 into main Oct 17, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant