diff --git a/lib/screens/artist_screen.dart b/lib/screens/artist_screen.dart index cdd95e12..0c7231c0 100644 --- a/lib/screens/artist_screen.dart +++ b/lib/screens/artist_screen.dart @@ -188,34 +188,15 @@ class _ArtistScreenState extends ConsumerState List _singlesBucket = const []; List _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); } diff --git a/lib/screens/home_tab.dart b/lib/screens/home_tab.dart index 53ffd600..4c83f9f2 100644 --- a/lib/screens/home_tab.dart +++ b/lib/screens/home_tab.dart @@ -148,35 +148,15 @@ class _HomeTabState extends ConsumerState List? _sortedTracksCache; List? _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 // 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 double _exploreSectionHeight(BuildContext context) { final cardSize = _exploreCardSize(context); - final textScale = _effectiveTextScale(context); + final textScale = effectiveTextScale(context); return cardSize + 58 + ((textScale - 1) * 12); } diff --git a/lib/screens/queue_tab.dart b/lib/screens/queue_tab.dart index 96ec8cf4..edfbee12 100644 --- a/lib/screens/queue_tab.dart +++ b/lib/screens/queue_tab.dart @@ -222,17 +222,10 @@ class _QueueTabState extends ConsumerState { _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); } diff --git a/lib/screens/tutorial_screen.dart b/lib/screens/tutorial_screen.dart index a3f4662b..925a5c89 100644 --- a/lib/screens/tutorial_screen.dart +++ b/lib/screens/tutorial_screen.dart @@ -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 { 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 { 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; diff --git a/lib/utils/adaptive_layout.dart b/lib/utils/adaptive_layout.dart index b4b169ad..9cc8c15a 100644 --- a/lib/utils/adaptive_layout.dart +++ b/lib/utils/adaptive_layout.dart @@ -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; +}