fix: Library screen causing server to go down because of api calls (#602)

This commit is contained in:
PartyDonut 2025-11-10 21:24:35 +01:00 committed by GitHub
parent a4ec2637fc
commit ed3d51bfed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 90 additions and 78 deletions

View file

@ -240,6 +240,7 @@ class _MainState extends ConsumerState<Main> with WindowListener, WidgetsBinding
windowManager.waitUntilReadyToShow(windowOptions, () async { windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show(); await windowManager.show();
await windowManager.focus(); await windowManager.focus();
final startupArguments = ref.read(argumentsStateProvider); final startupArguments = ref.read(argumentsStateProvider);
if (startupArguments.htpcMode && !(await windowManager.isFullScreen())) { if (startupArguments.htpcMode && !(await windowManager.isFullScreen())) {

View file

@ -84,9 +84,15 @@ class LibraryScreen extends _$LibraryScreen {
} }
Future<Response?> loadLibrary(ViewModel viewModel) async { Future<Response?> loadLibrary(ViewModel viewModel) async {
await loadRecommendations(viewModel); if (state.viewType.contains(LibraryViewType.recommended)) {
await loadGenres(viewModel); await loadRecommendations(viewModel);
await loadFavourites(viewModel); }
if (state.viewType.contains(LibraryViewType.favourites)) {
await loadFavourites(viewModel);
}
if (state.viewType.contains(LibraryViewType.genres)) {
await loadGenres(viewModel);
}
return null; return null;
} }
@ -97,7 +103,7 @@ class LibraryScreen extends _$LibraryScreen {
final resume = await api.usersUserIdItemsResumeGet( final resume = await api.usersUserIdItemsResumeGet(
parentId: viewModel.id, parentId: viewModel.id,
limit: 14, limit: 9,
enableUserData: true, enableUserData: true,
enableImageTypes: [ enableImageTypes: [
ImageType.primary, ImageType.primary,
@ -120,7 +126,7 @@ class LibraryScreen extends _$LibraryScreen {
final response = await api.moviesRecommendationsGet( final response = await api.moviesRecommendationsGet(
parentId: viewModel.id, parentId: viewModel.id,
categoryLimit: 6, categoryLimit: 6,
itemLimit: 14, itemLimit: 9,
fields: [ItemFields.mediasourcecount], fields: [ItemFields.mediasourcecount],
); );
newRecommendations = [ newRecommendations = [
@ -133,7 +139,7 @@ class LibraryScreen extends _$LibraryScreen {
} else { } else {
final nextUp = await api.showsNextUpGet( final nextUp = await api.showsNextUpGet(
parentId: viewModel.id, parentId: viewModel.id,
limit: 14, limit: 9,
imageTypeLimit: 1, imageTypeLimit: 1,
fields: [ItemFields.mediasourcecount, ItemFields.primaryimageaspectratio], fields: [ItemFields.mediasourcecount, ItemFields.primaryimageaspectratio],
); );
@ -157,7 +163,7 @@ class LibraryScreen extends _$LibraryScreen {
final latest = await api.usersUserIdItemsLatestGet( final latest = await api.usersUserIdItemsLatestGet(
parentId: viewModel.id, parentId: viewModel.id,
limit: 14, limit: 9,
imageTypeLimit: 1, imageTypeLimit: 1,
includeItemTypes: viewModel.collectionType.itemKinds.map((e) => e.dtoKind).toList(), includeItemTypes: viewModel.collectionType.itemKinds.map((e) => e.dtoKind).toList(),
); );
@ -180,7 +186,7 @@ class LibraryScreen extends _$LibraryScreen {
parentId: viewModel.id, parentId: viewModel.id,
isFavorite: true, isFavorite: true,
recursive: true, recursive: true,
limit: 14, limit: 9,
includeItemTypes: viewModel.collectionType.itemKinds.map((e) => e.dtoKind).toList(), includeItemTypes: viewModel.collectionType.itemKinds.map((e) => e.dtoKind).toList(),
enableImageTypes: [ImageType.primary], enableImageTypes: [ImageType.primary],
fields: [ fields: [
@ -211,11 +217,13 @@ class LibraryScreen extends _$LibraryScreen {
if (filteredGenres.isEmpty) return null; if (filteredGenres.isEmpty) return null;
final results = await Future.wait(filteredGenres.map((genre) async { final futures = filteredGenres.map((genre) {
final response = await api.itemsGet( return api
.itemsGet(
parentId: viewModel.id, parentId: viewModel.id,
genreIds: [genre.id], genreIds: [genre.id],
limit: 14, limit: 9,
recursive: true,
includeItemTypes: viewModel.collectionType.itemKinds.map((e) => e.dtoKind).toList(), includeItemTypes: viewModel.collectionType.itemKinds.map((e) => e.dtoKind).toList(),
enableImageTypes: [ImageType.primary], enableImageTypes: [ImageType.primary],
fields: [ fields: [
@ -226,14 +234,17 @@ class LibraryScreen extends _$LibraryScreen {
enableTotalRecordCount: false, enableTotalRecordCount: false,
imageTypeLimit: 1, imageTypeLimit: 1,
sortOrder: [SortOrder.ascending], sortOrder: [SortOrder.ascending],
); )
.then((response) {
final items = response.body?.items;
if (items != null && items.isNotEmpty) {
return RecommendedModel(name: Other(genre.name), posters: items);
}
return null;
});
}).toList();
final items = response.body?.items; final results = await Future.wait(futures);
if (items != null && items.isNotEmpty) {
return RecommendedModel(name: Other(genre.name), posters: items);
}
return null;
}));
state = state.copyWith( state = state.copyWith(
genres: results.whereType<RecommendedModel>().toList(), genres: results.whereType<RecommendedModel>().toList(),

View file

@ -45,6 +45,11 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen> with SingleTicker
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ref.listen(libraryScreenProvider, (previous, next) {
if ((previous?.viewType.length ?? 0) < next.viewType.length) {
refreshKey?.currentState?.show();
}
});
final libraryScreenState = ref.watch(libraryScreenProvider); final libraryScreenState = ref.watch(libraryScreenProvider);
final views = libraryScreenState.views; final views = libraryScreenState.views;
final recommendations = libraryScreenState.recommendations; final recommendations = libraryScreenState.recommendations;
@ -133,9 +138,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen> with SingleTicker
))) )))
.toList(), .toList(),
selectedValues: viewTypes, selectedValues: viewTypes,
onSelected: (value) { onSelected: (value) => ref.read(libraryScreenProvider.notifier).setViewType(value),
ref.read(libraryScreenProvider.notifier).setViewType(value);
},
), ),
const Padding( const Padding(
padding: EdgeInsets.symmetric(horizontal: 4.0), padding: EdgeInsets.symmetric(horizontal: 4.0),
@ -155,74 +158,71 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen> with SingleTicker
SliverFillRemaining( SliverFillRemaining(
child: Center(child: Text(context.localized.noResults)), child: Center(child: Text(context.localized.noResults)),
), ),
if (viewTypes.contains(LibraryViewType.recommended)) ...[ if (viewTypes.contains(LibraryViewType.recommended) && recommendations.isNotEmpty) ...[
if (recommendations.isNotEmpty) ...recommendations.where((element) => element.posters.isNotEmpty).map(
...recommendations.where((element) => element.posters.isNotEmpty).map( (element) {
(element) { return SliverToBoxAdapter(
return SliverToBoxAdapter( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: PosterRow(
contentPadding: padding,
posters: element.posters,
primaryPosters: element.name is Resume,
label: element.type != null
? "${element.type?.label(context)} - ${element.name.label(context)}"
: element.name.label(context),
),
),
);
},
),
],
if (viewTypes.contains(LibraryViewType.favourites) && favourites.isNotEmpty)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: PosterRow(
contentPadding: padding,
onLabelClick: () => context.pushRoute(
LibrarySearchRoute(
viewModelId: libraryScreenState.selectedViewModel?.id ?? "",
).withFilter(
const LibraryFilterModel(
favourites: true,
recursive: true,
),
),
),
posters: favourites,
label: context.localized.favorites,
),
),
),
if (viewTypes.contains(LibraryViewType.genres) && genres.isNotEmpty) ...[
...genres.where((element) => element.posters.isNotEmpty).map(
(element) => SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: PosterRow( child: PosterRow(
contentPadding: padding, contentPadding: padding,
posters: element.posters, posters: element.posters,
primaryPosters: element.name is Resume, onLabelClick: () => context.pushRoute(
LibrarySearchRoute(
viewModelId: libraryScreenState.selectedViewModel?.id ?? "",
).withFilter(
LibraryFilterModel(
recursive: true,
genres: {(element.name as Other).customLabel: true},
),
),
),
label: element.type != null label: element.type != null
? "${element.type?.label(context)} - ${element.name.label(context)}" ? "${element.type?.label(context)} - ${element.name.label(context)}"
: element.name.label(context), : element.name.label(context),
), ),
), ),
);
},
),
],
if (viewTypes.contains(LibraryViewType.favourites))
if (favourites.isNotEmpty)
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: PosterRow(
contentPadding: padding,
onLabelClick: () => context.pushRoute(
LibrarySearchRoute(
viewModelId: libraryScreenState.selectedViewModel?.id ?? "",
).withFilter(
const LibraryFilterModel(
favourites: true,
recursive: true,
),
),
),
posters: favourites,
label: context.localized.favorites,
), ),
), )
),
if (viewTypes.contains(LibraryViewType.genres)) ...[
if (genres.isNotEmpty)
...genres.where((element) => element.posters.isNotEmpty).map(
(element) => SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: PosterRow(
contentPadding: padding,
posters: element.posters,
onLabelClick: () => context.pushRoute(
LibrarySearchRoute(
viewModelId: libraryScreenState.selectedViewModel?.id ?? "",
).withFilter(
LibraryFilterModel(
recursive: true,
genres: {(element.name as Other).customLabel: true},
),
),
),
label: element.type != null
? "${element.type?.label(context)} - ${element.name.label(context)}"
: element.name.label(context),
),
),
),
)
], ],
const DefautlSliverBottomPadding(), const DefautlSliverBottomPadding(),
], ],