From b434f73b2a5d2d39d5cf160fbfae8dc835587eaf Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Nov 2025 22:18:20 +0000 Subject: [PATCH] perf: optimize scrolling and image loading performance Added performance optimizations to all library browser views: - Added cacheExtent: 500 to all GridView/ListView builders to pre-render items and reduce stuttering during scrolling - Wrapped grid items in RepaintBoundary to isolate repaints and improve performance - Optimized CachedNetworkImage with: - fadeInDuration/fadeOutDuration: Duration.zero to remove animation overhead - memCacheHeight: 300 to limit in-memory cache size - maxHeightDiskCache: 600 to resize images for better performance These changes should significantly reduce the stuttering observed when scrolling the authors grid and filtering books, especially on first load. --- .../view/filtered_library_items_page.dart | 9 ++++++++- .../library_browser/view/library_authors_page.dart | 9 ++++++++- .../library_browser/view/library_genres_page.dart | 1 + .../library_browser/view/library_series_page.dart | 1 + 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/features/library_browser/view/filtered_library_items_page.dart b/lib/features/library_browser/view/filtered_library_items_page.dart index 07392d1..12f88b8 100644 --- a/lib/features/library_browser/view/filtered_library_items_page.dart +++ b/lib/features/library_browser/view/filtered_library_items_page.dart @@ -84,6 +84,7 @@ class FilteredLibraryItemsPage extends HookConsumerWidget { return GridView.builder( padding: const EdgeInsets.all(16), + cacheExtent: 500, // Pre-render items for smoother scrolling gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, childAspectRatio: 0.65, @@ -93,7 +94,9 @@ class FilteredLibraryItemsPage extends HookConsumerWidget { itemCount: response.results.length, itemBuilder: (context, index) { final item = response.results[index]; - return LibraryItemCard(item: item); + return RepaintBoundary( + child: LibraryItemCard(item: item), + ); }, ); }, @@ -247,6 +250,10 @@ class LibraryItemCard extends ConsumerWidget { ? CachedNetworkImage( imageUrl: imageUrl, fit: BoxFit.cover, + fadeInDuration: Duration.zero, // Remove fade animation for better performance + fadeOutDuration: Duration.zero, + memCacheHeight: 300, // Limit memory cache size + maxHeightDiskCache: 600, // Limit disk cache size httpHeaders: { if (apiSettings.activeUser?.authToken != null) 'Authorization': diff --git a/lib/features/library_browser/view/library_authors_page.dart b/lib/features/library_browser/view/library_authors_page.dart index b84d21b..dfb665d 100644 --- a/lib/features/library_browser/view/library_authors_page.dart +++ b/lib/features/library_browser/view/library_authors_page.dart @@ -37,6 +37,7 @@ class LibraryAuthorsPage extends HookConsumerWidget { return GridView.builder( padding: const EdgeInsets.all(16), + cacheExtent: 500, // Pre-render items for smoother scrolling gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.75, @@ -46,7 +47,9 @@ class LibraryAuthorsPage extends HookConsumerWidget { itemCount: sortedAuthors.length, itemBuilder: (context, index) { final author = sortedAuthors[index]; - return AuthorCard(author: author); + return RepaintBoundary( + child: AuthorCard(author: author), + ); }, ); }, @@ -125,6 +128,10 @@ class AuthorCard extends HookConsumerWidget { 'Authorization': 'Bearer ${apiSettings.activeUser?.authToken}', }, fit: BoxFit.cover, + fadeInDuration: Duration.zero, // Remove fade animation for better performance + fadeOutDuration: Duration.zero, + memCacheHeight: 300, // Limit memory cache size + maxHeightDiskCache: 600, // Limit disk cache size placeholder: (context, url) => Container( color: Theme.of(context).colorScheme.surfaceContainerHighest, child: const Center( diff --git a/lib/features/library_browser/view/library_genres_page.dart b/lib/features/library_browser/view/library_genres_page.dart index e8cd02a..a619593 100644 --- a/lib/features/library_browser/view/library_genres_page.dart +++ b/lib/features/library_browser/view/library_genres_page.dart @@ -29,6 +29,7 @@ class LibraryGenresPage extends HookConsumerWidget { return ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), + cacheExtent: 500, // Pre-render items for smoother scrolling itemCount: sortedGenres.length, itemBuilder: (context, index) { final genre = sortedGenres[index]; diff --git a/lib/features/library_browser/view/library_series_page.dart b/lib/features/library_browser/view/library_series_page.dart index b680133..fa5705b 100644 --- a/lib/features/library_browser/view/library_series_page.dart +++ b/lib/features/library_browser/view/library_series_page.dart @@ -38,6 +38,7 @@ class LibrarySeriesPage extends HookConsumerWidget { return ListView.builder( padding: const EdgeInsets.symmetric(vertical: 8), + cacheExtent: 500, // Pre-render items for smoother scrolling itemCount: seriesList.length, itemBuilder: (context, index) { final series = seriesList[index];