From 185ac49de92fbfa0a719ba9f259b768e58b09720 Mon Sep 17 00:00:00 2001 From: otsmr Date: Wed, 5 Aug 2026 00:35:12 +0200 Subject: [PATCH] show msg in case app is --- .../background.notifications.dart | 5 ++ .../notifications/fcm.notifications.dart | 60 +++++++++++++++++++ pubspec.yaml | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/lib/src/services/notifications/background.notifications.dart b/lib/src/services/notifications/background.notifications.dart index eab8fe5d..df1d9fa6 100644 --- a/lib/src/services/notifications/background.notifications.dart +++ b/lib/src/services/notifications/background.notifications.dart @@ -102,6 +102,7 @@ Future showLocalPushNotification( PushUser pushUser, PushNotification pushNotification, { String? groupId, + String? titleSuffix, }) async { String? title; String? body; @@ -141,6 +142,10 @@ Future showLocalPushNotification( } title = pushUser.displayName; + if (titleSuffix != null && titleSuffix.isNotEmpty) { + title = '$title $titleSuffix'; + } + body = getPushNotificationText(pushNotification); if (body == '') { Log.error('No push notification type defined!'); diff --git a/lib/src/services/notifications/fcm.notifications.dart b/lib/src/services/notifications/fcm.notifications.dart index b0fca4c8..5f1938dc 100644 --- a/lib/src/services/notifications/fcm.notifications.dart +++ b/lib/src/services/notifications/fcm.notifications.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'dart:io' show Platform; import 'package:firebase_app_installations/firebase_app_installations.dart'; @@ -8,10 +9,13 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/locator.dart'; import 'package:twonly/src/constants/secure_storage.keys.dart'; +import 'package:twonly/src/model/protobuf/client/generated/push_notification.pb.dart'; import 'package:twonly/src/services/notifications/background.notifications.dart'; import 'package:twonly/src/services/notifications/fcm.background.dart'; +import 'package:twonly/src/services/notifications/pushkeys.notifications.dart'; import 'package:twonly/src/services/user.service.dart'; import 'package:twonly/src/utils/log.dart'; +import 'package:twonly/src/utils/misc.dart'; import '../../../firebase_options.dart'; @@ -144,6 +148,7 @@ class FcmNotificationService { } static Future handleRemoteMessage(RemoteMessage message) async { + Log.info('handleRemoteMessage received message: ${message.messageId}'); await _updateLastFcmMessageTimestamp(); if (!Platform.isAndroid) { Log.error('Got message in Dart while on iOS'); @@ -155,6 +160,61 @@ class FcmNotificationService { return; } + // In scenarios like Android Doze Mode or aggressive background restrictions, the OS may kill + // or heavily restrict network access, preventing the WebSocket from connecting in time. + // By parsing the FCM data payload offline, we can instantly display the notification, which also + // prevents FCM from penalizing/downgrading the app's data message priority for failing to show a notification. + // This is just a workarround until the new Rust decryption is enrolled fully. + final pushDataString = message.data['push_data'] as String?; + if (pushDataString != null) { + try { + final pushDataBytes = base64Decode(pushDataString); + final encryptedPush = EncryptedPushNotification.fromBuffer( + pushDataBytes, + ); + final pushUsers = await getPushKeys( + SecureStorageKeys.receivingPushKeys, + ); + for (final pushUser in pushUsers) { + for (final pushKey in pushUser.pushKeys) { + final decrypted = await tryDecryptMessage( + pushKey.key, + encryptedPush, + ); + if (decrypted != null) { + if (isUUIDNewer(pushUser.lastMessageId, decrypted.messageId)) { + Log.info( + 'Skipping local push notification because message is older than lastMessageId', + ); + return; + } + Log.info( + 'Successfully decrypted push_data directly from FCM payload! Showing notification.', + ); + await showLocalPushNotification( + pushUser, + decrypted, + titleSuffix: + (userService.isUserCreated && + userService.currentUser.isDeveloper) + ? ' [d]' + : null, + ); + unawaited( + updateLastMessageId( + pushUser.userId.toInt(), + decrypted.messageId, + ), + ); + return; + } + } + } + } catch (e) { + Log.error('Error handling push_data: $e'); + } + } + if (message.notification != null || message.data['title'] != null) { final title = message.notification?.title ?? message.data['title'] as String? ?? ''; diff --git a/pubspec.yaml b/pubspec.yaml index 747d3f21..1713105e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: "twonly, a privacy-friendly way to connect with friends through sec publish_to: 'none' -version: 0.5.0+166 +version: 0.5.0+167 environment: sdk: ^3.11.0