From b0e9a05ea283c0d1bd908a9bb16c565b0abfd03e Mon Sep 17 00:00:00 2001 From: StanislavDevIOS Date: Fri, 22 Apr 2022 18:18:02 +0300 Subject: [PATCH 1/6] setup sockets --- Adamant.xcodeproj/project.pbxproj | 52 +++++++++++------ Adamant/AppDelegate.swift | 3 +- Adamant/ServiceProtocols/SocketService.swift | 24 ++++++++ .../DataProviders/AdamantChatsProvider.swift | 56 ++++++++++++++++--- .../SocketService/AdamantSocketService.swift | 49 ++++++++++++++++ Adamant/SwinjectDependencies.swift | 20 +++++++ AdamantShared/Models/Transaction.swift | 7 ++- Podfile | 1 + Podfile.lock | 10 +++- 9 files changed, 193 insertions(+), 29 deletions(-) create mode 100644 Adamant/ServiceProtocols/SocketService.swift create mode 100644 Adamant/Services/SocketService/AdamantSocketService.swift diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 594a1723a..9fd24539d 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -12,6 +12,8 @@ 3A64FAA827BA67BF007D5588 /* AdamantSecret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A64FAA527BA67BF007D5588 /* AdamantSecret.swift */; }; 3A64FAA927BA67BF007D5588 /* AdamantSecret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A64FAA527BA67BF007D5588 /* AdamantSecret.swift */; }; 3A8875EF27BBF38D00436195 /* Parchment in Frameworks */ = {isa = PBXBuildFile; productRef = 3A8875EE27BBF38D00436195 /* Parchment */; }; + 3AA2D5F7280EADE3000ED971 /* SocketService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA2D5F6280EADE3000ED971 /* SocketService.swift */; }; + 3AA2D5FA280EAF5D000ED971 /* AdamantSocketService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA2D5F9280EAF5D000ED971 /* AdamantSocketService.swift */; }; 3C06931576393125C61FB8F6 /* Pods_Adamant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33975C0D891698AA7E74EBCC /* Pods_Adamant.framework */; }; 6403F5DB2272389800D58779 /* (null) in Sources */ = {isa = PBXBuildFile; }; 6403F5DE22723C6800D58779 /* DashMainnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6403F5DD22723C6800D58779 /* DashMainnet.swift */; }; @@ -607,6 +609,8 @@ 33975C0D891698AA7E74EBCC /* Pods_Adamant.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Adamant.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 36AB8CE9537B3B873972548B /* Pods_AdmCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AdmCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3A64FAA527BA67BF007D5588 /* AdamantSecret.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdamantSecret.swift; sourceTree = ""; }; + 3AA2D5F6280EADE3000ED971 /* SocketService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocketService.swift; sourceTree = ""; }; + 3AA2D5F9280EAF5D000ED971 /* AdamantSocketService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantSocketService.swift; sourceTree = ""; }; 4A4D67BD3DC89C07D1351248 /* Pods-AdmCore.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AdmCore.release.xcconfig"; path = "Target Support Files/Pods-AdmCore/Pods-AdmCore.release.xcconfig"; sourceTree = ""; }; 6403F5DD22723C6800D58779 /* DashMainnet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashMainnet.swift; sourceTree = ""; }; 6403F5DF22723F6400D58779 /* DashWalletRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashWalletRouter.swift; sourceTree = ""; }; @@ -1101,6 +1105,14 @@ path = Pods; sourceTree = ""; }; + 3AA2D5F8280EAF49000ED971 /* SocketService */ = { + isa = PBXGroup; + children = ( + 3AA2D5F9280EAF5D000ED971 /* AdamantSocketService.swift */, + ); + path = SocketService; + sourceTree = ""; + }; 6403F5DC22723C2800D58779 /* Dash */ = { isa = PBXGroup; children = ( @@ -1262,6 +1274,7 @@ E913C9071FFFA943001A83F7 /* AdamantCore.swift */, 6455E9F021075D3600B2E94C /* AddressBookService.swift */, E91947AB20001A9A001362F8 /* ApiService.swift */, + 3AA2D5F6280EADE3000ED971 /* SocketService.swift */, 648BCA6C213D384F00875EB5 /* AvatarService.swift */, E9A174B22057EC47003667CD /* BackgroundFetchService.swift */, E9E7CDBD2003AEFB00DFC4DB /* CellFactory.swift */, @@ -1281,6 +1294,7 @@ E913C9061FFFA92E001A83F7 /* Services */ = { isa = PBXGroup; children = ( + 3AA2D5F8280EAF49000ED971 /* SocketService */, E9CAE8D02018AA5000345E76 /* ApiService */, E9B3D39F201FA2090019EB36 /* DataProviders */, E9E7CD922002740500DFC4DB /* AdamantAccountService.swift */, @@ -2311,6 +2325,8 @@ "${BUILT_PRODUCTS_DIR}/MessageKit/MessageKit.framework", "${BUILT_PRODUCTS_DIR}/MyLittlePinpad/MyLittlePinpad.framework", "${BUILT_PRODUCTS_DIR}/PMAlertController/PMAlertController.framework", + "${BUILT_PRODUCTS_DIR}/Socket.IO-Client-Swift/SocketIO.framework", + "${BUILT_PRODUCTS_DIR}/Starscream/Starscream.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -2320,6 +2336,8 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MessageKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MyLittlePinpad.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PMAlertController.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketIO.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Starscream.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -2516,6 +2534,7 @@ 644793C32166314A00FC4CF5 /* OnboardPage.swift in Sources */, 64E1C831222E9617006C4DA7 /* DogeWalletService.swift in Sources */, E91947B22000246A001362F8 /* AdamantError.swift in Sources */, + 3AA2D5F7280EADE3000ED971 /* SocketService.swift in Sources */, E95F85802008C8D70070534A /* ChatsRoutes.swift in Sources */, 6416B1A721B024B6006089AC /* LskWalletService+Send.swift in Sources */, E9942B87203D9E5100C163AF /* EurekaQRRow.swift in Sources */, @@ -2617,6 +2636,7 @@ E9502740202E257E002C1098 /* RepeaterService.swift in Sources */, E93D7AC02052CF63005D19DC /* AdamantNotificationService.swift in Sources */, 645938942378395E00A2BE7C /* EulaViewController.swift in Sources */, + 3AA2D5FA280EAF5D000ED971 /* AdamantSocketService.swift in Sources */, 649D6BEC21BD5A53009E727B /* UISuffixTextField.swift in Sources */, E93B0D762028B28E00126346 /* AdamantChatsProvider.swift in Sources */, E993302021354B1800CD5200 /* AdmWalletRoutes.swift in Sources */, @@ -2877,7 +2897,7 @@ CODE_SIGN_ENTITLEMENTS = MessageNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2886,7 +2906,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.MessageNotificationContentExtension"; @@ -2906,7 +2926,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2915,7 +2935,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.MessageNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3053,7 +3073,7 @@ CODE_SIGN_ENTITLEMENTS = Adamant/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = ADM.Dev; EXCLUDED_SOURCE_FILE_NAMES = ""; @@ -3063,7 +3083,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "e4233bbf-3705-44fe-95b0-e77475672c60"; @@ -3082,7 +3102,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = Adamant; EXCLUDED_SOURCE_FILE_NAMES = Debug.xcassets; @@ -3092,7 +3112,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "bedd1b75-2f23-4a85-a0b2-14c424fcff42"; @@ -3110,7 +3130,7 @@ CODE_SIGN_ENTITLEMENTS = TransferNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3119,7 +3139,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.TransferNotificationContentExtension"; @@ -3139,7 +3159,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3148,7 +3168,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.TransferNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3168,7 +3188,7 @@ CODE_SIGN_ENTITLEMENTS = NotificationServiceExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3177,7 +3197,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.NotificationServiceExtension"; @@ -3197,7 +3217,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 173; + CURRENT_PROJECT_VERSION = 174; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3206,7 +3226,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.0; + MARKETING_VERSION = 2.3.1; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.NotificationServiceExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index d62661616..4bb28b722 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -182,7 +182,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Register repeater services if let chatsProvider = container.resolve(ChatsProvider.self) { - repeater.registerForegroundCall(label: "chatsProvider", interval: 3, queue: .global(qos: .utility), callback: chatsProvider.update) + repeater.registerForegroundCall(label: "chatsProvider", interval: 10, queue: .global(qos: .utility), callback: chatsProvider.update) + } else { dialogService.showError(withMessage: "Failed to register ChatsProvider autoupdate. Please, report a bug", error: nil) } diff --git a/Adamant/ServiceProtocols/SocketService.swift b/Adamant/ServiceProtocols/SocketService.swift new file mode 100644 index 000000000..21686a488 --- /dev/null +++ b/Adamant/ServiceProtocols/SocketService.swift @@ -0,0 +1,24 @@ +// +// SocketService.swift +// Adamant +// +// Created by Stanislav Jelezoglo on 19.04.2022. +// Copyright © 2022 Adamant. All rights reserved. +// + +import Foundation + +// - MARK: SocketService +protocol SocketService: AnyObject { + + /// Default is async queue with .utilities priority. + var defaultResponseDispatchQueue: DispatchQueue { get } + + // MARK: - Connection + + func connect(address: String) + + // MARK: - Receive New Transaction + + func receiveNewTransaction(completion: ((ApiServiceResult) -> Void)?) +} diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index 13ec569e5..bc1a6f0d1 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -14,6 +14,7 @@ class AdamantChatsProvider: ChatsProvider { // MARK: Dependencies var accountService: AccountService! var apiService: ApiService! + var socketService: SocketService! var stack: CoreDataStack! var adamantCore: AdamantCore! var accountsProvider: AccountsProvider! @@ -76,8 +77,8 @@ class AdamantChatsProvider: ChatsProvider { self?.dropStateData() store.set(loggedAddress, for: StoreKey.chatProvider.address) } - self?.update() + self?.connectToSocket() } NotificationCenter.default.addObserver(forName: Notification.Name.AdamantAccountService.userLoggedOut, object: nil, queue: nil) { [weak self] _ in @@ -183,6 +184,34 @@ extension AdamantChatsProvider { self.update(completion: nil) } + func connectToSocket() { + // MARK: 2. Prepare + guard let address = accountService.account?.address, + let privateKey = accountService.keypair?.privateKey else { + return + } + let cms = DispatchSemaphore(value: 1) + // MARK: 3. Get transactions + let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) + privateContext.parent = self.stack.container.viewContext + self.socketService.connect(address: address) + self.socketService.receiveNewTransaction { result in + switch result { + case .success(let trans): + self.processingQueue.async { + + self.process(messageTransactions: [trans], + senderId: address, + privateKey: privateKey, + context: privateContext, + contextMutatingSemaphore: cms) + } + case .failure(_): + break + } + } + } + func update(completion: ((ChatsProviderResult?) -> Void)?) { if state == .updating { completion?(nil) @@ -931,8 +960,14 @@ extension AdamantChatsProvider { height = chatTransaction.height } + let trans = privateChatroom.transactions?.first(where: { message in + return (message as? ChatTransaction)?.txId == chatTransaction.txId + }) as? ChatTransaction + if !trs.isOut { - newMessageTransactions.append(chatTransaction) + if trans == nil { + newMessageTransactions.append(chatTransaction) + } // Preset messages if account.isSystem, let address = account.address, @@ -957,22 +992,29 @@ extension AdamantChatsProvider { } } - messages.insert(chatTransaction) + if trans == nil { + messages.insert(chatTransaction) + } else { + trans?.height = chatTransaction.height + trans?.blockId = chatTransaction.blockId + trans?.confirmations = chatTransaction.confirmations + } } } - privateChatroom.addToTransactions(messages as NSSet) + if !messages.isEmpty { + privateChatroom.addToTransactions(messages as NSSet) + } + if let address = privateChatroom.partner?.address { chatroom.isHidden = self.blackList.contains(address) } } - // MARK: 4. Unread messagess if let readedLastHeight = readedLastHeight { let unreadTransactions = newMessageTransactions.filter { $0.height > readedLastHeight } let chatrooms = Dictionary(grouping: unreadTransactions, by: ({ (t: ChatTransaction) -> Chatroom in t.chatroom! })) - for (chatroom, trs) in chatrooms { if let address = chatroom.partner?.address { chatroom.isHidden = self.blackList.contains(address) @@ -982,7 +1024,6 @@ extension AdamantChatsProvider { } } - // MARK: 5. Dump new transactions if privateContext.hasChanges { do { @@ -998,7 +1039,6 @@ extension AdamantChatsProvider { } } - // MARK: 6. Save to main! if context.hasChanges { do { diff --git a/Adamant/Services/SocketService/AdamantSocketService.swift b/Adamant/Services/SocketService/AdamantSocketService.swift new file mode 100644 index 000000000..cdaa2c40c --- /dev/null +++ b/Adamant/Services/SocketService/AdamantSocketService.swift @@ -0,0 +1,49 @@ +// +// AdamantSocketService.swift +// Adamant +// +// Created by Stanislav Jelezoglo on 19.04.2022. +// Copyright © 2022 Adamant. All rights reserved. +// + +import Foundation +import SocketIO + +class AdamantSocketService: SocketService { + + // MARK: - Dependencies + + var adamantCore: AdamantCore! + var nodesSource: NodesSource! { + didSet { + //nodesSource.migrate() + // refreshNode() + } + } + + private let manager = SocketManager(socketURL: URL(string: "https://endless.adamant.im")!, config: [.log(true), .compress]) + private var socket:SocketIOClient? + + let defaultResponseDispatchQueue = DispatchQueue(label: "com.adamant.response-queue", qos: .utility, attributes: [.concurrent]) + + func connect(address: String) { + socket = manager.defaultSocket + socket?.on(clientEvent: .connect, callback: {[weak self] _, _ in + self?.socket?.emit("address", with: [address]) + }) + socket?.connect() + } + + func receiveNewTransaction(completion: ((ApiServiceResult) -> Void)?) { + socket?.on("newTrans", callback: { [weak self] data, ack in + guard let data = data.first else { return } + guard let dict = data as? [String: Any] else { return } + if let trans = try? JSONDecoder().decode(Transaction.self, from: JSONSerialization.data(withJSONObject: dict)) { + self?.defaultResponseDispatchQueue.async { + completion?(.success(trans)) + } + } + }) + } + +} diff --git a/Adamant/SwinjectDependencies.swift b/Adamant/SwinjectDependencies.swift index b75197b4c..d2c96968d 100644 --- a/Adamant/SwinjectDependencies.swift +++ b/Adamant/SwinjectDependencies.swift @@ -74,6 +74,16 @@ extension Container { service.nodesSource = r.resolve(NodesSource.self) }.inObjectScope(.container) + // MARK: SocketService + self.register(SocketService.self) { r in + let service = AdamantSocketService() + service.adamantCore = r.resolve(AdamantCore.self) + return service + }.initCompleted { (r, c) in // Weak reference + let service = c as! AdamantSocketService + service.nodesSource = r.resolve(NodesSource.self) + }.inObjectScope(.container) + // MARK: AccountService self.register(AccountService.self) { r in let service = AdamantAccountService() @@ -148,6 +158,7 @@ extension Container { self.register(ChatsProvider.self) { r in let provider = AdamantChatsProvider() provider.apiService = r.resolve(ApiService.self) + provider.socketService = r.resolve(SocketService.self) provider.stack = r.resolve(CoreDataStack.self) provider.adamantCore = r.resolve(AdamantCore.self) provider.securedStore = r.resolve(SecuredStore.self) @@ -183,6 +194,14 @@ extension Container { return service }.inObjectScope(.container) + // MARK: SocketService + // No need to init AdamantCore + self.register(SocketService.self) { r in + let service = AdamantSocketService() + service.nodesSource = r.resolve(NodesSource.self) + return service + }.inObjectScope(.container) + // MARK: Notifications self.register(NotificationsService.self) { r in let service = AdamantNotificationsService() @@ -194,6 +213,7 @@ extension Container { self.register(ChatsProvider.self) { r in let provider = AdamantChatsProvider() provider.apiService = r.resolve(ApiService.self) + provider.socketService = r.resolve(SocketService.self) provider.securedStore = r.resolve(SecuredStore.self) return provider }.inObjectScope(.container) diff --git a/AdamantShared/Models/Transaction.swift b/AdamantShared/Models/Transaction.swift index dc4de34c0..9243013e4 100644 --- a/AdamantShared/Models/Transaction.swift +++ b/AdamantShared/Models/Transaction.swift @@ -55,8 +55,8 @@ extension Transaction: Codable { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = UInt64(try container.decode(String.self, forKey: .id))! - self.height = try container.decode(Int64.self, forKey: .height) - self.blockId = try container.decode(String.self, forKey: .blockId) + self.height = (try? container.decode(Int64.self, forKey: .height)) ?? 0 + self.blockId = (try? container.decode(String.self, forKey: .blockId)) ?? "" self.type = try container.decode(TransactionType.self, forKey: .type) self.timestamp = try container.decode(UInt64.self, forKey: .timestamp) self.senderPublicKey = try container.decode(String.self, forKey: .senderPublicKey) @@ -67,7 +67,7 @@ extension Transaction: Codable { self.confirmations = (try? container.decode(Int64.self, forKey: .confirmations)) ?? 0 self.requesterPublicKey = try? container.decode(String.self, forKey: .requesterPublicKey) self.signSignature = try? container.decode(String.self, forKey: .signSignature) - self.signatures = try container.decode([String].self, forKey: .signatures) + self.signatures = (try? container.decode([String].self, forKey: .signatures)) ?? [] self.asset = try container.decode(TransactionAsset.self, forKey: .asset) let amount = try container.decode(Decimal.self, forKey: .amount) @@ -107,6 +107,7 @@ extension Transaction: Codable { try container.encode(amount.shiftedToAdamant(), forKey: .amount) // Decimal try container.encode(fee.shiftedToAdamant(), forKey: .fee) // Decimal } + } extension Transaction: WrappableModel { diff --git a/Podfile b/Podfile index 363e45fbe..a3abd5519 100644 --- a/Podfile +++ b/Podfile @@ -11,6 +11,7 @@ target 'Adamant' do pod 'MessageKit', '2.0.0' # Chat UI pod 'MyLittlePinpad' # Pinpad pod 'PMAlertController' # Custom alert controller + pod 'Socket.IO-Client-Swift', '~> 15.2.0' end post_install do |installer| diff --git a/Podfile.lock b/Podfile.lock index f216b18b4..0c3b61078 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -12,6 +12,9 @@ PODS: - MessageInputBar/Core - MyLittlePinpad (0.3) - PMAlertController (3.5.0) + - Socket.IO-Client-Swift (15.2.0): + - Starscream (~> 3.1) + - Starscream (3.1.1) DEPENDENCIES: - FreakingSimpleRoundImageView @@ -19,6 +22,7 @@ DEPENDENCIES: - MessageKit (= 2.0.0) - MyLittlePinpad - PMAlertController + - Socket.IO-Client-Swift (~> 15.2.0) SPEC REPOS: trunk: @@ -28,6 +32,8 @@ SPEC REPOS: - MessageKit - MyLittlePinpad - PMAlertController + - Socket.IO-Client-Swift + - Starscream SPEC CHECKSUMS: FreakingSimpleRoundImageView: 0d687cb05da8684e85c4c2ae9945bafcbe89d2a2 @@ -36,7 +42,9 @@ SPEC CHECKSUMS: MessageKit: 29c1c87e5a396d2ca7a3f712e5171dc9aba42a1e MyLittlePinpad: 5d57cb5a092ddbeb5c4e6fa0b46df83bd3e88b0c PMAlertController: 06dab8160066fc4ce991c880e3722cd403e2926a + Socket.IO-Client-Swift: 1e3e3a1f09f3312a167f0d781eb2f383d477357c + Starscream: 4bb2f9942274833f7b4d296a55504dcfc7edb7b0 -PODFILE CHECKSUM: 080a2c755d62f3318eb98b5950e1786073125f94 +PODFILE CHECKSUM: 1d081ac466709ab7ca1f43d0d3bf418f86bd7d6d COCOAPODS: 1.11.2 From dbf563249f92d2661891c106d49c9a2489a51a29 Mon Sep 17 00:00:00 2001 From: StanislavDevIOS Date: Fri, 29 Apr 2022 17:49:02 +0300 Subject: [PATCH 2/6] socket work improvements --- Adamant.xcodeproj/project.pbxproj | 32 +++++++++---------- Adamant/ServiceProtocols/NodesSource.swift | 2 ++ Adamant/Services/AdamantNodesSource.swift | 4 +++ .../DataProviders/AdamantChatsProvider.swift | 14 +++++--- .../SocketService/AdamantSocketService.swift | 25 ++++++++++++--- .../Chats/ChatViewController+MessageKit.swift | 9 +++++- ...AdmWalletService+RichMessageProvider.swift | 2 +- ...TransactionDetailsViewControllerBase.swift | 6 ++-- AdamantShared/Models/Node.swift | 6 +++- 9 files changed, 70 insertions(+), 30 deletions(-) diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 9fd24539d..5a1b59a26 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -2897,7 +2897,7 @@ CODE_SIGN_ENTITLEMENTS = MessageNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2906,7 +2906,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.MessageNotificationContentExtension"; @@ -2926,7 +2926,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2935,7 +2935,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.MessageNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3073,7 +3073,7 @@ CODE_SIGN_ENTITLEMENTS = Adamant/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = ADM.Dev; EXCLUDED_SOURCE_FILE_NAMES = ""; @@ -3083,7 +3083,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "e4233bbf-3705-44fe-95b0-e77475672c60"; @@ -3102,7 +3102,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = Adamant; EXCLUDED_SOURCE_FILE_NAMES = Debug.xcassets; @@ -3112,7 +3112,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "bedd1b75-2f23-4a85-a0b2-14c424fcff42"; @@ -3130,7 +3130,7 @@ CODE_SIGN_ENTITLEMENTS = TransferNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3139,7 +3139,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.TransferNotificationContentExtension"; @@ -3159,7 +3159,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3168,7 +3168,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.TransferNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3188,7 +3188,7 @@ CODE_SIGN_ENTITLEMENTS = NotificationServiceExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3197,7 +3197,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.NotificationServiceExtension"; @@ -3217,7 +3217,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 174; + CURRENT_PROJECT_VERSION = 175; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3226,7 +3226,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.1; + MARKETING_VERSION = 2.3.2; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.NotificationServiceExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Adamant/ServiceProtocols/NodesSource.swift b/Adamant/ServiceProtocols/NodesSource.swift index 0a91798c7..a10796955 100644 --- a/Adamant/ServiceProtocols/NodesSource.swift +++ b/Adamant/ServiceProtocols/NodesSource.swift @@ -43,6 +43,8 @@ protocol NodesSource { func getNewNode() -> Node func getValidNode(completion: @escaping ((Node?) -> Void)) + func getSocketNewNode() -> Node + func saveNodes() func reloadNodes() diff --git a/Adamant/Services/AdamantNodesSource.swift b/Adamant/Services/AdamantNodesSource.swift index d295cab7f..f9a85a1a0 100644 --- a/Adamant/Services/AdamantNodesSource.swift +++ b/Adamant/Services/AdamantNodesSource.swift @@ -71,6 +71,10 @@ class AdamantNodesSource: NodesSource { } } + func getSocketNewNode() -> Node { + return nodes[0] + } + // MARK: - Tools func saveNodes() { do { diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index bc1a6f0d1..cf002978b 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -199,7 +199,6 @@ extension AdamantChatsProvider { switch result { case .success(let trans): self.processingQueue.async { - self.process(messageTransactions: [trans], senderId: address, privateKey: privateKey, @@ -551,6 +550,7 @@ extension AdamantChatsProvider { switch result { case .success(let transaction): do { + transaction.statusEnum = MessageStatus.delivered try context.save() completion(.success(transaction: transaction)) } catch { @@ -941,7 +941,6 @@ extension AdamantChatsProvider { if height < h { height = h } - unconfirmedsSemaphore.signal() continue } else { @@ -993,11 +992,15 @@ extension AdamantChatsProvider { } if trans == nil { + if (chatTransaction.blockId?.isEmpty ?? true) && (chatTransaction.amountValue ?? 0.0 > 0.0) { + chatTransaction.statusEnum = .pending + } messages.insert(chatTransaction) } else { trans?.height = chatTransaction.height trans?.blockId = chatTransaction.blockId trans?.confirmations = chatTransaction.confirmations + trans?.statusEnum = .delivered } } } @@ -1013,7 +1016,10 @@ extension AdamantChatsProvider { // MARK: 4. Unread messagess if let readedLastHeight = readedLastHeight { - let unreadTransactions = newMessageTransactions.filter { $0.height > readedLastHeight } + var unreadTransactions = newMessageTransactions.filter { $0.height > readedLastHeight } + if unreadTransactions.count == 0 { + unreadTransactions = newMessageTransactions.filter { $0.height == 0 } + } let chatrooms = Dictionary(grouping: unreadTransactions, by: ({ (t: ChatTransaction) -> Chatroom in t.chatroom! })) for (chatroom, trs) in chatrooms { if let address = chatroom.partner?.address { @@ -1217,11 +1223,9 @@ extension AdamantChatsProvider { return } - transaction.isConfirmed = true transaction.height = height transaction.blockId = blockId transaction.confirmations = confirmations - transaction.statusEnum = .delivered self.unconfirmedTransactions.removeValue(forKey: id) if let lastHeight = receivedLastHeight, lastHeight < height { diff --git a/Adamant/Services/SocketService/AdamantSocketService.swift b/Adamant/Services/SocketService/AdamantSocketService.swift index cdaa2c40c..476e115b0 100644 --- a/Adamant/Services/SocketService/AdamantSocketService.swift +++ b/Adamant/Services/SocketService/AdamantSocketService.swift @@ -16,17 +16,34 @@ class AdamantSocketService: SocketService { var adamantCore: AdamantCore! var nodesSource: NodesSource! { didSet { - //nodesSource.migrate() - // refreshNode() + refreshNode() } } - private let manager = SocketManager(socketURL: URL(string: "https://endless.adamant.im")!, config: [.log(true), .compress]) - private var socket:SocketIOClient? + // MARK: - Properties + + private(set) var node: Node? { + didSet { + currentUrl = node?.asSocketURL() + } + } + + private var currentUrl: URL? + + private var manager: SocketManager! + private var socket: SocketIOClient? let defaultResponseDispatchQueue = DispatchQueue(label: "com.adamant.response-queue", qos: .utility, attributes: [.concurrent]) + // MARK: - Tools + + func refreshNode() { + node = nodesSource?.getSocketNewNode() + } + func connect(address: String) { + guard let currentUrl = currentUrl else { return } + manager = SocketManager(socketURL: currentUrl, config: [.log(false), .compress]) socket = manager.defaultSocket socket?.on(clientEvent: .connect, callback: {[weak self] _, _ in self?.socket?.emit("address", with: [address]) diff --git a/Adamant/Stories/Chats/ChatViewController+MessageKit.swift b/Adamant/Stories/Chats/ChatViewController+MessageKit.swift index 6061bb5f0..78e6ebc20 100644 --- a/Adamant/Stories/Chats/ChatViewController+MessageKit.swift +++ b/Adamant/Stories/Chats/ChatViewController+MessageKit.swift @@ -111,7 +111,14 @@ extension ChatViewController: MessagesDataSource { } } - return NSAttributedString(string: humanizedTime.string, attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption2), NSAttributedString.Key.foregroundColor: UIColor.adamant.secondary]) + var dop = "" + if let message = message as? MessageTransaction, + let blockId = message.blockId, + !blockId.isEmpty { + dop = "⚭ " + } + + return NSAttributedString(string: dop + humanizedTime.string, attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption2), NSAttributedString.Key.foregroundColor: UIColor.adamant.secondary]) } func customCell(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> UICollectionViewCell { diff --git a/Adamant/Wallets/Adamant/AdmWalletService+RichMessageProvider.swift b/Adamant/Wallets/Adamant/AdmWalletService+RichMessageProvider.swift index 3378326ea..77864de87 100644 --- a/Adamant/Wallets/Adamant/AdmWalletService+RichMessageProvider.swift +++ b/Adamant/Wallets/Adamant/AdmWalletService+RichMessageProvider.swift @@ -126,7 +126,7 @@ extension AdmWalletService: RichMessageProvider { extension MessageStatus { func toTransactionStatus() -> TransactionStatus { switch self { - case .pending: return TransactionStatus.updating + case .pending: return TransactionStatus.pending case .delivered: return TransactionStatus.success case .failed: return TransactionStatus.failed } diff --git a/Adamant/Wallets/TransactionDetailsViewControllerBase.swift b/Adamant/Wallets/TransactionDetailsViewControllerBase.swift index c9f983851..96aa3709f 100644 --- a/Adamant/Wallets/TransactionDetailsViewControllerBase.swift +++ b/Adamant/Wallets/TransactionDetailsViewControllerBase.swift @@ -411,7 +411,8 @@ class TransactionDetailsViewControllerBase: FormViewController { $0.tag = Rows.block.tag $0.title = Rows.block.localized - if let value = transaction?.blockValue { + if let value = transaction?.blockValue, + !value.isEmpty { $0.value = value } else { $0.value = TransactionDetailsViewControllerBase.awaitingValueString @@ -425,7 +426,8 @@ class TransactionDetailsViewControllerBase: FormViewController { }.cellUpdate { [weak self] (cell, row) in cell.textLabel?.textColor = .black - if let value = self?.transaction?.blockValue { + if let value = self?.transaction?.blockValue, + !value.isEmpty { row.value = value } else { row.value = TransactionDetailsViewControllerBase.awaitingValueString diff --git a/AdamantShared/Models/Node.swift b/AdamantShared/Models/Node.swift index bc85788b5..921d9964a 100644 --- a/AdamantShared/Models/Node.swift +++ b/AdamantShared/Models/Node.swift @@ -44,10 +44,14 @@ class Node: Equatable, Codable { } } - /// Builds URL, using specified port, or default scheme's port, if nil /// /// - Returns: URL, if no errors were thrown + + func asSocketURL() -> URL? { + return asURL(forcePort: false) + } + func asURL() -> URL? { return asURL(forcePort: true) } From 1b4512105f7602d1335a0c4a72b30e2bbfab7b16 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sat, 30 Apr 2022 20:04:01 +0300 Subject: [PATCH 3/6] Fixed node test crash --- Adamant.xcodeproj/project.pbxproj | 4 ++ Adamant/Services/AdamantDialogService.swift | 41 +++++----------- .../Services/AdamantNotificationService.swift | 20 ++------ .../AdamantAccountsProvider.swift | 42 +++++------------ .../Chats/ChatListViewController.swift | 21 ++------- .../Stories/Chats/ChatViewController.swift | 14 ++---- .../Stories/Chats/NewChatViewController.swift | 12 +---- .../Chats/SearchResultsViewController.swift | 10 ++-- .../DelegatesListViewController.swift | 32 ++++--------- .../Login/LoginViewController+QR.swift | 9 +--- .../NodeEditorViewController.swift | 47 ++++++++++--------- .../AdmTransactionsViewController.swift | 8 +--- .../ERC20TransactionsViewController.swift | 8 +--- .../EthTransactionsViewController.swift | 8 +--- .../TransferViewControllerBase+Alert.swift | 35 ++++---------- .../TransferViewControllerBase+QR.swift | 29 ++++-------- .../Wallets/TransferViewControllerBase.swift | 9 ++-- AdamantShared/Helpers/GCDUtilites.swift | 27 +++++++++++ 18 files changed, 131 insertions(+), 245 deletions(-) create mode 100644 AdamantShared/Helpers/GCDUtilites.swift diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 594a1723a..de377d295 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 3A64FAA927BA67BF007D5588 /* AdamantSecret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A64FAA527BA67BF007D5588 /* AdamantSecret.swift */; }; 3A8875EF27BBF38D00436195 /* Parchment in Frameworks */ = {isa = PBXBuildFile; productRef = 3A8875EE27BBF38D00436195 /* Parchment */; }; 3C06931576393125C61FB8F6 /* Pods_Adamant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33975C0D891698AA7E74EBCC /* Pods_Adamant.framework */; }; + 553B1284281C6EE100FFF24C /* GCDUtilites.swift in Sources */ = {isa = PBXBuildFile; fileRef = 553B1283281C6EE100FFF24C /* GCDUtilites.swift */; }; 6403F5DB2272389800D58779 /* (null) in Sources */ = {isa = PBXBuildFile; }; 6403F5DE22723C6800D58779 /* DashMainnet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6403F5DD22723C6800D58779 /* DashMainnet.swift */; }; 6403F5E022723F6400D58779 /* DashWalletRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6403F5DF22723F6400D58779 /* DashWalletRouter.swift */; }; @@ -608,6 +609,7 @@ 36AB8CE9537B3B873972548B /* Pods_AdmCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AdmCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3A64FAA527BA67BF007D5588 /* AdamantSecret.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdamantSecret.swift; sourceTree = ""; }; 4A4D67BD3DC89C07D1351248 /* Pods-AdmCore.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AdmCore.release.xcconfig"; path = "Target Support Files/Pods-AdmCore/Pods-AdmCore.release.xcconfig"; sourceTree = ""; }; + 553B1283281C6EE100FFF24C /* GCDUtilites.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GCDUtilites.swift; sourceTree = ""; }; 6403F5DD22723C6800D58779 /* DashMainnet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashMainnet.swift; sourceTree = ""; }; 6403F5DF22723F6400D58779 /* DashWalletRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashWalletRouter.swift; sourceTree = ""; }; 6403F5E122723F7500D58779 /* DashWallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashWallet.swift; sourceTree = ""; }; @@ -1759,6 +1761,7 @@ E927171D20C04613002BB9A6 /* UIColor+hex.swift */, E9D1BE19211DA25300E86B72 /* UIView+constraints.swift */, E935C84C22AC06E500A8CA2F /* RichMessageTools.swift */, + 553B1283281C6EE100FFF24C /* GCDUtilites.swift */, ); path = Helpers; sourceTree = ""; @@ -2432,6 +2435,7 @@ 6449BA69235CA0930033B936 /* ERC20TransferViewController.swift in Sources */, E9E7CD8B20026B0600DFC4DB /* AccountService.swift in Sources */, 640EFAA42558613A00E9724B /* EthProvider.swift in Sources */, + 553B1284281C6EE100FFF24C /* GCDUtilites.swift in Sources */, 648CE3AC229AD2190070A2CC /* DashTransferViewController.swift in Sources */, 640EFA9C2558613200E9724B /* AdamantProvider.swift in Sources */, 64F085D920E2D7600006DE68 /* AdmTransactionsViewController.swift in Sources */, diff --git a/Adamant/Services/AdamantDialogService.swift b/Adamant/Services/AdamantDialogService.swift index a65da2e34..996622c86 100644 --- a/Adamant/Services/AdamantDialogService.swift +++ b/Adamant/Services/AdamantDialogService.swift @@ -32,12 +32,9 @@ class AdamantDialogService: DialogService { extension AdamantDialogService { func present(_ viewController: UIViewController, animated: Bool, completion: (() -> Void)?) { viewController.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { - getTopmostViewController()?.present(viewController, animated: animated, completion: completion) - } else { - DispatchQueue.main.async { [weak self] in - self?.getTopmostViewController()?.present(viewController, animated: animated, completion: completion) - } + + DispatchQueue.onMainAsync { [weak self] in + self?.getTopmostViewController()?.present(viewController, animated: animated, completion: completion) } } @@ -86,12 +83,8 @@ extension AdamantDialogService { } func dismissProgress() { - if Thread.isMainThread { + DispatchQueue.onMainAsync { FTIndicator.dismissProgress() - } else { - DispatchQueue.main.async { - FTIndicator.dismissProgress() - } } } @@ -104,12 +97,8 @@ extension AdamantDialogService { } func showError(withMessage message: String, error: Error? = nil) { - if Thread.isMainThread { - internalShowError(withMessage: message, error: error) - } else { - DispatchQueue.main.async { [weak self] in - self?.internalShowError(withMessage: message, error: error) - } + DispatchQueue.onMainAsync { [weak self] in + self?.internalShowError(withMessage: message, error: error) } } @@ -372,12 +361,9 @@ extension AdamantDialogService { alert.addAction(UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel, handler: nil)) alert.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { - present(alert, animated: true, completion: nil) - } else { - DispatchQueue.main.async { [weak self] in - self?.present(alert, animated: true, completion: nil) - } + + DispatchQueue.onMainAsync { [weak self] in + self?.present(alert, animated: true, completion: nil) } } } @@ -504,12 +490,9 @@ extension AdamantDialogService { alertVC.alertActionStackViewHeightConstraint.constant = 50 } alertVC.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { - present(alertVC, animated: true, completion: nil) - } else { - DispatchQueue.main.async { [weak self] in - self?.present(alertVC, animated: true, completion: nil) - } + + DispatchQueue.onMainAsync { [weak self] in + self?.present(alertVC, animated: true, completion: nil) } } } diff --git a/Adamant/Services/AdamantNotificationService.swift b/Adamant/Services/AdamantNotificationService.swift index 2045d8fd7..6779d99df 100644 --- a/Adamant/Services/AdamantNotificationService.swift +++ b/Adamant/Services/AdamantNotificationService.swift @@ -155,13 +155,7 @@ extension AdamantNotificationsService { } } - if Thread.isMainThread { - callback() - } else { - DispatchQueue.main.sync { - callback() - } - } + DispatchQueue.onMainSync(callback) } } @@ -175,12 +169,8 @@ extension AdamantNotificationsService { content.sound = UNNotificationSound(named: UNNotificationSoundName("notification.mp3")) if let number = type.badge { - if Thread.isMainThread { + DispatchQueue.onMainSync { content.badge = NSNumber(value: UIApplication.shared.applicationIconBadgeNumber + backgroundNotifications + number) - } else { - DispatchQueue.main.sync { - content.badge = NSNumber(value: UIApplication.shared.applicationIconBadgeNumber + backgroundNotifications + number) - } } if isBackgroundSession { @@ -222,12 +212,8 @@ extension AdamantNotificationsService { securedStore.remove(StoreKey.notificationsService.customBadgeNumber) } - if Thread.isMainThread { + DispatchQueue.onMainAsync { UIApplication.shared.applicationIconBadgeNumber = appIconBadgeNumber - } else { - DispatchQueue.main.async { - UIApplication.shared.applicationIconBadgeNumber = appIconBadgeNumber - } } } diff --git a/Adamant/Services/DataProviders/AdamantAccountsProvider.swift b/Adamant/Services/DataProviders/AdamantAccountsProvider.swift index e7e43f369..4e84c0307 100644 --- a/Adamant/Services/DataProviders/AdamantAccountsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantAccountsProvider.swift @@ -162,24 +162,16 @@ class AdamantAccountsProvider: AccountsProvider { if let context = context { // viewContext only on MainThread if context == stack.container.viewContext { - if Thread.isMainThread { + DispatchQueue.onMainSync { acc = (try? context.fetch(request))?.first - } else { - DispatchQueue.main.sync { - acc = (try? context.fetch(request))?.first - } } } else { acc = (try? context.fetch(request))?.first } } else { // viewContext only on MainThread - if Thread.isMainThread { + DispatchQueue.onMainSync { acc = (try? stack.container.viewContext.fetch(request))?.first - } else { - DispatchQueue.main.sync { - acc = (try? stack.container.viewContext.fetch(request))?.first - } } } @@ -418,32 +410,24 @@ extension AdamantAccountsProvider { */ private func createCoreDataAccount(with address: String, publicKey: String) -> CoreDataAccount { - let coreAccount: CoreDataAccount - if Thread.isMainThread { - coreAccount = createCoreDataAccount(with: address, publicKey: publicKey, context: stack.container.viewContext) - } else { - var acc: CoreDataAccount! - DispatchQueue.main.sync { - acc = createCoreDataAccount(with: address, publicKey: publicKey, context: stack.container.viewContext) - } - coreAccount = acc - } + var coreAccount: CoreDataAccount! + DispatchQueue.onMainSync { + coreAccount = createCoreDataAccount( + with: address, + publicKey: publicKey, + context: stack.container.viewContext + ) + } return coreAccount } private func createCoreDataAccount(from account: AdamantAccount) -> CoreDataAccount { - let coreAccount: CoreDataAccount - if Thread.isMainThread { + var coreAccount: CoreDataAccount! + + DispatchQueue.onMainSync { coreAccount = createCoreDataAccount(from: account, context: stack.container.viewContext) - } else { - var acc: CoreDataAccount! - DispatchQueue.main.sync { - acc = createCoreDataAccount(from: account, context: stack.container.viewContext) - } - coreAccount = acc } - return coreAccount } diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index 84b72e69d..3b9079fb3 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -304,16 +304,10 @@ class ChatListViewController: UIViewController { return } - if Thread.isMainThread { - busyBackgroundView.isHidden = false - busyBackgroundView.alpha = 1.0 - busyIndicatorView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) - } else { - DispatchQueue.main.async { - self.busyBackgroundView.isHidden = false - self.busyBackgroundView.alpha = 1.0 - self.busyIndicatorView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) - } + DispatchQueue.onMainAsync { + self.busyBackgroundView.isHidden = false + self.busyBackgroundView.alpha = 1.0 + self.busyIndicatorView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0) } return @@ -341,14 +335,9 @@ class ChatListViewController: UIViewController { self.busyBackgroundView.isHidden = false } - if Thread.isMainThread { + DispatchQueue.onMainAsync { initialValues() UIView.animate(withDuration: 0.2, animations: animations, completion: completion) - } else { - DispatchQueue.main.async { - initialValues() - UIView.animate(withDuration: 0.2, animations: animations, completion: completion) - } } } } diff --git a/Adamant/Stories/Chats/ChatViewController.swift b/Adamant/Stories/Chats/ChatViewController.swift index 8d03098d8..955bd647d 100644 --- a/Adamant/Stories/Chats/ChatViewController.swift +++ b/Adamant/Stories/Chats/ChatViewController.swift @@ -889,20 +889,12 @@ extension ChatViewController: TransferViewControllerDelegate, ComplexTransferVie private func dismissTransferViewController(andPresent viewController: UIViewController?) { fixKeyboardInsets = true - if Thread.isMainThread { - dismiss(animated: true, completion: nil) + DispatchQueue.onMainAsync { [weak self] in + self?.dismiss(animated: true, completion: nil) - if let viewController = viewController, let nav = navigationController { + if let viewController = viewController, let nav = self?.navigationController { nav.pushViewController(viewController, animated: true) } - } else { - DispatchQueue.main.async { [weak self] in - self?.dismiss(animated: true, completion: nil) - - if let viewController = viewController, let nav = self?.navigationController { - nav.pushViewController(viewController, animated: true) - } - } } } } diff --git a/Adamant/Stories/Chats/NewChatViewController.swift b/Adamant/Stories/Chats/NewChatViewController.swift index 9eb5fa12f..82dc7ccca 100644 --- a/Adamant/Stories/Chats/NewChatViewController.swift +++ b/Adamant/Stories/Chats/NewChatViewController.swift @@ -180,12 +180,8 @@ class NewChatViewController: FormViewController { } if let done = self?.navigationItem.rightBarButtonItem { - if Thread.isMainThread { + DispatchQueue.onMainAsync { done.isEnabled = text.count > 6 - } else { - DispatchQueue.main.async { - done.isEnabled = text.count > 6 - } } } } else { @@ -375,12 +371,8 @@ extension NewChatViewController { AVCaptureDevice.requestAccess(for: .video) { [weak self] (granted: Bool) in if granted, let qrReader = self?.qrReader { qrReader.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { + DispatchQueue.onMainAsync { self?.present(qrReader, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - self?.present(qrReader, animated: true, completion: nil) - } } } else { return diff --git a/Adamant/Stories/Chats/SearchResultsViewController.swift b/Adamant/Stories/Chats/SearchResultsViewController.swift index 00a5bbb16..01470295d 100644 --- a/Adamant/Stories/Chats/SearchResultsViewController.swift +++ b/Adamant/Stories/Chats/SearchResultsViewController.swift @@ -148,14 +148,10 @@ class SearchResultsViewController: UITableViewController { cell.avatarImageView.tintColor = UIColor.adamant.primary } else { if let address = partner.publicKey { - if Thread.isMainThread { - let image = self.avatarService.avatar(for: address, size: 200) + let image = self.avatarService.avatar(for: address, size: 200) + + DispatchQueue.onMainAsync { cell.avatarImage = image - } else { - let image = self.avatarService.avatar(for: address, size: 200) - DispatchQueue.main.async { - cell.avatarImage = image - } } cell.avatarImageView.roundingMode = .round diff --git a/Adamant/Stories/Delegates/DelegatesListViewController.swift b/Adamant/Stories/Delegates/DelegatesListViewController.swift index 257878515..fc2fa4109 100644 --- a/Adamant/Stories/Delegates/DelegatesListViewController.swift +++ b/Adamant/Stories/Delegates/DelegatesListViewController.swift @@ -413,31 +413,17 @@ extension DelegatesListViewController { let newVotesColor = changes.count > maxVotes ? UIColor.adamant.alert : UIColor.adamant.primary let totalVotesColor = totalVoted > maxTotalVotes ? UIColor.adamant.alert : UIColor.adamant.primary - - if Thread.isMainThread { - upVotesLabel.text = String(upvoted) - downVotesLabel.text = String(downvoted) - newVotesLabel.text = "\(changes.count)/\(maxVotes)" - totalVotesLabel.text = "\(totalVoted)/\(maxTotalVotes)" + DispatchQueue.onMainAsync { [weak self] in + guard let self = self else { return } - voteBtn.isEnabled = votingEnabled - newVotesLabel.textColor = newVotesColor - totalVotesLabel.textColor = totalVotesColor - } else { - let changes = changes.count - let max = maxVotes - let totalMax = maxTotalVotes + self.upVotesLabel.text = "\(upvoted)" + self.downVotesLabel.text = "\(downvoted)" + self.newVotesLabel.text = "\(changes.count)/\(self.maxVotes)" + self.totalVotesLabel.text = "\(totalVoted)/\(self.maxTotalVotes)" - DispatchQueue.main.async { [unowned self] in - self.upVotesLabel.text = "\(upvoted)" - self.downVotesLabel.text = "\(downvoted)" - self.newVotesLabel.text = "\(changes)/\(max)" - self.totalVotesLabel.text = "\(totalVoted)/\(totalMax)" - - self.voteBtn.isEnabled = votingEnabled - self.newVotesLabel.textColor = newVotesColor - self.totalVotesLabel.textColor = totalVotesColor - } + self.voteBtn.isEnabled = votingEnabled + self.newVotesLabel.textColor = newVotesColor + self.totalVotesLabel.textColor = totalVotesColor } } } diff --git a/Adamant/Stories/Login/LoginViewController+QR.swift b/Adamant/Stories/Login/LoginViewController+QR.swift index 8a38dd6e5..6de266980 100644 --- a/Adamant/Stories/Login/LoginViewController+QR.swift +++ b/Adamant/Stories/Login/LoginViewController+QR.swift @@ -24,18 +24,11 @@ extension LoginViewController { case .notDetermined: AVCaptureDevice.requestAccess(for: .video) { [weak self] (granted: Bool) in if granted { - if Thread.isMainThread { + DispatchQueue.onMainAsync { let reader = QRCodeReaderViewController.adamantQrCodeReader() reader.delegate = self reader.modalPresentationStyle = .overFullScreen self?.present(reader, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - let reader = QRCodeReaderViewController.adamantQrCodeReader() - reader.delegate = self - reader.modalPresentationStyle = .overFullScreen - self?.present(reader, animated: true, completion: nil) - } } } else { return diff --git a/Adamant/Stories/NodesEditor/NodeEditorViewController.swift b/Adamant/Stories/NodesEditor/NodeEditorViewController.swift index 59fe67759..e0489dcc6 100644 --- a/Adamant/Stories/NodesEditor/NodeEditorViewController.swift +++ b/Adamant/Stories/NodesEditor/NodeEditorViewController.swift @@ -122,16 +122,10 @@ class NodeEditorViewController: FormViewController { let type = testState.accessoryType let value = testState.localized - if Thread.isMainThread { - row.baseCell.accessoryType = type + DispatchQueue.onMainAsync { row.baseValue = value row.updateCell() - } else { - DispatchQueue.main.async { - row.baseValue = value - row.updateCell() - row.baseCell.accessoryType = type - } + row.baseCell.accessoryType = type } } } @@ -239,7 +233,7 @@ class NodeEditorViewController: FormViewController { // MARK: - Actions extension NodeEditorViewController { - func testNode(completion: ((Bool) -> Void)? = nil) { + private func testNode(completion: ((Bool) -> Void)? = nil) { var components = URLComponents() // Host @@ -273,22 +267,29 @@ extension NodeEditorViewController { } dialogService.showProgress(withMessage: String.adamantLocalized.nodesEditor.testInProgressMessage, userInteractionEnable: false) - apiService.getNodeVersion(url: url) { result in - switch result { - case .success(_): - self.dialogService.dismissProgress() - self.testState = .passed - completion?(true) - - case .failure(let error): - self.dialogService.showWarning(withMessage: error.localized) - self.testState = .failed - completion?(false) + apiService.getNodeVersion(url: url) { [self] result in + let isSuccess = processApiServiceTestResult(result: result) + + DispatchQueue.onMainAsync { + completion?(isSuccess) } } } - @objc func done() { + private func processApiServiceTestResult(result: ApiServiceResult) -> Bool { + switch result { + case .success(_): + dialogService.dismissProgress() + testState = .passed + return true + case .failure(let error): + dialogService.showWarning(withMessage: error.localized) + testState = .failed + return false + } + } + + @objc private func done() { switch testState { case .notTested, .failed: testNode { success in @@ -338,12 +339,12 @@ extension NodeEditorViewController { delegate?.nodeEditorViewController(self, didFinishEditingWithResult: result) } - @objc func cancel() { + @objc private func cancel() { didCallDelegate = true delegate?.nodeEditorViewController(self, didFinishEditingWithResult: .cancel) } - func deleteNode() { + private func deleteNode() { let alert = UIAlertController(title: String.adamantLocalized.nodesEditor.deleteNodeAlert, message: nil, preferredStyle: .alert) alert.addAction(UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel, handler: nil)) alert.addAction(UIAlertAction(title: String.adamantLocalized.alert.delete, style: .destructive, handler: { _ in diff --git a/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift b/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift index a3b4299a3..04688cafb 100644 --- a/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift +++ b/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift @@ -64,12 +64,8 @@ class AdmTransactionsViewController: TransactionsListViewControllerBase { controller = nil } - if Thread.isMainThread { - tableView.reloadData() - } else { - DispatchQueue.main.async { - self.tableView.reloadData() - } + DispatchQueue.onMainAsync { + self.tableView.reloadData() } } diff --git a/Adamant/Wallets/ERC20/ERC20TransactionsViewController.swift b/Adamant/Wallets/ERC20/ERC20TransactionsViewController.swift index 8bd29db72..2cac852b0 100644 --- a/Adamant/Wallets/ERC20/ERC20TransactionsViewController.swift +++ b/Adamant/Wallets/ERC20/ERC20TransactionsViewController.swift @@ -73,12 +73,8 @@ class ERC20TransactionsViewController: TransactionsListViewControllerBase { } override func reloadData() { - if Thread.isMainThread { - refreshControl.beginRefreshing() - } else { - DispatchQueue.main.async { [weak self] in - self?.refreshControl.beginRefreshing() - } + DispatchQueue.onMainAsync { [weak self] in + self?.refreshControl.beginRefreshing() } handleRefresh(refreshControl) diff --git a/Adamant/Wallets/Ethereum/EthTransactionsViewController.swift b/Adamant/Wallets/Ethereum/EthTransactionsViewController.swift index cbd666ead..3f63599ed 100644 --- a/Adamant/Wallets/Ethereum/EthTransactionsViewController.swift +++ b/Adamant/Wallets/Ethereum/EthTransactionsViewController.swift @@ -67,12 +67,8 @@ class EthTransactionsViewController: TransactionsListViewControllerBase { } override func reloadData() { - if Thread.isMainThread { - refreshControl.beginRefreshing() - } else { - DispatchQueue.main.async { [weak self] in - self?.refreshControl.beginRefreshing() - } + DispatchQueue.onMainAsync { [weak self] in + self?.refreshControl.beginRefreshing() } handleRefresh(refreshControl) diff --git a/Adamant/Wallets/TransferViewControllerBase+Alert.swift b/Adamant/Wallets/TransferViewControllerBase+Alert.swift index 25f155490..64691c10c 100644 --- a/Adamant/Wallets/TransferViewControllerBase+Alert.swift +++ b/Adamant/Wallets/TransferViewControllerBase+Alert.swift @@ -31,19 +31,12 @@ extension TransferViewControllerBase { view.constrainCentered(indicator) indicator.startAnimating() - if animated { - if Thread.isMainThread { - view.alpha = 0 - UIView.animate(withDuration: 0.2) { - view.alpha = 1 - } - } else { - DispatchQueue.main.async { - view.alpha = 0 - UIView.animate(withDuration: 0.2) { - view.alpha = 1 - } - } + guard animated else { return } + + DispatchQueue.onMainAsync { + view.alpha = 0 + UIView.animate(withDuration: 0.2) { + view.alpha = 1 } } } @@ -90,13 +83,7 @@ extension TransferViewControllerBase { } } - if Thread.isMainThread { - callback() - } else { - DispatchQueue.main.async { - callback() - } - } + DispatchQueue.onMainAsync(callback) } func hideAlert(animated: Bool) { @@ -126,12 +113,6 @@ extension TransferViewControllerBase { } } - if Thread.isMainThread { - callback() - } else { - DispatchQueue.main.async { - callback() - } - } + DispatchQueue.onMainAsync(callback) } } diff --git a/Adamant/Wallets/TransferViewControllerBase+QR.swift b/Adamant/Wallets/TransferViewControllerBase+QR.swift index 92e124f8d..9e5356544 100644 --- a/Adamant/Wallets/TransferViewControllerBase+QR.swift +++ b/Adamant/Wallets/TransferViewControllerBase+QR.swift @@ -19,24 +19,17 @@ extension TransferViewControllerBase { switch AVCaptureDevice.authorizationStatus(for: .video) { case .authorized: qrReader.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { - self.present(qrReader, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - self.present(self.qrReader, animated: true, completion: nil) - } + + DispatchQueue.onMainAsync { + self.present(self.qrReader, animated: true, completion: nil) } case .notDetermined: AVCaptureDevice.requestAccess(for: .video) { [weak self] (granted: Bool) in if granted, let qrReader = self?.qrReader { qrReader.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { + DispatchQueue.onMainAsync { self?.present(qrReader, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - self?.present(qrReader, animated: true, completion: nil) - } } } else { return @@ -47,12 +40,9 @@ extension TransferViewControllerBase { let alert = UIAlertController(title: nil, message: String.adamantLocalized.login.cameraNotSupported, preferredStyle: .alert) alert.addAction(UIAlertAction(title: String.adamantLocalized.alert.ok, style: .cancel, handler: nil)) alert.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { + + DispatchQueue.onMainAsync { self.present(alert, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - self.present(alert, animated: true, completion: nil) - } } case .denied: @@ -68,12 +58,9 @@ extension TransferViewControllerBase { alert.addAction(UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel, handler: nil)) alert.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { + + DispatchQueue.onMainAsync { self.present(alert, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - self.present(alert, animated: true, completion: nil) - } } @unknown default: break diff --git a/Adamant/Wallets/TransferViewControllerBase.swift b/Adamant/Wallets/TransferViewControllerBase.swift index abc92d101..c3ea12a92 100644 --- a/Adamant/Wallets/TransferViewControllerBase.swift +++ b/Adamant/Wallets/TransferViewControllerBase.swift @@ -532,12 +532,9 @@ class TransferViewControllerBase: FormViewController { alert.addAction(cancelAction) alert.addAction(sendAction) alert.modalPresentationStyle = .overFullScreen - if Thread.isMainThread { - present(alert, animated: true, completion: nil) - } else { - DispatchQueue.main.async { - self.present(alert, animated: true, completion: nil) - } + + DispatchQueue.onMainAsync { + self.present(alert, animated: true, completion: nil) } } diff --git a/AdamantShared/Helpers/GCDUtilites.swift b/AdamantShared/Helpers/GCDUtilites.swift new file mode 100644 index 000000000..f4c8a6fce --- /dev/null +++ b/AdamantShared/Helpers/GCDUtilites.swift @@ -0,0 +1,27 @@ +// +// GCDUtilites.swift +// Adamant +// +// Created by Андрей on 29.04.2022. +// Copyright © 2022 Adamant. All rights reserved. +// + +import Foundation + +extension DispatchQueue { + static func onMainSync(_ action: () -> Void) { + guard Thread.isMainThread else { + DispatchQueue.main.sync(execute: action) + return + } + action() + } + + static func onMainAsync(_ action: @escaping () -> Void) { + guard Thread.isMainThread else { + DispatchQueue.main.async(execute: action) + return + } + action() + } +} From d73bbd6add6613abe5875ded941aab17c103bdd4 Mon Sep 17 00:00:00 2001 From: StanislavDevIOS Date: Mon, 2 May 2022 10:46:31 +0300 Subject: [PATCH 4/6] declared disconnect socket function --- Adamant/ServiceProtocols/SocketService.swift | 2 ++ .../DataProviders/AdamantChatsProvider.swift | 12 +++++++++--- .../SocketService/AdamantSocketService.swift | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Adamant/ServiceProtocols/SocketService.swift b/Adamant/ServiceProtocols/SocketService.swift index 21686a488..e9288fe60 100644 --- a/Adamant/ServiceProtocols/SocketService.swift +++ b/Adamant/ServiceProtocols/SocketService.swift @@ -18,6 +18,8 @@ protocol SocketService: AnyObject { func connect(address: String) + func disconnect() + // MARK: - Receive New Transaction func receiveNewTransaction(completion: ((ApiServiceResult) -> Void)?) diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index cf002978b..873208148 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -90,6 +90,8 @@ class AdamantChatsProvider: ChatsProvider { self?.blackList = [] self?.removedMessages = [] + + self?.disconnectFromSocket() } NotificationCenter.default.addObserver(forName: Notification.Name.AdamantAccountService.stayInChanged, object: nil, queue: nil) { [weak self] notification in @@ -195,11 +197,11 @@ extension AdamantChatsProvider { let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) privateContext.parent = self.stack.container.viewContext self.socketService.connect(address: address) - self.socketService.receiveNewTransaction { result in + self.socketService.receiveNewTransaction { [weak self] result in switch result { case .success(let trans): - self.processingQueue.async { - self.process(messageTransactions: [trans], + self?.processingQueue.async { + self?.process(messageTransactions: [trans], senderId: address, privateKey: privateKey, context: privateContext, @@ -211,6 +213,10 @@ extension AdamantChatsProvider { } } + func disconnectFromSocket() { + self.socketService.disconnect() + } + func update(completion: ((ChatsProviderResult?) -> Void)?) { if state == .updating { completion?(nil) diff --git a/Adamant/Services/SocketService/AdamantSocketService.swift b/Adamant/Services/SocketService/AdamantSocketService.swift index 476e115b0..475923556 100644 --- a/Adamant/Services/SocketService/AdamantSocketService.swift +++ b/Adamant/Services/SocketService/AdamantSocketService.swift @@ -51,6 +51,10 @@ class AdamantSocketService: SocketService { socket?.connect() } + func disconnect() { + socket?.disconnect() + } + func receiveNewTransaction(completion: ((ApiServiceResult) -> Void)?) { socket?.on("newTrans", callback: { [weak self] data, ack in guard let data = data.first else { return } From 61329649563169a937a44e49d3357d3d4eaaf9c3 Mon Sep 17 00:00:00 2001 From: StanislavDevIOS Date: Fri, 6 May 2022 17:10:37 +0300 Subject: [PATCH 5/6] Fix unread chat bug, filter signal messages, other changes --- Adamant.xcodeproj/project.pbxproj | 32 +++++----- Adamant/AppDelegate.swift | 61 +++++++++++++++++-- Adamant/CoreData/Chatroom+CoreDataClass.swift | 7 +-- .../DataProviders/AdamantChatsProvider.swift | 19 ++++-- .../AdamantTransfersProvider.swift | 1 - .../SocketService/AdamantSocketService.swift | 3 +- .../Chats/ChatListViewController.swift | 15 +++-- .../AdmTransactionsViewController.swift | 1 - 8 files changed, 100 insertions(+), 39 deletions(-) diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 5a1b59a26..8c2040e7a 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -2897,7 +2897,7 @@ CODE_SIGN_ENTITLEMENTS = MessageNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2906,7 +2906,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.MessageNotificationContentExtension"; @@ -2926,7 +2926,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2935,7 +2935,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.MessageNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3073,7 +3073,7 @@ CODE_SIGN_ENTITLEMENTS = Adamant/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = ADM.Dev; EXCLUDED_SOURCE_FILE_NAMES = ""; @@ -3083,7 +3083,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "e4233bbf-3705-44fe-95b0-e77475672c60"; @@ -3102,7 +3102,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = Adamant; EXCLUDED_SOURCE_FILE_NAMES = Debug.xcassets; @@ -3112,7 +3112,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "bedd1b75-2f23-4a85-a0b2-14c424fcff42"; @@ -3130,7 +3130,7 @@ CODE_SIGN_ENTITLEMENTS = TransferNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3139,7 +3139,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.TransferNotificationContentExtension"; @@ -3159,7 +3159,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3168,7 +3168,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.TransferNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3188,7 +3188,7 @@ CODE_SIGN_ENTITLEMENTS = NotificationServiceExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3197,7 +3197,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.NotificationServiceExtension"; @@ -3217,7 +3217,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 175; + CURRENT_PROJECT_VERSION = 176; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3226,7 +3226,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.2; + MARKETING_VERSION = 2.3.3; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.NotificationServiceExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index 4bb28b722..12c934bc9 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -265,7 +265,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } // MARK: - Remote notifications -extension AppDelegate { +extension AppDelegate: UNUserNotificationCenterDelegate { private struct RegistrationPayload: Codable { let token: String @@ -284,7 +284,6 @@ extension AppDelegate { } let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined() - // MARK: 1. Checking, if device token had not changed guard let securedStore = container.resolve(SecuredStore.self) else { fatalError("can't get secured store to get device token hash") @@ -339,6 +338,58 @@ extension AppDelegate { service.showError(withMessage: String.localizedStringWithFormat(String.adamantLocalized.notifications.registerRemotesError, error.localizedDescription), error: error) } } + + //MARK: Open Chat From Notification + func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { + if let recipientAddress = userInfo[AdamantNotificationUserInfoKeys.pushRecipient] as? String + { + if let tabbar = window?.rootViewController as? UITabBarController, + let chats = tabbar.viewControllers?.first as? UISplitViewController, + let chatList = chats.viewControllers.first as? UINavigationController, + let list = chatList.viewControllers.first as? ChatListViewController { + + guard let room = list.chatsController?.fetchedObjects?.first(where: { room in + return room.lastTransaction?.recipientAddress == recipientAddress + }) else { return } + + switch list.accountService.state { + case .loggedIn: + self.openDialog(chatList: chatList, tabbar: tabbar, list: list, chatroom: room) + case .notLogged: + break + case .isLoggingIn: + break + case .updating: + break + } + + // if not logged in + list.didLoadedMessages = { [weak self] in + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + self?.openDialog(chatList: chatList, tabbar: tabbar, list: list, chatroom: room) + } + } + } + completionHandler(.newData) + } else { + completionHandler(.noData) + } + } + + func openDialog(chatList: UINavigationController, tabbar: UITabBarController, list: ChatListViewController, chatroom: Chatroom) { + chatList.popToRootViewController(animated: false) + chatList.dismiss(animated: false, completion: nil) + tabbar.selectedIndex = 0 + + let vc = list.chatViewController(for: chatroom) + + if let split = list.splitViewController { + let chat = UINavigationController(rootViewController:vc) + split.showDetailViewController(chat, sender: self) + } else { + chatList.pushViewController(vc, animated: true) + } + } } @@ -530,9 +581,9 @@ extension AppDelegate { } // if not logged in - list.didLoadedMessages = { + list.didLoadedMessages = { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - self.openDialog(chatList: chatList, tabbar: tabbar, router: router, list: list, adamantAdr: adamantAdr) + self?.openDialog(chatList: chatList, tabbar: tabbar, router: router, list: list, adamantAdr: adamantAdr) } } } @@ -542,7 +593,7 @@ extension AppDelegate { return true } - func openDialog(chatList: UINavigationController, tabbar: UITabBarController, router: Router, list: ChatListViewController, adamantAdr: AdamantAddress){ + func openDialog(chatList: UINavigationController, tabbar: UITabBarController, router: Router, list: ChatListViewController, adamantAdr: AdamantAddress) { chatList.popToRootViewController(animated: false) chatList.dismiss(animated: false, completion: nil) tabbar.selectedIndex = 0 diff --git a/Adamant/CoreData/Chatroom+CoreDataClass.swift b/Adamant/CoreData/Chatroom+CoreDataClass.swift index ff4182fd7..8792884ad 100644 --- a/Adamant/CoreData/Chatroom+CoreDataClass.swift +++ b/Adamant/CoreData/Chatroom+CoreDataClass.swift @@ -15,13 +15,12 @@ public class Chatroom: NSManagedObject { static let entityName = "Chatroom" func markAsReaded() { - if hasUnreadMessages { - hasUnreadMessages = false - } - + hasUnreadMessages = false + if let trs = transactions as? Set { trs.filter { $0.isUnread }.forEach { $0.isUnread = false } } + lastTransaction?.isUnread = false } func getFirstUnread() -> ChatTransaction? { diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index 873208148..57bace107 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -52,6 +52,8 @@ class AdamantChatsProvider: ChatsProvider { private let markdownParser = MarkdownParser(font: UIFont.systemFont(ofSize: UIFont.systemFontSize)) + private var previousAppState: UIApplication.State? + // MARK: Lifecycle init() { NotificationCenter.default.addObserver(forName: Notification.Name.AdamantAccountService.userLoggedIn, object: nil, queue: nil) { [weak self] notification in @@ -109,6 +111,18 @@ class AdamantChatsProvider: ChatsProvider { } } } + + NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: OperationQueue.main) { [weak self] notification in + if let previousAppState = self?.previousAppState, + previousAppState == .background { + self?.previousAppState = .active + self?.update() + } + } + + NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: OperationQueue.main) { [weak self] notification in + self?.previousAppState = .background + } } deinit { @@ -250,7 +264,6 @@ extension AdamantChatsProvider { let processingGroup = DispatchGroup() let cms = DispatchSemaphore(value: 1) let prevHeight = receivedLastHeight - getTransactions(senderId: address, privateKey: privateKey, height: receivedLastHeight, offset: nil, dispatchGroup: processingGroup, context: privateContext, contextMutatingSemaphore: cms) // MARK: 4. Check @@ -743,7 +756,6 @@ extension AdamantChatsProvider { ]) let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: stack.container.viewContext, sectionNameKeyPath: nil, cacheName: nil) - return controller } @@ -1057,7 +1069,6 @@ extension AdamantChatsProvider { defer { contextMutatingSemaphore.signal() } - contextMutatingSemaphore.wait() try context.save() @@ -1073,7 +1084,6 @@ extension AdamantChatsProvider { } } - // MARK 7. Last message height highSemaphore.wait() if let lastHeight = receivedLastHeight { @@ -1083,7 +1093,6 @@ extension AdamantChatsProvider { } else { receivedLastHeight = height } - highSemaphore.signal() } } diff --git a/Adamant/Services/DataProviders/AdamantTransfersProvider.swift b/Adamant/Services/DataProviders/AdamantTransfersProvider.swift index 2555b6e06..e454b3136 100644 --- a/Adamant/Services/DataProviders/AdamantTransfersProvider.swift +++ b/Adamant/Services/DataProviders/AdamantTransfersProvider.swift @@ -923,7 +923,6 @@ extension AdamantTransfersProvider { self.receivedLastHeight = uH } } - // MARK: 5. Unread transactions if let unreadedHeight = readedLastHeight { let unreadTransactions = transfers.filter { !$0.isOutgoing && $0.height > unreadedHeight } diff --git a/Adamant/Services/SocketService/AdamantSocketService.swift b/Adamant/Services/SocketService/AdamantSocketService.swift index 475923556..f1ead1f1b 100644 --- a/Adamant/Services/SocketService/AdamantSocketService.swift +++ b/Adamant/Services/SocketService/AdamantSocketService.swift @@ -59,7 +59,8 @@ class AdamantSocketService: SocketService { socket?.on("newTrans", callback: { [weak self] data, ack in guard let data = data.first else { return } guard let dict = data as? [String: Any] else { return } - if let trans = try? JSONDecoder().decode(Transaction.self, from: JSONSerialization.data(withJSONObject: dict)) { + if let trans = try? JSONDecoder().decode(Transaction.self, from: JSONSerialization.data(withJSONObject: dict)), + trans.asset.chat?.type != .signal { self?.defaultResponseDispatchQueue.async { completion?(.success(trans)) } diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index 84b72e69d..e2291c969 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -447,13 +447,14 @@ extension ChatListViewController { } cell.hasUnreadMessages = chatroom.hasUnreadMessages - + if let lastTransaction = chatroom.lastTransaction { + cell.hasUnreadMessages = lastTransaction.isUnread cell.lastMessageLabel.attributedText = shortDescription(for: lastTransaction) } else { cell.lastMessageLabel.text = nil } - + if let date = chatroom.updatedAt as Date?, date != Date.adamantNullDate { cell.dateLabel.text = date.humanizedDay() } else { @@ -501,8 +502,8 @@ extension ChatListViewController: NSFetchedResultsControllerDelegate { case .update: if let indexPath = indexPath, - let cell = self.tableView.cellForRow(at: indexPath) as? ChatTableViewCell, - let chatroom = anObject as? Chatroom { + let cell = self.tableView.cellForRow(at: indexPath) as? ChatTableViewCell, + let chatroom = anObject as? Chatroom { configureCell(cell, for: chatroom) } @@ -524,7 +525,9 @@ extension ChatListViewController: NSFetchedResultsControllerDelegate { } if let transaction = anObject as? ChatTransaction { - showNotification(for: transaction) + if self.view.window == nil { + showNotification(for: transaction) + } } default: @@ -814,7 +817,7 @@ extension ChatListViewController { more.backgroundColor = UIColor.adamant.primary // Mark as read - if chatroom.hasUnreadMessages { + if chatroom.hasUnreadMessages || (chatroom.lastTransaction?.isUnread ?? false) { let markAsRead = UIContextualAction(style: .normal, title: nil) { [weak self] (_, _, completionHandler: (Bool) -> Void) in guard let chatroom = self?.chatsController?.object(at: indexPath) else { completionHandler(false) diff --git a/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift b/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift index a3b4299a3..12fed1773 100644 --- a/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift +++ b/Adamant/Wallets/Adamant/AdmTransactionsViewController.swift @@ -104,7 +104,6 @@ class AdmTransactionsViewController: TransactionsListViewControllerBase { guard let stack = stack else { return } - DispatchQueue.global(qos: .utility).async { let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) privateContext.parent = stack.container.viewContext From 943646550b8fa81db93bc250956b90ac7f354b47 Mon Sep 17 00:00:00 2001 From: StanislavDevIOS Date: Wed, 11 May 2022 14:54:30 +0300 Subject: [PATCH 6/6] Processing tap for push notification --- Adamant.xcodeproj/project.pbxproj | 32 +++++++++---------- Adamant/AppDelegate.swift | 32 ++++++++++++------- .../Chats/ChatListViewController.swift | 4 ++- .../Stories/Chats/ChatViewController.swift | 5 +++ 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 8c2040e7a..d66ff91d5 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -2897,7 +2897,7 @@ CODE_SIGN_ENTITLEMENTS = MessageNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2906,7 +2906,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.MessageNotificationContentExtension"; @@ -2926,7 +2926,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = MessageNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -2935,7 +2935,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.MessageNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3073,7 +3073,7 @@ CODE_SIGN_ENTITLEMENTS = Adamant/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = ADM.Dev; EXCLUDED_SOURCE_FILE_NAMES = ""; @@ -3083,7 +3083,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "e4233bbf-3705-44fe-95b0-e77475672c60"; @@ -3102,7 +3102,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; DISPLAY_NAME = Adamant; EXCLUDED_SOURCE_FILE_NAMES = Debug.xcassets; @@ -3112,7 +3112,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "bedd1b75-2f23-4a85-a0b2-14c424fcff42"; @@ -3130,7 +3130,7 @@ CODE_SIGN_ENTITLEMENTS = TransferNotificationContentExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3139,7 +3139,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.TransferNotificationContentExtension"; @@ -3159,7 +3159,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = TransferNotificationContentExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3168,7 +3168,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.TransferNotificationContentExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3188,7 +3188,7 @@ CODE_SIGN_ENTITLEMENTS = NotificationServiceExtension/Debug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3197,7 +3197,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger-dev.NotificationServiceExtension"; @@ -3217,7 +3217,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 176; + CURRENT_PROJECT_VERSION = 180; DEVELOPMENT_TEAM = J2L77FMN46; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 10.0; @@ -3226,7 +3226,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.3.3; + MARKETING_VERSION = 2.4.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "im.adamant.adamant-messenger.NotificationServiceExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index 12c934bc9..097d3b185 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -343,18 +343,19 @@ extension AppDelegate: UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { if let recipientAddress = userInfo[AdamantNotificationUserInfoKeys.pushRecipient] as? String { + if application.applicationState != .background && application.applicationState != .inactive { + completionHandler(.noData) + return + } + if let tabbar = window?.rootViewController as? UITabBarController, let chats = tabbar.viewControllers?.first as? UISplitViewController, let chatList = chats.viewControllers.first as? UINavigationController, let list = chatList.viewControllers.first as? ChatListViewController { - - guard let room = list.chatsController?.fetchedObjects?.first(where: { room in - return room.lastTransaction?.recipientAddress == recipientAddress - }) else { return } switch list.accountService.state { case .loggedIn: - self.openDialog(chatList: chatList, tabbar: tabbar, list: list, chatroom: room) + self.openDialog(chatList: chatList, tabbar: tabbar, list: list, recipientAddress: recipientAddress) case .notLogged: break case .isLoggingIn: @@ -366,7 +367,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate { // if not logged in list.didLoadedMessages = { [weak self] in DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - self?.openDialog(chatList: chatList, tabbar: tabbar, list: list, chatroom: room) + self?.openDialog(chatList: chatList, tabbar: tabbar, list: list, recipientAddress: recipientAddress) } } } @@ -376,18 +377,25 @@ extension AppDelegate: UNUserNotificationCenterDelegate { } } - func openDialog(chatList: UINavigationController, tabbar: UITabBarController, list: ChatListViewController, chatroom: Chatroom) { + func openDialog(chatList: UINavigationController, tabbar: UITabBarController, list: ChatListViewController, recipientAddress: String) { + guard let chatroom = list.chatsController?.fetchedObjects?.first(where: { room in + return room.lastTransaction?.recipientAddress == recipientAddress + }) else { return } + chatList.popToRootViewController(animated: false) chatList.dismiss(animated: false, completion: nil) tabbar.selectedIndex = 0 - let vc = list.chatViewController(for: chatroom) - + let vc = list.chatViewController(for: chatroom, forceScrollToBottom: true) if let split = list.splitViewController { - let chat = UINavigationController(rootViewController:vc) - split.showDetailViewController(chat, sender: self) + var timeout = 0.25 + if #available(iOS 13.0, *) { timeout = 0 } + DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { + let chat = UINavigationController(rootViewController:vc) + split.showDetailViewController(chat, sender: self) + } } else { - chatList.pushViewController(vc, animated: true) + chatList.pushViewController(vc, animated: false) } } } diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index e2291c969..0c0098801 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -219,7 +219,7 @@ class ChatListViewController: UIViewController { // MARK: Helpers - func chatViewController(for chatroom: Chatroom, with message: MessageTransaction? = nil) -> ChatViewController { + func chatViewController(for chatroom: Chatroom, with message: MessageTransaction? = nil, forceScrollToBottom: Bool = false) -> ChatViewController { guard let vc = router.get(scene: AdamantScene.Chats.chat) as? ChatViewController else { fatalError("Can't get ChatViewController") } @@ -232,6 +232,8 @@ class ChatListViewController: UIViewController { vc.messageToShow = message } + vc.forceScrollToBottom = forceScrollToBottom + vc.hidesBottomBarWhenPushed = true vc.chatroom = chatroom vc.delegate = self diff --git a/Adamant/Stories/Chats/ChatViewController.swift b/Adamant/Stories/Chats/ChatViewController.swift index 8d03098d8..55dd171f8 100644 --- a/Adamant/Stories/Chats/ChatViewController.swift +++ b/Adamant/Stories/Chats/ChatViewController.swift @@ -68,6 +68,7 @@ class ChatViewController: MessagesViewController { var account: AdamantAccount? var chatroom: Chatroom? var messageToShow: MessageTransaction? + var forceScrollToBottom: Bool? var dateFormatter: DateFormatter { let formatter = DateFormatter() formatter.dateStyle = .short @@ -505,6 +506,10 @@ class ChatViewController: MessagesViewController { scrollToBottomBtn.isHidden = chatPositionOffset < chatPositionDelata scrollToBottomBtnOffetConstraint?.constant = -20 - self.messageInputBar.bounds.height + + if forceScrollToBottom ?? false { + scrollDown() + } } override func viewDidDisappear(_ animated: Bool) {