From af8aa8b9155c60a129869a92179fe1bd1164b74c Mon Sep 17 00:00:00 2001 From: otsmr Date: Sat, 31 May 2025 01:50:39 +0200 Subject: [PATCH] fix #141 --- .../NotificationService.swift | 31 ++++++++++---- lib/src/database/daos/contacts_dao.dart | 15 +++++-- lib/src/services/notification.service.dart | 41 ++++++++++++++++++- lib/src/views/settings/notification.view.dart | 7 +++- 4 files changed, 78 insertions(+), 16 deletions(-) diff --git a/ios/NotificationService/NotificationService.swift b/ios/NotificationService/NotificationService.swift index f828e91..e701472 100644 --- a/ios/NotificationService/NotificationService.swift +++ b/ios/NotificationService/NotificationService.swift @@ -28,11 +28,16 @@ class NotificationService: UNNotificationServiceExtension { let data = getPushNotificationData(pushDataJson: push_data) if data != nil { + if data!.title == "blocked" { + NSLog("Block message because user is blocked!") + // https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.usernotifications.filtering + return contentHandler(UNNotificationContent()) + } bestAttemptContent.title = data!.title; bestAttemptContent.body = data!.body; bestAttemptContent.threadIdentifier = String(format: "%d", data!.notificationId) } else { - bestAttemptContent.title = "\(bestAttemptContent.title) [10]" + bestAttemptContent.title = "\(bestAttemptContent.title)" } contentHandler(bestAttemptContent) @@ -81,6 +86,7 @@ func getPushNotificationData(pushDataJson: String) -> (title: String, body: Stri var pushKind: PushKind? var displayName: String? var fromUserId: Int? + var blocked: Bool? // Check the keyId if pushData.keyId == 0 { @@ -96,6 +102,7 @@ func getPushNotificationData(pushDataJson: String) -> (title: String, body: Stri if pushKind != nil { displayName = userKeys.displayName fromUserId = userId + blocked = userKeys.blocked break } } @@ -107,6 +114,10 @@ func getPushNotificationData(pushDataJson: String) -> (title: String, body: Stri NSLog("pushKeys are empty") } } + + if blocked == true { + return ("blocked", "blocked", 0) + } // Handle the push notification based on the pushKind if let pushKind = pushKind { @@ -118,7 +129,7 @@ func getPushNotificationData(pushDataJson: String) -> (title: String, body: Stri } else { return ("", getPushNotificationTextWithoutUserId(pushKind: pushKind), 1) } - + } else { NSLog("Failed to decrypt message or pushKind is nil") } @@ -259,17 +270,19 @@ struct PushKeyMeta: Codable { struct PushUser: Codable { let displayName: String let keys: [PushKeyMeta] + let blocked: Bool? enum CodingKeys: String, CodingKey { case displayName case keys + case blocked } } func getPushKey() -> [Int: PushUser]? { // Retrieve the data from secure storage (Keychain) guard let data = readFromKeychain(key: "receivingPushKeys") else { - print("No data found for key: receivingPushKeys") + NSLog("No data found for key: receivingPushKeys") return nil } @@ -279,18 +292,18 @@ func getPushKey() -> [Int: PushUser]? { let jsonMap = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] var pushKeys: [Int: PushUser] = [:] - + // Iterate through the JSON map and decode each PushUser for (key, value) in jsonMap ?? [:] { - if let userData = try? JSONSerialization.data(withJSONObject: value, options: []), - let pushUser = try? JSONDecoder().decode(PushUser.self, from: userData) { - pushKeys[Int(key)!] = pushUser - } + if let userData = try? JSONSerialization.data(withJSONObject: value, options: []), + let pushUser = try? JSONDecoder().decode(PushUser.self, from: userData) { + pushKeys[Int(key)!] = pushUser + } } return pushKeys } catch { - print("Error decoding JSON: \(error)") + NSLog("Error decoding JSON: \(error)") return nil } } diff --git a/lib/src/database/daos/contacts_dao.dart b/lib/src/database/daos/contacts_dao.dart index 97daea9..ed5db31 100644 --- a/lib/src/database/daos/contacts_dao.dart +++ b/lib/src/database/daos/contacts_dao.dart @@ -1,6 +1,7 @@ import 'package:drift/drift.dart'; import 'package:twonly/src/database/tables/contacts_table.dart'; import 'package:twonly/src/database/twonly_database.dart'; +import 'package:twonly/src/services/notification.service.dart'; part 'contacts_dao.g.dart'; @@ -97,9 +98,17 @@ class ContactsDao extends DatabaseAccessor return (delete(contacts)..where((t) => t.userId.equals(userId))).go(); } - Future updateContact(int userId, ContactsCompanion updatedValues) { - return (update(contacts)..where((c) => c.userId.equals(userId))) - .write(updatedValues); + Future updateContact(int userId, ContactsCompanion updatedValues) async { + await ((update(contacts)..where((c) => c.userId.equals(userId))) + .write(updatedValues)); + if (updatedValues.blocked.present || + updatedValues.displayName.present || + updatedValues.nickName.present) { + final contact = await getContactByUserId(userId).getSingleOrNull(); + if (contact != null) { + await updatePushUser(contact); + } + } } Future newMessageExchange(int userId) { diff --git a/lib/src/services/notification.service.dart b/lib/src/services/notification.service.dart index 74f739d..b3dff9b 100644 --- a/lib/src/services/notification.service.dart +++ b/lib/src/services/notification.service.dart @@ -16,13 +16,16 @@ import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/model/json/message.dart' as my; import 'package:twonly/src/services/api/messages.dart'; +import 'package:twonly/src/utils/log.dart'; class PushUser { String displayName; + bool blocked; List keys; PushUser({ required this.displayName, + required this.blocked, required this.keys, }); @@ -30,6 +33,7 @@ class PushUser { factory PushUser.fromJson(Map json) { return PushUser( displayName: json['displayName'], + blocked: json['blocked'] ?? false, keys: (json['keys'] as List) .map((keyJson) => PushKeyMeta.fromJson(keyJson)) .toList(), @@ -40,6 +44,7 @@ class PushUser { Map toJson() { return { 'displayName': displayName, + 'blocked': blocked, 'keys': keys.map((key) => key.toJson()).toList(), }; } @@ -111,6 +116,7 @@ Future setupNotificationWithUsers({bool force = false}) async { await sendNewPushKey(contact.userId, pushKey); final pushUser = PushUser( displayName: getContactDisplayName(contact), + blocked: contact.blocked, keys: [pushKey], ); pushKeys[contact.userId] = pushUser; @@ -135,11 +141,29 @@ Future sendNewPushKey(int userId, PushKeyMeta pushKey) async { ); } +Future updatePushUser(Contact contact) async { + var receivingPushKeys = await getPushKeys("receivingPushKeys"); + + if (receivingPushKeys[contact.userId] == null) { + receivingPushKeys[contact.userId] = PushUser( + displayName: getContactDisplayName(contact), + keys: [], + blocked: contact.blocked, + ); + } else { + receivingPushKeys[contact.userId]!.displayName = + getContactDisplayName(contact); + receivingPushKeys[contact.userId]!.blocked = contact.blocked; + } + + await setPushKeys("receivingPushKeys", receivingPushKeys); +} + Future handleNewPushKey(int fromUserId, my.PushKeyContent pushKey) async { var pushKeys = await getPushKeys("sendingPushKeys"); if (pushKeys[fromUserId] == null) { - pushKeys[fromUserId] = PushUser(displayName: "-", keys: []); + pushKeys[fromUserId] = PushUser(displayName: "-", keys: [], blocked: false); } // only store the newest key... @@ -355,7 +379,14 @@ Future setPushKeys(String storageKey, Map pushKeys) async { jsonToSend[key.toString()] = value.toJson(); }); - await storage.delete(key: storageKey); + await storage.delete( + key: storageKey, + iOptions: IOSOptions( + groupId: "CN332ZUGRP.eu.twonly.shared", + synchronizable: false, + accessibility: KeychainAccessibility.first_unlock, + ), + ); String jsonString = jsonEncode(jsonToSend); await storage.write( @@ -433,6 +464,12 @@ Future showLocalPushNotification( if (user == null) return; + // do not show notification for blocked users... + if (user.blocked) { + Log.info("Blocked a message from a blocked user!"); + return; + } + title = getContactDisplayName(user); body = getPushNotificationText(pushKind); if (body == "") { diff --git a/lib/src/views/settings/notification.view.dart b/lib/src/views/settings/notification.view.dart index 6566469..9ccb7ff 100644 --- a/lib/src/views/settings/notification.view.dart +++ b/lib/src/views/settings/notification.view.dart @@ -33,8 +33,11 @@ class NotificationView extends StatelessWidget { if (storedToken == null) { final platform = Platform.isAndroid ? "Google's" : "Apple's"; - showAlertDialog(context, "Problem detected", - "twonly is not able to register your app to $platform push server infrastrukture. For Android that can happen when you do not have the Google Play Services installed. If you theses installed and want to help us to fix the issue please send us your debug log in Settings > Help > Debug log."); + showAlertDialog( + context, + "Problem detected", + "twonly is not able to register your app to $platform push server infrastructure. For Android that can happen when you do not have the Google Play Services installed. If you theses installed and want to help us to fix the issue please send us your debug log in Settings > Help > Debug log.", + ); } else { final run = await showAlertDialog( context,