implemented block on skip
This commit is contained in:
parent
2328454610
commit
935634f2a2
26 changed files with 949 additions and 45 deletions
|
@ -30,6 +30,8 @@ class Filter extends Equatable {
|
|||
this.maxPlayCount,
|
||||
required this.minLikeCount,
|
||||
required this.maxLikeCount,
|
||||
this.minSkipCount,
|
||||
this.maxSkipCount,
|
||||
this.minYear,
|
||||
this.maxYear,
|
||||
required this.excludeBlocked,
|
||||
|
@ -45,6 +47,9 @@ class Filter extends Equatable {
|
|||
final int minLikeCount;
|
||||
final int maxLikeCount;
|
||||
|
||||
final int? minSkipCount;
|
||||
final int? maxSkipCount;
|
||||
|
||||
final int? minYear;
|
||||
final int? maxYear;
|
||||
|
||||
|
@ -83,6 +88,7 @@ enum OrderCriterion {
|
|||
artistName,
|
||||
likeCount,
|
||||
playCount,
|
||||
skipCount,
|
||||
songTitle,
|
||||
timeAdded,
|
||||
year,
|
||||
|
@ -97,6 +103,8 @@ 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':
|
||||
|
|
|
@ -2,4 +2,9 @@ abstract class SettingsRepository {
|
|||
Stream<List<String>> get libraryFoldersStream;
|
||||
Future<void> addLibraryFolder(String? path);
|
||||
Future<void> removeLibraryFolder(String? path);
|
||||
|
||||
Future<void> setBlockSkippedSongs(bool enabled);
|
||||
Stream<bool> get isBlockSkippedSongsEnabled;
|
||||
Future<void> setBlockSkippedSongsThreshold(int threshold);
|
||||
Stream<int> get blockSkippedSongsThreshold;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import 'presentation/state/audio_store.dart';
|
|||
import 'presentation/state/music_data_store.dart';
|
||||
import 'presentation/state/navigation_store.dart';
|
||||
import 'presentation/state/search_page_store.dart';
|
||||
import 'presentation/state/settings_page_store.dart';
|
||||
import 'presentation/state/settings_store.dart';
|
||||
import 'presentation/state/smart_list_form_store.dart';
|
||||
import 'presentation/state/smart_list_page_store.dart';
|
||||
|
@ -79,16 +80,21 @@ Future<void> setupGetIt() async {
|
|||
musicDataInfoRepository: getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<SettingsStore>(
|
||||
() => SettingsStore(
|
||||
settingsRepository: getIt(),
|
||||
musicDataRepository: getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerFactoryParam<ArtistPageStore, Artist, void>(
|
||||
(Artist? artist, _) => ArtistPageStore(artist: artist!, musicDataInfoRepository: getIt()),
|
||||
);
|
||||
getIt.registerFactoryParam<AlbumPageStore, Album, void>(
|
||||
(Album? album, _) => AlbumPageStore(album: album!, musicDataInfoRepository: getIt()),
|
||||
);
|
||||
getIt.registerFactory<SettingsStore>(
|
||||
() => SettingsStore(
|
||||
getIt.registerFactory<SettingsPageStore>(
|
||||
() => SettingsPageStore(
|
||||
settingsRepository: getIt(),
|
||||
musicDataRepository: getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerFactoryParam<SmartListFormStore, SmartList, void>(
|
||||
|
|
|
@ -12,8 +12,8 @@ import '../state/music_data_store.dart';
|
|||
import '../state/settings_store.dart';
|
||||
import '../theming.dart';
|
||||
import 'playlist_page.dart';
|
||||
import 'smart_list_form_page.dart';
|
||||
import 'smart_list_page.dart';
|
||||
import 'smart_lists_form_page.dart';
|
||||
|
||||
class PlaylistsPage extends StatefulWidget {
|
||||
const PlaylistsPage({Key? key}) : super(key: key);
|
||||
|
|
|
@ -1,15 +1,54 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
import '../state/music_data_store.dart';
|
||||
import '../state/settings_page_store.dart';
|
||||
import '../theming.dart';
|
||||
import 'library_folders_page.dart';
|
||||
import 'smart_lists_settings_page.dart';
|
||||
|
||||
class SettingsPage extends StatelessWidget {
|
||||
class SettingsPage extends StatefulWidget {
|
||||
const SettingsPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SettingsPage> createState() => _SettingsPageState();
|
||||
}
|
||||
|
||||
class _SettingsPageState extends State<SettingsPage> {
|
||||
late SettingsPageStore settingsPageStore;
|
||||
late TextEditingController _controller;
|
||||
late ReactionDisposer _dispose;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
settingsPageStore = GetIt.I<SettingsPageStore>();
|
||||
settingsPageStore.init();
|
||||
settingsPageStore.setupValidations();
|
||||
|
||||
_controller = TextEditingController();
|
||||
_controller.addListener(() {
|
||||
if (_controller.text != settingsPageStore.blockSkippedSongsThreshold) {
|
||||
print('ctrl listener: ${_controller.text}');
|
||||
settingsPageStore.blockSkippedSongsThreshold = _controller.text;
|
||||
}
|
||||
});
|
||||
_dispose = autorun((_) {
|
||||
if (_controller.text != settingsPageStore.blockSkippedSongsThreshold) {
|
||||
print('autorun: ${settingsPageStore.blockSkippedSongsThreshold}');
|
||||
_controller.text = settingsPageStore.blockSkippedSongsThreshold;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
settingsPageStore.dispose();
|
||||
_dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final MusicDataStore musicDataStore = GetIt.I<MusicDataStore>();
|
||||
|
@ -65,18 +104,66 @@ class SettingsPage extends StatelessWidget {
|
|||
height: 4.0,
|
||||
),
|
||||
const SettingsSection(text: 'Home page'),
|
||||
ListTile(
|
||||
title: const Text('Customize smart lists'),
|
||||
trailing: const Icon(Icons.chevron_right),
|
||||
onTap: () => Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext context) => const SmartListsSettingsPage(),
|
||||
),
|
||||
),
|
||||
const ListTile(
|
||||
title: Text('Soon (tm)'),
|
||||
),
|
||||
const Divider(
|
||||
height: 4.0,
|
||||
),
|
||||
const SettingsSection(text: 'Customize playback'),
|
||||
Observer(
|
||||
builder: (_) {
|
||||
final bool enabled = settingsPageStore.isBlockSkippedSongsEnabled;
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING, vertical: 4.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('Mark skipped songs as blocked'),
|
||||
const Spacer(),
|
||||
Switch(
|
||||
value: settingsPageStore.isBlockSkippedSongsEnabled,
|
||||
onChanged: (bool value) {
|
||||
print('set: $value');
|
||||
settingsPageStore.isBlockSkippedSongsEnabled = value;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING, vertical: 4.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('Minimum skip count to block songs'),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 56.0,
|
||||
child: TextFormField(
|
||||
controller: _controller,
|
||||
enabled: enabled,
|
||||
keyboardType: TextInputType.number,
|
||||
textAlign: TextAlign.center,
|
||||
onChanged: (value) {
|
||||
print(value);
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
errorText: settingsPageStore.error.skipCountThreshold,
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -176,7 +176,7 @@ class _SmartListFormPageState extends State<SmartListFormPage> {
|
|||
child: TextFormField(
|
||||
enabled: store.maxPlayCountEnabled,
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: store.maxPlayCount.toString(),
|
||||
initialValue: store.maxPlayCount,
|
||||
textAlign: TextAlign.center,
|
||||
onChanged: (value) {
|
||||
store.maxPlayCount = value;
|
||||
|
@ -193,6 +193,74 @@ class _SmartListFormPageState extends State<SmartListFormPage> {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 24.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Row(
|
||||
children: [
|
||||
Switch(
|
||||
value: store.minSkipCountEnabled,
|
||||
onChanged: (bool value) => store.minSkipCountEnabled = value,
|
||||
),
|
||||
const Text('Minimum skip count'),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 36.0,
|
||||
child: TextFormField(
|
||||
enabled: store.minSkipCountEnabled,
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: store.minSkipCount,
|
||||
onChanged: (value) {
|
||||
store.minSkipCount = value;
|
||||
},
|
||||
textAlign: TextAlign.center,
|
||||
decoration: InputDecoration(
|
||||
errorText: store.error.minSkipCount,
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Row(
|
||||
children: [
|
||||
Switch(
|
||||
value: store.maxSkipCountEnabled,
|
||||
onChanged: (bool value) => store.maxSkipCountEnabled = value,
|
||||
),
|
||||
const Text('Maximum skip count'),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: 36.0,
|
||||
child: TextFormField(
|
||||
enabled: store.maxSkipCountEnabled,
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: store.maxSkipCount,
|
||||
textAlign: TextAlign.center,
|
||||
onChanged: (value) {
|
||||
store.maxSkipCount = value;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
errorText: store.error.maxSkipCount,
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Observer(
|
||||
|
@ -244,7 +312,7 @@ class _SmartListFormPageState extends State<SmartListFormPage> {
|
|||
child: TextFormField(
|
||||
enabled: store.maxYearEnabled,
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: store.maxYear.toString(),
|
||||
initialValue: store.maxYear,
|
||||
textAlign: TextAlign.center,
|
||||
onChanged: (value) {
|
||||
store.maxYear = value;
|
||||
|
@ -278,7 +346,7 @@ class _SmartListFormPageState extends State<SmartListFormPage> {
|
|||
child: TextFormField(
|
||||
enabled: store.limitEnabled,
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: store.limit.toString(),
|
||||
initialValue: store.limit,
|
||||
textAlign: TextAlign.center,
|
||||
onChanged: (value) {
|
||||
store.limit = value;
|
|
@ -9,7 +9,7 @@ import '../state/smart_list_page_store.dart';
|
|||
import '../theming.dart';
|
||||
import '../widgets/song_bottom_sheet.dart';
|
||||
import '../widgets/song_list_tile.dart';
|
||||
import 'smart_lists_form_page.dart';
|
||||
import 'smart_list_form_page.dart';
|
||||
|
||||
class SmartListPage extends StatefulWidget {
|
||||
const SmartListPage({Key? key, required this.smartList}) : super(key: key);
|
||||
|
|
|
@ -5,8 +5,9 @@ import 'package:get_it/get_it.dart';
|
|||
import '../../domain/entities/smart_list.dart';
|
||||
import '../state/settings_store.dart';
|
||||
import '../theming.dart';
|
||||
import 'smart_lists_form_page.dart';
|
||||
import 'smart_list_form_page.dart';
|
||||
|
||||
// TODO: currently unused
|
||||
class SmartListsSettingsPage extends StatelessWidget {
|
||||
const SmartListsSettingsPage({Key? key}) : super(key: key);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:mobx/mobx.dart';
|
|||
import '../../domain/entities/song.dart';
|
||||
import '../state/audio_store.dart';
|
||||
import '../state/music_data_store.dart';
|
||||
import '../state/settings_store.dart';
|
||||
import '../widgets/song_bottom_sheet.dart';
|
||||
import '../widgets/song_list_tile.dart';
|
||||
|
||||
|
@ -22,12 +23,15 @@ class _SongsPageState extends State<SongsPage> with AutomaticKeepAliveClientMixi
|
|||
print('SongsPage.build');
|
||||
final MusicDataStore musicDataStore = GetIt.I<MusicDataStore>();
|
||||
final AudioStore audioStore = GetIt.I<AudioStore>();
|
||||
final SettingsStore settingsStore = GetIt.I<SettingsStore>();
|
||||
|
||||
super.build(context);
|
||||
return Observer(builder: (_) {
|
||||
print('SongsPage.build -> Observer.builder');
|
||||
|
||||
final songStream = musicDataStore.songStream;
|
||||
final isBlockSkippedSongsEnabled = settingsStore.isBlockSkippedSongsEnabled.first;
|
||||
final blockSkippedSongsThreshold = settingsStore.blockSkippedSongsThreshold.first;
|
||||
|
||||
switch (songStream.status) {
|
||||
case StreamStatus.active:
|
||||
|
@ -43,6 +47,8 @@ class _SongsPageState extends State<SongsPage> with AutomaticKeepAliveClientMixi
|
|||
subtitle: Subtitle.artistAlbum,
|
||||
onTap: () => audioStore.playSong(index, songs),
|
||||
onTapMore: () => SongBottomSheet()(song, context),
|
||||
isBlockSkippedSongsEnabled: isBlockSkippedSongsEnabled.value,
|
||||
blockSkippedSongsThreshold: blockSkippedSongsThreshold.value,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) => const SizedBox(
|
||||
|
|
84
lib/presentation/state/settings_page_store.dart
Normal file
84
lib/presentation/state/settings_page_store.dart
Normal file
|
@ -0,0 +1,84 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
|
||||
import '../../domain/repositories/settings_repository.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
part 'settings_page_store.g.dart';
|
||||
|
||||
class SettingsPageStore extends _SettingsPageStore with _$SettingsPageStore {
|
||||
SettingsPageStore({
|
||||
required SettingsRepository settingsRepository,
|
||||
}) : super(settingsRepository);
|
||||
}
|
||||
|
||||
abstract class _SettingsPageStore with Store {
|
||||
_SettingsPageStore(
|
||||
this._settingsRepository,
|
||||
);
|
||||
|
||||
final SettingsRepository _settingsRepository;
|
||||
|
||||
final FormErrorState error = FormErrorState();
|
||||
|
||||
@observable
|
||||
bool isBlockSkippedSongsEnabled = false;
|
||||
|
||||
@observable
|
||||
String blockSkippedSongsThreshold = '-1';
|
||||
|
||||
late List<ReactionDisposer> _disposers;
|
||||
|
||||
Future<void> addLibraryFolder(String? path) async {
|
||||
await _settingsRepository.addLibraryFolder(path);
|
||||
}
|
||||
|
||||
Future<void> removeLibraryFolder(String? path) async {
|
||||
await _settingsRepository.removeLibraryFolder(path);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> init() async {
|
||||
isBlockSkippedSongsEnabled = await _settingsRepository.isBlockSkippedSongsEnabled.first;
|
||||
blockSkippedSongsThreshold = (await _settingsRepository.blockSkippedSongsThreshold.first).toString();
|
||||
}
|
||||
|
||||
void setupValidations() {
|
||||
_disposers = [
|
||||
reaction((_) => blockSkippedSongsThreshold,
|
||||
(String n) => _validateSkipCountThreshold(isBlockSkippedSongsEnabled, n)),
|
||||
reaction((_) => isBlockSkippedSongsEnabled, _validateBlockSkipCountEnabled),
|
||||
];
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
for (final d in _disposers) {
|
||||
d();
|
||||
}
|
||||
}
|
||||
|
||||
void validateAll() {
|
||||
_validateSkipCountThreshold(isBlockSkippedSongsEnabled, blockSkippedSongsThreshold);
|
||||
}
|
||||
|
||||
void _validateSkipCountThreshold(bool enabled, String number) {
|
||||
error.skipCountThreshold = validateNumber(enabled, number);
|
||||
if (!error.hasErrors) {
|
||||
final val = int.parse(blockSkippedSongsThreshold);
|
||||
_settingsRepository.setBlockSkippedSongsThreshold(val);
|
||||
}
|
||||
}
|
||||
|
||||
void _validateBlockSkipCountEnabled(bool enabled) {
|
||||
_settingsRepository.setBlockSkippedSongs(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
class FormErrorState = _FormErrorState with _$FormErrorState;
|
||||
|
||||
abstract class _FormErrorState with Store {
|
||||
@observable
|
||||
String? skipCountThreshold;
|
||||
|
||||
@computed
|
||||
bool get hasErrors => skipCountThreshold != null;
|
||||
}
|
94
lib/presentation/state/settings_page_store.g.dart
Normal file
94
lib/presentation/state/settings_page_store.g.dart
Normal file
|
@ -0,0 +1,94 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'settings_page_store.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// StoreGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
|
||||
|
||||
mixin _$SettingsPageStore on _SettingsPageStore, Store {
|
||||
final _$isBlockSkippedSongsEnabledAtom =
|
||||
Atom(name: '_SettingsPageStore.isBlockSkippedSongsEnabled');
|
||||
|
||||
@override
|
||||
bool get isBlockSkippedSongsEnabled {
|
||||
_$isBlockSkippedSongsEnabledAtom.reportRead();
|
||||
return super.isBlockSkippedSongsEnabled;
|
||||
}
|
||||
|
||||
@override
|
||||
set isBlockSkippedSongsEnabled(bool value) {
|
||||
_$isBlockSkippedSongsEnabledAtom
|
||||
.reportWrite(value, super.isBlockSkippedSongsEnabled, () {
|
||||
super.isBlockSkippedSongsEnabled = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$blockSkippedSongsThresholdAtom =
|
||||
Atom(name: '_SettingsPageStore.blockSkippedSongsThreshold');
|
||||
|
||||
@override
|
||||
String get blockSkippedSongsThreshold {
|
||||
_$blockSkippedSongsThresholdAtom.reportRead();
|
||||
return super.blockSkippedSongsThreshold;
|
||||
}
|
||||
|
||||
@override
|
||||
set blockSkippedSongsThreshold(String value) {
|
||||
_$blockSkippedSongsThresholdAtom
|
||||
.reportWrite(value, super.blockSkippedSongsThreshold, () {
|
||||
super.blockSkippedSongsThreshold = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$initAsyncAction = AsyncAction('_SettingsPageStore.init');
|
||||
|
||||
@override
|
||||
Future<void> init() {
|
||||
return _$initAsyncAction.run(() => super.init());
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
isBlockSkippedSongsEnabled: ${isBlockSkippedSongsEnabled},
|
||||
blockSkippedSongsThreshold: ${blockSkippedSongsThreshold}
|
||||
''';
|
||||
}
|
||||
}
|
||||
|
||||
mixin _$FormErrorState on _FormErrorState, Store {
|
||||
Computed<bool>? _$hasErrorsComputed;
|
||||
|
||||
@override
|
||||
bool get hasErrors =>
|
||||
(_$hasErrorsComputed ??= Computed<bool>(() => super.hasErrors,
|
||||
name: '_FormErrorState.hasErrors'))
|
||||
.value;
|
||||
|
||||
final _$skipCountThresholdAtom =
|
||||
Atom(name: '_FormErrorState.skipCountThreshold');
|
||||
|
||||
@override
|
||||
String? get skipCountThreshold {
|
||||
_$skipCountThresholdAtom.reportRead();
|
||||
return super.skipCountThreshold;
|
||||
}
|
||||
|
||||
@override
|
||||
set skipCountThreshold(String? value) {
|
||||
_$skipCountThresholdAtom.reportWrite(value, super.skipCountThreshold, () {
|
||||
super.skipCountThreshold = value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
skipCountThreshold: ${skipCountThreshold},
|
||||
hasErrors: ${hasErrors}
|
||||
''';
|
||||
}
|
||||
}
|
|
@ -30,6 +30,12 @@ abstract class _SettingsStore with Store {
|
|||
late ObservableStream<List<String>> libraryFoldersStream =
|
||||
_settingsRepository.libraryFoldersStream.asObservable(initialValue: []);
|
||||
|
||||
@observable
|
||||
late ObservableStream<bool> isBlockSkippedSongsEnabled = _settingsRepository.isBlockSkippedSongsEnabled.asObservable();
|
||||
|
||||
@observable
|
||||
late ObservableStream<int> blockSkippedSongsThreshold = _settingsRepository.blockSkippedSongsThreshold.asObservable();
|
||||
|
||||
Future<void> addLibraryFolder(String? path) async {
|
||||
await _settingsRepository.addLibraryFolder(path);
|
||||
}
|
||||
|
|
|
@ -41,11 +41,47 @@ mixin _$SettingsStore on _SettingsStore, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$isBlockSkippedSongsEnabledAtom =
|
||||
Atom(name: '_SettingsStore.isBlockSkippedSongsEnabled');
|
||||
|
||||
@override
|
||||
ObservableStream<bool> get isBlockSkippedSongsEnabled {
|
||||
_$isBlockSkippedSongsEnabledAtom.reportRead();
|
||||
return super.isBlockSkippedSongsEnabled;
|
||||
}
|
||||
|
||||
@override
|
||||
set isBlockSkippedSongsEnabled(ObservableStream<bool> value) {
|
||||
_$isBlockSkippedSongsEnabledAtom
|
||||
.reportWrite(value, super.isBlockSkippedSongsEnabled, () {
|
||||
super.isBlockSkippedSongsEnabled = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$blockSkippedSongsThresholdAtom =
|
||||
Atom(name: '_SettingsStore.blockSkippedSongsThreshold');
|
||||
|
||||
@override
|
||||
ObservableStream<int> get blockSkippedSongsThreshold {
|
||||
_$blockSkippedSongsThresholdAtom.reportRead();
|
||||
return super.blockSkippedSongsThreshold;
|
||||
}
|
||||
|
||||
@override
|
||||
set blockSkippedSongsThreshold(ObservableStream<int> value) {
|
||||
_$blockSkippedSongsThresholdAtom
|
||||
.reportWrite(value, super.blockSkippedSongsThreshold, () {
|
||||
super.blockSkippedSongsThreshold = value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
smartListsStream: ${smartListsStream},
|
||||
libraryFoldersStream: ${libraryFoldersStream}
|
||||
libraryFoldersStream: ${libraryFoldersStream},
|
||||
isBlockSkippedSongsEnabled: ${isBlockSkippedSongsEnabled},
|
||||
blockSkippedSongsThreshold: ${blockSkippedSongsThreshold}
|
||||
''';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:mobx/mobx.dart';
|
|||
import '../../domain/entities/artist.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
import '../../domain/repositories/music_data_repository.dart';
|
||||
import '../utils.dart';
|
||||
|
||||
part 'smart_list_form_store.g.dart';
|
||||
|
||||
|
@ -42,6 +43,16 @@ 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
|
||||
|
@ -118,6 +129,8 @@ 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)),
|
||||
|
@ -135,6 +148,8 @@ 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);
|
||||
|
@ -145,29 +160,34 @@ abstract class _SmartListStore with Store {
|
|||
}
|
||||
|
||||
void _validateMinPlayCount(bool enabled, String number) {
|
||||
error.minPlayCount = _validateNumber(enabled, number);
|
||||
error.minPlayCount = validateNumber(enabled, number);
|
||||
}
|
||||
|
||||
void _validateMaxPlayCount(bool enabled, String number) {
|
||||
error.maxPlayCount = _validateNumber(enabled, number);
|
||||
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);
|
||||
error.minYear = validateNumber(enabled, number);
|
||||
}
|
||||
|
||||
void _validateMaxYear(bool enabled, String number) {
|
||||
error.maxYear = _validateNumber(enabled, number);
|
||||
error.maxYear = validateNumber(enabled, number);
|
||||
}
|
||||
|
||||
void _validateLimit(bool enabled, String number) {
|
||||
error.limit = _validateNumber(enabled, number);
|
||||
error.limit = validateNumber(enabled, number);
|
||||
}
|
||||
|
||||
String? _validateNumber(bool enabled, String number) {
|
||||
if (!enabled) return null;
|
||||
return int.tryParse(number) == null ? 'Error' : null;
|
||||
}
|
||||
|
||||
|
||||
Future<void> _createSmartList() async {
|
||||
await _musicDataRepository.insertSmartList(
|
||||
|
@ -177,6 +197,8 @@ 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,
|
||||
|
@ -201,6 +223,8 @@ 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,
|
||||
|
@ -229,6 +253,12 @@ abstract class _FormErrorState with Store {
|
|||
@observable
|
||||
String? maxPlayCount;
|
||||
|
||||
@observable
|
||||
String? minSkipCount;
|
||||
|
||||
@observable
|
||||
String? maxSkipCount;
|
||||
|
||||
@observable
|
||||
String? minYear;
|
||||
|
||||
|
@ -267,6 +297,7 @@ 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',
|
||||
|
@ -279,6 +310,8 @@ 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(
|
||||
|
|
|
@ -116,6 +116,68 @@ mixin _$SmartListFormStore on _SmartListStore, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$minSkipCountEnabledAtom =
|
||||
Atom(name: '_SmartListStore.minSkipCountEnabled');
|
||||
|
||||
@override
|
||||
bool get minSkipCountEnabled {
|
||||
_$minSkipCountEnabledAtom.reportRead();
|
||||
return super.minSkipCountEnabled;
|
||||
}
|
||||
|
||||
@override
|
||||
set minSkipCountEnabled(bool value) {
|
||||
_$minSkipCountEnabledAtom.reportWrite(value, super.minSkipCountEnabled, () {
|
||||
super.minSkipCountEnabled = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$minSkipCountAtom = Atom(name: '_SmartListStore.minSkipCount');
|
||||
|
||||
@override
|
||||
String get minSkipCount {
|
||||
_$minSkipCountAtom.reportRead();
|
||||
return super.minSkipCount;
|
||||
}
|
||||
|
||||
@override
|
||||
set minSkipCount(String value) {
|
||||
_$minSkipCountAtom.reportWrite(value, super.minSkipCount, () {
|
||||
super.minSkipCount = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$maxSkipCountEnabledAtom =
|
||||
Atom(name: '_SmartListStore.maxSkipCountEnabled');
|
||||
|
||||
@override
|
||||
bool get maxSkipCountEnabled {
|
||||
_$maxSkipCountEnabledAtom.reportRead();
|
||||
return super.maxSkipCountEnabled;
|
||||
}
|
||||
|
||||
@override
|
||||
set maxSkipCountEnabled(bool value) {
|
||||
_$maxSkipCountEnabledAtom.reportWrite(value, super.maxSkipCountEnabled, () {
|
||||
super.maxSkipCountEnabled = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$maxSkipCountAtom = Atom(name: '_SmartListStore.maxSkipCount');
|
||||
|
||||
@override
|
||||
String get maxSkipCount {
|
||||
_$maxSkipCountAtom.reportRead();
|
||||
return super.maxSkipCount;
|
||||
}
|
||||
|
||||
@override
|
||||
set maxSkipCount(String value) {
|
||||
_$maxSkipCountAtom.reportWrite(value, super.maxSkipCount, () {
|
||||
super.maxSkipCount = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$minYearEnabledAtom = Atom(name: '_SmartListStore.minYearEnabled');
|
||||
|
||||
@override
|
||||
|
@ -334,6 +396,10 @@ minPlayCountEnabled: ${minPlayCountEnabled},
|
|||
minPlayCount: ${minPlayCount},
|
||||
maxPlayCountEnabled: ${maxPlayCountEnabled},
|
||||
maxPlayCount: ${maxPlayCount},
|
||||
minSkipCountEnabled: ${minSkipCountEnabled},
|
||||
minSkipCount: ${minSkipCount},
|
||||
maxSkipCountEnabled: ${maxSkipCountEnabled},
|
||||
maxSkipCount: ${maxSkipCount},
|
||||
minYearEnabled: ${minYearEnabled},
|
||||
minYear: ${minYear},
|
||||
maxYearEnabled: ${maxYearEnabled},
|
||||
|
@ -402,6 +468,36 @@ mixin _$FormErrorState on _FormErrorState, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$minSkipCountAtom = Atom(name: '_FormErrorState.minSkipCount');
|
||||
|
||||
@override
|
||||
String? get minSkipCount {
|
||||
_$minSkipCountAtom.reportRead();
|
||||
return super.minSkipCount;
|
||||
}
|
||||
|
||||
@override
|
||||
set minSkipCount(String? value) {
|
||||
_$minSkipCountAtom.reportWrite(value, super.minSkipCount, () {
|
||||
super.minSkipCount = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$maxSkipCountAtom = Atom(name: '_FormErrorState.maxSkipCount');
|
||||
|
||||
@override
|
||||
String? get maxSkipCount {
|
||||
_$maxSkipCountAtom.reportRead();
|
||||
return super.maxSkipCount;
|
||||
}
|
||||
|
||||
@override
|
||||
set maxSkipCount(String? value) {
|
||||
_$maxSkipCountAtom.reportWrite(value, super.maxSkipCount, () {
|
||||
super.maxSkipCount = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$minYearAtom = Atom(name: '_FormErrorState.minYear');
|
||||
|
||||
@override
|
||||
|
@ -453,6 +549,8 @@ mixin _$FormErrorState on _FormErrorState, Store {
|
|||
name: ${name},
|
||||
minPlayCount: ${minPlayCount},
|
||||
maxPlayCount: ${maxPlayCount},
|
||||
minSkipCount: ${minSkipCount},
|
||||
maxSkipCount: ${maxSkipCount},
|
||||
minYear: ${minYear},
|
||||
maxYear: ${maxYear},
|
||||
limit: ${limit},
|
||||
|
|
|
@ -35,6 +35,8 @@ ThemeData theme() => ThemeData(
|
|||
primary: LIGHT1,
|
||||
),
|
||||
),
|
||||
progressIndicatorTheme: const ProgressIndicatorThemeData(color: LIGHT2),
|
||||
sliderTheme: const SliderThemeData(activeTrackColor: LIGHT2, thumbColor: LIGHT2, inactiveTrackColor: Colors.white24),
|
||||
// https://api.flutter.dev/flutter/material/TextTheme-class.html
|
||||
textTheme: const TextTheme(
|
||||
headline1: TextStyle(
|
||||
|
|
|
@ -21,7 +21,7 @@ String msToTimeString(Duration duration) {
|
|||
|
||||
final int hours = duration.inHours;
|
||||
final int minutes = duration.inMinutes.remainder(60);
|
||||
|
||||
|
||||
final String twoDigitMinutes = twoDigits(minutes);
|
||||
final String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
|
||||
|
||||
|
@ -30,3 +30,8 @@ String msToTimeString(Duration duration) {
|
|||
}
|
||||
return '$minutes:$twoDigitSeconds';
|
||||
}
|
||||
|
||||
String? validateNumber(bool enabled, String number) {
|
||||
if (!enabled) return null;
|
||||
return int.tryParse(number) == null ? 'Error' : null;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ class SongListTile extends StatelessWidget {
|
|||
this.highlight = false,
|
||||
this.showAlbum = true,
|
||||
this.subtitle = Subtitle.artist,
|
||||
this.isBlockSkippedSongsEnabled,
|
||||
this.blockSkippedSongsThreshold,
|
||||
}) : super(key: key);
|
||||
|
||||
final Song song;
|
||||
|
@ -23,9 +25,14 @@ class SongListTile extends StatelessWidget {
|
|||
final bool highlight;
|
||||
final bool showAlbum;
|
||||
final Subtitle subtitle;
|
||||
final bool? isBlockSkippedSongsEnabled;
|
||||
final int? blockSkippedSongsThreshold;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isBlockEnabled = isBlockSkippedSongsEnabled ?? false;
|
||||
final blockThreshold = blockSkippedSongsThreshold ?? 1000;
|
||||
|
||||
final Widget leading = showAlbum
|
||||
? Image(
|
||||
image: utils.getAlbumImage(song.albumArtPath),
|
||||
|
@ -97,10 +104,16 @@ class SongListTile extends StatelessWidget {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (song.blocked)
|
||||
Icon(
|
||||
const Icon(
|
||||
Icons.remove_circle_outline,
|
||||
size: 14.0,
|
||||
color: Colors.white.withOpacity(0.4),
|
||||
color: Colors.white38,
|
||||
),
|
||||
if (!song.blocked && isBlockEnabled && blockThreshold <= song.skipCount)
|
||||
Icon(
|
||||
Icons.skip_next_rounded,
|
||||
size: 18.0,
|
||||
color: Colors.red.shade900,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
|
|
|
@ -156,6 +156,8 @@ 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),
|
||||
|
@ -256,6 +258,11 @@ 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)
|
||||
|
@ -312,6 +319,14 @@ 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(
|
||||
|
|
|
@ -5,7 +5,7 @@ import '../settings_data_source.dart';
|
|||
|
||||
part 'settings_dao.g.dart';
|
||||
|
||||
@UseDao(tables: [LibraryFolders, SmartLists, SmartListArtists, Artists])
|
||||
@UseDao(tables: [LibraryFolders, BlockSkippedSongs])
|
||||
class SettingsDao extends DatabaseAccessor<MoorDatabase>
|
||||
with _$SettingsDaoMixin
|
||||
implements SettingsDataSource {
|
||||
|
@ -24,4 +24,22 @@ class SettingsDao extends DatabaseAccessor<MoorDatabase>
|
|||
Future<void> addLibraryFolder(String path) async {
|
||||
await into(libraryFolders).insert(LibraryFoldersCompanion(path: Value(path)));
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<bool> get isBlockSkippedSongsEnabled =>
|
||||
(select(blockSkippedSongs)..limit(1)).watchSingle().map((tbl) => tbl.enabled);
|
||||
|
||||
@override
|
||||
Stream<int> get blockSkippedSongsThreshold =>
|
||||
(select(blockSkippedSongs)..limit(1)).watchSingle().map((tbl) => tbl.threshold);
|
||||
|
||||
@override
|
||||
Future<void> setBlockSkippedSongsThreshold(int threshold) async {
|
||||
await update(blockSkippedSongs).write(BlockSkippedSongsCompanion(threshold: Value(threshold)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setBlockSkippedSongs(bool enabled) async {
|
||||
await update(blockSkippedSongs).write(BlockSkippedSongsCompanion(enabled: Value(enabled)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ part of 'settings_dao.dart';
|
|||
|
||||
mixin _$SettingsDaoMixin on DatabaseAccessor<MoorDatabase> {
|
||||
$LibraryFoldersTable get libraryFolders => attachedDatabase.libraryFolders;
|
||||
$SmartListsTable get smartLists => attachedDatabase.smartLists;
|
||||
$SmartListArtistsTable get smartListArtists =>
|
||||
attachedDatabase.smartListArtists;
|
||||
$ArtistsTable get artists => attachedDatabase.artists;
|
||||
$BlockSkippedSongsTable get blockSkippedSongs =>
|
||||
attachedDatabase.blockSkippedSongs;
|
||||
}
|
||||
|
|
|
@ -107,6 +107,11 @@ class LibraryFolders extends Table {
|
|||
TextColumn get path => text()();
|
||||
}
|
||||
|
||||
class BlockSkippedSongs extends Table {
|
||||
BoolColumn get enabled => boolean().withDefault(const Constant(false))();
|
||||
IntColumn get threshold => integer().withDefault(const Constant(3))();
|
||||
}
|
||||
|
||||
class MoorAlbumOfDay extends Table {
|
||||
IntColumn get albumId => integer()();
|
||||
IntColumn get milliSecSinceEpoch => integer()();
|
||||
|
@ -128,6 +133,8 @@ class SmartLists extends Table {
|
|||
IntColumn get maxLikeCount => integer().withDefault(const Constant(5))();
|
||||
IntColumn get minPlayCount => integer().nullable()();
|
||||
IntColumn get maxPlayCount => integer().nullable()();
|
||||
IntColumn get minSkipCount => integer().nullable()();
|
||||
IntColumn get maxSkipCount => integer().nullable()();
|
||||
IntColumn get minYear => integer().nullable()();
|
||||
IntColumn get maxYear => integer().nullable()();
|
||||
IntColumn get limit => integer().nullable()();
|
||||
|
@ -173,6 +180,7 @@ class PlaylistEntries extends Table {
|
|||
SmartListArtists,
|
||||
Playlists,
|
||||
PlaylistEntries,
|
||||
BlockSkippedSongs,
|
||||
],
|
||||
daos: [
|
||||
PersistentStateDao,
|
||||
|
@ -192,7 +200,7 @@ class MoorDatabase extends _$MoorDatabase {
|
|||
MoorDatabase.connect(DatabaseConnection connection) : super.connect(connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 4;
|
||||
int get schemaVersion => 5;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(beforeOpen: (details) async {
|
||||
|
@ -235,6 +243,12 @@ class MoorDatabase extends _$MoorDatabase {
|
|||
await m.createTable(playlists);
|
||||
await m.createTable(playlistEntries);
|
||||
}
|
||||
if (from < 5) {
|
||||
await m.addColumn(smartLists, smartLists.minSkipCount);
|
||||
await m.addColumn(smartLists, smartLists.maxSkipCount);
|
||||
await m.createTable(blockSkippedSongs);
|
||||
await into(blockSkippedSongs).insert(const BlockSkippedSongsCompanion());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2814,6 +2814,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
final int maxLikeCount;
|
||||
final int? minPlayCount;
|
||||
final int? maxPlayCount;
|
||||
final int? minSkipCount;
|
||||
final int? maxSkipCount;
|
||||
final int? minYear;
|
||||
final int? maxYear;
|
||||
final int? limit;
|
||||
|
@ -2829,6 +2831,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
required this.maxLikeCount,
|
||||
this.minPlayCount,
|
||||
this.maxPlayCount,
|
||||
this.minSkipCount,
|
||||
this.maxSkipCount,
|
||||
this.minYear,
|
||||
this.maxYear,
|
||||
this.limit,
|
||||
|
@ -2857,6 +2861,10 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
.mapFromDatabaseResponse(data['${effectivePrefix}min_play_count']),
|
||||
maxPlayCount: const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}max_play_count']),
|
||||
minSkipCount: const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}min_skip_count']),
|
||||
maxSkipCount: const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}max_skip_count']),
|
||||
minYear: const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}min_year']),
|
||||
maxYear: const IntType()
|
||||
|
@ -2887,6 +2895,12 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
if (!nullToAbsent || maxPlayCount != null) {
|
||||
map['max_play_count'] = Variable<int?>(maxPlayCount);
|
||||
}
|
||||
if (!nullToAbsent || minSkipCount != null) {
|
||||
map['min_skip_count'] = Variable<int?>(minSkipCount);
|
||||
}
|
||||
if (!nullToAbsent || maxSkipCount != null) {
|
||||
map['max_skip_count'] = Variable<int?>(maxSkipCount);
|
||||
}
|
||||
if (!nullToAbsent || minYear != null) {
|
||||
map['min_year'] = Variable<int?>(minYear);
|
||||
}
|
||||
|
@ -2918,6 +2932,12 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
maxPlayCount: maxPlayCount == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(maxPlayCount),
|
||||
minSkipCount: minSkipCount == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(minSkipCount),
|
||||
maxSkipCount: maxSkipCount == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(maxSkipCount),
|
||||
minYear: minYear == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(minYear),
|
||||
|
@ -2944,6 +2964,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
maxLikeCount: serializer.fromJson<int>(json['maxLikeCount']),
|
||||
minPlayCount: serializer.fromJson<int?>(json['minPlayCount']),
|
||||
maxPlayCount: serializer.fromJson<int?>(json['maxPlayCount']),
|
||||
minSkipCount: serializer.fromJson<int?>(json['minSkipCount']),
|
||||
maxSkipCount: serializer.fromJson<int?>(json['maxSkipCount']),
|
||||
minYear: serializer.fromJson<int?>(json['minYear']),
|
||||
maxYear: serializer.fromJson<int?>(json['maxYear']),
|
||||
limit: serializer.fromJson<int?>(json['limit']),
|
||||
|
@ -2964,6 +2986,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
'maxLikeCount': serializer.toJson<int>(maxLikeCount),
|
||||
'minPlayCount': serializer.toJson<int?>(minPlayCount),
|
||||
'maxPlayCount': serializer.toJson<int?>(maxPlayCount),
|
||||
'minSkipCount': serializer.toJson<int?>(minSkipCount),
|
||||
'maxSkipCount': serializer.toJson<int?>(maxSkipCount),
|
||||
'minYear': serializer.toJson<int?>(minYear),
|
||||
'maxYear': serializer.toJson<int?>(maxYear),
|
||||
'limit': serializer.toJson<int?>(limit),
|
||||
|
@ -2982,6 +3006,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
int? maxLikeCount,
|
||||
int? minPlayCount,
|
||||
int? maxPlayCount,
|
||||
int? minSkipCount,
|
||||
int? maxSkipCount,
|
||||
int? minYear,
|
||||
int? maxYear,
|
||||
int? limit,
|
||||
|
@ -2997,6 +3023,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
maxLikeCount: maxLikeCount ?? this.maxLikeCount,
|
||||
minPlayCount: minPlayCount ?? this.minPlayCount,
|
||||
maxPlayCount: maxPlayCount ?? this.maxPlayCount,
|
||||
minSkipCount: minSkipCount ?? this.minSkipCount,
|
||||
maxSkipCount: maxSkipCount ?? this.maxSkipCount,
|
||||
minYear: minYear ?? this.minYear,
|
||||
maxYear: maxYear ?? this.maxYear,
|
||||
limit: limit ?? this.limit,
|
||||
|
@ -3015,6 +3043,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
..write('maxLikeCount: $maxLikeCount, ')
|
||||
..write('minPlayCount: $minPlayCount, ')
|
||||
..write('maxPlayCount: $maxPlayCount, ')
|
||||
..write('minSkipCount: $minSkipCount, ')
|
||||
..write('maxSkipCount: $maxSkipCount, ')
|
||||
..write('minYear: $minYear, ')
|
||||
..write('maxYear: $maxYear, ')
|
||||
..write('limit: $limit, ')
|
||||
|
@ -3044,15 +3074,20 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
$mrjc(
|
||||
maxPlayCount.hashCode,
|
||||
$mrjc(
|
||||
minYear.hashCode,
|
||||
minSkipCount.hashCode,
|
||||
$mrjc(
|
||||
maxYear.hashCode,
|
||||
maxSkipCount.hashCode,
|
||||
$mrjc(
|
||||
limit.hashCode,
|
||||
minYear.hashCode,
|
||||
$mrjc(
|
||||
orderCriteria.hashCode,
|
||||
orderDirections
|
||||
.hashCode))))))))))))));
|
||||
maxYear.hashCode,
|
||||
$mrjc(
|
||||
limit.hashCode,
|
||||
$mrjc(
|
||||
orderCriteria
|
||||
.hashCode,
|
||||
orderDirections
|
||||
.hashCode))))))))))))))));
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
|
@ -3066,6 +3101,8 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
other.maxLikeCount == this.maxLikeCount &&
|
||||
other.minPlayCount == this.minPlayCount &&
|
||||
other.maxPlayCount == this.maxPlayCount &&
|
||||
other.minSkipCount == this.minSkipCount &&
|
||||
other.maxSkipCount == this.maxSkipCount &&
|
||||
other.minYear == this.minYear &&
|
||||
other.maxYear == this.maxYear &&
|
||||
other.limit == this.limit &&
|
||||
|
@ -3083,6 +3120,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
final Value<int> maxLikeCount;
|
||||
final Value<int?> minPlayCount;
|
||||
final Value<int?> maxPlayCount;
|
||||
final Value<int?> minSkipCount;
|
||||
final Value<int?> maxSkipCount;
|
||||
final Value<int?> minYear;
|
||||
final Value<int?> maxYear;
|
||||
final Value<int?> limit;
|
||||
|
@ -3098,6 +3137,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
this.maxLikeCount = const Value.absent(),
|
||||
this.minPlayCount = const Value.absent(),
|
||||
this.maxPlayCount = const Value.absent(),
|
||||
this.minSkipCount = const Value.absent(),
|
||||
this.maxSkipCount = const Value.absent(),
|
||||
this.minYear = const Value.absent(),
|
||||
this.maxYear = const Value.absent(),
|
||||
this.limit = const Value.absent(),
|
||||
|
@ -3114,6 +3155,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
this.maxLikeCount = const Value.absent(),
|
||||
this.minPlayCount = const Value.absent(),
|
||||
this.maxPlayCount = const Value.absent(),
|
||||
this.minSkipCount = const Value.absent(),
|
||||
this.maxSkipCount = const Value.absent(),
|
||||
this.minYear = const Value.absent(),
|
||||
this.maxYear = const Value.absent(),
|
||||
this.limit = const Value.absent(),
|
||||
|
@ -3132,6 +3175,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
Expression<int>? maxLikeCount,
|
||||
Expression<int?>? minPlayCount,
|
||||
Expression<int?>? maxPlayCount,
|
||||
Expression<int?>? minSkipCount,
|
||||
Expression<int?>? maxSkipCount,
|
||||
Expression<int?>? minYear,
|
||||
Expression<int?>? maxYear,
|
||||
Expression<int?>? limit,
|
||||
|
@ -3148,6 +3193,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
if (maxLikeCount != null) 'max_like_count': maxLikeCount,
|
||||
if (minPlayCount != null) 'min_play_count': minPlayCount,
|
||||
if (maxPlayCount != null) 'max_play_count': maxPlayCount,
|
||||
if (minSkipCount != null) 'min_skip_count': minSkipCount,
|
||||
if (maxSkipCount != null) 'max_skip_count': maxSkipCount,
|
||||
if (minYear != null) 'min_year': minYear,
|
||||
if (maxYear != null) 'max_year': maxYear,
|
||||
if (limit != null) 'limit': limit,
|
||||
|
@ -3166,6 +3213,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
Value<int>? maxLikeCount,
|
||||
Value<int?>? minPlayCount,
|
||||
Value<int?>? maxPlayCount,
|
||||
Value<int?>? minSkipCount,
|
||||
Value<int?>? maxSkipCount,
|
||||
Value<int?>? minYear,
|
||||
Value<int?>? maxYear,
|
||||
Value<int?>? limit,
|
||||
|
@ -3181,6 +3230,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
maxLikeCount: maxLikeCount ?? this.maxLikeCount,
|
||||
minPlayCount: minPlayCount ?? this.minPlayCount,
|
||||
maxPlayCount: maxPlayCount ?? this.maxPlayCount,
|
||||
minSkipCount: minSkipCount ?? this.minSkipCount,
|
||||
maxSkipCount: maxSkipCount ?? this.maxSkipCount,
|
||||
minYear: minYear ?? this.minYear,
|
||||
maxYear: maxYear ?? this.maxYear,
|
||||
limit: limit ?? this.limit,
|
||||
|
@ -3219,6 +3270,12 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
if (maxPlayCount.present) {
|
||||
map['max_play_count'] = Variable<int?>(maxPlayCount.value);
|
||||
}
|
||||
if (minSkipCount.present) {
|
||||
map['min_skip_count'] = Variable<int?>(minSkipCount.value);
|
||||
}
|
||||
if (maxSkipCount.present) {
|
||||
map['max_skip_count'] = Variable<int?>(maxSkipCount.value);
|
||||
}
|
||||
if (minYear.present) {
|
||||
map['min_year'] = Variable<int?>(minYear.value);
|
||||
}
|
||||
|
@ -3249,6 +3306,8 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
..write('maxLikeCount: $maxLikeCount, ')
|
||||
..write('minPlayCount: $minPlayCount, ')
|
||||
..write('maxPlayCount: $maxPlayCount, ')
|
||||
..write('minSkipCount: $minSkipCount, ')
|
||||
..write('maxSkipCount: $maxSkipCount, ')
|
||||
..write('minYear: $minYear, ')
|
||||
..write('maxYear: $maxYear, ')
|
||||
..write('limit: $limit, ')
|
||||
|
@ -3355,6 +3414,30 @@ class $SmartListsTable extends SmartLists
|
|||
);
|
||||
}
|
||||
|
||||
final VerificationMeta _minSkipCountMeta =
|
||||
const VerificationMeta('minSkipCount');
|
||||
@override
|
||||
late final GeneratedIntColumn minSkipCount = _constructMinSkipCount();
|
||||
GeneratedIntColumn _constructMinSkipCount() {
|
||||
return GeneratedIntColumn(
|
||||
'min_skip_count',
|
||||
$tableName,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
final VerificationMeta _maxSkipCountMeta =
|
||||
const VerificationMeta('maxSkipCount');
|
||||
@override
|
||||
late final GeneratedIntColumn maxSkipCount = _constructMaxSkipCount();
|
||||
GeneratedIntColumn _constructMaxSkipCount() {
|
||||
return GeneratedIntColumn(
|
||||
'max_skip_count',
|
||||
$tableName,
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
final VerificationMeta _minYearMeta = const VerificationMeta('minYear');
|
||||
@override
|
||||
late final GeneratedIntColumn minYear = _constructMinYear();
|
||||
|
@ -3423,6 +3506,8 @@ class $SmartListsTable extends SmartLists
|
|||
maxLikeCount,
|
||||
minPlayCount,
|
||||
maxPlayCount,
|
||||
minSkipCount,
|
||||
maxSkipCount,
|
||||
minYear,
|
||||
maxYear,
|
||||
limit,
|
||||
|
@ -3491,6 +3576,18 @@ class $SmartListsTable extends SmartLists
|
|||
maxPlayCount.isAcceptableOrUnknown(
|
||||
data['max_play_count']!, _maxPlayCountMeta));
|
||||
}
|
||||
if (data.containsKey('min_skip_count')) {
|
||||
context.handle(
|
||||
_minSkipCountMeta,
|
||||
minSkipCount.isAcceptableOrUnknown(
|
||||
data['min_skip_count']!, _minSkipCountMeta));
|
||||
}
|
||||
if (data.containsKey('max_skip_count')) {
|
||||
context.handle(
|
||||
_maxSkipCountMeta,
|
||||
maxSkipCount.isAcceptableOrUnknown(
|
||||
data['max_skip_count']!, _maxSkipCountMeta));
|
||||
}
|
||||
if (data.containsKey('min_year')) {
|
||||
context.handle(_minYearMeta,
|
||||
minYear.isAcceptableOrUnknown(data['min_year']!, _minYearMeta));
|
||||
|
@ -4153,6 +4250,188 @@ class $PlaylistEntriesTable extends PlaylistEntries
|
|||
}
|
||||
}
|
||||
|
||||
class BlockSkippedSong extends DataClass
|
||||
implements Insertable<BlockSkippedSong> {
|
||||
final bool enabled;
|
||||
final int threshold;
|
||||
BlockSkippedSong({required this.enabled, required this.threshold});
|
||||
factory BlockSkippedSong.fromData(
|
||||
Map<String, dynamic> data, GeneratedDatabase db,
|
||||
{String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
return BlockSkippedSong(
|
||||
enabled: const BoolType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}enabled'])!,
|
||||
threshold: const IntType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}threshold'])!,
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['enabled'] = Variable<bool>(enabled);
|
||||
map['threshold'] = Variable<int>(threshold);
|
||||
return map;
|
||||
}
|
||||
|
||||
BlockSkippedSongsCompanion toCompanion(bool nullToAbsent) {
|
||||
return BlockSkippedSongsCompanion(
|
||||
enabled: Value(enabled),
|
||||
threshold: Value(threshold),
|
||||
);
|
||||
}
|
||||
|
||||
factory BlockSkippedSong.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return BlockSkippedSong(
|
||||
enabled: serializer.fromJson<bool>(json['enabled']),
|
||||
threshold: serializer.fromJson<int>(json['threshold']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'enabled': serializer.toJson<bool>(enabled),
|
||||
'threshold': serializer.toJson<int>(threshold),
|
||||
};
|
||||
}
|
||||
|
||||
BlockSkippedSong copyWith({bool? enabled, int? threshold}) =>
|
||||
BlockSkippedSong(
|
||||
enabled: enabled ?? this.enabled,
|
||||
threshold: threshold ?? this.threshold,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('BlockSkippedSong(')
|
||||
..write('enabled: $enabled, ')
|
||||
..write('threshold: $threshold')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => $mrjf($mrjc(enabled.hashCode, threshold.hashCode));
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is BlockSkippedSong &&
|
||||
other.enabled == this.enabled &&
|
||||
other.threshold == this.threshold);
|
||||
}
|
||||
|
||||
class BlockSkippedSongsCompanion extends UpdateCompanion<BlockSkippedSong> {
|
||||
final Value<bool> enabled;
|
||||
final Value<int> threshold;
|
||||
const BlockSkippedSongsCompanion({
|
||||
this.enabled = const Value.absent(),
|
||||
this.threshold = const Value.absent(),
|
||||
});
|
||||
BlockSkippedSongsCompanion.insert({
|
||||
this.enabled = const Value.absent(),
|
||||
this.threshold = const Value.absent(),
|
||||
});
|
||||
static Insertable<BlockSkippedSong> custom({
|
||||
Expression<bool>? enabled,
|
||||
Expression<int>? threshold,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (enabled != null) 'enabled': enabled,
|
||||
if (threshold != null) 'threshold': threshold,
|
||||
});
|
||||
}
|
||||
|
||||
BlockSkippedSongsCompanion copyWith(
|
||||
{Value<bool>? enabled, Value<int>? threshold}) {
|
||||
return BlockSkippedSongsCompanion(
|
||||
enabled: enabled ?? this.enabled,
|
||||
threshold: threshold ?? this.threshold,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (enabled.present) {
|
||||
map['enabled'] = Variable<bool>(enabled.value);
|
||||
}
|
||||
if (threshold.present) {
|
||||
map['threshold'] = Variable<int>(threshold.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('BlockSkippedSongsCompanion(')
|
||||
..write('enabled: $enabled, ')
|
||||
..write('threshold: $threshold')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $BlockSkippedSongsTable extends BlockSkippedSongs
|
||||
with TableInfo<$BlockSkippedSongsTable, BlockSkippedSong> {
|
||||
final GeneratedDatabase _db;
|
||||
final String? _alias;
|
||||
$BlockSkippedSongsTable(this._db, [this._alias]);
|
||||
final VerificationMeta _enabledMeta = const VerificationMeta('enabled');
|
||||
@override
|
||||
late final GeneratedBoolColumn enabled = _constructEnabled();
|
||||
GeneratedBoolColumn _constructEnabled() {
|
||||
return GeneratedBoolColumn('enabled', $tableName, false,
|
||||
defaultValue: const Constant(false));
|
||||
}
|
||||
|
||||
final VerificationMeta _thresholdMeta = const VerificationMeta('threshold');
|
||||
@override
|
||||
late final GeneratedIntColumn threshold = _constructThreshold();
|
||||
GeneratedIntColumn _constructThreshold() {
|
||||
return GeneratedIntColumn('threshold', $tableName, false,
|
||||
defaultValue: const Constant(3));
|
||||
}
|
||||
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [enabled, threshold];
|
||||
@override
|
||||
$BlockSkippedSongsTable get asDslTable => this;
|
||||
@override
|
||||
String get $tableName => _alias ?? 'block_skipped_songs';
|
||||
@override
|
||||
final String actualTableName = 'block_skipped_songs';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<BlockSkippedSong> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('enabled')) {
|
||||
context.handle(_enabledMeta,
|
||||
enabled.isAcceptableOrUnknown(data['enabled']!, _enabledMeta));
|
||||
}
|
||||
if (data.containsKey('threshold')) {
|
||||
context.handle(_thresholdMeta,
|
||||
threshold.isAcceptableOrUnknown(data['threshold']!, _thresholdMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => <GeneratedColumn>{};
|
||||
@override
|
||||
BlockSkippedSong map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
return BlockSkippedSong.fromData(data, _db,
|
||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||
}
|
||||
|
||||
@override
|
||||
$BlockSkippedSongsTable createAlias(String alias) {
|
||||
return $BlockSkippedSongsTable(_db, alias);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$MoorDatabase extends GeneratedDatabase {
|
||||
_$MoorDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||
_$MoorDatabase.connect(DatabaseConnection c) : super.connect(c);
|
||||
|
@ -4178,6 +4457,8 @@ abstract class _$MoorDatabase extends GeneratedDatabase {
|
|||
late final $PlaylistsTable playlists = $PlaylistsTable(this);
|
||||
late final $PlaylistEntriesTable playlistEntries =
|
||||
$PlaylistEntriesTable(this);
|
||||
late final $BlockSkippedSongsTable blockSkippedSongs =
|
||||
$BlockSkippedSongsTable(this);
|
||||
late final PersistentStateDao persistentStateDao =
|
||||
PersistentStateDao(this as MoorDatabase);
|
||||
late final SettingsDao settingsDao = SettingsDao(this as MoorDatabase);
|
||||
|
@ -4201,6 +4482,7 @@ abstract class _$MoorDatabase extends GeneratedDatabase {
|
|||
smartLists,
|
||||
smartListArtists,
|
||||
playlists,
|
||||
playlistEntries
|
||||
playlistEntries,
|
||||
blockSkippedSongs
|
||||
];
|
||||
}
|
||||
|
|
|
@ -2,4 +2,9 @@ abstract class SettingsDataSource {
|
|||
Stream<List<String>> get libraryFoldersStream;
|
||||
Future<void> addLibraryFolder(String path);
|
||||
Future<void> removeLibraryFolder(String path);
|
||||
|
||||
Future<void> setBlockSkippedSongs(bool enabled);
|
||||
Stream<bool> get isBlockSkippedSongsEnabled;
|
||||
Future<void> setBlockSkippedSongsThreshold(int threshold);
|
||||
Stream<int> get blockSkippedSongsThreshold;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ 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,
|
||||
excludeBlocked: moorSmartList.excludeBlocked,
|
||||
|
@ -57,6 +59,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),
|
||||
minYear: m.Value(filter.minYear),
|
||||
maxYear: m.Value(filter.maxYear),
|
||||
excludeBlocked: m.Value(filter.excludeBlocked),
|
||||
|
|
|
@ -20,4 +20,20 @@ class SettingsRepositoryImpl implements SettingsRepository {
|
|||
if (path == null) return;
|
||||
await _settingsDataSource.removeLibraryFolder(path);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<int> get blockSkippedSongsThreshold => _settingsDataSource.blockSkippedSongsThreshold;
|
||||
|
||||
@override
|
||||
Stream<bool> get isBlockSkippedSongsEnabled => _settingsDataSource.isBlockSkippedSongsEnabled;
|
||||
|
||||
@override
|
||||
Future<void> setBlockSkippedSongsThreshold(int threshold) async {
|
||||
_settingsDataSource.setBlockSkippedSongsThreshold(threshold);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setBlockSkippedSongs(bool enabled) async {
|
||||
_settingsDataSource.setBlockSkippedSongs(enabled);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue