notification changes
- add like button - switch to rounded icons
BIN
src/android/app/src/main/res/drawable-hdpi/favorite_0.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
src/android/app/src/main/res/drawable-hdpi/favorite_1.png
Normal file
After Width: | Height: | Size: 943 B |
BIN
src/android/app/src/main/res/drawable-hdpi/favorite_2.png
Normal file
After Width: | Height: | Size: 891 B |
BIN
src/android/app/src/main/res/drawable-hdpi/favorite_3.png
Normal file
After Width: | Height: | Size: 748 B |
Before Width: | Height: | Size: 140 B |
Before Width: | Height: | Size: 272 B |
Before Width: | Height: | Size: 102 B |
BIN
src/android/app/src/main/res/drawable-hdpi/pause.png
Normal file
After Width: | Height: | Size: 603 B |
BIN
src/android/app/src/main/res/drawable-hdpi/play.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
src/android/app/src/main/res/drawable-hdpi/skip_next.png
Normal file
After Width: | Height: | Size: 614 B |
BIN
src/android/app/src/main/res/drawable-hdpi/skip_prev.png
Normal file
After Width: | Height: | Size: 687 B |
BIN
src/android/app/src/main/res/drawable-mdpi/favorite_0.png
Normal file
After Width: | Height: | Size: 594 B |
BIN
src/android/app/src/main/res/drawable-mdpi/favorite_1.png
Normal file
After Width: | Height: | Size: 539 B |
BIN
src/android/app/src/main/res/drawable-mdpi/favorite_2.png
Normal file
After Width: | Height: | Size: 505 B |
BIN
src/android/app/src/main/res/drawable-mdpi/favorite_3.png
Normal file
After Width: | Height: | Size: 457 B |
Before Width: | Height: | Size: 108 B |
Before Width: | Height: | Size: 159 B |
Before Width: | Height: | Size: 92 B |
BIN
src/android/app/src/main/res/drawable-mdpi/pause.png
Normal file
After Width: | Height: | Size: 372 B |
BIN
src/android/app/src/main/res/drawable-mdpi/play.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
src/android/app/src/main/res/drawable-mdpi/skip_next.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
src/android/app/src/main/res/drawable-mdpi/skip_prev.png
Normal file
After Width: | Height: | Size: 386 B |
BIN
src/android/app/src/main/res/drawable-xhdpi/favorite_0.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/android/app/src/main/res/drawable-xhdpi/favorite_1.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/android/app/src/main/res/drawable-xhdpi/favorite_2.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/android/app/src/main/res/drawable-xhdpi/favorite_3.png
Normal file
After Width: | Height: | Size: 926 B |
Before Width: | Height: | Size: 162 B |
Before Width: | Height: | Size: 288 B |
Before Width: | Height: | Size: 114 B |
BIN
src/android/app/src/main/res/drawable-xhdpi/pause.png
Normal file
After Width: | Height: | Size: 716 B |
BIN
src/android/app/src/main/res/drawable-xhdpi/play.png
Normal file
After Width: | Height: | Size: 751 B |
BIN
src/android/app/src/main/res/drawable-xhdpi/skip_next.png
Normal file
After Width: | Height: | Size: 670 B |
BIN
src/android/app/src/main/res/drawable-xhdpi/skip_prev.png
Normal file
After Width: | Height: | Size: 759 B |
BIN
src/android/app/src/main/res/drawable-xxhdpi/favorite_0.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/favorite_1.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/favorite_2.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/favorite_3.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 202 B |
Before Width: | Height: | Size: 547 B |
Before Width: | Height: | Size: 196 B |
BIN
src/android/app/src/main/res/drawable-xxhdpi/pause.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/play.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/skip_next.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/android/app/src/main/res/drawable-xxhdpi/skip_prev.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/favorite_0.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/favorite_1.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/favorite_2.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/favorite_3.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 244 B |
Before Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 244 B |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/pause.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/play.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/skip_next.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/android/app/src/main/res/drawable-xxxhdpi/skip_prev.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
|
@ -1,4 +1,5 @@
|
|||
import '../repositories/audio_player_repository.dart';
|
||||
import '../repositories/music_data_repository.dart';
|
||||
import '../repositories/platform_integration_repository.dart';
|
||||
import '../usecases/seek_to_next.dart';
|
||||
|
||||
|
@ -7,17 +8,19 @@ class PlatformIntegrationActor {
|
|||
this._platformIntegrationInfoRepository,
|
||||
this._seekToNext,
|
||||
this._audioPlayerRepository,
|
||||
this._musicDataRepository,
|
||||
) {
|
||||
_platformIntegrationInfoRepository.eventStream
|
||||
.listen((event) => _handlePlatformIntegrationEvent(event));
|
||||
}
|
||||
|
||||
final AudioPlayerRepository _audioPlayerRepository;
|
||||
final MusicDataRepository _musicDataRepository;
|
||||
final PlatformIntegrationInfoRepository _platformIntegrationInfoRepository;
|
||||
|
||||
final SeekToNext _seekToNext;
|
||||
|
||||
void _handlePlatformIntegrationEvent(PlatformIntegrationEvent event) {
|
||||
Future<void> _handlePlatformIntegrationEvent(PlatformIntegrationEvent event) async {
|
||||
switch (event.type) {
|
||||
case PlatformIntegrationEventType.play:
|
||||
_audioPlayerRepository.play();
|
||||
|
@ -36,6 +39,13 @@ class PlatformIntegrationActor {
|
|||
case PlatformIntegrationEventType.seek:
|
||||
_seekToPosition(event.payload!['position'] as Duration);
|
||||
break;
|
||||
case PlatformIntegrationEventType.like:
|
||||
final path = event.payload?['path'];
|
||||
if (path != null) {
|
||||
final song = await _musicDataRepository.getSongByPath(path as String);
|
||||
_musicDataRepository.incrementLikeCount(song);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ abstract class MusicDataRepository extends MusicDataInfoRepository {
|
|||
Future<Song> resetSkipCount(Song song);
|
||||
|
||||
Future<void> setLikeCount(List<Song> songs, int count);
|
||||
Future<void> incrementLikeCount(Song song);
|
||||
|
||||
Future<Song> incrementPlayCount(Song song);
|
||||
|
||||
|
|
|
@ -2,12 +2,6 @@ import '../entities/event.dart';
|
|||
import '../entities/playback_event.dart';
|
||||
import '../entities/song.dart';
|
||||
|
||||
/*
|
||||
|
||||
- position
|
||||
- controls (playbackState)
|
||||
|
||||
*/
|
||||
|
||||
abstract class PlatformIntegrationInfoRepository {
|
||||
Stream<PlatformIntegrationEvent> get eventStream;
|
||||
|
@ -16,7 +10,6 @@ abstract class PlatformIntegrationInfoRepository {
|
|||
abstract class PlatformIntegrationRepository extends PlatformIntegrationInfoRepository {
|
||||
void handlePlaybackEvent(PlaybackEvent playbackEvent);
|
||||
void setCurrentSong(Song? song);
|
||||
// void setQueue(List<Song> queue);
|
||||
}
|
||||
|
||||
class PlatformIntegrationEvent extends Event {
|
||||
|
@ -32,4 +25,5 @@ enum PlatformIntegrationEventType {
|
|||
skipNext,
|
||||
skipPrevious,
|
||||
seek,
|
||||
like,
|
||||
}
|
||||
|
|
|
@ -349,6 +349,7 @@ Future<void> setupGetIt() async {
|
|||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
@ -9,6 +9,50 @@ import '../models/playback_event_model.dart';
|
|||
import '../models/song_model.dart';
|
||||
import 'platform_integration_data_source.dart';
|
||||
|
||||
const favs = [
|
||||
MediaControl(
|
||||
androidIcon: 'drawable/favorite_0',
|
||||
label: 'Like',
|
||||
action: MediaAction.rewind,
|
||||
),
|
||||
MediaControl(
|
||||
androidIcon: 'drawable/favorite_1',
|
||||
label: 'Like',
|
||||
action: MediaAction.rewind,
|
||||
),
|
||||
MediaControl(
|
||||
androidIcon: 'drawable/favorite_2',
|
||||
label: 'Like',
|
||||
action: MediaAction.rewind,
|
||||
),
|
||||
MediaControl(
|
||||
androidIcon: 'drawable/favorite_3',
|
||||
label: 'Like',
|
||||
action: MediaAction.rewind,
|
||||
),
|
||||
];
|
||||
|
||||
const playCtrl = MediaControl(
|
||||
androidIcon: 'drawable/play',
|
||||
label: 'Play',
|
||||
action: MediaAction.play,
|
||||
);
|
||||
const pauseCtrl = MediaControl(
|
||||
androidIcon: 'drawable/pause',
|
||||
label: 'Pause',
|
||||
action: MediaAction.pause,
|
||||
);
|
||||
const nextCtrl = MediaControl(
|
||||
androidIcon: 'drawable/skip_next',
|
||||
label: 'Next',
|
||||
action: MediaAction.skipToNext,
|
||||
);
|
||||
const prevCtrl = MediaControl(
|
||||
androidIcon: 'drawable/skip_prev',
|
||||
label: 'Previous',
|
||||
action: MediaAction.skipToPrevious,
|
||||
);
|
||||
|
||||
class PlatformIntegrationDataSourceImpl extends BaseAudioHandler
|
||||
implements PlatformIntegrationDataSource {
|
||||
PlatformIntegrationDataSourceImpl();
|
||||
|
@ -52,6 +96,13 @@ class PlatformIntegrationDataSourceImpl extends BaseAudioHandler
|
|||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> rewind() async {
|
||||
_log.d('rewind -> like');
|
||||
_eventSubject.add(PlatformIntegrationEvent(
|
||||
type: PlatformIntegrationEventType.like, payload: {'path': mediaItem.value?.id}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> click([MediaButton button = MediaButton.media]) async {
|
||||
_log.i(button.toString());
|
||||
|
@ -89,39 +140,45 @@ class PlatformIntegrationDataSourceImpl extends BaseAudioHandler
|
|||
|
||||
@override
|
||||
Future<void> handlePlaybackEvent(PlaybackEventModel pe) async {
|
||||
final mi = mediaItem.value;
|
||||
final int likeCount = mi == null ? 0 : mi.extras!['likeCount'] as int;
|
||||
|
||||
if (pe.processingState == ProcessingState.ready) {
|
||||
final timeDelta = DateTime.now().difference(pe.updateTime);
|
||||
if (pe.playing) {
|
||||
playbackState.add(playbackState.value.copyWith(
|
||||
controls: [MediaControl.skipToPrevious, MediaControl.pause, MediaControl.skipToNext],
|
||||
controls: [favs[likeCount], prevCtrl, pauseCtrl, nextCtrl],
|
||||
systemActions: const {
|
||||
MediaAction.seek,
|
||||
},
|
||||
playing: true,
|
||||
processingState: AudioProcessingState.ready,
|
||||
updatePosition: pe.updatePosition + timeDelta,
|
||||
androidCompactActionIndices: [0, 2, 3],
|
||||
));
|
||||
} else {
|
||||
playbackState.add(playbackState.value.copyWith(
|
||||
controls: [MediaControl.skipToPrevious, MediaControl.play, MediaControl.skipToNext],
|
||||
controls: [favs[likeCount], prevCtrl, playCtrl, nextCtrl],
|
||||
systemActions: const {
|
||||
MediaAction.seek,
|
||||
},
|
||||
processingState: AudioProcessingState.ready,
|
||||
updatePosition: pe.updatePosition + timeDelta,
|
||||
playing: false,
|
||||
androidCompactActionIndices: [0, 2, 3],
|
||||
));
|
||||
}
|
||||
} else if (pe.processingState == ProcessingState.completed) {
|
||||
final timeDelta = DateTime.now().difference(pe.updateTime);
|
||||
playbackState.add(playbackState.value.copyWith(
|
||||
controls: [MediaControl.skipToPrevious, MediaControl.play, MediaControl.skipToNext],
|
||||
controls: [favs[likeCount], prevCtrl, playCtrl, nextCtrl],
|
||||
systemActions: const {
|
||||
MediaAction.seek,
|
||||
},
|
||||
processingState: AudioProcessingState.ready,
|
||||
updatePosition: pe.updatePosition + timeDelta,
|
||||
playing: false,
|
||||
androidCompactActionIndices: [0, 2, 3],
|
||||
));
|
||||
} else if (pe.processingState == ProcessingState.none) {
|
||||
stop();
|
||||
|
@ -133,6 +190,17 @@ class PlatformIntegrationDataSourceImpl extends BaseAudioHandler
|
|||
@override
|
||||
Future<void> setCurrentSong(SongModel? songModel) async {
|
||||
mediaItem.add(songModel?.toMediaItem());
|
||||
|
||||
if (songModel != null) {
|
||||
final state = playbackState.value;
|
||||
final controls = state.controls.sublist(1);
|
||||
final timeDelta = state.playing ? DateTime.now().difference(state.updateTime) : Duration.zero;
|
||||
|
||||
playbackState.add(playbackState.value.copyWith(
|
||||
controls: [favs[songModel.likeCount]] + controls,
|
||||
updatePosition: state.updatePosition + timeDelta,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,12 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> incrementLikeCount(Song song) async {
|
||||
final count = song.likeCount < MAX_LIKE_COUNT ? song.likeCount + 1 : 0;
|
||||
await setLikeCount([song], count);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Song> resetSkipCount(Song song) async {
|
||||
final newSong = (song as SongModel).copyWith(skipCount: 0);
|
||||
|
|