From 2751663d6ccd53ac39c14cb43410ac89f969f7e9 Mon Sep 17 00:00:00 2001 From: Vladimir Klevtsov Date: Fri, 2 May 2025 01:52:27 +0200 Subject: [PATCH 1/4] [trello.com/c/lwOnjxPQ] clear draft before send message to remove delay for update --- .../Chat/ViewModel/ChatPreservationProtocol.swift | 1 + Adamant/Modules/Chat/ViewModel/ChatViewModel.swift | 1 + Adamant/ServiceProtocols/ChatPreservation.swift | 13 +++++++++---- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift b/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift index 76de16f6b..baa8dff52 100644 --- a/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift +++ b/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift @@ -11,6 +11,7 @@ import CommonKit protocol ChatPreservationProtocol: AnyObject, Sendable { var updateNotifier: ObservableSender { get } var forceUpdateNotifier: ObservableSender { get } + func clearPreservedMessagesForSigleChat(address: String) func getPreservedMessageFor(address: String) -> String? func getReplyMessage(address: String) -> MessageModel? func preserveChatState(message: String?, replyMessage: MessageModel?, files: [FileResult]?, forAddress address: String, isForsedUpdate: Bool) diff --git a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift index 25e2e0723..fbb0506f9 100644 --- a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift +++ b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift @@ -320,6 +320,7 @@ final class ChatViewModel: NSObject { func sendMessage(text: String) { guard let partnerAddress = chatroom?.partner?.address else { return } + chatPreservation.clearPreservedMessagesForSigleChat(address: partnerAddress) guard chatroom?.partner?.isDummy != true else { dialog.send(.dummy(partnerAddress)) diff --git a/Adamant/ServiceProtocols/ChatPreservation.swift b/Adamant/ServiceProtocols/ChatPreservation.swift index b6c6139a2..a7edd84b7 100644 --- a/Adamant/ServiceProtocols/ChatPreservation.swift +++ b/Adamant/ServiceProtocols/ChatPreservation.swift @@ -23,20 +23,25 @@ final class ChatPreservation: ChatPreservationProtocol, @unchecked Sendable { NotificationCenter.default .notifications(named: .AdamantAccountService.userLoggedOut) .sink { [weak self] _ in - self?.clearPreservedMessages() + self?.clearAllPreservedMessages() } .store(in: ¬ificationsSet) } // MARK: Notification actions - private func clearPreservedMessages() { + private func clearAllPreservedMessages() { preservedMessages = [:] preservedReplayMessage = [:] preservedFiles = [:] - - updateNotifier.send() } + + func clearPreservedMessagesForSigleChat(address: String) { + preservedMessages.removeValue(forKey: address) + preservedReplayMessage.removeValue(forKey: address) + preservedFiles.removeValue(forKey: address) + } + func preserveChatState( message: String?, From 6b839dd9c074e5e952b235e0212563066d2e61e6 Mon Sep 17 00:00:00 2001 From: Vladimir Klevtsov Date: Mon, 5 May 2025 04:21:55 +0200 Subject: [PATCH 2/4] [trello.com/c/lwOnjxPQ] fix double remote noti after read --- Adamant.xcodeproj/project.pbxproj | 26 +++++++++-------- Adamant/Helpers/UserDefaultsManager.swift | 17 ----------- .../CoreData/Chatroom+CoreDataClass.swift | 20 ++++++++++--- .../Chat/View/ChatViewController.swift | 2 +- .../Chat/ViewModel/ChatViewModel.swift | 7 ++--- .../DataProviders/AdamantChatsProvider.swift | 1 + .../CommonKit/Core/UserDefaultsKeys.swift | 1 + .../CommonKit/Core/UserDefaultsManager.swift | 29 +++++++++++++++++++ .../CommonKit/Core/UserDefaultsWrapper.swift | 3 +- .../NotificationService.swift | 23 +++++++++------ 10 files changed, 81 insertions(+), 48 deletions(-) delete mode 100644 Adamant/Helpers/UserDefaultsManager.swift create mode 100644 CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index f27085bdd..6629322f2 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -18,7 +18,7 @@ 557AC306287B10D8004699D7 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 557AC305287B10D8004699D7 /* SnapKit */; }; 55D1D84F287B78F200F94A4E /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 55D1D84E287B78F200F94A4E /* SnapKit */; }; 55D1D851287B78FC00F94A4E /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 55D1D850287B78FC00F94A4E /* SnapKit */; }; - 6403F5DB2272389800D58779 /* BuildFile in Sources */ = {isa = PBXBuildFile; }; + 6403F5DB2272389800D58779 /* (null) in Sources */ = {isa = PBXBuildFile; }; 6FB686162D3AAE8800CAB6DD /* AdamantWalletsKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6FB686152D3AAE8800CAB6DD /* AdamantWalletsKit */; }; 9342F6C22A6A35E300A9B39F /* CommonKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9342F6C12A6A35E300A9B39F /* CommonKit */; }; 937751A52A68B3320054BD65 /* CommonKit in Frameworks */ = {isa = PBXBuildFile; productRef = 937751A42A68B3320054BD65 /* CommonKit */; }; @@ -31,7 +31,7 @@ A5241B70262DEDE1009FA43E /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = A5241B6F262DEDE1009FA43E /* Clibsodium */; }; A5241B77262DEDEF009FA43E /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = A5241B76262DEDEF009FA43E /* Clibsodium */; }; A5241B7E262DEDFE009FA43E /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = A5241B7D262DEDFE009FA43E /* Clibsodium */; }; - A530B0D82842110D003F0210 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; + A530B0D82842110D003F0210 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; A544F0D4262C9878001F1A6D /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = A544F0D3262C9878001F1A6D /* Eureka */; }; A57282CA262C94CD00C96FA8 /* DateToolsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A57282C9262C94CD00C96FA8 /* DateToolsSwift */; }; A57282D1262C94DA00C96FA8 /* DateToolsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A57282D0262C94DA00C96FA8 /* DateToolsSwift */; }; @@ -242,8 +242,6 @@ }; D3A860F82DA1C1980007B599 /* NotificationsShared */ = { isa = PBXFileSystemSynchronizedRootGroup; - exceptions = ( - ); path = NotificationsShared; sourceTree = ""; }; @@ -309,7 +307,7 @@ A5DBBABD262C7221004AC028 /* Clibsodium in Frameworks */, 6FB686162D3AAE8800CAB6DD /* AdamantWalletsKit in Frameworks */, 938F7D582955C1DA001915CA /* MessageKit in Frameworks */, - A530B0D82842110D003F0210 /* BuildFile in Frameworks */, + A530B0D82842110D003F0210 /* (null) in Frameworks */, 4177E5E12A52DA7100C089FE /* AdvancedContextMenuKit in Frameworks */, A5D87BA3262CA01D00DC28F0 /* ProcedureKit in Frameworks */, A5C99E0E262C9E3A00F7B1B7 /* Reachability in Frameworks */, @@ -661,12 +659,12 @@ A57282C8262C94CD00C96FA8 /* XCRemoteSwiftPackageReference "DateTools" */, A544F0D2262C9878001F1A6D /* XCRemoteSwiftPackageReference "Eureka" */, A5F0A049262C9CA90009672A /* XCRemoteSwiftPackageReference "Swinject" */, - A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability.swift" */, + A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability" */, A5D87BA1262CA01D00DC28F0 /* XCRemoteSwiftPackageReference "ProcedureKit" */, A5AC8DFD262E0B030053A7E2 /* XCRemoteSwiftPackageReference "SipHash" */, 3A8875ED27BBF38D00436195 /* XCRemoteSwiftPackageReference "Parchment" */, 557AC304287B10D8004699D7 /* XCRemoteSwiftPackageReference "SnapKit" */, - 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */, + 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket" */, 938F7D562955C1DA001915CA /* XCRemoteSwiftPackageReference "MessageKit" */, 4184F16F2A33044E00D7B8B9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 3AC76E3B2AB09118008042C4 /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */, @@ -756,10 +754,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Adamant/Pods-Adamant-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Adamant/Pods-Adamant-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Adamant/Pods-Adamant-frameworks.sh\"\n"; @@ -816,7 +818,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6403F5DB2272389800D58779 /* BuildFile in Sources */, + 6403F5DB2272389800D58779 /* (null) in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1359,7 +1361,7 @@ kind = branch; }; }; - 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */ = { + 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/socketio/socket.io-client-swift"; requirement = { @@ -1439,7 +1441,7 @@ minimumVersion = 1.2.2; }; }; - A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability.swift" */ = { + A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/ashleymills/Reachability.swift"; requirement = { @@ -1518,7 +1520,7 @@ }; 416F5EA3290162EB00EF0400 /* SocketIO */ = { isa = XCSwiftPackageProductDependency; - package = 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */; + package = 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket" */; productName = SocketIO; }; 4177E5E02A52DA7100C089FE /* AdvancedContextMenuKit */ = { @@ -1636,7 +1638,7 @@ }; A5C99E0D262C9E3A00F7B1B7 /* Reachability */ = { isa = XCSwiftPackageProductDependency; - package = A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability.swift" */; + package = A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability" */; productName = Reachability; }; A5D87BA2262CA01D00DC28F0 /* ProcedureKit */ = { diff --git a/Adamant/Helpers/UserDefaultsManager.swift b/Adamant/Helpers/UserDefaultsManager.swift deleted file mode 100644 index 812af786d..000000000 --- a/Adamant/Helpers/UserDefaultsManager.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// UserDefaultsManager.swift -// Adamant -// -// Created by Sergei Veretennikov on 22.03.2025. -// Copyright © 2025 Adamant. All rights reserved. -// - -import CommonKit - -struct UserDefaultsManager { - @UserDefaultsStorage(.needsToShowNoActiveNodesAlert) static var needsToShowNoActiveNodesAlert: Bool? - - static func setInitialUserDefaults() { - needsToShowNoActiveNodesAlert = true - } -} diff --git a/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift b/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift index 329ed6891..fad9fb035 100644 --- a/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift +++ b/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift @@ -9,6 +9,7 @@ import CoreData import Foundation +import CommonKit @objc(Chatroom) public class Chatroom: NSManagedObject, @unchecked Sendable { @@ -16,9 +17,12 @@ public class Chatroom: NSManagedObject, @unchecked Sendable { func markAsReaded() { hasUnreadMessages = false - + if let trs = transactions as? Set { - trs.filter { $0.isUnread }.forEach { $0.isUnread = false } + trs.filter { $0.isUnread }.forEach { + $0.isUnread = false + UserDefaultsManager.addLastReadId($0.transactionId) + } } } @@ -28,9 +32,17 @@ public class Chatroom: NSManagedObject, @unchecked Sendable { else { return } - message.isUnread = false + if message.isUnread { + UserDefaultsManager.addLastReadId(message.transactionId) + message.isUnread = false + } - message.richMessageTransactions?.forEach { $0.isUnread = false } + message.richMessageTransactions?.forEach { + if $0.isUnread { + UserDefaultsManager.addLastReadId($0.transactionId) + $0.isUnread = false + } + } if let context = message.managedObjectContext, context.hasChanges { try? context.save() diff --git a/Adamant/Modules/Chat/View/ChatViewController.swift b/Adamant/Modules/Chat/View/ChatViewController.swift index 7e2387809..674a242e1 100644 --- a/Adamant/Modules/Chat/View/ChatViewController.swift +++ b/Adamant/Modules/Chat/View/ChatViewController.swift @@ -997,7 +997,7 @@ extension ChatViewController { } let visibleIndexPaths = messagesCollectionView.indexPathsForVisibleItems - let indexPath = IndexPath(item: index, section: 0) + let indexPath = IndexPath(item: 0, section: index) //if we will not trigger didEndScrolling if visibleIndexPaths.contains(indexPath) { diff --git a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift index fbb0506f9..b107288ee 100644 --- a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift +++ b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift @@ -547,14 +547,13 @@ final class ChatViewModel: NSObject { recipient: partnerAddress ) } + if let chatroom { + await chatsProvider.markMessageAsRead(chatroom: chatroom, message: messageId) + } await waitForMessage(withId: messageId) scrollToId = messageId - dialog.send(.progress(false)) - if let chatroom { - await chatsProvider.markMessageAsRead(chatroom: chatroom, message: messageId) - } } catch { print(error) dialog.send(.progress(false)) diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index d789cc4b5..6293ac08a 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -323,6 +323,7 @@ extension AdamantChatsProvider { SecureStore.remove(StoreKey.chatProvider.receivedLastHeight) SecureStore.remove(StoreKey.chatProvider.readedLastHeight) SecureStore.remove(StoreKey.chatProvider.markedChatsAsUnread) + UserDefaultsManager.lastReadId = nil // Set State setState(.empty, previous: prevState, notify: notify) diff --git a/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift b/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift index cdba7f386..5413376f1 100644 --- a/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift +++ b/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift @@ -10,4 +10,5 @@ public enum UserDefaultsKey: String { case leftSplitViewController case rightSplitViewController + case lastReadId } diff --git a/CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift b/CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift new file mode 100644 index 000000000..b1fdb11da --- /dev/null +++ b/CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift @@ -0,0 +1,29 @@ +// +// UserDefaultsManager.swift +// CommonKit +// +// Created by Владимир Клевцов on 2. 5. 2025.. +// +public struct UserDefaultsManager { + @UserDefaultsStorage(.needsToShowNoActiveNodesAlert) + static var needsToShowNoActiveNodesAlert: Bool? + + @UserDefaultsStorage(.lastReadId) + public static var lastReadId: [String]? + + public static func setInitialUserDefaults() { + needsToShowNoActiveNodesAlert = true + } +} + +public extension UserDefaultsManager { + static func addLastReadId(_ id: String) { + var ids = lastReadId ?? [] + ids.removeAll { $0 == id } + ids.insert(id, at: 0) + if ids.count > 100 { + ids = Array(ids.prefix(100)) + } + lastReadId = ids + } +} diff --git a/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift b/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift index ab6383f6e..a54b0b191 100644 --- a/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift +++ b/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift @@ -9,7 +9,8 @@ import Foundation @propertyWrapper public struct UserDefaultsStorage { - private let defaults = UserDefaults.standard + //user group.adamant.adamant-messenger to share UserDefaults Data to NotificationService and another app targets + private let defaults = UserDefaults(suiteName: "group.adamant.adamant-messenger") ?? UserDefaults.standard private let key: String public var wrappedValue: T? { diff --git a/NotificationServiceExtension/NotificationService.swift b/NotificationServiceExtension/NotificationService.swift index 5dd260063..4f530164c 100644 --- a/NotificationServiceExtension/NotificationService.swift +++ b/NotificationServiceExtension/NotificationService.swift @@ -43,8 +43,11 @@ class NotificationService: UNNotificationServiceExtension { // MARK: - Hanlder var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? + var shouldIgnoreNotification = false + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + shouldIgnoreNotification = false AdamantUtilities.consoleLog( "Push notification received", request.content.userInfo.debugDescription, @@ -79,6 +82,13 @@ class NotificationService: UNNotificationServiceExtension { contentHandler(bestAttemptContent) return } + let lastReadIds = UserDefaultsManager.lastReadId + + if let lastReadIds, + lastReadIds.contains(String(transaction.id)) { + shouldIgnoreNotification = true + return + } // MARK: 3. Working on transaction let partnerAddress: String @@ -107,9 +117,7 @@ class NotificationService: UNNotificationServiceExtension { partnerName = partnerAddress.checkAndReplaceSystemWallets() bestAttemptContent.userInfo[AdamantNotificationUserInfoKeys.partnerNoDislpayNameKey] = AdamantNotificationUserInfoKeys.partnerNoDisplayNameValue } - - var shouldIgnoreNotification = false - + var isReaction = false // MARK: 5. Content @@ -313,11 +321,6 @@ class NotificationService: UNNotificationServiceExtension { break } - guard !shouldIgnoreNotification else { - contentHandler(UNNotificationContent()) - return - } - bestAttemptContent.sound = getSound( SecureStore: SecureStore, isReaction: isReaction @@ -338,7 +341,9 @@ class NotificationService: UNNotificationServiceExtension { 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 { + if !shouldIgnoreNotification, + let contentHandler = contentHandler, + let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } From a10da727baf3e1e59fd2820882a06fce0263f348 Mon Sep 17 00:00:00 2001 From: Vladimir Klevtsov Date: Mon, 5 May 2025 04:32:48 +0200 Subject: [PATCH 3/4] Revert "[trello.com/c/lwOnjxPQ] fix double remote noti after read" This reverts commit 6b839dd9c074e5e952b235e0212563066d2e61e6. --- Adamant.xcodeproj/project.pbxproj | 26 ++++++++--------- Adamant/Helpers/UserDefaultsManager.swift | 17 +++++++++++ .../CoreData/Chatroom+CoreDataClass.swift | 20 +++---------- .../Chat/View/ChatViewController.swift | 2 +- .../Chat/ViewModel/ChatViewModel.swift | 7 +++-- .../DataProviders/AdamantChatsProvider.swift | 1 - .../CommonKit/Core/UserDefaultsKeys.swift | 1 - .../CommonKit/Core/UserDefaultsManager.swift | 29 ------------------- .../CommonKit/Core/UserDefaultsWrapper.swift | 3 +- .../NotificationService.swift | 23 ++++++--------- 10 files changed, 48 insertions(+), 81 deletions(-) create mode 100644 Adamant/Helpers/UserDefaultsManager.swift delete mode 100644 CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 6629322f2..f27085bdd 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -18,7 +18,7 @@ 557AC306287B10D8004699D7 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 557AC305287B10D8004699D7 /* SnapKit */; }; 55D1D84F287B78F200F94A4E /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 55D1D84E287B78F200F94A4E /* SnapKit */; }; 55D1D851287B78FC00F94A4E /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 55D1D850287B78FC00F94A4E /* SnapKit */; }; - 6403F5DB2272389800D58779 /* (null) in Sources */ = {isa = PBXBuildFile; }; + 6403F5DB2272389800D58779 /* BuildFile in Sources */ = {isa = PBXBuildFile; }; 6FB686162D3AAE8800CAB6DD /* AdamantWalletsKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6FB686152D3AAE8800CAB6DD /* AdamantWalletsKit */; }; 9342F6C22A6A35E300A9B39F /* CommonKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9342F6C12A6A35E300A9B39F /* CommonKit */; }; 937751A52A68B3320054BD65 /* CommonKit in Frameworks */ = {isa = PBXBuildFile; productRef = 937751A42A68B3320054BD65 /* CommonKit */; }; @@ -31,7 +31,7 @@ A5241B70262DEDE1009FA43E /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = A5241B6F262DEDE1009FA43E /* Clibsodium */; }; A5241B77262DEDEF009FA43E /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = A5241B76262DEDEF009FA43E /* Clibsodium */; }; A5241B7E262DEDFE009FA43E /* Clibsodium in Frameworks */ = {isa = PBXBuildFile; productRef = A5241B7D262DEDFE009FA43E /* Clibsodium */; }; - A530B0D82842110D003F0210 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; + A530B0D82842110D003F0210 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; A544F0D4262C9878001F1A6D /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = A544F0D3262C9878001F1A6D /* Eureka */; }; A57282CA262C94CD00C96FA8 /* DateToolsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A57282C9262C94CD00C96FA8 /* DateToolsSwift */; }; A57282D1262C94DA00C96FA8 /* DateToolsSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A57282D0262C94DA00C96FA8 /* DateToolsSwift */; }; @@ -242,6 +242,8 @@ }; D3A860F82DA1C1980007B599 /* NotificationsShared */ = { isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); path = NotificationsShared; sourceTree = ""; }; @@ -307,7 +309,7 @@ A5DBBABD262C7221004AC028 /* Clibsodium in Frameworks */, 6FB686162D3AAE8800CAB6DD /* AdamantWalletsKit in Frameworks */, 938F7D582955C1DA001915CA /* MessageKit in Frameworks */, - A530B0D82842110D003F0210 /* (null) in Frameworks */, + A530B0D82842110D003F0210 /* BuildFile in Frameworks */, 4177E5E12A52DA7100C089FE /* AdvancedContextMenuKit in Frameworks */, A5D87BA3262CA01D00DC28F0 /* ProcedureKit in Frameworks */, A5C99E0E262C9E3A00F7B1B7 /* Reachability in Frameworks */, @@ -659,12 +661,12 @@ A57282C8262C94CD00C96FA8 /* XCRemoteSwiftPackageReference "DateTools" */, A544F0D2262C9878001F1A6D /* XCRemoteSwiftPackageReference "Eureka" */, A5F0A049262C9CA90009672A /* XCRemoteSwiftPackageReference "Swinject" */, - A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability" */, + A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability.swift" */, A5D87BA1262CA01D00DC28F0 /* XCRemoteSwiftPackageReference "ProcedureKit" */, A5AC8DFD262E0B030053A7E2 /* XCRemoteSwiftPackageReference "SipHash" */, 3A8875ED27BBF38D00436195 /* XCRemoteSwiftPackageReference "Parchment" */, 557AC304287B10D8004699D7 /* XCRemoteSwiftPackageReference "SnapKit" */, - 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket" */, + 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */, 938F7D562955C1DA001915CA /* XCRemoteSwiftPackageReference "MessageKit" */, 4184F16F2A33044E00D7B8B9 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */, 3AC76E3B2AB09118008042C4 /* XCRemoteSwiftPackageReference "Elegant-Emoji-Picker" */, @@ -754,14 +756,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Adamant/Pods-Adamant-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Adamant/Pods-Adamant-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Adamant/Pods-Adamant-frameworks.sh\"\n"; @@ -818,7 +816,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6403F5DB2272389800D58779 /* (null) in Sources */, + 6403F5DB2272389800D58779 /* BuildFile in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1361,7 +1359,7 @@ kind = branch; }; }; - 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket" */ = { + 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/socketio/socket.io-client-swift"; requirement = { @@ -1441,7 +1439,7 @@ minimumVersion = 1.2.2; }; }; - A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability" */ = { + A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability.swift" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/ashleymills/Reachability.swift"; requirement = { @@ -1520,7 +1518,7 @@ }; 416F5EA3290162EB00EF0400 /* SocketIO */ = { isa = XCSwiftPackageProductDependency; - package = 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket" */; + package = 416F5EA2290162EB00EF0400 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */; productName = SocketIO; }; 4177E5E02A52DA7100C089FE /* AdvancedContextMenuKit */ = { @@ -1638,7 +1636,7 @@ }; A5C99E0D262C9E3A00F7B1B7 /* Reachability */ = { isa = XCSwiftPackageProductDependency; - package = A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability" */; + package = A5C99E0C262C9E3A00F7B1B7 /* XCRemoteSwiftPackageReference "Reachability.swift" */; productName = Reachability; }; A5D87BA2262CA01D00DC28F0 /* ProcedureKit */ = { diff --git a/Adamant/Helpers/UserDefaultsManager.swift b/Adamant/Helpers/UserDefaultsManager.swift new file mode 100644 index 000000000..812af786d --- /dev/null +++ b/Adamant/Helpers/UserDefaultsManager.swift @@ -0,0 +1,17 @@ +// +// UserDefaultsManager.swift +// Adamant +// +// Created by Sergei Veretennikov on 22.03.2025. +// Copyright © 2025 Adamant. All rights reserved. +// + +import CommonKit + +struct UserDefaultsManager { + @UserDefaultsStorage(.needsToShowNoActiveNodesAlert) static var needsToShowNoActiveNodesAlert: Bool? + + static func setInitialUserDefaults() { + needsToShowNoActiveNodesAlert = true + } +} diff --git a/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift b/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift index fad9fb035..329ed6891 100644 --- a/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift +++ b/Adamant/Models/CoreData/Chatroom+CoreDataClass.swift @@ -9,7 +9,6 @@ import CoreData import Foundation -import CommonKit @objc(Chatroom) public class Chatroom: NSManagedObject, @unchecked Sendable { @@ -17,12 +16,9 @@ public class Chatroom: NSManagedObject, @unchecked Sendable { func markAsReaded() { hasUnreadMessages = false - + if let trs = transactions as? Set { - trs.filter { $0.isUnread }.forEach { - $0.isUnread = false - UserDefaultsManager.addLastReadId($0.transactionId) - } + trs.filter { $0.isUnread }.forEach { $0.isUnread = false } } } @@ -32,17 +28,9 @@ public class Chatroom: NSManagedObject, @unchecked Sendable { else { return } - if message.isUnread { - UserDefaultsManager.addLastReadId(message.transactionId) - message.isUnread = false - } + message.isUnread = false - message.richMessageTransactions?.forEach { - if $0.isUnread { - UserDefaultsManager.addLastReadId($0.transactionId) - $0.isUnread = false - } - } + message.richMessageTransactions?.forEach { $0.isUnread = false } if let context = message.managedObjectContext, context.hasChanges { try? context.save() diff --git a/Adamant/Modules/Chat/View/ChatViewController.swift b/Adamant/Modules/Chat/View/ChatViewController.swift index 674a242e1..7e2387809 100644 --- a/Adamant/Modules/Chat/View/ChatViewController.swift +++ b/Adamant/Modules/Chat/View/ChatViewController.swift @@ -997,7 +997,7 @@ extension ChatViewController { } let visibleIndexPaths = messagesCollectionView.indexPathsForVisibleItems - let indexPath = IndexPath(item: 0, section: index) + let indexPath = IndexPath(item: index, section: 0) //if we will not trigger didEndScrolling if visibleIndexPaths.contains(indexPath) { diff --git a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift index b107288ee..fbb0506f9 100644 --- a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift +++ b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift @@ -547,13 +547,14 @@ final class ChatViewModel: NSObject { recipient: partnerAddress ) } - if let chatroom { - await chatsProvider.markMessageAsRead(chatroom: chatroom, message: messageId) - } await waitForMessage(withId: messageId) scrollToId = messageId + dialog.send(.progress(false)) + if let chatroom { + await chatsProvider.markMessageAsRead(chatroom: chatroom, message: messageId) + } } catch { print(error) dialog.send(.progress(false)) diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index 6293ac08a..d789cc4b5 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -323,7 +323,6 @@ extension AdamantChatsProvider { SecureStore.remove(StoreKey.chatProvider.receivedLastHeight) SecureStore.remove(StoreKey.chatProvider.readedLastHeight) SecureStore.remove(StoreKey.chatProvider.markedChatsAsUnread) - UserDefaultsManager.lastReadId = nil // Set State setState(.empty, previous: prevState, notify: notify) diff --git a/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift b/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift index 5413376f1..cdba7f386 100644 --- a/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift +++ b/CommonKit/Sources/CommonKit/Core/UserDefaultsKeys.swift @@ -10,5 +10,4 @@ public enum UserDefaultsKey: String { case leftSplitViewController case rightSplitViewController - case lastReadId } diff --git a/CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift b/CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift deleted file mode 100644 index b1fdb11da..000000000 --- a/CommonKit/Sources/CommonKit/Core/UserDefaultsManager.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// UserDefaultsManager.swift -// CommonKit -// -// Created by Владимир Клевцов on 2. 5. 2025.. -// -public struct UserDefaultsManager { - @UserDefaultsStorage(.needsToShowNoActiveNodesAlert) - static var needsToShowNoActiveNodesAlert: Bool? - - @UserDefaultsStorage(.lastReadId) - public static var lastReadId: [String]? - - public static func setInitialUserDefaults() { - needsToShowNoActiveNodesAlert = true - } -} - -public extension UserDefaultsManager { - static func addLastReadId(_ id: String) { - var ids = lastReadId ?? [] - ids.removeAll { $0 == id } - ids.insert(id, at: 0) - if ids.count > 100 { - ids = Array(ids.prefix(100)) - } - lastReadId = ids - } -} diff --git a/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift b/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift index a54b0b191..ab6383f6e 100644 --- a/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift +++ b/CommonKit/Sources/CommonKit/Core/UserDefaultsWrapper.swift @@ -9,8 +9,7 @@ import Foundation @propertyWrapper public struct UserDefaultsStorage { - //user group.adamant.adamant-messenger to share UserDefaults Data to NotificationService and another app targets - private let defaults = UserDefaults(suiteName: "group.adamant.adamant-messenger") ?? UserDefaults.standard + private let defaults = UserDefaults.standard private let key: String public var wrappedValue: T? { diff --git a/NotificationServiceExtension/NotificationService.swift b/NotificationServiceExtension/NotificationService.swift index 4f530164c..5dd260063 100644 --- a/NotificationServiceExtension/NotificationService.swift +++ b/NotificationServiceExtension/NotificationService.swift @@ -43,11 +43,8 @@ class NotificationService: UNNotificationServiceExtension { // MARK: - Hanlder var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? - var shouldIgnoreNotification = false - override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { - shouldIgnoreNotification = false AdamantUtilities.consoleLog( "Push notification received", request.content.userInfo.debugDescription, @@ -82,13 +79,6 @@ class NotificationService: UNNotificationServiceExtension { contentHandler(bestAttemptContent) return } - let lastReadIds = UserDefaultsManager.lastReadId - - if let lastReadIds, - lastReadIds.contains(String(transaction.id)) { - shouldIgnoreNotification = true - return - } // MARK: 3. Working on transaction let partnerAddress: String @@ -117,7 +107,9 @@ class NotificationService: UNNotificationServiceExtension { partnerName = partnerAddress.checkAndReplaceSystemWallets() bestAttemptContent.userInfo[AdamantNotificationUserInfoKeys.partnerNoDislpayNameKey] = AdamantNotificationUserInfoKeys.partnerNoDisplayNameValue } - + + var shouldIgnoreNotification = false + var isReaction = false // MARK: 5. Content @@ -321,6 +313,11 @@ class NotificationService: UNNotificationServiceExtension { break } + guard !shouldIgnoreNotification else { + contentHandler(UNNotificationContent()) + return + } + bestAttemptContent.sound = getSound( SecureStore: SecureStore, isReaction: isReaction @@ -341,9 +338,7 @@ class NotificationService: UNNotificationServiceExtension { 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 !shouldIgnoreNotification, - let contentHandler = contentHandler, - let bestAttemptContent = bestAttemptContent { + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } From 5856b71810a273a3e05bd4c16d7ba68ba8c4579d Mon Sep 17 00:00:00 2001 From: Vladimir Klevtsov Date: Wed, 7 May 2025 20:53:27 +0200 Subject: [PATCH 4/4] [trello.com/c/lwOnjxPQ] fix typo --- Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift | 2 +- Adamant/Modules/Chat/ViewModel/ChatViewModel.swift | 2 +- Adamant/ServiceProtocols/ChatPreservation.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift b/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift index baa8dff52..5634b56bc 100644 --- a/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift +++ b/Adamant/Modules/Chat/ViewModel/ChatPreservationProtocol.swift @@ -11,7 +11,7 @@ import CommonKit protocol ChatPreservationProtocol: AnyObject, Sendable { var updateNotifier: ObservableSender { get } var forceUpdateNotifier: ObservableSender { get } - func clearPreservedMessagesForSigleChat(address: String) + func clearPreservedMessagesForSingleChat(address: String) func getPreservedMessageFor(address: String) -> String? func getReplyMessage(address: String) -> MessageModel? func preserveChatState(message: String?, replyMessage: MessageModel?, files: [FileResult]?, forAddress address: String, isForsedUpdate: Bool) diff --git a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift index fbb0506f9..4d8e5dea2 100644 --- a/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift +++ b/Adamant/Modules/Chat/ViewModel/ChatViewModel.swift @@ -320,7 +320,7 @@ final class ChatViewModel: NSObject { func sendMessage(text: String) { guard let partnerAddress = chatroom?.partner?.address else { return } - chatPreservation.clearPreservedMessagesForSigleChat(address: partnerAddress) + chatPreservation.clearPreservedMessagesForSingleChat(address: partnerAddress) guard chatroom?.partner?.isDummy != true else { dialog.send(.dummy(partnerAddress)) diff --git a/Adamant/ServiceProtocols/ChatPreservation.swift b/Adamant/ServiceProtocols/ChatPreservation.swift index a7edd84b7..e8217a391 100644 --- a/Adamant/ServiceProtocols/ChatPreservation.swift +++ b/Adamant/ServiceProtocols/ChatPreservation.swift @@ -36,7 +36,7 @@ final class ChatPreservation: ChatPreservationProtocol, @unchecked Sendable { preservedFiles = [:] } - func clearPreservedMessagesForSigleChat(address: String) { + func clearPreservedMessagesForSingleChat(address: String) { preservedMessages.removeValue(forKey: address) preservedReplayMessage.removeValue(forKey: address) preservedFiles.removeValue(forKey: address)