fix buttons that require navigation in track menu
wakelock when lyrics screen open
This commit is contained in:
parent
36f8666906
commit
2e67b50332
|
@ -143,6 +143,7 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
JustAudioMediaKit.ensureInitialized();
|
JustAudioMediaKit.ensureInitialized();
|
||||||
JustAudioMediaKit.title = 'Freezer';
|
JustAudioMediaKit.title = 'Freezer';
|
||||||
JustAudioMediaKit.protocolWhitelist = const ['http'];
|
JustAudioMediaKit.protocolWhitelist = const ['http'];
|
||||||
|
JustAudioMediaKit.prefetchPlaylist = true;
|
||||||
//JustAudioMediaKit.bufferSize = 128;
|
//JustAudioMediaKit.bufferSize = 128;
|
||||||
|
|
||||||
_deezerAPI = initArgs.deezerAPI;
|
_deezerAPI = initArgs.deezerAPI;
|
||||||
|
@ -366,23 +367,6 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
return Future.value();
|
return Future.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// unused.
|
|
||||||
@override
|
|
||||||
Future<void> seekForward(bool begin) => Future.value();
|
|
||||||
|
|
||||||
Future<void> seekBackward(bool begin) async {
|
|
||||||
// (un)favourite action
|
|
||||||
if (cache.libraryTracks.contains(currentMediaItem.id)) {
|
|
||||||
cache.libraryTracks.remove(currentMediaItem.id);
|
|
||||||
_broadcastState();
|
|
||||||
return _deezerAPI.removeFavorite(currentMediaItem.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.libraryTracks.add(currentMediaItem.id);
|
|
||||||
_broadcastState();
|
|
||||||
return _deezerAPI.addFavoriteTrack(currentMediaItem.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove item from queue
|
//Remove item from queue
|
||||||
@override
|
@override
|
||||||
Future<void> removeQueueItem(MediaItem mediaItem) async {
|
Future<void> removeQueueItem(MediaItem mediaItem) async {
|
||||||
|
@ -415,13 +399,9 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
@override
|
@override
|
||||||
Future<void> skipToPrevious() async {
|
Future<void> skipToPrevious() async {
|
||||||
if (_queueIndex == 0) return;
|
if (_queueIndex == 0) return;
|
||||||
//Update buffering state
|
|
||||||
//_skipState = AudioProcessingState.skippingToPrevious;
|
|
||||||
//Normal skip to previous
|
|
||||||
unawaited(_logListenedTrack(currentMediaItem.id, sync: false, prev: true));
|
unawaited(_logListenedTrack(currentMediaItem.id, sync: false, prev: true));
|
||||||
_queueIndex--;
|
_queueIndex--;
|
||||||
await _player.seekToPrevious();
|
await _player.seekToPrevious();
|
||||||
//_skipState = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _logListenedTrack(String trackId,
|
Future<void> _logListenedTrack(String trackId,
|
||||||
|
@ -479,42 +459,52 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
customAction: CustomMediaAction(name: 'favorite'));
|
customAction: CustomMediaAction(name: 'favorite'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> toggleFavoriteCurrent() async {
|
||||||
|
// (un)favourite action
|
||||||
|
if (cache.libraryTracks.contains(currentMediaItem.id)) {
|
||||||
|
cache.libraryTracks.remove(currentMediaItem.id);
|
||||||
|
_broadcastState();
|
||||||
|
await _deezerAPI.removeFavorite(currentMediaItem.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.libraryTracks.add(currentMediaItem.id);
|
||||||
|
_broadcastState();
|
||||||
|
await _deezerAPI.addFavoriteTrack(currentMediaItem.id);
|
||||||
|
}
|
||||||
|
|
||||||
//Update state on all clients
|
//Update state on all clients
|
||||||
void _broadcastState() {
|
void _broadcastState() {
|
||||||
|
final controls = !currentMediaItemIsShow
|
||||||
|
? [
|
||||||
|
if (queue.value.isNotEmpty) favoriteControl(),
|
||||||
|
if (_queueIndex != 0) MediaControl.skipToPrevious,
|
||||||
|
_player.playing ? MediaControl.pause : MediaControl.play,
|
||||||
|
MediaControl.stop,
|
||||||
|
if (queue.hasValue && _queueIndex != queue.value.length - 1)
|
||||||
|
MediaControl.skipToNext,
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
const MediaControl(
|
||||||
|
androidIcon: 'drawable/ic_replay_30',
|
||||||
|
label: 'replay 30',
|
||||||
|
action: MediaAction.rewind,
|
||||||
|
), // acts as prev-30
|
||||||
|
_player.playing ? MediaControl.pause : MediaControl.play,
|
||||||
|
MediaControl.stop,
|
||||||
|
const MediaControl(
|
||||||
|
androidIcon: 'drawable/ic_forward_30',
|
||||||
|
label: 'forward 30',
|
||||||
|
action: MediaAction.fastForward,
|
||||||
|
), // next-30
|
||||||
|
];
|
||||||
playbackState.add(PlaybackState(
|
playbackState.add(PlaybackState(
|
||||||
controls: !currentMediaItemIsShow
|
controls: controls,
|
||||||
? [
|
|
||||||
if (queue.value.isNotEmpty) favoriteControl(),
|
|
||||||
/*if (_queueIndex != 0)*/ MediaControl.skipToPrevious,
|
|
||||||
_player.playing ? MediaControl.pause : MediaControl.play,
|
|
||||||
/**/ MediaControl.skipToNext,
|
|
||||||
//Stop -- USELESS.
|
|
||||||
// MediaControl(
|
|
||||||
// androidIcon: 'drawable/ic_action_stop',
|
|
||||||
// label: 'stop',
|
|
||||||
// action: MediaAction.stop),
|
|
||||||
// i mean, the user can just swipe the notification away to stop
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
const MediaControl(
|
|
||||||
androidIcon: 'drawable/ic_replay_30',
|
|
||||||
label: 'replay 30',
|
|
||||||
action: MediaAction.rewind,
|
|
||||||
), // acts as prev-30
|
|
||||||
_player.playing ? MediaControl.pause : MediaControl.play,
|
|
||||||
const MediaControl(
|
|
||||||
androidIcon: 'drawable/ic_forward_30',
|
|
||||||
label: 'forward 30',
|
|
||||||
action: MediaAction.fastForward,
|
|
||||||
), // next-30
|
|
||||||
],
|
|
||||||
systemActions: !currentMediaItemIsShow
|
systemActions: !currentMediaItemIsShow
|
||||||
? {
|
? const {
|
||||||
MediaAction.seek,
|
MediaAction.seek,
|
||||||
if (queue.hasValue && _queueIndex != queue.value.length - 1)
|
MediaAction.seekForward,
|
||||||
MediaAction.skipToNext,
|
MediaAction.seekBackward,
|
||||||
if (_queueIndex != 0) MediaAction.skipToPrevious,
|
|
||||||
MediaAction.stop
|
|
||||||
}
|
}
|
||||||
: const {
|
: const {
|
||||||
MediaAction.seek,
|
MediaAction.seek,
|
||||||
|
@ -527,8 +517,9 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
bufferedPosition: _player.bufferedPosition,
|
bufferedPosition: _player.bufferedPosition,
|
||||||
speed: _player.speed,
|
speed: _player.speed,
|
||||||
queueIndex: _queueIndex,
|
queueIndex: _queueIndex,
|
||||||
androidCompactActionIndices:
|
androidCompactActionIndices: List.generate(controls.length, (i) => i)
|
||||||
!currentMediaItemIsShow ? const [1, 2, 3] : const [0, 1, 2],
|
.whereNot((i) => controls[i].action == MediaAction.stop)
|
||||||
|
.toList(growable: false),
|
||||||
repeatMode: _repeatMode,
|
repeatMode: _repeatMode,
|
||||||
shuffleMode: _originalQueue == null
|
shuffleMode: _originalQueue == null
|
||||||
? AudioServiceShuffleMode.none
|
? AudioServiceShuffleMode.none
|
||||||
|
@ -536,16 +527,16 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
//just_audio state -> audio_service state. If skipping, use _skipState
|
//just_audio state -> audio_service state.
|
||||||
AudioProcessingState _convertProcessingState(
|
AudioProcessingState _convertProcessingState(
|
||||||
ProcessingState processingState) {
|
ProcessingState processingState) {
|
||||||
return const <ProcessingState, AudioProcessingState>{
|
return switch (processingState) {
|
||||||
ProcessingState.idle: AudioProcessingState.idle,
|
ProcessingState.idle => AudioProcessingState.idle,
|
||||||
ProcessingState.loading: AudioProcessingState.loading,
|
ProcessingState.loading => AudioProcessingState.loading,
|
||||||
ProcessingState.buffering: AudioProcessingState.buffering,
|
ProcessingState.buffering => AudioProcessingState.buffering,
|
||||||
ProcessingState.ready: AudioProcessingState.ready,
|
ProcessingState.ready => AudioProcessingState.ready,
|
||||||
ProcessingState.completed: AudioProcessingState.completed,
|
ProcessingState.completed => AudioProcessingState.completed,
|
||||||
}[processingState]!;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//Replace current queue
|
//Replace current queue
|
||||||
|
@ -699,6 +690,8 @@ class AudioPlayerTask extends BaseAudioHandler {
|
||||||
case 'setIndex':
|
case 'setIndex':
|
||||||
_queueIndex = extras!['index'];
|
_queueIndex = extras!['index'];
|
||||||
break;
|
break;
|
||||||
|
case 'favorite':
|
||||||
|
toggleFavoriteCurrent();
|
||||||
//Start visualizer
|
//Start visualizer
|
||||||
// case 'startVisualizer':
|
// case 'startVisualizer':
|
||||||
// if (_visualizerSubscription != null) break;
|
// if (_visualizerSubscription != null) break;
|
||||||
|
|
|
@ -166,8 +166,8 @@ class MenuSheet {
|
||||||
title: option.label,
|
title: option.label,
|
||||||
leading: option.icon,
|
leading: option.icon,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
option.onTap.call();
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
option.onTap.call();
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.toList(growable: false)),
|
.toList(growable: false)),
|
||||||
|
@ -367,10 +367,7 @@ class MenuSheet {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
navigatorKey.currentState!
|
navigatorKey.currentState!
|
||||||
.push(MaterialPageRoute(builder: (context) => ArtistDetails(a)));
|
.push(MaterialPageRoute(builder: (context) => ArtistDetails(a)));
|
||||||
|
navigateCallback?.call();
|
||||||
if (navigateCallback != null) {
|
|
||||||
navigateCallback!();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -385,9 +382,7 @@ class MenuSheet {
|
||||||
navigatorKey.currentState!
|
navigatorKey.currentState!
|
||||||
.push(MaterialPageRoute(builder: (context) => AlbumDetails(a)));
|
.push(MaterialPageRoute(builder: (context) => AlbumDetails(a)));
|
||||||
|
|
||||||
if (navigateCallback != null) {
|
navigateCallback?.call();
|
||||||
navigateCallback!();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -686,7 +681,9 @@ class MenuSheet {
|
||||||
);
|
);
|
||||||
|
|
||||||
MenuSheetOption wakelock() => MenuSheetOption(
|
MenuSheetOption wakelock() => MenuSheetOption(
|
||||||
Text('Keep the screen on'.i18n),
|
Text(cache.wakelock
|
||||||
|
? 'Don\'t keep screen on'.i18n
|
||||||
|
: 'Keep the screen on'.i18n),
|
||||||
icon: const Icon(Icons.screen_lock_portrait),
|
icon: const Icon(Icons.screen_lock_portrait),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
//Enable
|
//Enable
|
||||||
|
|
|
@ -31,6 +31,7 @@ import 'package:marquee/marquee.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:photo_view/photo_view.dart';
|
import 'package:photo_view/photo_view.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||||
|
|
||||||
const _blurStrength = 90.0;
|
const _blurStrength = 90.0;
|
||||||
|
|
||||||
|
@ -949,11 +950,19 @@ class _BigAlbumArtState extends State<BigAlbumArt> with WidgetsBindingObserver {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushLyrics() {
|
void _pushLyrics() async {
|
||||||
|
// enable wakelock if not already enabled
|
||||||
|
final wakelockChanged = !(await WakelockPlus.enabled);
|
||||||
|
if (wakelockChanged) {
|
||||||
|
WakelockPlus.enable();
|
||||||
|
}
|
||||||
builder(ctx) => ChangeNotifierProvider<BackgroundProvider>.value(
|
builder(ctx) => ChangeNotifierProvider<BackgroundProvider>.value(
|
||||||
value: Provider.of<BackgroundProvider>(context),
|
value: Provider.of<BackgroundProvider>(context),
|
||||||
child: const LyricsScreen());
|
child: const LyricsScreen());
|
||||||
Navigator.of(context).pushRoute(builder: builder);
|
final pushed = Navigator.of(context).pushRoute(builder: builder);
|
||||||
|
if (wakelockChanged) {
|
||||||
|
pushed.then((_) => WakelockPlus.disable());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1044,9 +1053,9 @@ class _BigAlbumArtState extends State<BigAlbumArt> with WidgetsBindingObserver {
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
|
||||||
return Center(
|
return AspectRatio(
|
||||||
child: AspectRatio(
|
aspectRatio: 1.0,
|
||||||
aspectRatio: 1.0,
|
child: Center(
|
||||||
child: settings.playerAlbumArtDropShadow
|
child: settings.playerAlbumArtDropShadow
|
||||||
? Consumer<BackgroundProvider>(
|
? Consumer<BackgroundProvider>(
|
||||||
builder: (context, background, child) => AnimatedContainer(
|
builder: (context, background, child) => AnimatedContainer(
|
||||||
|
|
|
@ -1538,13 +1538,15 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
||||||
ScaffoldMessenger.of(context).snack('Copied'.i18n);
|
ScaffoldMessenger.of(context).snack('Copied'.i18n);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// ListTile(
|
if (kDebugMode) ...[
|
||||||
// title: const Text('DEBUG: stop audioHandler'),
|
ListTile(
|
||||||
// onTap: () => audioHandler.stop()),
|
title: const Text('DEBUG: stop audioHandler'),
|
||||||
// ListTile(
|
onTap: () => audioHandler.stop()),
|
||||||
// title: const Text('DEBUG: show login screen'),
|
ListTile(
|
||||||
// onTap: () => Navigator.of(context, rootNavigator: true)
|
title: const Text('DEBUG: show login screen'),
|
||||||
// .pushRoute(builder: (ctx) => LoginWidget())),
|
onTap: () => Navigator.of(context, rootNavigator: true)
|
||||||
|
.pushRoute(builder: (ctx) => LoginWidget())),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -73,7 +73,7 @@ apply_standard_settings(${BINARY_NAME})
|
||||||
# Add dependency libraries. Add any application-specific dependencies here.
|
# Add dependency libraries. Add any application-specific dependencies here.
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE ${MIMALLOC_LIB})
|
||||||
# Run the Flutter tool portions of the build. This must not be removed.
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ if [ ! -w "$APPLICATIONS_DIR" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF > "$APPLICATIONS_DIR/freezer.desktop"
|
||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=freezer
|
Name=freezer
|
||||||
|
@ -30,5 +30,5 @@ Icon=$ICON
|
||||||
Categories=Audio;Music;Player;AudioVideo;
|
Categories=Audio;Music;Player;AudioVideo;
|
||||||
Keywords=Music;Player;Streaming;Online;
|
Keywords=Music;Player;Streaming;Online;
|
||||||
Terminal=false
|
Terminal=false
|
||||||
EOF > "$APPLICATIONS_DIR/freezer.desktop"
|
EOF
|
||||||
|
|
||||||
|
|
3540
pubspec.lock
3540
pubspec.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue