mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-09-20 06:34:00 +00:00
Merge pull request #1 from Raasu258/feat/add-favorite-button-android-auto-ui
feat(android-auto): add favorite button to notification UI
This commit is contained in:
commit
a8bd52718f
9
android/app/src/main/res/drawable/ic_favorite.xml
Normal file
9
android/app/src/main/res/drawable/ic_favorite.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5 18.5,5 20,6.5 20,8.5c0,2.89 -3.14,5.74 -7.9,10.05z" />
|
||||||
|
</vector>
|
||||||
9
android/app/src/main/res/drawable/ic_favorite_on.xml
Normal file
9
android/app/src/main/res/drawable/ic_favorite_on.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z" />
|
||||||
|
</vector>
|
||||||
@ -7,6 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:spotube/models/metadata/metadata.dart';
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/provider/audio_player/state.dart';
|
import 'package:spotube/provider/audio_player/state.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/library/tracks.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/services/metadata/metadata.dart';
|
import 'package:spotube/services/metadata/metadata.dart';
|
||||||
@ -49,6 +50,9 @@ class MobileAudioService extends BaseAudioHandler {
|
|||||||
/// Name of the custom "shuffle" media control action.
|
/// Name of the custom "shuffle" media control action.
|
||||||
static const String _shuffleActionName = 'shuffle';
|
static const String _shuffleActionName = 'shuffle';
|
||||||
|
|
||||||
|
/// Name of the custom "favorite" media control action.
|
||||||
|
static const String _favoriteActionName = 'favorite';
|
||||||
|
|
||||||
// ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
|
// ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
|
||||||
AudioPlayerState get playlist => audioPlayerNotifier.state;
|
AudioPlayerState get playlist => audioPlayerNotifier.state;
|
||||||
|
|
||||||
@ -143,6 +147,22 @@ class MobileAudioService extends BaseAudioHandler {
|
|||||||
playbackState.add(await _transformEvent());
|
playbackState.add(await _transformEvent());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (name == _favoriteActionName) {
|
||||||
|
final track = playlist.activeTrack;
|
||||||
|
if (track != null) {
|
||||||
|
final isLiked =
|
||||||
|
await ref.read(metadataPluginIsSavedTrackProvider(track.id).future);
|
||||||
|
final notifier = ref.read(metadataPluginSavedTracksProvider.notifier);
|
||||||
|
if (isLiked) {
|
||||||
|
await notifier.removeFavorite([track]);
|
||||||
|
} else {
|
||||||
|
await notifier.addFavorite([track]);
|
||||||
|
}
|
||||||
|
// Refresh playback state so the control's icon reflects the new state.
|
||||||
|
playbackState.add(await _transformEvent());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return super.customAction(name, extras);
|
return super.customAction(name, extras);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -534,12 +554,26 @@ class MobileAudioService extends BaseAudioHandler {
|
|||||||
|
|
||||||
Future<PlaybackState> _transformEvent() async {
|
Future<PlaybackState> _transformEvent() async {
|
||||||
try {
|
try {
|
||||||
|
final activeTrackId = playlist.activeTrack?.id;
|
||||||
|
final favoriteAsync = activeTrackId != null
|
||||||
|
? ref.read(metadataPluginIsSavedTrackProvider(activeTrackId))
|
||||||
|
: null;
|
||||||
|
final isFavorite = favoriteAsync?.valueOrNull ?? false;
|
||||||
|
|
||||||
return PlaybackState(
|
return PlaybackState(
|
||||||
controls: [
|
controls: [
|
||||||
MediaControl.skipToPrevious,
|
MediaControl.skipToPrevious,
|
||||||
audioPlayer.isPlaying ? MediaControl.pause : MediaControl.play,
|
audioPlayer.isPlaying ? MediaControl.pause : MediaControl.play,
|
||||||
MediaControl.skipToNext,
|
MediaControl.skipToNext,
|
||||||
MediaControl.stop,
|
// Toggles the current track's Liked status instead of the less
|
||||||
|
// useful "stop". audio_service doesn't expose a standard favorite
|
||||||
|
// action, so this is a tappable custom control, same as shuffle.
|
||||||
|
MediaControl.custom(
|
||||||
|
androidIcon:
|
||||||
|
isFavorite ? 'drawable/ic_favorite_on' : 'drawable/ic_favorite',
|
||||||
|
label: 'Favorite',
|
||||||
|
name: _favoriteActionName,
|
||||||
|
),
|
||||||
// Explicit shuffle toggle. audio_service always advertises the
|
// Explicit shuffle toggle. audio_service always advertises the
|
||||||
// standard ACTION_SET_SHUFFLE_MODE, but Android Auto doesn't reliably
|
// standard ACTION_SET_SHUFFLE_MODE, but Android Auto doesn't reliably
|
||||||
// render a toggle from it, so we expose a tappable custom control.
|
// render a toggle from it, so we expose a tappable custom control.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user