mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 20:48:24 +00:00
Implement NIP-09 deletions
This commit is contained in:
@@ -234,6 +234,32 @@ Future<bool> _checkForUpdatesInBackground(Set<String>? appCatalogRelays) async {
|
||||
}
|
||||
}
|
||||
|
||||
// NIP-09: fetch kind-5 deletion events since last sync.
|
||||
// No author filter — the AppCatalog relay is curated and the `since`
|
||||
// cursor keeps incremental runs cheap. The DB layer auto-processes
|
||||
// each kind-5 event (removes referenced events, records in deletions
|
||||
// table). We then clean up the kind-5 events themselves as housekeeping,
|
||||
// but save the cursor regardless — a cleanup failure is non-critical.
|
||||
final secureStorage = SecureStorageService();
|
||||
final lastDeletionSync = await secureStorage.getDeletionsSyncedUntil();
|
||||
final deletionRequests = await storage.query(
|
||||
RequestFilter<EventDeletionRequest>(
|
||||
since: lastDeletionSync,
|
||||
limit: 99,
|
||||
).toRequest(subscriptionPrefix: 'app-bg-deletions'),
|
||||
source: const RemoteSource(relays: 'AppCatalog', stream: false),
|
||||
);
|
||||
await secureStorage.setDeletionsSyncedUntil(DateTime.now());
|
||||
if (deletionRequests.isNotEmpty) {
|
||||
try {
|
||||
await (storage as PurplebaseStorageNotifier)
|
||||
.delete(deletionRequests.map((d) => d.id).toSet());
|
||||
} catch (_) {
|
||||
// Orphaned kind-5 rows are harmless; referenced events are
|
||||
// already removed by the DB layer during save.
|
||||
}
|
||||
}
|
||||
|
||||
// Re-query apps from local to ensure relationships are loaded
|
||||
final appsWithRelations = await storage.query(
|
||||
RequestFilter<App>(
|
||||
|
||||
@@ -116,6 +116,34 @@ class SecureStorageService {
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Deletion Sync Timestamp (for NIP-09 incremental checks)
|
||||
// =========================================================================
|
||||
|
||||
static const _deletionSyncedUntilKey = 'deletion_synced_until';
|
||||
|
||||
/// Get the timestamp of the last successful NIP-09 deletion sync.
|
||||
/// Used as `since` on the next kind-5 query so checks are incremental.
|
||||
Future<DateTime?> getDeletionsSyncedUntil() async {
|
||||
final value = await _storage.read(key: _deletionSyncedUntilKey);
|
||||
if (int.tryParse(value ?? '') case final ms?) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(ms);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Persist the deletion sync cursor after a successful kind-5 fetch.
|
||||
Future<void> setDeletionsSyncedUntil(DateTime time) async {
|
||||
await _storage.write(
|
||||
key: _deletionSyncedUntilKey,
|
||||
value: '${time.millisecondsSinceEpoch}',
|
||||
);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// App Catalog Relays
|
||||
// =========================================================================
|
||||
|
||||
/// Store app catalog relay URLs.
|
||||
///
|
||||
/// This is the local source of truth for relay configuration,
|
||||
|
||||
Reference in New Issue
Block a user