From 85aea3bccf64141c3e12ecdf847b484a280fa3ec Mon Sep 17 00:00:00 2001 From: franzap <_@franzap.com> Date: Fri, 10 Apr 2026 22:39:41 -0300 Subject: [PATCH] Fix latest releases bug --- lib/widgets/latest_releases_container.dart | 100 ++++++++++++--------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/lib/widgets/latest_releases_container.dart b/lib/widgets/latest_releases_container.dart index eb88f57..c8ef4f1 100644 --- a/lib/widgets/latest_releases_container.dart +++ b/lib/widgets/latest_releases_container.dart @@ -31,12 +31,12 @@ class LatestReleasesState { }); factory LatestReleasesState.loading() => const LatestReleasesState( - firstPage: [], - olderPages: [], - appsByIdentifier: {}, - isLoadingMore: false, - hasMore: true, - ); + firstPage: [], + olderPages: [], + appsByIdentifier: {}, + isLoadingMore: false, + hasMore: true, + ); bool get isLoading => firstPage.isEmpty && olderPages.isEmpty && error == null; @@ -50,15 +50,14 @@ class LatestReleasesState { bool? isLoadingMore, bool? hasMore, Object? error, - }) => - LatestReleasesState( - firstPage: firstPage ?? this.firstPage, - olderPages: olderPages ?? this.olderPages, - appsByIdentifier: appsByIdentifier ?? this.appsByIdentifier, - isLoadingMore: isLoadingMore ?? this.isLoadingMore, - hasMore: hasMore ?? this.hasMore, - error: error, - ); + }) => LatestReleasesState( + firstPage: firstPage ?? this.firstPage, + olderPages: olderPages ?? this.olderPages, + appsByIdentifier: appsByIdentifier ?? this.appsByIdentifier, + isLoadingMore: isLoadingMore ?? this.isLoadingMore, + hasMore: hasMore ?? this.hasMore, + error: error, + ); } // --------------------------------------------------------------------------- @@ -78,18 +77,19 @@ class LatestReleasesNotifier extends StateNotifier { _sub = ref.listen( query( limit: _kPageSize, - where: (r) => r.event.getTagSetValues('f').contains('android-arm64-v8a'), source: const LocalAndRemoteSource(relays: 'AppCatalog', stream: true), subscriptionPrefix: 'app-latest-releases', ), (_, next) async { if (next is StorageData) { final liveIds = next.models.map((r) => r.id).toSet(); - final filteredOlder = - state.olderPages.where((r) => !liveIds.contains(r.id)).toList(); + final filteredOlder = state.olderPages + .where((r) => !liveIds.contains(r.id)) + .toList(); final unresolved = next.models - .where((r) => - !state.appsByIdentifier.containsKey(r.appIdentifier)) + .where( + (r) => !state.appsByIdentifier.containsKey(r.appIdentifier), + ) .toList(); final apps = await _resolveRelated(unresolved); if (mounted) { @@ -127,20 +127,17 @@ class LatestReleasesNotifier extends StateNotifier { subscriptionPrefix: 'app-latest-releases-older', ); - final filtered = releases - .where((r) => r.event.getTagSetValues('f').contains('android-arm64-v8a')) - .toList(); - - if (filtered.isEmpty) { + if (releases.isEmpty) { state = state.copyWith(isLoadingMore: false, hasMore: false); return; } - final apps = await _resolveRelated(filtered); + final apps = await _resolveRelated(releases); final existingIds = all.map((r) => r.id).toSet(); - final unique = - filtered.where((r) => !existingIds.contains(r.id)).toList(); + final unique = releases + .where((r) => !existingIds.contains(r.id)) + .toList(); state = state.copyWith( olderPages: [...state.olderPages, ...unique], appsByIdentifier: {...state.appsByIdentifier, ...apps}, @@ -158,8 +155,9 @@ class LatestReleasesNotifier extends StateNotifier { if (releases.isEmpty) return const {}; final storage = ref.read(storageNotifierProvider.notifier); - final assetIds = - releases.expand((r) => r.event.getTagSetValues('e')).toSet(); + final assetIds = releases + .expand((r) => r.event.getTagSetValues('e')) + .toSet(); final appIds = releases .map((r) => r.appIdentifier) .where((id) => id.isNotEmpty) @@ -170,7 +168,9 @@ class LatestReleasesNotifier extends StateNotifier { storage.query( RequestFilter( ids: assetIds, - tags: {'#f': {'android-arm64-v8a'}}, + tags: { + '#f': {'android-arm64-v8a'}, + }, ).toRequest(), source: const LocalAndRemoteSource( relays: 'AppCatalog', @@ -180,9 +180,7 @@ class LatestReleasesNotifier extends StateNotifier { ), if (appIds.isNotEmpty) storage.query( - RequestFilter( - tags: {'#d': appIds, '#f': {'android-arm64-v8a'}}, - ).toRequest(), + RequestFilter(tags: {'#d': appIds}).toRequest(), source: const LocalAndRemoteSource( relays: 'AppCatalog', stream: false, @@ -194,11 +192,19 @@ class LatestReleasesNotifier extends StateNotifier { if (appIds.isEmpty) return const {}; final apps = appIds - .expand((id) => storage.querySync( - RequestFilter(tags: {'#d': {id}}, limit: 1).toRequest(), - )) + .expand( + (id) => storage.querySync( + RequestFilter( + tags: { + '#d': {id}, + }, + limit: 1, + ).toRequest(), + ), + ) .cast() .toList(); + '${apps.map((a) => a.identifier).toList()}'; await loadAuthors(storage, apps, 'app-latest-releases-authors'); return {for (final app in apps) app.identifier: app}; @@ -213,8 +219,8 @@ class LatestReleasesNotifier extends StateNotifier { final latestReleasesProvider = StateNotifierProvider((ref) { - return LatestReleasesNotifier(ref); -}); + return LatestReleasesNotifier(ref); + }); // --------------------------------------------------------------------------- // Widget @@ -264,6 +270,7 @@ class LatestReleasesContainer extends HookConsumerWidget { ref.read(latestReleasesProvider.notifier).loadMore(); } } + scrollController.addListener(onScroll); return () => scrollController.removeListener(onScroll); }, [scrollController, state]); @@ -288,7 +295,13 @@ class LatestReleasesContainer extends HookConsumerWidget { if (state.isLoadingMore) const Padding( padding: EdgeInsets.all(16.0), - child: Center(child: CircularProgressIndicator()), + child: Center( + child: SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(strokeWidth: 5), + ), + ), ), ], const SizedBox(height: 24), @@ -313,10 +326,9 @@ class LatestReleasesContainer extends HookConsumerWidget { child: Text( 'LATEST RELEASES', style: context.textTheme.labelLarge?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withValues(alpha: 0.85), + color: Theme.of( + context, + ).colorScheme.onSurface.withValues(alpha: 0.85), letterSpacing: 1.5, fontWeight: FontWeight.bold, ),