mirror of
https://github.com/krille-chan/fluffychat
synced 2024-09-10 12:25:11 +00:00
refactor: Better logic for removing outdated notifications
This commit is contained in:
parent
c0ba68dff5
commit
6d973db6fc
5 changed files with 15 additions and 108 deletions
|
@ -17,7 +17,6 @@ abstract class SettingKeys {
|
||||||
static const String unifiedPushRegistered =
|
static const String unifiedPushRegistered =
|
||||||
'chat.fluffy.unifiedpush.registered';
|
'chat.fluffy.unifiedpush.registered';
|
||||||
static const String unifiedPushEndpoint = 'chat.fluffy.unifiedpush.endpoint';
|
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 ownStatusMessage = 'chat.fluffy.status_msg';
|
||||||
static const String dontAskForBootstrapKey =
|
static const String dontAskForBootstrapKey =
|
||||||
'chat.fluffychat.dont_ask_bootstrap';
|
'chat.fluffychat.dont_ask_bootstrap';
|
||||||
|
|
|
@ -13,13 +13,13 @@ import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.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:go_router/go_router.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:record/record.dart';
|
import 'package:record/record.dart';
|
||||||
import 'package:scroll_to_index/scroll_to_index.dart';
|
import 'package:scroll_to_index/scroll_to_index.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.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/app_config.dart';
|
||||||
import 'package:fluffychat/config/themes.dart';
|
import 'package:fluffychat/config/themes.dart';
|
||||||
|
|
|
@ -70,9 +70,6 @@ class BackgroundPush {
|
||||||
bool upAction = false;
|
bool upAction = false;
|
||||||
|
|
||||||
BackgroundPush._(this.client) {
|
BackgroundPush._(this.client) {
|
||||||
onRoomSync ??= client.onSync.stream
|
|
||||||
.where((s) => s.hasRoomUpdate)
|
|
||||||
.listen((s) => _onClearingPush(getFromServer: false));
|
|
||||||
firebase?.setListeners(
|
firebase?.setListeners(
|
||||||
onMessage: (message) => pushHelper(
|
onMessage: (message) => pushHelper(
|
||||||
PushNotification.fromJson(
|
PushNotification.fromJson(
|
||||||
|
@ -128,8 +125,6 @@ class BackgroundPush {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamSubscription<SyncUpdate>? onRoomSync;
|
|
||||||
|
|
||||||
Future<void> setupPusher({
|
Future<void> setupPusher({
|
||||||
String? gatewayUrl,
|
String? gatewayUrl,
|
||||||
String? token,
|
String? token,
|
||||||
|
@ -405,95 +400,4 @@ class BackgroundPush {
|
||||||
activeRoomId: matrix?.activeRoomId,
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:flutter_local_notifications/flutter_local_notifications.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:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/config/app_config.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/client_manager.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||||
import 'package:fluffychat/utils/platform_infos.dart';
|
import 'package:fluffychat/utils/platform_infos.dart';
|
||||||
|
@ -113,14 +112,20 @@ Future<void> _tryPushHelper(
|
||||||
|
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
Logs().v('Notification is a clearing indicator.');
|
Logs().v('Notification is a clearing indicator.');
|
||||||
if (notification.counts?.unread == 0) {
|
if (notification.counts?.unread == null ||
|
||||||
if (notification.counts == null || notification.counts?.unread == 0) {
|
notification.counts?.unread == 0) {
|
||||||
await flutterLocalNotificationsPlugin.cancelAll();
|
await flutterLocalNotificationsPlugin.cancelAll();
|
||||||
final store = await SharedPreferences.getInstance();
|
} else {
|
||||||
await store.setString(
|
await client.roomsLoading;
|
||||||
SettingKeys.notificationCurrentIds,
|
final activeNotifications =
|
||||||
json.encode({}),
|
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;
|
return;
|
||||||
|
|
|
@ -466,7 +466,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
||||||
client.httpClient.close();
|
client.httpClient.close();
|
||||||
onFocusSub?.cancel();
|
onFocusSub?.cancel();
|
||||||
onBlurSub?.cancel();
|
onBlurSub?.cancel();
|
||||||
backgroundPush?.onRoomSync?.cancel();
|
|
||||||
|
|
||||||
linuxNotifications?.close();
|
linuxNotifications?.close();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue