Fladder/lib/models/library_search/library_search_model.dart
PartyDonut a8795cf0c9
fix: Use sortName instead of name for searches/library views (#359)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
2025-06-01 15:29:38 +02:00

224 lines
6.7 KiB
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';
part 'library_search_model.mapper.dart';
@MappableClass()
class LibrarySearchModel with LibrarySearchModelMappable {
final bool loading;
final bool selecteMode;
final String searchQuery;
final List<ItemBaseModel> folderOverwrite;
final Map<ViewModel, bool> views;
final List<ItemBaseModel> posters;
final List<ItemBaseModel> selectedPosters;
final Map<ItemFilter, bool> filters;
final Map<String, bool> genres;
final Map<Studio, bool> studios;
final Map<String, bool> tags;
final Map<int, bool> years;
final Map<String, bool> officialRatings;
final Map<FladderItemType, bool> types;
final SortingOptions sortingOption;
final SortingOrder sortOrder;
final bool favourites;
final bool hideEmptyShows;
final bool recursive;
final GroupBy groupBy;
final Map<String, int> lastIndices;
final Map<String, int> libraryItemCounts;
final bool fetchingItems;
const LibrarySearchModel({
this.loading = false,
this.selecteMode = false,
this.folderOverwrite = const [],
this.searchQuery = "",
this.views = const {},
this.posters = const [],
this.selectedPosters = const [],
this.filters = const {
ItemFilter.isplayed: false,
ItemFilter.isunplayed: false,
ItemFilter.isresumable: false,
},
this.genres = const {},
this.studios = const {},
this.tags = const {},
this.years = const {},
this.officialRatings = const {},
this.types = const {
FladderItemType.audio: false,
FladderItemType.boxset: false,
FladderItemType.book: false,
FladderItemType.collectionFolder: false,
FladderItemType.episode: false,
FladderItemType.folder: false,
FladderItemType.movie: true,
FladderItemType.musicAlbum: false,
FladderItemType.musicVideo: false,
FladderItemType.photo: false,
FladderItemType.person: false,
FladderItemType.photoAlbum: false,
FladderItemType.series: true,
FladderItemType.video: true,
},
this.favourites = false,
this.sortingOption = SortingOptions.sortName,
this.sortOrder = SortingOrder.ascending,
this.hideEmptyShows = true,
this.recursive = false,
this.groupBy = GroupBy.none,
this.lastIndices = const {},
this.libraryItemCounts = const {},
this.fetchingItems = false,
});
bool get hasActiveFilters {
return genres.hasEnabled ||
studios.hasEnabled ||
tags.hasEnabled ||
years.hasEnabled ||
officialRatings.hasEnabled ||
hideEmptyShows ||
filters.hasEnabled ||
favourites ||
searchQuery.isNotEmpty;
}
int get totalItemCount {
if (libraryItemCounts.isEmpty) return posters.length;
int totalCount = 0;
for (var item in libraryItemCounts.values) {
totalCount += item;
}
return totalCount;
}
bool get allDoneFetching {
if (libraryItemCounts.isEmpty) return false;
if (libraryItemCounts.length != lastIndices.length) {
return false;
} else {
for (var item in libraryItemCounts.entries) {
if (lastIndices[item.key] != item.value) {
return false;
}
}
}
return true;
}
String searchBarTitle(BuildContext context) {
if (folderOverwrite.isNotEmpty) {
return "${context.localized.search} ${folderOverwrite.last.name}...";
}
return views.included.length == 1
? "${context.localized.search} ${views.included.first.name}..."
: "${context.localized.search} ${context.localized.library(2)}...";
}
ItemBaseModel? get nestedCurrentItem => folderOverwrite.lastOrNull;
List<ItemBaseModel> get activePosters => selectedPosters.isNotEmpty ? selectedPosters : posters;
bool get showPlayButtons {
if (totalItemCount == 0) return false;
return types.included.isEmpty ||
types.included.containsAny(
{...FladderItemType.playable, FladderItemType.folder},
);
}
bool get showGalleryButtons {
if (totalItemCount == 0) return false;
return types.included.isEmpty ||
types.included.containsAny(
{...FladderItemType.galleryItem, FladderItemType.photoAlbum, FladderItemType.folder},
);
}
LibrarySearchModel resetLazyLoad() {
return copyWith(
selectedPosters: [],
lastIndices: const {},
libraryItemCounts: const {},
);
}
LibrarySearchModel fullReset() {
return copyWith(
posters: [],
selectedPosters: [],
lastIndices: const {},
libraryItemCounts: const {},
);
}
LibrarySearchModel setFiltersToDefault() {
return copyWith(
genres: const {},
tags: const {},
officialRatings: const {},
years: const {},
searchQuery: '',
favourites: false,
recursive: false,
studios: const {},
hideEmptyShows: true,
);
}
@override
bool operator ==(covariant LibrarySearchModel other) {
if (identical(this, other)) return true;
return other.searchQuery == searchQuery &&
listEquals(other.folderOverwrite, folderOverwrite) &&
mapEquals(other.views, views) &&
mapEquals(other.filters, filters) &&
mapEquals(other.genres, genres) &&
mapEquals(other.studios, studios) &&
mapEquals(other.tags, tags) &&
mapEquals(other.years, years) &&
mapEquals(other.officialRatings, officialRatings) &&
mapEquals(other.types, types) &&
other.sortingOption == sortingOption &&
other.sortOrder == sortOrder &&
other.favourites == favourites &&
other.recursive == recursive;
}
@override
int get hashCode {
return searchQuery.hashCode ^
folderOverwrite.hashCode ^
views.hashCode ^
posters.hashCode ^
selectedPosters.hashCode ^
filters.hashCode ^
genres.hashCode ^
studios.hashCode ^
tags.hashCode ^
years.hashCode ^
officialRatings.hashCode ^
types.hashCode ^
sortingOption.hashCode ^
sortOrder.hashCode ^
favourites.hashCode ^
recursive.hashCode;
}
}