diff --git a/lib/presentation/widgets/audio_service_widget.dart b/lib/presentation/widgets/audio_service_widget.dart index fe5e311..02ebb9b 100644 --- a/lib/presentation/widgets/audio_service_widget.dart +++ b/lib/presentation/widgets/audio_service_widget.dart @@ -35,7 +35,8 @@ class _AudioServiceWidgetState extends State case AppLifecycleState.resumed: print('AppLifecycleState.resumed'); AudioService.connect(); - AudioService.customAction(APP_LIFECYCLE_RESUMED); + if (AudioService.running) + AudioService.customAction(APP_LIFECYCLE_RESUMED); break; case AppLifecycleState.paused: print('AppLifecycleState.paused'); diff --git a/lib/system/datasources/moor_music_data_source.dart b/lib/system/datasources/moor_music_data_source.dart index 21edca8..6dd4bf1 100644 --- a/lib/system/datasources/moor_music_data_source.dart +++ b/lib/system/datasources/moor_music_data_source.dart @@ -44,6 +44,7 @@ class Songs extends Table { TextColumn get albumArtPath => text().nullable()(); IntColumn get trackNumber => integer().nullable()(); BoolColumn get blocked => boolean().withDefault(const Constant(false))(); + BoolColumn get present => boolean().withDefault(const Constant(true))(); @override Set get primaryKey => {path}; @@ -139,6 +140,29 @@ class MoorMusicDataSource extends _$MoorMusicDataSource .map((moorArtist) => ArtistModel.fromMoorArtist(moorArtist)) .toList()); } + + @override + Future insertSongs(List songModels) async { + + await update(songs).write(const SongsCompanion(present: Value(false))); + + await batch((batch) { + batch.insertAllOnConflictUpdate( + songs, + songModels + .map((e) => e.toMoorInsert()) + .toList(), + ); + }); + + await (delete(songs)..where((tbl) => tbl.present.equals(false))).go(); + } + + @override + Future setSongBlocked(SongModel song, bool blocked) async { + await (update(songs)..where((tbl) => tbl.path.equals(song.path))) + .write(SongsCompanion(blocked: Value(blocked))); + } } LazyDatabase _openConnection() { diff --git a/lib/system/datasources/moor_music_data_source.g.dart b/lib/system/datasources/moor_music_data_source.g.dart index 04de88d..112afa3 100644 --- a/lib/system/datasources/moor_music_data_source.g.dart +++ b/lib/system/datasources/moor_music_data_source.g.dart @@ -498,6 +498,7 @@ class MoorSong extends DataClass implements Insertable { final String albumArtPath; final int trackNumber; final bool blocked; + final bool present; MoorSong( {@required this.title, @required this.albumTitle, @@ -507,7 +508,8 @@ class MoorSong extends DataClass implements Insertable { this.duration, this.albumArtPath, this.trackNumber, - @required this.blocked}); + @required this.blocked, + @required this.present}); factory MoorSong.fromData(Map data, GeneratedDatabase db, {String prefix}) { final effectivePrefix = prefix ?? ''; @@ -532,6 +534,8 @@ class MoorSong extends DataClass implements Insertable { .mapFromDatabaseResponse(data['${effectivePrefix}track_number']), blocked: boolType.mapFromDatabaseResponse(data['${effectivePrefix}blocked']), + present: + boolType.mapFromDatabaseResponse(data['${effectivePrefix}present']), ); } @override @@ -564,6 +568,9 @@ class MoorSong extends DataClass implements Insertable { if (!nullToAbsent || blocked != null) { map['blocked'] = Variable(blocked); } + if (!nullToAbsent || present != null) { + map['present'] = Variable(present); + } return map; } @@ -592,6 +599,9 @@ class MoorSong extends DataClass implements Insertable { blocked: blocked == null && nullToAbsent ? const Value.absent() : Value(blocked), + present: present == null && nullToAbsent + ? const Value.absent() + : Value(present), ); } @@ -608,6 +618,7 @@ class MoorSong extends DataClass implements Insertable { albumArtPath: serializer.fromJson(json['albumArtPath']), trackNumber: serializer.fromJson(json['trackNumber']), blocked: serializer.fromJson(json['blocked']), + present: serializer.fromJson(json['present']), ); } @override @@ -623,6 +634,7 @@ class MoorSong extends DataClass implements Insertable { 'albumArtPath': serializer.toJson(albumArtPath), 'trackNumber': serializer.toJson(trackNumber), 'blocked': serializer.toJson(blocked), + 'present': serializer.toJson(present), }; } @@ -635,7 +647,8 @@ class MoorSong extends DataClass implements Insertable { int duration, String albumArtPath, int trackNumber, - bool blocked}) => + bool blocked, + bool present}) => MoorSong( title: title ?? this.title, albumTitle: albumTitle ?? this.albumTitle, @@ -646,6 +659,7 @@ class MoorSong extends DataClass implements Insertable { albumArtPath: albumArtPath ?? this.albumArtPath, trackNumber: trackNumber ?? this.trackNumber, blocked: blocked ?? this.blocked, + present: present ?? this.present, ); @override String toString() { @@ -658,7 +672,8 @@ class MoorSong extends DataClass implements Insertable { ..write('duration: $duration, ') ..write('albumArtPath: $albumArtPath, ') ..write('trackNumber: $trackNumber, ') - ..write('blocked: $blocked') + ..write('blocked: $blocked, ') + ..write('present: $present') ..write(')')) .toString(); } @@ -678,8 +693,10 @@ class MoorSong extends DataClass implements Insertable { duration.hashCode, $mrjc( albumArtPath.hashCode, - $mrjc(trackNumber.hashCode, - blocked.hashCode))))))))); + $mrjc( + trackNumber.hashCode, + $mrjc(blocked.hashCode, + present.hashCode)))))))))); @override bool operator ==(dynamic other) => identical(this, other) || @@ -692,7 +709,8 @@ class MoorSong extends DataClass implements Insertable { other.duration == this.duration && other.albumArtPath == this.albumArtPath && other.trackNumber == this.trackNumber && - other.blocked == this.blocked); + other.blocked == this.blocked && + other.present == this.present); } class SongsCompanion extends UpdateCompanion { @@ -705,6 +723,7 @@ class SongsCompanion extends UpdateCompanion { final Value albumArtPath; final Value trackNumber; final Value blocked; + final Value present; const SongsCompanion({ this.title = const Value.absent(), this.albumTitle = const Value.absent(), @@ -715,6 +734,7 @@ class SongsCompanion extends UpdateCompanion { this.albumArtPath = const Value.absent(), this.trackNumber = const Value.absent(), this.blocked = const Value.absent(), + this.present = const Value.absent(), }); SongsCompanion.insert({ @required String title, @@ -726,6 +746,7 @@ class SongsCompanion extends UpdateCompanion { this.albumArtPath = const Value.absent(), this.trackNumber = const Value.absent(), this.blocked = const Value.absent(), + this.present = const Value.absent(), }) : title = Value(title), albumTitle = Value(albumTitle), albumId = Value(albumId), @@ -741,6 +762,7 @@ class SongsCompanion extends UpdateCompanion { Expression albumArtPath, Expression trackNumber, Expression blocked, + Expression present, }) { return RawValuesInsertable({ if (title != null) 'title': title, @@ -752,6 +774,7 @@ class SongsCompanion extends UpdateCompanion { if (albumArtPath != null) 'album_art_path': albumArtPath, if (trackNumber != null) 'track_number': trackNumber, if (blocked != null) 'blocked': blocked, + if (present != null) 'present': present, }); } @@ -764,7 +787,8 @@ class SongsCompanion extends UpdateCompanion { Value duration, Value albumArtPath, Value trackNumber, - Value blocked}) { + Value blocked, + Value present}) { return SongsCompanion( title: title ?? this.title, albumTitle: albumTitle ?? this.albumTitle, @@ -775,6 +799,7 @@ class SongsCompanion extends UpdateCompanion { albumArtPath: albumArtPath ?? this.albumArtPath, trackNumber: trackNumber ?? this.trackNumber, blocked: blocked ?? this.blocked, + present: present ?? this.present, ); } @@ -808,6 +833,9 @@ class SongsCompanion extends UpdateCompanion { if (blocked.present) { map['blocked'] = Variable(blocked.value); } + if (present.present) { + map['present'] = Variable(present.value); + } return map; } @@ -822,7 +850,8 @@ class SongsCompanion extends UpdateCompanion { ..write('duration: $duration, ') ..write('albumArtPath: $albumArtPath, ') ..write('trackNumber: $trackNumber, ') - ..write('blocked: $blocked') + ..write('blocked: $blocked, ') + ..write('present: $present') ..write(')')) .toString(); } @@ -941,6 +970,15 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> { defaultValue: const Constant(false)); } + final VerificationMeta _presentMeta = const VerificationMeta('present'); + GeneratedBoolColumn _present; + @override + GeneratedBoolColumn get present => _present ??= _constructPresent(); + GeneratedBoolColumn _constructPresent() { + return GeneratedBoolColumn('present', $tableName, false, + defaultValue: const Constant(true)); + } + @override List get $columns => [ title, @@ -951,7 +989,8 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> { duration, albumArtPath, trackNumber, - blocked + blocked, + present ]; @override $SongsTable get asDslTable => this; @@ -1016,6 +1055,10 @@ class $SongsTable extends Songs with TableInfo<$SongsTable, MoorSong> { context.handle(_blockedMeta, blocked.isAcceptableOrUnknown(data['blocked'], _blockedMeta)); } + if (data.containsKey('present')) { + context.handle(_presentMeta, + present.isAcceptableOrUnknown(data['present'], _presentMeta)); + } return context; } diff --git a/lib/system/datasources/music_data_source_contract.dart b/lib/system/datasources/music_data_source_contract.dart index f9833aa..5716185 100644 --- a/lib/system/datasources/music_data_source_contract.dart +++ b/lib/system/datasources/music_data_source_contract.dart @@ -11,7 +11,8 @@ abstract class MusicDataSource { Future> getSongs(); Future> getSongsFromAlbum(AlbumModel album); Future insertSong(SongModel songModel); - + Future insertSongs(List songModels); + Future setSongBlocked(SongModel song, bool blocked); Future getSongByPath(String path); diff --git a/lib/system/datasources/queue_manager.dart b/lib/system/datasources/queue_manager.dart index 05ffca6..144d742 100644 --- a/lib/system/datasources/queue_manager.dart +++ b/lib/system/datasources/queue_manager.dart @@ -63,7 +63,7 @@ class QueueManager { List mediaItems, int startIndex) { final List indices = []; for (var i = 0; i < mediaItems.length; i++) { - if (!(mediaItems[i].extras['blocked'] as bool)) { + if (mediaItems[i].extras['blocked'] == 'false') { indices.add(i); } } diff --git a/lib/system/models/song_model.dart b/lib/system/models/song_model.dart index 88c9e6c..cee1bf3 100644 --- a/lib/system/models/song_model.dart +++ b/lib/system/models/song_model.dart @@ -126,6 +126,19 @@ class SongModel extends Song { trackNumber: Value(trackNumber), ); + SongsCompanion toMoorInsert() => SongsCompanion( + albumTitle: Value(album), + albumId: Value(albumId), + artist: Value(artist), + title: Value(title), + path: Value(path), + duration: Value(duration), + albumArtPath: Value(albumArtPath), + trackNumber: Value(trackNumber), + // blocked: Value(blocked), + present: const Value(true), + ); + MediaItem toMediaItem() => MediaItem( id: path, title: title, diff --git a/lib/system/repositories/music_data_repository_impl.dart b/lib/system/repositories/music_data_repository_impl.dart index f6ada0c..4b83448 100644 --- a/lib/system/repositories/music_data_repository_impl.dart +++ b/lib/system/repositories/music_data_repository_impl.dart @@ -1,4 +1,5 @@ import 'package:dartz/dartz.dart'; +import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; import '../../core/error/failures.dart'; @@ -21,6 +22,8 @@ class MusicDataRepositoryImpl implements MusicDataRepository { final LocalMusicFetcher localMusicFetcher; final MusicDataSource musicDataSource; + static final _log = Logger('MusicDataRepository'); + @override Future>> getArtists() async { return musicDataSource.getArtists().then((List artists) => @@ -47,6 +50,8 @@ class MusicDataRepositoryImpl implements MusicDataRepository { @override Future updateDatabase() async { + _log.info('updataDatabase called'); + await musicDataSource.deleteAllArtists(); final List artists = await localMusicFetcher.getArtists(); @@ -63,21 +68,19 @@ class MusicDataRepositoryImpl implements MusicDataRepository { albumIdMap[album.id] = newAlbumId; } - await musicDataSource.deleteAllSongs(); final List songs = await localMusicFetcher.getSongs(); + final List songsToInsert = []; for (final SongModel song in songs) { - final SongModel songToInsert = - song.copyWith(albumId: albumIdMap[song.albumId]); - - // TODO: fails if albumId is null - await musicDataSource.insertSong(songToInsert); + songsToInsert.add(song.copyWith(albumId: albumIdMap[song.albumId])); } + await musicDataSource.insertSongs(songsToInsert); + + _log.info('updataDatabase finished'); } @override - Future setSongBlocked(Song song, bool blocked) { - // TODO: implement setSongBlocked - throw UnimplementedError(); + Future setSongBlocked(Song song, bool blocked) async { + await musicDataSource.setSongBlocked(song as SongModel, blocked); } }