options for home widgets
This commit is contained in:
parent
ee89a92a73
commit
528306515c
39 changed files with 1739 additions and 184 deletions
29
lib/domain/entities/custom_list.dart
Normal file
29
lib/domain/entities/custom_list.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../presentation/gradients.dart';
|
||||
import '../../presentation/icons.dart';
|
||||
import 'shuffle_mode.dart';
|
||||
|
||||
class CustomList {
|
||||
const CustomList(
|
||||
this.name,
|
||||
this.iconString,
|
||||
this.gradientString,
|
||||
this.shuffleMode,
|
||||
this.timeCreated,
|
||||
this.timeChanged,
|
||||
this.timeLastPlayed,
|
||||
);
|
||||
|
||||
final String name;
|
||||
final String iconString;
|
||||
final String gradientString;
|
||||
final ShuffleMode? shuffleMode;
|
||||
|
||||
final DateTime timeCreated;
|
||||
final DateTime timeChanged;
|
||||
final DateTime timeLastPlayed;
|
||||
|
||||
IconData get icon => CUSTOM_ICONS[iconString]!;
|
||||
Gradient get gradient => CUSTOM_GRADIENTS[gradientString]!;
|
||||
}
|
17
lib/domain/entities/enums.dart
Normal file
17
lib/domain/entities/enums.dart
Normal file
|
@ -0,0 +1,17 @@
|
|||
enum OrderDirection {
|
||||
ascending,
|
||||
descending,
|
||||
}
|
||||
|
||||
extension OrderDirectionExtension on String {
|
||||
OrderDirection? toOrderDirection() {
|
||||
switch (this) {
|
||||
case 'OrderDirection.ascending':
|
||||
return OrderDirection.ascending;
|
||||
case 'OrderDirection.descending':
|
||||
return OrderDirection.descending;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import '../shuffle_mode.dart';
|
|||
import 'home_widget.dart';
|
||||
|
||||
class HomeArtistOfDay implements HomeWidget {
|
||||
HomeArtistOfDay(this.position, this.shuffleMode);
|
||||
HomeArtistOfDay({required this.position, required this.shuffleMode});
|
||||
|
||||
@override
|
||||
HomeWidgetType get type => HomeWidgetType.artist_of_day;
|
||||
|
|
|
@ -1,11 +1,74 @@
|
|||
import '../enums.dart';
|
||||
import 'home_widget.dart';
|
||||
|
||||
class HomePlaylists implements HomeWidget {
|
||||
HomePlaylists(this.position);
|
||||
HomePlaylists({
|
||||
required this.position,
|
||||
this.maxEntries = 3,
|
||||
this.title = 'Your Playlists',
|
||||
this.orderCriterion = HomePlaylistsOrder.name,
|
||||
this.orderDirection = OrderDirection.ascending,
|
||||
this.filter = HomePlaylistsFilter.both,
|
||||
});
|
||||
|
||||
@override
|
||||
HomeWidgetType get type => HomeWidgetType.playlists;
|
||||
|
||||
@override
|
||||
int position;
|
||||
|
||||
final String title;
|
||||
|
||||
final int maxEntries;
|
||||
|
||||
final HomePlaylistsOrder orderCriterion;
|
||||
|
||||
final OrderDirection orderDirection;
|
||||
|
||||
final HomePlaylistsFilter filter;
|
||||
}
|
||||
|
||||
enum HomePlaylistsOrder {
|
||||
name,
|
||||
creationDate,
|
||||
changeDate,
|
||||
history,
|
||||
}
|
||||
|
||||
extension HomePlaylistsOrderExtension on String {
|
||||
HomePlaylistsOrder? toHomePlaylistsOrder() {
|
||||
switch (this) {
|
||||
case 'HomePlaylistsOrder.name':
|
||||
return HomePlaylistsOrder.name;
|
||||
case 'HomePlaylistsOrder.creationDate':
|
||||
return HomePlaylistsOrder.creationDate;
|
||||
case 'HomePlaylistsOrder.changeDate':
|
||||
return HomePlaylistsOrder.changeDate;
|
||||
case 'HomePlaylistsOrder.history':
|
||||
return HomePlaylistsOrder.history;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum HomePlaylistsFilter {
|
||||
both,
|
||||
playlists,
|
||||
smartlists,
|
||||
}
|
||||
|
||||
extension HomePlaylistsFilterExtension on String {
|
||||
HomePlaylistsFilter? toHomePlaylistsFilter() {
|
||||
switch (this) {
|
||||
case 'HomePlaylistsFilter.both':
|
||||
return HomePlaylistsFilter.both;
|
||||
case 'HomePlaylistsFilter.playlists':
|
||||
return HomePlaylistsFilter.playlists;
|
||||
case 'HomePlaylistsFilter.smartlists':
|
||||
return HomePlaylistsFilter.smartlists;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ import '../shuffle_mode.dart';
|
|||
import 'home_widget.dart';
|
||||
|
||||
class HomeShuffleAll implements HomeWidget {
|
||||
HomeShuffleAll(this.position, this.shuffleMode);
|
||||
HomeShuffleAll({required this.position, required this.shuffleMode});
|
||||
|
||||
@override
|
||||
HomeWidgetType get type => HomeWidgetType.shuffle_all;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// TODO: vielleicht soll Playable immer mit einer Songliste kommen?
|
||||
// dann müsste man eventuell neue Klassen definieren, die bspw. Album/Artist beinhalten
|
||||
abstract class Playable {
|
||||
PlayableType get type;
|
||||
}
|
||||
|
|
|
@ -1,30 +1,42 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../presentation/gradients.dart';
|
||||
import '../../presentation/icons.dart';
|
||||
import 'custom_list.dart';
|
||||
import 'playable.dart';
|
||||
import 'shuffle_mode.dart';
|
||||
|
||||
class Playlist extends Equatable implements Playable {
|
||||
class Playlist extends CustomList with EquatableMixin implements Playable {
|
||||
const Playlist({
|
||||
required String name,
|
||||
required String iconString,
|
||||
required String gradientString,
|
||||
required DateTime timeCreated,
|
||||
required DateTime timeChanged,
|
||||
required DateTime timeLastPlayed,
|
||||
ShuffleMode? shuffleMode,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.iconString,
|
||||
required this.gradientString,
|
||||
this.shuffleMode,
|
||||
});
|
||||
}) : super(
|
||||
name,
|
||||
iconString,
|
||||
gradientString,
|
||||
shuffleMode,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed,
|
||||
);
|
||||
|
||||
final int id;
|
||||
final String name;
|
||||
final ShuffleMode? shuffleMode;
|
||||
final String iconString;
|
||||
final String gradientString;
|
||||
IconData get icon => CUSTOM_ICONS[iconString]!;
|
||||
Gradient get gradient => CUSTOM_GRADIENTS[gradientString]!;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [id, name, iconString, gradientString, shuffleMode];
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
name,
|
||||
iconString,
|
||||
gradientString,
|
||||
shuffleMode,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed,
|
||||
];
|
||||
|
||||
@override
|
||||
PlayableType get type => PlayableType.playlist;
|
||||
|
|
|
@ -1,35 +1,49 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../presentation/gradients.dart';
|
||||
import '../../presentation/icons.dart';
|
||||
import 'artist.dart';
|
||||
import 'custom_list.dart';
|
||||
import 'enums.dart';
|
||||
import 'playable.dart';
|
||||
import 'shuffle_mode.dart';
|
||||
|
||||
class SmartList extends Equatable implements Playable {
|
||||
class SmartList extends CustomList with EquatableMixin implements Playable {
|
||||
const SmartList({
|
||||
required String name,
|
||||
required String iconString,
|
||||
required String gradientString,
|
||||
required DateTime timeCreated,
|
||||
required DateTime timeChanged,
|
||||
required DateTime timeLastPlayed,
|
||||
ShuffleMode? shuffleMode,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.filter,
|
||||
required this.orderBy,
|
||||
required this.iconString,
|
||||
required this.gradientString,
|
||||
this.shuffleMode,
|
||||
});
|
||||
}) : super(
|
||||
name,
|
||||
iconString,
|
||||
gradientString,
|
||||
shuffleMode,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed,
|
||||
);
|
||||
|
||||
final int id;
|
||||
final String name;
|
||||
final Filter filter;
|
||||
final OrderBy orderBy;
|
||||
final ShuffleMode? shuffleMode;
|
||||
final String iconString;
|
||||
final String gradientString;
|
||||
IconData get icon => CUSTOM_ICONS[iconString]!;
|
||||
Gradient get gradient => CUSTOM_GRADIENTS[gradientString]!;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [name, filter, orderBy, shuffleMode, icon, gradient];
|
||||
List<Object?> get props => [
|
||||
name,
|
||||
filter,
|
||||
orderBy,
|
||||
shuffleMode,
|
||||
iconString,
|
||||
gradientString,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed,
|
||||
];
|
||||
|
||||
@override
|
||||
PlayableType get type => PlayableType.smartlist;
|
||||
|
@ -129,21 +143,3 @@ extension OrderCriterionExtension on String {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum OrderDirection {
|
||||
ascending,
|
||||
descending,
|
||||
}
|
||||
|
||||
extension OrderDirectionExtension on String {
|
||||
OrderDirection? toOrderDirection() {
|
||||
switch (this) {
|
||||
case 'OrderDirection.ascending':
|
||||
return OrderDirection.ascending;
|
||||
case 'OrderDirection.descending':
|
||||
return OrderDirection.descending;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ import 'package:rxdart/rxdart.dart';
|
|||
|
||||
import '../entities/album.dart';
|
||||
import '../entities/artist.dart';
|
||||
import '../entities/custom_list.dart';
|
||||
import '../entities/enums.dart';
|
||||
import '../entities/home_widgets/playlists.dart';
|
||||
import '../entities/playlist.dart';
|
||||
import '../entities/shuffle_mode.dart';
|
||||
import '../entities/smart_list.dart';
|
||||
|
@ -27,6 +30,13 @@ abstract class MusicDataInfoRepository {
|
|||
Stream<List<SmartList>> get smartListsStream;
|
||||
Stream<SmartList> getSmartListStream(int smartListId);
|
||||
|
||||
Stream<List<CustomList>> getCustomListsStream({
|
||||
HomePlaylistsOrder orderCriterion = HomePlaylistsOrder.name,
|
||||
OrderDirection orderDirection = OrderDirection.ascending,
|
||||
HomePlaylistsFilter filter = HomePlaylistsFilter.both,
|
||||
int? limit,
|
||||
});
|
||||
|
||||
Stream<List<Album>> get albumStream;
|
||||
Stream<List<Album>> getArtistAlbumStream(Artist artist);
|
||||
Future<int?> getAlbumId(String title, String artist, int? year);
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import '../entities/playable.dart';
|
||||
import '../entities/playlist.dart';
|
||||
import '../entities/smart_list.dart';
|
||||
import '../entities/song.dart';
|
||||
import '../repositories/audio_player_repository.dart';
|
||||
import '../repositories/music_data_repository.dart';
|
||||
|
||||
class PlaySongs {
|
||||
PlaySongs(
|
||||
this._audioPlayerRepository,
|
||||
this._musicDataRepository,
|
||||
);
|
||||
|
||||
final AudioPlayerRepository _audioPlayerRepository;
|
||||
final MusicDataRepository _musicDataRepository;
|
||||
|
||||
/// Generate and play a queue from the [songs] according to current AudioPlayer settings.
|
||||
Future<void> call({
|
||||
|
@ -24,6 +29,38 @@ class PlaySongs {
|
|||
keepInitialIndex: keepInitialIndex,
|
||||
);
|
||||
_audioPlayerRepository.play();
|
||||
|
||||
if (playable.type == PlayableType.playlist) {
|
||||
playable as Playlist;
|
||||
_musicDataRepository.updatePlaylist(
|
||||
Playlist(
|
||||
id: playable.id,
|
||||
gradientString: playable.gradientString,
|
||||
iconString: playable.iconString,
|
||||
name: playable.name,
|
||||
timeChanged: playable.timeChanged,
|
||||
timeCreated: playable.timeCreated,
|
||||
timeLastPlayed: DateTime.now(),
|
||||
shuffleMode: playable.shuffleMode,
|
||||
),
|
||||
);
|
||||
} else if (playable.type == PlayableType.smartlist) {
|
||||
playable as SmartList;
|
||||
_musicDataRepository.updateSmartList(
|
||||
SmartList(
|
||||
id: playable.id,
|
||||
gradientString: playable.gradientString,
|
||||
iconString: playable.iconString,
|
||||
name: playable.name,
|
||||
timeChanged: playable.timeChanged,
|
||||
timeCreated: playable.timeCreated,
|
||||
timeLastPlayed: DateTime.now(),
|
||||
filter: playable.filter,
|
||||
orderBy: playable.orderBy,
|
||||
shuffleMode: playable.shuffleMode,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ import 'domain/actors/persistence_actor.dart';
|
|||
import 'domain/actors/platform_integration_actor.dart';
|
||||
import 'domain/entities/album.dart';
|
||||
import 'domain/entities/artist.dart';
|
||||
import 'domain/entities/home_widgets/artist_of_day.dart';
|
||||
import 'domain/entities/home_widgets/playlists.dart';
|
||||
import 'domain/entities/home_widgets/shuffle_all.dart';
|
||||
import 'domain/entities/playlist.dart';
|
||||
import 'domain/entities/smart_list.dart';
|
||||
import 'domain/entities/song.dart';
|
||||
|
@ -30,6 +33,9 @@ import 'presentation/state/album_page_store.dart';
|
|||
import 'presentation/state/artist_page_store.dart';
|
||||
import 'presentation/state/audio_store.dart';
|
||||
import 'presentation/state/home_page_store.dart';
|
||||
import 'presentation/state/home_widget_forms/artistofday_form_store.dart';
|
||||
import 'presentation/state/home_widget_forms/playlists_form_store.dart';
|
||||
import 'presentation/state/home_widget_forms/shuffleall_form_store.dart';
|
||||
import 'presentation/state/music_data_store.dart';
|
||||
import 'presentation/state/navigation_store.dart';
|
||||
import 'presentation/state/play_list_page_store.dart';
|
||||
|
@ -134,6 +140,24 @@ Future<void> setupGetIt() async {
|
|||
musicDataInfoRepository: getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerFactoryParam<PlaylistsFormStore, HomePlaylists, void>(
|
||||
(HomePlaylists playlists, _) => PlaylistsFormStore(
|
||||
homeWidgetRepository: getIt(),
|
||||
homePlaylists: playlists,
|
||||
),
|
||||
);
|
||||
getIt.registerFactoryParam<ShuffleAllFormStore, HomeShuffleAll, void>(
|
||||
(HomeShuffleAll shuffleAll, _) => ShuffleAllFormStore(
|
||||
homeWidgetRepository: getIt(),
|
||||
homeShuffleAll: shuffleAll,
|
||||
),
|
||||
);
|
||||
getIt.registerFactoryParam<ArtistOfDayFormStore, HomeArtistOfDay, void>(
|
||||
(HomeArtistOfDay artistOfDay, _) => ArtistOfDayFormStore(
|
||||
homeWidgetRepository: getIt(),
|
||||
homeArtistOfDay: artistOfDay,
|
||||
),
|
||||
);
|
||||
|
||||
// use cases
|
||||
getIt.registerLazySingleton<PlayAlbum>(
|
||||
|
@ -167,6 +191,7 @@ Future<void> setupGetIt() async {
|
|||
getIt.registerLazySingleton<PlaySongs>(
|
||||
() => PlaySongs(
|
||||
getIt(),
|
||||
getIt(),
|
||||
),
|
||||
);
|
||||
getIt.registerLazySingleton<SeekToNext>(
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:get_it/get_it.dart';
|
|||
|
||||
import '../../domain/entities/home_widgets/artist_of_day.dart';
|
||||
import '../../domain/entities/home_widgets/home_widget.dart';
|
||||
import '../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../domain/entities/home_widgets/shuffle_all.dart';
|
||||
import '../state/home_page_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
|
@ -100,6 +101,6 @@ Widget _createHomeWidget(HomeWidget homeWidget) {
|
|||
),
|
||||
);
|
||||
case HomeWidgetType.playlists:
|
||||
return const SmartLists();
|
||||
return SmartLists(homePlaylists: homeWidget as HomePlaylists);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ import '../state/home_page_store.dart';
|
|||
import '../state/navigation_store.dart';
|
||||
import '../theming.dart';
|
||||
import '../widgets/custom_modal_bottom_sheet.dart';
|
||||
import 'home_widget_forms/artistofday_form_page.dart';
|
||||
import 'home_widget_forms/playlists_form_page.dart';
|
||||
import 'home_widget_forms/shuffle_all_form_page.dart';
|
||||
|
||||
class HomeSettingsPage extends StatelessWidget {
|
||||
const HomeSettingsPage({Key? key}) : super(key: key);
|
||||
|
@ -31,6 +34,13 @@ class HomeSettingsPage extends StatelessWidget {
|
|||
HomeWidgetType.shuffle_all: Icons.shuffle_rounded,
|
||||
};
|
||||
|
||||
static const hasParameters = {
|
||||
HomeWidgetType.album_of_day: false,
|
||||
HomeWidgetType.artist_of_day: true,
|
||||
HomeWidgetType.playlists: true,
|
||||
HomeWidgetType.shuffle_all: true,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final homeStore = GetIt.I<HomePageStore>();
|
||||
|
@ -57,17 +67,6 @@ class HomeSettingsPage extends StatelessWidget {
|
|||
body: Observer(
|
||||
builder: (context) {
|
||||
final widgetEntities = homeStore.homeWidgetsStream.value ?? <HomeWidget>[];
|
||||
final List<Widget> widgets = [
|
||||
const SliverPadding(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
),
|
||||
];
|
||||
|
||||
widgets.add(
|
||||
const SliverPadding(
|
||||
padding: EdgeInsets.only(bottom: 8.0),
|
||||
),
|
||||
);
|
||||
|
||||
return Scrollbar(
|
||||
child: CustomScrollView(
|
||||
|
@ -75,18 +74,86 @@ class HomeSettingsPage extends StatelessWidget {
|
|||
ReorderableSliverList(
|
||||
delegate: ReorderableSliverChildBuilderDelegate(
|
||||
(context, int index) {
|
||||
return ListTile(
|
||||
title: Text(titles[widgetEntities[index].type]!),
|
||||
leading: Icon(icons[widgetEntities[index].type]),
|
||||
trailing: IconButton(
|
||||
onPressed: () => _onTapMore(context, widgetEntities[index]),
|
||||
icon: const Icon(Icons.more_vert_rounded),
|
||||
return Dismissible(
|
||||
key: UniqueKey(),
|
||||
child: ListTile(
|
||||
title: Text(titles[widgetEntities[index].type]!),
|
||||
leading: Icon(icons[widgetEntities[index].type]),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (hasParameters[widgetEntities[index].type]!)
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
switch (widgetEntities[index].type) {
|
||||
case HomeWidgetType.shuffle_all:
|
||||
navStore.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ShuffleAllFormPage(
|
||||
shuffleAll: widgetEntities[index] as HomeShuffleAll,
|
||||
),
|
||||
),
|
||||
);
|
||||
break;
|
||||
case HomeWidgetType.artist_of_day:
|
||||
navStore.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ArtistOfDayFormPage(
|
||||
artistOfDay:
|
||||
widgetEntities[index] as HomeArtistOfDay,
|
||||
),
|
||||
),
|
||||
);
|
||||
break;
|
||||
case HomeWidgetType.playlists:
|
||||
navStore.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PlaylistsFormPage(
|
||||
playlists: widgetEntities[index] as HomePlaylists,
|
||||
),
|
||||
),
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.edit_rounded),
|
||||
),
|
||||
],
|
||||
),
|
||||
contentPadding: const EdgeInsets.fromLTRB(
|
||||
HORIZONTAL_PADDING,
|
||||
8.0,
|
||||
0.0,
|
||||
8.0,
|
||||
),
|
||||
),
|
||||
contentPadding: const EdgeInsets.fromLTRB(
|
||||
HORIZONTAL_PADDING,
|
||||
8.0,
|
||||
0.0,
|
||||
8.0,
|
||||
onDismissed: (direction) {
|
||||
homeStore.removeHomeWidget(widgetEntities[index]);
|
||||
},
|
||||
background: Container(
|
||||
width: double.infinity,
|
||||
color: RED,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.delete_forever_rounded,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(
|
||||
Icons.delete_forever_rounded,
|
||||
color: Colors.white,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -141,54 +208,16 @@ class HomeSettingsPage extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> _onTapMore(BuildContext context, HomeWidget homeWidget) async {
|
||||
final homeStore = GetIt.I<HomePageStore>();
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
builder: (context) => Observer(builder: (context) {
|
||||
return MyBottomSheet(
|
||||
widgets: [
|
||||
ListTile(
|
||||
title: Text(titles[homeWidget.type]!),
|
||||
subtitle: Text(
|
||||
'Position: ${homeWidget.position + 1}',
|
||||
style: TEXT_SMALL_SUBTITLE,
|
||||
),
|
||||
leading: Icon(icons[homeWidget.type]),
|
||||
tileColor: DARK2,
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('Remove widget'),
|
||||
leading: const Icon(
|
||||
Icons.delete_forever_rounded,
|
||||
color: RED,
|
||||
),
|
||||
onTap: () {
|
||||
homeStore.removeHomeWidget(homeWidget);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: replace this with opening a custom bottom sheet for components with parameters
|
||||
HomeWidget _createHomeWidget(HomeWidgetType type, int position) {
|
||||
switch (type) {
|
||||
case HomeWidgetType.shuffle_all:
|
||||
return HomeShuffleAll(position, ShuffleMode.plus);
|
||||
return HomeShuffleAll(position: position, shuffleMode: ShuffleMode.plus);
|
||||
case HomeWidgetType.album_of_day:
|
||||
return HomeAlbumOfDay(position);
|
||||
case HomeWidgetType.artist_of_day:
|
||||
return HomeArtistOfDay(position, ShuffleMode.plus);
|
||||
return HomeArtistOfDay(position: position, shuffleMode: ShuffleMode.plus);
|
||||
case HomeWidgetType.playlists:
|
||||
return HomePlaylists(position);
|
||||
return HomePlaylists(position: position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../../../domain/entities/home_widgets/artist_of_day.dart';
|
||||
import '../../../domain/entities/shuffle_mode.dart';
|
||||
import '../../state/home_widget_forms/artistofday_form_store.dart';
|
||||
import '../../state/navigation_store.dart';
|
||||
import '../../theming.dart';
|
||||
|
||||
class ArtistOfDayFormPage extends StatefulWidget {
|
||||
const ArtistOfDayFormPage({Key? key, required this.artistOfDay}) : super(key: key);
|
||||
|
||||
final HomeArtistOfDay artistOfDay;
|
||||
|
||||
@override
|
||||
_ArtistOfDayFormPageState createState() => _ArtistOfDayFormPageState();
|
||||
}
|
||||
|
||||
class _ArtistOfDayFormPageState extends State<ArtistOfDayFormPage> {
|
||||
late ArtistOfDayFormStore store;
|
||||
|
||||
static const CARD_PADDING = 8.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
store = GetIt.I<ArtistOfDayFormStore>(param1: widget.artistOfDay);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NavigationStore navStore = GetIt.I<NavigationStore>();
|
||||
|
||||
const playbackModeTexts = <String>[
|
||||
'Normal Mode',
|
||||
'Shuffle Mode',
|
||||
'Favorite Shuffle Mode',
|
||||
];
|
||||
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
'Edit Artist of the Day Widget',
|
||||
style: TEXT_HEADER,
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
onPressed: () => navStore.pop(context),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_rounded),
|
||||
onPressed: () async {
|
||||
// TODO: this works, but may only pop back to the smart list page...
|
||||
// can I use pop 2x here?
|
||||
// await musicDataStore.removePlaylist(widget.playlist!);
|
||||
navStore.pop(context);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.check_rounded),
|
||||
onPressed: () async {
|
||||
// store.validateAll();
|
||||
// if (!store.error.hasErrors) {
|
||||
await store.save();
|
||||
navStore.pop(context);
|
||||
// }
|
||||
},
|
||||
),
|
||||
],
|
||||
titleSpacing: 0.0,
|
||||
),
|
||||
body: ListTileTheme(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Scrollbar(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
const SizedBox(height: 16.0),
|
||||
const ListTile(
|
||||
title: Text('Playback Settings', style: TEXT_HEADER),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: CARD_PADDING,
|
||||
),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Column(
|
||||
children: <int>[0, 1, 2].map<RadioListTile<int>>(
|
||||
(int value) {
|
||||
return RadioListTile<int>(
|
||||
title: Text(
|
||||
playbackModeTexts[value],
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
value: value,
|
||||
groupValue: store.shuffleMode.index,
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
if (newValue != null) store.shuffleMode = ShuffleMode.values[newValue];
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../../../domain/entities/enums.dart';
|
||||
import '../../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../state/home_widget_forms/playlists_form_store.dart';
|
||||
import '../../state/navigation_store.dart';
|
||||
import '../../theming.dart';
|
||||
import '../../widgets/switch_text_listtile.dart';
|
||||
|
||||
class PlaylistsFormPage extends StatefulWidget {
|
||||
const PlaylistsFormPage({Key? key, required this.playlists}) : super(key: key);
|
||||
|
||||
final HomePlaylists playlists;
|
||||
|
||||
@override
|
||||
_PlaylistsFormPageState createState() => _PlaylistsFormPageState();
|
||||
}
|
||||
|
||||
class _PlaylistsFormPageState extends State<PlaylistsFormPage> {
|
||||
late PlaylistsFormStore store;
|
||||
|
||||
static const CARD_PADDING = 8.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
store = GetIt.I<PlaylistsFormStore>(param1: widget.playlists);
|
||||
super.initState();
|
||||
// store.setupValidations();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// store.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NavigationStore navStore = GetIt.I<NavigationStore>();
|
||||
|
||||
const orderCriterionTexts = <String>[
|
||||
'Name',
|
||||
'Creation Date',
|
||||
'Change Date',
|
||||
'Last Time Played',
|
||||
];
|
||||
|
||||
const orderDirectionTexts = <String>[
|
||||
'Ascending',
|
||||
'Descending',
|
||||
];
|
||||
|
||||
const filterTexts = <String>[
|
||||
'Both',
|
||||
'Playlists Only',
|
||||
'Smart Lists Only',
|
||||
];
|
||||
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
'Edit Playlists Widget',
|
||||
style: TEXT_HEADER,
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
onPressed: () => navStore.pop(context),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_rounded),
|
||||
onPressed: () async {
|
||||
// TODO: this works, but may only pop back to the smart list page...
|
||||
// can I use pop 2x here?
|
||||
// await musicDataStore.removePlaylist(widget.playlist!);
|
||||
navStore.pop(context);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.check_rounded),
|
||||
onPressed: () async {
|
||||
// store.validateAll();
|
||||
// if (!store.error.hasErrors) {
|
||||
await store.save();
|
||||
navStore.pop(context);
|
||||
// }
|
||||
},
|
||||
),
|
||||
],
|
||||
titleSpacing: 0.0,
|
||||
),
|
||||
body: ListTileTheme(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Scrollbar(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
const SizedBox(height: 16.0),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
child: Observer(
|
||||
builder: (_) => TextFormField(
|
||||
initialValue: store.title,
|
||||
onChanged: (value) => store.title = value,
|
||||
style: TEXT_HEADER,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Name',
|
||||
labelStyle: const TextStyle(color: Colors.white),
|
||||
floatingLabelStyle: TEXT_HEADER_S.copyWith(color: Colors.white),
|
||||
// errorText: store.error.name,
|
||||
errorStyle: const TextStyle(color: RED),
|
||||
filled: true,
|
||||
fillColor: DARK35,
|
||||
border: const OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.all(Radius.circular(4.0)),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 4.0,
|
||||
horizontal: 12.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
const ListTile(
|
||||
title: Text('Sorting and Filter Settings', style: TEXT_HEADER),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: CARD_PADDING,
|
||||
),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return SwitchTextListTile(
|
||||
title: 'Maximum number of entries',
|
||||
switchValue: store.maxEntriesEnabled,
|
||||
onSwitchChanged: (bool value) {
|
||||
store.maxEntriesEnabled = value;
|
||||
},
|
||||
textValue: store.maxEntries,
|
||||
onTextChanged: (String value) {
|
||||
store.maxEntries = value;
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: CARD_PADDING,
|
||||
),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Column(
|
||||
children: <int>[0, 1, 2, 3].map<RadioListTile<int>>((int value) {
|
||||
return RadioListTile<int>(
|
||||
title: Text(
|
||||
orderCriterionTexts[value],
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
value: value,
|
||||
groupValue: store.orderCriterion.index,
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
if (newValue != null)
|
||||
store.orderCriterion =
|
||||
HomePlaylistsOrder.values[newValue];
|
||||
});
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: CARD_PADDING,
|
||||
),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Column(
|
||||
children: <int>[0, 1].map<RadioListTile<int>>((int value) {
|
||||
return RadioListTile<int>(
|
||||
title: Text(
|
||||
orderDirectionTexts[value],
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
value: value,
|
||||
groupValue: store.orderDirection.index,
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
if (newValue != null)
|
||||
store.orderDirection = OrderDirection.values[newValue];
|
||||
});
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: CARD_PADDING,
|
||||
),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Column(
|
||||
children: <int>[0, 1, 2].map<RadioListTile<int>>((int value) {
|
||||
return RadioListTile<int>(
|
||||
title: Text(
|
||||
filterTexts[value],
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
value: value,
|
||||
groupValue: store.filter.index,
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
if (newValue != null)
|
||||
store.filter = HomePlaylistsFilter.values[newValue];
|
||||
});
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../../../domain/entities/home_widgets/shuffle_all.dart';
|
||||
import '../../../domain/entities/shuffle_mode.dart';
|
||||
import '../../state/home_widget_forms/shuffleall_form_store.dart';
|
||||
import '../../state/navigation_store.dart';
|
||||
import '../../theming.dart';
|
||||
|
||||
class ShuffleAllFormPage extends StatefulWidget {
|
||||
const ShuffleAllFormPage({Key? key, required this.shuffleAll}) : super(key: key);
|
||||
|
||||
final HomeShuffleAll shuffleAll;
|
||||
|
||||
@override
|
||||
_ShuffleAllFormPageState createState() => _ShuffleAllFormPageState();
|
||||
}
|
||||
|
||||
class _ShuffleAllFormPageState extends State<ShuffleAllFormPage> {
|
||||
late ShuffleAllFormStore store;
|
||||
|
||||
static const CARD_PADDING = 8.0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
store = GetIt.I<ShuffleAllFormStore>(param1: widget.shuffleAll);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NavigationStore navStore = GetIt.I<NavigationStore>();
|
||||
|
||||
const playbackModeTexts = <String>[
|
||||
'Normal Mode',
|
||||
'Shuffle Mode',
|
||||
'Favorite Shuffle Mode',
|
||||
];
|
||||
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
'Edit Shuffle All Widget',
|
||||
style: TEXT_HEADER,
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
onPressed: () => navStore.pop(context),
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete_rounded),
|
||||
onPressed: () async {
|
||||
// TODO: this works, but may only pop back to the smart list page...
|
||||
// can I use pop 2x here?
|
||||
// await musicDataStore.removePlaylist(widget.playlist!);
|
||||
navStore.pop(context);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.check_rounded),
|
||||
onPressed: () async {
|
||||
// store.validateAll();
|
||||
// if (!store.error.hasErrors) {
|
||||
await store.save();
|
||||
navStore.pop(context);
|
||||
// }
|
||||
},
|
||||
),
|
||||
],
|
||||
titleSpacing: 0.0,
|
||||
),
|
||||
body: ListTileTheme(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Scrollbar(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
const SizedBox(height: 16.0),
|
||||
const ListTile(
|
||||
title: Text('Playback Settings', style: TEXT_HEADER),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: CARD_PADDING,
|
||||
),
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return Column(
|
||||
children: <int>[1, 2].map<RadioListTile<int>>(
|
||||
(int value) {
|
||||
return RadioListTile<int>(
|
||||
title: Text(
|
||||
playbackModeTexts[value],
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
),
|
||||
),
|
||||
value: value,
|
||||
groupValue: store.shuffleMode.index,
|
||||
onChanged: (int? newValue) {
|
||||
setState(() {
|
||||
if (newValue != null) store.shuffleMode = ShuffleMode.values[newValue];
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -39,7 +39,7 @@ class _PlaylistFormPageState extends State<PlaylistFormPage> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final title = widget.playlist == null ? 'Create smart list' : 'Edit smart list';
|
||||
final title = widget.playlist == null ? 'Create Playlist' : 'Edit Playlist';
|
||||
final NavigationStore navStore = GetIt.I<NavigationStore>();
|
||||
final MusicDataStore musicDataStore = GetIt.I<MusicDataStore>();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import '../state/audio_store.dart';
|
|||
import '../state/music_data_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
import '../state/play_list_page_store.dart';
|
||||
import '../theming.dart';
|
||||
import '../utils.dart' as utils;
|
||||
import '../widgets/bottom_sheet/add_to_playlist.dart';
|
||||
import '../widgets/bottom_sheet/remove_from_playlist.dart';
|
||||
|
@ -216,6 +217,28 @@ class _PlaylistPageState extends State<PlaylistPage> {
|
|||
onDismissed: (direction) {
|
||||
musicDataStore.removePlaylistEntry(playlist.id, index);
|
||||
},
|
||||
background: Container(
|
||||
width: double.infinity,
|
||||
color: RED,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: HORIZONTAL_PADDING,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.playlist_remove_rounded,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(
|
||||
Icons.playlist_remove_rounded,
|
||||
color: Colors.white,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
childCount: songs.length,
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:get_it/get_it.dart';
|
|||
import 'package:reorderables/reorderables.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../domain/entities/enums.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
import '../state/music_data_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
|
||||
import '../../../domain/entities/home_widgets/artist_of_day.dart';
|
||||
import '../../../domain/entities/shuffle_mode.dart';
|
||||
import '../../../domain/repositories/home_widget_repository.dart';
|
||||
|
||||
part 'artistofday_form_store.g.dart';
|
||||
|
||||
class ArtistOfDayFormStore extends _ArtistOfDayFormStore with _$ArtistOfDayFormStore {
|
||||
ArtistOfDayFormStore({
|
||||
required HomeWidgetRepository homeWidgetRepository,
|
||||
required HomeArtistOfDay homeArtistOfDay,
|
||||
}) : super(homeWidgetRepository, homeArtistOfDay);
|
||||
}
|
||||
|
||||
abstract class _ArtistOfDayFormStore with Store {
|
||||
_ArtistOfDayFormStore(
|
||||
this._homeWidgetRepository,
|
||||
this._shuffleAll,
|
||||
);
|
||||
|
||||
final HomeWidgetRepository _homeWidgetRepository;
|
||||
|
||||
final HomeArtistOfDay _shuffleAll;
|
||||
|
||||
@observable
|
||||
late ShuffleMode shuffleMode = _shuffleAll.shuffleMode;
|
||||
|
||||
Future<void> save() async {
|
||||
_homeWidgetRepository.updateHomeWidget(
|
||||
HomeArtistOfDay(
|
||||
position: _shuffleAll.position,
|
||||
shuffleMode: shuffleMode,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'artistofday_form_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, no_leading_underscores_for_local_identifiers
|
||||
|
||||
mixin _$ArtistOfDayFormStore on _ArtistOfDayFormStore, Store {
|
||||
late final _$shuffleModeAtom =
|
||||
Atom(name: '_ArtistOfDayFormStore.shuffleMode', context: context);
|
||||
|
||||
@override
|
||||
ShuffleMode get shuffleMode {
|
||||
_$shuffleModeAtom.reportRead();
|
||||
return super.shuffleMode;
|
||||
}
|
||||
|
||||
@override
|
||||
set shuffleMode(ShuffleMode value) {
|
||||
_$shuffleModeAtom.reportWrite(value, super.shuffleMode, () {
|
||||
super.shuffleMode = value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
shuffleMode: ${shuffleMode}
|
||||
''';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
|
||||
import '../../../domain/entities/enums.dart';
|
||||
import '../../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../../domain/repositories/home_widget_repository.dart';
|
||||
|
||||
part 'playlists_form_store.g.dart';
|
||||
|
||||
class PlaylistsFormStore extends _PlaylistsFormStore with _$PlaylistsFormStore {
|
||||
PlaylistsFormStore({
|
||||
required HomeWidgetRepository homeWidgetRepository,
|
||||
required HomePlaylists homePlaylists,
|
||||
}) : super(homeWidgetRepository, homePlaylists);
|
||||
}
|
||||
|
||||
abstract class _PlaylistsFormStore with Store {
|
||||
_PlaylistsFormStore(
|
||||
this._homeWidgetRepository,
|
||||
this._playlists,
|
||||
);
|
||||
|
||||
final HomeWidgetRepository _homeWidgetRepository;
|
||||
|
||||
final HomePlaylists _playlists;
|
||||
|
||||
@observable
|
||||
late String title = _playlists.title;
|
||||
|
||||
@observable
|
||||
late String maxEntries = _intToString(_playlists.maxEntries > 0 ? _playlists.maxEntries : 3);
|
||||
|
||||
@observable
|
||||
late bool maxEntriesEnabled = _playlists.maxEntries > 0;
|
||||
|
||||
@observable
|
||||
late HomePlaylistsOrder orderCriterion = _playlists.orderCriterion;
|
||||
|
||||
@observable
|
||||
late OrderDirection orderDirection = _playlists.orderDirection;
|
||||
|
||||
@observable
|
||||
late HomePlaylistsFilter filter = _playlists.filter;
|
||||
|
||||
Future<void> save() async {
|
||||
int maxEntriesInt = int.parse(maxEntries);
|
||||
if (!maxEntriesEnabled || maxEntriesInt < 1) {
|
||||
maxEntriesInt = 0;
|
||||
}
|
||||
|
||||
_homeWidgetRepository.updateHomeWidget(
|
||||
HomePlaylists(
|
||||
position: _playlists.position,
|
||||
title: title,
|
||||
maxEntries: maxEntriesInt,
|
||||
orderCriterion: orderCriterion,
|
||||
orderDirection: orderDirection,
|
||||
filter: filter,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _intToString(int? number) {
|
||||
if (number == null) return '0';
|
||||
return number.toString();
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'playlists_form_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, no_leading_underscores_for_local_identifiers
|
||||
|
||||
mixin _$PlaylistsFormStore on _PlaylistsFormStore, Store {
|
||||
late final _$titleAtom =
|
||||
Atom(name: '_PlaylistsFormStore.title', context: context);
|
||||
|
||||
@override
|
||||
String get title {
|
||||
_$titleAtom.reportRead();
|
||||
return super.title;
|
||||
}
|
||||
|
||||
@override
|
||||
set title(String value) {
|
||||
_$titleAtom.reportWrite(value, super.title, () {
|
||||
super.title = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$maxEntriesAtom =
|
||||
Atom(name: '_PlaylistsFormStore.maxEntries', context: context);
|
||||
|
||||
@override
|
||||
String get maxEntries {
|
||||
_$maxEntriesAtom.reportRead();
|
||||
return super.maxEntries;
|
||||
}
|
||||
|
||||
@override
|
||||
set maxEntries(String value) {
|
||||
_$maxEntriesAtom.reportWrite(value, super.maxEntries, () {
|
||||
super.maxEntries = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$maxEntriesEnabledAtom =
|
||||
Atom(name: '_PlaylistsFormStore.maxEntriesEnabled', context: context);
|
||||
|
||||
@override
|
||||
bool get maxEntriesEnabled {
|
||||
_$maxEntriesEnabledAtom.reportRead();
|
||||
return super.maxEntriesEnabled;
|
||||
}
|
||||
|
||||
@override
|
||||
set maxEntriesEnabled(bool value) {
|
||||
_$maxEntriesEnabledAtom.reportWrite(value, super.maxEntriesEnabled, () {
|
||||
super.maxEntriesEnabled = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$orderCriterionAtom =
|
||||
Atom(name: '_PlaylistsFormStore.orderCriterion', context: context);
|
||||
|
||||
@override
|
||||
HomePlaylistsOrder get orderCriterion {
|
||||
_$orderCriterionAtom.reportRead();
|
||||
return super.orderCriterion;
|
||||
}
|
||||
|
||||
@override
|
||||
set orderCriterion(HomePlaylistsOrder value) {
|
||||
_$orderCriterionAtom.reportWrite(value, super.orderCriterion, () {
|
||||
super.orderCriterion = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$orderDirectionAtom =
|
||||
Atom(name: '_PlaylistsFormStore.orderDirection', context: context);
|
||||
|
||||
@override
|
||||
OrderDirection get orderDirection {
|
||||
_$orderDirectionAtom.reportRead();
|
||||
return super.orderDirection;
|
||||
}
|
||||
|
||||
@override
|
||||
set orderDirection(OrderDirection value) {
|
||||
_$orderDirectionAtom.reportWrite(value, super.orderDirection, () {
|
||||
super.orderDirection = value;
|
||||
});
|
||||
}
|
||||
|
||||
late final _$filterAtom =
|
||||
Atom(name: '_PlaylistsFormStore.filter', context: context);
|
||||
|
||||
@override
|
||||
HomePlaylistsFilter get filter {
|
||||
_$filterAtom.reportRead();
|
||||
return super.filter;
|
||||
}
|
||||
|
||||
@override
|
||||
set filter(HomePlaylistsFilter value) {
|
||||
_$filterAtom.reportWrite(value, super.filter, () {
|
||||
super.filter = value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
title: ${title},
|
||||
maxEntries: ${maxEntries},
|
||||
maxEntriesEnabled: ${maxEntriesEnabled},
|
||||
orderCriterion: ${orderCriterion},
|
||||
orderDirection: ${orderDirection},
|
||||
filter: ${filter}
|
||||
''';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
|
||||
import '../../../domain/entities/home_widgets/shuffle_all.dart';
|
||||
import '../../../domain/entities/shuffle_mode.dart';
|
||||
import '../../../domain/repositories/home_widget_repository.dart';
|
||||
|
||||
part 'shuffleall_form_store.g.dart';
|
||||
|
||||
class ShuffleAllFormStore extends _ShuffleAllFormStore with _$ShuffleAllFormStore {
|
||||
ShuffleAllFormStore({
|
||||
required HomeWidgetRepository homeWidgetRepository,
|
||||
required HomeShuffleAll homeShuffleAll,
|
||||
}) : super(homeWidgetRepository, homeShuffleAll);
|
||||
}
|
||||
|
||||
abstract class _ShuffleAllFormStore with Store {
|
||||
_ShuffleAllFormStore(
|
||||
this._homeWidgetRepository,
|
||||
this._shuffleAll,
|
||||
);
|
||||
|
||||
final HomeWidgetRepository _homeWidgetRepository;
|
||||
|
||||
final HomeShuffleAll _shuffleAll;
|
||||
|
||||
@observable
|
||||
late ShuffleMode shuffleMode = _shuffleAll.shuffleMode;
|
||||
|
||||
Future<void> save() async {
|
||||
_homeWidgetRepository.updateHomeWidget(
|
||||
HomeShuffleAll(
|
||||
position: _shuffleAll.position,
|
||||
shuffleMode: shuffleMode,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'shuffleall_form_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, no_leading_underscores_for_local_identifiers
|
||||
|
||||
mixin _$ShuffleAllFormStore on _ShuffleAllFormStore, Store {
|
||||
late final _$shuffleModeAtom =
|
||||
Atom(name: '_ShuffleAllFormStore.shuffleMode', context: context);
|
||||
|
||||
@override
|
||||
ShuffleMode get shuffleMode {
|
||||
_$shuffleModeAtom.reportRead();
|
||||
return super.shuffleMode;
|
||||
}
|
||||
|
||||
@override
|
||||
set shuffleMode(ShuffleMode value) {
|
||||
_$shuffleModeAtom.reportWrite(value, super.shuffleMode, () {
|
||||
super.shuffleMode = value;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''
|
||||
shuffleMode: ${shuffleMode}
|
||||
''';
|
||||
}
|
||||
}
|
|
@ -2,6 +2,9 @@ import 'package:mobx/mobx.dart';
|
|||
|
||||
import '../../domain/entities/album.dart';
|
||||
import '../../domain/entities/artist.dart';
|
||||
import '../../domain/entities/custom_list.dart';
|
||||
import '../../domain/entities/enums.dart';
|
||||
import '../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../domain/entities/playlist.dart';
|
||||
import '../../domain/entities/shuffle_mode.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
|
@ -61,6 +64,22 @@ abstract class _MusicDataStore with Store {
|
|||
late ObservableStream<Artist?> artistOfDay =
|
||||
_musicDataRepository.artistOfDayStream.asObservable();
|
||||
|
||||
ObservableStream<List<CustomList>> getCustomLists({
|
||||
required HomePlaylistsOrder orderCriterion,
|
||||
required OrderDirection orderDirection,
|
||||
required HomePlaylistsFilter filter,
|
||||
int? limit,
|
||||
}) {
|
||||
return _musicDataRepository
|
||||
.getCustomListsStream(
|
||||
orderCriterion: orderCriterion,
|
||||
orderDirection: orderDirection,
|
||||
filter: filter,
|
||||
limit: limit,
|
||||
)
|
||||
.asObservable();
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> updateDatabase() async {
|
||||
isUpdatingDatabase = true;
|
||||
|
|
|
@ -91,6 +91,9 @@ abstract class _PlaylistStore with Store {
|
|||
iconString: cover.iconString,
|
||||
gradientString: cover.gradientString,
|
||||
shuffleMode: shuffleMode,
|
||||
timeChanged: DateTime.now(),
|
||||
timeCreated: _playlist!.timeCreated,
|
||||
timeLastPlayed: _playlist!.timeLastPlayed,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -106,7 +109,6 @@ abstract class _FormErrorState with Store {
|
|||
bool get hasErrors => name != null;
|
||||
}
|
||||
|
||||
|
||||
int _shuffleModeIndex(ShuffleMode? shuffleMode) {
|
||||
if (shuffleMode == null) return 0;
|
||||
switch (shuffleMode) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:mobx/mobx.dart';
|
|||
|
||||
import '../../constants.dart';
|
||||
import '../../domain/entities/artist.dart';
|
||||
import '../../domain/entities/enums.dart';
|
||||
import '../../domain/entities/shuffle_mode.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
import '../../domain/repositories/music_data_repository.dart';
|
||||
|
@ -240,6 +241,9 @@ abstract class _SmartListStore with Store {
|
|||
name: name ?? 'This needs a name',
|
||||
iconString: cover.iconString,
|
||||
gradientString: cover.gradientString,
|
||||
timeChanged: DateTime.now(),
|
||||
timeCreated: _smartList!.timeCreated,
|
||||
timeLastPlayed: _smartList!.timeLastPlayed,
|
||||
shuffleMode: shuffleMode,
|
||||
filter: Filter(
|
||||
artists: selectedArtists.toList(),
|
||||
|
|
|
@ -2,7 +2,11 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../../domain/entities/custom_list.dart';
|
||||
import '../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../domain/entities/playlist.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
import '../pages/playlist_page.dart';
|
||||
import '../pages/smart_list_page.dart';
|
||||
import '../state/audio_store.dart';
|
||||
import '../state/music_data_store.dart';
|
||||
|
@ -11,7 +15,9 @@ import 'play_shuffle_button.dart';
|
|||
import 'playlist_cover.dart';
|
||||
|
||||
class SmartLists extends StatelessWidget {
|
||||
const SmartLists({Key? key}) : super(key: key);
|
||||
const SmartLists({Key? key, required this.homePlaylists}) : super(key: key);
|
||||
|
||||
final HomePlaylists homePlaylists;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -19,24 +25,40 @@ class SmartLists extends StatelessWidget {
|
|||
final NavigationStore navStore = GetIt.I<NavigationStore>();
|
||||
final MusicDataStore musicDataStore = GetIt.I<MusicDataStore>();
|
||||
|
||||
final customListsStream = musicDataStore.getCustomLists(
|
||||
orderCriterion: homePlaylists.orderCriterion,
|
||||
orderDirection: homePlaylists.orderDirection,
|
||||
filter: homePlaylists.filter,
|
||||
limit: homePlaylists.maxEntries,
|
||||
);
|
||||
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
final smartLists = musicDataStore.smartListsStream.value ?? [];
|
||||
final customLists = customListsStream.value ?? [];
|
||||
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(_, int index) {
|
||||
|
||||
if (index % 2 == 1) {
|
||||
return const SizedBox(height: 12.0);
|
||||
}
|
||||
|
||||
final SmartList smartList = smartLists[index ~/ 2];
|
||||
final CustomList customList = customLists[index ~/ 2];
|
||||
return GestureDetector(
|
||||
onTap: () => navStore.pushOnLibrary(
|
||||
MaterialPageRoute<Widget>(
|
||||
builder: (context) => SmartListPage(smartList: smartList),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
if (customList is SmartList)
|
||||
navStore.pushOnLibrary(
|
||||
MaterialPageRoute<Widget>(
|
||||
builder: (context) => SmartListPage(smartList: customList),
|
||||
),
|
||||
);
|
||||
else if (customList is Playlist)
|
||||
navStore.pushOnLibrary(
|
||||
MaterialPageRoute<Widget>(
|
||||
builder: (context) => PlaylistPage(playlist: customList),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
|
@ -59,8 +81,8 @@ class SmartLists extends StatelessWidget {
|
|||
children: [
|
||||
PlaylistCover(
|
||||
size: 48,
|
||||
gradient: smartList.gradient,
|
||||
icon: smartList.icon,
|
||||
gradient: customList.gradient,
|
||||
icon: customList.icon,
|
||||
shadows: const [
|
||||
BoxShadow(
|
||||
color: Colors.black54,
|
||||
|
@ -72,7 +94,7 @@ class SmartLists extends StatelessWidget {
|
|||
const SizedBox(width: 16.0),
|
||||
Expanded(
|
||||
child: Text(
|
||||
smartList.name,
|
||||
customList.name,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -80,8 +102,12 @@ class SmartLists extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(width: 8.0),
|
||||
PlayShuffleButton(
|
||||
onPressed: () => audioStore.playSmartList(smartList),
|
||||
shuffleMode: smartList.shuffleMode,
|
||||
onPressed: () {
|
||||
if (customList is SmartList)
|
||||
audioStore.playSmartList(customList);
|
||||
else if (customList is Playlist) audioStore.playPlaylist(customList);
|
||||
},
|
||||
shuffleMode: customList.shuffleMode,
|
||||
size: 48.0,
|
||||
),
|
||||
],
|
||||
|
@ -91,7 +117,7 @@ class SmartLists extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
},
|
||||
childCount: smartLists.length * 2 - 1,
|
||||
childCount: customLists.length * 2 - 1,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -67,9 +67,9 @@ class HomeWidgetDao extends DatabaseAccessor<MoorDatabase>
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> updateHomeWidget(HomeWidgetModel homeWidget) {
|
||||
// TODO: implement updateHomeWidget
|
||||
throw UnimplementedError();
|
||||
Future<void> updateHomeWidget(HomeWidgetModel homeWidget) async {
|
||||
await (update(homeWidgets)..where((tbl) => tbl.position.equals(homeWidget.position)))
|
||||
.write(homeWidget.toMoor());
|
||||
}
|
||||
|
||||
HomeWidgetModel _getHomeWidget(MoorHomeWidget moorHomeWidget) {
|
||||
|
|
|
@ -37,6 +37,9 @@ class PlaylistDao extends DatabaseAccessor<MoorDatabase>
|
|||
i++;
|
||||
}
|
||||
|
||||
await (update(playlists)..where((tbl) => tbl.id.equals(playlist.id)))
|
||||
.write(PlaylistsCompanion(timeChanged: Value(DateTime.now())));
|
||||
|
||||
await batch((batch) {
|
||||
batch.insertAll(playlistEntries, entries);
|
||||
});
|
||||
|
@ -121,6 +124,9 @@ class PlaylistDao extends DatabaseAccessor<MoorDatabase>
|
|||
await (update(playlistEntries)
|
||||
..where((tbl) => tbl.position.equals(-1) & tbl.playlistId.equals(playlistId)))
|
||||
.write(PlaylistEntriesCompanion(position: Value(newIndex)));
|
||||
|
||||
await (update(playlists)..where((tbl) => tbl.id.equals(playlistId)))
|
||||
.write(PlaylistsCompanion(timeChanged: Value(DateTime.now())));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +146,9 @@ class PlaylistDao extends DatabaseAccessor<MoorDatabase>
|
|||
..where((tbl) => tbl.position.equals(i) & tbl.playlistId.equals(playlistId)))
|
||||
.write(PlaylistEntriesCompanion(position: Value(i - 1)));
|
||||
}
|
||||
|
||||
await (update(playlists)..where((tbl) => tbl.id.equals(playlistId)))
|
||||
.write(PlaylistsCompanion(timeChanged: Value(DateTime.now())));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,10 @@ class SmartLists extends Table {
|
|||
TextColumn get shuffleMode => text().nullable()();
|
||||
TextColumn get icon => text().withDefault(const Constant('auto_awesome_rounded'))();
|
||||
TextColumn get gradient => text().withDefault(const Constant('sanguine'))();
|
||||
DateTimeColumn get timeCreated => dateTime().withDefault(currentDateAndTime)();
|
||||
DateTimeColumn get timeChanged => dateTime().withDefault(currentDateAndTime)();
|
||||
DateTimeColumn get timeLastPlayed =>
|
||||
dateTime().withDefault(Constant(DateTime.fromMillisecondsSinceEpoch(0)))();
|
||||
|
||||
// Filter
|
||||
BoolColumn get excludeArtists => boolean().withDefault(const Constant(false))();
|
||||
|
@ -144,6 +148,10 @@ class Playlists extends Table {
|
|||
TextColumn get shuffleMode => text().nullable()();
|
||||
TextColumn get icon => text().withDefault(const Constant('queue_music_rounded'))();
|
||||
TextColumn get gradient => text().withDefault(const Constant('oceanblue'))();
|
||||
DateTimeColumn get timeCreated => dateTime().withDefault(currentDateAndTime)();
|
||||
DateTimeColumn get timeChanged => dateTime().withDefault(currentDateAndTime)();
|
||||
DateTimeColumn get timeLastPlayed =>
|
||||
dateTime().withDefault(Constant(DateTime.fromMillisecondsSinceEpoch(0)))();
|
||||
}
|
||||
|
||||
@DataClassName('MoorPlaylistEntry')
|
||||
|
@ -197,7 +205,7 @@ class MoorDatabase extends _$MoorDatabase {
|
|||
MoorDatabase.connect(DatabaseConnection connection) : super.connect(connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 8;
|
||||
int get schemaVersion => 9;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
|
@ -244,10 +252,18 @@ class MoorDatabase extends _$MoorDatabase {
|
|||
),
|
||||
);
|
||||
await into(homeWidgets).insert(
|
||||
const HomeWidgetsCompanion(
|
||||
position: Value(3),
|
||||
type: Value('HomeWidgetType.playlists'),
|
||||
data: Value('{}'),
|
||||
HomeWidgetsCompanion(
|
||||
position: const Value(3),
|
||||
type: const Value('HomeWidgetType.playlists'),
|
||||
data: Value(
|
||||
json.encode({
|
||||
'title': 'Your Playlists',
|
||||
'maxEntries': 3,
|
||||
'orderCriterion': 'HomePlaylistsOrder.name',
|
||||
'orderDirection': 'OrderDirection.ascending',
|
||||
'filter': 'HomePlaylistsFilter.both',
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -323,6 +339,19 @@ class MoorDatabase extends _$MoorDatabase {
|
|||
),
|
||||
);
|
||||
}
|
||||
if (from < 9) {
|
||||
final now = DateTime.now();
|
||||
await m.addColumn(smartLists, smartLists.timeLastPlayed);
|
||||
await m.alterTable(TableMigration(smartLists, columnTransformer: {
|
||||
smartLists.timeChanged: Constant(now),
|
||||
smartLists.timeCreated: Constant(now),
|
||||
}));
|
||||
await m.addColumn(playlists, playlists.timeLastPlayed);
|
||||
await m.alterTable(TableMigration(playlists, columnTransformer: {
|
||||
playlists.timeChanged: Constant(now),
|
||||
playlists.timeCreated: Constant(now),
|
||||
}));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2024,6 +2024,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
final String? shuffleMode;
|
||||
final String icon;
|
||||
final String gradient;
|
||||
final DateTime timeCreated;
|
||||
final DateTime timeChanged;
|
||||
final DateTime timeLastPlayed;
|
||||
final bool excludeArtists;
|
||||
final int blockLevel;
|
||||
final int minLikeCount;
|
||||
|
@ -2043,6 +2046,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
this.shuffleMode,
|
||||
required this.icon,
|
||||
required this.gradient,
|
||||
required this.timeCreated,
|
||||
required this.timeChanged,
|
||||
required this.timeLastPlayed,
|
||||
required this.excludeArtists,
|
||||
required this.blockLevel,
|
||||
required this.minLikeCount,
|
||||
|
@ -2069,6 +2075,12 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
.mapFromDatabaseResponse(data['${effectivePrefix}icon'])!,
|
||||
gradient: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}gradient'])!,
|
||||
timeCreated: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}time_created'])!,
|
||||
timeChanged: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}time_changed'])!,
|
||||
timeLastPlayed: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}time_last_played'])!,
|
||||
excludeArtists: const BoolType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}exclude_artists'])!,
|
||||
blockLevel: const IntType()
|
||||
|
@ -2107,6 +2119,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
}
|
||||
map['icon'] = Variable<String>(icon);
|
||||
map['gradient'] = Variable<String>(gradient);
|
||||
map['time_created'] = Variable<DateTime>(timeCreated);
|
||||
map['time_changed'] = Variable<DateTime>(timeChanged);
|
||||
map['time_last_played'] = Variable<DateTime>(timeLastPlayed);
|
||||
map['exclude_artists'] = Variable<bool>(excludeArtists);
|
||||
map['block_level'] = Variable<int>(blockLevel);
|
||||
map['min_like_count'] = Variable<int>(minLikeCount);
|
||||
|
@ -2146,6 +2161,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
: Value(shuffleMode),
|
||||
icon: Value(icon),
|
||||
gradient: Value(gradient),
|
||||
timeCreated: Value(timeCreated),
|
||||
timeChanged: Value(timeChanged),
|
||||
timeLastPlayed: Value(timeLastPlayed),
|
||||
excludeArtists: Value(excludeArtists),
|
||||
blockLevel: Value(blockLevel),
|
||||
minLikeCount: Value(minLikeCount),
|
||||
|
@ -2184,6 +2202,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
shuffleMode: serializer.fromJson<String?>(json['shuffleMode']),
|
||||
icon: serializer.fromJson<String>(json['icon']),
|
||||
gradient: serializer.fromJson<String>(json['gradient']),
|
||||
timeCreated: serializer.fromJson<DateTime>(json['timeCreated']),
|
||||
timeChanged: serializer.fromJson<DateTime>(json['timeChanged']),
|
||||
timeLastPlayed: serializer.fromJson<DateTime>(json['timeLastPlayed']),
|
||||
excludeArtists: serializer.fromJson<bool>(json['excludeArtists']),
|
||||
blockLevel: serializer.fromJson<int>(json['blockLevel']),
|
||||
minLikeCount: serializer.fromJson<int>(json['minLikeCount']),
|
||||
|
@ -2208,6 +2229,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
'shuffleMode': serializer.toJson<String?>(shuffleMode),
|
||||
'icon': serializer.toJson<String>(icon),
|
||||
'gradient': serializer.toJson<String>(gradient),
|
||||
'timeCreated': serializer.toJson<DateTime>(timeCreated),
|
||||
'timeChanged': serializer.toJson<DateTime>(timeChanged),
|
||||
'timeLastPlayed': serializer.toJson<DateTime>(timeLastPlayed),
|
||||
'excludeArtists': serializer.toJson<bool>(excludeArtists),
|
||||
'blockLevel': serializer.toJson<int>(blockLevel),
|
||||
'minLikeCount': serializer.toJson<int>(minLikeCount),
|
||||
|
@ -2230,6 +2254,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
String? shuffleMode,
|
||||
String? icon,
|
||||
String? gradient,
|
||||
DateTime? timeCreated,
|
||||
DateTime? timeChanged,
|
||||
DateTime? timeLastPlayed,
|
||||
bool? excludeArtists,
|
||||
int? blockLevel,
|
||||
int? minLikeCount,
|
||||
|
@ -2249,6 +2276,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
shuffleMode: shuffleMode ?? this.shuffleMode,
|
||||
icon: icon ?? this.icon,
|
||||
gradient: gradient ?? this.gradient,
|
||||
timeCreated: timeCreated ?? this.timeCreated,
|
||||
timeChanged: timeChanged ?? this.timeChanged,
|
||||
timeLastPlayed: timeLastPlayed ?? this.timeLastPlayed,
|
||||
excludeArtists: excludeArtists ?? this.excludeArtists,
|
||||
blockLevel: blockLevel ?? this.blockLevel,
|
||||
minLikeCount: minLikeCount ?? this.minLikeCount,
|
||||
|
@ -2271,6 +2301,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
..write('shuffleMode: $shuffleMode, ')
|
||||
..write('icon: $icon, ')
|
||||
..write('gradient: $gradient, ')
|
||||
..write('timeCreated: $timeCreated, ')
|
||||
..write('timeChanged: $timeChanged, ')
|
||||
..write('timeLastPlayed: $timeLastPlayed, ')
|
||||
..write('excludeArtists: $excludeArtists, ')
|
||||
..write('blockLevel: $blockLevel, ')
|
||||
..write('minLikeCount: $minLikeCount, ')
|
||||
|
@ -2289,25 +2322,29 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
id,
|
||||
name,
|
||||
shuffleMode,
|
||||
icon,
|
||||
gradient,
|
||||
excludeArtists,
|
||||
blockLevel,
|
||||
minLikeCount,
|
||||
maxLikeCount,
|
||||
minPlayCount,
|
||||
maxPlayCount,
|
||||
minSkipCount,
|
||||
maxSkipCount,
|
||||
minYear,
|
||||
maxYear,
|
||||
limit,
|
||||
orderCriteria,
|
||||
orderDirections);
|
||||
int get hashCode => Object.hashAll([
|
||||
id,
|
||||
name,
|
||||
shuffleMode,
|
||||
icon,
|
||||
gradient,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed,
|
||||
excludeArtists,
|
||||
blockLevel,
|
||||
minLikeCount,
|
||||
maxLikeCount,
|
||||
minPlayCount,
|
||||
maxPlayCount,
|
||||
minSkipCount,
|
||||
maxSkipCount,
|
||||
minYear,
|
||||
maxYear,
|
||||
limit,
|
||||
orderCriteria,
|
||||
orderDirections
|
||||
]);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
|
@ -2317,6 +2354,9 @@ class MoorSmartList extends DataClass implements Insertable<MoorSmartList> {
|
|||
other.shuffleMode == this.shuffleMode &&
|
||||
other.icon == this.icon &&
|
||||
other.gradient == this.gradient &&
|
||||
other.timeCreated == this.timeCreated &&
|
||||
other.timeChanged == this.timeChanged &&
|
||||
other.timeLastPlayed == this.timeLastPlayed &&
|
||||
other.excludeArtists == this.excludeArtists &&
|
||||
other.blockLevel == this.blockLevel &&
|
||||
other.minLikeCount == this.minLikeCount &&
|
||||
|
@ -2338,6 +2378,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
final Value<String?> shuffleMode;
|
||||
final Value<String> icon;
|
||||
final Value<String> gradient;
|
||||
final Value<DateTime> timeCreated;
|
||||
final Value<DateTime> timeChanged;
|
||||
final Value<DateTime> timeLastPlayed;
|
||||
final Value<bool> excludeArtists;
|
||||
final Value<int> blockLevel;
|
||||
final Value<int> minLikeCount;
|
||||
|
@ -2357,6 +2400,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
this.shuffleMode = const Value.absent(),
|
||||
this.icon = const Value.absent(),
|
||||
this.gradient = const Value.absent(),
|
||||
this.timeCreated = const Value.absent(),
|
||||
this.timeChanged = const Value.absent(),
|
||||
this.timeLastPlayed = const Value.absent(),
|
||||
this.excludeArtists = const Value.absent(),
|
||||
this.blockLevel = const Value.absent(),
|
||||
this.minLikeCount = const Value.absent(),
|
||||
|
@ -2377,6 +2423,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
this.shuffleMode = const Value.absent(),
|
||||
this.icon = const Value.absent(),
|
||||
this.gradient = const Value.absent(),
|
||||
this.timeCreated = const Value.absent(),
|
||||
this.timeChanged = const Value.absent(),
|
||||
this.timeLastPlayed = const Value.absent(),
|
||||
this.excludeArtists = const Value.absent(),
|
||||
this.blockLevel = const Value.absent(),
|
||||
this.minLikeCount = const Value.absent(),
|
||||
|
@ -2399,6 +2448,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
Expression<String?>? shuffleMode,
|
||||
Expression<String>? icon,
|
||||
Expression<String>? gradient,
|
||||
Expression<DateTime>? timeCreated,
|
||||
Expression<DateTime>? timeChanged,
|
||||
Expression<DateTime>? timeLastPlayed,
|
||||
Expression<bool>? excludeArtists,
|
||||
Expression<int>? blockLevel,
|
||||
Expression<int>? minLikeCount,
|
||||
|
@ -2419,6 +2471,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
if (shuffleMode != null) 'shuffle_mode': shuffleMode,
|
||||
if (icon != null) 'icon': icon,
|
||||
if (gradient != null) 'gradient': gradient,
|
||||
if (timeCreated != null) 'time_created': timeCreated,
|
||||
if (timeChanged != null) 'time_changed': timeChanged,
|
||||
if (timeLastPlayed != null) 'time_last_played': timeLastPlayed,
|
||||
if (excludeArtists != null) 'exclude_artists': excludeArtists,
|
||||
if (blockLevel != null) 'block_level': blockLevel,
|
||||
if (minLikeCount != null) 'min_like_count': minLikeCount,
|
||||
|
@ -2441,6 +2496,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
Value<String?>? shuffleMode,
|
||||
Value<String>? icon,
|
||||
Value<String>? gradient,
|
||||
Value<DateTime>? timeCreated,
|
||||
Value<DateTime>? timeChanged,
|
||||
Value<DateTime>? timeLastPlayed,
|
||||
Value<bool>? excludeArtists,
|
||||
Value<int>? blockLevel,
|
||||
Value<int>? minLikeCount,
|
||||
|
@ -2460,6 +2518,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
shuffleMode: shuffleMode ?? this.shuffleMode,
|
||||
icon: icon ?? this.icon,
|
||||
gradient: gradient ?? this.gradient,
|
||||
timeCreated: timeCreated ?? this.timeCreated,
|
||||
timeChanged: timeChanged ?? this.timeChanged,
|
||||
timeLastPlayed: timeLastPlayed ?? this.timeLastPlayed,
|
||||
excludeArtists: excludeArtists ?? this.excludeArtists,
|
||||
blockLevel: blockLevel ?? this.blockLevel,
|
||||
minLikeCount: minLikeCount ?? this.minLikeCount,
|
||||
|
@ -2494,6 +2555,15 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
if (gradient.present) {
|
||||
map['gradient'] = Variable<String>(gradient.value);
|
||||
}
|
||||
if (timeCreated.present) {
|
||||
map['time_created'] = Variable<DateTime>(timeCreated.value);
|
||||
}
|
||||
if (timeChanged.present) {
|
||||
map['time_changed'] = Variable<DateTime>(timeChanged.value);
|
||||
}
|
||||
if (timeLastPlayed.present) {
|
||||
map['time_last_played'] = Variable<DateTime>(timeLastPlayed.value);
|
||||
}
|
||||
if (excludeArtists.present) {
|
||||
map['exclude_artists'] = Variable<bool>(excludeArtists.value);
|
||||
}
|
||||
|
@ -2544,6 +2614,9 @@ class SmartListsCompanion extends UpdateCompanion<MoorSmartList> {
|
|||
..write('shuffleMode: $shuffleMode, ')
|
||||
..write('icon: $icon, ')
|
||||
..write('gradient: $gradient, ')
|
||||
..write('timeCreated: $timeCreated, ')
|
||||
..write('timeChanged: $timeChanged, ')
|
||||
..write('timeLastPlayed: $timeLastPlayed, ')
|
||||
..write('excludeArtists: $excludeArtists, ')
|
||||
..write('blockLevel: $blockLevel, ')
|
||||
..write('minLikeCount: $minLikeCount, ')
|
||||
|
@ -2600,6 +2673,30 @@ class $SmartListsTable extends SmartLists
|
|||
type: const StringType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant('sanguine'));
|
||||
final VerificationMeta _timeCreatedMeta =
|
||||
const VerificationMeta('timeCreated');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime?> timeCreated =
|
||||
GeneratedColumn<DateTime?>('time_created', aliasedName, false,
|
||||
type: const IntType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: currentDateAndTime);
|
||||
final VerificationMeta _timeChangedMeta =
|
||||
const VerificationMeta('timeChanged');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime?> timeChanged =
|
||||
GeneratedColumn<DateTime?>('time_changed', aliasedName, false,
|
||||
type: const IntType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: currentDateAndTime);
|
||||
final VerificationMeta _timeLastPlayedMeta =
|
||||
const VerificationMeta('timeLastPlayed');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime?> timeLastPlayed =
|
||||
GeneratedColumn<DateTime?>('time_last_played', aliasedName, false,
|
||||
type: const IntType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: Constant(DateTime.fromMillisecondsSinceEpoch(0)));
|
||||
final VerificationMeta _excludeArtistsMeta =
|
||||
const VerificationMeta('excludeArtists');
|
||||
@override
|
||||
|
@ -2690,6 +2787,9 @@ class $SmartListsTable extends SmartLists
|
|||
shuffleMode,
|
||||
icon,
|
||||
gradient,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed,
|
||||
excludeArtists,
|
||||
blockLevel,
|
||||
minLikeCount,
|
||||
|
@ -2736,6 +2836,24 @@ class $SmartListsTable extends SmartLists
|
|||
context.handle(_gradientMeta,
|
||||
gradient.isAcceptableOrUnknown(data['gradient']!, _gradientMeta));
|
||||
}
|
||||
if (data.containsKey('time_created')) {
|
||||
context.handle(
|
||||
_timeCreatedMeta,
|
||||
timeCreated.isAcceptableOrUnknown(
|
||||
data['time_created']!, _timeCreatedMeta));
|
||||
}
|
||||
if (data.containsKey('time_changed')) {
|
||||
context.handle(
|
||||
_timeChangedMeta,
|
||||
timeChanged.isAcceptableOrUnknown(
|
||||
data['time_changed']!, _timeChangedMeta));
|
||||
}
|
||||
if (data.containsKey('time_last_played')) {
|
||||
context.handle(
|
||||
_timeLastPlayedMeta,
|
||||
timeLastPlayed.isAcceptableOrUnknown(
|
||||
data['time_last_played']!, _timeLastPlayedMeta));
|
||||
}
|
||||
if (data.containsKey('exclude_artists')) {
|
||||
context.handle(
|
||||
_excludeArtistsMeta,
|
||||
|
@ -3020,12 +3138,18 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
final String? shuffleMode;
|
||||
final String icon;
|
||||
final String gradient;
|
||||
final DateTime timeCreated;
|
||||
final DateTime timeChanged;
|
||||
final DateTime timeLastPlayed;
|
||||
MoorPlaylist(
|
||||
{required this.id,
|
||||
required this.name,
|
||||
this.shuffleMode,
|
||||
required this.icon,
|
||||
required this.gradient});
|
||||
required this.gradient,
|
||||
required this.timeCreated,
|
||||
required this.timeChanged,
|
||||
required this.timeLastPlayed});
|
||||
factory MoorPlaylist.fromData(Map<String, dynamic> data, {String? prefix}) {
|
||||
final effectivePrefix = prefix ?? '';
|
||||
return MoorPlaylist(
|
||||
|
@ -3039,6 +3163,12 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
.mapFromDatabaseResponse(data['${effectivePrefix}icon'])!,
|
||||
gradient: const StringType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}gradient'])!,
|
||||
timeCreated: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}time_created'])!,
|
||||
timeChanged: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}time_changed'])!,
|
||||
timeLastPlayed: const DateTimeType()
|
||||
.mapFromDatabaseResponse(data['${effectivePrefix}time_last_played'])!,
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
@ -3051,6 +3181,9 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
}
|
||||
map['icon'] = Variable<String>(icon);
|
||||
map['gradient'] = Variable<String>(gradient);
|
||||
map['time_created'] = Variable<DateTime>(timeCreated);
|
||||
map['time_changed'] = Variable<DateTime>(timeChanged);
|
||||
map['time_last_played'] = Variable<DateTime>(timeLastPlayed);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -3063,6 +3196,9 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
: Value(shuffleMode),
|
||||
icon: Value(icon),
|
||||
gradient: Value(gradient),
|
||||
timeCreated: Value(timeCreated),
|
||||
timeChanged: Value(timeChanged),
|
||||
timeLastPlayed: Value(timeLastPlayed),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3075,6 +3211,9 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
shuffleMode: serializer.fromJson<String?>(json['shuffleMode']),
|
||||
icon: serializer.fromJson<String>(json['icon']),
|
||||
gradient: serializer.fromJson<String>(json['gradient']),
|
||||
timeCreated: serializer.fromJson<DateTime>(json['timeCreated']),
|
||||
timeChanged: serializer.fromJson<DateTime>(json['timeChanged']),
|
||||
timeLastPlayed: serializer.fromJson<DateTime>(json['timeLastPlayed']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
|
@ -3086,6 +3225,9 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
'shuffleMode': serializer.toJson<String?>(shuffleMode),
|
||||
'icon': serializer.toJson<String>(icon),
|
||||
'gradient': serializer.toJson<String>(gradient),
|
||||
'timeCreated': serializer.toJson<DateTime>(timeCreated),
|
||||
'timeChanged': serializer.toJson<DateTime>(timeChanged),
|
||||
'timeLastPlayed': serializer.toJson<DateTime>(timeLastPlayed),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3094,13 +3236,19 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
String? name,
|
||||
String? shuffleMode,
|
||||
String? icon,
|
||||
String? gradient}) =>
|
||||
String? gradient,
|
||||
DateTime? timeCreated,
|
||||
DateTime? timeChanged,
|
||||
DateTime? timeLastPlayed}) =>
|
||||
MoorPlaylist(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
shuffleMode: shuffleMode ?? this.shuffleMode,
|
||||
icon: icon ?? this.icon,
|
||||
gradient: gradient ?? this.gradient,
|
||||
timeCreated: timeCreated ?? this.timeCreated,
|
||||
timeChanged: timeChanged ?? this.timeChanged,
|
||||
timeLastPlayed: timeLastPlayed ?? this.timeLastPlayed,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
|
@ -3109,13 +3257,17 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
..write('name: $name, ')
|
||||
..write('shuffleMode: $shuffleMode, ')
|
||||
..write('icon: $icon, ')
|
||||
..write('gradient: $gradient')
|
||||
..write('gradient: $gradient, ')
|
||||
..write('timeCreated: $timeCreated, ')
|
||||
..write('timeChanged: $timeChanged, ')
|
||||
..write('timeLastPlayed: $timeLastPlayed')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, name, shuffleMode, icon, gradient);
|
||||
int get hashCode => Object.hash(id, name, shuffleMode, icon, gradient,
|
||||
timeCreated, timeChanged, timeLastPlayed);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
|
@ -3124,7 +3276,10 @@ class MoorPlaylist extends DataClass implements Insertable<MoorPlaylist> {
|
|||
other.name == this.name &&
|
||||
other.shuffleMode == this.shuffleMode &&
|
||||
other.icon == this.icon &&
|
||||
other.gradient == this.gradient);
|
||||
other.gradient == this.gradient &&
|
||||
other.timeCreated == this.timeCreated &&
|
||||
other.timeChanged == this.timeChanged &&
|
||||
other.timeLastPlayed == this.timeLastPlayed);
|
||||
}
|
||||
|
||||
class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
||||
|
@ -3133,12 +3288,18 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
final Value<String?> shuffleMode;
|
||||
final Value<String> icon;
|
||||
final Value<String> gradient;
|
||||
final Value<DateTime> timeCreated;
|
||||
final Value<DateTime> timeChanged;
|
||||
final Value<DateTime> timeLastPlayed;
|
||||
const PlaylistsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.name = const Value.absent(),
|
||||
this.shuffleMode = const Value.absent(),
|
||||
this.icon = const Value.absent(),
|
||||
this.gradient = const Value.absent(),
|
||||
this.timeCreated = const Value.absent(),
|
||||
this.timeChanged = const Value.absent(),
|
||||
this.timeLastPlayed = const Value.absent(),
|
||||
});
|
||||
PlaylistsCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
|
@ -3146,6 +3307,9 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
this.shuffleMode = const Value.absent(),
|
||||
this.icon = const Value.absent(),
|
||||
this.gradient = const Value.absent(),
|
||||
this.timeCreated = const Value.absent(),
|
||||
this.timeChanged = const Value.absent(),
|
||||
this.timeLastPlayed = const Value.absent(),
|
||||
}) : name = Value(name);
|
||||
static Insertable<MoorPlaylist> custom({
|
||||
Expression<int>? id,
|
||||
|
@ -3153,6 +3317,9 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
Expression<String?>? shuffleMode,
|
||||
Expression<String>? icon,
|
||||
Expression<String>? gradient,
|
||||
Expression<DateTime>? timeCreated,
|
||||
Expression<DateTime>? timeChanged,
|
||||
Expression<DateTime>? timeLastPlayed,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
|
@ -3160,6 +3327,9 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
if (shuffleMode != null) 'shuffle_mode': shuffleMode,
|
||||
if (icon != null) 'icon': icon,
|
||||
if (gradient != null) 'gradient': gradient,
|
||||
if (timeCreated != null) 'time_created': timeCreated,
|
||||
if (timeChanged != null) 'time_changed': timeChanged,
|
||||
if (timeLastPlayed != null) 'time_last_played': timeLastPlayed,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3168,13 +3338,19 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
Value<String>? name,
|
||||
Value<String?>? shuffleMode,
|
||||
Value<String>? icon,
|
||||
Value<String>? gradient}) {
|
||||
Value<String>? gradient,
|
||||
Value<DateTime>? timeCreated,
|
||||
Value<DateTime>? timeChanged,
|
||||
Value<DateTime>? timeLastPlayed}) {
|
||||
return PlaylistsCompanion(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
shuffleMode: shuffleMode ?? this.shuffleMode,
|
||||
icon: icon ?? this.icon,
|
||||
gradient: gradient ?? this.gradient,
|
||||
timeCreated: timeCreated ?? this.timeCreated,
|
||||
timeChanged: timeChanged ?? this.timeChanged,
|
||||
timeLastPlayed: timeLastPlayed ?? this.timeLastPlayed,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -3196,6 +3372,15 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
if (gradient.present) {
|
||||
map['gradient'] = Variable<String>(gradient.value);
|
||||
}
|
||||
if (timeCreated.present) {
|
||||
map['time_created'] = Variable<DateTime>(timeCreated.value);
|
||||
}
|
||||
if (timeChanged.present) {
|
||||
map['time_changed'] = Variable<DateTime>(timeChanged.value);
|
||||
}
|
||||
if (timeLastPlayed.present) {
|
||||
map['time_last_played'] = Variable<DateTime>(timeLastPlayed.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -3206,7 +3391,10 @@ class PlaylistsCompanion extends UpdateCompanion<MoorPlaylist> {
|
|||
..write('name: $name, ')
|
||||
..write('shuffleMode: $shuffleMode, ')
|
||||
..write('icon: $icon, ')
|
||||
..write('gradient: $gradient')
|
||||
..write('gradient: $gradient, ')
|
||||
..write('timeCreated: $timeCreated, ')
|
||||
..write('timeChanged: $timeChanged, ')
|
||||
..write('timeLastPlayed: $timeLastPlayed')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
@ -3250,8 +3438,41 @@ class $PlaylistsTable extends Playlists
|
|||
type: const StringType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant('oceanblue'));
|
||||
final VerificationMeta _timeCreatedMeta =
|
||||
const VerificationMeta('timeCreated');
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, name, shuffleMode, icon, gradient];
|
||||
late final GeneratedColumn<DateTime?> timeCreated =
|
||||
GeneratedColumn<DateTime?>('time_created', aliasedName, false,
|
||||
type: const IntType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: currentDateAndTime);
|
||||
final VerificationMeta _timeChangedMeta =
|
||||
const VerificationMeta('timeChanged');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime?> timeChanged =
|
||||
GeneratedColumn<DateTime?>('time_changed', aliasedName, false,
|
||||
type: const IntType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: currentDateAndTime);
|
||||
final VerificationMeta _timeLastPlayedMeta =
|
||||
const VerificationMeta('timeLastPlayed');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime?> timeLastPlayed =
|
||||
GeneratedColumn<DateTime?>('time_last_played', aliasedName, false,
|
||||
type: const IntType(),
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: Constant(DateTime.fromMillisecondsSinceEpoch(0)));
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
id,
|
||||
name,
|
||||
shuffleMode,
|
||||
icon,
|
||||
gradient,
|
||||
timeCreated,
|
||||
timeChanged,
|
||||
timeLastPlayed
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? 'playlists';
|
||||
@override
|
||||
|
@ -3284,6 +3505,24 @@ class $PlaylistsTable extends Playlists
|
|||
context.handle(_gradientMeta,
|
||||
gradient.isAcceptableOrUnknown(data['gradient']!, _gradientMeta));
|
||||
}
|
||||
if (data.containsKey('time_created')) {
|
||||
context.handle(
|
||||
_timeCreatedMeta,
|
||||
timeCreated.isAcceptableOrUnknown(
|
||||
data['time_created']!, _timeCreatedMeta));
|
||||
}
|
||||
if (data.containsKey('time_changed')) {
|
||||
context.handle(
|
||||
_timeChangedMeta,
|
||||
timeChanged.isAcceptableOrUnknown(
|
||||
data['time_changed']!, _timeChangedMeta));
|
||||
}
|
||||
if (data.containsKey('time_last_played')) {
|
||||
context.handle(
|
||||
_timeLastPlayedMeta,
|
||||
timeLastPlayed.isAcceptableOrUnknown(
|
||||
data['time_last_played']!, _timeLastPlayedMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,13 @@ import '../../datasources/moor_database.dart';
|
|||
import 'home_widget_model.dart';
|
||||
|
||||
class HomeArtistOfDayModel extends HomeArtistOfDay implements HomeWidgetModel {
|
||||
HomeArtistOfDayModel(super.position, super.shuffleMode);
|
||||
HomeArtistOfDayModel(
|
||||
int position,
|
||||
ShuffleMode shuffleMode,
|
||||
) : super(
|
||||
position: position,
|
||||
shuffleMode: shuffleMode,
|
||||
);
|
||||
|
||||
factory HomeArtistOfDayModel.fromMoor(MoorHomeWidget moorHomeWidget) {
|
||||
final type = moorHomeWidget.type.toHomeWidgetType();
|
||||
|
@ -32,11 +38,11 @@ class HomeArtistOfDayModel extends HomeArtistOfDay implements HomeWidgetModel {
|
|||
|
||||
@override
|
||||
HomeWidgetsCompanion toMoor() {
|
||||
final data = '{"shuffleMode": "$shuffleMode"}';
|
||||
final data = {'shuffleMode': '$shuffleMode'};
|
||||
return HomeWidgetsCompanion(
|
||||
position: Value(position),
|
||||
type: Value(type.toString()),
|
||||
data: Value(data),
|
||||
data: Value(json.encode(data)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,29 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
import '../../../domain/entities/enums.dart';
|
||||
import '../../../domain/entities/home_widgets/home_widget.dart';
|
||||
import '../../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../datasources/moor_database.dart';
|
||||
import 'home_widget_model.dart';
|
||||
|
||||
class HomePlaylistsModel extends HomePlaylists implements HomeWidgetModel {
|
||||
HomePlaylistsModel(super.position);
|
||||
HomePlaylistsModel(
|
||||
int position,
|
||||
int maxEntries,
|
||||
String title,
|
||||
HomePlaylistsOrder orderCriterion,
|
||||
OrderDirection orderDirection,
|
||||
HomePlaylistsFilter filter,
|
||||
) : super(
|
||||
position: position,
|
||||
maxEntries: maxEntries,
|
||||
title: title,
|
||||
orderCriterion: orderCriterion,
|
||||
orderDirection: orderDirection,
|
||||
filter: filter,
|
||||
);
|
||||
|
||||
factory HomePlaylistsModel.fromMoor(MoorHomeWidget moorHomeWidget) {
|
||||
final type = moorHomeWidget.type.toHomeWidgetType();
|
||||
|
@ -14,7 +31,16 @@ class HomePlaylistsModel extends HomePlaylists implements HomeWidgetModel {
|
|||
throw TypeError();
|
||||
}
|
||||
|
||||
return HomePlaylistsModel(moorHomeWidget.position);
|
||||
final data = json.decode(moorHomeWidget.data);
|
||||
|
||||
return HomePlaylistsModel(
|
||||
moorHomeWidget.position,
|
||||
data['maxEntries'] as int,
|
||||
data['title'] as String,
|
||||
(data['orderCriterion'] as String).toHomePlaylistsOrder()!,
|
||||
(data['orderDirection'] as String).toOrderDirection()!,
|
||||
(data['filter'] as String).toHomePlaylistsFilter()!,
|
||||
);
|
||||
}
|
||||
|
||||
factory HomePlaylistsModel.fromEntity(HomeWidget entity) {
|
||||
|
@ -22,16 +48,29 @@ class HomePlaylistsModel extends HomePlaylists implements HomeWidgetModel {
|
|||
throw TypeError();
|
||||
}
|
||||
entity as HomePlaylists;
|
||||
return HomePlaylistsModel(entity.position);
|
||||
return HomePlaylistsModel(
|
||||
entity.position,
|
||||
entity.maxEntries,
|
||||
entity.title,
|
||||
entity.orderCriterion,
|
||||
entity.orderDirection,
|
||||
entity.filter,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
HomeWidgetsCompanion toMoor() {
|
||||
const data = '{}';
|
||||
final Map<String, dynamic> data = {
|
||||
'title': title,
|
||||
'maxEntries': maxEntries,
|
||||
'orderCriterion': orderCriterion.toString(),
|
||||
'orderDirection': orderDirection.toString(),
|
||||
'filter': filter.toString(),
|
||||
};
|
||||
return HomeWidgetsCompanion(
|
||||
position: Value(position),
|
||||
type: Value(type.toString()),
|
||||
data: const Value(data),
|
||||
data: Value(json.encode(data)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,13 @@ import '../../datasources/moor_database.dart';
|
|||
import 'home_widget_model.dart';
|
||||
|
||||
class HomeShuffleAllModel extends HomeShuffleAll implements HomeWidgetModel {
|
||||
HomeShuffleAllModel(super.position, super.shuffleMode);
|
||||
HomeShuffleAllModel(
|
||||
int position,
|
||||
ShuffleMode shuffleMode,
|
||||
) : super(
|
||||
position: position,
|
||||
shuffleMode: shuffleMode,
|
||||
);
|
||||
|
||||
factory HomeShuffleAllModel.fromMoor(MoorHomeWidget moorHomeWidget) {
|
||||
final type = moorHomeWidget.type.toHomeWidgetType();
|
||||
|
@ -32,11 +38,11 @@ class HomeShuffleAllModel extends HomeShuffleAll implements HomeWidgetModel {
|
|||
|
||||
@override
|
||||
HomeWidgetsCompanion toMoor() {
|
||||
final data = '{"shuffleMode": "$shuffleMode"}';
|
||||
final data = {'shuffleMode': '$shuffleMode'};
|
||||
return HomeWidgetsCompanion(
|
||||
position: Value(position),
|
||||
type: Value(type.toString()),
|
||||
data: Value(data),
|
||||
data: Value(json.encode(data)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@ class PlaylistModel extends Playlist {
|
|||
required String name,
|
||||
required String iconString,
|
||||
required String gradientString,
|
||||
required DateTime timeCreated,
|
||||
required DateTime timeChanged,
|
||||
required DateTime timeLastPlayed,
|
||||
ShuffleMode? shuffleMode,
|
||||
}) : super(
|
||||
id: id,
|
||||
|
@ -17,6 +20,9 @@ class PlaylistModel extends Playlist {
|
|||
iconString: iconString,
|
||||
gradientString: gradientString,
|
||||
shuffleMode: shuffleMode,
|
||||
timeCreated: timeCreated,
|
||||
timeChanged: timeChanged,
|
||||
timeLastPlayed: timeLastPlayed,
|
||||
);
|
||||
|
||||
factory PlaylistModel.fromPlaylist(Playlist playlist) {
|
||||
|
@ -26,6 +32,9 @@ class PlaylistModel extends Playlist {
|
|||
iconString: playlist.iconString,
|
||||
gradientString: playlist.gradientString,
|
||||
shuffleMode: playlist.shuffleMode,
|
||||
timeChanged: playlist.timeChanged,
|
||||
timeCreated: playlist.timeCreated,
|
||||
timeLastPlayed: playlist.timeLastPlayed,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -36,6 +45,9 @@ class PlaylistModel extends Playlist {
|
|||
iconString: moorPlaylist.icon,
|
||||
gradientString: moorPlaylist.gradient,
|
||||
shuffleMode: moorPlaylist.shuffleMode?.toShuffleMode(),
|
||||
timeChanged: moorPlaylist.timeChanged,
|
||||
timeCreated: moorPlaylist.timeCreated,
|
||||
timeLastPlayed: moorPlaylist.timeLastPlayed,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -45,5 +57,8 @@ class PlaylistModel extends Playlist {
|
|||
shuffleMode: m.Value(shuffleMode?.toString()),
|
||||
icon: m.Value(iconString),
|
||||
gradient: m.Value(gradientString),
|
||||
timeChanged: m.Value(timeChanged),
|
||||
timeCreated: m.Value(timeCreated),
|
||||
timeLastPlayed: m.Value(timeLastPlayed),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:drift/drift.dart' as m;
|
||||
|
||||
import '../../domain/entities/enums.dart';
|
||||
import '../../domain/entities/shuffle_mode.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
import '../datasources/moor_database.dart';
|
||||
|
@ -11,6 +12,9 @@ class SmartListModel extends SmartList {
|
|||
required String name,
|
||||
required String iconString,
|
||||
required String gradientString,
|
||||
required DateTime timeCreated,
|
||||
required DateTime timeChanged,
|
||||
required DateTime timeLastPlayed,
|
||||
required Filter filter,
|
||||
required OrderBy orderBy,
|
||||
ShuffleMode? shuffleMode,
|
||||
|
@ -22,9 +26,12 @@ class SmartListModel extends SmartList {
|
|||
shuffleMode: shuffleMode,
|
||||
iconString: iconString,
|
||||
gradientString: gradientString,
|
||||
timeCreated: timeCreated,
|
||||
timeChanged: timeChanged,
|
||||
timeLastPlayed: timeLastPlayed,
|
||||
);
|
||||
|
||||
factory SmartListModel.fromSmartList(SmartList smartList) {
|
||||
factory SmartListModel.fromSmartList(SmartList smartList) {
|
||||
return SmartListModel(
|
||||
id: smartList.id,
|
||||
name: smartList.name,
|
||||
|
@ -33,6 +40,9 @@ class SmartListModel extends SmartList {
|
|||
shuffleMode: smartList.shuffleMode,
|
||||
iconString: smartList.iconString,
|
||||
gradientString: smartList.gradientString,
|
||||
timeCreated: smartList.timeCreated,
|
||||
timeChanged: smartList.timeChanged,
|
||||
timeLastPlayed: smartList.timeLastPlayed,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -49,7 +59,7 @@ class SmartListModel extends SmartList {
|
|||
minYear: moorSmartList.minYear,
|
||||
maxYear: moorSmartList.maxYear,
|
||||
blockLevel: moorSmartList.blockLevel,
|
||||
limit: moorSmartList.limit,
|
||||
limit: moorSmartList.limit,
|
||||
);
|
||||
|
||||
final orderBy = OrderBy(
|
||||
|
@ -65,6 +75,9 @@ class SmartListModel extends SmartList {
|
|||
shuffleMode: moorSmartList.shuffleMode?.toShuffleMode(),
|
||||
iconString: moorSmartList.icon,
|
||||
gradientString: moorSmartList.gradient,
|
||||
timeChanged: moorSmartList.timeChanged,
|
||||
timeCreated: moorSmartList.timeCreated,
|
||||
timeLastPlayed: moorSmartList.timeLastPlayed,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -87,6 +100,9 @@ class SmartListModel extends SmartList {
|
|||
orderDirections: m.Value(orderBy.orderDirections.join(',')),
|
||||
icon: m.Value(iconString),
|
||||
gradient: m.Value(gradientString),
|
||||
timeChanged: m.Value(timeChanged),
|
||||
timeCreated: m.Value(timeCreated),
|
||||
timeLastPlayed: m.Value(timeLastPlayed),
|
||||
);
|
||||
|
||||
List<SmartListArtistsCompanion> toMoorArtists() {
|
||||
|
|
|
@ -7,6 +7,9 @@ import 'package:string_similarity/string_similarity.dart';
|
|||
import '../../constants.dart';
|
||||
import '../../domain/entities/album.dart';
|
||||
import '../../domain/entities/artist.dart';
|
||||
import '../../domain/entities/custom_list.dart';
|
||||
import '../../domain/entities/enums.dart';
|
||||
import '../../domain/entities/home_widgets/playlists.dart';
|
||||
import '../../domain/entities/playlist.dart';
|
||||
import '../../domain/entities/shuffle_mode.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
|
@ -492,4 +495,49 @@ class MusicDataRepositoryImpl implements MusicDataRepository {
|
|||
DateTime _day(DateTime dateTime) {
|
||||
return DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<CustomList>> getCustomListsStream({
|
||||
HomePlaylistsOrder orderCriterion = HomePlaylistsOrder.name,
|
||||
OrderDirection orderDirection = OrderDirection.ascending,
|
||||
HomePlaylistsFilter filter = HomePlaylistsFilter.both,
|
||||
int? limit,
|
||||
}) {
|
||||
final List<Stream<List<CustomList>>> streams = [];
|
||||
if ([HomePlaylistsFilter.both, HomePlaylistsFilter.smartlists].contains(filter)) {
|
||||
streams.add(_playlistDataSource.smartListsStream);
|
||||
}
|
||||
if ([HomePlaylistsFilter.both, HomePlaylistsFilter.playlists].contains(filter)) {
|
||||
streams.add(_playlistDataSource.playlistsStream);
|
||||
}
|
||||
|
||||
return Rx.combineLatest(streams, (List<List<CustomList>> lists) {
|
||||
List<CustomList> combined = lists.expand((element) => element).toList();
|
||||
|
||||
switch (orderCriterion) {
|
||||
case HomePlaylistsOrder.name:
|
||||
combined.sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
|
||||
break;
|
||||
case HomePlaylistsOrder.creationDate:
|
||||
combined.sort((a, b) => a.timeCreated.compareTo(b.timeCreated));
|
||||
break;
|
||||
case HomePlaylistsOrder.changeDate:
|
||||
combined.sort((a, b) => a.timeChanged.compareTo(b.timeChanged));
|
||||
break;
|
||||
case HomePlaylistsOrder.history:
|
||||
combined.sort((a, b) => a.timeLastPlayed.compareTo(b.timeLastPlayed));
|
||||
break;
|
||||
}
|
||||
|
||||
if (orderDirection == OrderDirection.descending) {
|
||||
combined = combined.reversed.toList();
|
||||
}
|
||||
|
||||
if (limit != null && limit > 0) {
|
||||
combined = combined.take(limit).toList();
|
||||
}
|
||||
|
||||
return combined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue