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": [
|
||||
"Jellyfin"
|
||||
"Jellyfin",
|
||||
"jellyfin"
|
||||
],
|
||||
"dart.flutterSdkPath": ".fvm/versions/3.24.3",
|
||||
"search.exclude": {
|
||||
|
|
|
|||
|
|
@ -1084,5 +1084,20 @@
|
|||
"speed": "Speed",
|
||||
"unableToPlayMedia": "There was an error finding a compatible media type",
|
||||
"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
|
||||
|
||||
import 'package:ficonsax/ficonsax.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.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/models/credentials_model.dart';
|
||||
import 'package:fladder/models/library_filters_model.dart';
|
||||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
|
||||
part 'account_model.freezed.dart';
|
||||
part 'account_model.g.dart';
|
||||
|
|
@ -30,6 +31,7 @@ class AccountModel with _$AccountModel {
|
|||
@Default([]) List<String> latestItemsExcludes,
|
||||
@Default([]) List<String> searchQueryHistory,
|
||||
@Default(false) bool quickConnectState,
|
||||
@Default([]) List<LibraryFiltersModel> savedFilters,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false) ServerConfiguration? serverConfiguration,
|
||||
}) = _AccountModel;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ mixin _$AccountModel {
|
|||
List<String> get latestItemsExcludes => throw _privateConstructorUsedError;
|
||||
List<String> get searchQueryHistory => throw _privateConstructorUsedError;
|
||||
bool get quickConnectState => throw _privateConstructorUsedError;
|
||||
List<LibraryFiltersModel> get savedFilters =>
|
||||
throw _privateConstructorUsedError;
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
UserPolicy? get policy => throw _privateConstructorUsedError;
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
|
|
@ -63,6 +65,7 @@ abstract class $AccountModelCopyWith<$Res> {
|
|||
List<String> latestItemsExcludes,
|
||||
List<String> searchQueryHistory,
|
||||
bool quickConnectState,
|
||||
List<LibraryFiltersModel> savedFilters,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
ServerConfiguration? serverConfiguration});
|
||||
|
|
@ -93,6 +96,7 @@ class _$AccountModelCopyWithImpl<$Res, $Val extends AccountModel>
|
|||
Object? latestItemsExcludes = null,
|
||||
Object? searchQueryHistory = null,
|
||||
Object? quickConnectState = null,
|
||||
Object? savedFilters = null,
|
||||
Object? policy = freezed,
|
||||
Object? serverConfiguration = freezed,
|
||||
}) {
|
||||
|
|
@ -137,6 +141,10 @@ class _$AccountModelCopyWithImpl<$Res, $Val extends AccountModel>
|
|||
? _value.quickConnectState
|
||||
: quickConnectState // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
savedFilters: null == savedFilters
|
||||
? _value.savedFilters
|
||||
: savedFilters // ignore: cast_nullable_to_non_nullable
|
||||
as List<LibraryFiltersModel>,
|
||||
policy: freezed == policy
|
||||
? _value.policy
|
||||
: policy // ignore: cast_nullable_to_non_nullable
|
||||
|
|
@ -168,6 +176,7 @@ abstract class _$$AccountModelImplCopyWith<$Res>
|
|||
List<String> latestItemsExcludes,
|
||||
List<String> searchQueryHistory,
|
||||
bool quickConnectState,
|
||||
List<LibraryFiltersModel> savedFilters,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false) UserPolicy? policy,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
ServerConfiguration? serverConfiguration});
|
||||
|
|
@ -196,6 +205,7 @@ class __$$AccountModelImplCopyWithImpl<$Res>
|
|||
Object? latestItemsExcludes = null,
|
||||
Object? searchQueryHistory = null,
|
||||
Object? quickConnectState = null,
|
||||
Object? savedFilters = null,
|
||||
Object? policy = freezed,
|
||||
Object? serverConfiguration = freezed,
|
||||
}) {
|
||||
|
|
@ -240,6 +250,10 @@ class __$$AccountModelImplCopyWithImpl<$Res>
|
|||
? _value.quickConnectState
|
||||
: quickConnectState // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
savedFilters: null == savedFilters
|
||||
? _value._savedFilters
|
||||
: savedFilters // ignore: cast_nullable_to_non_nullable
|
||||
as List<LibraryFiltersModel>,
|
||||
policy: freezed == policy
|
||||
? _value.policy
|
||||
: 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> searchQueryHistory = const [],
|
||||
this.quickConnectState = false,
|
||||
final List<LibraryFiltersModel> savedFilters = const [],
|
||||
@JsonKey(includeFromJson: false, includeToJson: false) this.policy,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
this.serverConfiguration})
|
||||
: _latestItemsExcludes = latestItemsExcludes,
|
||||
_searchQueryHistory = searchQueryHistory,
|
||||
_savedFilters = savedFilters,
|
||||
super._();
|
||||
|
||||
factory _$AccountModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
|
|
@ -315,6 +331,15 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
|||
@override
|
||||
@JsonKey()
|
||||
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
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
final UserPolicy? policy;
|
||||
|
|
@ -324,7 +349,7 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
|||
|
||||
@override
|
||||
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
|
||||
|
|
@ -342,6 +367,7 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
|||
..add(DiagnosticsProperty('latestItemsExcludes', latestItemsExcludes))
|
||||
..add(DiagnosticsProperty('searchQueryHistory', searchQueryHistory))
|
||||
..add(DiagnosticsProperty('quickConnectState', quickConnectState))
|
||||
..add(DiagnosticsProperty('savedFilters', savedFilters))
|
||||
..add(DiagnosticsProperty('policy', policy))
|
||||
..add(DiagnosticsProperty('serverConfiguration', serverConfiguration));
|
||||
}
|
||||
|
|
@ -368,6 +394,8 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
|||
.equals(other._searchQueryHistory, _searchQueryHistory) &&
|
||||
(identical(other.quickConnectState, quickConnectState) ||
|
||||
other.quickConnectState == quickConnectState) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._savedFilters, _savedFilters) &&
|
||||
(identical(other.policy, policy) || other.policy == policy) &&
|
||||
(identical(other.serverConfiguration, serverConfiguration) ||
|
||||
other.serverConfiguration == serverConfiguration));
|
||||
|
|
@ -387,6 +415,7 @@ class _$AccountModelImpl extends _AccountModel with DiagnosticableTreeMixin {
|
|||
const DeepCollectionEquality().hash(_latestItemsExcludes),
|
||||
const DeepCollectionEquality().hash(_searchQueryHistory),
|
||||
quickConnectState,
|
||||
const DeepCollectionEquality().hash(_savedFilters),
|
||||
policy,
|
||||
serverConfiguration);
|
||||
|
||||
|
|
@ -418,6 +447,7 @@ abstract class _AccountModel extends AccountModel {
|
|||
final List<String> latestItemsExcludes,
|
||||
final List<String> searchQueryHistory,
|
||||
final bool quickConnectState,
|
||||
final List<LibraryFiltersModel> savedFilters,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
final UserPolicy? policy,
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
|
|
@ -448,6 +478,8 @@ abstract class _AccountModel extends AccountModel {
|
|||
@override
|
||||
bool get quickConnectState;
|
||||
@override
|
||||
List<LibraryFiltersModel> get savedFilters;
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
UserPolicy? get policy;
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ _$AccountModelImpl _$$AccountModelImplFromJson(Map<String, dynamic> json) =>
|
|||
.toList() ??
|
||||
const [],
|
||||
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) =>
|
||||
|
|
@ -40,6 +45,7 @@ Map<String, dynamic> _$$AccountModelImplToJson(_$AccountModelImpl instance) =>
|
|||
'latestItemsExcludes': instance.latestItemsExcludes,
|
||||
'searchQueryHistory': instance.searchQueryHistory,
|
||||
'quickConnectState': instance.quickConnectState,
|
||||
'savedFilters': instance.savedFilters,
|
||||
};
|
||||
|
||||
const _$AuthenticationEnumMap = {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ extension CollectionTypeExtension on CollectionType {
|
|||
case CollectionType.tvshows:
|
||||
return {FladderItemType.series};
|
||||
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.folders:
|
||||
case CollectionType.books:
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ class ItemBaseModel with ItemBaseModelMappable {
|
|||
MovieModel _ => FladderItemType.movie,
|
||||
SeriesModel _ => FladderItemType.series,
|
||||
SeasonModel _ => FladderItemType.season,
|
||||
PhotoAlbumModel _ => FladderItemType.photoalbum,
|
||||
PhotoAlbumModel _ => FladderItemType.photoAlbum,
|
||||
PhotoModel model => model.internalType,
|
||||
EpisodeModel _ => FladderItemType.episode,
|
||||
BookModel _ => FladderItemType.book,
|
||||
|
|
@ -281,7 +281,7 @@ enum FladderItemType {
|
|||
icon: IconsaxOutline.user,
|
||||
selectedicon: IconsaxBold.user,
|
||||
),
|
||||
photoalbum(
|
||||
photoAlbum(
|
||||
icon: IconsaxOutline.gallery,
|
||||
selectedicon: IconsaxBold.gallery,
|
||||
),
|
||||
|
|
@ -331,7 +331,7 @@ enum FladderItemType {
|
|||
FladderItemType.episode => context.localized.mediaTypeEpisode,
|
||||
FladderItemType.photo => context.localized.mediaTypePhoto,
|
||||
FladderItemType.person => context.localized.mediaTypePerson,
|
||||
FladderItemType.photoalbum => context.localized.mediaTypePhotoAlbum,
|
||||
FladderItemType.photoAlbum => context.localized.mediaTypePhotoAlbum,
|
||||
FladderItemType.folder => context.localized.mediaTypeFolder,
|
||||
FladderItemType.boxset => context.localized.mediaTypeBoxset,
|
||||
FladderItemType.playlist => context.localized.mediaTypePlaylist,
|
||||
|
|
@ -352,7 +352,7 @@ enum FladderItemType {
|
|||
FladderItemType.episode => BaseItemKind.episode,
|
||||
FladderItemType.photo => BaseItemKind.photo,
|
||||
FladderItemType.person => BaseItemKind.person,
|
||||
FladderItemType.photoalbum => BaseItemKind.photoalbum,
|
||||
FladderItemType.photoAlbum => BaseItemKind.photoalbum,
|
||||
FladderItemType.folder => BaseItemKind.folder,
|
||||
FladderItemType.boxset => BaseItemKind.boxset,
|
||||
FladderItemType.playlist => BaseItemKind.playlist,
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
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_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/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';
|
||||
|
||||
@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/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.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_options.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/map_bool_helper.dart';
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
|||
final SortingOptions sortingOption;
|
||||
final SortingOrder sortOrder;
|
||||
final bool favourites;
|
||||
final bool hideEmtpyShows;
|
||||
final bool hideEmptyShows;
|
||||
final bool recursive;
|
||||
final GroupBy groupBy;
|
||||
final Map<String, int> lastIndices;
|
||||
|
|
@ -71,14 +72,14 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
|||
FladderItemType.musicVideo: false,
|
||||
FladderItemType.photo: false,
|
||||
FladderItemType.person: false,
|
||||
FladderItemType.photoalbum: false,
|
||||
FladderItemType.photoAlbum: false,
|
||||
FladderItemType.series: true,
|
||||
FladderItemType.video: true,
|
||||
},
|
||||
this.favourites = false,
|
||||
this.sortingOption = SortingOptions.name,
|
||||
this.sortOrder = SortingOrder.ascending,
|
||||
this.hideEmtpyShows = true,
|
||||
this.hideEmptyShows = true,
|
||||
this.recursive = false,
|
||||
this.groupBy = GroupBy.none,
|
||||
this.lastIndices = const {},
|
||||
|
|
@ -92,7 +93,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
|||
tags.hasEnabled ||
|
||||
years.hasEnabled ||
|
||||
officialRatings.hasEnabled ||
|
||||
hideEmtpyShows ||
|
||||
hideEmptyShows ||
|
||||
filters.hasEnabled ||
|
||||
favourites ||
|
||||
searchQuery.isNotEmpty;
|
||||
|
|
@ -146,7 +147,7 @@ class LibrarySearchModel with LibrarySearchModelMappable {
|
|||
if (totalItemCount == 0) return false;
|
||||
return types.included.isEmpty ||
|
||||
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,
|
||||
recursive: false,
|
||||
studios: const {},
|
||||
hideEmtpyShows: true,
|
||||
hideEmptyShows: true,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
|||
FladderItemType.musicVideo: false,
|
||||
FladderItemType.photo: false,
|
||||
FladderItemType.person: false,
|
||||
FladderItemType.photoalbum: false,
|
||||
FladderItemType.photoAlbum: false,
|
||||
FladderItemType.series: true,
|
||||
FladderItemType.video: true
|
||||
});
|
||||
|
|
@ -98,9 +98,9 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
|||
static SortingOrder _$sortOrder(LibrarySearchModel v) => v.sortOrder;
|
||||
static const Field<LibrarySearchModel, SortingOrder> _f$sortOrder =
|
||||
Field('sortOrder', _$sortOrder, opt: true, def: SortingOrder.ascending);
|
||||
static bool _$hideEmtpyShows(LibrarySearchModel v) => v.hideEmtpyShows;
|
||||
static const Field<LibrarySearchModel, bool> _f$hideEmtpyShows =
|
||||
Field('hideEmtpyShows', _$hideEmtpyShows, opt: true, def: true);
|
||||
static bool _$hideEmptyShows(LibrarySearchModel v) => v.hideEmptyShows;
|
||||
static const Field<LibrarySearchModel, bool> _f$hideEmptyShows =
|
||||
Field('hideEmptyShows', _$hideEmptyShows, opt: true, def: true);
|
||||
static bool _$recursive(LibrarySearchModel v) => v.recursive;
|
||||
static const Field<LibrarySearchModel, bool> _f$recursive =
|
||||
Field('recursive', _$recursive, opt: true, def: false);
|
||||
|
|
@ -138,7 +138,7 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
|||
#favourites: _f$favourites,
|
||||
#sortingOption: _f$sortingOption,
|
||||
#sortOrder: _f$sortOrder,
|
||||
#hideEmtpyShows: _f$hideEmtpyShows,
|
||||
#hideEmptyShows: _f$hideEmptyShows,
|
||||
#recursive: _f$recursive,
|
||||
#groupBy: _f$groupBy,
|
||||
#lastIndices: _f$lastIndices,
|
||||
|
|
@ -167,7 +167,7 @@ class LibrarySearchModelMapper extends ClassMapperBase<LibrarySearchModel> {
|
|||
favourites: data.dec(_f$favourites),
|
||||
sortingOption: data.dec(_f$sortingOption),
|
||||
sortOrder: data.dec(_f$sortOrder),
|
||||
hideEmtpyShows: data.dec(_f$hideEmtpyShows),
|
||||
hideEmptyShows: data.dec(_f$hideEmptyShows),
|
||||
recursive: data.dec(_f$recursive),
|
||||
groupBy: data.dec(_f$groupBy),
|
||||
lastIndices: data.dec(_f$lastIndices),
|
||||
|
|
@ -257,7 +257,7 @@ abstract class LibrarySearchModelCopyWith<$R, $In extends LibrarySearchModel,
|
|||
bool? favourites,
|
||||
SortingOptions? sortingOption,
|
||||
SortingOrder? sortOrder,
|
||||
bool? hideEmtpyShows,
|
||||
bool? hideEmptyShows,
|
||||
bool? recursive,
|
||||
GroupBy? groupBy,
|
||||
Map<String, int>? lastIndices,
|
||||
|
|
@ -353,7 +353,7 @@ class _LibrarySearchModelCopyWithImpl<$R, $Out>
|
|||
bool? favourites,
|
||||
SortingOptions? sortingOption,
|
||||
SortingOrder? sortOrder,
|
||||
bool? hideEmtpyShows,
|
||||
bool? hideEmptyShows,
|
||||
bool? recursive,
|
||||
GroupBy? groupBy,
|
||||
Map<String, int>? lastIndices,
|
||||
|
|
@ -377,7 +377,7 @@ class _LibrarySearchModelCopyWithImpl<$R, $Out>
|
|||
if (favourites != null) #favourites: favourites,
|
||||
if (sortingOption != null) #sortingOption: sortingOption,
|
||||
if (sortOrder != null) #sortOrder: sortOrder,
|
||||
if (hideEmtpyShows != null) #hideEmtpyShows: hideEmtpyShows,
|
||||
if (hideEmptyShows != null) #hideEmptyShows: hideEmptyShows,
|
||||
if (recursive != null) #recursive: recursive,
|
||||
if (groupBy != null) #groupBy: groupBy,
|
||||
if (lastIndices != null) #lastIndices: lastIndices,
|
||||
|
|
@ -403,7 +403,7 @@ class _LibrarySearchModelCopyWithImpl<$R, $Out>
|
|||
favourites: data.get(#favourites, or: $value.favourites),
|
||||
sortingOption: data.get(#sortingOption, or: $value.sortingOption),
|
||||
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),
|
||||
groupBy: data.get(#groupBy, or: $value.groupBy),
|
||||
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/item_shared_models.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_options.dart';
|
||||
import 'package:fladder/models/playlist_model.dart';
|
||||
import 'package:fladder/models/view_model.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/settings/client_settings_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;
|
||||
|
||||
LibraryFiltersProvider get filterProvider => libraryFiltersProvider(state.views.included.map((e) => e.id).toList());
|
||||
|
||||
late final JellyService api = ref.read(jellyApiProvider);
|
||||
|
||||
set loading(bool loading) => state = state.copyWith(loading: loading);
|
||||
|
|
@ -52,6 +56,8 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
|||
List<String>? folderId,
|
||||
String? viewModelId,
|
||||
bool? favourites,
|
||||
SortingOrder? sortOrder,
|
||||
SortingOptions? sortingOptions,
|
||||
) async {
|
||||
loading = true;
|
||||
state = state.resetLazyLoad();
|
||||
|
|
@ -59,7 +65,7 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
|||
if (folderId != null) {
|
||||
await loadFolders(folderId: folderId);
|
||||
} 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
|
||||
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 createdViews = response.body?.items?.map((e) => ViewModel.fromBodyDto(e, ref));
|
||||
Map<ViewModel, bool> mappedModels =
|
||||
|
|
@ -159,12 +170,28 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
|||
|
||||
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(
|
||||
views: selectedModel != null
|
||||
? mappedModels.setKey(mappedModels.keys.firstWhere((element) => element.id == viewModelId), true)
|
||||
: mappedModels,
|
||||
favourites: favourites,
|
||||
views: views,
|
||||
);
|
||||
|
||||
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 {
|
||||
|
|
@ -348,7 +375,7 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
|||
recursive: false,
|
||||
studios: state.studios.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 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 setFolderId(ItemBaseModel item) {
|
||||
|
|
@ -460,13 +487,6 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
|||
state = state.copyWith(posters: currentItems);
|
||||
}
|
||||
|
||||
void setDefaultOptions(SortingOrder? sortOrder, SortingOptions? sortingOptions) {
|
||||
state = state.copyWith(
|
||||
sortOrder: sortOrder,
|
||||
sortingOption: sortingOptions,
|
||||
);
|
||||
}
|
||||
|
||||
void updateUserDataMain(UserData? userData) {
|
||||
state = state.copyWith(
|
||||
folderOverwrite: [state.folderOverwrite.lastOrNull?.copyWith(userData: userData)].whereNotNull().toList(),
|
||||
|
|
@ -657,6 +677,34 @@ class LibrarySearchNotifier extends StateNotifier<LibrarySearchModel> {
|
|||
void updateEverything() {
|
||||
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> {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
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/models/account_model.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/service_provider.dart';
|
||||
import 'package:fladder/providers/shared_provider.dart';
|
||||
import 'package:fladder/providers/sync_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'user_provider.g.dart';
|
||||
|
||||
|
|
@ -142,4 +145,30 @@ class User extends _$User {
|
|||
AccountModel? build() {
|
||||
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>;
|
||||
String _$userHash() => r'4a4302c819d26fc7c28d04b9274d0dfd0dc8e201';
|
||||
String _$userHash() => r'418b3d4ade830479db9f48c7793ac5b646778b82';
|
||||
|
||||
/// See also [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/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_saved_filters.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/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/list_padding.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/router_extension.dart';
|
||||
import 'package:fladder/util/sliver_list_padding.dart';
|
||||
|
|
@ -105,14 +107,12 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
|||
|
||||
Future.microtask(
|
||||
() async {
|
||||
if (libraryProvider.mounted) {
|
||||
libraryProvider.setDefaultOptions(widget.sortOrder, widget.sortingOptions);
|
||||
}
|
||||
await refreshKey.currentState?.show();
|
||||
SystemChrome.setEnabledSystemUIMode(
|
||||
SystemUiMode.edgeToEdge,
|
||||
overlays: [],
|
||||
);
|
||||
|
||||
if (context.mounted && widget.photoToView != null) {
|
||||
libraryProvider.viewGallery(context, selected: widget.photoToView);
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
|||
Widget build(BuildContext context) {
|
||||
final isEmptySearchScreen = widget.viewModelId == null && widget.favourites == null && widget.folderId == null;
|
||||
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 libraryViewType = ref.watch(libraryViewTypeProvider);
|
||||
|
||||
|
|
@ -230,7 +230,12 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
|||
onRefresh: () async {
|
||||
if (libraryProvider.mounted) {
|
||||
return libraryProvider.initRefresh(
|
||||
widget.folderId, widget.viewModelId, widget.favourites);
|
||||
widget.folderId,
|
||||
widget.viewModelId,
|
||||
widget.favourites,
|
||||
widget.sortOrder,
|
||||
widget.sortingOptions,
|
||||
);
|
||||
}
|
||||
},
|
||||
refreshOnStart: false,
|
||||
|
|
@ -282,6 +287,11 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
|||
action: () => refreshKey.currentState?.show(),
|
||||
icon: const Icon(IconsaxOutline.refresh),
|
||||
);
|
||||
final showSavedFiltersDialogue = ItemActionButton(
|
||||
label: Text("Filters"),
|
||||
action: () => showSavedFilters(context, librarySearchResults, libraryProvider),
|
||||
icon: const Icon(IconsaxOutline.refresh),
|
||||
);
|
||||
final itemViewAction = ItemActionButton(
|
||||
label: Text(context.localized.selectViewType),
|
||||
icon: Icon(libraryViewType.icon),
|
||||
|
|
@ -359,6 +369,8 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
|||
itemCountWidget.toPopupMenuItem(useIcons: true),
|
||||
refreshAction.toPopupMenuItem(useIcons: true),
|
||||
itemViewAction.toPopupMenuItem(useIcons: true),
|
||||
if (librarySearchResults.views.hasEnabled == true)
|
||||
showSavedFiltersDialogue.toPopupMenuItem(useIcons: true),
|
||||
if (itemActions.isNotEmpty) ItemActionDivider().toPopupMenuItem(),
|
||||
...itemActions.popupMenuItems(useIcons: true),
|
||||
],
|
||||
|
|
@ -374,6 +386,8 @@ class _LibrarySearchScreenState extends ConsumerState<LibrarySearchScreen> {
|
|||
itemCountWidget.toListItem(context, useIcons: true),
|
||||
refreshAction.toListItem(context, useIcons: true),
|
||||
itemViewAction.toListItem(context, useIcons: true),
|
||||
if (librarySearchResults.views.hasEnabled == true)
|
||||
showSavedFiltersDialogue.toPopupMenuItem(useIcons: true),
|
||||
if (itemActions.isNotEmpty) ItemActionDivider().toListItem(context),
|
||||
...itemActions.listTileItems(context, useIcons: true),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -190,10 +190,10 @@ List<Widget> libraryFilterChips(
|
|||
if (librarySearchResults.types[FladderItemType.series] == true)
|
||||
FilterChip(
|
||||
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,
|
||||
),
|
||||
selected: librarySearchResults.hideEmtpyShows,
|
||||
selected: librarySearchResults.hideEmptyShows,
|
||||
showCheckmark: false,
|
||||
label: Text(context.localized.hideEmpty),
|
||||
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)
|
||||
ItemActionButton(
|
||||
icon: Icon(FladderItemType.photoalbum.icon),
|
||||
icon: Icon(FladderItemType.photoAlbum.icon),
|
||||
action: () => (this as PhotoModel).navigateToAlbum(context),
|
||||
label: Text(context.localized.showAlbum),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ extension MapExtensions<T> on Map<T, bool> {
|
|||
|
||||
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> result = {};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue