From edb6f3cd1c9ee2961040b2fe7a91c48577cee4f7 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Sun, 9 Oct 2022 10:52:51 +0600 Subject: [PATCH] feat: volume slider mouse scroll and preference for Rotating Album Art #255 --- lib/components/Player/Player.dart | 44 +++++++++++++++-------- lib/components/Player/PlayerView.dart | 52 ++++++++++++++++++++------- lib/components/Settings/Settings.dart | 11 ++++++ lib/provider/UserPreferences.dart | 10 ++++++ 4 files changed, 89 insertions(+), 28 deletions(-) diff --git a/lib/components/Player/Player.dart b/lib/components/Player/Player.dart index 5750e1b93..c9c555978 100644 --- a/lib/components/Player/Player.dart +++ b/lib/components/Player/Player.dart @@ -1,3 +1,4 @@ +import 'package:flutter/gestures.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/components/Player/PlayerActions.dart'; @@ -122,23 +123,36 @@ class Player extends HookConsumerWidget { } return null; }, [playback.volume]); - return Slider.adaptive( - min: 0, - max: 1, - value: volume.value, - onChanged: (v) { - volume.value = v; - }, - onChangeEnd: (value) async { - try { - // You don't really need to know why but this - // way it works only - await playback.setVolume(value); - await playback.setVolume(value); - } catch (e, stack) { - logger.e("onChange", e, stack); + return Listener( + onPointerSignal: (event) async { + if (event is PointerScrollEvent) { + if (event.scrollDelta.dy > 0) { + final value = volume.value - .2; + playback.setVolume(value < 0 ? 0 : value); + } else { + final value = volume.value + .2; + playback.setVolume(value > 1 ? 1 : value); + } } }, + child: Slider.adaptive( + min: 0, + max: 1, + value: volume.value, + onChanged: (v) { + volume.value = v; + }, + onChangeEnd: (value) async { + try { + // You don't really need to know why but this + // way it works only + await playback.setVolume(value); + await playback.setVolume(value); + } catch (e, stack) { + logger.e("onChange", e, stack); + } + }, + ), ); }), ), diff --git a/lib/components/Player/PlayerView.dart b/lib/components/Player/PlayerView.dart index d3aece58a..e77e557b9 100644 --- a/lib/components/Player/PlayerView.dart +++ b/lib/components/Player/PlayerView.dart @@ -1,6 +1,5 @@ import 'dart:ui'; -import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; @@ -15,6 +14,7 @@ import 'package:spotube/hooks/useBreakpoints.dart'; import 'package:spotube/hooks/useCustomStatusBarColor.dart'; import 'package:spotube/hooks/usePaletteColor.dart'; import 'package:spotube/provider/Playback.dart'; +import 'package:spotube/provider/UserPreferences.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; class PlayerView extends HookConsumerWidget { @@ -28,6 +28,9 @@ class PlayerView extends HookConsumerWidget { (value) => value.track, )); final breakpoint = useBreakpoints(); + final canRotate = ref.watch( + userPreferencesProvider.select((s) => s.rotatingAlbumArt), + ); useEffect(() { if (breakpoint.isMoreThan(Breakpoints.md)) { @@ -108,23 +111,46 @@ class PlayerView extends HookConsumerWidget { final controller = useAnimationController( duration: const Duration(seconds: 10), vsync: ticker, - )..repeat(); + ); + + useEffect( + () { + controller.repeat(); + if (!canRotate) controller.stop(); + return null; + }, + [controller], + ); return RotationTransition( turns: Tween(begin: 0.0, end: 1.0).animate(controller), child: Container( decoration: BoxDecoration( - border: Border.all( - color: paletteColor.titleTextColor, - width: 2, - ), - shape: BoxShape.circle, - ), - child: CircleAvatar( - backgroundImage: - UniversalImage.imageProvider(albumArt), - radius: MediaQuery.of(context).size.width * - (breakpoint.isSm ? 0.4 : 0.3), + border: canRotate + ? Border.all( + color: paletteColor.titleTextColor, + width: 2, + ) + : null, + borderRadius: + !canRotate ? BorderRadius.circular(15) : null, + shape: + canRotate ? BoxShape.circle : BoxShape.rectangle, ), + child: !canRotate + ? ClipRRect( + borderRadius: BorderRadius.circular(15), + child: UniversalImage( + path: albumArt, + width: MediaQuery.of(context).size.width * + (breakpoint.isSm ? 0.8 : 0.5), + ), + ) + : CircleAvatar( + backgroundImage: + UniversalImage.imageProvider(albumArt), + radius: MediaQuery.of(context).size.width * + (breakpoint.isSm ? 0.4 : 0.3), + ), ), ); }), diff --git a/lib/components/Settings/Settings.dart b/lib/components/Settings/Settings.dart index 3950e79c3..948f639d6 100644 --- a/lib/components/Settings/Settings.dart +++ b/lib/components/Settings/Settings.dart @@ -231,6 +231,17 @@ class Settings extends HookConsumerWidget { ), onTap: pickColorScheme(ColorSchemeType.background), ), + ListTile( + leading: const Icon(Icons.album_rounded), + title: const Text("Rotating Album Art"), + trailing: Switch.adaptive( + activeColor: Theme.of(context).primaryColor, + value: preferences.rotatingAlbumArt, + onChanged: (state) { + preferences.setRotatingAlbumArt(state); + }, + ), + ), const Text( " Playback", style: diff --git a/lib/provider/UserPreferences.dart b/lib/provider/UserPreferences.dart index cc24325f9..57b6ef386 100644 --- a/lib/provider/UserPreferences.dart +++ b/lib/provider/UserPreferences.dart @@ -36,6 +36,7 @@ class UserPreferences extends PersistedChangeNotifier { String downloadLocation; LayoutMode layoutMode; + bool rotatingAlbumArt; UserPreferences({ required this.geniusAccessToken, @@ -51,6 +52,7 @@ class UserPreferences extends PersistedChangeNotifier { this.audioQuality = AudioQuality.high, this.skipSponsorSegments = true, this.downloadLocation = "", + this.rotatingAlbumArt = true, }) : super() { if (downloadLocation.isEmpty) { _getDefaultDownloadDirectory().then( @@ -140,6 +142,12 @@ class UserPreferences extends PersistedChangeNotifier { updatePersistence(); } + void setRotatingAlbumArt(bool should) { + rotatingAlbumArt = should; + notifyListeners(); + updatePersistence(); + } + Future _getDefaultDownloadDirectory() async { if (kIsAndroid) return "/storage/emulated/0/Download/Spotube"; @@ -182,6 +190,7 @@ class UserPreferences extends PersistedChangeNotifier { (mode) => mode.name == map["layoutMode"], orElse: () => kIsDesktop ? LayoutMode.extended : LayoutMode.compact, ); + rotatingAlbumArt = map["rotatingAlbumArt"] ?? rotatingAlbumArt; } @override @@ -200,6 +209,7 @@ class UserPreferences extends PersistedChangeNotifier { "skipSponsorSegments": skipSponsorSegments, "downloadLocation": downloadLocation, "layoutMode": layoutMode.name, + "rotatingAlbumArt": rotatingAlbumArt, }; } }