added play-, like- and skipCount
This commit is contained in:
parent
a4d7a0071e
commit
58e2c7be81
15 changed files with 235 additions and 52 deletions
|
@ -41,5 +41,16 @@ class Song extends Equatable {
|
|||
final int trackNumber;
|
||||
|
||||
@override
|
||||
List<Object> get props => [title, album, artist, blocked];
|
||||
List<Object> get props => [
|
||||
path,
|
||||
title,
|
||||
album,
|
||||
artist,
|
||||
blocked,
|
||||
next,
|
||||
previous,
|
||||
likeCount,
|
||||
playCount,
|
||||
skipCount,
|
||||
];
|
||||
}
|
||||
|
|
16
lib/domain/repositories/music_data_modifier_repository.dart
Normal file
16
lib/domain/repositories/music_data_modifier_repository.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
import '../entities/song.dart';
|
||||
|
||||
abstract class MusicDataModifierRepository {
|
||||
Future<void> setSongBlocked(Song song, bool blocked);
|
||||
Future<void> toggleNextSongLink(Song song);
|
||||
|
||||
Future<void> incrementSkipCount(Song song);
|
||||
Future<void> resetSkipCount(Song song);
|
||||
|
||||
Future<void> incrementLikeCount(Song song);
|
||||
Future<void> decrementLikeCount(Song song);
|
||||
Future<void> resetLikeCount(Song song);
|
||||
|
||||
Future<void> incrementPlayCount(Song song);
|
||||
Future<void> resetPlayCount(Song song);
|
||||
}
|
|
@ -12,7 +12,4 @@ abstract class MusicDataRepository {
|
|||
Stream<List<Artist>> get artistStream;
|
||||
|
||||
Future<void> updateDatabase();
|
||||
|
||||
Future<void> setSongBlocked(Song song, bool blocked);
|
||||
Future<void> toggleNextSongLink(Song song);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:get_it/get_it.dart';
|
|||
import 'package:just_audio/just_audio.dart' as ja;
|
||||
|
||||
import 'domain/repositories/audio_repository.dart';
|
||||
import 'domain/repositories/music_data_modifier_repository.dart';
|
||||
import 'domain/repositories/music_data_repository.dart';
|
||||
import 'domain/repositories/persistent_player_state_repository.dart';
|
||||
import 'domain/repositories/settings_repository.dart';
|
||||
|
@ -24,6 +25,7 @@ import 'system/datasources/music_data_source_contract.dart';
|
|||
import 'system/datasources/player_state_data_source.dart';
|
||||
import 'system/datasources/settings_data_source.dart';
|
||||
import 'system/repositories/audio_repository_impl.dart';
|
||||
import 'system/repositories/music_data_modifier_repository_impl.dart';
|
||||
import 'system/repositories/music_data_repository_impl.dart';
|
||||
import 'system/repositories/persistent_player_state_repository_impl.dart';
|
||||
import 'system/repositories/settings_repository_impl.dart';
|
||||
|
@ -39,6 +41,7 @@ Future<void> setupGetIt() async {
|
|||
final musicDataStore = MusicDataStore(
|
||||
musicDataRepository: getIt(),
|
||||
settingsRepository: getIt(),
|
||||
musicDataModifierRepository: getIt(),
|
||||
);
|
||||
return musicDataStore;
|
||||
},
|
||||
|
@ -66,15 +69,26 @@ Future<void> setupGetIt() async {
|
|||
getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<MusicDataModifierRepository>(
|
||||
() => MusicDataModifierRepositoryImpl(
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<AudioRepository>(
|
||||
() => AudioRepositoryImpl(
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<PlayerStateRepository>(
|
||||
() => PlayerStateRepositoryImpl(getIt()),
|
||||
() => PlayerStateRepositoryImpl(
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<SettingsRepository>(
|
||||
() => SettingsRepositoryImpl(
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<SettingsRepository>(() => SettingsRepositoryImpl(getIt()));
|
||||
|
||||
// data sources
|
||||
final MoorDatabase moorDatabase = MoorDatabase();
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:mobx/mobx.dart';
|
|||
import '../../domain/entities/album.dart';
|
||||
import '../../domain/entities/artist.dart';
|
||||
import '../../domain/entities/song.dart';
|
||||
import '../../domain/repositories/music_data_modifier_repository.dart';
|
||||
import '../../domain/repositories/music_data_repository.dart';
|
||||
import '../../domain/repositories/settings_repository.dart';
|
||||
|
||||
|
@ -13,17 +14,20 @@ class MusicDataStore extends _MusicDataStore with _$MusicDataStore {
|
|||
MusicDataStore({
|
||||
@required MusicDataRepository musicDataRepository,
|
||||
@required SettingsRepository settingsRepository,
|
||||
}) : super(musicDataRepository, settingsRepository);
|
||||
@required MusicDataModifierRepository musicDataModifierRepository,
|
||||
}) : super(musicDataRepository, settingsRepository, musicDataModifierRepository);
|
||||
}
|
||||
|
||||
abstract class _MusicDataStore with Store {
|
||||
_MusicDataStore(this._musicDataRepository, this._settingsRepository) {
|
||||
_MusicDataStore(
|
||||
this._musicDataRepository, this._settingsRepository, this._musicDataModifierRepository) {
|
||||
songStream = _musicDataRepository.songStream.asObservable(initialValue: []);
|
||||
albumStream = _musicDataRepository.albumStream.asObservable(initialValue: []);
|
||||
artistStream = _musicDataRepository.artistStream.asObservable(initialValue: []);
|
||||
}
|
||||
|
||||
final MusicDataRepository _musicDataRepository;
|
||||
final MusicDataModifierRepository _musicDataModifierRepository;
|
||||
final SettingsRepository _settingsRepository;
|
||||
|
||||
@observable
|
||||
|
@ -51,7 +55,6 @@ abstract class _MusicDataStore with Store {
|
|||
isUpdatingDatabase = false;
|
||||
}
|
||||
|
||||
|
||||
@action
|
||||
Future<void> fetchSongsFromAlbum(Album album) async {
|
||||
albumSongStream = _musicDataRepository.getAlbumSongStream(album).asObservable(initialValue: []);
|
||||
|
@ -64,13 +67,18 @@ abstract class _MusicDataStore with Store {
|
|||
}
|
||||
|
||||
Future<void> setSongBlocked(Song song, bool blocked) async {
|
||||
await _musicDataRepository.setSongBlocked(song, blocked);
|
||||
await _musicDataModifierRepository.setSongBlocked(song, blocked);
|
||||
}
|
||||
|
||||
Future<void> toggleNextSongLink(Song song) async {
|
||||
await _musicDataRepository.toggleNextSongLink(song);
|
||||
await _musicDataModifierRepository.toggleNextSongLink(song);
|
||||
}
|
||||
|
||||
Future<void> incrementLikeCount(Song song) =>
|
||||
_musicDataModifierRepository.incrementLikeCount(song);
|
||||
|
||||
Future<void> resetLikeCount(Song song) => _musicDataModifierRepository.resetLikeCount(song);
|
||||
|
||||
Future<void> addLibraryFolder(String path) async {
|
||||
await _settingsRepository.addLibraryFolder(path);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ class AlbumArt extends StatelessWidget {
|
|||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0x00000000), Color(0xCC000000)],
|
||||
colors: [Color(0x00000000), Color(0xBB000000)],
|
||||
stops: [0.0, 1.0],
|
||||
),
|
||||
),
|
||||
|
@ -64,22 +64,32 @@ class AlbumArt extends StatelessWidget {
|
|||
shadows: [
|
||||
const Shadow(
|
||||
blurRadius: 2.0,
|
||||
color: Colors.black45,
|
||||
color: Colors.black87,
|
||||
offset: Offset(.5, .5),
|
||||
),
|
||||
const Shadow(
|
||||
blurRadius: 8.0,
|
||||
color: Colors.black54,
|
||||
offset: Offset(0, 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
song.artist,
|
||||
style: TEXT_SUBTITLE.copyWith(
|
||||
color: Colors.grey[300],
|
||||
color: Colors.grey[100],
|
||||
shadows: [
|
||||
const Shadow(
|
||||
blurRadius: 2.0,
|
||||
color: Colors.black45,
|
||||
color: Colors.black87,
|
||||
offset: Offset(.5, .5),
|
||||
),
|
||||
const Shadow(
|
||||
blurRadius: 8.0,
|
||||
color: Colors.black54,
|
||||
offset: Offset(0, 0),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -28,7 +28,7 @@ class LikeButton extends StatelessWidget {
|
|||
size: iconSize,
|
||||
color: Colors.white24,
|
||||
),
|
||||
onPressed: null,
|
||||
onPressed: () => musicDataStore.incrementLikeCount(song),
|
||||
);
|
||||
} else {
|
||||
return IconButton(
|
||||
|
@ -50,7 +50,12 @@ class LikeButton extends StatelessWidget {
|
|||
],
|
||||
alignment: AlignmentDirectional.center,
|
||||
),
|
||||
onPressed: null,
|
||||
onPressed: () {
|
||||
if (song.likeCount < 5) {
|
||||
return musicDataStore.incrementLikeCount(song);
|
||||
}
|
||||
return musicDataStore.resetLikeCount(song);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -20,22 +20,22 @@ class MyAudioHandler extends BaseAudioHandler {
|
|||
_handleSetQueue(event);
|
||||
});
|
||||
|
||||
_audioPlayer.currentSongStream.listen((songModel) {
|
||||
mediaItem.add(songModel.toMediaItem());
|
||||
});
|
||||
_audioPlayer.currentSongStream.listen((songModel) => mediaItem.add(songModel.toMediaItem()));
|
||||
|
||||
_audioPlayer.playbackEventStream.listen((event) {
|
||||
_handlePlaybackEvent(event);
|
||||
});
|
||||
_audioPlayer.playbackEventStream.listen((event) => _handlePlaybackEvent(event));
|
||||
|
||||
_audioPlayer.shuffleModeStream.listen((shuffleMode) {
|
||||
_audioPlayer.shuffleModeStream.skip(1).listen((shuffleMode) {
|
||||
_playerStateDataSource.setShuffleMode(shuffleMode);
|
||||
});
|
||||
|
||||
_audioPlayer.loopModeStream.listen((event) {
|
||||
_audioPlayer.loopModeStream.skip(1).listen((event) {
|
||||
_playerStateDataSource.setLoopMode(event);
|
||||
});
|
||||
|
||||
_audioPlayer.positionStream.listen((event) {
|
||||
_handlePosition(event, _audioPlayer.currentSongStream.value);
|
||||
});
|
||||
|
||||
_initAudioPlayer();
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,8 @@ class MyAudioHandler extends BaseAudioHandler {
|
|||
|
||||
static final _log = Logger('AudioHandler');
|
||||
|
||||
bool _countSongPlayback = true;
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
await _audioPlayer.stop();
|
||||
|
@ -82,7 +84,11 @@ class MyAudioHandler extends BaseAudioHandler {
|
|||
|
||||
@override
|
||||
Future<void> skipToNext() async {
|
||||
_audioPlayer.seekToNext();
|
||||
_audioPlayer.seekToNext().then((value) {
|
||||
if (value) {
|
||||
_musicDataSource.incrementSkipCount(_audioPlayer.currentSongStream.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -187,4 +193,18 @@ class MyAudioHandler extends BaseAudioHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _handlePosition(Duration position, SongModel song) {
|
||||
if (song == null || position == null)
|
||||
return;
|
||||
|
||||
final int pos = position.inMilliseconds;
|
||||
|
||||
if (pos < song.duration * 0.05) {
|
||||
_countSongPlayback = true;
|
||||
} else if (pos > song.duration * 0.95 && _countSongPlayback) {
|
||||
_countSongPlayback = false;
|
||||
_musicDataSource.incrementPlayCount(song);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ abstract class AudioPlayer {
|
|||
Future<void> play();
|
||||
Future<void> pause();
|
||||
Future<void> stop();
|
||||
Future<void> seekToNext();
|
||||
Future<bool> seekToNext();
|
||||
Future<void> seekToPrevious();
|
||||
Future<void> dispose();
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class AudioPlayerImpl implements AudioPlayer {
|
|||
_audioPlayer.currentIndexStream.listen((event) {
|
||||
_log.info('currentIndex: $event');
|
||||
_currentIndexSubject.add(event);
|
||||
if (_queueSubject.value != null) {
|
||||
if (_queueSubject.value != null && event != null) {
|
||||
_currentSongSubject.add(_queueSubject.value[event].song);
|
||||
}
|
||||
});
|
||||
|
@ -151,13 +151,19 @@ class AudioPlayerImpl implements AudioPlayer {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> seekToNext() async {
|
||||
Future<bool> seekToNext() async {
|
||||
final result = _audioPlayer.hasNext;
|
||||
await _audioPlayer.seekToNext();
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> seekToPrevious() async {
|
||||
await _audioPlayer.seekToPrevious();
|
||||
if (_audioPlayer.position > const Duration(seconds: 3) || !_audioPlayer.hasPrevious) {
|
||||
await _audioPlayer.seek(const Duration(seconds: 0));
|
||||
} else {
|
||||
await _audioPlayer.seekToPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -180,10 +186,9 @@ class AudioPlayerImpl implements AudioPlayer {
|
|||
@override
|
||||
Future<void> moveQueueItem(int oldIndex, int newIndex) async {
|
||||
final QueueItemModel queueItem = _queue.removeAt(oldIndex);
|
||||
final index = newIndex < oldIndex ? newIndex : newIndex - 1;
|
||||
_queue.insert(index, queueItem);
|
||||
_queue.insert(newIndex, queueItem);
|
||||
_queueSubject.add(_queue);
|
||||
await _audioSource.move(oldIndex, index);
|
||||
await _audioSource.move(oldIndex, newIndex);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -195,6 +200,7 @@ class AudioPlayerImpl implements AudioPlayer {
|
|||
|
||||
@override
|
||||
Future<void> setShuffleMode(ShuffleMode shuffleMode, bool updateQueue) async {
|
||||
_log.info('setShuffleMode: $shuffleMode');
|
||||
if (shuffleMode == null) return;
|
||||
_shuffleModeSubject.add(shuffleMode);
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ class MusicDataDao extends DatabaseAccessor<MoorDatabase>
|
|||
|
||||
@override
|
||||
Stream<List<SongModel>> get songStream {
|
||||
return select(songs).watch().map((moorSongList) =>
|
||||
moorSongList.map((moorSong) => SongModel.fromMoor(moorSong)).toList());
|
||||
return select(songs).watch().map(
|
||||
(moorSongList) => moorSongList.map((moorSong) => SongModel.fromMoor(moorSong)).toList());
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -46,8 +46,8 @@ class MusicDataDao extends DatabaseAccessor<MoorDatabase>
|
|||
|
||||
@override
|
||||
Future<List<SongModel>> getSongs() {
|
||||
return select(songs).get().then((moorSongList) =>
|
||||
moorSongList.map((moorSong) => SongModel.fromMoor(moorSong)).toList());
|
||||
return select(songs).get().then(
|
||||
(moorSongList) => moorSongList.map((moorSong) => SongModel.fromMoor(moorSong)).toList());
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -170,4 +170,58 @@ class MusicDataDao extends DatabaseAccessor<MoorDatabase>
|
|||
.write(const SongsCompanion(next: Value(null)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> decrementLikeCount(SongModel song) async {
|
||||
final songEntry = await (select(songs)..where((tbl) => tbl.path.equals(song.path))).getSingle();
|
||||
|
||||
if (song.likeCount > 0) {
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(SongsCompanion(likeCount: Value(songEntry.likeCount - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> incrementLikeCount(SongModel song) async {
|
||||
final songEntry = await (select(songs)..where((tbl) => tbl.path.equals(song.path))).getSingle();
|
||||
|
||||
if (song.likeCount < 5) {
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(SongsCompanion(likeCount: Value(songEntry.likeCount + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> incrementPlayCount(SongModel song) async {
|
||||
final songEntry = await (select(songs)..where((tbl) => tbl.path.equals(song.path))).getSingle();
|
||||
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(SongsCompanion(playCount: Value(songEntry.playCount + 1)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> incrementSkipCount(SongModel song) async {
|
||||
final songEntry = await (select(songs)..where((tbl) => tbl.path.equals(song.path))).getSingle();
|
||||
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(SongsCompanion(skipCount: Value(songEntry.skipCount + 1)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> resetLikeCount(SongModel song) async {
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(const SongsCompanion(likeCount: Value(0)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> resetPlayCount(SongModel song) async {
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(const SongsCompanion(playCount: Value(0)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> resetSkipCount(SongModel song) async {
|
||||
await (update(songs)..where((tbl) => tbl.path.equals(song.path)))
|
||||
.write(const SongsCompanion(skipCount: Value(0)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,11 +86,13 @@ class PlayerStateDao extends DatabaseAccessor<MoorDatabase>
|
|||
Future<void> setLoopMode(LoopMode loopMode) async {
|
||||
final currentState = await select(persistentLoopMode).getSingle();
|
||||
if (currentState != null) {
|
||||
update(persistentLoopMode)
|
||||
.write(PersistentLoopModeCompanion(loopMode: Value(loopMode.toInt())));
|
||||
update(persistentLoopMode).write(PersistentLoopModeCompanion(
|
||||
loopMode: Value(loopMode.toInt()),
|
||||
));
|
||||
} else {
|
||||
into(persistentLoopMode)
|
||||
.insert(PersistentLoopModeCompanion(loopMode: Value(loopMode.toInt())));
|
||||
into(persistentLoopMode).insert(PersistentLoopModeCompanion(
|
||||
loopMode: Value(loopMode.toInt()),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,9 +17,16 @@ abstract class MusicDataSource {
|
|||
|
||||
Future<void> insertSong(SongModel songModel);
|
||||
Future<void> insertSongs(List<SongModel> songModels);
|
||||
Future<void> deleteAllSongs();
|
||||
Future<void> setSongBlocked(SongModel song, bool blocked);
|
||||
Future<void> toggleNextSongLink(SongModel song);
|
||||
Future<void> deleteAllSongs();
|
||||
Future<void> incrementSkipCount(SongModel song);
|
||||
Future<void> resetSkipCount(SongModel song);
|
||||
Future<void> incrementLikeCount(SongModel song);
|
||||
Future<void> decrementLikeCount(SongModel song);
|
||||
Future<void> resetLikeCount(SongModel song);
|
||||
Future<void> incrementPlayCount(SongModel song);
|
||||
Future<void> resetPlayCount(SongModel song);
|
||||
|
||||
/// Insert album into the database. Return the ID of the inserted album.
|
||||
Future<int> insertAlbum(AlbumModel albumModel);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import '../../domain/entities/song.dart';
|
||||
import '../../domain/repositories/music_data_modifier_repository.dart';
|
||||
import '../datasources/music_data_source_contract.dart';
|
||||
import '../models/song_model.dart';
|
||||
|
||||
class MusicDataModifierRepositoryImpl implements MusicDataModifierRepository {
|
||||
MusicDataModifierRepositoryImpl(this._musicDataSource);
|
||||
|
||||
final MusicDataSource _musicDataSource;
|
||||
|
||||
@override
|
||||
Future<void> setSongBlocked(Song song, bool blocked) =>
|
||||
_musicDataSource.setSongBlocked(song as SongModel, blocked);
|
||||
|
||||
@override
|
||||
Future<void> toggleNextSongLink(Song song) =>
|
||||
_musicDataSource.toggleNextSongLink(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> decrementLikeCount(Song song) =>
|
||||
_musicDataSource.decrementLikeCount(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> incrementLikeCount(Song song) =>
|
||||
_musicDataSource.incrementLikeCount(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> incrementPlayCount(Song song) =>
|
||||
_musicDataSource.incrementPlayCount(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> incrementSkipCount(Song song) =>
|
||||
_musicDataSource.incrementSkipCount(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> resetLikeCount(Song song) => _musicDataSource.resetLikeCount(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> resetPlayCount(Song song) => _musicDataSource.resetPlayCount(song as SongModel);
|
||||
|
||||
@override
|
||||
Future<void> resetSkipCount(Song song) => _musicDataSource.resetSkipCount(song as SongModel);
|
||||
}
|
|
@ -50,11 +50,6 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
|||
_log.info('updateDatabase finished');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setSongBlocked(Song song, bool blocked) async {
|
||||
await _musicDataSource.setSongBlocked(song as SongModel, blocked);
|
||||
}
|
||||
|
||||
Future<void> updateArtists(List<ArtistModel> artists) async {
|
||||
await _musicDataSource.deleteAllArtists();
|
||||
for (final ArtistModel artist in artists) {
|
||||
|
@ -107,11 +102,6 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
|||
await _musicDataSource.insertSongs(songsToInsert);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> toggleNextSongLink(Song song) async {
|
||||
_musicDataSource.toggleNextSongLink(song as SongModel);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<Album>> getArtistAlbumStream(Artist artist) {
|
||||
return _musicDataSource.getArtistAlbumStream(artist as ArtistModel);
|
||||
|
|
Loading…
Add table
Reference in a new issue