Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

### Display Modes
- **New installs follow the system refresh rate by default**: a fresh installation now starts on the Adaptive refresh-rate mode instead of forcing the highest rate. Existing installations keep the mode they already use, and Settings → Interface → Refresh Rate still offers Adaptive, 60 Hz, and maximum.
- **60 Hz now means an actual 60 Hz mode**: the Standard option picks the advertised mode closest to 60 Hz at the current resolution, instead of the panel's lowest rate (10 Hz on displays with low-power modes). If no ~60 Hz mode exists, Flick follows the system instead.
- **Refresh-rate changes apply immediately**: the selected mode is applied app-wide when it changes in Settings, instead of waiting for the next screen to mount.
- **Saved refresh rate is restored on reopening**: Flick waits for saved preferences and checks the current Android window before skipping a repeated request. Background refresh-rate changes no longer trigger a false rejection or session fallback.
- **Forced refresh rates are verified after they are applied**: if the system ignores or downgrades the request (seen on some Fairphone 6 firmware), Flick returns to the system default, logs the mismatch in the developer log, and stops re-forcing for the session.
- Refresh-rate requests are no longer re-sent on every screen mount and resume; redundant applies are skipped.
- Re-applying a mode already preferred by the current window is skipped.

## 0.22.1-beta.3 (2026-09-30)

Expand Down
7 changes: 5 additions & 2 deletions docs/RELEASE_0.22.2-beta.4.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Flick 0.22.2-beta.4

Display refresh-rate reliability: new installs follow the system rate by default, and forced modes now detect when the system rejects them.
Display refresh-rate reliability: new installs follow the system rate by default, the 60 Hz option now targets a real ~60 Hz mode, and forced modes detect when the system rejects them.

## Display Modes

- **New installs follow the system refresh rate by default** — a fresh installation starts on the Adaptive refresh-rate mode instead of forcing the highest rate. Existing installations keep the mode they already use.
- **60 Hz now means an actual 60 Hz mode** — the Standard option picks the advertised mode closest to 60 Hz at the current resolution instead of the panel's lowest rate (10 Hz on some displays); if no ~60 Hz mode exists, Flick follows the system.
- **Refresh-rate changes apply immediately** — the selected mode is applied app-wide when it changes in Settings instead of waiting for the next screen to mount.
- **Saved refresh rate is restored on reopening**: Flick waits for saved preferences and reapplies the selected mode if Android recreated its window. A lower refresh rate while the app is in the background no longer triggers a false rejection.
- **Forced refresh rates are verified after they are applied** — if the system ignores or downgrades the request (seen on some Fairphone 6 firmware, [#210](https://github.com/moss-apps/Flick/issues/210)), Flick returns to the system default, logs the mismatch, and stops re-forcing for the session.
- Refresh-rate requests are skipped when the target mode was already requested, instead of being re-sent from every screen mount or resume.
- Re-applying a mode already preferred by the current window is skipped.

## Builds & Flavors

Expand Down
13 changes: 8 additions & 5 deletions lib/app/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import 'package:flick/providers/mini_player_config_provider.dart';
import 'package:flick/widgets/common/floating_mini_player.dart';
import 'package:flick/widgets/common/floating_scan_progress.dart';
import 'package:flick/widgets/common/connection_notice_host.dart';
import 'package:flick/widgets/common/display_mode_controller.dart';
import 'package:flick/widgets/uac2/usb_bit_perfect_prompt.dart';
import 'package:flick/models/song.dart';
import 'package:flick/services/library_scanner_service.dart';
Expand Down Expand Up @@ -1082,11 +1083,13 @@ class _RootRouter extends ConsumerWidget {
? const MainShell()
: const OnboardingScreen();

return MediaQuery(
data: MediaQuery.of(
context,
).copyWith(disableAnimations: !animationsEnabled),
child: child,
return DisplayModeController(
child: MediaQuery(
data: MediaQuery.of(
context,
).copyWith(disableAnimations: !animationsEnabled),
child: child,
),
);
}
}
49 changes: 23 additions & 26 deletions lib/features/albums/screens/albums_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import 'package:flick/services/player_service.dart';
import 'package:flick/services/motion_art/animated_artwork_service.dart';
import 'package:flick/widgets/common/cached_image_widget.dart';
import 'package:flick/widgets/common/surface_icon_button.dart';
import 'package:flick/widgets/common/display_mode_wrapper.dart';
import 'package:flick/widgets/common/glass_bottom_sheet.dart';
import 'package:flick/l10n/l10n.dart';

Expand Down Expand Up @@ -195,32 +194,30 @@ class _AlbumsScreenState extends ConsumerState<AlbumsScreen> {
if (next.hasValue) _loadAlbums();
});

return DisplayModeWrapper(
child: Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: [
Positioned.fill(
child: AmbientBackground(song: currentSong),
),
SafeArea(
bottom: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(context),
Expanded(
child: _isLoading
? _buildLoadingState()
: _sortedAlbums.isEmpty
? _buildEmptyState()
: _buildAlbumsGrid(),
),
],
),
return Scaffold(
backgroundColor: Colors.transparent,
body: Stack(
children: [
Positioned.fill(
child: AmbientBackground(song: currentSong),
),
SafeArea(
bottom: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(context),
Expanded(
child: _isLoading
? _buildLoadingState()
: _sortedAlbums.isEmpty
? _buildEmptyState()
: _buildAlbumsGrid(),
),
],
),
],
),
),
],
),
);
}
Expand Down
Loading
Loading