diff --git a/lib/components/player/volume_slider.dart b/lib/components/player/volume_slider.dart new file mode 100644 index 000000000..55f8520dd --- /dev/null +++ b/lib/components/player/volume_slider.dart @@ -0,0 +1,66 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; + +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:spotube/collections/spotube_icons.dart'; +import 'package:spotube/provider/volume_provider.dart'; + +class VolumeSlider extends HookConsumerWidget { + final bool fullWidth; + const VolumeSlider({ + Key? key, + this.fullWidth = false, + }) : super(key: key); + + @override + Widget build(BuildContext context, ref) { + final volume = ref.watch(volumeProvider); + final volumeNotifier = ref.watch(volumeProvider.notifier); + + var slider = Listener( + onPointerSignal: (event) async { + if (event is PointerScrollEvent) { + if (event.scrollDelta.dy > 0) { + final value = volume - .2; + volumeNotifier.setVolume(value < 0 ? 0 : value); + } else { + final value = volume + .2; + volumeNotifier.setVolume(value > 1 ? 1 : value); + } + } + }, + child: Slider.adaptive( + min: 0, + max: 1, + value: volume, + onChanged: volumeNotifier.setVolume, + ), + ); + return Row( + mainAxisAlignment: + !fullWidth ? MainAxisAlignment.center : MainAxisAlignment.start, + children: [ + IconButton( + icon: Icon( + volume == 0 + ? SpotubeIcons.volumeMute + : volume <= 0.2 + ? SpotubeIcons.volumeLow + : volume <= 0.6 + ? SpotubeIcons.volumeMedium + : SpotubeIcons.volumeHigh, + size: 16, + ), + onPressed: () { + if (volume == 0) { + volumeNotifier.setVolume(1); + } else { + volumeNotifier.setVolume(0); + } + }, + ), + if (fullWidth) Expanded(child: slider) else slider, + ], + ); + } +} diff --git a/lib/components/root/bottom_player.dart b/lib/components/root/bottom_player.dart index 891da2c13..2b0bc1ff6 100644 --- a/lib/components/root/bottom_player.dart +++ b/lib/components/root/bottom_player.dart @@ -12,6 +12,7 @@ import 'package:spotube/components/player/player_actions.dart'; import 'package:spotube/components/player/player_overlay.dart'; import 'package:spotube/components/player/player_track_details.dart'; import 'package:spotube/components/player/player_controls.dart'; +import 'package:spotube/components/player/volume_slider.dart'; import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; import 'package:spotube/hooks/use_brightness_value.dart'; @@ -115,57 +116,7 @@ class BottomPlayer extends HookConsumerWidget { Container( height: 40, constraints: const BoxConstraints(maxWidth: 250), - child: HookBuilder(builder: (context) { - final volume = ref.watch(volumeProvider); - final volumeNotifier = - ref.watch(volumeProvider.notifier); - - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - icon: Icon( - volume == 0 - ? SpotubeIcons.volumeMute - : volume <= 0.2 - ? SpotubeIcons.volumeLow - : volume <= 0.6 - ? SpotubeIcons.volumeMedium - : SpotubeIcons.volumeHigh, - size: 16, - ), - onPressed: () { - if (volume == 0) { - volumeNotifier.setVolume(1); - } else { - volumeNotifier.setVolume(0); - } - }, - ), - Listener( - onPointerSignal: (event) async { - if (event is PointerScrollEvent) { - if (event.scrollDelta.dy > 0) { - final value = volume - .2; - volumeNotifier - .setVolume(value < 0 ? 0 : value); - } else { - final value = volume + .2; - volumeNotifier - .setVolume(value > 1 ? 1 : value); - } - } - }, - child: Slider.adaptive( - min: 0, - max: 1, - value: volume, - onChanged: volumeNotifier.setVolume, - ), - ), - ], - ); - }), + child: const VolumeSlider(), ) ], ) diff --git a/lib/pages/player/player.dart b/lib/pages/player/player.dart index 9234d82c2..61b54d72a 100644 --- a/lib/pages/player/player.dart +++ b/lib/pages/player/player.dart @@ -9,6 +9,7 @@ import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/player/player_actions.dart'; import 'package:spotube/components/player/player_controls.dart'; +import 'package:spotube/components/player/volume_slider.dart'; import 'package:spotube/components/shared/animated_gradient.dart'; import 'package:spotube/components/shared/dialogs/track_details_dialog.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; @@ -247,6 +248,25 @@ class PlayerView extends HookConsumerWidget { const SizedBox(width: 10), ], ), + const SizedBox(height: 25), + SliderTheme( + data: theme.sliderTheme.copyWith( + activeTrackColor: titleTextColor, + inactiveTrackColor: bodyTextColor, + thumbColor: titleTextColor, + overlayColor: titleTextColor?.withOpacity(0.2), + trackHeight: 2, + thumbShape: const RoundSliderThumbShape( + enabledThumbRadius: 6, + ), + ), + child: const Padding( + padding: EdgeInsets.symmetric(horizontal: 16), + child: VolumeSlider( + fullWidth: true, + ), + ), + ), ], ), ),