feat: reactive volume slider and slicker bottom bar with lowered height

This commit is contained in:
Kingkor Roy Tirtho 2023-06-10 22:15:23 +06:00
parent 6ae896441a
commit 9d14517202
4 changed files with 94 additions and 76 deletions

View File

@ -82,4 +82,8 @@ abstract class SpotubeIcons {
static const piped = FeatherIcons.cloud; static const piped = FeatherIcons.cloud;
static const magic = Icons.auto_fix_high_outlined; static const magic = Icons.auto_fix_high_outlined;
static const selectionCheck = Icons.checklist_rounded; static const selectionCheck = Icons.checklist_rounded;
static const volumeHigh = FeatherIcons.volume2;
static const volumeMedium = FeatherIcons.volume1;
static const volumeLow = FeatherIcons.volume;
static const volumeMute = FeatherIcons.volumeX;
} }

View File

@ -26,8 +26,8 @@ class PlayerTrackDetails extends HookConsumerWidget {
Container( Container(
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(6),
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: 70, maxWidth: 80,
maxHeight: 70, maxHeight: 80,
), ),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),

View File

@ -71,90 +71,103 @@ class BottomPlayer extends HookConsumerWidget {
type: MaterialType.transparency, type: MaterialType.transparency,
textStyle: theme.textTheme.bodyMedium!, textStyle: theme.textTheme.bodyMedium!,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded(child: PlayerTrackDetails(albumArt: albumArt)), Expanded(child: PlayerTrackDetails(albumArt: albumArt)),
// controls // controls
Flexible( Flexible(
flex: 3, flex: 3,
child: PlayerControls(), child: Padding(
padding: const EdgeInsets.only(top: 5),
child: PlayerControls(),
),
), ),
// add to saved tracks // add to saved tracks
Expanded( Column(
flex: 1, children: [
child: Wrap( PlayerActions(
alignment: WrapAlignment.center, extraActions: [
runAlignment: WrapAlignment.center, IconButton(
children: [ tooltip: context.l10n.mini_player,
Container( icon: const Icon(SpotubeIcons.miniPlayer),
height: 20, onPressed: () async {
constraints: const BoxConstraints(maxWidth: 200), await DesktopTools.window.setMinimumSize(
child: HookBuilder(builder: (context) { const Size(300, 300),
final volumeState = );
useStream(audioPlayer.volumeStream).data ?? await DesktopTools.window.setAlwaysOnTop(true);
audioPlayer.volume; if (!kIsLinux) {
final volume = useState(volumeState); await DesktopTools.window.setHasShadow(false);
useEffect(() {
if (volume.value != volumeState) {
volume.value = volumeState;
} }
return null; await DesktopTools.window
}, [volumeState]); .setAlignment(Alignment.topRight);
await DesktopTools.window
return Listener( .setSize(const Size(400, 500));
onPointerSignal: (event) async { await Future.delayed(
if (event is PointerScrollEvent) { const Duration(milliseconds: 100),
if (event.scrollDelta.dy > 0) { () async {
final value = volume.value - .2; GoRouter.of(context).go('/mini-player');
audioPlayer.setVolume(value < 0 ? 0 : value); },
} else { );
final value = volume.value + .2; },
audioPlayer.setVolume(value > 1 ? 1 : value); ),
} ],
} ),
}, Container(
child: Slider( height: 40,
min: 0, constraints: const BoxConstraints(maxWidth: 250),
max: 1, child: HookBuilder(builder: (context) {
value: volume.value, final volume =
onChanged: (v) { useStream(audioPlayer.volumeStream).data ??
volume.value = v; audioPlayer.volume;
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) {
audioPlayer.setVolume(1);
} else {
audioPlayer.setVolume(0);
}
}, },
onChangeEnd: audioPlayer.setVolume,
), ),
); Listener(
}), onPointerSignal: (event) async {
), if (event is PointerScrollEvent) {
PlayerActions( if (event.scrollDelta.dy > 0) {
extraActions: [ final value = volume - .2;
IconButton( audioPlayer
tooltip: context.l10n.mini_player, .setVolume(value < 0 ? 0 : value);
icon: const Icon(SpotubeIcons.miniPlayer), } else {
onPressed: () async { final value = volume + .2;
await DesktopTools.window.setMinimumSize( audioPlayer
const Size(300, 300), .setVolume(value > 1 ? 1 : value);
); }
await DesktopTools.window.setAlwaysOnTop(true); }
if (!kIsLinux) { },
await DesktopTools.window.setHasShadow(false); child: Slider(
} min: 0,
await DesktopTools.window max: 1,
.setAlignment(Alignment.topRight); value: volume,
await DesktopTools.window onChanged: audioPlayer.setVolume,
.setSize(const Size(400, 500)); ),
await Future.delayed( ),
const Duration(milliseconds: 100), ],
() async { );
GoRouter.of(context).go('/mini-player'); }),
}, )
); ],
},
),
],
)
],
),
) )
], ],
), ),

View File

@ -48,5 +48,6 @@ ThemeData theme(Color seed, Brightness brightness) {
backgroundColor: scheme.onSurface, backgroundColor: scheme.onSurface,
contentTextStyle: TextStyle(color: scheme.surface), contentTextStyle: TextStyle(color: scheme.surface),
), ),
sliderTheme: SliderThemeData(overlayShape: SliderComponentShape.noOverlay),
); );
} }