import 'package:localstore/localstore.dart'; /// A rendered notification's bookkeeping, keyed by the Nextcloud notification /// id (`nid`). Lets a later delete-push (which only carries the `nid`) find and /// cancel the exact tray notification that was shown. class NidEntry { final int nid; final int notificationId; final String tag; final String? chatToken; const NidEntry({ required this.nid, required this.notificationId, required this.tag, this.chatToken, }); Map toJson() => { 'nid': nid, 'notificationId': notificationId, 'tag': tag, if (chatToken != null) 'chatToken': chatToken, }; factory NidEntry.fromJson(Map json) => NidEntry( nid: (json['nid'] as num).toInt(), notificationId: (json['notificationId'] as num).toInt(), tag: json['tag'] as String, chatToken: json['chatToken'] as String?, ); } /// Persists the `nid → tray notification` mapping via [Localstore] so both the /// foreground and background isolates can resolve delete-pushes. class NidStore { static const _collection = 'push_nids'; final Localstore _db; NidStore({Localstore? db}) : _db = db ?? Localstore.instance; Future put(NidEntry entry) => _db.collection(_collection).doc('${entry.nid}').set(entry.toJson()); Future get(int nid) async { final data = await _db.collection(_collection).doc('$nid').get(); if (data == null) return null; return NidEntry.fromJson(data); } Future delete(int nid) => _db.collection(_collection).doc('$nid').delete(); Future> all() async { final docs = await _db.collection(_collection).get(); if (docs == null) return const []; return docs.values .map((e) => NidEntry.fromJson(e as Map)) .toList(); } Future clear() async { final docs = await _db.collection(_collection).get(); if (docs == null) return; for (final id in docs.keys) { // Localstore keys are the full document paths (/push_nids/). final nid = int.tryParse(id.split('/').last); if (nid != null) await delete(nid); } } }