refactor: Better logic for removing outdated notifications

This commit is contained in:
Krille 2024-03-06 15:45:00 +01:00
commit 6d973db6fc
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
5 changed files with 15 additions and 108 deletions

View file

@ -70,9 +70,6 @@ class BackgroundPush {
bool upAction = false;
BackgroundPush._(this.client) {
onRoomSync ??= client.onSync.stream
.where((s) => s.hasRoomUpdate)
.listen((s) => _onClearingPush(getFromServer: false));
firebase?.setListeners(
onMessage: (message) => pushHelper(
PushNotification.fromJson(
@ -128,8 +125,6 @@ class BackgroundPush {
}
}
StreamSubscription<SyncUpdate>? onRoomSync;
Future<void> setupPusher({
String? gatewayUrl,
String? token,
@ -405,95 +400,4 @@ class BackgroundPush {
activeRoomId: matrix?.activeRoomId,
);
}
/// Workaround for the problem that local notification IDs must be int but we
/// sort by [roomId] which is a String. To make sure that we don't have duplicated
/// IDs we map the [roomId] to a number and matrix?.store this number.
late Map<String, int> idMap;
Future<void> _loadIdMap() async {
idMap = Map<String, int>.from(
json.decode(
(matrix?.store.getString(SettingKeys.notificationCurrentIds)) ?? '{}',
),
);
}
bool _clearingPushLock = false;
Future<void> _onClearingPush({bool getFromServer = true}) async {
if (_clearingPushLock) {
return;
}
try {
_clearingPushLock = true;
late Iterable<String> emptyRooms;
if (getFromServer) {
Logs().v('[Push] Got new clearing push');
var syncErrored = false;
if (client.syncPending) {
Logs().v('[Push] waiting for existing sync');
// we need to catchError here as the Future might be in a different execution zone
await client.oneShotSync().catchError((e) {
syncErrored = true;
Logs().v('[Push] Error one-shot syncing', e);
});
}
if (!syncErrored) {
Logs().v('[Push] single oneShotSync');
// we need to catchError here as the Future might be in a different execution zone
await client.oneShotSync().catchError((e) {
syncErrored = true;
Logs().v('[Push] Error one-shot syncing', e);
});
if (!syncErrored) {
emptyRooms = client.rooms
.where((r) => r.notificationCount == 0)
.map((r) => r.id);
}
}
if (syncErrored) {
try {
Logs().v(
'[Push] failed to sync for fallback push, fetching notifications endpoint...',
);
final notifications = await client.getNotifications(limit: 20);
final notificationRooms =
notifications.notifications.map((n) => n.roomId).toSet();
emptyRooms = client.rooms
.where((r) => !notificationRooms.contains(r.id))
.map((r) => r.id);
} catch (e) {
Logs().v(
'[Push] failed to fetch pending notifications for clearing push, falling back...',
e,
);
emptyRooms = client.rooms
.where((r) => r.notificationCount == 0)
.map((r) => r.id);
}
}
} else {
emptyRooms = client.rooms
.where((r) => r.notificationCount == 0)
.map((r) => r.id);
}
await _loadIdMap();
var changed = false;
for (final roomId in emptyRooms) {
final id = idMap[roomId];
if (id != null) {
idMap.remove(roomId);
changed = true;
await _flutterLocalNotificationsPlugin.cancel(id);
}
}
if (changed) {
await matrix?.store.setString(
SettingKeys.notificationCurrentIds,
json.encode(idMap),
);
}
} finally {
_clearingPushLock = false;
}
}
}