diff --git a/lib/components/PlayerScreen/player_screen_album_image.dart b/lib/components/PlayerScreen/player_screen_album_image.dart index 9c6f42fa..84fabaf1 100644 --- a/lib/components/PlayerScreen/player_screen_album_image.dart +++ b/lib/components/PlayerScreen/player_screen_album_image.dart @@ -81,42 +81,39 @@ class PlayerScreenAlbumImage extends ConsumerWidget { } } }, - child: AspectRatio( - aspectRatio: 1.0, - //aspectRatio: 0.5, - child: Align( - alignment: Alignment.center, - child: LayoutBuilder(builder: (context, constraints) { - //print( - // "control height is ${MediaQuery.sizeOf(context).height - 53.0 - constraints.maxHeight - 24}"); - final horizontalPadding = constraints.maxWidth * - (FinampSettingsHelper - .finampSettings.playerScreenCoverMinimumPadding / - 100.0); - return Padding( - padding: EdgeInsets.only( - left: horizontalPadding, - right: horizontalPadding, - ), - child: AlbumImage( - imageListenable: currentAlbumImageProvider, - borderRadius: BorderRadius.circular(8.0), - // Load player cover at max size to allow more seamless scaling - autoScale: false, - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - blurRadius: 24, - offset: const Offset(0, 4), - color: Colors.black.withOpacity(0.3), - ) - ], - ), - ), - ); - }), - ), - ), + child: LayoutBuilder(builder: (context, constraints) { + //print( + // "control height is ${MediaQuery.sizeOf(context).height - 53.0 - constraints.maxHeight - 24}"); + final horizontalPadding = constraints.maxWidth * + (FinampSettingsHelper + .finampSettings.playerScreenCoverMinimumPadding / + 100.0); + final verticalPadding = constraints.maxHeight * + (FinampSettingsHelper + .finampSettings.playerScreenCoverMinimumPadding / + 100.0); + return Padding( + padding: EdgeInsets.symmetric( + horizontal: horizontalPadding, + vertical: verticalPadding, + ), + child: AlbumImage( + imageListenable: currentAlbumImageProvider, + borderRadius: BorderRadius.circular(8.0), + // Load player cover at max size to allow more seamless scaling + autoScale: false, + decoration: BoxDecoration( + boxShadow: [ + BoxShadow( + blurRadius: 24, + offset: const Offset(0, 4), + color: Colors.black.withOpacity(0.3), + ) + ], + ), + ), + ); + }), ), ); }, diff --git a/lib/components/album_image.dart b/lib/components/album_image.dart index 06e72bf9..c7385594 100644 --- a/lib/components/album_image.dart +++ b/lib/components/album_image.dart @@ -74,61 +74,64 @@ class AlbumImage extends ConsumerWidget { ); } - return ClipRRect( - borderRadius: borderRadius, - child: AspectRatio( - aspectRatio: 1, - child: LayoutBuilder(builder: (context, constraints) { - int? physicalWidth; - int? physicalHeight; - if (autoScale) { - // LayoutBuilder (and other pixel-related stuff in Flutter) returns logical pixels instead of physical pixels. - // While this is great for doing layout stuff, we want to get images that are the right size in pixels. - // Logical pixels aren't the same as the physical pixels on the device, they're quite a bit bigger. - // If we use logical pixels for the image request, we'll get a smaller image than we want. - // Because of this, we convert the logical pixels to physical pixels by multiplying by the device's DPI. - final MediaQueryData mediaQuery = MediaQuery.of(context); - physicalWidth = - (constraints.maxWidth * mediaQuery.devicePixelRatio).toInt(); - physicalHeight = - (constraints.maxHeight * mediaQuery.devicePixelRatio).toInt(); - // If using grid music screen view without fixed size tiles, and if the view is resizable due - // to being on desktop and using split screen, then clamp album size to reduce server requests when resizing. - if ((!(Platform.isIOS || Platform.isAndroid) || - usingPlayerSplitScreen) && - !FinampSettingsHelper.finampSettings.useFixedSizeGridTiles && - FinampSettingsHelper.finampSettings.contentViewType == - ContentViewType.grid) { - physicalWidth = exp((log(physicalWidth) * 3).ceil() / 3).toInt(); + return AspectRatio( + aspectRatio: 1.0, + child: Align( + child: ClipRRect( + borderRadius: borderRadius, + child: LayoutBuilder(builder: (context, constraints) { + int? physicalWidth; + int? physicalHeight; + if (autoScale) { + // LayoutBuilder (and other pixel-related stuff in Flutter) returns logical pixels instead of physical pixels. + // While this is great for doing layout stuff, we want to get images that are the right size in pixels. + // Logical pixels aren't the same as the physical pixels on the device, they're quite a bit bigger. + // If we use logical pixels for the image request, we'll get a smaller image than we want. + // Because of this, we convert the logical pixels to physical pixels by multiplying by the device's DPI. + final MediaQueryData mediaQuery = MediaQuery.of(context); + physicalWidth = + (constraints.maxWidth * mediaQuery.devicePixelRatio).toInt(); physicalHeight = - exp((log(physicalHeight) * 3).ceil() / 3).toInt(); + (constraints.maxHeight * mediaQuery.devicePixelRatio).toInt(); + // If using grid music screen view without fixed size tiles, and if the view is resizable due + // to being on desktop and using split screen, then clamp album size to reduce server requests when resizing. + if ((!(Platform.isIOS || Platform.isAndroid) || + usingPlayerSplitScreen) && + !FinampSettingsHelper.finampSettings.useFixedSizeGridTiles && + FinampSettingsHelper.finampSettings.contentViewType == + ContentViewType.grid) { + physicalWidth = + exp((log(physicalWidth) * 3).ceil() / 3).toInt(); + physicalHeight = + exp((log(physicalHeight) * 3).ceil() / 3).toInt(); + } } - } - var image = Container( - decoration: decoration, - child: BareAlbumImage( - imageListenable: imageListenable ?? - albumImageProvider(AlbumImageRequest( - item: item!, - maxWidth: physicalWidth, - maxHeight: physicalHeight, - )).select((value) => (value, item?.blurHash)), - imageProviderCallback: themeCallback == null - ? null - : (image) => themeCallback!( - FinampTheme.fromImageDeferred(image, item?.blurHash)), - placeholderBuilder: placeholderBuilder), - ); - return disabled - ? Opacity( - opacity: 0.75, - child: ColorFiltered( - colorFilter: - const ColorFilter.mode(Colors.black, BlendMode.color), - child: image)) - : image; - }), + var image = Container( + decoration: decoration, + child: BareAlbumImage( + imageListenable: imageListenable ?? + albumImageProvider(AlbumImageRequest( + item: item!, + maxWidth: physicalWidth, + maxHeight: physicalHeight, + )).select((value) => (value, item?.blurHash)), + imageProviderCallback: themeCallback == null + ? null + : (image) => themeCallback!( + FinampTheme.fromImageDeferred(image, item?.blurHash)), + placeholderBuilder: placeholderBuilder), + ); + return disabled + ? Opacity( + opacity: 0.75, + child: ColorFiltered( + colorFilter: const ColorFilter.mode( + Colors.black, BlendMode.color), + child: image)) + : image; + }), + ), ), ); } diff --git a/lib/screens/player_screen.dart b/lib/screens/player_screen.dart index 3b85cce9..1f786163 100644 --- a/lib/screens/player_screen.dart +++ b/lib/screens/player_screen.dart @@ -205,7 +205,8 @@ class _PlayerScreenContent extends ConsumerWidget { }, onHorizontalSwipe: (direction) { if (direction == SwipeDirection.left && isLyricsAvailable) { - if (!FinampSettingsHelper.finampSettings.disableGesture || !controller.shouldShow(PlayerHideable.bottomActions)) { + if (!FinampSettingsHelper.finampSettings.disableGesture || + !controller.shouldShow(PlayerHideable.bottomActions)) { Navigator.of(context).push(_buildSlideRouteTransition( playerScreen, const LyricsScreen(), routeSettings: @@ -302,7 +303,7 @@ class _PlayerScreenContent extends ConsumerWidget { ); } else { return Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ SizedBox( @@ -509,9 +510,12 @@ class PlayerHideableController { size.height - maxAlbumSize * (1 - (minAlbumPadding / 100.0) * 2); var paddedControlsHeight = max(_getSize().height, desiredHeight); _target = Size(targetWidth, _controlsInternalHeight(paddedControlsHeight)); + // 1/3 of padding goes under the controls and is added by the Column, the other + // 2/3 should be included in the album cover region + var controlsBottomPadding = (paddedControlsHeight - _target!.height) / 3.0; // Do not let album size go negative, use full width _album = Size(size.width, - (size.height - paddedControlsHeight).clamp(1.0, size.width)); + max(1.0, size.height - _target!.height - controlsBottomPadding)); } /// Update player screen hidden elements based on usable area in landscape mode. diff --git a/lib/services/keep_screen_on_helper.dart b/lib/services/keep_screen_on_helper.dart index 5142fb5c..ec40a782 100644 --- a/lib/services/keep_screen_on_helper.dart +++ b/lib/services/keep_screen_on_helper.dart @@ -15,11 +15,9 @@ class KeepScreenOnHelper { bool _isPlaying = false; bool _isLyricsShowing = false; bool _isPluggedIn = false; - BatteryState _prevBattState = BatteryState.unknown; - final _keepScreenOnLogger = Logger("KeepScreenOnHelper"); - + KeepScreenOnHelper() { _attachEvents(); } @@ -28,14 +26,17 @@ class KeepScreenOnHelper { // Subscribe to audio playback events final audioHandler = GetIt.instance(); audioHandler.playbackState.listen((event) async { - setCondition(isPlaying: event.playing); + if (_isPlaying != event.playing) { + setCondition(isPlaying: event.playing); + } }); // Subscribe to battery state change events var battery = Battery(); + BatteryState prevBattState = BatteryState.unknown; battery.onBatteryStateChanged.listen((BatteryState state) { - if (_prevBattState != state) { - _prevBattState = state; + if (prevBattState != state) { + prevBattState = state; setCondition(batteryState: state); } }); @@ -47,7 +48,8 @@ class KeepScreenOnHelper { } void setKeepScreenOn() { - if (FinampSettingsHelper.finampSettings.keepScreenOnWhilePluggedIn && !_isPluggedIn) { + if (FinampSettingsHelper.finampSettings.keepScreenOnWhilePluggedIn && + !_isPluggedIn) { _turnOff(); } else { switch (FinampSettingsHelper.finampSettings.keepScreenOnOption) { @@ -70,10 +72,12 @@ class KeepScreenOnHelper { break; } } - _keepScreenOnLogger.fine("keepingScreenOn: $_keepingScreenOn | mainSetting: ${FinampSettingsHelper.finampSettings.keepScreenOnOption} | whilePluggedInSetting: ${FinampSettingsHelper.finampSettings.keepScreenOnWhilePluggedIn} | isPlaying: $_isPlaying | lyricsShowing: $_isLyricsShowing | isPluggedIn: $_isPluggedIn"); + _keepScreenOnLogger.fine( + "keepingScreenOn: $_keepingScreenOn | mainSetting: ${FinampSettingsHelper.finampSettings.keepScreenOnOption} | whilePluggedInSetting: ${FinampSettingsHelper.finampSettings.keepScreenOnWhilePluggedIn} | isPlaying: $_isPlaying | lyricsShowing: $_isLyricsShowing | isPluggedIn: $_isPluggedIn"); } - void setCondition({bool? isPlaying, bool? isLyricsShowing, BatteryState? batteryState}) { + void setCondition( + {bool? isPlaying, bool? isLyricsShowing, BatteryState? batteryState}) { if (isPlaying != null) _isPlaying = isPlaying; if (isLyricsShowing != null) _isLyricsShowing = isLyricsShowing; if (batteryState != null) { @@ -113,20 +117,25 @@ class KeepScreenOnHelper { } class KeepScreenOnObserver extends NavigatorObserver { - final KeepScreenOnHelper keepScreenOnHelper = GetIt.instance(); + final KeepScreenOnHelper keepScreenOnHelper = + GetIt.instance(); static final _lyricsCheck = ModalRoute.withName(LyricsScreen.routeName); @override void didPush(Route route, Route? previousRoute) { // Just pushed to lyrics? - if (_lyricsCheck(route)) keepScreenOnHelper.setCondition(isLyricsShowing: true); + if (_lyricsCheck(route)) { + keepScreenOnHelper.setCondition(isLyricsShowing: true); + } super.didPush(route, previousRoute); } @override void didPop(Route route, Route? previousRoute) { // Just popped lyrics? - if (_lyricsCheck(route)) keepScreenOnHelper.setCondition(isLyricsShowing: false); + if (_lyricsCheck(route)) { + keepScreenOnHelper.setCondition(isLyricsShowing: false); + } super.didPop(route, previousRoute); } -} \ No newline at end of file +}