✨ Infinite playing
💄 Optimized UX
This commit is contained in:
@@ -103,7 +103,11 @@ class AlbumDetailScreen extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
void _playAlbum(WidgetRef ref, List<Track> tracks, {int initialIndex = 0}) {
|
||||
final loadingNotifier = ref.read(remoteTrackLoadingProvider.notifier);
|
||||
final audioHandler = ref.read(audioHandlerProvider);
|
||||
audioHandler.playTracks(tracks, initialIndex: initialIndex);
|
||||
loadingNotifier.setLoading(true);
|
||||
audioHandler.playTracks(tracks, initialIndex: initialIndex).then((_) {
|
||||
loadingNotifier.setLoading(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,8 +525,14 @@ class LibraryScreen extends HookConsumerWidget {
|
||||
onTrailingPressed: () =>
|
||||
_showTrackOptions(context, ref, track),
|
||||
onTap: () {
|
||||
final loadingNotifier = ref.read(
|
||||
remoteTrackLoadingProvider.notifier,
|
||||
);
|
||||
final audio = ref.read(audioHandlerProvider);
|
||||
audio.playTrack(track);
|
||||
loadingNotifier.setLoading(true);
|
||||
audio.playTrack(track).then((_) {
|
||||
loadingNotifier.setLoading(false);
|
||||
});
|
||||
},
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
|
||||
@@ -108,19 +108,35 @@ class PlayerScreen extends HookConsumerWidget {
|
||||
autofocus: true,
|
||||
onKeyEvent: (node, event) {
|
||||
if (event is KeyDownEvent) {
|
||||
if (event.logicalKey == LogicalKeyboardKey.space) {
|
||||
if (player.state.playing) {
|
||||
player.pause();
|
||||
} else {
|
||||
player.play();
|
||||
}
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.bracketLeft) {
|
||||
player.previous();
|
||||
return KeyEventResult.handled;
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.bracketRight) {
|
||||
player.next();
|
||||
return KeyEventResult.handled;
|
||||
switch (event.logicalKey) {
|
||||
case LogicalKeyboardKey.space:
|
||||
if (player.state.playing) {
|
||||
player.pause();
|
||||
} else {
|
||||
player.play();
|
||||
}
|
||||
return KeyEventResult.handled;
|
||||
case LogicalKeyboardKey.bracketLeft:
|
||||
player.previous();
|
||||
return KeyEventResult.handled;
|
||||
case LogicalKeyboardKey.bracketRight:
|
||||
player.next();
|
||||
return KeyEventResult.handled;
|
||||
case LogicalKeyboardKey.escape:
|
||||
Navigator.of(context).pop();
|
||||
return KeyEventResult.handled;
|
||||
case LogicalKeyboardKey.arrowUp:
|
||||
player.setVolume(
|
||||
(player.state.volume + 10).clamp(0, 100),
|
||||
); // Increase volume
|
||||
return KeyEventResult.handled;
|
||||
case LogicalKeyboardKey.arrowDown:
|
||||
player.setVolume(
|
||||
(player.state.volume - 10).clamp(0, 100),
|
||||
); // Decrease volume
|
||||
return KeyEventResult.handled;
|
||||
default:
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
@@ -1700,7 +1716,10 @@ class _PlayerControls extends HookWidget {
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
playing ? Symbols.pause : Symbols.play_arrow,
|
||||
playing
|
||||
? Symbols.pause_rounded
|
||||
: Symbols.play_arrow_rounded,
|
||||
fill: 1,
|
||||
key: ValueKey<bool>(playing),
|
||||
size: 48,
|
||||
),
|
||||
|
||||
@@ -114,7 +114,11 @@ class PlaylistDetailScreen extends HookConsumerWidget {
|
||||
List<Track> tracks, {
|
||||
int initialIndex = 0,
|
||||
}) {
|
||||
final loadingNotifier = ref.read(remoteTrackLoadingProvider.notifier);
|
||||
final audioHandler = ref.read(audioHandlerProvider);
|
||||
audioHandler.playTracks(tracks, initialIndex: initialIndex);
|
||||
loadingNotifier.setLoading(true);
|
||||
audioHandler.playTracks(tracks, initialIndex: initialIndex).then((_) {
|
||||
loadingNotifier.setLoading(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,6 +379,21 @@ class SettingsScreen extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: const Text('Continue Playing'),
|
||||
subtitle: const Text(
|
||||
'Continue playing music after the queue is empty',
|
||||
),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
value: settings.continuePlays,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(continuePlaysProvider.notifier)
|
||||
.update(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -156,8 +156,7 @@ class _MobileMiniPlayer extends HookConsumerWidget {
|
||||
color: Colors.white54,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
).clipRRect(all: 8).padding(left: 8, vertical: 8),
|
||||
// Title & Artist
|
||||
Expanded(
|
||||
child: Padding(
|
||||
@@ -184,6 +183,14 @@ class _MobileMiniPlayer extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
// Next Button
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.skip_previous),
|
||||
onPressed: player.previous,
|
||||
iconSize: 24,
|
||||
visualDensity: const VisualDensity(horizontal: -4),
|
||||
padding: EdgeInsets.all(8),
|
||||
),
|
||||
// Play/Pause Button
|
||||
StreamBuilder<bool>(
|
||||
stream: player.stream.playing,
|
||||
@@ -206,8 +213,11 @@ class _MobileMiniPlayer extends HookConsumerWidget {
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
playing ? Symbols.pause : Symbols.play_arrow,
|
||||
playing
|
||||
? Symbols.pause_rounded
|
||||
: Symbols.play_arrow_rounded,
|
||||
key: ValueKey<bool>(playing),
|
||||
fill: 1,
|
||||
),
|
||||
),
|
||||
onPressed: playing ? player.pause : player.play,
|
||||
@@ -215,12 +225,7 @@ class _MobileMiniPlayer extends HookConsumerWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
// Next Button
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.skip_next),
|
||||
onPressed: player.next,
|
||||
iconSize: 24,
|
||||
),
|
||||
const Gap(12),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -381,8 +386,7 @@ class _DesktopMiniPlayer extends HookConsumerWidget {
|
||||
color: Colors.white54,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(8),
|
||||
).clipRRect(all: 8).padding(left: 8, vertical: 8),
|
||||
// Title & Artist
|
||||
Flexible(
|
||||
child: Padding(
|
||||
@@ -501,8 +505,9 @@ class _DesktopMiniPlayer extends HookConsumerWidget {
|
||||
},
|
||||
child: Icon(
|
||||
playing
|
||||
? Symbols.pause
|
||||
: Symbols.play_arrow,
|
||||
? Symbols.pause_rounded
|
||||
: Symbols.play_arrow_rounded,
|
||||
fill: 1,
|
||||
key: ValueKey<bool>(playing),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user