refactor: Better logic for removing outdated notifications

This commit is contained in:
Krille 2024-03-06 15:45:00 +01:00
parent c0ba68dff5
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

@ -17,7 +17,6 @@ abstract class SettingKeys {
static const String unifiedPushRegistered =
'chat.fluffy.unifiedpush.registered';
static const String unifiedPushEndpoint = 'chat.fluffy.unifiedpush.endpoint';
static const String notificationCurrentIds = 'chat.fluffy.notification_ids';
static const String ownStatusMessage = 'chat.fluffy.status_msg';
static const String dontAskForBootstrapKey =
'chat.fluffychat.dont_ask_bootstrap';

View file

@ -13,13 +13,13 @@ import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:universal_html/html.dart' as html;
import 'package:go_router/go_router.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart';
import 'package:record/record.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:universal_html/html.dart' as html;
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';

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;
}
}
}

View file

@ -1,10 +1,10 @@
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
@ -13,7 +13,6 @@ import 'package:matrix/matrix.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/utils/client_manager.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart';
@ -113,14 +112,20 @@ Future<void> _tryPushHelper(
if (event == null) {
Logs().v('Notification is a clearing indicator.');
if (notification.counts?.unread == 0) {
if (notification.counts == null || notification.counts?.unread == 0) {
await flutterLocalNotificationsPlugin.cancelAll();
final store = await SharedPreferences.getInstance();
await store.setString(
SettingKeys.notificationCurrentIds,
json.encode({}),
if (notification.counts?.unread == null ||
notification.counts?.unread == 0) {
await flutterLocalNotificationsPlugin.cancelAll();
} else {
await client.roomsLoading;
final activeNotifications =
await flutterLocalNotificationsPlugin.getActiveNotifications();
for (final activeNotification in activeNotifications) {
final room = client.rooms.singleWhereOrNull(
(room) => room.id.hashCode == activeNotification.id,
);
if (room == null || !room.isUnreadOrInvited) {
flutterLocalNotificationsPlugin.cancel(activeNotification.id!);
}
}
}
return;

View file

@ -466,7 +466,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
client.httpClient.close();
onFocusSub?.cancel();
onBlurSub?.cancel();
backgroundPush?.onRoomSync?.cancel();
linuxNotifications?.close();