mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 13:08:42 +00:00
fix #213
This commit is contained in:
parent
3b777f7130
commit
ff96a80373
3 changed files with 256 additions and 385 deletions
|
|
@ -1,421 +1,286 @@
|
||||||
//
|
import CryptoKit
|
||||||
// NotificationService.swift
|
import Foundation
|
||||||
// NotificationService
|
import Security
|
||||||
//
|
import UserNotifications
|
||||||
// Created by Tobi on 03.04.25.
|
|
||||||
//
|
|
||||||
|
|
||||||
// import UserNotifications
|
class NotificationService: UNNotificationServiceExtension {
|
||||||
// import CryptoKit
|
|
||||||
// import Foundation
|
|
||||||
|
|
||||||
// class NotificationService: UNNotificationServiceExtension {
|
var contentHandler: ((UNNotificationContent) -> Void)?
|
||||||
|
var bestAttemptContent: UNMutableNotificationContent?
|
||||||
|
|
||||||
// var contentHandler: ((UNNotificationContent) -> Void)?
|
override func didReceive(
|
||||||
// var bestAttemptContent: UNMutableNotificationContent?
|
_ request: UNNotificationRequest,
|
||||||
|
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
|
||||||
|
) {
|
||||||
|
self.contentHandler = contentHandler
|
||||||
|
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
||||||
|
|
||||||
// override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
if let bestAttemptContent = bestAttemptContent {
|
||||||
// self.contentHandler = contentHandler
|
|
||||||
// bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
|
|
||||||
|
|
||||||
// if let bestAttemptContent = bestAttemptContent {
|
guard bestAttemptContent.userInfo as? [String: Any] != nil,
|
||||||
|
let push_data = bestAttemptContent.userInfo["push_data"] as? String
|
||||||
|
else {
|
||||||
|
return contentHandler(bestAttemptContent)
|
||||||
|
}
|
||||||
|
|
||||||
// guard let _ = bestAttemptContent.userInfo as? [String: Any],
|
let data = getPushNotificationData(pushData: push_data)
|
||||||
// let push_data = bestAttemptContent.userInfo["push_data"] as? String else {
|
|
||||||
// return contentHandler(bestAttemptContent);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 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)"
|
||||||
|
}
|
||||||
|
|
||||||
// if data != nil {
|
contentHandler(bestAttemptContent)
|
||||||
// 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)"
|
|
||||||
// }
|
|
||||||
|
|
||||||
// contentHandler(bestAttemptContent)
|
override func serviceExtensionTimeWillExpire() {
|
||||||
// }
|
// Called just before the extension will be terminated by the system.
|
||||||
// }
|
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
|
||||||
|
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
||||||
|
contentHandler(bestAttemptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// override func serviceExtensionTimeWillExpire() {
|
}
|
||||||
// // Called just before the extension will be terminated by the system.
|
|
||||||
// // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
|
|
||||||
// if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
|
||||||
// contentHandler(bestAttemptContent)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
func getPushNotificationData(pushData: String) -> (
|
||||||
|
title: String, body: String, notificationId: Int64
|
||||||
|
)? {
|
||||||
|
|
||||||
|
guard let data = Data(base64Encoded: pushData) else {
|
||||||
|
NSLog("Failed to decode base64 string")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// enum PushKind: String, Codable {
|
do {
|
||||||
// case text
|
let pushData = try EncryptedPushNotification(serializedBytes: data)
|
||||||
// case twonly
|
|
||||||
// case video
|
|
||||||
// case image
|
|
||||||
// case contactRequest
|
|
||||||
// case acceptRequest
|
|
||||||
// case storedMediaFile
|
|
||||||
// case reaction
|
|
||||||
// case testNotification
|
|
||||||
// case reopenedMedia
|
|
||||||
// case reactionToVideo
|
|
||||||
// case reactionToText
|
|
||||||
// case reactionToImage
|
|
||||||
// case response
|
|
||||||
// }
|
|
||||||
|
|
||||||
// import CryptoKit
|
|
||||||
// import Foundation
|
|
||||||
// import Security
|
|
||||||
|
|
||||||
// func getPushNotificationData(pushDataJson: String) -> (title: String, body: String, notificationId: Int)? {
|
var pushNotification: PushNotification?
|
||||||
// // Decode the pushDataJson
|
var pushUser: PushUser?
|
||||||
// guard let pushData = decodePushData(pushDataJson) else {
|
|
||||||
// NSLog("Failed to decode push data")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var pushKind: PushKind?
|
// Check the keyId
|
||||||
// var displayName: String?
|
if pushData.keyID == 0 {
|
||||||
// var fromUserId: Int?
|
let key = "InsecureOnlyUsedForAddingContact".data(using: .utf8)!
|
||||||
// var blocked: Bool?
|
pushNotification = tryDecryptMessage(key: key, pushData: pushData)
|
||||||
|
} else {
|
||||||
|
let pushUsers = getPushUsers()
|
||||||
|
if pushUsers != nil {
|
||||||
|
for tryPushUser in pushUsers! {
|
||||||
|
for pushKey in tryPushUser.pushKeys {
|
||||||
|
if pushKey.id == pushData.keyID {
|
||||||
|
pushNotification = tryDecryptMessage(key: pushKey.key, pushData: pushData)
|
||||||
|
if pushNotification != nil {
|
||||||
|
if (pushNotification!.messageID <= pushUser!.lastMessageID) {
|
||||||
|
return ("blocked", "blocked", 0)
|
||||||
|
}
|
||||||
|
pushUser = tryPushUser
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pushUser != nil { break }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NSLog("pushKeys are empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pushUser?.blocked == true {
|
||||||
|
return ("blocked", "blocked", 0)
|
||||||
|
}
|
||||||
|
|
||||||
// // Check the keyId
|
// Handle the push notification based on the pushKind
|
||||||
// if pushData.keyId == 0 {
|
if let pushNotification = pushNotification {
|
||||||
// let key = "InsecureOnlyUsedForAddingContact".data(using: .utf8)!.map { Int($0) }
|
|
||||||
// pushKind = tryDecryptMessage(key: key, pushData: pushData)
|
|
||||||
// } else {
|
|
||||||
// let pushKeys = getPushKey()
|
|
||||||
// if pushKeys != nil {
|
|
||||||
// for (userId, userKeys) in pushKeys! {
|
|
||||||
// for key in userKeys.keys {
|
|
||||||
// if key.id == pushData.keyId {
|
|
||||||
// pushKind = tryDecryptMessage(key: key.key, pushData: pushData)
|
|
||||||
// if pushKind != nil {
|
|
||||||
// displayName = userKeys.displayName
|
|
||||||
// fromUserId = userId
|
|
||||||
// blocked = userKeys.blocked
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Found correct key and user
|
|
||||||
// if displayName != nil { break }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// NSLog("pushKeys are empty")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if blocked == true {
|
if pushNotification.kind == .testNotification {
|
||||||
// return ("blocked", "blocked", 0)
|
return ("Test Notification", "This is a test notification.", 0)
|
||||||
// }
|
} else if pushUser != nil {
|
||||||
|
return (pushUser!.displayName, getPushNotificationText(pushNotification: pushNotification), pushUser!.userID)
|
||||||
|
} else {
|
||||||
|
return ("", getPushNotificationTextWithoutUserId(pushKind: pushNotification.kind), 1)
|
||||||
|
}
|
||||||
|
|
||||||
// // Handle the push notification based on the pushKind
|
} else {
|
||||||
// if let pushKind = pushKind {
|
NSLog("Failed to decrypt message or pushKind is nil")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} catch {
|
||||||
|
NSLog("Error decoding JSON: \(error)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if pushKind == .testNotification {
|
func tryDecryptMessage(key: Data, pushData: EncryptedPushNotification) -> PushNotification? {
|
||||||
// return ("Test Notification", "This is a test notification.", 0)
|
|
||||||
// } else if displayName != nil && fromUserId != nil {
|
|
||||||
// return (displayName!, getPushNotificationText(pushKind: pushKind), fromUserId!)
|
|
||||||
// } else {
|
|
||||||
// return ("", getPushNotificationTextWithoutUserId(pushKind: pushKind), 1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } else {
|
do {
|
||||||
// NSLog("Failed to decrypt message or pushKind is nil")
|
// Create a nonce for ChaChaPoly
|
||||||
// }
|
let nonce = try ChaChaPoly.Nonce(data: pushData.nonce)
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func tryDecryptMessage(key: [Int], pushData: PushNotification) -> PushKind? {
|
// Create a sealed box for ChaChaPoly
|
||||||
// // Convert the key from [Int] to Data
|
let sealedBox = try ChaChaPoly.SealedBox(
|
||||||
// let keyData = Data(key.map { UInt8($0) }) // Convert Int to UInt8
|
nonce: nonce,
|
||||||
|
ciphertext: pushData.ciphertext,
|
||||||
|
tag: pushData.mac
|
||||||
|
)
|
||||||
|
|
||||||
// guard let nonceData = Data(base64Encoded: pushData.nonce),
|
// Decrypt the data using the key
|
||||||
// let cipherTextData = Data(base64Encoded: pushData.cipherText),
|
let decryptedData = try ChaChaPoly.open(sealedBox, using: SymmetricKey(data: key))
|
||||||
// let macData = Data(base64Encoded: pushData.mac) else {
|
|
||||||
// NSLog("Failed to decode base64 strings")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// do {
|
// Here you can determine the PushKind based on the decrypted message
|
||||||
// // Create a nonce for ChaChaPoly
|
return try PushNotification(serializedBytes: decryptedData)
|
||||||
// let nonce = try ChaChaPoly.Nonce(data: nonceData)
|
} catch {
|
||||||
|
NSLog("Decryption failed: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
// // Create a sealed box for ChaChaPoly
|
return nil
|
||||||
// let sealedBox = try ChaChaPoly.SealedBox(nonce: nonce, ciphertext: cipherTextData, tag: macData)
|
}
|
||||||
|
|
||||||
// // Decrypt the data using the key
|
func getPushUsers() -> [PushUser]? {
|
||||||
// let decryptedData = try ChaChaPoly.open(sealedBox, using: SymmetricKey(data: keyData))
|
// Retrieve the data from secure storage (Keychain)
|
||||||
|
guard let pushUsersB64 = readFromKeychain(key: "receiving_push_keys") else {
|
||||||
|
NSLog("No data found for key: receiving_push_keys")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
guard let pushUsersBytes = Data(base64Encoded: pushUsersB64) else {
|
||||||
|
NSLog("Failed to decode base64 push users")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// // Convert decrypted data to a string
|
do {
|
||||||
// if let decryptedMessage = String(data: decryptedData, encoding: .utf8) {
|
let pushUsers = try PushUsers(serializedBytes: pushUsersBytes)
|
||||||
// NSLog("Decrypted message: \(decryptedMessage)")
|
return pushUsers.users
|
||||||
|
} catch {
|
||||||
|
NSLog("Error decoding JSON: \(error)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// // Here you can determine the PushKind based on the decrypted message
|
// Helper function to read from Keychain
|
||||||
// return determinePushKind(from: decryptedMessage)
|
func readFromKeychain(key: String) -> String? {
|
||||||
// }
|
let query: [String: Any] = [
|
||||||
// } catch {
|
kSecClass as String: kSecClassGenericPassword,
|
||||||
// NSLog("Decryption failed: \(error)")
|
kSecAttrAccount as String: key,
|
||||||
// }
|
kSecReturnData as String: kCFBooleanTrue!,
|
||||||
|
kSecMatchLimit as String: kSecMatchLimitOne,
|
||||||
|
kSecAttrAccessGroup as String: "CN332ZUGRP.eu.twonly.shared", // Use your access group
|
||||||
|
]
|
||||||
|
|
||||||
// return nil
|
var dataTypeRef: AnyObject? = nil
|
||||||
// }
|
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
|
||||||
|
|
||||||
// // Placeholder function to determine PushKind from the decrypted message
|
if status == errSecSuccess {
|
||||||
// func determinePushKind(from message: String) -> PushKind? {
|
if let data = dataTypeRef as? Data {
|
||||||
// // Implement your logic to determine the PushKind based on the message content
|
return String(data: data, encoding: .utf8)
|
||||||
// // For example, you might check for specific keywords or formats in the message
|
}
|
||||||
// // This is just a placeholder implementation
|
}
|
||||||
// if message.contains("text") {
|
|
||||||
// return .text
|
|
||||||
// } else if message.contains("video") {
|
|
||||||
// return .video
|
|
||||||
// } else if message.contains("image") {
|
|
||||||
// return .image
|
|
||||||
// } else if message.contains("twonly") {
|
|
||||||
// return .twonly
|
|
||||||
// } else if message.contains("contactRequest") {
|
|
||||||
// return .contactRequest
|
|
||||||
// } else if message.contains("acceptRequest") {
|
|
||||||
// return .acceptRequest
|
|
||||||
// } else if message.contains("storedMediaFile") {
|
|
||||||
// return .storedMediaFile
|
|
||||||
// } else if message.contains("reaction") {
|
|
||||||
// return .reaction
|
|
||||||
// } else if message.contains("testNotification") {
|
|
||||||
// return .testNotification
|
|
||||||
// } else if message.contains("reopenedMedia") {
|
|
||||||
// return .reopenedMedia
|
|
||||||
// } else if message.contains("reactionToVideo") {
|
|
||||||
// return .reactionToVideo
|
|
||||||
// } else if message.contains("reactionToText") {
|
|
||||||
// return .reactionToText
|
|
||||||
// } else if message.contains("reactionToImage") {
|
|
||||||
// return .reactionToImage
|
|
||||||
// } else if message.contains("response") {
|
|
||||||
// return .response
|
|
||||||
// } else {
|
|
||||||
// return nil // Unknown PushKind
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func decodePushData(_ json: String) -> PushNotification? {
|
return nil
|
||||||
// // First, decode the base64 string
|
}
|
||||||
// guard let base64Data = Data(base64Encoded: json) else {
|
|
||||||
// NSLog("Failed to decode base64 string")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Convert the base64 decoded data to a JSON string
|
func getPushNotificationText(pushNotification: PushNotification) -> String {
|
||||||
// guard let jsonString = String(data: base64Data, encoding: .utf8) else {
|
let systemLanguage = Locale.current.language.languageCode?.identifier ?? "en" // Get the current system language
|
||||||
// NSLog("Failed to convert base64 data to JSON string")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Convert the JSON string to Data
|
var pushNotificationText: [PushKind: String] = [:]
|
||||||
// guard let jsonData = jsonString.data(using: .utf8) else {
|
|
||||||
// NSLog("Failed to convert JSON string to Data")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// do {
|
// Define the messages based on the system language
|
||||||
// // Use JSONDecoder to decode the JSON data into a PushNotification instance
|
if systemLanguage.contains("de") { // German
|
||||||
// let decoder = JSONDecoder()
|
pushNotificationText = [
|
||||||
// let pushNotification = try decoder.decode(PushNotification.self, from: jsonData)
|
.text: "hat dir eine Nachricht gesendet.",
|
||||||
// return pushNotification
|
.twonly: "hat dir ein twonly gesendet.",
|
||||||
// } catch {
|
.video: "hat dir ein Video gesendet.",
|
||||||
// NSLog("Error decoding JSON: \(error)")
|
.image: "hat dir ein Bild gesendet.",
|
||||||
// return nil
|
.contactRequest: "möchte sich mit dir vernetzen.",
|
||||||
// }
|
.acceptRequest: "ist jetzt mit dir vernetzt.",
|
||||||
// }
|
.storedMediaFile: "hat dein Bild gespeichert.",
|
||||||
|
.reaction: "hat auf dein Bild reagiert.",
|
||||||
|
.testNotification: "Das ist eine Testbenachrichtigung.",
|
||||||
|
.reopenedMedia: "hat dein Bild erneut geöffnet.",
|
||||||
|
.reactionToVideo: "hat mit {{reaction}} auf dein Video reagiert.",
|
||||||
|
.reactionToText: "hat mit {{reaction}} auf deinen Text reagiert.",
|
||||||
|
.reactionToImage: "hat mit {{reaction}} auf dein Bild reagiert.",
|
||||||
|
.response: "hat dir geantwortet.",
|
||||||
|
]
|
||||||
|
} else { // Default to English
|
||||||
|
pushNotificationText = [
|
||||||
|
.text: "has sent you a message.",
|
||||||
|
.twonly: "has sent you a twonly.",
|
||||||
|
.video: "has sent you a video.",
|
||||||
|
.image: "has sent you an image.",
|
||||||
|
.contactRequest: "wants to connect with you.",
|
||||||
|
.acceptRequest: "is now connected with you.",
|
||||||
|
.storedMediaFile: "has stored your image.",
|
||||||
|
.reaction: "has reacted to your image.",
|
||||||
|
.testNotification: "This is a test notification.",
|
||||||
|
.reopenedMedia: "has reopened your image.",
|
||||||
|
.reactionToVideo: "has reacted with {{reaction}} to your video.",
|
||||||
|
.reactionToText: "has reacted with {{reaction}} to your text.",
|
||||||
|
.reactionToImage: "has reacted with {{reaction}} to your image.",
|
||||||
|
.response: "has responded.",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var content = pushNotificationText[pushNotification.kind] ?? "";
|
||||||
|
|
||||||
|
if (pushNotification.hasReactionContent) {
|
||||||
|
content.replace("{{reaction}}", with: pushNotification.reactionContent)
|
||||||
|
}
|
||||||
|
|
||||||
// struct PushNotification: Codable {
|
// Return the corresponding message or an empty string if not found
|
||||||
// let keyId: Int
|
return content
|
||||||
// let nonce: String
|
}
|
||||||
// let cipherText: String
|
|
||||||
// let mac: String
|
|
||||||
|
|
||||||
// // You can add custom coding keys if the JSON keys differ from the property names
|
func getPushNotificationTextWithoutUserId(pushKind: PushKind) -> String {
|
||||||
// enum CodingKeys: String, CodingKey {
|
let systemLanguage = Locale.current.language.languageCode?.identifier ?? "en" // Get the current system language
|
||||||
// case keyId
|
|
||||||
// case nonce
|
|
||||||
// case cipherText
|
|
||||||
// case mac
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// struct PushKeyMeta: Codable {
|
var pushNotificationText: [PushKind: String] = [:]
|
||||||
// let id: Int
|
|
||||||
// let key: [Int]
|
|
||||||
// let createdAt: Date
|
|
||||||
|
|
||||||
// enum CodingKeys: String, CodingKey {
|
// Define the messages based on the system language
|
||||||
// case id
|
if systemLanguage.contains("de") { // German
|
||||||
// case key
|
pushNotificationText = [
|
||||||
// case createdAt
|
.text: "Du hast eine Nachricht erhalten.",
|
||||||
// }
|
.twonly: "Du hast ein twonly erhalten.",
|
||||||
// }
|
.video: "Du hast ein Video erhalten.",
|
||||||
|
.image: "Du hast ein Bild erhalten.",
|
||||||
|
.contactRequest: "Du hast eine Kontaktanfrage erhalten.",
|
||||||
|
.acceptRequest: "Deine Kontaktanfrage wurde angenommen.",
|
||||||
|
.storedMediaFile: "Dein Bild wurde gespeichert.",
|
||||||
|
.reaction: "Du hast eine Reaktion auf dein Bild erhalten.",
|
||||||
|
.testNotification: "Das ist eine Testbenachrichtigung.",
|
||||||
|
.reopenedMedia: "hat dein Bild erneut geöffnet.",
|
||||||
|
.reactionToVideo: "Du hast eine Reaktion auf dein Video erhalten.",
|
||||||
|
.reactionToText: "Du hast eine Reaktion auf deinen Text erhalten.",
|
||||||
|
.reactionToImage: "Du hast eine Reaktion auf dein Bild erhalten.",
|
||||||
|
.response: "Du hast eine Antwort erhalten.",
|
||||||
|
]
|
||||||
|
} else { // Default to English
|
||||||
|
pushNotificationText = [
|
||||||
|
.text: "You got a message.",
|
||||||
|
.twonly: "You got a twonly.",
|
||||||
|
.video: "You got a video.",
|
||||||
|
.image: "You got an image.",
|
||||||
|
.contactRequest: "You got a contact request.",
|
||||||
|
.acceptRequest: "Your contact request has been accepted.",
|
||||||
|
.storedMediaFile: "Your image has been saved.",
|
||||||
|
.reaction: "You got a reaction to your image.",
|
||||||
|
.testNotification: "This is a test notification.",
|
||||||
|
.reopenedMedia: "has reopened your image.",
|
||||||
|
.reactionToVideo: "You got a reaction to your video.",
|
||||||
|
.reactionToText: "You got a reaction to your text.",
|
||||||
|
.reactionToImage: "You got a reaction to your image.",
|
||||||
|
.response: "You got a response.",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
// struct PushUser: Codable {
|
// Return the corresponding message or an empty string if not found
|
||||||
// let displayName: String
|
return pushNotificationText[pushKind] ?? ""
|
||||||
// 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 {
|
|
||||||
// NSLog("No data found for key: receivingPushKeys")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// do {
|
|
||||||
// // Decode the JSON data into a dictionary
|
|
||||||
// let jsonData = data.data(using: .utf8)!
|
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return pushKeys
|
|
||||||
// } catch {
|
|
||||||
// NSLog("Error decoding JSON: \(error)")
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Helper function to read from Keychain
|
|
||||||
// func readFromKeychain(key: String) -> String? {
|
|
||||||
// let query: [String: Any] = [
|
|
||||||
// kSecClass as String: kSecClassGenericPassword,
|
|
||||||
// kSecAttrAccount as String: key,
|
|
||||||
// kSecReturnData as String: kCFBooleanTrue!,
|
|
||||||
// kSecMatchLimit as String: kSecMatchLimitOne,
|
|
||||||
// kSecAttrAccessGroup as String: "CN332ZUGRP.eu.twonly.shared" // Use your access group
|
|
||||||
// ]
|
|
||||||
|
|
||||||
// var dataTypeRef: AnyObject? = nil
|
|
||||||
// let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
|
|
||||||
|
|
||||||
// if status == errSecSuccess {
|
|
||||||
// if let data = dataTypeRef as? Data {
|
|
||||||
// return String(data: data, encoding: .utf8)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func getPushNotificationText(pushKind: PushKind) -> String {
|
|
||||||
// let systemLanguage = Locale.current.languageCode ?? "en" // Get the current system language
|
|
||||||
|
|
||||||
// var pushNotificationText: [PushKind: String] = [:]
|
|
||||||
|
|
||||||
// // Define the messages based on the system language
|
|
||||||
// if systemLanguage.contains("de") { // German
|
|
||||||
// pushNotificationText = [
|
|
||||||
// .text: "hat dir eine Nachricht gesendet.",
|
|
||||||
// .twonly: "hat dir ein twonly gesendet.",
|
|
||||||
// .video: "hat dir ein Video gesendet.",
|
|
||||||
// .image: "hat dir ein Bild gesendet.",
|
|
||||||
// .contactRequest: "möchte sich mit dir vernetzen.",
|
|
||||||
// .acceptRequest: "ist jetzt mit dir vernetzt.",
|
|
||||||
// .storedMediaFile: "hat dein Bild gespeichert.",
|
|
||||||
// .reaction: "hat auf dein Bild reagiert.",
|
|
||||||
// .testNotification: "Das ist eine Testbenachrichtigung.",
|
|
||||||
// .reopenedMedia: "hat dein Bild erneut geöffnet.",
|
|
||||||
// .reactionToVideo: "hat auf dein Video reagiert.",
|
|
||||||
// .reactionToText: "hat auf deinen Text reagiert.",
|
|
||||||
// .reactionToImage: "hat auf dein Bild reagiert.",
|
|
||||||
// .response: "hat dir geantwortet."
|
|
||||||
// ]
|
|
||||||
// } else { // Default to English
|
|
||||||
// pushNotificationText = [
|
|
||||||
// .text: "has sent you a message.",
|
|
||||||
// .twonly: "has sent you a twonly.",
|
|
||||||
// .video: "has sent you a video.",
|
|
||||||
// .image: "has sent you an image.",
|
|
||||||
// .contactRequest: "wants to connect with you.",
|
|
||||||
// .acceptRequest: "is now connected with you.",
|
|
||||||
// .storedMediaFile: "has stored your image.",
|
|
||||||
// .reaction: "has reacted to your image.",
|
|
||||||
// .testNotification: "This is a test notification.",
|
|
||||||
// .reopenedMedia: "has reopened your image.",
|
|
||||||
// .reactionToVideo: "has reacted to your video.",
|
|
||||||
// .reactionToText: "has reacted to your text.",
|
|
||||||
// .reactionToImage: "has reacted to your image.",
|
|
||||||
// .response: "has responded."
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Return the corresponding message or an empty string if not found
|
|
||||||
// return pushNotificationText[pushKind] ?? ""
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func getPushNotificationTextWithoutUserId(pushKind: PushKind) -> String {
|
|
||||||
// let systemLanguage = Locale.current.languageCode ?? "en" // Get the current system language
|
|
||||||
|
|
||||||
// var pushNotificationText: [PushKind: String] = [:]
|
|
||||||
|
|
||||||
// // Define the messages based on the system language
|
|
||||||
// if systemLanguage.contains("de") { // German
|
|
||||||
// pushNotificationText = [
|
|
||||||
// .text: "Du hast eine Nachricht erhalten.",
|
|
||||||
// .twonly: "Du hast ein twonly erhalten.",
|
|
||||||
// .video: "Du hast ein Video erhalten.",
|
|
||||||
// .image: "Du hast ein Bild erhalten.",
|
|
||||||
// .contactRequest: "Du hast eine Kontaktanfrage erhalten.",
|
|
||||||
// .acceptRequest: "Deine Kontaktanfrage wurde angenommen.",
|
|
||||||
// .storedMediaFile: "Dein Bild wurde gespeichert.",
|
|
||||||
// .reaction: "Du hast eine Reaktion auf dein Bild erhalten.",
|
|
||||||
// .testNotification: "Das ist eine Testbenachrichtigung.",
|
|
||||||
// .reopenedMedia: "hat dein Bild erneut geöffnet.",
|
|
||||||
// .reactionToVideo: "Du hast eine Reaktion auf dein Video erhalten.",
|
|
||||||
// .reactionToText: "Du hast eine Reaktion auf deinen Text erhalten.",
|
|
||||||
// .reactionToImage: "Du hast eine Reaktion auf dein Bild erhalten.",
|
|
||||||
// .response: "Du hast eine Antwort erhalten."
|
|
||||||
// ]
|
|
||||||
// } else { // Default to English
|
|
||||||
// pushNotificationText = [
|
|
||||||
// .text: "You got a message.",
|
|
||||||
// .twonly: "You got a twonly.",
|
|
||||||
// .video: "You got a video.",
|
|
||||||
// .image: "You got an image.",
|
|
||||||
// .contactRequest: "You got a contact request.",
|
|
||||||
// .acceptRequest: "Your contact request has been accepted.",
|
|
||||||
// .storedMediaFile: "Your image has been saved.",
|
|
||||||
// .reaction: "You got a reaction to your image.",
|
|
||||||
// .testNotification: "This is a test notification.",
|
|
||||||
// .reopenedMedia: "has reopened your image.",
|
|
||||||
// .reactionToVideo: "You got a reaction to your video.",
|
|
||||||
// .reactionToText: "You got a reaction to your text.",
|
|
||||||
// .reactionToImage: "You got a reaction to your image.",
|
|
||||||
// .response: "You got a response."
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Return the corresponding message or an empty string if not found
|
|
||||||
// return pushNotificationText[pushKind] ?? ""
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ class SecureStorageKeys {
|
||||||
static const String userData = "userData";
|
static const String userData = "userData";
|
||||||
static const String twonlySafeLastBackupHash = "twonly_safe_last_backup_hash";
|
static const String twonlySafeLastBackupHash = "twonly_safe_last_backup_hash";
|
||||||
|
|
||||||
static const String receivingPushKeys = "receiving_pus_keys";
|
static const String receivingPushKeys = "receiving_push_keys";
|
||||||
static const String sendingPushKeys = "sending_pus_keys";
|
static const String sendingPushKeys = "sending_push_keys";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,11 @@ Future sendTextMessage(
|
||||||
PushNotification? pushNotification,
|
PushNotification? pushNotification,
|
||||||
) async {
|
) async {
|
||||||
DateTime messageSendAt = DateTime.now();
|
DateTime messageSendAt = DateTime.now();
|
||||||
|
DateTime? openedAt;
|
||||||
|
|
||||||
|
if (pushNotification != null && pushNotification.hasReactionContent()) {
|
||||||
|
openedAt = DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
int? messageId = await twonlyDB.messagesDao.insertMessage(
|
int? messageId = await twonlyDB.messagesDao.insertMessage(
|
||||||
MessagesCompanion(
|
MessagesCompanion(
|
||||||
|
|
@ -173,6 +178,7 @@ Future sendTextMessage(
|
||||||
responseToOtherMessageId: Value(content.responseToMessageId),
|
responseToOtherMessageId: Value(content.responseToMessageId),
|
||||||
responseToMessageId: Value(content.responseToOtherMessageId),
|
responseToMessageId: Value(content.responseToOtherMessageId),
|
||||||
downloadState: Value(DownloadState.downloaded),
|
downloadState: Value(DownloadState.downloaded),
|
||||||
|
openedAt: Value(openedAt),
|
||||||
contentJson: Value(
|
contentJson: Value(
|
||||||
jsonEncode(content.toJson()),
|
jsonEncode(content.toJson()),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue