mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-07 21:48:14 -08:00
feature: Added option to save and set default filters for libraries (#107)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
d3e34d57e0
commit
691293648b
23 changed files with 1353 additions and 62 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"Jellyfin"
|
"Jellyfin",
|
||||||
|
"jellyfin"
|
||||||
],
|
],
|
||||||
"dart.flutterSdkPath": ".fvm/versions/3.24.3",
|
"dart.flutterSdkPath": ".fvm/versions/3.24.3",
|
||||||
"search.exclude": {
|
"search.exclude": {
|
||||||
|
|
|
||||||
|
|
@ -1084,5 +1084,20 @@
|
||||||
"speed": "Speed",
|
"speed": "Speed",
|
||||||
"unableToPlayMedia": "There was an error finding a compatible media type",
|
"unableToPlayMedia": "There was an error finding a compatible media type",
|
||||||
"errorOpeningMedia": "Something went trying to play this media",
|
"errorOpeningMedia": "Something went trying to play this media",
|
||||||
"unableToPlayBooksOnWeb": "Books are not supported on web for now"
|
"unableToPlayBooksOnWeb": "Books are not supported on web for now",
|
||||||
|
"defaultFilterForLibrary": "Default filter for library",
|
||||||
|
"updateFilterForLibrary": "Update filter",
|
||||||
|
"removeFilterForLibrary": "Remove {filter}?",
|
||||||
|
"@removeFilterForLibrary": {
|
||||||
|
"description": "removeFilterForLibrary",
|
||||||
|
"placeholders": {
|
||||||
|
"filter":{
|
||||||
|
"type": "String"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deleteFilterConfirmation": "Are you sure you want to delete this filter?",
|
||||||
|
"libraryFiltersLimitReached" : "Filter limit reached (10) remove some filters",
|
||||||
|
"libraryFiltersRemoveAll": "Remove all filters",
|
||||||
|
"libraryFiltersRemoveAllConfirm": "This will delete all saved filters for every library"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
// ignore_for_file: public_member_api_docs, sort_constructors_first, invalid_annotation_target
|
// ignore_for_file: public_member_api_docs, sort_constructors_first, invalid_annotation_target
|
||||||
|
|
||||||
import 'package:ficonsax/ficonsax.dart';
|
|
||||||
import 'package:fladder/util/localization_helper.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import 'package:ficonsax/ficonsax.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
||||||
import 'package:fladder/models/credentials_model.dart';
|
import 'package:fladder/models/credentials_model.dart';
|
||||||
|
import 'package:fladder/models/library_filters_model.dart';
|
||||||
import 'package:fladder/util/adaptive_layout.dart';
|
import 'package:fladder/util/adaptive_layout.dart';
|
||||||
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
||||||
|
|
||||||
part 'account_model.freezed.dart';
|
part 'account_model.freezed.dart';
|
||||||
part 'account_model.g.dart';
|
part 'account_model.g.dart';
|
||||||
|
|
@ -30,6 +31,7 @@ class AccountModel with _$AccountModel {
|
||||||
@Default([]) List<String> latestItemsExcludes,
|
@Default([]) List<String> latestItemsExcludes,
|
||||||
@Default([]) List<String> searchQueryHistory,
|
@Default([]) List<String> searchQueryHistory,
|
||||||
@Default(false) bool quickConnectState,
|
@Default(false) bool quickConnectState,
|
||||||
|
@Default([]) List<LibraryFiltersModel> savedFilters,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false) ServerConfiguration? serverConfiguration,
|
@JsonKey(includeFromJson: false, includeToJson: false) ServerConfiguration? serverConfiguration,
|
||||||
}) = _AccountModel;
|
}) = _AccountModel;
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ mixin _$AccountModel {
|
||||||
List<String> get latestItemsExcludes => throw _privateConstructorUsedError;
|
List<String> get latestItemsExcludes => throw _privateConstructorUsedError;
|
||||||
List<String> get searchQueryHistory => throw _privateConstructorUsedError;
|
List<String> get searchQueryHistory => throw _privateConstructorUsedError;
|
||||||
bool get quickConnectState => throw _privateConstructorUsedError;
|
bool get quickConnectState => throw _privateConstructorUsedError;
|
||||||
|
List<LibraryFiltersModel> get savedFilters =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
UserPolicy? get policy => throw _privateConstructorUsedError;
|
UserPolicy? get policy => throw _privateConstructorUsedError;
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
|
@ -63,6 +65,7 @@ abstract class $AccountModelCopyWith<$Res> {
|
||||||
List<String> latestItemsExcludes,
|
List<String> latestItemsExcludes,
|
||||||
List<String> searchQueryHistory,
|
List<String> searchQueryHistory,
|
||||||
bool quickConnectState,
|
bool quickConnectState,
|
||||||
|
List<LibraryFiltersModel> savedFilters,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
ServerConfiguration? serverConfiguration});
|
ServerConfiguration? serverConfiguration});
|
||||||
|
|
@ -93,6 +96,7 @@ class _$AccountModelCopyWithImpl<$Res, $Val extends AccountModel>
|
||||||
Object? latestItemsExcludes = null,
|
Object? latestItemsExcludes = null,
|
||||||
Object? searchQueryHistory = null,
|
Object? searchQueryHistory = null,
|
||||||
Object? quickConnectState = null,
|
Object? quickConnectState = null,
|
||||||
|
Object? savedFilters = null,
|
||||||
Object? policy = freezed,
|
Object? policy = freezed,
|
||||||
Object? serverConfiguration = freezed,
|
Object? serverConfiguration = freezed,
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -137,6 +141,10 @@ class _$AccountModelCopyWithImpl<$Res, $Val extends AccountModel>
|
||||||
? _value.quickConnectState
|
? _value.quickConnectState
|
||||||
: quickConnectState // ignore: cast_nullable_to_non_nullable
|
: quickConnectState // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
savedFilters: null == savedFilters
|
||||||
|
? _value.savedFilters
|
||||||
|
: savedFilters // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<LibraryFiltersModel>,
|
||||||
policy: freezed == policy
|
policy: freezed == policy
|
||||||
? _value.policy
|
? _value.policy
|
||||||
: policy // ignore: cast_nullable_to_non_nullable
|
: policy // ignore: cast_nullable_to_non_nullable
|
||||||
|
|
@ -168,6 +176,7 @@ abstract class _$$AccountModelImplCopyWith<$Res>
|
||||||
List<String> latestItemsExcludes,
|
List<String> latestItemsExcludes,
|
||||||
List<String> searchQueryHistory,
|
List<String> searchQueryHistory,
|
||||||
bool quickConnectState,
|
bool quickConnectState,
|
||||||
|
List<LibraryFiltersModel> savedFilters,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
ServerConfiguration? serverConfiguration});
|
ServerConfiguration? serverConfiguration});
|
||||||
|
|
@ -196,6 +205,7 @@ class __$$AccountModelImplCopyWithImpl<$Res>
|
||||||
Object? latestItemsExcludes = null,
|
Object? latestItemsExcludes = null,
|
||||||
Object? searchQueryHistory = null,
|
Object? searchQueryHistory = null,
|
||||||
Object? quickConnectState = null,
|
Object? quickConnectState = null,
|
||||||
|
Object? savedFilters = null,
|
||||||
Object? policy = freezed,
|
Object? policy = freezed,
|
||||||
Object? serverConfiguration = freezed,
|
Object? serverConfiguration = freezed,
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -240,6 +250,10 @@ class __$$AccountModelImplCopyWithImpl<$Res>
|
||||||
? _value.quickConnectState
|
? _value.quickConnectState
|
||||||
: quickConnectState // ignore: cast_nullable_to_non_nullable
|
: quickConnectState // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
savedFilters: null == savedFilters
|
||||||
|
? _value._savedFilters
|
||||||
|
: savedFilters // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<LibraryFiltersModel>,
|
||||||
policy: freezed == policy
|
policy: freezed == policy
|
||||||
? _value.policy
|
? _value.policy
|
||||||
: policy // ignore: cast_nullable_to_non_nullable
|
: policy // ignore: cast_nullable_to_non_nullable
|
||||||
|
|
@ -266,11 +280,13 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
||||||
final List<String> latestItemsExcludes = const [],
|
final List<String> latestItemsExcludes = const [],
|
||||||
final List<String> searchQueryHistory = const [],
|
final List<String> searchQueryHistory = const [],
|
||||||
this.quickConnectState = false,
|
this.quickConnectState = false,
|
||||||
|
final List<LibraryFiltersModel> savedFilters = const [],
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false) this.policy,
|
@JsonKey(includeFromJson: false, includeToJson: false) this.policy,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
this.serverConfiguration})
|
this.serverConfiguration})
|
||||||
: _latestItemsExcludes = latestItemsExcludes,
|
: _latestItemsExcludes = latestItemsExcludes,
|
||||||
_searchQueryHistory = searchQueryHistory,
|
_searchQueryHistory = searchQueryHistory,
|
||||||
|
_savedFilters = savedFilters,
|
||||||
super._();
|
super._();
|
||||||
|
|
||||||
factory _$AccountModelImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$AccountModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|
@ -315,6 +331,15 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool quickConnectState;
|
final bool quickConnectState;
|
||||||
|
final List<LibraryFiltersModel> _savedFilters;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
List<LibraryFiltersModel> get savedFilters {
|
||||||
|
if (_savedFilters is EqualUnmodifiableListView) return _savedFilters;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_savedFilters);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
final UserPolicy? policy;
|
final UserPolicy? policy;
|
||||||
|
|
@ -324,7 +349,7 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
|
||||||
return 'AccountModel(name: $name, id: $id, avatar: $avatar, lastUsed: $lastUsed, authMethod: $authMethod, localPin: $localPin, credentials: $credentials, latestItemsExcludes: $latestItemsExcludes, searchQueryHistory: $searchQueryHistory, quickConnectState: $quickConnectState, policy: $policy, serverConfiguration: $serverConfiguration)';
|
return 'AccountModel(name: $name, id: $id, avatar: $avatar, lastUsed: $lastUsed, authMethod: $authMethod, localPin: $localPin, credentials: $credentials, latestItemsExcludes: $latestItemsExcludes, searchQueryHistory: $searchQueryHistory, quickConnectState: $quickConnectState, savedFilters: $savedFilters, policy: $policy, serverConfiguration: $serverConfiguration)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -342,6 +367,7 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
||||||
..add(DiagnosticsProperty('latestItemsExcludes', latestItemsExcludes))
|
..add(DiagnosticsProperty('latestItemsExcludes', latestItemsExcludes))
|
||||||
..add(DiagnosticsProperty('searchQueryHistory', searchQueryHistory))
|
..add(DiagnosticsProperty('searchQueryHistory', searchQueryHistory))
|
||||||
..add(DiagnosticsProperty('quickConnectState', quickConnectState))
|
..add(DiagnosticsProperty('quickConnectState', quickConnectState))
|
||||||
|
..add(DiagnosticsProperty('savedFilters', savedFilters))
|
||||||
..add(DiagnosticsProperty('policy', policy))
|
..add(DiagnosticsProperty('policy', policy))
|
||||||
..add(DiagnosticsProperty('serverConfiguration', serverConfiguration));
|
..add(DiagnosticsProperty('serverConfiguration', serverConfiguration));
|
||||||
}
|
}
|
||||||
|
|
@ -368,6 +394,8 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
||||||
.equals(other._searchQueryHistory, _searchQueryHistory) &&
|
.equals(other._searchQueryHistory, _searchQueryHistory) &&
|
||||||
(identical(other.quickConnectState, quickConnectState) ||
|
(identical(other.quickConnectState, quickConnectState) ||
|
||||||
other.quickConnectState == quickConnectState) &&
|
other.quickConnectState == quickConnectState) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other._savedFilters, _savedFilters) &&
|
||||||
(identical(other.policy, policy) || other.policy == policy) &&
|
(identical(other.policy, policy) || other.policy == policy) &&
|
||||||
(identical(other.serverConfiguration, serverConfiguration) ||
|
(identical(other.serverConfiguration, serverConfiguration) ||
|
||||||
other.serverConfiguration == serverConfiguration));
|
other.serverConfiguration == serverConfiguration));
|
||||||
|
|
@ -387,6 +415,7 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
||||||
const DeepCollectionEquality().hash(_latestItemsExcludes),
|
const DeepCollectionEquality().hash(_latestItemsExcludes),
|
||||||
const DeepCollectionEquality().hash(_searchQueryHistory),
|
const DeepCollectionEquality().hash(_searchQueryHistory),
|
||||||
quickConnectState,
|
quickConnectState,
|
||||||
|
const DeepCollectionEquality().hash(_savedFilters),
|
||||||
policy,
|
policy,
|
||||||
serverConfiguration);
|
serverConfiguration);
|
||||||
|
|
||||||
|
|
@ -418,6 +447,7 @@ abstract class _AccountModel extends AccountModel {
|
||||||
final List<String> latestItemsExcludes,
|
final List<String> latestItemsExcludes,
|
||||||
final List<String> searchQueryHistory,
|
final List<String> searchQueryHistory,
|
||||||
final bool quickConnectState,
|
final bool quickConnectState,
|
||||||
|
final List<LibraryFiltersModel> savedFilters,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
final UserPolicy? policy,
|
final UserPolicy? policy,
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
|
@ -448,6 +478,8 @@ abstract class _AccountModel extends AccountModel {
|
||||||
@override
|
@override
|
||||||
bool get quickConnectState;
|
bool get quickConnectState;
|
||||||
@override
|
@override
|
||||||
|
List<LibraryFiltersModel> get savedFilters;
|
||||||
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
UserPolicy? get policy;
|
UserPolicy? get policy;
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ _$AccountModelImpl _$$AccountModelImplFromJson(Map<String, dynamic> json) =>
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
quickConnectState: json['quickConnectState'] as bool? ?? false,
|
quickConnectState: json['quickConnectState'] as bool? ?? false,
|
||||||
|
savedFilters: (json['savedFilters'] as List<dynamic>?)
|
||||||
|
?.map((e) =>
|
||||||
|
LibraryFiltersModel.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$AccountModelImplToJson(_$AccountModelImpl instance) =>
|
Map<String, dynamic> _$$AccountModelImplToJson(_$AccountModelImpl instance) =>
|
||||||
|
|
@ -40,6 +45,7 @@ Map<String, dynamic> _$$AccountModelImplToJson(_$AccountModelImpl instance) =>
|
||||||
'latestItemsExcludes': instance.latestItemsExcludes,
|
'latestItemsExcludes': instance.latestItemsExcludes,
|
||||||
'searchQueryHistory': instance.searchQueryHistory,
|
'searchQueryHistory': instance.searchQueryHistory,
|
||||||
'quickConnectState': instance.quickConnectState,
|
'quickConnectState': instance.quickConnectState,
|
||||||
|
'savedFilters': instance.savedFilters,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$AuthenticationEnumMap = {
|
const _$AuthenticationEnumMap = {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ extension CollectionTypeExtension on CollectionType {
|
||||||
case CollectionType.tvshows:
|
case CollectionType.tvshows:
|
||||||
return {FladderItemType.series};
|
return {FladderItemType.series};
|
||||||
case CollectionType.homevideos:
|
case CollectionType.homevideos:
|
||||||
return {FladderItemType.photoalbum, FladderItemType.folder, FladderItemType.photo, FladderItemType.video};
|
return {FladderItemType.photoAlbum, FladderItemType.folder, FladderItemType.photo, FladderItemType.video};
|
||||||
case CollectionType.boxsets:
|
case CollectionType.boxsets:
|
||||||
case CollectionType.folders:
|
case CollectionType.folders:
|
||||||
case CollectionType.books:
|
case CollectionType.books:
|
||||||
|
|
|
||||||
|
|
@ -210,7 +210,7 @@ class ItemBaseModel with ItemBaseModelMappable {
|
||||||
MovieModel _ => FladderItemType.movie,
|
MovieModel _ => FladderItemType.movie,
|
||||||
SeriesModel _ => FladderItemType.series,
|
SeriesModel _ => FladderItemType.series,
|
||||||
SeasonModel _ => FladderItemType.season,
|
SeasonModel _ => FladderItemType.season,
|
||||||
PhotoAlbumModel _ => FladderItemType.photoalbum,
|
PhotoAlbumModel _ => FladderItemType.photoAlbum,
|
||||||
PhotoModel model => model.internalType,
|
PhotoModel model => model.internalType,
|
||||||
EpisodeModel _ => FladderItemType.episode,
|
EpisodeModel _ => FladderItemType.episode,
|
||||||
BookModel _ => FladderItemType.book,
|
BookModel _ => FladderItemType.book,
|
||||||
|
|
@ -281,7 +281,7 @@ enum FladderItemType {
|
||||||
icon: IconsaxOutline.user,
|
icon: IconsaxOutline.user,
|
||||||
selectedicon: IconsaxBold.user,
|
selectedicon: IconsaxBold.user,
|
||||||
),
|
),
|
||||||
photoalbum(
|
photoAlbum(
|
||||||
icon: IconsaxOutline.gallery,
|
icon: IconsaxOutline.gallery,
|
||||||
selectedicon: IconsaxBold.gallery,
|
selectedicon: IconsaxBold.gallery,
|
||||||
),
|
),
|
||||||
|
|
@ -331,7 +331,7 @@ enum FladderItemType {
|
||||||
FladderItemType.episode => context.localized.mediaTypeEpisode,
|
FladderItemType.episode => context.localized.mediaTypeEpisode,
|
||||||
FladderItemType.photo => context.localized.mediaTypePhoto,
|
FladderItemType.photo => context.localized.mediaTypePhoto,
|
||||||
FladderItemType.person => context.localized.mediaTypePerson,
|
FladderItemType.person => context.localized.mediaTypePerson,
|
||||||
FladderItemType.photoalbum => context.localized.mediaTypePhotoAlbum,
|
FladderItemType.photoAlbum => context.localized.mediaTypePhotoAlbum,
|
||||||
FladderItemType.folder => context.localized.mediaTypeFolder,
|
FladderItemType.folder => context.localized.mediaTypeFolder,
|
||||||
FladderItemType.boxset => context.localized.mediaTypeBoxset,
|
FladderItemType.boxset => context.localized.mediaTypeBoxset,
|
||||||
FladderItemType.playlist => context.localized.mediaTypePlaylist,
|
FladderItemType.playlist => context.localized.mediaTypePlaylist,
|
||||||
|
|
@ -352,7 +352,7 @@ enum FladderItemType {
|
||||||
FladderItemType.episode => BaseItemKind.episode,
|
FladderItemType.episode => BaseItemKind.episode,
|
||||||
FladderItemType.photo => BaseItemKind.photo,
|
FladderItemType.photo => BaseItemKind.photo,
|
||||||
FladderItemType.person => BaseItemKind.person,
|
FladderItemType.person => BaseItemKind.person,
|
||||||
FladderItemType.photoalbum => BaseItemKind.photoalbum,
|
FladderItemType.photoAlbum => BaseItemKind.photoalbum,
|
||||||
FladderItemType.folder => BaseItemKind.folder,
|
FladderItemType.folder => BaseItemKind.folder,
|
||||||
FladderItemType.boxset => BaseItemKind.boxset,
|
FladderItemType.boxset => BaseItemKind.boxset,
|
||||||
FladderItemType.playlist => BaseItemKind.playlist,
|
FladderItemType.playlist => BaseItemKind.playlist,
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:dart_mappable/dart_mappable.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart';
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart' as dto;
|
||||||
import 'package:fladder/models/items/images_models.dart';
|
import 'package:fladder/models/items/images_models.dart';
|
||||||
|
|
||||||
import 'package:dart_mappable/dart_mappable.dart';
|
|
||||||
import 'package:json_annotation/json_annotation.dart';
|
|
||||||
|
|
||||||
part 'item_shared_models.mapper.dart';
|
part 'item_shared_models.mapper.dart';
|
||||||
|
|
||||||
@MappableClass()
|
@MappableClass()
|
||||||
|
|
|
||||||
79
lib/models/library_filters_model.dart
Normal file
79
lib/models/library_filters_model.dart
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:xid/xid.dart';
|
||||||
|
|
||||||
|
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart';
|
||||||
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
||||||
|
import 'package:fladder/models/item_base_model.dart';
|
||||||
|
import 'package:fladder/models/items/item_shared_models.dart';
|
||||||
|
import 'package:fladder/models/library_search/library_search_model.dart';
|
||||||
|
import 'package:fladder/models/library_search/library_search_options.dart';
|
||||||
|
import 'package:fladder/util/map_bool_helper.dart';
|
||||||
|
|
||||||
|
part 'library_filters_model.freezed.dart';
|
||||||
|
part 'library_filters_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class LibraryFiltersModel with _$LibraryFiltersModel {
|
||||||
|
const LibraryFiltersModel._();
|
||||||
|
|
||||||
|
factory LibraryFiltersModel._internal({
|
||||||
|
required String id,
|
||||||
|
required String name,
|
||||||
|
@Default(false) isFavourite,
|
||||||
|
required List<String> ids,
|
||||||
|
required Map<String, bool> genres,
|
||||||
|
required Map<ItemFilter, bool> filters,
|
||||||
|
@StudioEncoder() required Map<Studio, bool> studios,
|
||||||
|
required Map<String, bool> tags,
|
||||||
|
required Map<int, bool> years,
|
||||||
|
required Map<String, bool> officialRatings,
|
||||||
|
required Map<FladderItemType, bool> types,
|
||||||
|
required SortingOptions sortingOption,
|
||||||
|
required SortingOrder sortOrder,
|
||||||
|
required bool favourites,
|
||||||
|
required bool hideEmptyShows,
|
||||||
|
required bool recursive,
|
||||||
|
required GroupBy groupBy,
|
||||||
|
}) = _LibraryFiltersModel;
|
||||||
|
|
||||||
|
factory LibraryFiltersModel.fromJson(Map<String, dynamic> json) => _$LibraryFiltersModelFromJson(json);
|
||||||
|
|
||||||
|
factory LibraryFiltersModel.fromLibrarySearch(String name, LibrarySearchModel searchModel) {
|
||||||
|
return LibraryFiltersModel._internal(
|
||||||
|
id: Xid().toString(),
|
||||||
|
name: name,
|
||||||
|
ids: searchModel.views.included.map((e) => e.id).toList(),
|
||||||
|
genres: searchModel.genres,
|
||||||
|
filters: searchModel.filters,
|
||||||
|
studios: searchModel.studios,
|
||||||
|
tags: searchModel.tags,
|
||||||
|
years: searchModel.years,
|
||||||
|
officialRatings: searchModel.officialRatings,
|
||||||
|
types: searchModel.types,
|
||||||
|
sortingOption: searchModel.sortingOption,
|
||||||
|
sortOrder: searchModel.sortOrder,
|
||||||
|
favourites: searchModel.favourites,
|
||||||
|
hideEmptyShows: searchModel.hideEmptyShows,
|
||||||
|
recursive: searchModel.recursive,
|
||||||
|
groupBy: searchModel.groupBy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool containsSameIds(List<String> otherIds) => ids.length == otherIds.length && Set.from(ids).containsAll(otherIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
class StudioEncoder implements JsonConverter<Map<Studio, bool>, String> {
|
||||||
|
const StudioEncoder();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<Studio, bool> fromJson(String json) {
|
||||||
|
final decodedMap = jsonDecode(json) as Map<dynamic, dynamic>;
|
||||||
|
final studios = decodedMap.map((key, value) => MapEntry(Studio.fromJson(key), value as bool));
|
||||||
|
return studios;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toJson(Map<Studio, bool> studios) => jsonEncode(studios.map((key, value) => MapEntry(key.toJson(), value)));
|
||||||
|
}
|
||||||
573
lib/models/library_filters_model.freezed.dart
Normal file
573
lib/models/library_filters_model.freezed.dart
Normal file
|
|
@ -0,0 +1,573 @@
|
||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'library_filters_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||||
|
|
||||||
|
LibraryFiltersModel _$LibraryFiltersModelFromJson(Map<String, dynamic> json) {
|
||||||
|
return _LibraryFiltersModel.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$LibraryFiltersModel {
|
||||||
|
String get id => throw _privateConstructorUsedError;
|
||||||
|
String get name => throw _privateConstructorUsedError;
|
||||||
|
dynamic get isFavourite => throw _privateConstructorUsedError;
|
||||||
|
List<String> get ids => throw _privateConstructorUsedError;
|
||||||
|
Map<String, bool> get genres => throw _privateConstructorUsedError;
|
||||||
|
Map<ItemFilter, bool> get filters => throw _privateConstructorUsedError;
|
||||||
|
@StudioEncoder()
|
||||||
|
Map<Studio, bool> get studios => throw _privateConstructorUsedError;
|
||||||
|
Map<String, bool> get tags => throw _privateConstructorUsedError;
|
||||||
|
Map<int, bool> get years => throw _privateConstructorUsedError;
|
||||||
|
Map<String, bool> get officialRatings => throw _privateConstructorUsedError;
|
||||||
|
Map<FladderItemType, bool> get types => throw _privateConstructorUsedError;
|
||||||
|
SortingOptions get sortingOption => throw _privateConstructorUsedError;
|
||||||
|
SortingOrder get sortOrder => throw _privateConstructorUsedError;
|
||||||
|
bool get favourites => throw _privateConstructorUsedError;
|
||||||
|
bool get hideEmptyShows => throw _privateConstructorUsedError;
|
||||||
|
bool get recursive => throw _privateConstructorUsedError;
|
||||||
|
GroupBy get groupBy => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Serializes this LibraryFiltersModel to a JSON map.
|
||||||
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of LibraryFiltersModel
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$LibraryFiltersModelCopyWith<LibraryFiltersModel> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $LibraryFiltersModelCopyWith<$Res> {
|
||||||
|
factory $LibraryFiltersModelCopyWith(
|
||||||
|
LibraryFiltersModel value, $Res Function(LibraryFiltersModel) then) =
|
||||||
|
_$LibraryFiltersModelCopyWithImpl<$Res, LibraryFiltersModel>;
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String id,
|
||||||
|
String name,
|
||||||
|
dynamic isFavourite,
|
||||||
|
List<String> ids,
|
||||||
|
Map<String, bool> genres,
|
||||||
|
Map<ItemFilter, bool> filters,
|
||||||
|
@StudioEncoder() Map<Studio, bool> studios,
|
||||||
|
Map<String, bool> tags,
|
||||||
|
Map<int, bool> years,
|
||||||
|
Map<String, bool> officialRatings,
|
||||||
|
Map<FladderItemType, bool> types,
|
||||||
|
SortingOptions sortingOption,
|
||||||
|
SortingOrder sortOrder,
|
||||||
|
bool favourites,
|
||||||
|
bool hideEmptyShows,
|
||||||
|
bool recursive,
|
||||||
|
GroupBy groupBy});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$LibraryFiltersModelCopyWithImpl<$Res, $Val extends LibraryFiltersModel>
|
||||||
|
implements $LibraryFiltersModelCopyWith<$Res> {
|
||||||
|
_$LibraryFiltersModelCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of LibraryFiltersModel
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? isFavourite = freezed,
|
||||||
|
Object? ids = null,
|
||||||
|
Object? genres = null,
|
||||||
|
Object? filters = null,
|
||||||
|
Object? studios = null,
|
||||||
|
Object? tags = null,
|
||||||
|
Object? years = null,
|
||||||
|
Object? officialRatings = null,
|
||||||
|
Object? types = null,
|
||||||
|
Object? sortingOption = null,
|
||||||
|
Object? sortOrder = null,
|
||||||
|
Object? favourites = null,
|
||||||
|
Object? hideEmptyShows = null,
|
||||||
|
Object? recursive = null,
|
||||||
|
Object? groupBy = null,
|
||||||
|
}) {
|
||||||
|
return _then(_value.copyWith(
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
isFavourite: freezed == isFavourite
|
||||||
|
? _value.isFavourite
|
||||||
|
: isFavourite // ignore: cast_nullable_to_non_nullable
|
||||||
|
as dynamic,
|
||||||
|
ids: null == ids
|
||||||
|
? _value.ids
|
||||||
|
: ids // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>,
|
||||||
|
genres: null == genres
|
||||||
|
? _value.genres
|
||||||
|
: genres // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,
|
||||||
|
filters: null == filters
|
||||||
|
? _value.filters
|
||||||
|
: filters // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<ItemFilter, bool>,
|
||||||
|
studios: null == studios
|
||||||
|
? _value.studios
|
||||||
|
: studios // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<Studio, bool>,
|
||||||
|
tags: null == tags
|
||||||
|
? _value.tags
|
||||||
|
: tags // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,
|
||||||
|
years: null == years
|
||||||
|
? _value.years
|
||||||
|
: years // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<int, bool>,
|
||||||
|
officialRatings: null == officialRatings
|
||||||
|
? _value.officialRatings
|
||||||
|
: officialRatings // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,
|
||||||
|
types: null == types
|
||||||
|
? _value.types
|
||||||
|
: types // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<FladderItemType, bool>,
|
||||||
|
sortingOption: null == sortingOption
|
||||||
|
? _value.sortingOption
|
||||||
|
: sortingOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SortingOptions,
|
||||||
|
sortOrder: null == sortOrder
|
||||||
|
? _value.sortOrder
|
||||||
|
: sortOrder // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SortingOrder,
|
||||||
|
favourites: null == favourites
|
||||||
|
? _value.favourites
|
||||||
|
: favourites // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
hideEmptyShows: null == hideEmptyShows
|
||||||
|
? _value.hideEmptyShows
|
||||||
|
: hideEmptyShows // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
recursive: null == recursive
|
||||||
|
? _value.recursive
|
||||||
|
: recursive // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
groupBy: null == groupBy
|
||||||
|
? _value.groupBy
|
||||||
|
: groupBy // ignore: cast_nullable_to_non_nullable
|
||||||
|
as GroupBy,
|
||||||
|
) as $Val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$LibraryFiltersModelImplCopyWith<$Res>
|
||||||
|
implements $LibraryFiltersModelCopyWith<$Res> {
|
||||||
|
factory _$$LibraryFiltersModelImplCopyWith(_$LibraryFiltersModelImpl value,
|
||||||
|
$Res Function(_$LibraryFiltersModelImpl) then) =
|
||||||
|
__$$LibraryFiltersModelImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call(
|
||||||
|
{String id,
|
||||||
|
String name,
|
||||||
|
dynamic isFavourite,
|
||||||
|
List<String> ids,
|
||||||
|
Map<String, bool> genres,
|
||||||
|
Map<ItemFilter, bool> filters,
|
||||||
|
@StudioEncoder() Map<Studio, bool> studios,
|
||||||
|
Map<String, bool> tags,
|
||||||
|
Map<int, bool> years,
|
||||||
|
Map<String, bool> officialRatings,
|
||||||
|
Map<FladderItemType, bool> types,
|
||||||
|
SortingOptions sortingOption,
|
||||||
|
SortingOrder sortOrder,
|
||||||
|
bool favourites,
|
||||||
|
bool hideEmptyShows,
|
||||||
|
bool recursive,
|
||||||
|
GroupBy groupBy});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$LibraryFiltersModelImplCopyWithImpl<$Res>
|
||||||
|
extends _$LibraryFiltersModelCopyWithImpl<$Res, _$LibraryFiltersModelImpl>
|
||||||
|
implements _$$LibraryFiltersModelImplCopyWith<$Res> {
|
||||||
|
__$$LibraryFiltersModelImplCopyWithImpl(_$LibraryFiltersModelImpl _value,
|
||||||
|
$Res Function(_$LibraryFiltersModelImpl) _then)
|
||||||
|
: super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of LibraryFiltersModel
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({
|
||||||
|
Object? id = null,
|
||||||
|
Object? name = null,
|
||||||
|
Object? isFavourite = freezed,
|
||||||
|
Object? ids = null,
|
||||||
|
Object? genres = null,
|
||||||
|
Object? filters = null,
|
||||||
|
Object? studios = null,
|
||||||
|
Object? tags = null,
|
||||||
|
Object? years = null,
|
||||||
|
Object? officialRatings = null,
|
||||||
|
Object? types = null,
|
||||||
|
Object? sortingOption = null,
|
||||||
|
Object? sortOrder = null,
|
||||||
|
Object? favourites = null,
|
||||||
|
Object? hideEmptyShows = null,
|
||||||
|
Object? recursive = null,
|
||||||
|
Object? groupBy = null,
|
||||||
|
}) {
|
||||||
|
return _then(_$LibraryFiltersModelImpl(
|
||||||
|
id: null == id
|
||||||
|
? _value.id
|
||||||
|
: id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
name: null == name
|
||||||
|
? _value.name
|
||||||
|
: name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
isFavourite: freezed == isFavourite ? _value.isFavourite! : isFavourite,
|
||||||
|
ids: null == ids
|
||||||
|
? _value._ids
|
||||||
|
: ids // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>,
|
||||||
|
genres: null == genres
|
||||||
|
? _value._genres
|
||||||
|
: genres // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,
|
||||||
|
filters: null == filters
|
||||||
|
? _value._filters
|
||||||
|
: filters // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<ItemFilter, bool>,
|
||||||
|
studios: null == studios
|
||||||
|
? _value._studios
|
||||||
|
: studios // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<Studio, bool>,
|
||||||
|
tags: null == tags
|
||||||
|
? _value._tags
|
||||||
|
: tags // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,
|
||||||
|
years: null == years
|
||||||
|
? _value._years
|
||||||
|
: years // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<int, bool>,
|
||||||
|
officialRatings: null == officialRatings
|
||||||
|
? _value._officialRatings
|
||||||
|
: officialRatings // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,
|
||||||
|
types: null == types
|
||||||
|
? _value._types
|
||||||
|
: types // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<FladderItemType, bool>,
|
||||||
|
sortingOption: null == sortingOption
|
||||||
|
? _value.sortingOption
|
||||||
|
: sortingOption // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SortingOptions,
|
||||||
|
sortOrder: null == sortOrder
|
||||||
|
? _value.sortOrder
|
||||||
|
: sortOrder // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SortingOrder,
|
||||||
|
favourites: null == favourites
|
||||||
|
? _value.favourites
|
||||||
|
: favourites // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
hideEmptyShows: null == hideEmptyShows
|
||||||
|
? _value.hideEmptyShows
|
||||||
|
: hideEmptyShows // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
recursive: null == recursive
|
||||||
|
? _value.recursive
|
||||||
|
: recursive // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
|
groupBy: null == groupBy
|
||||||
|
? _value.groupBy
|
||||||
|
: groupBy // ignore: cast_nullable_to_non_nullable
|
||||||
|
as GroupBy,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
class _$LibraryFiltersModelImpl extends _LibraryFiltersModel {
|
||||||
|
_$LibraryFiltersModelImpl(
|
||||||
|
{required this.id,
|
||||||
|
required this.name,
|
||||||
|
this.isFavourite = false,
|
||||||
|
required final List<String> ids,
|
||||||
|
required final Map<String, bool> genres,
|
||||||
|
required final Map<ItemFilter, bool> filters,
|
||||||
|
@StudioEncoder() required final Map<Studio, bool> studios,
|
||||||
|
required final Map<String, bool> tags,
|
||||||
|
required final Map<int, bool> years,
|
||||||
|
required final Map<String, bool> officialRatings,
|
||||||
|
required final Map<FladderItemType, bool> types,
|
||||||
|
required this.sortingOption,
|
||||||
|
required this.sortOrder,
|
||||||
|
required this.favourites,
|
||||||
|
required this.hideEmptyShows,
|
||||||
|
required this.recursive,
|
||||||
|
required this.groupBy})
|
||||||
|
: _ids = ids,
|
||||||
|
_genres = genres,
|
||||||
|
_filters = filters,
|
||||||
|
_studios = studios,
|
||||||
|
_tags = tags,
|
||||||
|
_years = years,
|
||||||
|
_officialRatings = officialRatings,
|
||||||
|
_types = types,
|
||||||
|
super._();
|
||||||
|
|
||||||
|
factory _$LibraryFiltersModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$$LibraryFiltersModelImplFromJson(json);
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String name;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final dynamic isFavourite;
|
||||||
|
final List<String> _ids;
|
||||||
|
@override
|
||||||
|
List<String> get ids {
|
||||||
|
if (_ids is EqualUnmodifiableListView) return _ids;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, bool> _genres;
|
||||||
|
@override
|
||||||
|
Map<String, bool> get genres {
|
||||||
|
if (_genres is EqualUnmodifiableMapView) return _genres;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_genres);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<ItemFilter, bool> _filters;
|
||||||
|
@override
|
||||||
|
Map<ItemFilter, bool> get filters {
|
||||||
|
if (_filters is EqualUnmodifiableMapView) return _filters;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<Studio, bool> _studios;
|
||||||
|
@override
|
||||||
|
@StudioEncoder()
|
||||||
|
Map<Studio, bool> get studios {
|
||||||
|
if (_studios is EqualUnmodifiableMapView) return _studios;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_studios);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, bool> _tags;
|
||||||
|
@override
|
||||||
|
Map<String, bool> get tags {
|
||||||
|
if (_tags is EqualUnmodifiableMapView) return _tags;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<int, bool> _years;
|
||||||
|
@override
|
||||||
|
Map<int, bool> get years {
|
||||||
|
if (_years is EqualUnmodifiableMapView) return _years;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_years);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, bool> _officialRatings;
|
||||||
|
@override
|
||||||
|
Map<String, bool> get officialRatings {
|
||||||
|
if (_officialRatings is EqualUnmodifiableMapView) return _officialRatings;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_officialRatings);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<FladderItemType, bool> _types;
|
||||||
|
@override
|
||||||
|
Map<FladderItemType, bool> get types {
|
||||||
|
if (_types is EqualUnmodifiableMapView) return _types;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_types);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
final SortingOptions sortingOption;
|
||||||
|
@override
|
||||||
|
final SortingOrder sortOrder;
|
||||||
|
@override
|
||||||
|
final bool favourites;
|
||||||
|
@override
|
||||||
|
final bool hideEmptyShows;
|
||||||
|
@override
|
||||||
|
final bool recursive;
|
||||||
|
@override
|
||||||
|
final GroupBy groupBy;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'LibraryFiltersModel._internal(id: $id, name: $name, isFavourite: $isFavourite, ids: $ids, genres: $genres, filters: $filters, studios: $studios, tags: $tags, years: $years, officialRatings: $officialRatings, types: $types, sortingOption: $sortingOption, sortOrder: $sortOrder, favourites: $favourites, hideEmptyShows: $hideEmptyShows, recursive: $recursive, groupBy: $groupBy)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$LibraryFiltersModelImpl &&
|
||||||
|
(identical(other.id, id) || other.id == id) &&
|
||||||
|
(identical(other.name, name) || other.name == name) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other.isFavourite, isFavourite) &&
|
||||||
|
const DeepCollectionEquality().equals(other._ids, _ids) &&
|
||||||
|
const DeepCollectionEquality().equals(other._genres, _genres) &&
|
||||||
|
const DeepCollectionEquality().equals(other._filters, _filters) &&
|
||||||
|
const DeepCollectionEquality().equals(other._studios, _studios) &&
|
||||||
|
const DeepCollectionEquality().equals(other._tags, _tags) &&
|
||||||
|
const DeepCollectionEquality().equals(other._years, _years) &&
|
||||||
|
const DeepCollectionEquality()
|
||||||
|
.equals(other._officialRatings, _officialRatings) &&
|
||||||
|
const DeepCollectionEquality().equals(other._types, _types) &&
|
||||||
|
(identical(other.sortingOption, sortingOption) ||
|
||||||
|
other.sortingOption == sortingOption) &&
|
||||||
|
(identical(other.sortOrder, sortOrder) ||
|
||||||
|
other.sortOrder == sortOrder) &&
|
||||||
|
(identical(other.favourites, favourites) ||
|
||||||
|
other.favourites == favourites) &&
|
||||||
|
(identical(other.hideEmptyShows, hideEmptyShows) ||
|
||||||
|
other.hideEmptyShows == hideEmptyShows) &&
|
||||||
|
(identical(other.recursive, recursive) ||
|
||||||
|
other.recursive == recursive) &&
|
||||||
|
(identical(other.groupBy, groupBy) || other.groupBy == groupBy));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
const DeepCollectionEquality().hash(isFavourite),
|
||||||
|
const DeepCollectionEquality().hash(_ids),
|
||||||
|
const DeepCollectionEquality().hash(_genres),
|
||||||
|
const DeepCollectionEquality().hash(_filters),
|
||||||
|
const DeepCollectionEquality().hash(_studios),
|
||||||
|
const DeepCollectionEquality().hash(_tags),
|
||||||
|
const DeepCollectionEquality().hash(_years),
|
||||||
|
const DeepCollectionEquality().hash(_officialRatings),
|
||||||
|
const DeepCollectionEquality().hash(_types),
|
||||||
|
sortingOption,
|
||||||
|
sortOrder,
|
||||||
|
favourites,
|
||||||
|
hideEmptyShows,
|
||||||
|
recursive,
|
||||||
|
groupBy);
|
||||||
|
|
||||||
|
/// Create a copy of LibraryFiltersModel
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$LibraryFiltersModelImplCopyWith<_$LibraryFiltersModelImpl> get copyWith =>
|
||||||
|
__$$LibraryFiltersModelImplCopyWithImpl<_$LibraryFiltersModelImpl>(
|
||||||
|
this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$$LibraryFiltersModelImplToJson(
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _LibraryFiltersModel extends LibraryFiltersModel {
|
||||||
|
factory _LibraryFiltersModel(
|
||||||
|
{required final String id,
|
||||||
|
required final String name,
|
||||||
|
final dynamic isFavourite,
|
||||||
|
required final List<String> ids,
|
||||||
|
required final Map<String, bool> genres,
|
||||||
|
required final Map<ItemFilter, bool> filters,
|
||||||
|
@StudioEncoder() required final Map<Studio, bool> studios,
|
||||||
|
required final Map<String, bool> tags,
|
||||||
|
required final Map<int, bool> years,
|
||||||
|
required final Map<String, bool> officialRatings,
|
||||||
|
required final Map<FladderItemType, bool> types,
|
||||||
|
required final SortingOptions sortingOption,
|
||||||
|
required final SortingOrder sortOrder,
|
||||||
|
required final bool favourites,
|
||||||
|
required final bool hideEmptyShows,
|
||||||
|
required final bool recursive,
|
||||||
|
required final GroupBy groupBy}) = _$LibraryFiltersModelImpl;
|
||||||
|
_LibraryFiltersModel._() : super._();
|
||||||
|
|
||||||
|
factory _LibraryFiltersModel.fromJson(Map<String, dynamic> json) =
|
||||||
|
_$LibraryFiltersModelImpl.fromJson;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get id;
|
||||||
|
@override
|
||||||
|
String get name;
|
||||||
|
@override
|
||||||
|
dynamic get isFavourite;
|
||||||
|
@override
|
||||||
|
List<String> get ids;
|
||||||
|
@override
|
||||||
|
Map<String, bool> get genres;
|
||||||
|
@override
|
||||||
|
Map<ItemFilter, bool> get filters;
|
||||||
|
@override
|
||||||
|
@StudioEncoder()
|
||||||
|
Map<Studio, bool> get studios;
|
||||||
|
@override
|
||||||
|
Map<String, bool> get tags;
|
||||||
|
@override
|
||||||
|
Map<int, bool> get years;
|
||||||
|
@override
|
||||||
|
Map<String, bool> get officialRatings;
|
||||||
|
@override
|
||||||
|
Map<FladderItemType, bool> get types;
|
||||||
|
@override
|
||||||
|
SortingOptions get sortingOption;
|
||||||
|
@override
|
||||||
|
SortingOrder get sortOrder;
|
||||||
|
@override
|
||||||
|
bool get favourites;
|
||||||
|
@override
|
||||||
|
bool get hideEmptyShows;
|
||||||
|
@override
|
||||||
|
bool get recursive;
|
||||||
|
@override
|
||||||
|
GroupBy get groupBy;
|
||||||
|
|
||||||
|
/// Create a copy of LibraryFiltersModel
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$LibraryFiltersModelImplCopyWith<_$LibraryFiltersModelImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
124
lib/models/library_filters_model.g.dart
Normal file
124
lib/models/library_filters_model.g.dart
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'library_filters_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_$LibraryFiltersModelImpl _$$LibraryFiltersModelImplFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
_$LibraryFiltersModelImpl(
|
||||||
|
id: json['id'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
isFavourite: json['isFavourite'] ?? false,
|
||||||
|
ids: (json['ids'] as List<dynamic>).map((e) => e as String).toList(),
|
||||||
|
genres: Map<String, bool>.from(json['genres'] as Map),
|
||||||
|
filters: (json['filters'] as Map<String, dynamic>).map(
|
||||||
|
(k, e) => MapEntry($enumDecode(_$ItemFilterEnumMap, k), e as bool),
|
||||||
|
),
|
||||||
|
studios: const StudioEncoder().fromJson(json['studios'] as String),
|
||||||
|
tags: Map<String, bool>.from(json['tags'] as Map),
|
||||||
|
years: (json['years'] as Map<String, dynamic>).map(
|
||||||
|
(k, e) => MapEntry(int.parse(k), e as bool),
|
||||||
|
),
|
||||||
|
officialRatings: Map<String, bool>.from(json['officialRatings'] as Map),
|
||||||
|
types: (json['types'] as Map<String, dynamic>).map(
|
||||||
|
(k, e) => MapEntry($enumDecode(_$FladderItemTypeEnumMap, k), e as bool),
|
||||||
|
),
|
||||||
|
sortingOption:
|
||||||
|
$enumDecode(_$SortingOptionsEnumMap, json['sortingOption']),
|
||||||
|
sortOrder: $enumDecode(_$SortingOrderEnumMap, json['sortOrder']),
|
||||||
|
favourites: json['favourites'] as bool,
|
||||||
|
hideEmptyShows: json['hideEmptyShows'] as bool,
|
||||||
|
recursive: json['recursive'] as bool,
|
||||||
|
groupBy: $enumDecode(_$GroupByEnumMap, json['groupBy']),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$$LibraryFiltersModelImplToJson(
|
||||||
|
_$LibraryFiltersModelImpl instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'name': instance.name,
|
||||||
|
'isFavourite': instance.isFavourite,
|
||||||
|
'ids': instance.ids,
|
||||||
|
'genres': instance.genres,
|
||||||
|
'filters':
|
||||||
|
instance.filters.map((k, e) => MapEntry(_$ItemFilterEnumMap[k], e)),
|
||||||
|
'studios': const StudioEncoder().toJson(instance.studios),
|
||||||
|
'tags': instance.tags,
|
||||||
|
'years': instance.years.map((k, e) => MapEntry(k.toString(), e)),
|
||||||
|
'officialRatings': instance.officialRatings,
|
||||||
|
'types': instance.types
|
||||||
|
.map((k, e) => MapEntry(_$FladderItemTypeEnumMap[k]!, e)),
|
||||||
|
'sortingOption': _$SortingOptionsEnumMap[instance.sortingOption]!,
|
||||||
|
'sortOrder': _$SortingOrderEnumMap[instance.sortOrder]!,
|
||||||
|
'favourites': instance.favourites,
|
||||||
|
'hideEmptyShows': instance.hideEmptyShows,
|
||||||
|
'recursive': instance.recursive,
|
||||||
|
'groupBy': _$GroupByEnumMap[instance.groupBy]!,
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$ItemFilterEnumMap = {
|
||||||
|
ItemFilter.swaggerGeneratedUnknown: null,
|
||||||
|
ItemFilter.isfolder: 'IsFolder',
|
||||||
|
ItemFilter.isnotfolder: 'IsNotFolder',
|
||||||
|
ItemFilter.isunplayed: 'IsUnplayed',
|
||||||
|
ItemFilter.isplayed: 'IsPlayed',
|
||||||
|
ItemFilter.isfavorite: 'IsFavorite',
|
||||||
|
ItemFilter.isresumable: 'IsResumable',
|
||||||
|
ItemFilter.likes: 'Likes',
|
||||||
|
ItemFilter.dislikes: 'Dislikes',
|
||||||
|
ItemFilter.isfavoriteorlikes: 'IsFavoriteOrLikes',
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$FladderItemTypeEnumMap = {
|
||||||
|
FladderItemType.baseType: 'baseType',
|
||||||
|
FladderItemType.audio: 'audio',
|
||||||
|
FladderItemType.musicAlbum: 'musicAlbum',
|
||||||
|
FladderItemType.musicVideo: 'musicVideo',
|
||||||
|
FladderItemType.collectionFolder: 'collectionFolder',
|
||||||
|
FladderItemType.video: 'video',
|
||||||
|
FladderItemType.movie: 'movie',
|
||||||
|
FladderItemType.series: 'series',
|
||||||
|
FladderItemType.season: 'season',
|
||||||
|
FladderItemType.episode: 'episode',
|
||||||
|
FladderItemType.photo: 'photo',
|
||||||
|
FladderItemType.person: 'person',
|
||||||
|
FladderItemType.photoAlbum: 'photoAlbum',
|
||||||
|
FladderItemType.folder: 'folder',
|
||||||
|
FladderItemType.boxset: 'boxset',
|
||||||
|
FladderItemType.playlist: 'playlist',
|
||||||
|
FladderItemType.book: 'book',
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$SortingOptionsEnumMap = {
|
||||||
|
SortingOptions.name: 'name',
|
||||||
|
SortingOptions.communityRating: 'communityRating',
|
||||||
|
SortingOptions.parentalRating: 'parentalRating',
|
||||||
|
SortingOptions.dateAdded: 'dateAdded',
|
||||||
|
SortingOptions.dateLastContentAdded: 'dateLastContentAdded',
|
||||||
|
SortingOptions.favorite: 'favorite',
|
||||||
|
SortingOptions.datePlayed: 'datePlayed',
|
||||||
|
SortingOptions.folders: 'folders',
|
||||||
|
SortingOptions.playCount: 'playCount',
|
||||||
|
SortingOptions.releaseDate: 'releaseDate',
|
||||||
|
SortingOptions.runTime: 'runTime',
|
||||||
|
SortingOptions.random: 'random',
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$SortingOrderEnumMap = {
|
||||||
|
SortingOrder.ascending: 'ascending',
|
||||||
|
SortingOrder.descending: 'descending',
|
||||||
|
};
|
||||||
|
|
||||||
|
const _$GroupByEnumMap = {
|
||||||
|
GroupBy.none: 'none',
|
||||||
|
GroupBy.name: 'name',
|
||||||
|
GroupBy.genres: 'genres',
|
||||||
|
GroupBy.dateAdded: 'dateAdded',
|
||||||
|
GroupBy.tags: 'tags',
|
||||||
|
GroupBy.releaseDate: 'releaseDate',
|
||||||
|
GroupBy.rating: 'rating',
|
||||||
|
GroupBy.type: 'type',
|
||||||
|
};
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:dart_mappable/dart_mappable.dart';
|
|
||||||
import 'package:fladder/util/list_extensions.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:dart_mappable/dart_mappable.dart';
|
||||||
|
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart';
|
import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart';
|
||||||
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
import 'package:fladder/jellyfin/jellyfin_open_api.swagger.dart';
|
||||||
import 'package:fladder/models/item_base_model.dart';
|
import 'package:fladder/models/item_base_model.dart';
|
||||||
import 'package:fladder/models/items/item_shared_models.dart';
|
import 'package:fladder/models/items/item_shared_models.dart';
|
||||||
import 'package:fladder/models/library_search/library_search_options.dart';
|
import 'package:fladder/models/library_search/library_search_options.dart';
|
||||||
import 'package:fladder/models/view_model.dart';
|
import 'package:fladder/models/view_model.dart';
|
||||||
|
import 'package:fladder/util/list_extensions.dart';
|
||||||
import 'package:fladder/util/localization_helper.dart';
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
import 'package:fladder/util/map_bool_helper.dart';
|
import 'package:fladder/util/map_bool_helper.dart';
|
||||||
|
|
||||||
|
|
@ -34,7 +35,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
||||||
final SortingOptions sortingOption;
|
final SortingOptions sortingOption;
|
||||||
final SortingOrder sortOrder;
|
final SortingOrder sortOrder;
|
||||||
final bool favourites;
|
final bool favourites;
|
||||||
final bool hideEmtpyShows;
|
final bool hideEmptyShows;
|
||||||
final bool recursive;
|
final bool recursive;
|
||||||
final GroupBy groupBy;
|
final GroupBy groupBy;
|
||||||
final Map<String, int> lastIndices;
|
final Map<String, int> lastIndices;
|
||||||
|
|
@ -71,14 +72,14 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
||||||
FladderItemType.musicVideo: false,
|
FladderItemType.musicVideo: false,
|
||||||
FladderItemType.photo: false,
|
FladderItemType.photo: false,
|
||||||
FladderItemType.person: false,
|
FladderItemType.person: false,
|
||||||
FladderItemType.photoalbum: false,
|
FladderItemType.photoAlbum: false,
|
||||||
FladderItemType.series: true,
|
FladderItemType.series: true,
|
||||||
FladderItemType.video: true,
|
FladderItemType.video: true,
|
||||||
},
|
},
|
||||||
this.favourites = false,
|
this.favourites = false,
|
||||||
this.sortingOption = SortingOptions.name,
|
this.sortingOption = SortingOptions.name,
|
||||||
this.sortOrder = SortingOrder.ascending,
|
this.sortOrder = SortingOrder.ascending,
|
||||||
this.hideEmtpyShows = true,
|
this.hideEmptyShows = true,
|
||||||
this.recursive = false,
|
this.recursive = false,
|
||||||
this.groupBy = GroupBy.none,
|
this.groupBy = GroupBy.none,
|
||||||
this.lastIndices = const {},
|
this.lastIndices = const {},
|
||||||
|
|
@ -92,7 +93,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
||||||
tags.hasEnabled ||
|
tags.hasEnabled ||
|
||||||
years.hasEnabled ||
|
years.hasEnabled ||
|
||||||
officialRatings.hasEnabled ||
|
officialRatings.hasEnabled ||
|
||||||
hideEmtpyShows ||
|
hideEmptyShows ||
|
||||||
filters.hasEnabled ||
|
filters.hasEnabled ||
|
||||||
favourites ||
|
favourites ||
|
||||||
searchQuery.isNotEmpty;
|
searchQuery.isNotEmpty;
|
||||||
|
|
@ -146,7 +147,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
||||||
if (totalItemCount == 0) return false;
|
if (totalItemCount == 0) return false;
|
||||||
return types.included.isEmpty ||
|
return types.included.isEmpty ||
|
||||||
types.included.containsAny(
|
types.included.containsAny(
|
||||||
{...FladderItemType.galleryItem, FladderItemType.photoalbum, FladderItemType.folder},
|
{...FladderItemType.galleryItem, FladderItemType.photoAlbum, FladderItemType.folder},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +178,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
||||||
favourites: false,
|
favourites: false,
|
||||||
recursive: false,
|
recursive: false,
|
||||||
studios: const {},
|
studios: const {},
|
||||||
hideEmtpyShows: true,
|
hideEmptyShows: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
||||||
FladderItemType.musicVideo: false,
|
FladderItemType.musicVideo: false,
|
||||||
FladderItemType.photo: false,
|
FladderItemType.photo: false,
|
||||||
FladderItemType.person: false,
|
FladderItemType.person: false,
|
||||||
FladderItemType.photoalbum: false,
|
FladderItemType.photoAlbum: false,
|
||||||
FladderItemType.series: true,
|
FladderItemType.series: true,
|
||||||
FladderItemType.video: true
|
FladderItemType.video: true
|
||||||
});
|
});
|
||||||
|
|
@ -98,9 +98,9 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
||||||
static SortingOrder _$sortOrder(LibrarySearchModel v) => v.sortOrder;
|
static SortingOrder _$sortOrder(LibrarySearchModel v) => v.sortOrder;
|
||||||
static const Field<LibrarySearchModel, SortingOrder> _f$sortOrder =
|
static const Field<LibrarySearchModel, SortingOrder> _f$sortOrder =
|
||||||
Field('sortOrder', _$sortOrder, opt: true, def: SortingOrder.ascending);
|
Field('sortOrder', _$sortOrder, opt: true, def: SortingOrder.ascending);
|
||||||
static bool _$hideEmtpyShows(LibrarySearchModel v) => v.hideEmtpyShows;
|
static bool _$hideEmptyShows(LibrarySearchModel v) => v.hideEmptyShows;
|
||||||
static const Field<LibrarySearchModel, bool> _f$hideEmtpyShows =
|
static const Field<LibrarySearchModel, bool> _f$hideEmptyShows =
|
||||||
Field('hideEmtpyShows', _$hideEmtpyShows, opt: true, def: true);
|
Field('hideEmptyShows', _$hideEmptyShows, opt: true, def: true);
|
||||||
static bool _$recursive(LibrarySearchModel v) => v.recursive;
|
static bool _$recursive(LibrarySearchModel v) => v.recursive;
|
||||||
static const Field<LibrarySearchModel, bool> _f$recursive =
|
static const Field<LibrarySearchModel, bool> _f$recursive =
|
||||||
Field('recursive', _$recursive, opt: true, def: false);
|
Field('recursive', _$recursive, opt: true, def: false);
|
||||||
|
|
@ -138,7 +138,7 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
||||||
#favourites: _f$favourites,
|
#favourites: _f$favourites,
|
||||||
#sortingOption: _f$sortingOption,
|
#sortingOption: _f$sortingOption,
|
||||||
#sortOrder: _f$sortOrder,
|
#sortOrder: _f$sortOrder,
|
||||||
#hideEmtpyShows: _f$hideEmtpyShows,
|
#hideEmptyShows: _f$hideEmptyShows,
|
||||||
#recursive: _f$recursive,
|
#recursive: _f$recursive,
|
||||||
#groupBy: _f$groupBy,
|
#groupBy: _f$groupBy,
|
||||||
#lastIndices: _f$lastIndices,
|
#lastIndices: _f$lastIndices,
|
||||||
|
|
@ -167,7 +167,7 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
||||||
favourites: data.dec(_f$favourites),
|
favourites: data.dec(_f$favourites),
|
||||||
sortingOption: data.dec(_f$sortingOption),
|
sortingOption: data.dec(_f$sortingOption),
|
||||||
sortOrder: data.dec(_f$sortOrder),
|
sortOrder: data.dec(_f$sortOrder),
|
||||||
hideEmtpyShows: data.dec(_f$hideEmtpyShows),
|
hideEmptyShows: data.dec(_f$hideEmptyShows),
|
||||||
recursive: data.dec(_f$recursive),
|
recursive: data.dec(_f$recursive),
|
||||||
groupBy: data.dec(_f$groupBy),
|
groupBy: data.dec(_f$groupBy),
|
||||||
lastIndices: data.dec(_f$lastIndices),
|
lastIndices: data.dec(_f$lastIndices),
|
||||||
|
|
@ -257,7 +257,7 @@ abstract class LibrarySearchModelCopyWith<$R, $In extends LibrarySearchModel,
|
||||||
bool? favourites,
|
bool? favourites,
|
||||||
SortingOptions? sortingOption,
|
SortingOptions? sortingOption,
|
||||||
SortingOrder? sortOrder,
|
SortingOrder? sortOrder,
|
||||||
bool? hideEmtpyShows,
|
bool? hideEmptyShows,
|
||||||
bool? recursive,
|
bool? recursive,
|
||||||
GroupBy? groupBy,
|
GroupBy? groupBy,
|
||||||
Map<String, int>? lastIndices,
|
Map<String, int>? lastIndices,
|
||||||
|
|
@ -353,7 +353,7 @@ class _LibrarySearchModelCopyWithImpl<$R, $Out>
|
||||||
bool? favourites,
|
bool? favourites,
|
||||||
SortingOptions? sortingOption,
|
SortingOptions? sortingOption,
|
||||||
SortingOrder? sortOrder,
|
SortingOrder? sortOrder,
|
||||||
bool? hideEmtpyShows,
|
bool? hideEmptyShows,
|
||||||
bool? recursive,
|
bool? recursive,
|
||||||
GroupBy? groupBy,
|
GroupBy? groupBy,
|
||||||
Map<String, int>? lastIndices,
|
Map<String, int>? lastIndices,
|
||||||
|
|
@ -377,7 +377,7 @@ class _LibrarySearchModelCopyWithImpl<$R, $Out>
|
||||||
if (favourites != null) #favourites: favourites,
|
if (favourites != null) #favourites: favourites,
|
||||||
if (sortingOption != null) #sortingOption: sortingOption,
|
if (sortingOption != null) #sortingOption: sortingOption,
|
||||||
if (sortOrder != null) #sortOrder: sortOrder,
|
if (sortOrder != null) #sortOrder: sortOrder,
|
||||||
if (hideEmtpyShows != null) #hideEmtpyShows: hideEmtpyShows,
|
if (hideEmptyShows != null) #hideEmptyShows: hideEmptyShows,
|
||||||
if (recursive != null) #recursive: recursive,
|
if (recursive != null) #recursive: recursive,
|
||||||
if (groupBy != null) #groupBy: groupBy,
|
if (groupBy != null) #groupBy: groupBy,
|
||||||
if (lastIndices != null) #lastIndices: lastIndices,
|
if (lastIndices != null) #lastIndices: lastIndices,
|
||||||
|
|
@ -403,7 +403,7 @@ class _LibrarySearchModelCopyWithImpl<$R, $Out>
|
||||||
favourites: data.get(#favourites, or: $value.favourites),
|
favourites: data.get(#favourites, or: $value.favourites),
|
||||||
sortingOption: data.get(#sortingOption, or: $value.sortingOption),
|
sortingOption: data.get(#sortingOption, or: $value.sortingOption),
|
||||||
sortOrder: data.get(#sortOrder, or: $value.sortOrder),
|
sortOrder: data.get(#sortOrder, or: $value.sortOrder),
|
||||||
hideEmtpyShows: data.get(#hideEmtpyShows, or: $value.hideEmtpyShows),
|
hideEmptyShows: data.get(#hideEmptyShows, or: $value.hideEmptyShows),
|
||||||
recursive: data.get(#recursive, or: $value.recursive),
|
recursive: data.get(#recursive, or: $value.recursive),
|
||||||
groupBy: data.get(#groupBy, or: $value.groupBy),
|
groupBy: data.get(#groupBy, or: $value.groupBy),
|
||||||
lastIndices: data.get(#lastIndices, or: $value.lastIndices),
|
lastIndices: data.get(#lastIndices, or: $value.lastIndices),
|
||||||
|
|
|
||||||
21
lib/providers/library_filters_provider.dart
Normal file
21
lib/providers/library_filters_provider.dart
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
import 'package:fladder/models/library_filters_model.dart';
|
||||||
|
import 'package:fladder/providers/user_provider.dart';
|
||||||
|
|
||||||
|
part 'library_filters_provider.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class LibraryFilters extends _$LibraryFilters {
|
||||||
|
@override
|
||||||
|
List<LibraryFiltersModel> build(List<String> ids) => ref.watch(
|
||||||
|
userProvider
|
||||||
|
.select((value) => (value?.savedFilters ?? []).where((element) => element.containsSameIds(ids)).toList()),
|
||||||
|
);
|
||||||
|
|
||||||
|
void removeFilter(LibraryFiltersModel model) => ref.read(userProvider.notifier).removeFilter(model);
|
||||||
|
|
||||||
|
void saveFilter(LibraryFiltersModel model) => ref.read(userProvider.notifier).saveFilter(model);
|
||||||
|
|
||||||
|
void deleteAllFilters() => ref.read(userProvider.notifier).deleteAllFilters();
|
||||||
|
}
|
||||||
174
lib/providers/library_filters_provider.g.dart
Normal file
174
lib/providers/library_filters_provider.g.dart
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'library_filters_provider.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$libraryFiltersHash() => r'7b4661651df7e0c019dca5bb7eb6433bcd8b3ebb';
|
||||||
|
|
||||||
|
/// Copied from Dart SDK
|
||||||
|
class _SystemHash {
|
||||||
|
_SystemHash._();
|
||||||
|
|
||||||
|
static int combine(int hash, int value) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + value);
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finish(int hash) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = hash ^ (hash >> 11);
|
||||||
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _$LibraryFilters
|
||||||
|
extends BuildlessAutoDisposeNotifier<List<LibraryFiltersModel>> {
|
||||||
|
late final List<String> ids;
|
||||||
|
|
||||||
|
List<LibraryFiltersModel> build(
|
||||||
|
List<String> ids,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [LibraryFilters].
|
||||||
|
@ProviderFor(LibraryFilters)
|
||||||
|
const libraryFiltersProvider = LibraryFiltersFamily();
|
||||||
|
|
||||||
|
/// See also [LibraryFilters].
|
||||||
|
class LibraryFiltersFamily extends Family<List<LibraryFiltersModel>> {
|
||||||
|
/// See also [LibraryFilters].
|
||||||
|
const LibraryFiltersFamily();
|
||||||
|
|
||||||
|
/// See also [LibraryFilters].
|
||||||
|
LibraryFiltersProvider call(
|
||||||
|
List<String> ids,
|
||||||
|
) {
|
||||||
|
return LibraryFiltersProvider(
|
||||||
|
ids,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
LibraryFiltersProvider getProviderOverride(
|
||||||
|
covariant LibraryFiltersProvider provider,
|
||||||
|
) {
|
||||||
|
return call(
|
||||||
|
provider.ids,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'libraryFiltersProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [LibraryFilters].
|
||||||
|
class LibraryFiltersProvider extends AutoDisposeNotifierProviderImpl<
|
||||||
|
LibraryFilters, List<LibraryFiltersModel>> {
|
||||||
|
/// See also [LibraryFilters].
|
||||||
|
LibraryFiltersProvider(
|
||||||
|
List<String> ids,
|
||||||
|
) : this._internal(
|
||||||
|
() => LibraryFilters()..ids = ids,
|
||||||
|
from: libraryFiltersProvider,
|
||||||
|
name: r'libraryFiltersProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$libraryFiltersHash,
|
||||||
|
dependencies: LibraryFiltersFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
LibraryFiltersFamily._allTransitiveDependencies,
|
||||||
|
ids: ids,
|
||||||
|
);
|
||||||
|
|
||||||
|
LibraryFiltersProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.ids,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final List<String> ids;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<LibraryFiltersModel> runNotifierBuild(
|
||||||
|
covariant LibraryFilters notifier,
|
||||||
|
) {
|
||||||
|
return notifier.build(
|
||||||
|
ids,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(LibraryFilters Function() create) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: LibraryFiltersProvider._internal(
|
||||||
|
() => create()..ids = ids,
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
ids: ids,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeNotifierProviderElement<LibraryFilters, List<LibraryFiltersModel>>
|
||||||
|
createElement() {
|
||||||
|
return _LibraryFiltersProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is LibraryFiltersProvider && other.ids == ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, ids.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin LibraryFiltersRef
|
||||||
|
on AutoDisposeNotifierProviderRef<List<LibraryFiltersModel>> {
|
||||||
|
/// The parameter `ids` of this provider.
|
||||||
|
List<String> get ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LibraryFiltersProviderElement extends AutoDisposeNotifierProviderElement<
|
||||||
|
LibraryFilters, List<LibraryFiltersModel>> with LibraryFiltersRef {
|
||||||
|
_LibraryFiltersProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> get ids => (origin as LibraryFiltersProvider).ids;
|
||||||
|
}
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||||
|
|
@ -13,11 +13,13 @@ import 'package:fladder/models/item_base_model.dart';
|
||||||
import 'package:fladder/models/items/folder_model.dart';
|
import 'package:fladder/models/items/folder_model.dart';
|
||||||
import 'package:fladder/models/items/item_shared_models.dart';
|
import 'package:fladder/models/items/item_shared_models.dart';
|
||||||
import 'package:fladder/models/items/photos_model.dart';
|
import 'package:fladder/models/items/photos_model.dart';
|
||||||
|
import 'package:fladder/models/library_filters_model.dart';
|
||||||
import 'package:fladder/models/library_search/library_search_model.dart';
|
import 'package:fladder/models/library_search/library_search_model.dart';
|
||||||
import 'package:fladder/models/library_search/library_search_options.dart';
|
import 'package:fladder/models/library_search/library_search_options.dart';
|
||||||
import 'package:fladder/models/playlist_model.dart';
|
import 'package:fladder/models/playlist_model.dart';
|
||||||
import 'package:fladder/models/view_model.dart';
|
import 'package:fladder/models/view_model.dart';
|
||||||
import 'package:fladder/providers/api_provider.dart';
|
import 'package:fladder/providers/api_provider.dart';
|
||||||
|
import 'package:fladder/providers/library_filters_provider.dart';
|
||||||
import 'package:fladder/providers/service_provider.dart';
|
import 'package:fladder/providers/service_provider.dart';
|
||||||
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||||
import 'package:fladder/providers/user_provider.dart';
|
import 'package:fladder/providers/user_provider.dart';
|
||||||
|
|
@ -40,6 +42,8 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
|
|
||||||
int get pageSize => ref.read(clientSettingsProvider).libraryPageSize ?? 500;
|
int get pageSize => ref.read(clientSettingsProvider).libraryPageSize ?? 500;
|
||||||
|
|
||||||
|
LibraryFiltersProvider get filterProvider => libraryFiltersProvider(state.views.included.map((e) => e.id).toList());
|
||||||
|
|
||||||
late final JellyService api = ref.read(jellyApiProvider);
|
late final JellyService api = ref.read(jellyApiProvider);
|
||||||
|
|
||||||
set loading(bool loading) => state = state.copyWith(loading: loading);
|
set loading(bool loading) => state = state.copyWith(loading: loading);
|
||||||
|
|
@ -52,6 +56,8 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
List<String>? folderId,
|
List<String>? folderId,
|
||||||
String? viewModelId,
|
String? viewModelId,
|
||||||
bool? favourites,
|
bool? favourites,
|
||||||
|
SortingOrder? sortOrder,
|
||||||
|
SortingOptions? sortingOptions,
|
||||||
) async {
|
) async {
|
||||||
loading = true;
|
loading = true;
|
||||||
state = state.resetLazyLoad();
|
state = state.resetLazyLoad();
|
||||||
|
|
@ -59,7 +65,7 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
if (folderId != null) {
|
if (folderId != null) {
|
||||||
await loadFolders(folderId: folderId);
|
await loadFolders(folderId: folderId);
|
||||||
} else {
|
} else {
|
||||||
await loadViews(viewModelId, favourites);
|
await loadViews(viewModelId, favourites, sortOrder, sortingOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +157,12 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Pas viewmodel otherwise select first
|
//Pas viewmodel otherwise select first
|
||||||
Future<void> loadViews(String? viewModelId, bool? favourites) async {
|
Future<void> loadViews(
|
||||||
|
String? viewModelId,
|
||||||
|
bool? favourites,
|
||||||
|
SortingOrder? sortOrder,
|
||||||
|
SortingOptions? sortingOptions,
|
||||||
|
) async {
|
||||||
final response = await api.usersUserIdViewsGet(includeHidden: false);
|
final response = await api.usersUserIdViewsGet(includeHidden: false);
|
||||||
final createdViews = response.body?.items?.map((e) => ViewModel.fromBodyDto(e, ref));
|
final createdViews = response.body?.items?.map((e) => ViewModel.fromBodyDto(e, ref));
|
||||||
Map<ViewModel, bool> mappedModels =
|
Map<ViewModel, bool> mappedModels =
|
||||||
|
|
@ -159,12 +170,28 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
|
|
||||||
final selectedModel = mappedModels.keys.firstWhereOrNull((element) => element.id == viewModelId);
|
final selectedModel = mappedModels.keys.firstWhereOrNull((element) => element.id == viewModelId);
|
||||||
|
|
||||||
|
final views = selectedModel != null
|
||||||
|
? mappedModels.setKey(mappedModels.keys.firstWhere((element) => element.id == viewModelId), true)
|
||||||
|
: mappedModels;
|
||||||
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
views: selectedModel != null
|
views: views,
|
||||||
? mappedModels.setKey(mappedModels.keys.firstWhere((element) => element.id == viewModelId), true)
|
|
||||||
: mappedModels,
|
|
||||||
favourites: favourites,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (sortOrder == null && sortingOptions == null && favourites == null) {
|
||||||
|
final findFavouriteFilter = ref
|
||||||
|
.read(libraryFiltersProvider(views.included.map((e) => e.id).toList()))
|
||||||
|
.firstWhereOrNull((element) => element.isFavourite);
|
||||||
|
if (findFavouriteFilter != null) {
|
||||||
|
loadModel(findFavouriteFilter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state = state.copyWith(
|
||||||
|
sortOrder: sortOrder,
|
||||||
|
sortingOption: sortingOptions,
|
||||||
|
favourites: favourites,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadFolders({List<String>? folderId}) async {
|
Future<void> loadFolders({List<String>? folderId}) async {
|
||||||
|
|
@ -348,7 +375,7 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
recursive: false,
|
recursive: false,
|
||||||
studios: state.studios.setAll(false),
|
studios: state.studios.setAll(false),
|
||||||
filters: state.filters.setAll(false),
|
filters: state.filters.setAll(false),
|
||||||
hideEmtpyShows: false,
|
hideEmptyShows: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -356,7 +383,7 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
|
|
||||||
void setSortOrder(SortingOrder e) => state = state.copyWith(sortOrder: e);
|
void setSortOrder(SortingOrder e) => state = state.copyWith(sortOrder: e);
|
||||||
|
|
||||||
void setHideEmpty(bool value) => state = state.copyWith(hideEmtpyShows: value);
|
void setHideEmpty(bool value) => state = state.copyWith(hideEmptyShows: value);
|
||||||
void setGroupBy(GroupBy groupBy) => state = state.copyWith(groupBy: groupBy);
|
void setGroupBy(GroupBy groupBy) => state = state.copyWith(groupBy: groupBy);
|
||||||
|
|
||||||
void setFolderId(ItemBaseModel item) {
|
void setFolderId(ItemBaseModel item) {
|
||||||
|
|
@ -460,13 +487,6 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
state = state.copyWith(posters: currentItems);
|
state = state.copyWith(posters: currentItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDefaultOptions(SortingOrder? sortOrder, SortingOptions? sortingOptions) {
|
|
||||||
state = state.copyWith(
|
|
||||||
sortOrder: sortOrder,
|
|
||||||
sortingOption: sortingOptions,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateUserDataMain(UserData? userData) {
|
void updateUserDataMain(UserData? userData) {
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
folderOverwrite: [state.folderOverwrite.lastOrNull?.copyWith(userData: userData)].whereNotNull().toList(),
|
folderOverwrite: [state.folderOverwrite.lastOrNull?.copyWith(userData: userData)].whereNotNull().toList(),
|
||||||
|
|
@ -657,6 +677,34 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
||||||
void updateEverything() {
|
void updateEverything() {
|
||||||
state = state.copyWith();
|
state = state.copyWith();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadModel(LibraryFiltersModel model) {
|
||||||
|
state = state.copyWith(
|
||||||
|
genres: state.genres.replaceMap(model.genres),
|
||||||
|
filters: state.filters.replaceMap(model.filters),
|
||||||
|
studios: state.studios.replaceMap(model.studios),
|
||||||
|
tags: state.tags.replaceMap(model.tags),
|
||||||
|
years: state.years.replaceMap(model.years),
|
||||||
|
officialRatings: state.officialRatings.replaceMap(model.officialRatings),
|
||||||
|
types: state.types.replaceMap(model.types),
|
||||||
|
sortingOption: model.sortingOption,
|
||||||
|
sortOrder: model.sortOrder,
|
||||||
|
favourites: model.favourites,
|
||||||
|
hideEmptyShows: model.hideEmptyShows,
|
||||||
|
recursive: model.recursive,
|
||||||
|
groupBy: model.groupBy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveFiltersNew(String newName) =>
|
||||||
|
ref.read(filterProvider.notifier).saveFilter(LibraryFiltersModel.fromLibrarySearch(newName, state));
|
||||||
|
|
||||||
|
void updateFilter(LibraryFiltersModel model) {
|
||||||
|
ref.read(filterProvider.notifier).saveFilter(LibraryFiltersModel.fromLibrarySearch(model.name, state).copyWith(
|
||||||
|
isFavourite: model.isFavourite,
|
||||||
|
id: model.id,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SimpleSorter on List<ItemBaseModel> {
|
extension SimpleSorter on List<ItemBaseModel> {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
import 'package:chopper/chopper.dart';
|
import 'package:chopper/chopper.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
import 'package:fladder/jellyfin/enum_models.dart';
|
import 'package:fladder/jellyfin/enum_models.dart';
|
||||||
import 'package:fladder/models/account_model.dart';
|
import 'package:fladder/models/account_model.dart';
|
||||||
import 'package:fladder/models/items/item_shared_models.dart';
|
import 'package:fladder/models/items/item_shared_models.dart';
|
||||||
|
import 'package:fladder/models/library_filters_model.dart';
|
||||||
import 'package:fladder/providers/api_provider.dart';
|
import 'package:fladder/providers/api_provider.dart';
|
||||||
import 'package:fladder/providers/service_provider.dart';
|
import 'package:fladder/providers/service_provider.dart';
|
||||||
import 'package:fladder/providers/shared_provider.dart';
|
import 'package:fladder/providers/shared_provider.dart';
|
||||||
import 'package:fladder/providers/sync_provider.dart';
|
import 'package:fladder/providers/sync_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
||||||
|
|
||||||
part 'user_provider.g.dart';
|
part 'user_provider.g.dart';
|
||||||
|
|
||||||
|
|
@ -142,4 +145,30 @@ class User extends _$User {
|
||||||
AccountModel? build() {
|
AccountModel? build() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void removeFilter(LibraryFiltersModel model) {
|
||||||
|
final currentList = ((state?.savedFilters ?? [])).toList(growable: true);
|
||||||
|
currentList.remove(model);
|
||||||
|
state = state?.copyWith(savedFilters: currentList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveFilter(LibraryFiltersModel model) {
|
||||||
|
final currentList = (state?.savedFilters ?? []).toList(growable: true);
|
||||||
|
if (currentList.firstWhereOrNull((value) => value.id == model.id) != null) {
|
||||||
|
state = state?.copyWith(
|
||||||
|
savedFilters: currentList.map(
|
||||||
|
(e) {
|
||||||
|
if (e.id == model.id) {
|
||||||
|
return model;
|
||||||
|
} else {
|
||||||
|
return e.copyWith(isFavourite: model.isFavourite && model.containsSameIds(e.ids) ? false : e.isFavourite);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).toList());
|
||||||
|
} else {
|
||||||
|
state = state?.copyWith(savedFilters: [model, ...currentList]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteAllFilters() => state = state?.copyWith(savedFilters: []);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ final showSyncButtonProviderProvider = AutoDisposeProvider<bool>.internal(
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef ShowSyncButtonProviderRef = AutoDisposeProviderRef<bool>;
|
typedef ShowSyncButtonProviderRef = AutoDisposeProviderRef<bool>;
|
||||||
String _$userHash() => r'4a4302c819d26fc7c28d04b9274d0dfd0dc8e201';
|
String _$userHash() => r'418b3d4ade830479db9f48c7793ac5b646778b82';
|
||||||
|
|
||||||
/// See also [User].
|
/// See also [User].
|
||||||
@ProviderFor(User)
|
@ProviderFor(User)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||||
import 'package:fladder/providers/video_player_provider.dart';
|
import 'package:fladder/providers/video_player_provider.dart';
|
||||||
import 'package:fladder/screens/collections/add_to_collection.dart';
|
import 'package:fladder/screens/collections/add_to_collection.dart';
|
||||||
import 'package:fladder/screens/library_search/widgets/library_filter_chips.dart';
|
import 'package:fladder/screens/library_search/widgets/library_filter_chips.dart';
|
||||||
|
import 'package:fladder/screens/library_search/widgets/library_saved_filters.dart';
|
||||||
import 'package:fladder/screens/library_search/widgets/library_sort_dialogue.dart';
|
import 'package:fladder/screens/library_search/widgets/library_sort_dialogue.dart';
|
||||||
import 'package:fladder/screens/library_search/widgets/library_views.dart';
|
import 'package:fladder/screens/library_search/widgets/library_views.dart';
|
||||||
import 'package:fladder/screens/library_search/widgets/suggestion_search_bar.dart';
|
import 'package:fladder/screens/library_search/widgets/suggestion_search_bar.dart';
|
||||||
|
|
@ -31,6 +32,7 @@ import 'package:fladder/util/fab_extended_anim.dart';
|
||||||
import 'package:fladder/util/item_base_model/item_base_model_extensions.dart';
|
import 'package:fladder/util/item_base_model/item_base_model_extensions.dart';
|
||||||
import 'package:fladder/util/list_padding.dart';
|
import 'package:fladder/util/list_padding.dart';
|
||||||
import 'package:fladder/util/localization_helper.dart';
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
|
import 'package:fladder/util/map_bool_helper.dart';
|
||||||
import 'package:fladder/util/refresh_state.dart';
|
import 'package:fladder/util/refresh_state.dart';
|
||||||
import 'package:fladder/util/router_extension.dart';
|
import 'package:fladder/util/router_extension.dart';
|
||||||
import 'package:fladder/util/sliver_list_padding.dart';
|
import 'package:fladder/util/sliver_list_padding.dart';
|
||||||
|
|
@ -105,14 +107,12 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
||||||
|
|
||||||
Future.microtask(
|
Future.microtask(
|
||||||
() async {
|
() async {
|
||||||
if (libraryProvider.mounted) {
|
|
||||||
libraryProvider.setDefaultOptions(widget.sortOrder, widget.sortingOptions);
|
|
||||||
}
|
|
||||||
await refreshKey.currentState?.show();
|
await refreshKey.currentState?.show();
|
||||||
SystemChrome.setEnabledSystemUIMode(
|
SystemChrome.setEnabledSystemUIMode(
|
||||||
SystemUiMode.edgeToEdge,
|
SystemUiMode.edgeToEdge,
|
||||||
overlays: [],
|
overlays: [],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (context.mounted && widget.photoToView != null) {
|
if (context.mounted && widget.photoToView != null) {
|
||||||
libraryProvider.viewGallery(context, selected: widget.photoToView);
|
libraryProvider.viewGallery(context, selected: widget.photoToView);
|
||||||
}
|
}
|
||||||
|
|
@ -133,7 +133,7 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isEmptySearchScreen = widget.viewModelId == null && widget.favourites == null && widget.folderId == null;
|
final isEmptySearchScreen = widget.viewModelId == null && widget.favourites == null && widget.folderId == null;
|
||||||
final librarySearchResults = ref.watch(providerKey);
|
final librarySearchResults = ref.watch(providerKey);
|
||||||
final postersList = librarySearchResults.posters.hideEmptyChildren(librarySearchResults.hideEmtpyShows);
|
final postersList = librarySearchResults.posters.hideEmptyChildren(librarySearchResults.hideEmptyShows);
|
||||||
final playerState = ref.watch(mediaPlaybackProvider.select((value) => value.state));
|
final playerState = ref.watch(mediaPlaybackProvider.select((value) => value.state));
|
||||||
final libraryViewType = ref.watch(libraryViewTypeProvider);
|
final libraryViewType = ref.watch(libraryViewTypeProvider);
|
||||||
|
|
||||||
|
|
@ -230,7 +230,12 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
if (libraryProvider.mounted) {
|
if (libraryProvider.mounted) {
|
||||||
return libraryProvider.initRefresh(
|
return libraryProvider.initRefresh(
|
||||||
widget.folderId, widget.viewModelId, widget.favourites);
|
widget.folderId,
|
||||||
|
widget.viewModelId,
|
||||||
|
widget.favourites,
|
||||||
|
widget.sortOrder,
|
||||||
|
widget.sortingOptions,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
refreshOnStart: false,
|
refreshOnStart: false,
|
||||||
|
|
@ -282,6 +287,11 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
||||||
action: () => refreshKey.currentState?.show(),
|
action: () => refreshKey.currentState?.show(),
|
||||||
icon: const Icon(IconsaxOutline.refresh),
|
icon: const Icon(IconsaxOutline.refresh),
|
||||||
);
|
);
|
||||||
|
final showSavedFiltersDialogue = ItemActionButton(
|
||||||
|
label: Text("Filters"),
|
||||||
|
action: () => showSavedFilters(context, librarySearchResults, libraryProvider),
|
||||||
|
icon: const Icon(IconsaxOutline.refresh),
|
||||||
|
);
|
||||||
final itemViewAction = ItemActionButton(
|
final itemViewAction = ItemActionButton(
|
||||||
label: Text(context.localized.selectViewType),
|
label: Text(context.localized.selectViewType),
|
||||||
icon: Icon(libraryViewType.icon),
|
icon: Icon(libraryViewType.icon),
|
||||||
|
|
@ -359,6 +369,8 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
||||||
itemCountWidget.toPopupMenuItem(useIcons: true),
|
itemCountWidget.toPopupMenuItem(useIcons: true),
|
||||||
refreshAction.toPopupMenuItem(useIcons: true),
|
refreshAction.toPopupMenuItem(useIcons: true),
|
||||||
itemViewAction.toPopupMenuItem(useIcons: true),
|
itemViewAction.toPopupMenuItem(useIcons: true),
|
||||||
|
if (librarySearchResults.views.hasEnabled == true)
|
||||||
|
showSavedFiltersDialogue.toPopupMenuItem(useIcons: true),
|
||||||
if (itemActions.isNotEmpty) ItemActionDivider().toPopupMenuItem(),
|
if (itemActions.isNotEmpty) ItemActionDivider().toPopupMenuItem(),
|
||||||
...itemActions.popupMenuItems(useIcons: true),
|
...itemActions.popupMenuItems(useIcons: true),
|
||||||
],
|
],
|
||||||
|
|
@ -374,6 +386,8 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
||||||
itemCountWidget.toListItem(context, useIcons: true),
|
itemCountWidget.toListItem(context, useIcons: true),
|
||||||
refreshAction.toListItem(context, useIcons: true),
|
refreshAction.toListItem(context, useIcons: true),
|
||||||
itemViewAction.toListItem(context, useIcons: true),
|
itemViewAction.toListItem(context, useIcons: true),
|
||||||
|
if (librarySearchResults.views.hasEnabled == true)
|
||||||
|
showSavedFiltersDialogue.toPopupMenuItem(useIcons: true),
|
||||||
if (itemActions.isNotEmpty) ItemActionDivider().toListItem(context),
|
if (itemActions.isNotEmpty) ItemActionDivider().toListItem(context),
|
||||||
...itemActions.listTileItems(context, useIcons: true),
|
...itemActions.listTileItems(context, useIcons: true),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -190,10 +190,10 @@ List<Widget> libraryFilterChips(
|
||||||
if (librarySearchResults.types[FladderItemType.series] == true)
|
if (librarySearchResults.types[FladderItemType.series] == true)
|
||||||
FilterChip(
|
FilterChip(
|
||||||
avatar: Icon(
|
avatar: Icon(
|
||||||
librarySearchResults.hideEmtpyShows ? Icons.visibility_off_rounded : Icons.visibility_rounded,
|
librarySearchResults.hideEmptyShows ? Icons.visibility_off_rounded : Icons.visibility_rounded,
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
selected: librarySearchResults.hideEmtpyShows,
|
selected: librarySearchResults.hideEmptyShows,
|
||||||
showCheckmark: false,
|
showCheckmark: false,
|
||||||
label: Text(context.localized.hideEmpty),
|
label: Text(context.localized.hideEmpty),
|
||||||
onSelected: libraryProvider.setHideEmpty,
|
onSelected: libraryProvider.setHideEmpty,
|
||||||
|
|
|
||||||
171
lib/screens/library_search/widgets/library_saved_filters.dart
Normal file
171
lib/screens/library_search/widgets/library_saved_filters.dart
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:ficonsax/ficonsax.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import 'package:fladder/models/library_search/library_search_model.dart';
|
||||||
|
import 'package:fladder/providers/library_search_provider.dart';
|
||||||
|
import 'package:fladder/screens/shared/default_alert_dialog.dart';
|
||||||
|
import 'package:fladder/screens/shared/flat_button.dart';
|
||||||
|
import 'package:fladder/screens/shared/outlined_text_field.dart';
|
||||||
|
import 'package:fladder/util/list_padding.dart';
|
||||||
|
import 'package:fladder/util/localization_helper.dart';
|
||||||
|
|
||||||
|
Future<void> showSavedFilters(
|
||||||
|
BuildContext context,
|
||||||
|
LibrarySearchModel model,
|
||||||
|
LibrarySearchNotifier provider,
|
||||||
|
) {
|
||||||
|
return showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => LibrarySavedFiltersDialogue(
|
||||||
|
searchModel: model,
|
||||||
|
provider: provider,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LibrarySavedFiltersDialogue extends ConsumerWidget {
|
||||||
|
final LibrarySearchModel searchModel;
|
||||||
|
final LibrarySearchNotifier provider;
|
||||||
|
const LibrarySavedFiltersDialogue({
|
||||||
|
required this.searchModel,
|
||||||
|
required this.provider,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final controller = TextEditingController();
|
||||||
|
final filters = ref.watch(provider.filterProvider);
|
||||||
|
final filterProvider = ref.watch(provider.filterProvider.notifier);
|
||||||
|
return Dialog(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
context.localized.filter(2),
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
if (filters.isNotEmpty) ...[
|
||||||
|
const Divider(),
|
||||||
|
Flexible(
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
children: [
|
||||||
|
...filters.map(
|
||||||
|
(filter) {
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
child: Card(
|
||||||
|
child: FlatButton(
|
||||||
|
onTap: () => provider.loadModel(filter),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: Text(filter.name)),
|
||||||
|
IconButton.filledTonal(
|
||||||
|
tooltip: context.localized.defaultFilterForLibrary,
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: WidgetStatePropertyAll(
|
||||||
|
filter.isFavourite ? Colors.yellowAccent.shade700.withOpacity(0.5) : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () =>
|
||||||
|
filterProvider.saveFilter(filter.copyWith(isFavourite: !filter.isFavourite)),
|
||||||
|
icon: Icon(
|
||||||
|
color: filter.isFavourite ? Colors.yellowAccent : null,
|
||||||
|
filter.isFavourite ? IconsaxBold.star_1 : IconsaxOutline.star,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton.filledTonal(
|
||||||
|
tooltip: context.localized.updateFilterForLibrary,
|
||||||
|
onPressed: () => provider.updateFilter(filter),
|
||||||
|
icon: Icon(IconsaxBold.refresh),
|
||||||
|
),
|
||||||
|
IconButton.filledTonal(
|
||||||
|
tooltip: context.localized.delete,
|
||||||
|
onPressed: () {
|
||||||
|
showDefaultAlertDialog(
|
||||||
|
context,
|
||||||
|
context.localized.removeFilterForLibrary(filter.name),
|
||||||
|
context.localized.deleteFilterConfirmation,
|
||||||
|
(context) {
|
||||||
|
filterProvider.removeFilter(filter);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
context.localized.delete,
|
||||||
|
(context) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
context.localized.cancel,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
WidgetStatePropertyAll(Theme.of(context).colorScheme.errorContainer),
|
||||||
|
foregroundColor:
|
||||||
|
WidgetStatePropertyAll(Theme.of(context).colorScheme.onErrorContainer),
|
||||||
|
),
|
||||||
|
icon: Icon(IconsaxOutline.trash),
|
||||||
|
),
|
||||||
|
].addInBetween(const SizedBox(width: 8)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
],
|
||||||
|
if (filters.length < 10)
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: OutlinedTextField(
|
||||||
|
controller: controller,
|
||||||
|
label: context.localized.name,
|
||||||
|
onSubmitted: (value) => provider.saveFiltersNew(value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
FilledButton.tonal(
|
||||||
|
onPressed: () => provider.saveFiltersNew(controller.text),
|
||||||
|
child: Icon(IconsaxOutline.save_2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Text(context.localized.libraryFiltersLimitReached),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDefaultAlertDialog(
|
||||||
|
context,
|
||||||
|
context.localized.libraryFiltersRemoveAll,
|
||||||
|
context.localized.libraryFiltersRemoveAllConfirm,
|
||||||
|
(context) {
|
||||||
|
filterProvider.deleteAllFilters();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
context.localized.delete,
|
||||||
|
(context) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
context.localized.cancel,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(context.localized.libraryFiltersRemoveAll),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -106,7 +106,7 @@ extension ItemBaseModelExtensions on ItemBaseModel {
|
||||||
)
|
)
|
||||||
else if (!exclude.contains(ItemActions.showAlbum) && galleryItem)
|
else if (!exclude.contains(ItemActions.showAlbum) && galleryItem)
|
||||||
ItemActionButton(
|
ItemActionButton(
|
||||||
icon: Icon(FladderItemType.photoalbum.icon),
|
icon: Icon(FladderItemType.photoAlbum.icon),
|
||||||
action: () => (this as PhotoModel).navigateToAlbum(context),
|
action: () => (this as PhotoModel).navigateToAlbum(context),
|
||||||
label: Text(context.localized.showAlbum),
|
label: Text(context.localized.showAlbum),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ extension MapExtensions<T> on Map<T, bool> {
|
||||||
|
|
||||||
bool get hasEnabled => values.any((element) => element == true);
|
bool get hasEnabled => values.any((element) => element == true);
|
||||||
|
|
||||||
|
//Replaces only keys that exist with the new values
|
||||||
Map<T, bool> replaceMap(Map<T, bool> oldMap) {
|
Map<T, bool> replaceMap(Map<T, bool> oldMap) {
|
||||||
Map<T, bool> result = {};
|
Map<T, bool> result = {};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue