diff --git a/lib/screens/libraries/tabs/library_browse_tab.dart b/lib/screens/libraries/tabs/library_browse_tab.dart index ce47b3ec..1a5b7d49 100644 --- a/lib/screens/libraries/tabs/library_browse_tab.dart +++ b/lib/screens/libraries/tabs/library_browse_tab.dart @@ -208,6 +208,10 @@ class _LibraryBrowseTabState extends BaseLibraryTabState _loadContent() async { // Cancel any pending request _cancelToken?.cancel(); + _retryTimer?.cancel(); _cancelToken = CancelToken(); // Use a generation counter for the filter/sort loading phase final generation = ++_requestId; @@ -451,6 +457,7 @@ class _LibraryBrowseTabState extends BaseLibraryTabState _loadItems() async { final currentRequestId = ++_requestId; _cancelToken?.cancel(); + _retryTimer?.cancel(); _cancelToken = CancelToken(); setState(() { @@ -506,15 +513,15 @@ class _LibraryBrowseTabState extends BaseLibraryTabState _fetchRange(int start, int size) async { + Future _fetchRange(int start, int size) async { // Clamp to totalSize - if (start >= _totalSize) return; + if (start >= _totalSize) return false; final clampedSize = size.clamp(0, _totalSize - start); - if (clampedSize == 0) return; + if (clampedSize == 0) return false; // Deduplicate: track every index in-flight to prevent overlapping fetches final indices = List.generate(clampedSize, (i) => start + i); - if (indices.every((i) => _loadingRanges.contains(i) || _loadedItems.containsKey(i))) return; + if (indices.every((i) => _loadingRanges.contains(i) || _loadedItems.containsKey(i))) return true; _loadingRanges.addAll(indices); final currentRequestId = _requestId; @@ -531,31 +538,31 @@ class _LibraryBrowseTabState extends BaseLibraryTabState _loadVisibleRange() async { + if (_visibleRangeLoading) return; if (_totalSize == 0 || _currentColumnCount < 1 || !_scrollController.hasClients) return; if (_lastCrossAxisExtent <= 0) return; @@ -1100,7 +1123,6 @@ class _LibraryBrowseTabState extends BaseLibraryTabState