From 3b8435c909c3403ada5cdffa56656da093323690 Mon Sep 17 00:00:00 2001 From: franzap <_@franzap.com> Date: Mon, 23 Mar 2026 20:46:16 -0300 Subject: [PATCH] Add indexer pubkey, fix all subscription prefixes --- lib/constants/app_constants.dart | 6 ++++++ lib/main.dart | 1 + lib/screens/app_detail_screen.dart | 1 + lib/screens/app_stack_screen.dart | 1 + lib/screens/profile_screen.dart | 1 + lib/screens/user_screen.dart | 12 +++++++----- lib/services/bookmarks_service.dart | 2 +- lib/services/package_manager/package_manager.dart | 2 ++ lib/services/updates_service.dart | 2 +- lib/utils/extensions.dart | 4 ++-- lib/widgets/app_card.dart | 1 + lib/widgets/app_detail_widgets.dart | 3 ++- lib/widgets/app_stack_container.dart | 1 + lib/widgets/bookmark_widgets.dart | 2 +- lib/widgets/comments_section.dart | 4 +++- lib/widgets/common/note_parser.dart | 1 + lib/widgets/install_alert_dialog.dart | 1 + lib/widgets/latest_releases_container.dart | 4 ++++ lib/widgets/relevant_who_follow_container.dart | 4 ++-- 19 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/constants/app_constants.dart b/lib/constants/app_constants.dart index 64f84e1..282c5f8 100644 --- a/lib/constants/app_constants.dart +++ b/lib/constants/app_constants.dart @@ -5,6 +5,12 @@ const kZapstoreAppIdentifier = 'dev.zapstore.app'; const kZapstorePubkey = '78ce6faa72264387284e647ba6938995735ec8c7d5c5a65737e55130f026307d'; +/// Additional trusted relay pubkeys for relay-signed apps +const kTrustedRelayPubkeys = { + kZapstorePubkey, + 'fd2d438d5c0b419179b67ce4e8ae72a170aeca3045acccbe7661a5e1b5f0b7b1', +}; + /// Franzap's public key for curation sets const kFranzapPubkey = '726a1e261cc6474674e8285e3951b3bb139be9a773d1acf49dc868db861a1c11'; diff --git a/lib/main.dart b/lib/main.dart index 3cfef0a..546f286 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -312,6 +312,7 @@ Future onSignInSuccess(Ref ref) async { await storage.query( RequestFilter(authors: {pubkey}).toRequest(), source: const RemoteSource(relays: 'social', stream: false), + subscriptionPrefix: 'app-contact-list', ); } diff --git a/lib/screens/app_detail_screen.dart b/lib/screens/app_detail_screen.dart index 59c2135..1f02114 100644 --- a/lib/screens/app_detail_screen.dart +++ b/lib/screens/app_detail_screen.dart @@ -179,6 +179,7 @@ class _AppDetailContent extends HookConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-detail-profile', ), ); final author = switch (authorState) { diff --git a/lib/screens/app_stack_screen.dart b/lib/screens/app_stack_screen.dart index bf2bd3a..8b03037 100644 --- a/lib/screens/app_stack_screen.dart +++ b/lib/screens/app_stack_screen.dart @@ -149,6 +149,7 @@ class _AppStackContent extends HookConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-stack-profile', ), ); final author = authorState.models.firstOrNull; diff --git a/lib/screens/profile_screen.dart b/lib/screens/profile_screen.dart index 3baf8a4..77e6914 100644 --- a/lib/screens/profile_screen.dart +++ b/lib/screens/profile_screen.dart @@ -112,6 +112,7 @@ class _AuthenticationSection extends ConsumerWidget { stream: false, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-profile-detail', ), ); final profile = profileState.models.firstOrNull; diff --git a/lib/screens/user_screen.dart b/lib/screens/user_screen.dart index f8512ab..efe4f02 100644 --- a/lib/screens/user_screen.dart +++ b/lib/screens/user_screen.dart @@ -30,6 +30,7 @@ class UserScreen extends HookConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-user-profile', ), ); final profile = profileState.models.firstOrNull; @@ -55,8 +56,8 @@ class UserScreen extends HookConsumerWidget { ), ); - // For Zapstore pubkey, only show Zapstore's own apps (not relay-signed ones) - final apps = pubkey == kZapstorePubkey + // For trusted relay pubkeys, only show Zapstore's own apps (not relay-signed ones) + final apps = kTrustedRelayPubkeys.contains(pubkey) ? userAppsState.models.where((a) => a.isZapstoreApp).toList() : userAppsState.models; @@ -75,7 +76,7 @@ class UserScreen extends HookConsumerWidget { ), }, source: LocalAndRemoteSource(stream: false, relays: 'social'), - subscriptionPrefix: 'user-screen-stacks', + subscriptionPrefix: 'app-user-stacks', schemaFilter: appStackEventFilter, ), ); @@ -210,7 +211,7 @@ class _UserZapsList extends HookConsumerWidget { query( tags: allAppTags, source: const LocalAndRemoteSource(relays: 'social'), - subscriptionPrefix: 'user-screen-app-zaps', + subscriptionPrefix: 'app-user-app-zaps', ), ); @@ -220,7 +221,7 @@ class _UserZapsList extends HookConsumerWidget { query( tags: {'#e': metadataIds}, source: const LocalAndRemoteSource(relays: 'social'), - subscriptionPrefix: 'user-screen-metadata-zaps', + subscriptionPrefix: 'app-user-metadata-zaps', ), ) : null; @@ -253,6 +254,7 @@ class _UserZapsList extends HookConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-user-profiles', ), ); final profilesMap = {for (final p in profilesState.models) p.pubkey: p}; diff --git a/lib/services/bookmarks_service.dart b/lib/services/bookmarks_service.dart index 889bee9..660323d 100644 --- a/lib/services/bookmarks_service.dart +++ b/lib/services/bookmarks_service.dart @@ -25,7 +25,7 @@ final bookmarksProvider = FutureProvider>((ref) async { relays: 'social', stream: false, ), - subscriptionPrefix: 'user-saved-apps', + subscriptionPrefix: 'app-user-saved-apps', ), ); diff --git a/lib/services/package_manager/package_manager.dart b/lib/services/package_manager/package_manager.dart index 57f8b45..246fe60 100644 --- a/lib/services/package_manager/package_manager.dart +++ b/lib/services/package_manager/package_manager.dart @@ -1329,6 +1329,7 @@ abstract class PackageManager extends StateNotifier { try { final results = await storage.query( RequestFilter(ids: {metadataId}).toRequest(), + subscriptionPrefix: 'app-file-metadata', ); if (results.isNotEmpty) return results.first; } catch (_) {} @@ -1340,6 +1341,7 @@ abstract class PackageManager extends StateNotifier { try { final results = await storage.query( RequestFilter(search: hash).toRequest(), + subscriptionPrefix: 'app-file-metadata-search', ); if (results.isNotEmpty) return results.first; } catch (_) {} diff --git a/lib/services/updates_service.dart b/lib/services/updates_service.dart index 8aabfaa..bc000ea 100644 --- a/lib/services/updates_service.dart +++ b/lib/services/updates_service.dart @@ -215,7 +215,7 @@ class UpdatePollerNotifier extends Notifier { cachedFor: Duration(hours: 2), stream: false, ), - subscriptionPrefix: 'updates-profiles', + subscriptionPrefix: 'app-updates-profiles', ), ); } diff --git a/lib/utils/extensions.dart b/lib/utils/extensions.dart index 27ddf4f..8dd6237 100644 --- a/lib/utils/extensions.dart +++ b/lib/utils/extensions.dart @@ -19,8 +19,8 @@ extension AppExt on App { /// Whether this app is one of Zapstore's own apps bool get isZapstoreApp => identifier == kZapstoreAppIdentifier; - /// Whether this app is signed by Zapstore pubkey - bool get isSignedByZapstore => pubkey == kZapstorePubkey; + /// Whether this app is signed by a trusted relay pubkey + bool get isSignedByZapstore => kTrustedRelayPubkeys.contains(pubkey); /// Whether this app is "relay signed" - indexed by Zapstore but not a Zapstore app itself bool get isRelaySigned => isSignedByZapstore && !isZapstoreApp; diff --git a/lib/widgets/app_card.dart b/lib/widgets/app_card.dart index ca0d451..ecbb0fc 100644 --- a/lib/widgets/app_card.dart +++ b/lib/widgets/app_card.dart @@ -181,6 +181,7 @@ class AppCard extends HookConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-card-profile', ), ); diff --git a/lib/widgets/app_detail_widgets.dart b/lib/widgets/app_detail_widgets.dart index 2b2ae71..770c997 100644 --- a/lib/widgets/app_detail_widgets.dart +++ b/lib/widgets/app_detail_widgets.dart @@ -296,7 +296,7 @@ class _ZappersListSection extends ConsumerWidget { '#e': {metadataId}, }, source: const LocalAndRemoteSource(relays: 'social'), - subscriptionPrefix: 'metadata-zaps', + subscriptionPrefix: 'app-metadata-zaps', ), ) : null; @@ -327,6 +327,7 @@ class _ZappersListSection extends ConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-zapper-profiles', ), ); final profilesMap = { diff --git a/lib/widgets/app_stack_container.dart b/lib/widgets/app_stack_container.dart index 75358e6..546f36d 100644 --- a/lib/widgets/app_stack_container.dart +++ b/lib/widgets/app_stack_container.dart @@ -122,6 +122,7 @@ class AppStackContainer extends HookConsumerWidget { stream: false, cachedFor: Duration(hours: 1), ), + subscriptionPrefix: 'app-stack-contacts', ), ) : null; diff --git a/lib/widgets/bookmark_widgets.dart b/lib/widgets/bookmark_widgets.dart index 684decd..1db883e 100644 --- a/lib/widgets/bookmark_widgets.dart +++ b/lib/widgets/bookmark_widgets.dart @@ -289,7 +289,7 @@ class _AddToStackDialogSignedIn extends HookConsumerWidget { stack.apps.query(source: const LocalSource()), }, source: const LocalAndRemoteSource(relays: 'social', stream: false), - subscriptionPrefix: 'user-stacks-dialog', + subscriptionPrefix: 'app-user-stacks-dialog', // Filter at query level: exclude saved-apps stack and stacks with no app references schemaFilter: (event) { final tags = event['tags'] as List?; diff --git a/lib/widgets/comments_section.dart b/lib/widgets/comments_section.dart index f683c44..639e831 100644 --- a/lib/widgets/comments_section.dart +++ b/lib/widgets/comments_section.dart @@ -73,7 +73,7 @@ class StackCommentsSection extends HookConsumerWidget { '#A': {stack.id}, }, source: LocalAndRemoteSource(stream: true, relays: 'social'), - subscriptionPrefix: 'stack-comments', + subscriptionPrefix: 'app-stack-comments', and: (comment) => {comment.replies.query()}, ), ); @@ -274,6 +274,7 @@ class _ThreadedCommentCard extends HookConsumerWidget { stream: false, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-comment-profile', ), ); final author = authorState.models.firstOrNull; @@ -718,6 +719,7 @@ class _ReplyComposer extends HookConsumerWidget { stream: false, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-reply-profile', ), ); final parentAuthor = switch (parentAuthorState) { diff --git a/lib/widgets/common/note_parser.dart b/lib/widgets/common/note_parser.dart index 62cc802..2598ebe 100644 --- a/lib/widgets/common/note_parser.dart +++ b/lib/widgets/common/note_parser.dart @@ -393,6 +393,7 @@ class ProfileEntityWidget extends ConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-note-profile', ), ); diff --git a/lib/widgets/install_alert_dialog.dart b/lib/widgets/install_alert_dialog.dart index e1d03ab..30749e0 100644 --- a/lib/widgets/install_alert_dialog.dart +++ b/lib/widgets/install_alert_dialog.dart @@ -25,6 +25,7 @@ class InstallAlertDialog extends HookConsumerWidget { relays: {'social', 'vertex'}, cachedFor: Duration(hours: 2), ), + subscriptionPrefix: 'app-install-profile', ), ); final publisher = switch (publisherState) { diff --git a/lib/widgets/latest_releases_container.dart b/lib/widgets/latest_releases_container.dart index a9f7349..ffddc5d 100644 --- a/lib/widgets/latest_releases_container.dart +++ b/lib/widgets/latest_releases_container.dart @@ -372,6 +372,7 @@ class LatestReleasesNotifier extends StateNotifier { }, ).toRequest(), source: const LocalAndRemoteSource(stream: false), + subscriptionPrefix: 'app-latest-older', ); if (olderPage.isNotEmpty) { @@ -384,6 +385,7 @@ class LatestReleasesNotifier extends StateNotifier { .toList(), ), source: const RemoteSource(stream: false), + subscriptionPrefix: 'app-latest-releases', ); // Load file metadata for the releases (old format) @@ -396,6 +398,7 @@ class LatestReleasesNotifier extends StateNotifier { .toList(), ), source: const RemoteSource(stream: false), + subscriptionPrefix: 'app-latest-metadata', ); // Load software assets for the releases (new format) await ref.storage.query( @@ -406,6 +409,7 @@ class LatestReleasesNotifier extends StateNotifier { .toList(), ), source: const RemoteSource(stream: false), + subscriptionPrefix: 'app-latest-assets', ); } diff --git a/lib/widgets/relevant_who_follow_container.dart b/lib/widgets/relevant_who_follow_container.dart index 99929e7..df56ed7 100644 --- a/lib/widgets/relevant_who_follow_container.dart +++ b/lib/widgets/relevant_who_follow_container.dart @@ -230,7 +230,7 @@ class RelevantWhoFollowContainer extends HookConsumerWidget { authors: {signedInPubkey}, limit: 1, source: const LocalAndRemoteSource(relays: 'social', stream: false), - subscriptionPrefix: 'user-contacts', + subscriptionPrefix: 'app-user-contacts', ), ); @@ -378,7 +378,7 @@ final relevantWhoFollowProvider = FutureProvider.autoDispose final profiles = await storage.query( Request([RequestFilter(authors: response.pubkeys)]), source: const LocalAndRemoteSource(relays: 'social', stream: false), - subscriptionPrefix: 'verify-reputation-profiles', + subscriptionPrefix: 'app-reputation-profiles', ); return profiles; }