play count, song blocking

This commit is contained in:
Moritz Weber 2021-05-02 12:39:31 +02:00
parent 0bece0df29
commit caae3bf8dd
8 changed files with 167 additions and 6 deletions

View file

@ -2,26 +2,60 @@ import '../entities/song.dart';
import '../repositories/audio_player_repository.dart';
import '../repositories/music_data_repository.dart';
import '../usecases/handle_playback_state.dart';
import '../usecases/increment_play_count.dart';
import '../usecases/set_current_song.dart';
class AudioPlayerActor {
AudioPlayerActor(this._audioPlayerRepository, this._musicDataInfoRepository, this._handlePlaybackEvent, this._setCurrentSong) {
AudioPlayerActor(
this._audioPlayerRepository,
this._musicDataInfoRepository,
this._handlePlaybackEvent,
this._incrementPlayCount,
this._setCurrentSong,
) {
_audioPlayerRepository.currentSongStream.listen(_handleCurrentSong);
_audioPlayerRepository.playbackEventStream.listen(_handlePlaybackEvent);
_audioPlayerRepository.positionStream
.listen((duration) => _handlePosition(duration, _currentSong));
_musicDataInfoRepository.songUpdateStream.listen(_handleSongUpdate);
}
// TODO: is this against a previous design choice? only direct "read" access to repos?
// Should this actor only listen to AudioPlayer events? --> move song update to new actor?
final AudioPlayerRepository _audioPlayerRepository;
final MusicDataInfoRepository _musicDataInfoRepository;
final HandlePlaybackEvent _handlePlaybackEvent;
final IncrementPlayCount _incrementPlayCount;
final SetCurrentSong _setCurrentSong;
void _handleCurrentSong(Song song) => _setCurrentSong(song);
Song _currentSong;
bool _countSongPlayback = false;
Future<void> _handleCurrentSong(Song song) async {
_currentSong = song;
return _setCurrentSong(song);
}
void _handlePosition(Duration position, Song song) {
if (song == null || position == null) return;
print('HANDLE POSITION');
final int pos = position.inMilliseconds;
if (pos < song.duration * 0.05) {
print('COUNT -> TRUE');
_countSongPlayback = true;
} else if (pos > song.duration * 0.95 && _countSongPlayback) {
print('INCREMENT PLAY COUNT: ${song.title}');
_countSongPlayback = false;
_incrementPlayCount(song);
}
}
void _handleSongUpdate(Map<String, Song> songs) {
_audioPlayerRepository.updateSongs(songs);
}
}
}

View file

@ -18,6 +18,16 @@ abstract class MusicDataInfoRepository {
abstract class MusicDataRepository extends MusicDataInfoRepository {
Future<void> updateDatabase();
Future<void> setSongBlocked(Song song, bool blocked);
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);
}

View file

@ -0,0 +1,12 @@
import '../entities/song.dart';
import '../repositories/music_data_repository.dart';
class IncrementPlayCount {
IncrementPlayCount(this._musicDataRepository);
final MusicDataRepository _musicDataRepository;
Future<void> call(Song song) async {
await _musicDataRepository.incrementPlayCount(song);
}
}

View file

@ -0,0 +1,12 @@
import '../entities/song.dart';
import '../repositories/music_data_repository.dart';
class SetSongBlocked {
SetSongBlocked(this._musicDataRepository);
final MusicDataRepository _musicDataRepository;
Future<void> call(Song song, bool blocked) async {
await _musicDataRepository.setSongBlocked(song, blocked);
}
}

View file

@ -14,6 +14,7 @@ import 'domain/repositories/platform_integration_repository.dart';
import 'domain/repositories/settings_repository.dart';
import 'domain/usecases/add_to_queue.dart';
import 'domain/usecases/handle_playback_state.dart';
import 'domain/usecases/increment_play_count.dart';
import 'domain/usecases/inrement_like_count.dart';
import 'domain/usecases/move_queue_item.dart';
import 'domain/usecases/pause.dart';
@ -29,6 +30,7 @@ import 'domain/usecases/seek_to_previous.dart';
import 'domain/usecases/set_current_song.dart';
import 'domain/usecases/set_loop_mode.dart';
import 'domain/usecases/set_shuffle_mode.dart';
import 'domain/usecases/set_song_blocked.dart';
import 'domain/usecases/shuffle_all.dart';
import 'domain/usecases/update_database.dart';
import 'presentation/state/audio_store.dart';
@ -64,6 +66,7 @@ Future<void> setupGetIt() async {
settingsRepository: getIt(),
musicDataModifierRepository: getIt(),
incrementLikeCount: getIt(),
setSongBlocked: getIt(),
updateDatabase: getIt(),
);
return musicDataStore;
@ -118,6 +121,11 @@ Future<void> setupGetIt() async {
getIt(),
),
);
getIt.registerLazySingleton<IncrementPlayCount>(
() => IncrementPlayCount(
getIt(),
),
);
getIt.registerLazySingleton<MoveQueueItem>(
() => MoveQueueItem(
getIt(),
@ -207,6 +215,11 @@ Future<void> setupGetIt() async {
getIt(),
),
);
getIt.registerLazySingleton<SetSongBlocked>(
() => SetSongBlocked(
getIt(),
),
);
getIt.registerLazySingleton<ShuffleAll>(
() => ShuffleAll(
getIt(),
@ -325,6 +338,7 @@ Future<void> setupGetIt() async {
getIt(),
getIt(),
getIt(),
getIt(),
),
);
}

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mucke/presentation/widgets/song_info.dart';
import 'package:provider/provider.dart';
import '../../domain/entities/album.dart';
@ -168,6 +169,35 @@ class AlbumDetailsPage extends StatelessWidget {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Show song info'),
leading: const Icon(Icons.info),
onTap: () {
Navigator.pop(context);
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
backgroundColor: DARK3,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(HORIZONTAL_PADDING),
child: SongInfo(song),
),
SimpleDialogOption(
onPressed: () {
Navigator.pop(context);
},
child: const Text(
'Close',
textAlign: TextAlign.right,
),
),
],
);
});
},
),
],
),
);

View file

@ -8,6 +8,7 @@ import '../../domain/repositories/music_data_modifier_repository.dart';
import '../../domain/repositories/music_data_repository.dart';
import '../../domain/repositories/settings_repository.dart';
import '../../domain/usecases/inrement_like_count.dart';
import '../../domain/usecases/set_song_blocked.dart';
import '../../domain/usecases/update_database.dart';
part 'music_data_store.g.dart';
@ -19,12 +20,14 @@ class MusicDataStore extends _MusicDataStore with _$MusicDataStore {
@required SettingsRepository settingsRepository,
@required UpdateDatabase updateDatabase,
@required IncrementLikeCount incrementLikeCount,
@required SetSongBlocked setSongBlocked,
}) : super(
musicDataInfoRepository,
settingsRepository,
musicDataModifierRepository,
updateDatabase,
incrementLikeCount,
setSongBlocked,
);
}
@ -35,6 +38,7 @@ abstract class _MusicDataStore with Store {
this._musicDataModifierRepository,
this._updateDatabase,
this._incrementLikeCount,
this._setSongBlocked,
) {
songStream = _musicDataInfoRepository.songStream.asObservable(initialValue: []);
albumStream = _musicDataInfoRepository.albumStream.asObservable(initialValue: []);
@ -42,6 +46,7 @@ abstract class _MusicDataStore with Store {
}
final IncrementLikeCount _incrementLikeCount;
final SetSongBlocked _setSongBlocked;
final UpdateDatabase _updateDatabase;
final MusicDataInfoRepository _musicDataInfoRepository;
@ -93,9 +98,7 @@ abstract class _MusicDataStore with Store {
_musicDataInfoRepository.getArtistAlbumStream(artist).asObservable(initialValue: []);
}
Future<void> setSongBlocked(Song song, bool blocked) async {
await _musicDataModifierRepository.setSongBlocked(song, blocked);
}
Future<void> setSongBlocked(Song song, bool blocked) => _setSongBlocked(song, blocked);
Future<void> toggleNextSongLink(Song song) async {
await _musicDataModifierRepository.toggleNextSongLink(song);

View file

@ -91,4 +91,50 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
Future<void> _updateSongs(List<SongModel> songs) async {
await _musicDataSource.insertSongs(songs);
}
@override
Future<void> setSongBlocked(Song song, bool blocked) async {
if (song.blocked != blocked) {
final newSong = (song as SongModel).copyWith(blocked: blocked);
_songUpdateSubject.add({song.path: newSong});
_musicDataSource.setSongBlocked(song as SongModel, blocked);
}
}
@override
Future<void> decrementLikeCount(Song song) {
// TODO: implement decrementLikeCount
throw UnimplementedError();
}
@override
Future<void> incrementPlayCount(Song song) async {
final newSong = (song as SongModel).copyWith(playCount: song.playCount + 1);
_songUpdateSubject.add({song.path: newSong});
_musicDataSource.incrementPlayCount(song as SongModel);
}
@override
Future<void> incrementSkipCount(Song song) {
// TODO: implement incrementSkipCount
throw UnimplementedError();
}
@override
Future<void> resetLikeCount(Song song) {
// TODO: implement resetLikeCount
throw UnimplementedError();
}
@override
Future<void> resetPlayCount(Song song) {
// TODO: implement resetPlayCount
throw UnimplementedError();
}
@override
Future<void> resetSkipCount(Song song) {
// TODO: implement resetSkipCount
throw UnimplementedError();
}
}