remove skip count from songs

This commit is contained in:
Moritz Weber 2023-01-28 20:44:59 +01:00
parent eb56b9d3ef
commit 3179797350
15 changed files with 19 additions and 352 deletions

View file

@ -37,9 +37,7 @@ class AudioPlayerActor {
_countSongPlayback = true;
} else if (position > song.duration * 0.95 && _countSongPlayback) {
_countSongPlayback = false;
final updatedSong = await _musicDataRepository.incrementPlayCount(song);
if (updatedSong.skipCount > 0)
_musicDataRepository.resetSkipCount(updatedSong);
await _musicDataRepository.incrementPlayCount(song);
}
}
}

View file

@ -63,8 +63,6 @@ class Filter extends Equatable {
this.maxPlayCount,
required this.minLikeCount,
required this.maxLikeCount,
this.minSkipCount,
this.maxSkipCount,
this.minYear,
this.maxYear,
required this.blockLevel,
@ -80,9 +78,6 @@ class Filter extends Equatable {
final int minLikeCount;
final int maxLikeCount;
final int? minSkipCount;
final int? maxSkipCount;
final int? minYear;
final int? maxYear;
@ -121,7 +116,6 @@ enum OrderCriterion {
artistName,
likeCount,
playCount,
skipCount,
songTitle,
timeAdded,
year,
@ -136,8 +130,6 @@ extension OrderCriterionExtension on String {
return OrderCriterion.likeCount;
case 'OrderCriterion.playCount':
return OrderCriterion.playCount;
case 'OrderCriterion.skipCount':
return OrderCriterion.skipCount;
case 'OrderCriterion.songTitle':
return OrderCriterion.songTitle;
case 'OrderCriterion.timeAdded':

View file

@ -10,7 +10,6 @@ class Song extends Equatable {
required this.path,
required this.title,
required this.likeCount,
required this.skipCount,
required this.playCount,
required this.discNumber,
required this.next,
@ -33,7 +32,6 @@ class Song extends Equatable {
final String title;
final int likeCount;
final int skipCount;
final int playCount;
final int discNumber;
@ -59,7 +57,6 @@ class Song extends Equatable {
previous,
likeCount,
playCount,
skipCount,
timeAdded,
];
}

View file

@ -61,9 +61,6 @@ abstract class MusicDataRepository extends MusicDataInfoRepository {
Future<void> setSongsBlockLevel(List<Song> songs, int blockLevel);
Future<Song> incrementSkipCount(Song song);
Future<Song> resetSkipCount(Song song);
Future<void> setLikeCount(List<Song> songs, int count);
Future<void> incrementLikeCount(Song song);

View file

@ -1,16 +1,11 @@
import '../repositories/audio_player_repository.dart';
import '../repositories/music_data_repository.dart';
class SeekToNext {
SeekToNext(this._audioPlayerRepository, this._musicDataRepository);
SeekToNext(this._audioPlayerRepository);
final AudioPlayerRepository _audioPlayerRepository;
final MusicDataRepository _musicDataRepository;
Future<bool> call() async {
final song = await _audioPlayerRepository.currentSongStream.first;
final hasNext = await _audioPlayerRepository.seekToNext();
if (hasNext && song != null) _musicDataRepository.incrementSkipCount(song);
return hasNext;
return await _audioPlayerRepository.seekToNext();
}
}

View file

@ -230,7 +230,6 @@ Future<void> setupGetIt() async {
getIt.registerLazySingleton<SeekToNext>(
() => SeekToNext(
getIt(),
getIt(),
),
);
getIt.registerLazySingleton<SetSongsBlocked>(

View file

@ -266,48 +266,6 @@ class _SmartListFormPageState extends State<SmartListFormPage> {
),
),
),
Card(
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: CARD_PADDING,
),
child: Column(
children: [
Observer(
builder: (_) {
return SwitchTextListTile(
title: 'Minimum skip count',
switchValue: store.minSkipCountEnabled,
onSwitchChanged: (bool value) {
store.minSkipCountEnabled = value;
},
textValue: store.minSkipCount,
onTextChanged: (String value) {
store.minSkipCount = value;
},
);
},
),
const SizedBox(height: CARD_SPACING),
Observer(
builder: (_) {
return SwitchTextListTile(
title: 'Maximum skip count',
switchValue: store.maxSkipCountEnabled,
onSwitchChanged: (bool value) {
store.maxSkipCountEnabled = value;
},
textValue: store.maxSkipCount,
onTextChanged: (String value) {
store.maxSkipCount = value;
},
);
},
),
],
),
),
),
Card(
child: Padding(
padding: const EdgeInsets.symmetric(

View file

@ -54,16 +54,6 @@ abstract class _SmartListStore with Store {
@observable
late String maxPlayCount = _intToString(_smartList?.filter.maxPlayCount);
@observable
late bool minSkipCountEnabled = _smartList?.filter.minSkipCount != null;
@observable
late String minSkipCount = _intToString(_smartList?.filter.minSkipCount);
@observable
late bool maxSkipCountEnabled = _smartList?.filter.maxSkipCount != null;
@observable
late String maxSkipCount = _intToString(_smartList?.filter.maxSkipCount);
@observable
late bool minYearEnabled = _smartList?.filter.minYear != null;
@observable
@ -149,8 +139,6 @@ abstract class _SmartListStore with Store {
reaction((_) => name, _validateName),
reaction((_) => minPlayCount, (String n) => _validateMinPlayCount(minPlayCountEnabled, n)),
reaction((_) => maxPlayCount, (String n) => _validateMaxPlayCount(maxPlayCountEnabled, n)),
reaction((_) => minSkipCount, (String n) => _validateMinSkipCount(minSkipCountEnabled, n)),
reaction((_) => maxSkipCount, (String n) => _validateMaxSkipCount(maxSkipCountEnabled, n)),
reaction((_) => minYear, (String n) => _validateMinYear(minYearEnabled, n)),
reaction((_) => maxYear, (String n) => _validateMaxYear(maxYearEnabled, n)),
reaction((_) => limit, (String n) => _validateLimit(limitEnabled, n)),
@ -168,8 +156,6 @@ abstract class _SmartListStore with Store {
_validateName(name);
_validateMinPlayCount(minPlayCountEnabled, minPlayCount);
_validateMaxPlayCount(maxPlayCountEnabled, maxPlayCount);
_validateMinSkipCount(minSkipCountEnabled, minSkipCount);
_validateMaxSkipCount(maxSkipCountEnabled, maxSkipCount);
_validateMinYear(minYearEnabled, minYear);
_validateMaxYear(maxYearEnabled, maxYear);
_validateLimit(limitEnabled, limit);
@ -187,14 +173,6 @@ abstract class _SmartListStore with Store {
error.maxPlayCount = validateNumber(enabled, number);
}
void _validateMinSkipCount(bool enabled, String number) {
error.minSkipCount = validateNumber(enabled, number);
}
void _validateMaxSkipCount(bool enabled, String number) {
error.maxSkipCount = validateNumber(enabled, number);
}
void _validateMinYear(bool enabled, String number) {
error.minYear = validateNumber(enabled, number);
}
@ -218,8 +196,6 @@ abstract class _SmartListStore with Store {
excludeArtists: excludeArtists,
minPlayCount: minPlayCountEnabled ? int.tryParse(minPlayCount) : null,
maxPlayCount: maxPlayCountEnabled ? int.tryParse(maxPlayCount) : null,
minSkipCount: minSkipCountEnabled ? int.tryParse(minSkipCount) : null,
maxSkipCount: maxSkipCountEnabled ? int.tryParse(maxSkipCount) : null,
minYear: minYearEnabled ? int.tryParse(minYear) : null,
maxYear: maxYearEnabled ? int.tryParse(maxYear) : null,
minLikeCount: minLikeCount,
@ -250,8 +226,6 @@ abstract class _SmartListStore with Store {
excludeArtists: excludeArtists,
minPlayCount: minPlayCountEnabled ? int.tryParse(minPlayCount) : null,
maxPlayCount: maxPlayCountEnabled ? int.tryParse(maxPlayCount) : null,
minSkipCount: minSkipCountEnabled ? int.tryParse(minSkipCount) : null,
maxSkipCount: maxSkipCountEnabled ? int.tryParse(maxSkipCount) : null,
minYear: minYearEnabled ? int.tryParse(minYear) : null,
maxYear: maxYearEnabled ? int.tryParse(maxYear) : null,
minLikeCount: minLikeCount,
@ -280,12 +254,6 @@ abstract class _FormErrorState with Store {
@observable
String? maxPlayCount;
@observable
String? minSkipCount;
@observable
String? maxSkipCount;
@observable
String? minYear;
@ -324,7 +292,6 @@ List<OrderEntry> _createOrderState(OrderBy? orderBy) {
OrderCriterion.songTitle: 'Song title',
OrderCriterion.likeCount: 'Like count',
OrderCriterion.playCount: 'Play count',
OrderCriterion.skipCount: 'Skip count',
OrderCriterion.artistName: 'Artist name',
OrderCriterion.year: 'Year',
OrderCriterion.timeAdded: 'Time added',
@ -337,8 +304,6 @@ List<OrderEntry> _createOrderState(OrderBy? orderBy) {
descriptions[OrderCriterion.likeCount]!),
OrderEntry(false, OrderCriterion.playCount, OrderDirection.ascending,
descriptions[OrderCriterion.playCount]!),
OrderEntry(false, OrderCriterion.skipCount, OrderDirection.ascending,
descriptions[OrderCriterion.skipCount]!),
OrderEntry(false, OrderCriterion.artistName, OrderDirection.ascending,
descriptions[OrderCriterion.artistName]!),
OrderEntry(

View file

@ -128,70 +128,6 @@ mixin _$SmartListFormStore on _SmartListStore, Store {
});
}
late final _$minSkipCountEnabledAtom =
Atom(name: '_SmartListStore.minSkipCountEnabled', context: context);
@override
bool get minSkipCountEnabled {
_$minSkipCountEnabledAtom.reportRead();
return super.minSkipCountEnabled;
}
@override
set minSkipCountEnabled(bool value) {
_$minSkipCountEnabledAtom.reportWrite(value, super.minSkipCountEnabled, () {
super.minSkipCountEnabled = value;
});
}
late final _$minSkipCountAtom =
Atom(name: '_SmartListStore.minSkipCount', context: context);
@override
String get minSkipCount {
_$minSkipCountAtom.reportRead();
return super.minSkipCount;
}
@override
set minSkipCount(String value) {
_$minSkipCountAtom.reportWrite(value, super.minSkipCount, () {
super.minSkipCount = value;
});
}
late final _$maxSkipCountEnabledAtom =
Atom(name: '_SmartListStore.maxSkipCountEnabled', context: context);
@override
bool get maxSkipCountEnabled {
_$maxSkipCountEnabledAtom.reportRead();
return super.maxSkipCountEnabled;
}
@override
set maxSkipCountEnabled(bool value) {
_$maxSkipCountEnabledAtom.reportWrite(value, super.maxSkipCountEnabled, () {
super.maxSkipCountEnabled = value;
});
}
late final _$maxSkipCountAtom =
Atom(name: '_SmartListStore.maxSkipCount', context: context);
@override
String get maxSkipCount {
_$maxSkipCountAtom.reportRead();
return super.maxSkipCount;
}
@override
set maxSkipCount(String value) {
_$maxSkipCountAtom.reportWrite(value, super.maxSkipCount, () {
super.maxSkipCount = value;
});
}
late final _$minYearEnabledAtom =
Atom(name: '_SmartListStore.minYearEnabled', context: context);
@ -447,10 +383,6 @@ minPlayCountEnabled: ${minPlayCountEnabled},
minPlayCount: ${minPlayCount},
maxPlayCountEnabled: ${maxPlayCountEnabled},
maxPlayCount: ${maxPlayCount},
minSkipCountEnabled: ${minSkipCountEnabled},
minSkipCount: ${minSkipCount},
maxSkipCountEnabled: ${maxSkipCountEnabled},
maxSkipCount: ${maxSkipCount},
minYearEnabled: ${minYearEnabled},
minYear: ${minYear},
maxYearEnabled: ${maxYearEnabled},
@ -523,38 +455,6 @@ mixin _$FormErrorState on _FormErrorState, Store {
});
}
late final _$minSkipCountAtom =
Atom(name: '_FormErrorState.minSkipCount', context: context);
@override
String? get minSkipCount {
_$minSkipCountAtom.reportRead();
return super.minSkipCount;
}
@override
set minSkipCount(String? value) {
_$minSkipCountAtom.reportWrite(value, super.minSkipCount, () {
super.minSkipCount = value;
});
}
late final _$maxSkipCountAtom =
Atom(name: '_FormErrorState.maxSkipCount', context: context);
@override
String? get maxSkipCount {
_$maxSkipCountAtom.reportRead();
return super.maxSkipCount;
}
@override
set maxSkipCount(String? value) {
_$maxSkipCountAtom.reportWrite(value, super.maxSkipCount, () {
super.maxSkipCount = value;
});
}
late final _$minYearAtom =
Atom(name: '_FormErrorState.minYear', context: context);
@ -609,8 +509,6 @@ mixin _$FormErrorState on _FormErrorState, Store {
name: ${name},
minPlayCount: ${minPlayCount},
maxPlayCount: ${maxPlayCount},
minSkipCount: ${minSkipCount},
maxSkipCount: ${maxSkipCount},
minYear: ${minYear},
maxYear: ${maxYear},
limit: ${limit},

View file

@ -153,7 +153,7 @@ class _SongBottomSheetState extends State<SongBottomSheet> {
style: TEXT_SMALL_SUBTITLE,
),
Text(
'played: ${song.playCount} • skipped: ${song.skipCount}',
'Played ${song.playCount} times',
style: TEXT_SMALL_SUBTITLE,
),
],

View file

@ -1,99 +0,0 @@
import 'package:flutter/material.dart';
import '../../domain/entities/song.dart';
import '../utils.dart' as utils;
const _LEADING_WIDTH = 108.0;
class SongInfo extends StatelessWidget {
const SongInfo(
this.song, {
Key? key,
}) : super(key: key);
final Song song;
@override
Widget build(BuildContext context) {
final cover = Image(
image: utils.getAlbumImage(song.albumArtPath),
fit: BoxFit.cover,
);
return Column(
children: [
SizedBox(
height: 96,
width: 96,
child: cover,
),
Container(height: 8),
InfoRow(leading: 'Title:', trailing: song.title, leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Album:', trailing: song.album, leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Artist:', trailing: song.artist, leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Year:', trailing: song.year?.toString() ?? 'null', leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Path:', trailing: song.path, leadingWidth: _LEADING_WIDTH),
InfoRow(
leading: 'Album art path:',
trailing: song.albumArtPath ?? 'null',
leadingWidth: _LEADING_WIDTH,
),
InfoRow(
leading: 'Duration:',
trailing: utils.msToTimeString(song.duration),
leadingWidth: _LEADING_WIDTH,
),
InfoRow(
leading: 'Track number:',
trailing: '${song.trackNumber}',
leadingWidth: _LEADING_WIDTH),
InfoRow(
leading: 'Disc number:', trailing: '${song.discNumber}', leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Time added:', trailing: '${song.timeAdded}', leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Block level:', trailing: '${song.blockLevel}', leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Likes:', trailing: '${song.likeCount}', leadingWidth: _LEADING_WIDTH),
InfoRow(
leading: 'Times played:', trailing: '${song.playCount}', leadingWidth: _LEADING_WIDTH),
InfoRow(
leading: 'Times skipped:', trailing: '${song.skipCount}', leadingWidth: _LEADING_WIDTH),
InfoRow(
leading: 'Previous song:', trailing: '${song.previous}', leadingWidth: _LEADING_WIDTH),
InfoRow(leading: 'Next song:', trailing: '${song.next}', leadingWidth: _LEADING_WIDTH),
],
);
}
}
class InfoRow extends StatelessWidget {
const InfoRow({
Key? key,
required this.leadingWidth,
required this.leading,
required this.trailing,
}) : super(key: key);
final double leadingWidth;
final String leading;
final String trailing;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: leadingWidth,
child: Text(leading),
),
Expanded(
child: Text(
trailing,
),
),
],
),
);
}
}

View file

@ -185,8 +185,6 @@ class PlaylistDao extends DatabaseAccessor<MoorDatabase>
excludeArtists: Value(filter.excludeArtists),
minPlayCount: Value(filter.minPlayCount),
maxPlayCount: Value(filter.maxPlayCount),
minSkipCount: Value(filter.minSkipCount),
maxSkipCount: Value(filter.maxSkipCount),
minLikeCount: Value(filter.minLikeCount),
maxLikeCount: Value(filter.maxLikeCount),
minYear: Value(filter.minYear),
@ -232,6 +230,7 @@ class PlaylistDao extends DatabaseAccessor<MoorDatabase>
slArtistStream,
(a, b) {
return a.map((sl) {
print(sl);
final moorArtists =
(b.where((element) => element.readTable(smartListArtists).smartListId == sl.id))
.map((e) => e.readTable(artists))
@ -298,11 +297,6 @@ class PlaylistDao extends DatabaseAccessor<MoorDatabase>
if (filter.maxPlayCount != null)
query = query..where((tbl) => tbl.playCount.isSmallerOrEqualValue(filter.maxPlayCount));
if (filter.minSkipCount != null)
query = query..where((tbl) => tbl.skipCount.isBiggerOrEqualValue(filter.minSkipCount));
if (filter.maxSkipCount != null)
query = query..where((tbl) => tbl.skipCount.isSmallerOrEqualValue(filter.maxSkipCount));
if (filter.minYear != null)
query = query..where((tbl) => tbl.year.isBiggerOrEqualValue(filter.minYear));
if (filter.maxYear != null)
@ -455,14 +449,6 @@ List<OrderingTerm Function($SongsTable)> _generateOrderingTerms(sl.OrderBy order
),
);
break;
case sl.OrderCriterion.skipCount:
orderingTerms.add(
($SongsTable t) => OrderingTerm(
expression: t.skipCount,
mode: mode,
),
);
break;
case sl.OrderCriterion.songTitle:
orderingTerms.add(
($SongsTable t) => OrderingTerm(

View file

@ -54,17 +54,23 @@ class SmartListModel extends SmartList {
maxLikeCount: moorSmartList.maxLikeCount,
minPlayCount: moorSmartList.minPlayCount,
maxPlayCount: moorSmartList.maxPlayCount,
minSkipCount: moorSmartList.minSkipCount,
maxSkipCount: moorSmartList.maxSkipCount,
minYear: moorSmartList.minYear,
maxYear: moorSmartList.maxYear,
blockLevel: moorSmartList.blockLevel,
limit: moorSmartList.limit,
);
final criteria = _parseOrderCriteria(moorSmartList.orderCriteria);
final directions = _parseOrderDirections(moorSmartList.orderDirections);
final filteredDirections = <OrderDirection>[];
criteria.asMap().forEach((key, value) {
if (value != null) filteredDirections.add(directions[key]);
});
final orderBy = OrderBy(
orderCriteria: _parseOrderCriteria(moorSmartList.orderCriteria),
orderDirections: _parseOrderDirections(moorSmartList.orderDirections),
orderCriteria: criteria.whereType<OrderCriterion>().toList(),
orderDirections: filteredDirections,
);
return SmartListModel(
@ -90,8 +96,8 @@ class SmartListModel extends SmartList {
maxPlayCount: m.Value(filter.maxPlayCount),
minLikeCount: m.Value(filter.minLikeCount),
maxLikeCount: m.Value(filter.maxLikeCount),
minSkipCount: m.Value(filter.minSkipCount),
maxSkipCount: m.Value(filter.maxSkipCount),
minSkipCount: const m.Value(null),
maxSkipCount: const m.Value(null),
minYear: m.Value(filter.minYear),
maxYear: m.Value(filter.maxYear),
blockLevel: m.Value(filter.blockLevel),
@ -118,10 +124,10 @@ class SmartListModel extends SmartList {
}
}
List<OrderCriterion> _parseOrderCriteria(String orderCriteria) {
List<OrderCriterion?> _parseOrderCriteria(String orderCriteria) {
if (orderCriteria == '') return [];
final ocList = orderCriteria.split(',');
return ocList.map((e) => e.toOrderCriterion()!).toList();
return ocList.map((e) => e.toOrderCriterion()).toList();
}
List<OrderDirection> _parseOrderDirections(String orderDirections) {

View file

@ -22,7 +22,6 @@ class SongModel extends Song {
required bool previous,
required int trackNumber,
required int likeCount,
required int skipCount,
required int playCount,
required DateTime timeAdded,
required this.lastModified,
@ -41,7 +40,6 @@ class SongModel extends Song {
previous: previous,
trackNumber: trackNumber,
likeCount: likeCount,
skipCount: skipCount,
playCount: playCount,
timeAdded: timeAdded,
year: year,
@ -61,7 +59,6 @@ class SongModel extends Song {
previous: moorSong.previous,
trackNumber: moorSong.trackNumber,
likeCount: moorSong.likeCount,
skipCount: moorSong.skipCount,
playCount: moorSong.playCount,
timeAdded: moorSong.timeAdded,
lastModified: moorSong.lastModified,
@ -94,7 +91,6 @@ class SongModel extends Song {
previous: false,
likeCount: 0,
playCount: 0,
skipCount: 0,
year: parseYear(data['year'] as String?),
timeAdded: DateTime.fromMillisecondsSinceEpoch(0),
lastModified: lastModified,
@ -122,7 +118,6 @@ class SongModel extends Song {
bool? previous,
int? trackNumber,
int? likeCount,
int? skipCount,
int? playCount,
DateTime? timeAdded,
DateTime? lastModified,
@ -142,7 +137,6 @@ class SongModel extends Song {
previous: previous ?? this.previous,
trackNumber: trackNumber ?? this.trackNumber,
likeCount: likeCount ?? this.likeCount,
skipCount: skipCount ?? this.skipCount,
playCount: playCount ?? this.playCount,
timeAdded: timeAdded ?? this.timeAdded,
lastModified: lastModified ?? this.lastModified,
@ -164,7 +158,6 @@ class SongModel extends Song {
previous: Value(previous),
trackNumber: Value(trackNumber),
likeCount: Value(likeCount),
skipCount: Value(skipCount),
playCount: Value(playCount),
timeAdded: Value(timeAdded),
lastModified: Value(lastModified),
@ -202,7 +195,6 @@ class SongModel extends Song {
'previous': previous,
'likeCount': likeCount,
'playCount': playCount,
'skipCount': skipCount,
'timeAdded': timeAdded.millisecondsSinceEpoch,
});

View file

@ -162,14 +162,6 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
return newSong;
}
@override
Future<Song> incrementSkipCount(Song song) async {
final newSong = (song as SongModel).copyWith(skipCount: song.skipCount + 1);
_songUpdateSubject.add({song.path: newSong});
await _musicDataSource.updateSongs([newSong]);
return newSong;
}
@override
Future<void> setLikeCount(List<Song> songs, int count) async {
if (0 <= count && count <= MAX_LIKE_COUNT) {
@ -188,14 +180,6 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
await setLikeCount([song], count);
}
@override
Future<Song> resetSkipCount(Song song) async {
final newSong = (song as SongModel).copyWith(skipCount: 0);
_songUpdateSubject.add({song.path: newSong});
await _musicDataSource.updateSongs([newSong]);
return newSong;
}
@override
Future<Song> toggleNextSongLink(Song song) async {
SongModel newSong;
@ -258,7 +242,6 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
(a, b) {
int r = -a.likeCount.compareTo(b.likeCount);
if (r == 0) r = -a.playCount.compareTo(b.playCount);
if (r == 0) r = a.skipCount.compareTo(b.skipCount);
if (r == 0) r = a.title.compareTo(b.title);
return r;
},