refactor(layout): share responsiveScale and effectiveTextScale

The same clamp helpers were copied into four screens. They now live in
adaptive_layout.dart with identical bodies and clamp values.
This commit is contained in:
zarzet committed 2026-10-19 00:47:54 +07:00
1 parent 1521c49508
commit 78799e1bbc
5 files changed
+35 -78

No files matched your search

+3 -22
View File
@@ -188,34 +188,15 @@ class _ArtistScreenState extends ConsumerState<ArtistScreen>
List<ArtistAlbum> _singlesBucket = const [];
List<ArtistAlbum> _compilationsBucket = const [];
double _responsiveScale({
double min = 0.82,
double max = 1.08,
double baseShortestSide = 390,
}) {
final shortestSide = MediaQuery.sizeOf(context).shortestSide;
final scale = shortestSide / baseShortestSide;
if (scale < min) return min;
if (scale > max) return max;
return scale;
}
double _effectiveTextScale() {
final textScale = MediaQuery.textScalerOf(context).scale(1.0);
if (textScale < 1.0) return 1.0;
if (textScale > 1.4) return 1.4;
return textScale;
}
double _artistAlbumTileSize() {
final scale = _responsiveScale(min: 0.82, max: 1.05);
final textScale = _effectiveTextScale();
final scale = responsiveScale(context: context, min: 0.82, max: 1.05);
final textScale = effectiveTextScale(context);
return 140 * scale * (1 + (textScale - 1) * 0.12);
}
double _artistAlbumSectionHeight() {
final tileSize = _artistAlbumTileSize();
final textScale = _effectiveTextScale();
final textScale = effectiveTextScale(context);
return tileSize + 64 + ((textScale - 1) * 14);
}
+6 -26
View File
@@ -148,35 +148,15 @@ class _HomeTabState extends ConsumerState<HomeTab>
List<Track>? _sortedTracksCache;
List<int>? _sortedTrackIndexesCache;
double _responsiveScale({
required BuildContext context,
double min = 0.82,
double max = 1.08,
double baseShortestSide = 390,
}) {
final shortestSide = MediaQuery.sizeOf(context).shortestSide;
final scale = shortestSide / baseShortestSide;
if (scale < min) return min;
if (scale > max) return max;
return scale;
}
double _effectiveTextScale(BuildContext context) {
final textScale = MediaQuery.textScalerOf(context).scale(1.0);
if (textScale < 1.0) return 1.0;
if (textScale > 1.4) return 1.4;
return textScale;
}
double _recentDownloadCoverSize(BuildContext context) {
final scale = _responsiveScale(context: context, min: 0.82, max: 1.25);
final textScale = _effectiveTextScale(context);
final scale = responsiveScale(context: context, min: 0.82, max: 1.25);
final textScale = effectiveTextScale(context);
return 100 * scale * (1 + (textScale - 1) * 0.15);
}
double _recentDownloadsRowHeight(BuildContext context) {
final coverSize = _recentDownloadCoverSize(context);
final textScale = _effectiveTextScale(context);
final textScale = effectiveTextScale(context);
return coverSize + 28 + ((textScale - 1) * 8);
}
@@ -184,8 +164,8 @@ class _HomeTabState extends ConsumerState<HomeTab>
// Six phone-sized cards across an iPad made the feed look like a desktop
// page zoomed out. A higher tablet cap gives roughly five generous cards
// in portrait while leaving all phone sizes unchanged.
final scale = _responsiveScale(context: context, min: 0.82, max: 1.32);
final textScale = _effectiveTextScale(context);
final scale = responsiveScale(context: context, min: 0.82, max: 1.32);
final textScale = effectiveTextScale(context);
final size = 145 * scale * (1 + (textScale - 1) * 0.12);
// Landscape tablets are short: one carousel row should not take over a
// third of the screen. Portrait and phone heights never reach this cap.
@@ -195,7 +175,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
double _exploreSectionHeight(BuildContext context) {
final cardSize = _exploreCardSize(context);
final textScale = _effectiveTextScale(context);
final textScale = effectiveTextScale(context);
return cardSize + 58 + ((textScale - 1) * 12);
}
+1 -8
View File
@@ -222,17 +222,10 @@ class _QueueTabState extends ConsumerState<QueueTab> {
_queueLibraryPageDataCache = {};
DateTime? _lastBlankLibraryRepairAt;
double _effectiveTextScale() {
final textScale = MediaQuery.textScalerOf(context).scale(1.0);
if (textScale < 1.0) return 1.0;
if (textScale > 1.4) return 1.4;
return textScale;
}
double _queueCoverSize() {
final shortestSide = MediaQuery.sizeOf(context).shortestSide;
final scale = (shortestSide / 390).clamp(0.82, 1.0);
final textScale = _effectiveTextScale();
final textScale = effectiveTextScale(context);
return (56 * scale * (1 + ((textScale - 1) * 0.12))).clamp(46.0, 56.0);
}
+3 -22
View File
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:spotiflac_android/providers/settings_provider.dart';
import 'package:spotiflac_android/l10n/l10n.dart';
import 'package:spotiflac_android/utils/adaptive_layout.dart';
import 'package:spotiflac_android/widgets/scroll_edge_fade.dart';
import 'package:spotiflac_android/widgets/app_icon_button.dart';
import 'package:spotiflac_android/widgets/app_loading_indicator.dart';
@@ -22,26 +23,6 @@ class _TutorialScreenState extends ConsumerState<TutorialScreen> {
int _currentPage = 0;
static const int _totalPages = 6;
double _responsiveScale({
required BuildContext context,
double min = 0.82,
double max = 1.08,
double baseShortestSide = 390,
}) {
final shortestSide = MediaQuery.sizeOf(context).shortestSide;
final scale = shortestSide / baseShortestSide;
if (scale < min) return min;
if (scale > max) return max;
return scale;
}
double _effectiveTextScale(BuildContext context) {
final textScale = MediaQuery.textScalerOf(context).scale(1.0);
if (textScale < 1.0) return 1.0;
if (textScale > 1.4) return 1.4;
return textScale;
}
@override
void dispose() {
_pageController.dispose();
@@ -81,8 +62,8 @@ class _TutorialScreenState extends ConsumerState<TutorialScreen> {
final colorScheme = Theme.of(context).colorScheme;
final l10n = context.l10n;
final isLastPage = _currentPage == _totalPages - 1;
final scale = _responsiveScale(context: context, min: 0.86, max: 1.05);
final textScale = _effectiveTextScale(context);
final scale = responsiveScale(context: context, min: 0.86, max: 1.05);
final textScale = effectiveTextScale(context);
final topBarPaddingH = 24 * scale;
final topBarPaddingV = 16 * scale;
final pageIndicatorHeight = 8 * scale;
+22
View File
@@ -115,3 +115,25 @@ double wideListInset(
MediaQuery.sizeOf(context).width,
contentMaxWidth: contentMaxWidth,
);
/// Scales fixed sizes with the shortest screen side, clamped to [min]..[max].
double responsiveScale({
required BuildContext context,
double min = 0.82,
double max = 1.08,
double baseShortestSide = 390,
}) {
final shortestSide = MediaQuery.sizeOf(context).shortestSide;
final scale = shortestSide / baseShortestSide;
if (scale < min) return min;
if (scale > max) return max;
return scale;
}
/// The system text scale clamped to 1.0..1.4 for fixed-height layouts.
double effectiveTextScale(BuildContext context) {
final textScale = MediaQuery.textScalerOf(context).scale(1.0);
if (textScale < 1.0) return 1.0;
if (textScale > 1.4) return 1.4;
return textScale;
}