From cdd3559282cb939195ea6ccabf654bf1e406411f Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Thu, 8 Nov 2018 20:50:57 +0200 Subject: [PATCH 01/38] Make `MQTTService` perform work in background thread. --- Nynja/Services/MQTT/MQTTService.swift | 41 ++++++++++--------- Nynja/Services/MQTT/MQTTServiceHelper.swift | 30 ++++++++------ .../Handlers/Base/HandlerService.swift | 1 - 3 files changed, 40 insertions(+), 32 deletions(-) diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 120020895..45ff69be5 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -26,23 +26,24 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate case disconnected } - var mqtt: CocoaMQTT? - static let version = Bundle.main.modelsVersion - let host = Host() + var mqtt: CocoaMQTT? var push: String? let deviceId = UIDevice.current.persistentIdentifier - - let semaphore = DispatchSemaphore(value: 1) + private let semaphore = DispatchSemaphore(value: 1) var wasRunApp: Bool = false typealias MQTTServiceSubscribers = [WeakRef] private var subscribers = MQTTServiceSubscribers() - private let subscribersQueue = DispatchQueue(label: "com.nynja.mobile.communicator.mqttservice.subscribers") + private let subscribersQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.subscribers-queue"), attributes: .concurrent) + + let loggingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.logging-queue")) + private let receivingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.receiving-queue"), qos: .utility) + let publishingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.publishing-queue"), qos: .utility) let showHandlers : Set = [] @@ -247,7 +248,9 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16 ) { printMessage(msg: message, isSent: false) - HandlerService.handle(response: message) + receivingQueue.async { [weak self] in + HandlerService.handle(response: message) + } } func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) { @@ -272,29 +275,30 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate // MARK: Subscribers func addSubscriber(_ subscriber: MQTTServiceDelegate) { - subscribersQueue.sync { - subscribers.append(WeakRef(value: subscriber)) + subscribersQueue.async(flags: .barrier) { [weak self] in + guard let `self` = self else { return } + self.subscribers.append(WeakRef(value: subscriber)) } } func removeSubscriber(_ subscriber: MQTTServiceDelegate) { - subscribersQueue.sync { - subscribers = subscribers.filter { $0.value !== subscriber } + subscribersQueue.async(flags: .barrier) { [weak self] in + guard let `self` = self else { return } + self.subscribers = self.subscribers.filter { $0.value !== subscriber } } } func removeAllSubscribers() { - subscribersQueue.sync { - subscribers.removeAll() + subscribersQueue.async(flags: .barrier) { [weak self] in + guard let `self` = self else { return } + self.subscribers.removeAll() } } - /* Notify all subscribers that reachbility status changed */ - private func notifySubscribers(with eventClosure: (MQTTServiceDelegate) -> Void) { - - subscribersQueue.sync { - subscribers.forEach { (weak) in + subscribersQueue.sync { [weak self] in + guard let `self` = self else { return } + self.subscribers.forEach { (weak) in if let delegate = weak.value as? MQTTServiceDelegate { eventClosure(delegate) } @@ -306,7 +310,6 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate // MARK: - ConnectionServiceDelegate func connectionStatusChanged(_ sender: ConnectionService, service: ConnectionService.Service, oldValue: ConnectionService.ConnectionServiceState) { - if service == .networking { guard let networkStatus = sender.state[.networking] else { return } switch networkStatus { diff --git a/Nynja/Services/MQTT/MQTTServiceHelper.swift b/Nynja/Services/MQTT/MQTTServiceHelper.swift index 41e228ac7..fd07ad5bd 100644 --- a/Nynja/Services/MQTT/MQTTServiceHelper.swift +++ b/Nynja/Services/MQTT/MQTTServiceHelper.swift @@ -12,23 +12,29 @@ import CocoaMQTT extension MQTTService { func publish(model: BaseMQTTModel) { - guard let mqtt = self.mqtt, mqtt.connState == .connected else { - return + publishingQueue.async { [weak self] in + guard let mqtt = self?.mqtt, mqtt.connState == .connected else { + return + } + + let finalModel: CocoaMQTTMessage = model.getMessage() + mqtt.publish(finalModel) } - - let finalModel: CocoaMQTTMessage = model.getMessage() - mqtt.publish(finalModel) } func printMessage(msg: CocoaMQTTMessage, isSent: Bool) { - let desc = self.prepareOutputMessage(msg: msg, isSent: isSent) - guard let bert = desc.1 as? BertTuple else { - return + loggingQueue.async { [weak self] in + guard let `self` = self else { return } + + let desc = self.prepareOutputMessage(msg: msg, isSent: isSent) + guard let bert = desc.1 as? BertTuple else { + return + } + + if self.shouldShowLog(for: bert) { + LogService.log(topic: .MQTT) { return desc.0 } + } } - - if shouldShowLog(for: bert) { - LogService.log(topic: .MQTT) { return desc.0 } - } } private func shouldShowLog(for bert: BertTuple) -> Bool { diff --git a/Shared/Services/Handlers/Base/HandlerService.swift b/Shared/Services/Handlers/Base/HandlerService.swift index 7d5c1fee4..efbb47e23 100644 --- a/Shared/Services/Handlers/Base/HandlerService.swift +++ b/Shared/Services/Handlers/Base/HandlerService.swift @@ -17,5 +17,4 @@ class HandlerService: HandlerServiceProtocol { let handlerType = HandlerFactory.handler(for: handler) handlerType.executeHandle(data: params) } - } -- GitLab From 1e24b64133ea95f06dc91407844c5b3f471f5c82 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Thu, 8 Nov 2018 20:56:03 +0200 Subject: [PATCH 02/38] Update `NotificationManager`: 1. Do preparation work in background thread. 2. Do UI related work in main thread. --- Nynja/NotificationManager.swift | 34 ++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/Nynja/NotificationManager.swift b/Nynja/NotificationManager.swift index 4059601d6..d1a6987a8 100644 --- a/Nynja/NotificationManager.swift +++ b/Nynja/NotificationManager.swift @@ -53,6 +53,10 @@ final class NotificationManager { // MARK: - Properties + private let processingQueue = DispatchQueue( + label: String.label(withSuffix: "notification-manager.processing-queue"), + qos: .utility) + private(set) var previousView: NotificationView? private(set) var typeForNavigate: InAppNotificationType? { @@ -107,7 +111,9 @@ final class NotificationManager { return } - handleNavigation(presenter: mainPresenter) + processingQueue.async { [weak self] in + self?.handleNavigation(presenter: mainPresenter) + } } @@ -138,10 +144,12 @@ final class NotificationManager { switch type { case .message: if let vc = self.getMessageVC { - DispatchQueue.main.async { - if self.isFromPush { - vc.navigationController?.popToRootViewController(animated: false) + dispatchAsyncMain { [weak self] in + guard let `self` = self, self.isFromPush else { + return } + + vc.navigationController?.popToRootViewController(animated: false) } } @@ -154,7 +162,6 @@ final class NotificationManager { navigateToHistory(presenter: presenter) case .friend(let requestType): navigateToFriend(presenter: presenter, requestType: requestType) - default: break } } @@ -205,7 +212,10 @@ final class NotificationManager { self.showNotificationView(view: view) } else { - presenter.wireFrame.showHistory() + let time = withDelay ? DispatchTime.now() + 0.3 : DispatchTime.now() + DispatchQueue.main.asyncAfter(deadline: time) { + presenter.wireFrame.showHistory() + } clean() } } @@ -356,9 +366,15 @@ final class NotificationManager { // MARK: - Show Notification View private func showNotificationView(view: NotificationView) { - previousView?.remove() - previousView = view - view.show(duration: 3) + dispatchAsyncMain { [weak self] in + guard let `self` = self else { + return + } + + self.previousView?.remove() + self.previousView = view + view.show(duration: 3) + } } // MARK: - Get Notification View -- GitLab From bda7150f929157dfd2cc097d062d825687703400 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 11:24:57 +0200 Subject: [PATCH 03/38] Make `AlertManager` present view controller on main thread. --- Nynja/Library/UI/AlertManager.swift | 53 ++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/Nynja/Library/UI/AlertManager.swift b/Nynja/Library/UI/AlertManager.swift index f0519ed17..c013d0aa9 100644 --- a/Nynja/Library/UI/AlertManager.swift +++ b/Nynja/Library/UI/AlertManager.swift @@ -19,13 +19,13 @@ class AlertManager { return UIApplication.shared.keyWindow?.presentedViewController } - func showAlertOk(title: String, message: String, completion:(()->Void)? = nil) { + func showAlertOk(title: String, message: String, completion: (()->Void)? = nil) { let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) let defaultAction = UIAlertAction(title: String.localizable.ok, style: .default) { (action) in completion?() } alert.addAction(defaultAction) - presentingController?.present(alert, animated: true, completion: nil) + present(alert, from: presentingController) } func showAlert(title: String, dismissInterval: TimeInterval) { @@ -33,7 +33,7 @@ class AlertManager { dispatchAsyncMainAfter(dismissInterval) { alert.dismiss(animated: true, completion: nil) } - presentingController?.present(alert, animated: true, completion: nil) + present(alert, from: presentingController) } func showAlertOk(message: String, completion:(()->Void)? = nil) { @@ -58,7 +58,7 @@ class AlertManager { textFieldConfig.map { alert.addTextField(configurationHandler: $0) } - presentingController?.present(alert, animated: true, completion: nil) + present(alert, from: presentingController) } func showAlertWithTwoActions(title: String, message: String, firstActionTitle: String, @@ -74,13 +74,14 @@ class AlertManager { alert.addAction(firstAlertAction) alert.addAction(secondAlertAction) - presentingController?.present(alert, animated: true, completion: nil) + present(alert, from: presentingController) } func showAlertWithThreeActions(title: String?, message: String?, firstActionTitle: String, secondActionTitle: String, thirdActionTitle: String, firstAction: Handler?, secondAction: Handler?, thirdAction: Handler?) { let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + let firstAlertAction = UIAlertAction(title: firstActionTitle, style: .default) { (action) in firstAction?() } @@ -90,11 +91,12 @@ class AlertManager { let thirdAlertAction = UIAlertAction(title: thirdActionTitle, style: .default) { (action) in thirdAction?() } + alert.addAction(firstAlertAction) alert.addAction(secondAlertAction) alert.addAction(thirdAlertAction) - presentingController?.present(alert, animated: true, completion: nil) + present(alert, from: presentingController) } func showAlertAllowPermission(title: String = "", @@ -144,8 +146,7 @@ class AlertManager { func showActionSheet(title: String?, message: String?, actions: [UIAlertAction]) { let alert = UIAlertController(title: title, message: message, preferredStyle: .actionSheet) actions.forEach { alert.addAction($0) } - - presentingController?.present(alert, animated: true, completion: nil) + present(alert, from: presentingController) } func linkMenu(open:(()->Void)? = nil, showInChat:(()->Void)? = nil, share:(()->Void)? = nil, cancel: (()->Void)? = nil) { @@ -218,21 +219,23 @@ class AlertManager { func showNativeShare(with activityItems: [Any]) { let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) - - presentingController?.present(activityViewController, animated: true, completion: nil) + present(activityViewController, from: presentingController) } } + // MARK: - No Internet connection + extension AlertManager { func showNoInternetConnection() { showAlertOk(message: String.localizable.noInternetConnection) } - } + // MARK: - AlertImageViewController + extension AlertManager { func showImageAlert(with image: UIImage?, message: String?, on viewController: UIViewController? = nil, duration: Double? = nil, completion: AlertImageViewController.DismissCompletion? = nil) { @@ -241,19 +244,35 @@ extension AlertManager { alertController.duration = duration alertController.completion = completion - if let viewController = viewController { - viewController.present(alertController, animated: true, completion: nil) - } else { - presentingController?.present(alertController, animated: true, completion: nil) - } + let presentingVC = viewController ?? presentingController + present(alertController, from: presentingVC) } } + //MARK: - TimeFieldViewController + extension AlertManager { + func showTimeFieldAlert(with initialValue: Int, completion: TimeCallback?) { let alertControler = AlertTextFieldViewController(initialValue: initialValue) alertControler.completion = completion - presentingController?.present(alertControler, animated: true, completion: nil) + present(alertControler, from: presentingController) + } +} + + +// MARK: - Private + +private extension AlertManager { + + func present(_ vc: UIViewController, from presentingVC: UIViewController?, animated: Bool = true) { + guard let presentingVC = presentingVC else { + return + } + + dispatchAsyncMain { + presentingVC.present(vc, animated: animated, completion: nil) + } } } -- GitLab From 3daad58d9b4c9c455c5e2e74707b8bcd3828b91c Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 12:50:36 +0200 Subject: [PATCH 04/38] Make `StorageService` thread safe. --- Nynja/MemberHandler.swift | 4 +- .../Services/HandleServices/RoomHandler.swift | 1 - Nynja/Services/StorageService.swift | 17 +++++- Nynja/StorageService+UserInfo.swift | 60 ++++++++++++------- Nynja/UserInfo.swift | 1 - 5 files changed, 57 insertions(+), 26 deletions(-) diff --git a/Nynja/MemberHandler.swift b/Nynja/MemberHandler.swift index 361d24a8b..2332ee5a9 100644 --- a/Nynja/MemberHandler.swift +++ b/Nynja/MemberHandler.swift @@ -23,9 +23,7 @@ class MemberHandler: BaseHandler { try? StorageService.sharedInstance.perform(action: .save, with: member) default: return - } - + } } - } diff --git a/Nynja/Services/HandleServices/RoomHandler.swift b/Nynja/Services/HandleServices/RoomHandler.swift index 6193bb931..29df69ebd 100644 --- a/Nynja/Services/HandleServices/RoomHandler.swift +++ b/Nynja/Services/HandleServices/RoomHandler.swift @@ -228,5 +228,4 @@ class RoomHandler: BaseHandler { oldRoom.readers = room.readers oldRoom.status = room.status } - } diff --git a/Nynja/Services/StorageService.swift b/Nynja/Services/StorageService.swift index d003ee29f..0d214a471 100644 --- a/Nynja/Services/StorageService.swift +++ b/Nynja/Services/StorageService.swift @@ -28,6 +28,10 @@ class StorageService { } #endif + let isolationQueue = DispatchQueue( + label: String.label(withSuffix: "storage-service.isolation-queue"), + attributes: .concurrent) + // MARK: - Properties lazy var countries: [CountryModel] = { @@ -48,6 +52,12 @@ class StorageService { // MARK: - Setup func setupDatabase(with name: String, application: UIApplication) { + isolationQueue.sync(flags: .barrier) { [weak self] in + self?._setupDatabase(with: name, application: application) + } + } + + private func _setupDatabase(with name: String, application: UIApplication) { #if !SHARE_EXTENSION LogService.log(topic: .db) { return "Setup DB: name = \(name)" } @@ -103,6 +113,12 @@ class StorageService { // MARK: - Clear func clearStorage() { + isolationQueue.sync(flags: .barrier) { [weak self] in + self?._clearStorage() + } + } + + private func _clearStorage() { #if !SHARE_EXTENSION databaseManager.clear() #endif @@ -145,6 +161,5 @@ extension StorageService: DBManagerProtocol { func perform(action: DatabaseAction, with models: [DBModelProtocol]) throws { try databaseManager.perform(action: action, with: models) } - } #endif diff --git a/Nynja/StorageService+UserInfo.swift b/Nynja/StorageService+UserInfo.swift index 2e7b6d7b5..e567eb45e 100644 --- a/Nynja/StorageService+UserInfo.swift +++ b/Nynja/StorageService+UserInfo.swift @@ -15,7 +15,7 @@ extension StorageService: UserInfo { } private var tokenData: Data? { - return userDefaults?.data(forKey: UserIdentifiers.token.rawValue) + return value(forId: .token) } var token: String? { @@ -25,15 +25,19 @@ extension StorageService: UserInfo { return token } set { - guard let token = newValue, let data = token.data(using: encoding) else { - userDefaults?.removeObject(forKey: UserIdentifiers.token.rawValue) - userDefaults?.synchronize() - return + isolationQueue.async(flags: .barrier) { [weak self] in + guard let `self` = self else { return } + + guard let token = newValue, let data = token.data(using: self.encoding) else { + self.userDefaults?.removeObject(forKey: UserIdentifiers.token.rawValue) + self.userDefaults?.synchronize() + return + } + + self.set(data as NSData, forId: .token, isAsync: false) + LogService.log(topic: .userDefaults) { return "Save token: \(token)" } + MQTTService.sharedInstance.reconnect() } - - set(data as NSData, forId: .token) - LogService.log(topic: .userDefaults) { return "Save token: \(token)" } - MQTTService.sharedInstance.reconnect() } } @@ -42,30 +46,27 @@ extension StorageService: UserInfo { } var phone: String? { - get { return userDefaults?.string(forKey: UserIdentifiers.phone.rawValue) } + get { return value(forId: .phone) } set { set(newValue, forId: .phone) } } var rosterId: Int64? { - get { - guard let id = userDefaults?.value(forKey: UserIdentifiers.rosterId.rawValue) as? Int64 else { return nil } - return id - } + get { return value(forId: .rosterId) } set { set(newValue, forId: .rosterId) } } var clientId: String? { - get { return userDefaults?.string(forKey: UserIdentifiers.clientId.rawValue) } + get { return value(forId: .clientId) } set { set(newValue, forId: .clientId) } } var wasLogined: Bool { - get { return userDefaults?.bool(forKey: UserIdentifiers.wasLogined.rawValue) ?? false } + get { return value(forId: .wasLogined) ?? false } set { set(newValue, forId: .wasLogined) } } var wasRun: Bool { - get { return userDefaults?.bool(forKey: UserIdentifiers.wasRun.rawValue) ?? false } + get { return value(forId: .wasRun) ?? false } set { set(newValue, forId: .wasRun) } } @@ -79,9 +80,28 @@ extension StorageService: UserInfo { rosterId = roster.id } - private func set(_ value: Any?, forId id: UserIdentifiers) { - userDefaults?.set(value, forKey: id.rawValue) - userDefaults?.synchronize() + private func value(forId id: UserIdentifiers) -> T? { + var value: T? + isolationQueue.sync { [weak self] in + value = self?.userDefaults?.value(forKey: id.rawValue) as? T + } + return value } + private func set(_ value: Any?, forId id: UserIdentifiers, isAsync: Bool = true) { + let set = { [weak self] (value: Any?, id: UserIdentifiers) in + guard let `self` = self else { return } + + self.userDefaults?.set(value, forKey: id.rawValue) + self.userDefaults?.synchronize() + } + + if isAsync { + isolationQueue.async { + set(value, id) + } + } else { + set(value, id) + } + } } diff --git a/Nynja/UserInfo.swift b/Nynja/UserInfo.swift index b54af5b57..50d70c707 100644 --- a/Nynja/UserInfo.swift +++ b/Nynja/UserInfo.swift @@ -61,5 +61,4 @@ extension UserInfo { rosterId = nil clientId = nil } - } -- GitLab From 7b78e556a6a8a8ef9f9ff56fdf68ef08320d4636 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 13:54:01 +0200 Subject: [PATCH 05/38] Call delegate methods in main thread for in `IoHandler`. --- Nynja/Services/MQTT/MQTTService.swift | 2 +- Shared/Services/Handlers/IoHandler.swift | 60 ++++++++++++------------ 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 45ff69be5..da49aa27c 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -175,7 +175,7 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate self.state = .notAuthenticated(isLoggedOutFromServer: true) - IoHandler.delegate?.sessionNotFound() + IoHandler.notify { $0.sessionNotFound() } notifySubscribers { (delegate) in delegate.mqttServiceDidReceiveAuthenticationFailure(self) } diff --git a/Shared/Services/Handlers/IoHandler.swift b/Shared/Services/Handlers/IoHandler.swift index f6fd64282..0ce08c23c 100644 --- a/Shared/Services/Handlers/IoHandler.swift +++ b/Shared/Services/Handlers/IoHandler.swift @@ -33,7 +33,6 @@ protocol IoHandlerDelegate: class { func contactQRNotFound() func contactByUsernameNotFound() func usernameIsBusy() - } extension IoHandlerDelegate { @@ -62,11 +61,9 @@ extension IoHandlerDelegate { func usernameIsBusy() {} func numberNotAllowed() {} - - } -class IoHandler:BaseHandler { +class IoHandler: BaseHandler { static weak var delegate: IoHandlerDelegate? @@ -78,10 +75,6 @@ class IoHandler:BaseHandler { return .sharedInstance } - static var keychainService: KeychainService { - return .standard - } - static func executeHandle(data: BertTuple) { if let IO = get_io().parse(bert: data) as? io { var code: String? = nil @@ -110,68 +103,68 @@ class IoHandler:BaseHandler { if let action = code { switch action { case "deleted": - self.delegate?.sessionDeleted() + notify { $0.sessionDeleted() } case "cleared": - self.delegate?.sessionsCleared() + notify { $0.sessionsCleared() } case "sms_sent": - self.delegate?.smsSent() + notify { $0.smsSent() } case "invalid_data": - self.delegate?.invalidData() + notify { $0.invalidData() } case "session_not_found": - self.delegate?.sessionNotFound() + notify { $0.sessionNotFound() } case "call_in_progress": - self.delegate?.callInProgress() + notify { $0.callInProgress() } case "login": StorageService.sharedInstance.wasLogined = true case "mismatch_user_data": - self.delegate?.mismatchUserData() + notify { $0.mismatchUserData() } case "invalid_sms_code": - self.delegate?.wrongCode() + notify { $0.wrongCode() } case "attempts_expired": - self.delegate?.attemptsExpired() + notify { $0.attemptsExpired() } case "number_not_allowed": - self.delegate?.numberNotAllowed() + notify { $0.numberNotAllowed() } case "logout": LogService.log(topic: .db) { return "Clear storage: IoHandler" } storageService.clearStorage() - + mqttService.state = .notAuthenticated(isLoggedOutFromServer: true) mqttService.disconnect() mqttService.reconnect() - self.delegate?.logout() + notify { $0.logout() } case "phone": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { - self.delegate?.getContactSuccess(contact: contact) + notify { $0.getContactSuccess(contact: contact) } } else { - self.delegate?.contactNotFound() + notify { $0.contactNotFound() } } } case "phonebook": if let roster = IO.data as? Roster { if let contacts = roster.userlist { - self.delegate?.getContactsSuccess(contacts: contacts) + notify { $0.getContactsSuccess(contacts: contacts) } } else { - self.delegate?.contactsNotFound() + notify { $0.contactsNotFound() } } } case "qrcode": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { - self.delegate?.getContactQRSuccess(contact: contact) + notify { $0.getContactQRSuccess(contact: contact) } } else { - self.delegate?.contactQRNotFound() + notify { $0.contactQRNotFound() } } } case "nick": - self.delegate?.usernameIsBusy() + notify { $0.usernameIsBusy() } case "username": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { - self.delegate?.getContactByUsernameSucces(contact: contact) + notify { $0.getContactByUsernameSucces(contact: contact) } } else { - self.delegate?.contactByUsernameNotFound() + notify { $0.contactByUsernameNotFound() } } } default: @@ -181,4 +174,13 @@ class IoHandler:BaseHandler { } } + static func notify(_ closure: (IoHandlerDelegate) -> Void) { + guard let delegate = self.delegate else { + return + } + + dispatchAsyncMain { + closure(delegate) + } + } } -- GitLab From 45b40f471de04eb512a9febdda34e673400a8c06 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 13:54:17 +0200 Subject: [PATCH 06/38] Update `ContactHandler`. --- Nynja/Services/HandleServices/ContactHandler.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Nynja/Services/HandleServices/ContactHandler.swift b/Nynja/Services/HandleServices/ContactHandler.swift index 8a6aa1cfe..cf29ea6ed 100644 --- a/Nynja/Services/HandleServices/ContactHandler.swift +++ b/Nynja/Services/HandleServices/ContactHandler.swift @@ -16,6 +16,10 @@ class ContactHandler: BaseHandler { return .sharedInstance } + static var notificationManager: NotificationManager { + return .shared + } + // MARK: - Handler @@ -79,7 +83,7 @@ class ContactHandler: BaseHandler { if [.request, .authorization, .ignore].contains(prevStatus) { let friendRequestType: InAppNotificationType.FriendRequestType = prevStatus == .request ? .outcoming : .incoming - NotificationManager.shared.handle(bert: data, + notificationManager.handle(bert: data, type: .friend(friendRequestType) ) } } catch { @@ -90,7 +94,7 @@ class ContactHandler: BaseHandler { private static func handleAuthorization(_ contact: Contact, data: BertTuple) { do { try storageService.perform(action: .save, with: contact) - NotificationManager.shared.handle(bert: data, type: .request) + notificationManager.handle(bert: data, type: .request) } catch { LogService.log(topic: .db) { return "Storage Service Error: can't save contact with status 'authorization'" } } -- GitLab From be16dea70cf49c2a7ad535f79715564a66461243 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 13:55:31 +0200 Subject: [PATCH 07/38] Rename `HistoryHandlerDelegate` as `HistoryHandlerSubscriber`. --- Nynja.xcodeproj/project.pbxproj | 26 ++++++++++++++++--- Nynja/HistoryHandlerSubscriber.swift | 21 +++++++++++++++ .../Interactor/MessageInteractor.swift | 4 +-- .../HandleServices/HistoryHandler.swift | 20 +++----------- .../MessageHandlerSubscriber.swift | 1 + Shared/Services/Handlers/ErrorsHandler.swift | 1 - 6 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 Nynja/HistoryHandlerSubscriber.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 614866c94..7fa5725a2 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -656,6 +656,7 @@ 4B877139219315AA0014AD09 /* SercerModelConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B877138219315AA0014AD09 /* SercerModelConvertible.swift */; }; 4B87713B219328780014AD09 /* QueryArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87713A219328780014AD09 /* QueryArgs.swift */; }; 4B87713E219350940014AD09 /* DBJobQueryArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87713D219350940014AD09 /* DBJobQueryArgs.swift */; }; + 4B8771782195AC5B0014AD09 /* HistoryHandlerSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8771772195AC5B0014AD09 /* HistoryHandlerSubscriber.swift */; }; 4B8996C8204ECE9B00DCB183 /* ContactDAO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8996C7204ECE9B00DCB183 /* ContactDAO.swift */; }; 4B8996CA204ECEA700DCB183 /* ContactDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8996C9204ECEA700DCB183 /* ContactDAOProtocol.swift */; }; 4B8996CD204ED33400DCB183 /* StarDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8996CC204ED33400DCB183 /* StarDAOProtocol.swift */; }; @@ -2938,6 +2939,7 @@ 4B877138219315AA0014AD09 /* SercerModelConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SercerModelConvertible.swift; sourceTree = ""; }; 4B87713A219328780014AD09 /* QueryArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryArgs.swift; sourceTree = ""; }; 4B87713D219350940014AD09 /* DBJobQueryArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBJobQueryArgs.swift; sourceTree = ""; }; + 4B8771772195AC5B0014AD09 /* HistoryHandlerSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryHandlerSubscriber.swift; sourceTree = ""; }; 4B8996C7204ECE9B00DCB183 /* ContactDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDAO.swift; sourceTree = ""; }; 4B8996C9204ECEA700DCB183 /* ContactDAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDAOProtocol.swift; sourceTree = ""; }; 4B8996CC204ED33400DCB183 /* StarDAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StarDAOProtocol.swift; sourceTree = ""; }; @@ -5938,14 +5940,13 @@ isa = PBXGroup; children = ( A497F56520EFA517005CC60F /* Base */, + 4B8771752195ABE80014AD09 /* MessageHandler */, + 4B8771762195AC3C0014AD09 /* HistoryHandler */, 265AEA141FE9AFA600AC4806 /* MemberHandler.swift */, 269666171FB57963009E41C1 /* RoomHandler.swift */, 3A771CA91F191B38008D968A /* ProfileHandler.swift */, - 3A19FEAC1F3B7F1D00ACE750 /* MessageHandler.swift */, - 855C9FE52125B4C0000E3429 /* MessageHandlerSubscriber.swift */, 3A2374D81F262A1600701045 /* ContactHandler.swift */, 3A237BCC1F30E5D400C42B6E /* RosterHandler.swift */, - 3A1EB9A41F3A848A00658E93 /* HistoryHandler.swift */, 260552A51F9E1CD100D68DE6 /* SearchHandler.swift */, 263D66321FE8D95100A509F8 /* TypingHandler.swift */, 26FA420F201821B400E6F6EC /* StarHandler.swift */, @@ -6991,6 +6992,24 @@ name = Entity; sourceTree = ""; }; + 4B8771752195ABE80014AD09 /* MessageHandler */ = { + isa = PBXGroup; + children = ( + 3A19FEAC1F3B7F1D00ACE750 /* MessageHandler.swift */, + 855C9FE52125B4C0000E3429 /* MessageHandlerSubscriber.swift */, + ); + name = MessageHandler; + sourceTree = ""; + }; + 4B8771762195AC3C0014AD09 /* HistoryHandler */ = { + isa = PBXGroup; + children = ( + 3A1EB9A41F3A848A00658E93 /* HistoryHandler.swift */, + 4B8771772195AC5B0014AD09 /* HistoryHandlerSubscriber.swift */, + ); + name = HistoryHandler; + sourceTree = ""; + }; 4B8996C6204ECE8500DCB183 /* Contact */ = { isa = PBXGroup; children = ( @@ -15343,6 +15362,7 @@ FEA656052167777F00B44029 /* WalletBalancesWallet.swift in Sources */, A45F112E20B4218D00F45004 /* MessageContentProtocol.swift in Sources */, 0008E9132032D5AC003E316E /* MQTTServiceSchedule.swift in Sources */, + 4B8771782195AC5B0014AD09 /* HistoryHandlerSubscriber.swift in Sources */, A432CF1A20B4347D00993AFB /* MaterialTextInput.swift in Sources */, B77C11E62109254800CCB42E /* InterpretationTypePresenter.swift in Sources */, B750EF062046D7C700A99F9C /* SpeedStringRepresentable.swift in Sources */, diff --git a/Nynja/HistoryHandlerSubscriber.swift b/Nynja/HistoryHandlerSubscriber.swift new file mode 100644 index 000000000..08580e950 --- /dev/null +++ b/Nynja/HistoryHandlerSubscriber.swift @@ -0,0 +1,21 @@ +// +// HistoryHandlerSubscriber.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +protocol HistoryHandlerSubscriber: class { + func getHistorySuccess() + func getJobsHistorySuccess() + func getStickerPacksSuccess() +} + +extension HistoryHandlerSubscriber { + func getHistorySuccess() {} + func getJobsHistorySuccess() {} + func getStickerPacksSuccess() {} +} diff --git a/Nynja/Modules/Message/Interactor/MessageInteractor.swift b/Nynja/Modules/Message/Interactor/MessageInteractor.swift index d455ff61b..686bad549 100644 --- a/Nynja/Modules/Message/Interactor/MessageInteractor.swift +++ b/Nynja/Modules/Message/Interactor/MessageInteractor.swift @@ -10,7 +10,7 @@ import UIKit import CoreLocation -final class MessageInteractor: BaseInteractor, MessageInteractorInputProtocol, HistoryHandlerDelegate, TypingHandlerDelegate, ConnectionServiceDelegate, MQTTServiceDelegate, MessageProcessingDelegate, MessageHandlerSubscriber, MessageInteractorCallProtocol { +final class MessageInteractor: BaseInteractor, MessageInteractorInputProtocol, HistoryHandlerSubscriber, TypingHandlerDelegate, ConnectionServiceDelegate, MQTTServiceDelegate, MessageProcessingDelegate, MessageHandlerSubscriber, MessageInteractorCallProtocol { private var callService = NynjaCommunicatorService.sharedInstance @@ -915,7 +915,7 @@ final class MessageInteractor: BaseInteractor, MessageInteractorInputProtocol, H } } - // MARK: - HistoryHandlerDelegate + // MARK: - HistoryHandlerSubscriber private var isNew = false private var isHistoryUpdating: Bool = false diff --git a/Nynja/Services/HandleServices/HistoryHandler.swift b/Nynja/Services/HandleServices/HistoryHandler.swift index 11d6bf824..4b8bb4a73 100644 --- a/Nynja/Services/HandleServices/HistoryHandler.swift +++ b/Nynja/Services/HandleServices/HistoryHandler.swift @@ -8,18 +8,6 @@ import Foundation -protocol HistoryHandlerDelegate: class { - func getHistorySuccess() - func getJobsHistorySuccess() - func getStickerPacksSuccess() -} - -extension HistoryHandlerDelegate { - func getHistorySuccess() {} - func getJobsHistorySuccess() {} - func getStickerPacksSuccess() {} -} - final class HistoryHandler: BaseHandler { // MARK: - Subscribers @@ -28,13 +16,13 @@ final class HistoryHandler: BaseHandler { private static var subscribers = [WeakRef]() - private static func notify(block: (HistoryHandlerDelegate) -> Void) { + private static func notify(block: (HistoryHandlerSubscriber) -> Void) { subscribersLock.lock() - subscribers.forEach { ($0.value as? HistoryHandlerDelegate).map { block($0) } } + subscribers.forEach { ($0.value as? HistoryHandlerSubscriber).map { block($0) } } subscribersLock.unlock() } - static func addSubscriber(_ subscriber: HistoryHandlerDelegate) { + static func addSubscriber(_ subscriber: HistoryHandlerSubscriber) { subscribersLock.lock() defer { subscribersLock.unlock() } @@ -45,7 +33,7 @@ final class HistoryHandler: BaseHandler { subscribers.append(ref) } - static func removeSubscriber(_ subscriber: HistoryHandlerDelegate) { + static func removeSubscriber(_ subscriber: HistoryHandlerSubscriber) { subscribersLock.lock() subscribers = subscribers.filter { $0.value != nil && $0.value !== subscriber } subscribersLock.unlock() diff --git a/Nynja/Services/HandleServices/MessageHandlerSubscriber.swift b/Nynja/Services/HandleServices/MessageHandlerSubscriber.swift index 35f8bf9ef..08e51eb72 100644 --- a/Nynja/Services/HandleServices/MessageHandlerSubscriber.swift +++ b/Nynja/Services/HandleServices/MessageHandlerSubscriber.swift @@ -10,6 +10,7 @@ protocol MessageHandlerSubscriber: class { func willSave(_ message: Message) func didSave(_ message: Message) } + extension MessageHandlerSubscriber { func willSave(_ message: Message) { } func didSave(_ message: Message) { } diff --git a/Shared/Services/Handlers/ErrorsHandler.swift b/Shared/Services/Handlers/ErrorsHandler.swift index d284a35cb..5465d1571 100644 --- a/Shared/Services/Handlers/ErrorsHandler.swift +++ b/Shared/Services/Handlers/ErrorsHandler.swift @@ -20,5 +20,4 @@ final class ErrorsHandler: BaseHandler { let handler = HandlerFactory.handler(for: handlerKind) handler.executeHandle(data: dataTuple, codes: Set(codes)) } - } -- GitLab From f59a346e60fb022dd17f3efc2392d0c857f207bc Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 13:55:43 +0200 Subject: [PATCH 08/38] Correct `IoHandler`. --- Shared/Services/Handlers/IoHandler.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shared/Services/Handlers/IoHandler.swift b/Shared/Services/Handlers/IoHandler.swift index 0ce08c23c..9700c7486 100644 --- a/Shared/Services/Handlers/IoHandler.swift +++ b/Shared/Services/Handlers/IoHandler.swift @@ -174,7 +174,7 @@ class IoHandler: BaseHandler { } } - static func notify(_ closure: (IoHandlerDelegate) -> Void) { + static func notify(_ closure: @escaping (IoHandlerDelegate) -> Void) { guard let delegate = self.delegate else { return } -- GitLab From c385770e4c85bde32c18f853a548d0b3decfa079 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 14:04:28 +0200 Subject: [PATCH 09/38] Make `NotificationManager` more thread safe. --- Nynja/NotificationManager.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Nynja/NotificationManager.swift b/Nynja/NotificationManager.swift index d1a6987a8..16778475e 100644 --- a/Nynja/NotificationManager.swift +++ b/Nynja/NotificationManager.swift @@ -120,8 +120,10 @@ final class NotificationManager { // MARK: - Handle BERT func handle(bert: BertTuple, type: InAppNotificationType) { - tupleForNavigate = bert - typeForNavigate = type + processingQueue.async { [weak self] in + self?.tupleForNavigate = bert + self?.typeForNavigate = type + } } @@ -443,7 +445,9 @@ final class NotificationManager { // MARK: - Clean func clean() { - self.typeForNavigate = nil - self.tupleForNavigate = nil + processingQueue.async { [weak self] in + self?.typeForNavigate = nil + self?.tupleForNavigate = nil + } } } -- GitLab From fdca9198f675696131fb0b48eab43c634fa6f1e4 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 14:23:21 +0200 Subject: [PATCH 10/38] Call delegate methods in main thread for in `TypingHandler `. --- Nynja.xcodeproj/project.pbxproj | 18 +++++++++++- .../HandleServices/SearchHandler.swift | 1 - .../HandleServices/TypingHandler.swift | 10 ++----- Nynja/TypingHandlerDelegate.swift | 13 +++++++++ Shared/Library/StaticDelegating.swift | 28 +++++++++++++++++++ 5 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 Nynja/TypingHandlerDelegate.swift create mode 100644 Shared/Library/StaticDelegating.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 7fa5725a2..27b2e4ca3 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -657,6 +657,8 @@ 4B87713B219328780014AD09 /* QueryArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87713A219328780014AD09 /* QueryArgs.swift */; }; 4B87713E219350940014AD09 /* DBJobQueryArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87713D219350940014AD09 /* DBJobQueryArgs.swift */; }; 4B8771782195AC5B0014AD09 /* HistoryHandlerSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8771772195AC5B0014AD09 /* HistoryHandlerSubscriber.swift */; }; + 4B87717B2195AF9D0014AD09 /* TypingHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87717A2195AF9D0014AD09 /* TypingHandlerDelegate.swift */; }; + 4B87717D2195AFF50014AD09 /* StaticDelegating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87717C2195AFF50014AD09 /* StaticDelegating.swift */; }; 4B8996C8204ECE9B00DCB183 /* ContactDAO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8996C7204ECE9B00DCB183 /* ContactDAO.swift */; }; 4B8996CA204ECEA700DCB183 /* ContactDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8996C9204ECEA700DCB183 /* ContactDAOProtocol.swift */; }; 4B8996CD204ED33400DCB183 /* StarDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8996CC204ED33400DCB183 /* StarDAOProtocol.swift */; }; @@ -2940,6 +2942,8 @@ 4B87713A219328780014AD09 /* QueryArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryArgs.swift; sourceTree = ""; }; 4B87713D219350940014AD09 /* DBJobQueryArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBJobQueryArgs.swift; sourceTree = ""; }; 4B8771772195AC5B0014AD09 /* HistoryHandlerSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryHandlerSubscriber.swift; sourceTree = ""; }; + 4B87717A2195AF9D0014AD09 /* TypingHandlerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypingHandlerDelegate.swift; sourceTree = ""; }; + 4B87717C2195AFF50014AD09 /* StaticDelegating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticDelegating.swift; sourceTree = ""; }; 4B8996C7204ECE9B00DCB183 /* ContactDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDAO.swift; sourceTree = ""; }; 4B8996C9204ECEA700DCB183 /* ContactDAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactDAOProtocol.swift; sourceTree = ""; }; 4B8996CC204ED33400DCB183 /* StarDAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StarDAOProtocol.swift; sourceTree = ""; }; @@ -5942,13 +5946,13 @@ A497F56520EFA517005CC60F /* Base */, 4B8771752195ABE80014AD09 /* MessageHandler */, 4B8771762195AC3C0014AD09 /* HistoryHandler */, + 4B8771792195AF7E0014AD09 /* TypingHandler */, 265AEA141FE9AFA600AC4806 /* MemberHandler.swift */, 269666171FB57963009E41C1 /* RoomHandler.swift */, 3A771CA91F191B38008D968A /* ProfileHandler.swift */, 3A2374D81F262A1600701045 /* ContactHandler.swift */, 3A237BCC1F30E5D400C42B6E /* RosterHandler.swift */, 260552A51F9E1CD100D68DE6 /* SearchHandler.swift */, - 263D66321FE8D95100A509F8 /* TypingHandler.swift */, 26FA420F201821B400E6F6EC /* StarHandler.swift */, 0008E91A20333A38003E316E /* JobHandler.swift */, 855EF424202CCADB00541BE3 /* ExtendedStarHandler.swift */, @@ -7010,6 +7014,15 @@ name = HistoryHandler; sourceTree = ""; }; + 4B8771792195AF7E0014AD09 /* TypingHandler */ = { + isa = PBXGroup; + children = ( + 4B87717A2195AF9D0014AD09 /* TypingHandlerDelegate.swift */, + 263D66321FE8D95100A509F8 /* TypingHandler.swift */, + ); + name = TypingHandler; + sourceTree = ""; + }; 4B8996C6204ECE8500DCB183 /* Contact */ = { isa = PBXGroup; children = ( @@ -10912,6 +10925,7 @@ A49E1BCA20A9A6880074DFD3 /* Library */ = { isa = PBXGroup; children = ( + 4B87717C2195AFF50014AD09 /* StaticDelegating.swift */, A4C92FFC20B323B600D6FB0F /* Extensions */, A49E1BCB20A9A68D0074DFD3 /* Models */, ); @@ -15575,6 +15589,7 @@ 2605311B212740FD002E1CF1 /* LogOutputProtocols.swift in Sources */, FBCE841420E525A6003B7558 /* NetworkService.swift in Sources */, A409B1CF2108D48E0051C20B /* QueryFactory.swift in Sources */, + 4B87717D2195AFF50014AD09 /* StaticDelegating.swift in Sources */, A42D52B7206A53AA00EEB952 /* reader_Spec.swift in Sources */, F119E66A20D24B960043A532 /* MultiplePreviewProtocols.swift in Sources */, 850FC611203312FA00832D87 /* ForwardSelectorViewControllerLayout.swift in Sources */, @@ -15698,6 +15713,7 @@ 26DCB2412064B9B1001EF0AB /* InviteFriendHeaderViewLayout.swift in Sources */, F105C6BB20A1347E0091786A /* PhotoPreviewPresenter.swift in Sources */, FEA655FA2167777F00B44029 /* TransferDetailsPresenter.swift in Sources */, + 4B87717B2195AF9D0014AD09 /* TypingHandlerDelegate.swift in Sources */, 8ED0F3CE1FBC5CF2004916AB /* GroupsListInteractor.swift in Sources */, 267BE2851FDE983400C47E18 /* SettingsGroupVC.swift in Sources */, 8580BAC720BD983400239D9D /* MentionFetchProtocols.swift in Sources */, diff --git a/Nynja/Services/HandleServices/SearchHandler.swift b/Nynja/Services/HandleServices/SearchHandler.swift index 9d8570b15..55acb374b 100644 --- a/Nynja/Services/HandleServices/SearchHandler.swift +++ b/Nynja/Services/HandleServices/SearchHandler.swift @@ -28,5 +28,4 @@ class SearchHandler: BaseHandler { break } } - } diff --git a/Nynja/Services/HandleServices/TypingHandler.swift b/Nynja/Services/HandleServices/TypingHandler.swift index e9023cba8..15b48900e 100644 --- a/Nynja/Services/HandleServices/TypingHandler.swift +++ b/Nynja/Services/HandleServices/TypingHandler.swift @@ -8,18 +8,12 @@ import Foundation -protocol TypingHandlerDelegate: class { - func getTyping(typing: Typing) -} - -class TypingHandler: BaseHandler { - +class TypingHandler: BaseHandler, StaticDelegating { static weak var delegate: TypingHandlerDelegate? static func executeHandle(data: BertTuple) { if let typing = get_Typing().parse(bert: data) as? Typing { - delegate?.getTyping(typing: typing) + delegate { $0.getTyping(typing: typing) } } } - } diff --git a/Nynja/TypingHandlerDelegate.swift b/Nynja/TypingHandlerDelegate.swift new file mode 100644 index 000000000..de1844d5f --- /dev/null +++ b/Nynja/TypingHandlerDelegate.swift @@ -0,0 +1,13 @@ +// +// TypingHandlerDelegate.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +protocol TypingHandlerDelegate: class { + func getTyping(typing: Typing) +} diff --git a/Shared/Library/StaticDelegating.swift b/Shared/Library/StaticDelegating.swift new file mode 100644 index 000000000..87d9661e1 --- /dev/null +++ b/Shared/Library/StaticDelegating.swift @@ -0,0 +1,28 @@ +// +// StaticDelegating.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +protocol StaticDelegating { + associatedtype Delegate + + static var delegate: Delegate? { get set } + + static func delegate(on queue: DispatchQueue, closure: @escaping (Delegate) -> Void) +} + +extension StaticDelegating { + + static func delegate(on queue: DispatchQueue = .main, closure: @escaping (Delegate) -> Void) { + guard let delegate = self.delegate else { + return + } + + queue.async { + closure(delegate) + } + } +} -- GitLab From 3f72354d768107f8428147a0f16303295a5f490f Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 14:33:19 +0200 Subject: [PATCH 11/38] Correct `TypingHandler`. --- Nynja.xcodeproj/project.pbxproj | 18 +++- .../HandleServices/TypingHandler.swift | 2 +- Nynja/Services/MQTT/MQTTService.swift | 2 +- Shared/Library/StaticDelegating.swift | 2 + .../Handlers/{ => IoHandler}/IoHandler.swift | 99 +++++-------------- .../IoHandler/IoHandlerDelegate.swift | 64 ++++++++++++ 6 files changed, 107 insertions(+), 80 deletions(-) rename Shared/Services/Handlers/{ => IoHandler}/IoHandler.swift (56%) create mode 100644 Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 27b2e4ca3..12dab44f0 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -560,6 +560,9 @@ 4B06D3202028A9B1003B275B /* P2pChatItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B06D31F2028A9B1003B275B /* P2pChatItemsFactory.swift */; }; 4B06D3222028A9C6003B275B /* GroupChatItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B06D3212028A9C6003B275B /* GroupChatItemsFactory.swift */; }; 4B06D3242028B209003B275B /* WCBaseItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B06D3232028B209003B275B /* WCBaseItemsFactory.swift */; }; + 4B0CC1FD2195B52000E0BA61 /* IoHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */; }; + 4B0CC1FE2195B52000E0BA61 /* IoHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */; }; + 4B0CC1FF2195B58000E0BA61 /* StaticDelegating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87717C2195AFF50014AD09 /* StaticDelegating.swift */; }; 4B1D7DFA2029BF3400703228 /* HistoryItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D7DF92029BF3400703228 /* HistoryItemsFactory.swift */; }; 4B1D7DFC2029C37900703228 /* FavoritesItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D7DFB2029C37900703228 /* FavoritesItemsFactory.swift */; }; 4B1D7DFE2029C41C00703228 /* AboutItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D7DFD2029C41C00703228 /* AboutItemsFactory.swift */; }; @@ -2858,6 +2861,7 @@ 4B06D31F2028A9B1003B275B /* P2pChatItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = P2pChatItemsFactory.swift; sourceTree = ""; }; 4B06D3212028A9C6003B275B /* GroupChatItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatItemsFactory.swift; sourceTree = ""; }; 4B06D3232028B209003B275B /* WCBaseItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WCBaseItemsFactory.swift; sourceTree = ""; }; + 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IoHandlerDelegate.swift; sourceTree = ""; }; 4B15A544CC681BABD1A631AF /* QRCodeGeneratorInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = QRCodeGeneratorInteractor.swift; sourceTree = ""; }; 4B1D7DF92029BF3400703228 /* HistoryItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItemsFactory.swift; sourceTree = ""; }; 4B1D7DFB2029C37900703228 /* FavoritesItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesItemsFactory.swift; sourceTree = ""; }; @@ -6600,6 +6604,15 @@ name = Chat; sourceTree = ""; }; + 4B0CC1FB2195B3C200E0BA61 /* IoHandler */ = { + isa = PBXGroup; + children = ( + 3A1DC73E1EF15B65006A8E9F /* IoHandler.swift */, + 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */, + ); + path = IoHandler; + sourceTree = ""; + }; 4B0DBA892137F6F800D79163 /* ChatService */ = { isa = PBXGroup; children = ( @@ -10980,8 +10993,8 @@ isa = PBXGroup; children = ( A497F56C20EFA86F005CC60F /* Base */, + 4B0CC1FB2195B3C200E0BA61 /* IoHandler */, A497F56D20EFA8B6005CC60F /* ErrorsHandler.swift */, - 3A1DC73E1EF15B65006A8E9F /* IoHandler.swift */, ); path = Handlers; sourceTree = ""; @@ -14612,6 +14625,7 @@ A42CE60420692EDB000889CC /* serviceTask_Spec.swift in Sources */, 264FFA981FC5917D0028243D /* WheelItemModel.swift in Sources */, 8503B51C20503B4B006F0593 /* NynjaCellButton.swift in Sources */, + 4B0CC1FE2195B52000E0BA61 /* IoHandlerDelegate.swift in Sources */, A4F3DAB32084949F00FF71C7 /* MessageExtension+BERT.swift in Sources */, 26B32B941FE20B9700888A0A /* mucExtension+BERT.swift in Sources */, A42CE5B620692EDB000889CC /* Room_Spec.swift in Sources */, @@ -14819,6 +14833,7 @@ A497F56E20EFA8B6005CC60F /* ErrorsHandler.swift in Sources */, 263D66311FE8D30200A509F8 /* TypingExtension+BERT.swift in Sources */, A42CE56220692EDB000889CC /* cur.swift in Sources */, + 4B0CC1FF2195B58000E0BA61 /* StaticDelegating.swift in Sources */, E7A77FDB1FACC58A004AE609 /* KeychainService.swift in Sources */, 85D669E720BD959800FBD803 /* Int+AnyObject.swift in Sources */, A42CE58420692EDB000889CC /* Vox.swift in Sources */, @@ -15019,6 +15034,7 @@ 3A1F74FA1F5ED344009A11E4 /* PushService.swift in Sources */, FEA656042167777F00B44029 /* WalletBalancesInteractor.swift in Sources */, 261F2E2E200EB0AD007D0813 /* RepliesVC+CellDelegate.swift in Sources */, + 4B0CC1FD2195B52000E0BA61 /* IoHandlerDelegate.swift in Sources */, A45F110620B4218D00F45004 /* MessageConfiguration.swift in Sources */, 26F5C8BE206BD49B003A7FF5 /* DefaultActionItemModel.swift in Sources */, 4B0213042037331100650298 /* ScheduleMessageViewControllerConstants.swift in Sources */, diff --git a/Nynja/Services/HandleServices/TypingHandler.swift b/Nynja/Services/HandleServices/TypingHandler.swift index 15b48900e..ce19b3bb3 100644 --- a/Nynja/Services/HandleServices/TypingHandler.swift +++ b/Nynja/Services/HandleServices/TypingHandler.swift @@ -8,7 +8,7 @@ import Foundation -class TypingHandler: BaseHandler, StaticDelegating { +final class TypingHandler: BaseHandler, StaticDelegating { static weak var delegate: TypingHandlerDelegate? static func executeHandle(data: BertTuple) { diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index da49aa27c..5ffe2ffb2 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -175,7 +175,7 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate self.state = .notAuthenticated(isLoggedOutFromServer: true) - IoHandler.notify { $0.sessionNotFound() } + IoHandler.delegate { $0.sessionNotFound() } notifySubscribers { (delegate) in delegate.mqttServiceDidReceiveAuthenticationFailure(self) } diff --git a/Shared/Library/StaticDelegating.swift b/Shared/Library/StaticDelegating.swift index 87d9661e1..39173973e 100644 --- a/Shared/Library/StaticDelegating.swift +++ b/Shared/Library/StaticDelegating.swift @@ -6,6 +6,8 @@ // Copyright © 2018 TecSynt Solutions. All rights reserved. // +import Foundation + protocol StaticDelegating { associatedtype Delegate diff --git a/Shared/Services/Handlers/IoHandler.swift b/Shared/Services/Handlers/IoHandler/IoHandler.swift similarity index 56% rename from Shared/Services/Handlers/IoHandler.swift rename to Shared/Services/Handlers/IoHandler/IoHandler.swift index 9700c7486..90565ee0e 100644 --- a/Shared/Services/Handlers/IoHandler.swift +++ b/Shared/Services/Handlers/IoHandler/IoHandler.swift @@ -8,62 +8,7 @@ import Foundation -protocol IoHandlerDelegate: class { - func smsSent() - func logined() - func wrongCode() - func mismatchUserData() - func sessionNotFound() - func attemptsExpired() - func notAuthorized() - func added() - func invalidData() - func callInProgress() - func logout() - func numberNotAllowed() - func sessionsCleared() - func sessionDeleted() - - func getContactSuccess(contact: Contact) - func getContactQRSuccess(contact: Contact) - func getContactByUsernameSucces(contact: Contact) - func getContactsSuccess(contacts: [Contact]) - func contactNotFound() - func contactsNotFound() - func contactQRNotFound() - func contactByUsernameNotFound() - func usernameIsBusy() -} - -extension IoHandlerDelegate { - func smsSent() {} - func logined() {} - func wrongCode() {} - func mismatchUserData() {} - func sessionNotFound() {} - func attemptsExpired() {} - func notAuthorized() {} - func added() {} - func invalidData() {} - func callInProgress() {} - func logout() {} - func sessionsCleared() {} - func sessionDeleted() {} - - func getContactSuccess(contact: Contact) {} - func getContactQRSuccess(contact: Contact) {} - func getContactByUsernameSucces(contact: Contact) {} - func getContactsSuccess(contacts: [Contact]) {} - func contactNotFound() {} - func contactsNotFound() {} - func contactQRNotFound() {} - func contactByUsernameNotFound() {} - - func usernameIsBusy() {} - func numberNotAllowed() {} -} - -class IoHandler: BaseHandler { +class IoHandler: BaseHandler, StaticDelegating { static weak var delegate: IoHandlerDelegate? @@ -103,27 +48,27 @@ class IoHandler: BaseHandler { if let action = code { switch action { case "deleted": - notify { $0.sessionDeleted() } + delegate { $0.sessionDeleted() } case "cleared": - notify { $0.sessionsCleared() } + delegate { $0.sessionsCleared() } case "sms_sent": - notify { $0.smsSent() } + delegate { $0.smsSent() } case "invalid_data": - notify { $0.invalidData() } + delegate { $0.invalidData() } case "session_not_found": - notify { $0.sessionNotFound() } + delegate { $0.sessionNotFound() } case "call_in_progress": - notify { $0.callInProgress() } + delegate { $0.callInProgress() } case "login": StorageService.sharedInstance.wasLogined = true case "mismatch_user_data": - notify { $0.mismatchUserData() } + delegate { $0.mismatchUserData() } case "invalid_sms_code": - notify { $0.wrongCode() } + delegate { $0.wrongCode() } case "attempts_expired": - notify { $0.attemptsExpired() } + delegate { $0.attemptsExpired() } case "number_not_allowed": - notify { $0.numberNotAllowed() } + delegate { $0.numberNotAllowed() } case "logout": LogService.log(topic: .db) { return "Clear storage: IoHandler" } storageService.clearStorage() @@ -132,39 +77,39 @@ class IoHandler: BaseHandler { mqttService.disconnect() mqttService.reconnect() - notify { $0.logout() } + delegate { $0.logout() } case "phone": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { - notify { $0.getContactSuccess(contact: contact) } + delegate { $0.getContactSuccess(contact: contact) } } else { - notify { $0.contactNotFound() } + delegate { $0.contactNotFound() } } } case "phonebook": if let roster = IO.data as? Roster { if let contacts = roster.userlist { - notify { $0.getContactsSuccess(contacts: contacts) } + delegate { $0.getContactsSuccess(contacts: contacts) } } else { - notify { $0.contactsNotFound() } + delegate { $0.contactsNotFound() } } } case "qrcode": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { - notify { $0.getContactQRSuccess(contact: contact) } + delegate { $0.getContactQRSuccess(contact: contact) } } else { - notify { $0.contactQRNotFound() } + delegate { $0.contactQRNotFound() } } } case "nick": - notify { $0.usernameIsBusy() } + delegate { $0.usernameIsBusy() } case "username": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { - notify { $0.getContactByUsernameSucces(contact: contact) } + delegate { $0.getContactByUsernameSucces(contact: contact) } } else { - notify { $0.contactByUsernameNotFound() } + delegate { $0.contactByUsernameNotFound() } } } default: @@ -174,7 +119,7 @@ class IoHandler: BaseHandler { } } - static func notify(_ closure: @escaping (IoHandlerDelegate) -> Void) { + static func delegate(_ closure: @escaping (IoHandlerDelegate) -> Void) { guard let delegate = self.delegate else { return } diff --git a/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift b/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift new file mode 100644 index 000000000..47393593b --- /dev/null +++ b/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift @@ -0,0 +1,64 @@ +// +// IoHandlerDelegate.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +protocol IoHandlerDelegate: class { + func smsSent() + func logined() + func wrongCode() + func mismatchUserData() + func sessionNotFound() + func attemptsExpired() + func notAuthorized() + func added() + func invalidData() + func callInProgress() + func logout() + func numberNotAllowed() + func sessionsCleared() + func sessionDeleted() + + func getContactSuccess(contact: Contact) + func getContactQRSuccess(contact: Contact) + func getContactByUsernameSucces(contact: Contact) + func getContactsSuccess(contacts: [Contact]) + func contactNotFound() + func contactsNotFound() + func contactQRNotFound() + func contactByUsernameNotFound() + func usernameIsBusy() +} + +extension IoHandlerDelegate { + func smsSent() {} + func logined() {} + func wrongCode() {} + func mismatchUserData() {} + func sessionNotFound() {} + func attemptsExpired() {} + func notAuthorized() {} + func added() {} + func invalidData() {} + func callInProgress() {} + func logout() {} + func sessionsCleared() {} + func sessionDeleted() {} + + func getContactSuccess(contact: Contact) {} + func getContactQRSuccess(contact: Contact) {} + func getContactByUsernameSucces(contact: Contact) {} + func getContactsSuccess(contacts: [Contact]) {} + func contactNotFound() {} + func contactsNotFound() {} + func contactQRNotFound() {} + func contactByUsernameNotFound() {} + + func usernameIsBusy() {} + func numberNotAllowed() {} +} -- GitLab From f63322b77ef864ed65ea1834160f9a3ac31dcfdc Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 14:37:54 +0200 Subject: [PATCH 12/38] Correct `IoHandler`. --- Shared/Services/Handlers/IoHandler/IoHandler.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shared/Services/Handlers/IoHandler/IoHandler.swift b/Shared/Services/Handlers/IoHandler/IoHandler.swift index 90565ee0e..61aa420c3 100644 --- a/Shared/Services/Handlers/IoHandler/IoHandler.swift +++ b/Shared/Services/Handlers/IoHandler/IoHandler.swift @@ -8,7 +8,7 @@ import Foundation -class IoHandler: BaseHandler, StaticDelegating { +final class IoHandler: BaseHandler, StaticDelegating { static weak var delegate: IoHandlerDelegate? -- GitLab From c7033c2b46a24bd479baddc212f5744f56a1de9d Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 15:10:15 +0200 Subject: [PATCH 13/38] Call delegate methods in main thread for in `LinkHandler`. --- Nynja.xcodeproj/project.pbxproj | 16 ++++++++++++++-- Nynja/LinkHandler.swift | 13 +++---------- Nynja/LinkHandlerDelegate.swift | 12 ++++++++++++ 3 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 Nynja/LinkHandlerDelegate.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 12dab44f0..ed3dc051e 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -563,6 +563,7 @@ 4B0CC1FD2195B52000E0BA61 /* IoHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */; }; 4B0CC1FE2195B52000E0BA61 /* IoHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */; }; 4B0CC1FF2195B58000E0BA61 /* StaticDelegating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87717C2195AFF50014AD09 /* StaticDelegating.swift */; }; + 4B0CC2022195B69900E0BA61 /* LinkHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CC2012195B69900E0BA61 /* LinkHandlerDelegate.swift */; }; 4B1D7DFA2029BF3400703228 /* HistoryItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D7DF92029BF3400703228 /* HistoryItemsFactory.swift */; }; 4B1D7DFC2029C37900703228 /* FavoritesItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D7DFB2029C37900703228 /* FavoritesItemsFactory.swift */; }; 4B1D7DFE2029C41C00703228 /* AboutItemsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D7DFD2029C41C00703228 /* AboutItemsFactory.swift */; }; @@ -2862,6 +2863,7 @@ 4B06D3212028A9C6003B275B /* GroupChatItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupChatItemsFactory.swift; sourceTree = ""; }; 4B06D3232028B209003B275B /* WCBaseItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WCBaseItemsFactory.swift; sourceTree = ""; }; 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IoHandlerDelegate.swift; sourceTree = ""; }; + 4B0CC2012195B69900E0BA61 /* LinkHandlerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkHandlerDelegate.swift; sourceTree = ""; }; 4B15A544CC681BABD1A631AF /* QRCodeGeneratorInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = QRCodeGeneratorInteractor.swift; sourceTree = ""; }; 4B1D7DF92029BF3400703228 /* HistoryItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItemsFactory.swift; sourceTree = ""; }; 4B1D7DFB2029C37900703228 /* FavoritesItemsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesItemsFactory.swift; sourceTree = ""; }; @@ -5951,6 +5953,7 @@ 4B8771752195ABE80014AD09 /* MessageHandler */, 4B8771762195AC3C0014AD09 /* HistoryHandler */, 4B8771792195AF7E0014AD09 /* TypingHandler */, + 4B0CC2002195B67D00E0BA61 /* LinkHandler */, 265AEA141FE9AFA600AC4806 /* MemberHandler.swift */, 269666171FB57963009E41C1 /* RoomHandler.swift */, 3A771CA91F191B38008D968A /* ProfileHandler.swift */, @@ -5961,7 +5964,6 @@ 0008E91A20333A38003E316E /* JobHandler.swift */, 855EF424202CCADB00541BE3 /* ExtendedStarHandler.swift */, 00E9825B205FD351008BF03D /* AuthHandler.swift */, - A48C154320EF7A15002DA994 /* LinkHandler.swift */, ); name = Handlers; sourceTree = ""; @@ -6613,6 +6615,15 @@ path = IoHandler; sourceTree = ""; }; + 4B0CC2002195B67D00E0BA61 /* LinkHandler */ = { + isa = PBXGroup; + children = ( + A48C154320EF7A15002DA994 /* LinkHandler.swift */, + 4B0CC2012195B69900E0BA61 /* LinkHandlerDelegate.swift */, + ); + name = LinkHandler; + sourceTree = ""; + }; 4B0DBA892137F6F800D79163 /* ChatService */ = { isa = PBXGroup; children = ( @@ -7030,8 +7041,8 @@ 4B8771792195AF7E0014AD09 /* TypingHandler */ = { isa = PBXGroup; children = ( - 4B87717A2195AF9D0014AD09 /* TypingHandlerDelegate.swift */, 263D66321FE8D95100A509F8 /* TypingHandler.swift */, + 4B87717A2195AF9D0014AD09 /* TypingHandlerDelegate.swift */, ); name = TypingHandler; sourceTree = ""; @@ -16345,6 +16356,7 @@ A43B25D720AB1EE400FF8107 /* NewChannelWireFrame.swift in Sources */, A4166F5C205FE3670008F231 /* JobService.swift in Sources */, 26F03C0D20698B0000712CB0 /* ChatWheelItemModel.swift in Sources */, + 4B0CC2022195B69900E0BA61 /* LinkHandlerDelegate.swift in Sources */, E4F62F7771D4BB7FE3B48FA2 /* VideoPreviewProtocols.swift in Sources */, FBD8857A2147F9640099B8C3 /* AssetsConstants.swift in Sources */, 8580BAEC20BD9A7100239D9D /* LinkRecognizable.swift in Sources */, diff --git a/Nynja/LinkHandler.swift b/Nynja/LinkHandler.swift index feebe3ae1..620ad386d 100644 --- a/Nynja/LinkHandler.swift +++ b/Nynja/LinkHandler.swift @@ -6,13 +6,7 @@ // Copyright © 2018 TecSynt Solutions. All rights reserved. // -protocol LinkHandlerDelegate: class { - func generatedLink(_ link: Link) - func linkIsAvailable(_ link: Link) -} - - -final class LinkHandler: BaseHandler { +final class LinkHandler: BaseHandler, StaticDelegating { static weak var delegate: LinkHandlerDelegate? @@ -35,9 +29,9 @@ final class LinkHandler: BaseHandler { switch status { case .check: - delegate?.linkIsAvailable(link) + delegate { $0.linkIsAvailable(link) } case .gen: - delegate?.generatedLink(link) + delegate { $0.generatedLink(link) } case .add, .delete, .update: // TODO: will be implemented in future. break @@ -51,5 +45,4 @@ final class LinkHandler: BaseHandler { .filter { StatusCode.linkCodes.contains($0) } .forEach { statusCodeManager.notify(model: link, code: $0) } } - } diff --git a/Nynja/LinkHandlerDelegate.swift b/Nynja/LinkHandlerDelegate.swift new file mode 100644 index 000000000..dd65b2588 --- /dev/null +++ b/Nynja/LinkHandlerDelegate.swift @@ -0,0 +1,12 @@ +// +// LinkHandlerDelegate.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +protocol LinkHandlerDelegate: class { + func generatedLink(_ link: Link) + func linkIsAvailable(_ link: Link) +} -- GitLab From 45789b297759920779910e8d57ec68c81be36726 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 15:23:54 +0200 Subject: [PATCH 14/38] Call delegate methods in main thread for in `AuthHandler`. --- Nynja.xcodeproj/project.pbxproj | 26 ++++++++++++++----- .../Handlers/AuthHandler}/AuthHandler.swift | 24 +++++++---------- .../AuthHandler/AuthHandlerDelegate.swift | 19 ++++++++++++++ 3 files changed, 48 insertions(+), 21 deletions(-) rename {Nynja => Shared/Services/Handlers/AuthHandler}/AuthHandler.swift (59%) create mode 100644 Shared/Services/Handlers/AuthHandler/AuthHandlerDelegate.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index ed3dc051e..277c808fd 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -64,9 +64,7 @@ 00E98254205C2726008BF03D /* SessionFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E98253205C2726008BF03D /* SessionFooterView.swift */; }; 00E98256205C2740008BF03D /* SessionItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E98255205C2740008BF03D /* SessionItemCell.swift */; }; 00E9825A205FC324008BF03D /* SessionDescView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E98259205FC324008BF03D /* SessionDescView.swift */; }; - 00E9825C205FD351008BF03D /* AuthHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E9825B205FD351008BF03D /* AuthHandler.swift */; }; 00E9825E205FDB1A008BF03D /* AuthExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E9825D205FDB1A008BF03D /* AuthExtension.swift */; }; - 00E9825F205FE86E008BF03D /* AuthHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00E9825B205FD351008BF03D /* AuthHandler.swift */; }; 00EB7872206E286A00E3FB03 /* WCReusableViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00EB7871206E286A00E3FB03 /* WCReusableViews.swift */; }; 00EDCA0D202B7243000928D4 /* TimeZoneSelectorDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00EDCA0C202B7243000928D4 /* TimeZoneSelectorDS.swift */; }; 00F7B33E2029DD4B00E443E1 /* AudioItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00F7B33D2029DD4B00E443E1 /* AudioItemView.swift */; }; @@ -542,6 +540,10 @@ 45F60C4B14438C65076457AB /* EditUsernameProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83894D517BFF22637F2878B7 /* EditUsernameProtocols.swift */; }; 4B02130220372C5700650298 /* OtherItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B02130120372C5700650298 /* OtherItemView.swift */; }; 4B0213042037331100650298 /* ScheduleMessageViewControllerConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0213032037331100650298 /* ScheduleMessageViewControllerConstants.swift */; }; + 4B030F2D2195BFF300F293B7 /* AuthHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */; }; + 4B030F2E2195BFF300F293B7 /* AuthHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */; }; + 4B030F2F2195BFF300F293B7 /* AuthHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */; }; + 4B030F302195BFF300F293B7 /* AuthHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */; }; 4B052CB0203614D400BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B052CB12036193900BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B058F03204EA928004C7D9F /* DAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F02204EA928004C7D9F /* DAOProtocol.swift */; }; @@ -2455,7 +2457,6 @@ 00E98253205C2726008BF03D /* SessionFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionFooterView.swift; sourceTree = ""; }; 00E98255205C2740008BF03D /* SessionItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionItemCell.swift; sourceTree = ""; }; 00E98259205FC324008BF03D /* SessionDescView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionDescView.swift; sourceTree = ""; }; - 00E9825B205FD351008BF03D /* AuthHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthHandler.swift; sourceTree = ""; }; 00E9825D205FDB1A008BF03D /* AuthExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthExtension.swift; sourceTree = ""; }; 00EB7871206E286A00E3FB03 /* WCReusableViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WCReusableViews.swift; sourceTree = ""; }; 00EBF72D0964E3EC64F5B966 /* SplashProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SplashProtocols.swift; sourceTree = ""; }; @@ -2842,6 +2843,8 @@ 499373C9A81A05B77308A5F0 /* AddContactByUsernameProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddContactByUsernameProtocols.swift; sourceTree = ""; }; 4B02130120372C5700650298 /* OtherItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherItemView.swift; sourceTree = ""; }; 4B0213032037331100650298 /* ScheduleMessageViewControllerConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleMessageViewControllerConstants.swift; sourceTree = ""; }; + 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthHandlerDelegate.swift; sourceTree = ""; }; + 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthHandler.swift; sourceTree = ""; }; 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAtomExtension.swift; sourceTree = ""; }; 4B058EFD204EA751004C7D9F /* ProfileDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDAO.swift; sourceTree = ""; }; 4B058F00204EA7F5004C7D9F /* DBManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBManagerProtocol.swift; sourceTree = ""; }; @@ -5963,7 +5966,6 @@ 26FA420F201821B400E6F6EC /* StarHandler.swift */, 0008E91A20333A38003E316E /* JobHandler.swift */, 855EF424202CCADB00541BE3 /* ExtendedStarHandler.swift */, - 00E9825B205FD351008BF03D /* AuthHandler.swift */, ); name = Handlers; sourceTree = ""; @@ -6474,6 +6476,15 @@ path = DateTime; sourceTree = ""; }; + 4B030F2A2195BFF300F293B7 /* AuthHandler */ = { + isa = PBXGroup; + children = ( + 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */, + 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */, + ); + path = AuthHandler; + sourceTree = ""; + }; 4B058EF9204EA6EE004C7D9F /* DB */ = { isa = PBXGroup; children = ( @@ -11005,6 +11016,7 @@ children = ( A497F56C20EFA86F005CC60F /* Base */, 4B0CC1FB2195B3C200E0BA61 /* IoHandler */, + 4B030F2A2195BFF300F293B7 /* AuthHandler */, A497F56D20EFA8B6005CC60F /* ErrorsHandler.swift */, ); path = Handlers; @@ -14709,7 +14721,6 @@ 4BF090CD21635FED00DCCA5C /* Message+Type.swift in Sources */, 26A856222074C4F000C642EA /* ActionsView+Layout.swift in Sources */, 266AE8C42034971A0096A12C /* AsyncOperation.swift in Sources */, - 00E9825F205FE86E008BF03D /* AuthHandler.swift in Sources */, 359EB27C1F9A2C8C00147437 /* MQTTServiceHelper.swift in Sources */, 4B5A0B74216E3BDD002C4160 /* ForwardAvatarViewModel.swift in Sources */, A4B544F020EFB4EC00EB7B0F /* BertTupleExtension.swift in Sources */, @@ -14822,6 +14833,7 @@ 8551CF0F2170857300829CF1 /* Message+Construct.swift in Sources */, A42CE57620692EDB000889CC /* push.swift in Sources */, A42CE55020692EDB000889CC /* Feature.swift in Sources */, + 4B030F302195BFF300F293B7 /* AuthHandler.swift in Sources */, 35B1AB831F9FB0DD00E65233 /* AmazonManager.swift in Sources */, 26B32B911FE20B7A00888A0A /* p2pExtension+BERT.swift in Sources */, 262D438820335225002F1E45 /* FriendRequstModel.swift in Sources */, @@ -14946,6 +14958,7 @@ 4B8AB705215CE52300C69DE1 /* SequenceExtension.swift in Sources */, 26C0C1EF2073DE2600C530DA /* ForwardSelectorProtocols+ShareExt.swift in Sources */, 26A8563A20750B5D00C642EA /* ScheduleInfo.swift in Sources */, + 4B030F2E2195BFF300F293B7 /* AuthHandlerDelegate.swift in Sources */, A45F115420B4224100F45004 /* RoomExtension.swift in Sources */, 26C0C1DC2073D94E00C530DA /* P2pExtension.swift in Sources */, 4B5A0B73216E3BDD002C4160 /* ActionsView.swift in Sources */, @@ -15821,6 +15834,7 @@ 8572C3BB2092366100E4840C /* StickerCollectionDataSource.swift in Sources */, E735853D1F6C2705003354B5 /* Geometry.swift in Sources */, 85B0013421272694000C89FE /* MessageInteractor+History.swift in Sources */, + 4B030F2F2195BFF300F293B7 /* AuthHandler.swift in Sources */, F119E67720D27E990043A532 /* ImagePreviewCVCell.swift in Sources */, 260313A720A0A4BA009AC66D /* ChatLanguageSettingsTableDataSource.swift in Sources */, 260313A520A0A4BA009AC66D /* BaseCell.swift in Sources */, @@ -16196,6 +16210,7 @@ FEA655DD2167777E00B44029 /* WalletDetailsProtocols.swift in Sources */, A43B259820AB1DFA00FF8107 /* TextInputContent.swift in Sources */, E723FD221F9E59A600E0B602 /* ProfileSection.swift in Sources */, + 4B030F2D2195BFF300F293B7 /* AuthHandlerDelegate.swift in Sources */, 4B752B652163A64300E852B9 /* Desc+Place.swift in Sources */, 8524C4D22177713C003BF374 /* Member+Status.swift in Sources */, E77D58A01F98C38100FBE926 /* ProfileSectionHeaderView.swift in Sources */, @@ -16650,7 +16665,6 @@ C02DD71CA3832908D422B83C /* CreateGroupWireframe.swift in Sources */, A45F110E20B4218D00F45004 /* PositionType.swift in Sources */, 26EEA5472091F84E0066D3B0 /* CollectionsExtensions.swift in Sources */, - 00E9825C205FD351008BF03D /* AuthHandler.swift in Sources */, 1CCEA1165C5D016C6768E5DC /* GroupRulesProtocols.swift in Sources */, 6B13E514036AA364CE2AC038 /* GroupRulesViewController.swift in Sources */, A4330A712109EBB30060BD93 /* CountriesProviding.swift in Sources */, diff --git a/Nynja/AuthHandler.swift b/Shared/Services/Handlers/AuthHandler/AuthHandler.swift similarity index 59% rename from Nynja/AuthHandler.swift rename to Shared/Services/Handlers/AuthHandler/AuthHandler.swift index c5ec8f5f2..ef1dd76f4 100644 --- a/Nynja/AuthHandler.swift +++ b/Shared/Services/Handlers/AuthHandler/AuthHandler.swift @@ -8,26 +8,20 @@ import Foundation -protocol AuthHandlerDelegate: class { - func processGetAll(auths: [Auth]) - func processDelete(auth: Auth) -} - -extension AuthHandlerDelegate { - func processGetAll(auths: [Auth]) {} - func processDelete(auth: Auth) {} -} - -class AuthHandler: BaseHandler { +final class AuthHandler: BaseHandler, StaticDelegating { static weak var delegate: AuthHandlerDelegate? static func executeHandle(data: BertTuple) { - guard let auth = get_Auth().parse(bert: data) as? Auth else {return} - guard let type = StringAtom.string(auth.type) else {return} + guard let auth = get_Auth().parse(bert: data) as? Auth, + let type = StringAtom.string(auth.type) else { + return + } + if type == "deleted" { - delegate?.processDelete(auth: auth) + delegate { $0.processDelete(auth: auth) } } + if auth.type?.string == "update" { LogService.log(topic: .MQTT) { return "Recived new token: \(auth.token ?? "")" } if let token = auth.token { @@ -38,6 +32,6 @@ class AuthHandler: BaseHandler { static func executeHandle(data: BertList) { let auths = data.elements.compactMap { get_Auth().parse(bert: $0) as? Auth } - delegate?.processGetAll(auths: auths) + delegate { $0.processGetAll(auths: auths) } } } diff --git a/Shared/Services/Handlers/AuthHandler/AuthHandlerDelegate.swift b/Shared/Services/Handlers/AuthHandler/AuthHandlerDelegate.swift new file mode 100644 index 000000000..aa6944289 --- /dev/null +++ b/Shared/Services/Handlers/AuthHandler/AuthHandlerDelegate.swift @@ -0,0 +1,19 @@ +// +// AuthHandlerDelegate.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +protocol AuthHandlerDelegate: class { + func processGetAll(auths: [Auth]) + func processDelete(auth: Auth) +} + +extension AuthHandlerDelegate { + func processGetAll(auths: [Auth]) {} + func processDelete(auth: Auth) {} +} -- GitLab From 7ed1b0228c7a93c2db8ba3761b3f0c8150b22554 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 15:30:12 +0200 Subject: [PATCH 15/38] Make small refactoring in handlers. --- Nynja/ExtendedStarHandler.swift | 1 - Nynja/JobHandler.swift | 3 +-- Nynja/Services/HandleServices/ContactHandler.swift | 4 +--- Nynja/Services/HandleServices/ProfileHandler.swift | 2 +- Nynja/Services/HandleServices/RoomHandler.swift | 2 +- Nynja/Services/HandleServices/RosterHandler.swift | 4 +--- Nynja/Services/HandleServices/SearchHandler.swift | 4 +--- Nynja/Services/HandleServices/StarHandler.swift | 8 +++++--- 8 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Nynja/ExtendedStarHandler.swift b/Nynja/ExtendedStarHandler.swift index 0322062f2..4ea3c670b 100644 --- a/Nynja/ExtendedStarHandler.swift +++ b/Nynja/ExtendedStarHandler.swift @@ -24,5 +24,4 @@ final class ExtendedStarHandler: BaseHandler { try? StorageService.sharedInstance.perform(action: .save, with: stars) } - } diff --git a/Nynja/JobHandler.swift b/Nynja/JobHandler.swift index cbf72bb79..0ea1a1720 100644 --- a/Nynja/JobHandler.swift +++ b/Nynja/JobHandler.swift @@ -6,7 +6,7 @@ // Copyright © 2018 TecSynt Solutions. All rights reserved. // -class JobHandler: BaseHandler { +final class JobHandler: BaseHandler { static func executeHandle(data: BertTuple) { guard let job = get_Job().parse(bert: data) as? Job, @@ -23,6 +23,5 @@ class JobHandler: BaseHandler { break } } - } diff --git a/Nynja/Services/HandleServices/ContactHandler.swift b/Nynja/Services/HandleServices/ContactHandler.swift index cf29ea6ed..42104e794 100644 --- a/Nynja/Services/HandleServices/ContactHandler.swift +++ b/Nynja/Services/HandleServices/ContactHandler.swift @@ -6,9 +6,7 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -import Foundation - -class ContactHandler: BaseHandler { +final class ContactHandler: BaseHandler { // MARK: - Dependencies diff --git a/Nynja/Services/HandleServices/ProfileHandler.swift b/Nynja/Services/HandleServices/ProfileHandler.swift index d3a900ce3..1c32e9f90 100644 --- a/Nynja/Services/HandleServices/ProfileHandler.swift +++ b/Nynja/Services/HandleServices/ProfileHandler.swift @@ -6,7 +6,7 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -class ProfileHandler: BaseHandler { +final class ProfileHandler: BaseHandler { // MARK: - Dependencies diff --git a/Nynja/Services/HandleServices/RoomHandler.swift b/Nynja/Services/HandleServices/RoomHandler.swift index 29df69ebd..f935f5d98 100644 --- a/Nynja/Services/HandleServices/RoomHandler.swift +++ b/Nynja/Services/HandleServices/RoomHandler.swift @@ -6,7 +6,7 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -class RoomHandler: BaseHandler { +final class RoomHandler: BaseHandler { // MARK: - Dependencies diff --git a/Nynja/Services/HandleServices/RosterHandler.swift b/Nynja/Services/HandleServices/RosterHandler.swift index 51ac27f17..ea054dddd 100644 --- a/Nynja/Services/HandleServices/RosterHandler.swift +++ b/Nynja/Services/HandleServices/RosterHandler.swift @@ -6,9 +6,7 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -import Foundation - -class RosterHandler: BaseHandler { +final class RosterHandler: BaseHandler { static func executeHandle(data: BertTuple) { guard let roster = get_Roster().parse(bert: data) as? Roster, diff --git a/Nynja/Services/HandleServices/SearchHandler.swift b/Nynja/Services/HandleServices/SearchHandler.swift index 55acb374b..5889095bd 100644 --- a/Nynja/Services/HandleServices/SearchHandler.swift +++ b/Nynja/Services/HandleServices/SearchHandler.swift @@ -6,9 +6,7 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -import Foundation - -class SearchHandler: BaseHandler { +final class SearchHandler: BaseHandler { static func executeHandle(data: BertTuple) { guard let search = get_Search().parse(bert: data) as? Search, diff --git a/Nynja/Services/HandleServices/StarHandler.swift b/Nynja/Services/HandleServices/StarHandler.swift index 416651962..22d335905 100644 --- a/Nynja/Services/HandleServices/StarHandler.swift +++ b/Nynja/Services/HandleServices/StarHandler.swift @@ -6,12 +6,14 @@ // Copyright © 2018 TecSynt Solutions. All rights reserved. // -class StarHandler: BaseHandler { +final class StarHandler: BaseHandler { static func executeHandle(data: BertTuple) { - guard let star = get_Star().parse(bert: data) as? Star, let status = star.starStatus else { - return + guard let star = get_Star().parse(bert: data) as? Star, + let status = star.starStatus else { + return } + do { switch status { case .add: -- GitLab From ab838cdfdd68e8b712a54998f05896ac11e3f7a2 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 16:33:48 +0200 Subject: [PATCH 16/38] Refactor `Aps`. --- Nynja/Services/Aps.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Nynja/Services/Aps.swift b/Nynja/Services/Aps.swift index 371112e55..dc39a64b1 100644 --- a/Nynja/Services/Aps.swift +++ b/Nynja/Services/Aps.swift @@ -56,7 +56,7 @@ struct Aps { self.contact = contact self.room = room - self.isValidIp = (nyn.dns == MQTTService.sharedInstance.host.url) + self.isValidIp = (nyn.dns == Host().url) self.isValidVersion = (NynjaPush.validVersion(version: nyn.version)) self.shouldNotify = NynjaPush.shouldNotify(room: room, contact: contact) @@ -238,7 +238,7 @@ extension Aps { static func validVersion(version: String) -> Bool { guard let versionString = version.components(separatedBy: "/").last, let version = Int(versionString) else { return false } - return version == MQTTService.version + return version == Bundle.main.modelsVersion } static func getContact(model: String) -> Contact? { -- GitLab From f2f881a4e7352f6645ecdb64ead136cf60393c5b Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 16:33:59 +0200 Subject: [PATCH 17/38] Refactor `PushService`. --- Nynja/Services/PushService.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Nynja/Services/PushService.swift b/Nynja/Services/PushService.swift index 91c423ae4..5ec5a47a0 100644 --- a/Nynja/Services/PushService.swift +++ b/Nynja/Services/PushService.swift @@ -12,6 +12,10 @@ import UserNotifications final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondable { + private var storageService: StorageService { + return .sharedInstance + } + static let sharedInstance: PushService = { let instance = PushService() instance.registerForPushNotifications() @@ -52,7 +56,7 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab @objc(pushRegistry:didReceiveIncomingPushWithPayload:forType:) func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) { - guard MQTTService.sharedInstance.isAuthenticated, + guard storageService.hasToken, UIApplication.shared.applicationState != .active, let aps = Aps(data: payload.dictionaryPayload), aps.isValidIp, @@ -214,7 +218,7 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab message.localStatus = status } try MessageDAO.trustIfNextMessageExists(before: message) - try StorageService.sharedInstance.perform(action: .save, with: message) + try storageService.perform(action: .save, with: message) } private func getMessage(_ aps: Aps) -> Message? { @@ -252,7 +256,7 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab if let lastMessage = contact.last_msg { try prepareForSave(message: lastMessage) } - try StorageService.sharedInstance.perform(action: .save, with: contact) + try storageService.perform(action: .save, with: contact) } catch { LogService.log(topic: .db) { return error.localizedDescription } } @@ -263,7 +267,7 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab if let lastMessage = room.last_msg { try prepareForSave(message: lastMessage) } - try StorageService.sharedInstance.perform(action: .save, with: room) + try storageService.perform(action: .save, with: room) } catch { LogService.log(topic: .db) { return error.localizedDescription } } -- GitLab From 0d05a31afd520b157a459209f2a00663fcb78c2b Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 16:34:13 +0200 Subject: [PATCH 18/38] Refactor `SplashViewController`. --- .../Modules/Splash/View/SplashViewController.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Nynja/Modules/Splash/View/SplashViewController.swift b/Nynja/Modules/Splash/View/SplashViewController.swift index 5ad891dfd..43a74e7c4 100644 --- a/Nynja/Modules/Splash/View/SplashViewController.swift +++ b/Nynja/Modules/Splash/View/SplashViewController.swift @@ -16,7 +16,9 @@ class SplashViewController: BaseVC, SplashViewProtocol { } } + // MARK: - Views + lazy var splash: UIView = { let launchScreen = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController() if let launchView = launchScreen?.view { @@ -40,7 +42,7 @@ class SplashViewController: BaseVC, SplashViewProtocol { let lbl = UILabel() lbl.font = UIFont(name: FontFamily.NotoSans.bold.name, size: 16)! lbl.numberOfLines = 0 - lbl.textColor = UIColor.nynja.manatee //UIColor.nynja.almostBlack + lbl.textColor = UIColor.nynja.manatee self.view.addSubview(lbl) lbl.snp.makeConstraints({ (make) in @@ -50,16 +52,15 @@ class SplashViewController: BaseVC, SplashViewProtocol { return lbl }() + // MARK: - View lifecycle + override func viewDidLoad() { super.viewDidLoad() self.view.frame = UIScreen.main.bounds splash.isHidden = false - if let dict = Bundle.main.infoDictionary { - if let buildV = dict["CFBundleVersion"] as? String { - let host = MQTTService.sharedInstance.host - info.text = "Build: \(buildV)"//" \nServer: \(host) (\"\(host.url)\")" - } + if let buildVersion = Bundle.main.buildVersion { + info.text = "Build: \(buildVersion)" } } -- GitLab From fcb24e05cb5837ebdf28d9233ea811da6d8fbda4 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 16:59:45 +0200 Subject: [PATCH 19/38] Refactor `MQTTService` and connected modules. --- Nynja.xcodeproj/project.pbxproj | 70 +++- .../Main/Interactor/MainInteractor.swift | 5 - Nynja/Modules/Main/MainProtocols.swift | 1 - .../Main/Presenter/MainPresenter.swift | 1 - .../MQTT/{ => API}/MQTTServiceAuth.swift | 8 +- .../MQTT/{ => API}/MQTTServiceChat.swift | 0 .../MQTT/{ => API}/MQTTServiceFriend.swift | 0 .../MQTT/{ => API}/MQTTServiceLink.swift | 0 .../MQTT/{ => API}/MQTTServiceProfile.swift | 0 .../MQTT/{ => API}/MQTTServiceSchedule.swift | 0 .../MQTT/{ => API}/MQTTServiceStars.swift | 0 .../MQTT/{ => API}/MQTTServiceWallet.swift | 0 Nynja/Services/MQTT/Entities/Host.swift | 19 ++ .../MQTTService+Helper.swift} | 15 +- .../Extensions/MQTTService+QueuePool.swift | 28 ++ Nynja/Services/MQTT/MQTTService.swift | 309 ++++++++---------- Nynja/Services/MQTT/MQTTServiceDelegate.swift | 23 ++ Nynja/Services/PushService.swift | 7 +- Nynja/StorageService+UserInfo.swift | 5 + Nynja/UserInfo.swift | 4 + .../Handlers/IoHandler/IoHandler.swift | 2 - 21 files changed, 276 insertions(+), 221 deletions(-) rename Nynja/Services/MQTT/{ => API}/MQTTServiceAuth.swift (95%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceChat.swift (100%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceFriend.swift (100%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceLink.swift (100%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceProfile.swift (100%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceSchedule.swift (100%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceStars.swift (100%) rename Nynja/Services/MQTT/{ => API}/MQTTServiceWallet.swift (100%) create mode 100644 Nynja/Services/MQTT/Entities/Host.swift rename Nynja/Services/MQTT/{MQTTServiceHelper.swift => Extensions/MQTTService+Helper.swift} (80%) create mode 100644 Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift create mode 100644 Nynja/Services/MQTT/MQTTServiceDelegate.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 277c808fd..91aef5bb2 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -468,7 +468,7 @@ 359EB23D1F9A1BE600147437 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D91F60E18E00AED866 /* Queue.swift */; }; 359EB2571F9A1E5000147437 /* BaseMQTTModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A62B7D71F4CB9D100F45B51 /* BaseMQTTModel.swift */; }; 359EB27B1F9A28C500147437 /* MessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 359EB27A1F9A28C500147437 /* MessageHandler.swift */; }; - 359EB27C1F9A2C8C00147437 /* MQTTServiceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D71F60C98200AED866 /* MQTTServiceHelper.swift */; }; + 359EB27C1F9A2C8C00147437 /* MQTTService+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D71F60C98200AED866 /* MQTTService+Helper.swift */; }; 359EB2831F9A2E6A00147437 /* ProfileHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 359EB2821F9A2E6A00147437 /* ProfileHandler.swift */; }; 359EB2841F9A6F2300147437 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6D36F8E41F0ADBD300FA1AC8 /* Localizable.strings */; }; 35B1AB821F9FB06500E65233 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35B1AB811F9FB06500E65233 /* Attachment.swift */; }; @@ -517,7 +517,7 @@ 3A8045D31F60C8E200AED866 /* MQTTServiceProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045CF1F60C8E200AED866 /* MQTTServiceProfile.swift */; }; 3A8045D41F60C8E200AED866 /* MQTTServiceAuth.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D01F60C8E200AED866 /* MQTTServiceAuth.swift */; }; 3A8045D61F60C93D00AED866 /* MQTTServiceChat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D51F60C93D00AED866 /* MQTTServiceChat.swift */; }; - 3A8045D81F60C98200AED866 /* MQTTServiceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D71F60C98200AED866 /* MQTTServiceHelper.swift */; }; + 3A8045D81F60C98200AED866 /* MQTTService+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D71F60C98200AED866 /* MQTTService+Helper.swift */; }; 3A8045DA1F60E18E00AED866 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A8045D91F60E18E00AED866 /* Queue.swift */; }; 3AA13C761F2252F900BE5D8F /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA13C751F2252F900BE5D8F /* SearchModel.swift */; }; 3AA4E6ACDBCB060172A7A279 /* FavoritesProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 462440AD41D807CE8957FDD9 /* FavoritesProtocols.swift */; }; @@ -544,6 +544,12 @@ 4B030F2E2195BFF300F293B7 /* AuthHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */; }; 4B030F2F2195BFF300F293B7 /* AuthHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */; }; 4B030F302195BFF300F293B7 /* AuthHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */; }; + 4B030F322195CD4500F293B7 /* MQTTServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F312195CD4500F293B7 /* MQTTServiceDelegate.swift */; }; + 4B030F332195CD4500F293B7 /* MQTTServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F312195CD4500F293B7 /* MQTTServiceDelegate.swift */; }; + 4B030F362195CD9B00F293B7 /* MQTTService+QueuePool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F352195CD9B00F293B7 /* MQTTService+QueuePool.swift */; }; + 4B030F372195CD9B00F293B7 /* MQTTService+QueuePool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F352195CD9B00F293B7 /* MQTTService+QueuePool.swift */; }; + 4B030F3B2195CF8100F293B7 /* Host.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3A2195CF8100F293B7 /* Host.swift */; }; + 4B030F3C2195CF8100F293B7 /* Host.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3A2195CF8100F293B7 /* Host.swift */; }; 4B052CB0203614D400BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B052CB12036193900BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B058F03204EA928004C7D9F /* DAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F02204EA928004C7D9F /* DAOProtocol.swift */; }; @@ -2812,7 +2818,7 @@ 3A8045CF1F60C8E200AED866 /* MQTTServiceProfile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MQTTServiceProfile.swift; sourceTree = ""; }; 3A8045D01F60C8E200AED866 /* MQTTServiceAuth.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MQTTServiceAuth.swift; sourceTree = ""; }; 3A8045D51F60C93D00AED866 /* MQTTServiceChat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MQTTServiceChat.swift; sourceTree = ""; }; - 3A8045D71F60C98200AED866 /* MQTTServiceHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MQTTServiceHelper.swift; sourceTree = ""; }; + 3A8045D71F60C98200AED866 /* MQTTService+Helper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MQTTService+Helper.swift"; sourceTree = ""; }; 3A8045D91F60E18E00AED866 /* Queue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Queue.swift; path = Library/Queue.swift; sourceTree = ""; }; 3A8C12DDFD0D831F21959665 /* Pods-Nynja-Share.devautotests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nynja-Share.devautotests.xcconfig"; path = "Pods/Target Support Files/Pods-Nynja-Share/Pods-Nynja-Share.devautotests.xcconfig"; sourceTree = ""; }; 3AA13C751F2252F900BE5D8F /* SearchModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = ""; }; @@ -2845,6 +2851,9 @@ 4B0213032037331100650298 /* ScheduleMessageViewControllerConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleMessageViewControllerConstants.swift; sourceTree = ""; }; 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthHandlerDelegate.swift; sourceTree = ""; }; 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthHandler.swift; sourceTree = ""; }; + 4B030F312195CD4500F293B7 /* MQTTServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTServiceDelegate.swift; sourceTree = ""; }; + 4B030F352195CD9B00F293B7 /* MQTTService+QueuePool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MQTTService+QueuePool.swift"; sourceTree = ""; }; + 4B030F3A2195CF8100F293B7 /* Host.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Host.swift; sourceTree = ""; }; 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAtomExtension.swift; sourceTree = ""; }; 4B058EFD204EA751004C7D9F /* ProfileDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDAO.swift; sourceTree = ""; }; 4B058F00204EA7F5004C7D9F /* DBManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBManagerProtocol.swift; sourceTree = ""; }; @@ -6081,16 +6090,11 @@ 3A8045CC1F60C8E200AED866 /* MQTT */ = { isa = PBXGroup; children = ( - FBCE83D420E52396003B7558 /* MQTTServiceWallet.swift */, + 4B030F392195CF7600F293B7 /* Entities */, + 4B030F342195CD4A00F293B7 /* API */, + 4B030F382195CDDA00F293B7 /* Extensions */, 3A8045CD1F60C8E200AED866 /* MQTTService.swift */, - 3A8045D71F60C98200AED866 /* MQTTServiceHelper.swift */, - 3A8045D51F60C93D00AED866 /* MQTTServiceChat.swift */, - 3A8045CE1F60C8E200AED866 /* MQTTServiceFriend.swift */, - 3A8045CF1F60C8E200AED866 /* MQTTServiceProfile.swift */, - 3A8045D01F60C8E200AED866 /* MQTTServiceAuth.swift */, - 0008E9122032D5AC003E316E /* MQTTServiceSchedule.swift */, - 855EF422202CC85300541BE3 /* MQTTServiceStars.swift */, - A48C153E20EF765E002DA994 /* MQTTServiceLink.swift */, + 4B030F312195CD4500F293B7 /* MQTTServiceDelegate.swift */, ); name = MQTT; path = Services/MQTT; @@ -6485,6 +6489,38 @@ path = AuthHandler; sourceTree = ""; }; + 4B030F342195CD4A00F293B7 /* API */ = { + isa = PBXGroup; + children = ( + FBCE83D420E52396003B7558 /* MQTTServiceWallet.swift */, + 3A8045D51F60C93D00AED866 /* MQTTServiceChat.swift */, + 3A8045CE1F60C8E200AED866 /* MQTTServiceFriend.swift */, + 3A8045CF1F60C8E200AED866 /* MQTTServiceProfile.swift */, + 3A8045D01F60C8E200AED866 /* MQTTServiceAuth.swift */, + 0008E9122032D5AC003E316E /* MQTTServiceSchedule.swift */, + 855EF422202CC85300541BE3 /* MQTTServiceStars.swift */, + A48C153E20EF765E002DA994 /* MQTTServiceLink.swift */, + ); + path = API; + sourceTree = ""; + }; + 4B030F382195CDDA00F293B7 /* Extensions */ = { + isa = PBXGroup; + children = ( + 3A8045D71F60C98200AED866 /* MQTTService+Helper.swift */, + 4B030F352195CD9B00F293B7 /* MQTTService+QueuePool.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + 4B030F392195CF7600F293B7 /* Entities */ = { + isa = PBXGroup; + children = ( + 4B030F3A2195CF8100F293B7 /* Host.swift */, + ); + path = Entities; + sourceTree = ""; + }; 4B058EF9204EA6EE004C7D9F /* DB */ = { isa = PBXGroup; children = ( @@ -14721,7 +14757,7 @@ 4BF090CD21635FED00DCCA5C /* Message+Type.swift in Sources */, 26A856222074C4F000C642EA /* ActionsView+Layout.swift in Sources */, 266AE8C42034971A0096A12C /* AsyncOperation.swift in Sources */, - 359EB27C1F9A2C8C00147437 /* MQTTServiceHelper.swift in Sources */, + 359EB27C1F9A2C8C00147437 /* MQTTService+Helper.swift in Sources */, 4B5A0B74216E3BDD002C4160 /* ForwardAvatarViewModel.swift in Sources */, A4B544F020EFB4EC00EB7B0F /* BertTupleExtension.swift in Sources */, 4BF090CF2163601400DCCA5C /* Message+LinkedId.swift in Sources */, @@ -14762,6 +14798,7 @@ A42CE5E820692EDB000889CC /* Auth_Spec.swift in Sources */, A415132320DBD5C100C2C01F /* Link_Spec.swift in Sources */, A42CE5C620692EDB000889CC /* reader_Spec.swift in Sources */, + 4B030F372195CD9B00F293B7 /* MQTTService+QueuePool.swift in Sources */, 359EB2831F9A2E6A00147437 /* ProfileHandler.swift in Sources */, A42CE5A820692EDB000889CC /* Star.swift in Sources */, A42CE5C020692EDB000889CC /* ok_Spec.swift in Sources */, @@ -14770,6 +14807,7 @@ A42CE59420692EDB000889CC /* Tag.swift in Sources */, A42CE5A020692EDB000889CC /* ok.swift in Sources */, 267D465720AB45E200D42242 /* Customizable.swift in Sources */, + 4B030F332195CD4500F293B7 /* MQTTServiceDelegate.swift in Sources */, A42CE60820692EDB000889CC /* task_Spec.swift in Sources */, A43B25B220AB1E2600FF8107 /* ImagePlaceholderField.swift in Sources */, A43B25B120AB1E1B00FF8107 /* NynjaSearchField.swift in Sources */, @@ -14785,6 +14823,7 @@ A42CE5B020692EDB000889CC /* TypeSpec.swift in Sources */, 26B32B971FE20BB500888A0A /* DescExtension+BERT.swift in Sources */, A42CE54220692EDA000889CC /* muc.swift in Sources */, + 4B030F3C2195CF8100F293B7 /* Host.swift in Sources */, 2611CEF82182090900FFD4DD /* LogWriterProtocol.swift in Sources */, A45F115620B4226600F45004 /* RawRepresentable+Localized.swift in Sources */, 4BD53BF4202C8BCA00569C1A /* AVURLAsset+Duration.swift in Sources */, @@ -15015,7 +15054,7 @@ 4B1D7E112029FF5000703228 /* Array+WheelItemModel.swift in Sources */, A46C36342121999100172773 /* DDMechanism.swift in Sources */, 854A4B302080D6C400759152 /* CellWithImageTableViewCell.swift in Sources */, - 3A8045D81F60C98200AED866 /* MQTTServiceHelper.swift in Sources */, + 3A8045D81F60C98200AED866 /* MQTTService+Helper.swift in Sources */, 8E9601971FF2EC8100E0C21D /* GroupFilesListVC.swift in Sources */, 4B06D3222028A9C6003B275B /* GroupChatItemsFactory.swift in Sources */, A4F3DABE2084990C00FF71C7 /* Roster+DB.swift in Sources */, @@ -15876,6 +15915,7 @@ A94B03A70E016BDA759B0703 /* EditProfileViewController.swift in Sources */, 8562853920D166E5000C9739 /* CollectionPreviewState.swift in Sources */, 4B7C73F2215A5509007924DB /* MotionManager.swift in Sources */, + 4B030F322195CD4500F293B7 /* MQTTServiceDelegate.swift in Sources */, F11786BB20A8A63F007A9A1B /* CoordinatorProtocol.swift in Sources */, F105C6BE20A1347E0091786A /* PhotoPreviewInteractor.swift in Sources */, F18AEAFD20C15792004FE01C /* SelectAvatarCoordinator.swift in Sources */, @@ -16431,6 +16471,7 @@ C99D6CD77325A09D045DB760 /* FavoritesViewController.swift in Sources */, 00E98256205C2740008BF03D /* SessionItemCell.swift in Sources */, 85D77807211D9B980044E72F /* ScrollPosition.swift in Sources */, + 4B030F362195CD9B00F293B7 /* MQTTService+QueuePool.swift in Sources */, FEA655F22167777E00B44029 /* PaymentWireFrame.swift in Sources */, DF55CCC682DAB5392F2A763D /* FavoritesPresenter.swift in Sources */, 4BDDAAEB218CA2C700F775A7 /* HomeDataProviderImpl.swift in Sources */, @@ -16699,6 +16740,7 @@ 260313AB20A0A4BA009AC66D /* ChatLanguageSettingsInteractor.swift in Sources */, 7C51CDC1260CE191C07EE46C /* SelectCountryViewController.swift in Sources */, 8596CEF22048A763006FC65D /* ThemeCellModel.swift in Sources */, + 4B030F3B2195CF8100F293B7 /* Host.swift in Sources */, 8566772020C1924500DD4204 /* MessageInteractor+MessageHandlerSubscriber.swift in Sources */, A1AD6864F4F49D9FC8997D59 /* SelectCountryPresenter.swift in Sources */, 32E5A25AD25BF752EB3864AB /* SelectCountryInteractor.swift in Sources */, diff --git a/Nynja/Modules/Main/Interactor/MainInteractor.swift b/Nynja/Modules/Main/Interactor/MainInteractor.swift index 6952408d4..b9eebeb06 100644 --- a/Nynja/Modules/Main/Interactor/MainInteractor.swift +++ b/Nynja/Modules/Main/Interactor/MainInteractor.swift @@ -146,10 +146,6 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic self.presenter.changeScreenToAuth() } } - - func saveLogoutState() { - MQTTService.sharedInstance.state = .notAuthenticated(isLoggedOutFromServer: false) - } private func setupIntercom() { Intercom.logout() @@ -166,5 +162,4 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic userAttributes.phone = contact.phoneNumber Intercom.updateUser(userAttributes) } - } diff --git a/Nynja/Modules/Main/MainProtocols.swift b/Nynja/Modules/Main/MainProtocols.swift index 98d9743d6..45812c17c 100644 --- a/Nynja/Modules/Main/MainProtocols.swift +++ b/Nynja/Modules/Main/MainProtocols.swift @@ -238,7 +238,6 @@ protocol MainInteractorInputProtocol: class { func logout() func deleteAccount() func updateAvatar(url: URL) - func saveLogoutState() func dialInGroup(name: String) func createGroupCall(callId: String?, contacts: [Contact], room: Room?) func createConferenceCall(callId: String?, contacts: [Contact], room: Room?) diff --git a/Nynja/Modules/Main/Presenter/MainPresenter.swift b/Nynja/Modules/Main/Presenter/MainPresenter.swift index 5292588ec..1cc2cee73 100644 --- a/Nynja/Modules/Main/Presenter/MainPresenter.swift +++ b/Nynja/Modules/Main/Presenter/MainPresenter.swift @@ -135,7 +135,6 @@ class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, Schedu } func logout() { - self.interactor.saveLogoutState() self.interactor.logout() self.changeScreenToAuth() } diff --git a/Nynja/Services/MQTT/MQTTServiceAuth.swift b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift similarity index 95% rename from Nynja/Services/MQTT/MQTTServiceAuth.swift rename to Nynja/Services/MQTT/API/MQTTServiceAuth.swift index 30e1c9094..bdca505a5 100644 --- a/Nynja/Services/MQTT/MQTTServiceAuth.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift @@ -49,11 +49,11 @@ extension MQTTService { publish(model: model) } - func updatePushToken(push_token: String) { - if - let phone = StorageService.sharedInstance.phone, + func update(pushToken: String) { + if let phone = StorageService.sharedInstance.phone, let token = StorageService.sharedInstance.tokenAsNSData, let clientID = StorageService.sharedInstance.clientId { + let model = AuthModel(type: .PUSH, phoneNumber: phone, userID: nil, @@ -63,7 +63,7 @@ extension MQTTService { token: token, smsCode: nil, languages: nil, - pushID: push_token) + pushID: pushToken) publish(model: model) } } diff --git a/Nynja/Services/MQTT/MQTTServiceChat.swift b/Nynja/Services/MQTT/API/MQTTServiceChat.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceChat.swift rename to Nynja/Services/MQTT/API/MQTTServiceChat.swift diff --git a/Nynja/Services/MQTT/MQTTServiceFriend.swift b/Nynja/Services/MQTT/API/MQTTServiceFriend.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceFriend.swift rename to Nynja/Services/MQTT/API/MQTTServiceFriend.swift diff --git a/Nynja/Services/MQTT/MQTTServiceLink.swift b/Nynja/Services/MQTT/API/MQTTServiceLink.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceLink.swift rename to Nynja/Services/MQTT/API/MQTTServiceLink.swift diff --git a/Nynja/Services/MQTT/MQTTServiceProfile.swift b/Nynja/Services/MQTT/API/MQTTServiceProfile.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceProfile.swift rename to Nynja/Services/MQTT/API/MQTTServiceProfile.swift diff --git a/Nynja/Services/MQTT/MQTTServiceSchedule.swift b/Nynja/Services/MQTT/API/MQTTServiceSchedule.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceSchedule.swift rename to Nynja/Services/MQTT/API/MQTTServiceSchedule.swift diff --git a/Nynja/Services/MQTT/MQTTServiceStars.swift b/Nynja/Services/MQTT/API/MQTTServiceStars.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceStars.swift rename to Nynja/Services/MQTT/API/MQTTServiceStars.swift diff --git a/Nynja/Services/MQTT/MQTTServiceWallet.swift b/Nynja/Services/MQTT/API/MQTTServiceWallet.swift similarity index 100% rename from Nynja/Services/MQTT/MQTTServiceWallet.swift rename to Nynja/Services/MQTT/API/MQTTServiceWallet.swift diff --git a/Nynja/Services/MQTT/Entities/Host.swift b/Nynja/Services/MQTT/Entities/Host.swift new file mode 100644 index 000000000..1ce1d6f21 --- /dev/null +++ b/Nynja/Services/MQTT/Entities/Host.swift @@ -0,0 +1,19 @@ +// +// Host.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +struct Host { + let url: String + let port: UInt16 + + init() { + url = Bundle.main.serverUrl + port = Bundle.main.serverPort + } +} diff --git a/Nynja/Services/MQTT/MQTTServiceHelper.swift b/Nynja/Services/MQTT/Extensions/MQTTService+Helper.swift similarity index 80% rename from Nynja/Services/MQTT/MQTTServiceHelper.swift rename to Nynja/Services/MQTT/Extensions/MQTTService+Helper.swift index fd07ad5bd..052f20245 100644 --- a/Nynja/Services/MQTT/MQTTServiceHelper.swift +++ b/Nynja/Services/MQTT/Extensions/MQTTService+Helper.swift @@ -1,5 +1,5 @@ // -// MQTTServiceHelper.swift +// MQTTService+Helper.swift // Nynja // // Created by Anton Makarov on 07.09.2017. @@ -11,19 +11,8 @@ import CocoaMQTT extension MQTTService { - func publish(model: BaseMQTTModel) { - publishingQueue.async { [weak self] in - guard let mqtt = self?.mqtt, mqtt.connState == .connected else { - return - } - - let finalModel: CocoaMQTTMessage = model.getMessage() - mqtt.publish(finalModel) - } - } - func printMessage(msg: CocoaMQTTMessage, isSent: Bool) { - loggingQueue.async { [weak self] in + queuePool.loggingQueue.async { [weak self] in guard let `self` = self else { return } let desc = self.prepareOutputMessage(msg: msg, isSent: isSent) diff --git a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift new file mode 100644 index 000000000..0f29b39d9 --- /dev/null +++ b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift @@ -0,0 +1,28 @@ +// +// MQTTService+QueuePool.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +extension MQTTService { + + struct QueuePool { + let subscribersQueue = DispatchQueue( + label: String.label(withSuffix: "mqtt-service.subscribers-queue"), + attributes: .concurrent) + + let loggingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.logging-queue")) + let processingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.processing-queue")) + let receivingQueue = DispatchQueue( + label: String.label(withSuffix: "mqtt-service.receiving-queue"), + qos: .utility) + + let publishingQueue = DispatchQueue( + label: String.label(withSuffix: "mqtt-service.publishing-queue"), + qos: .utility) + } +} diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 5ffe2ffb2..3696cde3f 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -9,45 +9,21 @@ import Foundation import CocoaMQTT -struct Host { - let url: String - let port: UInt16 - - init() { - url = Bundle.main.serverUrl - port = Bundle.main.serverPort - } -} - final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate { - enum ConnectionState { - case connected - case disconnected - } - - static let version = Bundle.main.modelsVersion - let host = Host() - - var mqtt: CocoaMQTT? - var push: String? - - let deviceId = UIDevice.current.persistentIdentifier - private let semaphore = DispatchSemaphore(value: 1) - + private var mqtt: CocoaMQTT? var wasRunApp: Bool = false - typealias MQTTServiceSubscribers = [WeakRef] - private var subscribers = MQTTServiceSubscribers() - private let subscribersQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.subscribers-queue"), attributes: .concurrent) - - let loggingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.logging-queue")) - private let receivingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.receiving-queue"), qos: .utility) - let publishingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.publishing-queue"), qos: .utility) - - let showHandlers : Set = [] + let queuePool = QueuePool() + let showHandlers: Set = [] + + var deviceId: String { + return UIDevice.current.persistentIdentifier + } - static let sharedInstance = MQTTService() + var storageService: StorageService { + return .sharedInstance + } private var autoReconnectTimeInterval: UInt16? { willSet { @@ -81,65 +57,38 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate } } } - - // MARK: - Session State - private let userDefaults: UserDefaults = .standard + // MARK: - Subscribers - enum SessionState { - case notDetermined - case notAuthenticated(isLoggedOutFromServer: Bool) - - enum Keys { - static let state = "SessionState.AuthenticationState" - static let isLoggedOutFromServer = "SessionState.isLoggedOutFromServer" - } - } + typealias MQTTServiceSubscribers = [WeakRef] + private var subscribers = MQTTServiceSubscribers() - var state: SessionState = .notDetermined { - didSet { - switch state { - case .notDetermined: - break - case let .notAuthenticated(isLoggedOutFromServer): - let value: [String: Bool] = [ - SessionState.Keys.isLoggedOutFromServer: isLoggedOutFromServer - ] - userDefaults.set(value, forKey: SessionState.Keys.state) - } - } - } - var isAuthenticated: Bool { - return StorageService.sharedInstance.hasToken - } + // MARK: - Singeton + static let sharedInstance = MQTTService() - // MARK: - Init + private override init() {} - override init () { - super.init() - state = fetchCurrentState() - } + + // MARK: - Setup func initialize() { - self.setup() - myConnect() - } - - func myConnect() { - semaphore.wait() - mqtt?.connect() - semaphore.signal() + queuePool.processingQueue.async { [unowned self] in + self.setup() + self.mqtt?.connect() + } } - func setup() { + private func setup() { // NOTE: Don't subscribe for ConnectionService because of the bug found there. None of the subscribers will be // invoked on conenction change, which might introduce regressions // ConnectionService.shared.addSubscriber(self) - if let token = StorageService.sharedInstance.token, let clientId = StorageService.sharedInstance.clientId, !token.isEmpty { + let host = Host() + + if let token = storageService.token, let clientId = storageService.clientId, !token.isEmpty { mqtt?.delegate = nil mqtt = CocoaMQTT(clientID: clientId, host: host.url, port: host.port) mqtt?.password = token @@ -152,8 +101,9 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate mqtt?.username = "api" mqtt?.cleanSession = false } + mqtt?.enableSSL = Bundle.main.isServerConnectionSecure - mqtt?.willMessage = CocoaMQTTWill(topic: "version/\(MQTTService.version)", message: "") + mqtt?.willMessage = CocoaMQTTWill(topic: "version/\(Bundle.main.modelsVersion)", message: "") mqtt?.keepAlive = 0 mqtt?.delegate = self @@ -164,107 +114,124 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate } } - func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { - if ack == .badUsernameOrPassword { - if let actualToken = StorageService.sharedInstance.token { - if actualToken == mqtt.password { - LogService.log(topic: .MQTT) { return "Bad Username or Password" } - #if !SHARE_EXTENSION - LogService.log(topic: .db) { return "Clear storage: bad username" } - StorageService.sharedInstance.clearStorage() - - self.state = .notAuthenticated(isLoggedOutFromServer: true) - - IoHandler.delegate { $0.sessionNotFound() } - notifySubscribers { (delegate) in - delegate.mqttServiceDidReceiveAuthenticationFailure(self) - } - self.reconnect() - #endif - } - } else { - LogService.log(topic: .MQTT) { return "Bad protocol version" } - isBadProtocolVersion = true - notifySubscribers { (delegate) in - delegate.mqttServiceDidReceiveWrongServerVersion() - } + func tryReconnect() { + queuePool.processingQueue.async { [unowned self] in + let states: [CocoaMQTTConnState] = [.initial, .disconnected] + if let connState = self.mqtt?.connState, states.contains(connState) { + self.reconnect() } } - if ack == .accept { - LogService.log(topic: .MQTT) { return "clientID: \(mqtt.clientID ) & password: \(mqtt.password ?? "") & clearSession: \(mqtt.cleanSession) state: \(mqtt.connState)" } - - isConnectedSuccess = true - - #if !SHARE_EXTENSION - if (mqtt.password ?? "") != "" && self.push != nil { - self.updatePushToken(push_token: self.push!) + } + + func reconnect() { + LogService.log(topic: .MQTT) { return "Reconnect" } + initialize() + } + + func disconnect(shouldRemoveConnectionSubscriber: Bool = true) { + queuePool.processingQueue.async { [unowned self] in + LogService.log(topic: .MQTT) { return "Disconnect" } + self.mqtt?.disconnect() + } + } + + + // MARK: - Publish + + func publish(model: BaseMQTTModel) { + queuePool.publishingQueue.async { [weak self] in + guard let mqtt = self?.mqtt, mqtt.connState == .connected else { + return } - #endif + + let finalModel: CocoaMQTTMessage = model.getMessage() + mqtt.publish(finalModel) } } - private func fetchCurrentState() -> SessionState { - guard let sessionState = userDefaults.dictionary(forKey: SessionState.Keys.state), - let isLoggedOutFromServer = sessionState[SessionState.Keys.isLoggedOutFromServer] as? Bool else { - return .notDetermined + + // MARK: - CocoaMQTTDelegate + + func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { + queuePool.processingQueue.async { [unowned self] in + if ack == .badUsernameOrPassword { + self.handleBadUsernameOrPassword(mqtt) + } + if ack == .accept { + self.handleAccept(mqtt) + } } - return self.isAuthenticated ? .notDetermined : .notAuthenticated(isLoggedOutFromServer: isLoggedOutFromServer) } - private var shouldResendLogout: Bool { - let storage = StorageService.sharedInstance - if !storage.hasToken, case let .notAuthenticated(isLoggedOutFromServer) = self.state, !isLoggedOutFromServer { - return true + private func handleBadUsernameOrPassword(_ mqtt: CocoaMQTT) { + if let actualToken = storageService.token, actualToken == mqtt.password { + handleInvalidToken(mqtt) + } else { + handleBadProtocolVersion(mqtt) } - return false } - func tryReconnect() { - let states: [CocoaMQTTConnState] = [.initial, .disconnected] - if let connState = mqtt?.connState, states.contains(connState) { - reconnect() + private func handleInvalidToken(_ mqtt: CocoaMQTT) { + LogService.log(topic: .MQTT) { return "Bad Username or Password" } + #if !SHARE_EXTENSION + LogService.log(topic: .db) { return "Clear storage: bad username" } + storageService.clearStorage() + + IoHandler.delegate { $0.sessionNotFound() } + notifySubscribers { (delegate) in + delegate.mqttServiceDidReceiveAuthenticationFailure(self) } + self.reconnect() + #endif } - func reconnect() { - LogService.log(topic: .MQTT) { return "Reconnect" } - self.setup() - myConnect() + private func handleBadProtocolVersion(_ mqtt: CocoaMQTT) { + LogService.log(topic: .MQTT) { return "Bad protocol version" } + isBadProtocolVersion = true + notifySubscribers { (delegate) in + delegate.mqttServiceDidReceiveWrongServerVersion() + } } - func disconnect(shouldRemoveConnectionSubscriber: Bool = true) { - LogService.log(topic: .MQTT) { return "Disconnect" } - // NOTE: Don't unsubscribe for ConnectionService because of the bug found there. None of the subscribers will be - // invoked on conenction change, which might introduce regressions -// if shouldRemoveConnectionSubscriber { -// ConnectionService.shared.removeSubscriber(self) -// } - mqtt?.disconnect() + private func handleAccept(_ mqtt: CocoaMQTT) { + LogService.log(topic: .MQTT) { return "clientID: \(mqtt.clientID ) & password: \(mqtt.password ?? "") & clearSession: \(mqtt.cleanSession) state: \(mqtt.connState)" } + + isConnectedSuccess = true + + #if !SHARE_EXTENSION + if let pushToken = storageService.pushToken, (mqtt.password ?? "") != "" { + self.update(pushToken: pushToken) + } + #endif } func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) { printMessage(msg: message, isSent: true) } - func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16 ) { + func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) { printMessage(msg: message, isSent: false) - receivingQueue.async { [weak self] in + queuePool.receivingQueue.async { [weak self] in HandlerService.handle(response: message) } } func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) { - LogService.log(topic: .MQTT) { return "clientID: \(mqtt.clientID ) & password: \(mqtt.password ?? "") & clearSession: \(mqtt.cleanSession) state: \(mqtt.connState) & error: \(err?.localizedDescription)" } - - if let error = err as NSError?, error.code == 7 { - LogService.log(topic: .MQTT) { return "Something went wrong" } + queuePool.processingQueue.async { [unowned self] in + LogService.log(topic: .MQTT) { return "clientID: \(mqtt.clientID ) & password: \(mqtt.password ?? "") & clearSession: \(mqtt.cleanSession) state: \(mqtt.connState) & error: \(err?.localizedDescription)" } + + if let error = err as NSError?, error.code == 7 { + LogService.log(topic: .MQTT) { return "Something went wrong" } + } + + self.isConnectedSuccess = false } - - isConnectedSuccess = false } func mqtt(_ mqtt: CocoaMQTT, didConnect host: String, port: Int) { - isConnectedSuccess = true + queuePool.processingQueue.async { [unowned self] in + self.isConnectedSuccess = true + } } func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopic topic: String) {} @@ -273,31 +240,29 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate func mqttDidPing(_ mqtt: CocoaMQTT) {} func mqttDidReceivePong(_ mqtt: CocoaMQTT) {} + // MARK: Subscribers + func addSubscriber(_ subscriber: MQTTServiceDelegate) { - subscribersQueue.async(flags: .barrier) { [weak self] in - guard let `self` = self else { return } + queuePool.subscribersQueue.async(flags: .barrier) { [unowned self] in self.subscribers.append(WeakRef(value: subscriber)) } } func removeSubscriber(_ subscriber: MQTTServiceDelegate) { - subscribersQueue.async(flags: .barrier) { [weak self] in - guard let `self` = self else { return } + queuePool.subscribersQueue.async(flags: .barrier) { [unowned self] in self.subscribers = self.subscribers.filter { $0.value !== subscriber } } } func removeAllSubscribers() { - subscribersQueue.async(flags: .barrier) { [weak self] in - guard let `self` = self else { return } + queuePool.subscribersQueue.async(flags: .barrier) { [unowned self] in self.subscribers.removeAll() } } private func notifySubscribers(with eventClosure: (MQTTServiceDelegate) -> Void) { - subscribersQueue.sync { [weak self] in - guard let `self` = self else { return } + queuePool.subscribersQueue.sync { [unowned self] in self.subscribers.forEach { (weak) in if let delegate = weak.value as? MQTTServiceDelegate { eventClosure(delegate) @@ -309,30 +274,20 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate // MARK: - ConnectionServiceDelegate - func connectionStatusChanged(_ sender: ConnectionService, service: ConnectionService.Service, oldValue: ConnectionService.ConnectionServiceState) { - if service == .networking { - guard let networkStatus = sender.state[.networking] else { return } - switch networkStatus { - case .connected: myConnect() - case .disconnected: disconnect(shouldRemoveConnectionSubscriber: false) - case .switched: reconnect() - default: break + func connectionStatusChanged( + _ sender: ConnectionService, + service: ConnectionService.Service, oldValue: ConnectionService.ConnectionServiceState) { + + queuePool.processingQueue.async { [unowned self] in + if service == .networking { + guard let networkStatus = sender.state[.networking] else { return } + switch networkStatus { + case .connected: self.mqtt?.connect() + case .disconnected: self.disconnect(shouldRemoveConnectionSubscriber: false) + case .switched: self.reconnect() + default: break + } } } } - -} - -protocol MQTTServiceDelegate: class { - func mqttServiceDidConnect(_ mqttService: MQTTService) - func mqttServiceDidDisconnect(_ mqttService: MQTTService) - func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) - func mqttServiceDidReceiveWrongServerVersion() -} - -extension MQTTServiceDelegate { - func mqttServiceDidConnect(_ mqttService: MQTTService) {} - func mqttServiceDidDisconnect(_ mqttService: MQTTService) {} - func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) {} - func mqttServiceDidReceiveWrongServerVersion() {} } diff --git a/Nynja/Services/MQTT/MQTTServiceDelegate.swift b/Nynja/Services/MQTT/MQTTServiceDelegate.swift new file mode 100644 index 000000000..9a2ab23ff --- /dev/null +++ b/Nynja/Services/MQTT/MQTTServiceDelegate.swift @@ -0,0 +1,23 @@ +// +// MQTTServiceDelegate.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +protocol MQTTServiceDelegate: class { + func mqttServiceDidConnect(_ mqttService: MQTTService) + func mqttServiceDidDisconnect(_ mqttService: MQTTService) + func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) + func mqttServiceDidReceiveWrongServerVersion() +} + +extension MQTTServiceDelegate { + func mqttServiceDidConnect(_ mqttService: MQTTService) {} + func mqttServiceDidDisconnect(_ mqttService: MQTTService) {} + func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) {} + func mqttServiceDidReceiveWrongServerVersion() {} +} diff --git a/Nynja/Services/PushService.swift b/Nynja/Services/PushService.swift index 5ec5a47a0..0cc420b9b 100644 --- a/Nynja/Services/PushService.swift +++ b/Nynja/Services/PushService.swift @@ -49,8 +49,7 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) { let voipPushToken = credentials.token let token = voipPushToken.map { String(format: "%02.2hhx", $0) }.joined() - //MQTTService.sharedInstance.updatePushToken(push_token: token) - MQTTService.sharedInstance.push = token + storageService.pushToken = token LogService.log(topic: .system) { return "Register push token: \(token)" } } @@ -79,8 +78,8 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab case historyDelete = "history_delete" case updateHistory = "history_update" case messageDelete = "message_delete" - case messageEdit = "message_edit" - case undefined = "" + case messageEdit = "message_edit" + case undefined = "" } // MARK: - Handle Notifications diff --git a/Nynja/StorageService+UserInfo.swift b/Nynja/StorageService+UserInfo.swift index e567eb45e..6571c3e06 100644 --- a/Nynja/StorageService+UserInfo.swift +++ b/Nynja/StorageService+UserInfo.swift @@ -45,6 +45,11 @@ extension StorageService: UserInfo { return tokenData.flatMap { NSData(data: $0) } } + var pushToken: String? { + get { return value(forId: .pushToken) } + set { set(newValue, forId: .pushToken) } + } + var phone: String? { get { return value(forId: .phone) } set { set(newValue, forId: .phone) } diff --git a/Nynja/UserInfo.swift b/Nynja/UserInfo.swift index 50d70c707..e42e56006 100644 --- a/Nynja/UserInfo.swift +++ b/Nynja/UserInfo.swift @@ -10,6 +10,8 @@ import Foundation enum UserIdentifiers: String { case token + case pushToken + case phone case rosterId case clientId = "clientID" @@ -22,6 +24,8 @@ protocol UserInfo: class { var token: String? { get set } var tokenAsNSData: NSData? { get } + var pushToken: String? { get set } + var phone: String? { get set } var rosterId: Int64? { get set } var clientId: String? { get set } diff --git a/Shared/Services/Handlers/IoHandler/IoHandler.swift b/Shared/Services/Handlers/IoHandler/IoHandler.swift index 61aa420c3..4ee13a7eb 100644 --- a/Shared/Services/Handlers/IoHandler/IoHandler.swift +++ b/Shared/Services/Handlers/IoHandler/IoHandler.swift @@ -73,8 +73,6 @@ final class IoHandler: BaseHandler, StaticDelegating { LogService.log(topic: .db) { return "Clear storage: IoHandler" } storageService.clearStorage() - mqttService.state = .notAuthenticated(isLoggedOutFromServer: true) - mqttService.disconnect() mqttService.reconnect() delegate { $0.logout() } -- GitLab From f8fb388f8c622aa42d032f8ba6a9559798ceb1c1 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 22:05:24 +0200 Subject: [PATCH 20/38] Update usage of `UserInfo` inside `StorageService` in order to remove `wasRunApp` from `MQTTService`. --- Nynja.xcodeproj/project.pbxproj | 12 +- Nynja/AppDelegate.swift | 2 - Nynja/Services/MQTT/API/MQTTServiceAuth.swift | 8 +- Nynja/Services/MQTT/MQTTService.swift | 1 - Nynja/Services/Models/AuthModel.swift | 6 +- Nynja/Services/StorageService.swift | 111 +++++++++++++++++- Nynja/UserInfo.swift | 2 +- ...vice+UserInfo.swift => UserInfoImpl.swift} | 84 ++++++------- .../Services/UserInfo/UserInfoTest.swift | 3 +- 9 files changed, 166 insertions(+), 63 deletions(-) rename Nynja/{StorageService+UserInfo.swift => UserInfoImpl.swift} (50%) diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 91aef5bb2..aea6a9616 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -550,6 +550,8 @@ 4B030F372195CD9B00F293B7 /* MQTTService+QueuePool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F352195CD9B00F293B7 /* MQTTService+QueuePool.swift */; }; 4B030F3B2195CF8100F293B7 /* Host.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3A2195CF8100F293B7 /* Host.swift */; }; 4B030F3C2195CF8100F293B7 /* Host.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3A2195CF8100F293B7 /* Host.swift */; }; + 4B030F3E2195D88100F293B7 /* UserInfoImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */; }; + 4B030F3F2195D88100F293B7 /* UserInfoImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */; }; 4B052CB0203614D400BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B052CB12036193900BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B058F03204EA928004C7D9F /* DAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F02204EA928004C7D9F /* DAOProtocol.swift */; }; @@ -1506,8 +1508,6 @@ A4330A6F2109EBA70060BD93 /* CountriesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4330A6D2109EBA70060BD93 /* CountriesProvider.swift */; }; A4330A712109EBB30060BD93 /* CountriesProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4330A702109EBB30060BD93 /* CountriesProviding.swift */; }; A4330A722109EBB30060BD93 /* CountriesProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4330A702109EBB30060BD93 /* CountriesProviding.swift */; }; - A4330A742109F0D40060BD93 /* StorageService+UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4330A732109F0D40060BD93 /* StorageService+UserInfo.swift */; }; - A4330A752109F0D40060BD93 /* StorageService+UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4330A732109F0D40060BD93 /* StorageService+UserInfo.swift */; }; A433D9A120A5C18C00C946F9 /* ContactsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A433D9A020A5C18C00C946F9 /* ContactsProvider.swift */; }; A433D9A320A5C19600C946F9 /* ContactsProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = A433D9A220A5C19600C946F9 /* ContactsProviding.swift */; }; A438DB9220763AFB00AA86A2 /* Contact+Desc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A438DB9120763AFB00AA86A2 /* Contact+Desc.swift */; }; @@ -2854,6 +2854,7 @@ 4B030F312195CD4500F293B7 /* MQTTServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTServiceDelegate.swift; sourceTree = ""; }; 4B030F352195CD9B00F293B7 /* MQTTService+QueuePool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MQTTService+QueuePool.swift"; sourceTree = ""; }; 4B030F3A2195CF8100F293B7 /* Host.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Host.swift; sourceTree = ""; }; + 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoImpl.swift; sourceTree = ""; }; 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAtomExtension.swift; sourceTree = ""; }; 4B058EFD204EA751004C7D9F /* ProfileDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDAO.swift; sourceTree = ""; }; 4B058F00204EA7F5004C7D9F /* DBManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBManagerProtocol.swift; sourceTree = ""; }; @@ -3624,7 +3625,6 @@ A4330A692109EA850060BD93 /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = ""; }; A4330A6D2109EBA70060BD93 /* CountriesProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountriesProvider.swift; sourceTree = ""; }; A4330A702109EBB30060BD93 /* CountriesProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountriesProviding.swift; sourceTree = ""; }; - A4330A732109F0D40060BD93 /* StorageService+UserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StorageService+UserInfo.swift"; sourceTree = ""; }; A433D9A020A5C18C00C946F9 /* ContactsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsProvider.swift; sourceTree = ""; }; A433D9A220A5C19600C946F9 /* ContactsProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsProviding.swift; sourceTree = ""; }; A438DB9120763AFB00AA86A2 /* Contact+Desc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Contact+Desc.swift"; sourceTree = ""; }; @@ -10156,7 +10156,7 @@ isa = PBXGroup; children = ( A4330A642109DFA00060BD93 /* UserInfo.swift */, - A4330A732109F0D40060BD93 /* StorageService+UserInfo.swift */, + 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */, ); name = UserInfo; sourceTree = ""; @@ -14725,6 +14725,7 @@ A415132420DBD5C400C2C01F /* Link.swift in Sources */, 35B1AB8E1FA3470500E65233 /* NavigateProtocol.swift in Sources */, A42CE55C20692EDB000889CC /* error.swift in Sources */, + 4B030F3F2195D88100F293B7 /* UserInfoImpl.swift in Sources */, 267D465C20AB4CD500D42242 /* AuthExtension.swift in Sources */, A42CE5F420692EDB000889CC /* Loc_Spec.swift in Sources */, A42CE57A20692EDB000889CC /* serviceTask.swift in Sources */, @@ -14811,7 +14812,6 @@ A42CE60820692EDB000889CC /* task_Spec.swift in Sources */, A43B25B220AB1E2600FF8107 /* ImagePlaceholderField.swift in Sources */, A43B25B120AB1E1B00FF8107 /* NynjaSearchField.swift in Sources */, - A4330A752109F0D40060BD93 /* StorageService+UserInfo.swift in Sources */, 26C0C1CA2073C93400C530DA /* ForwardContent.swift in Sources */, 263529132075725200DC6FBD /* SendJob.swift in Sources */, 35B98F9B1F9B956F009B8DEC /* StringExtensions.swift in Sources */, @@ -15512,7 +15512,6 @@ 8502DB512061030100613C8C /* WheelPositionPickerProtocols.swift in Sources */, 00F7B3402029DD6200E443E1 /* TextItemView.swift in Sources */, E77764BE1FBDA9B60042541D /* ImageWheelItemView.swift in Sources */, - A4330A742109F0D40060BD93 /* StorageService+UserInfo.swift in Sources */, FBCE841520E525A6003B7558 /* URLRequestConvertible.swift in Sources */, 264638271FFFE7F9002590E6 /* RepliesPresenter.swift in Sources */, E7C36C391FC46A9E00740630 /* ServiceExtension.swift in Sources */, @@ -15921,6 +15920,7 @@ F18AEAFD20C15792004FE01C /* SelectAvatarCoordinator.swift in Sources */, 85D66A1220BD965300FBD803 /* UserMentionTableViewCell.swift in Sources */, 2657BE51201233E300F21935 /* ImageFilledItemModel.swift in Sources */, + 4B030F3E2195D88100F293B7 /* UserInfoImpl.swift in Sources */, 85BA176120BEA7BD001EF8AC /* StickerPreviewContainerView.swift in Sources */, 85CB25DF20D7325500D5E565 /* StickerPackExtension.swift in Sources */, 00E8513B2021E96E007DC792 /* GApiResponse.swift in Sources */, diff --git a/Nynja/AppDelegate.swift b/Nynja/AppDelegate.swift index 332ecf388..7ce25040d 100644 --- a/Nynja/AppDelegate.swift +++ b/Nynja/AppDelegate.swift @@ -125,8 +125,6 @@ private extension AppDelegate { } private func wipeStorage() { - MQTTService.sharedInstance.wasRunApp = storageService.wasRun - if !storageService.wasRun { LogService.log(topic: .db) { return "Clear storage: AppDelegate - if it is first runs" } storageService.clearStorage() diff --git a/Nynja/Services/MQTT/API/MQTTServiceAuth.swift b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift index bdca505a5..6c67a190c 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceAuth.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift @@ -11,7 +11,7 @@ import Foundation extension MQTTService { func logout() { - let token = StorageService.sharedInstance.tokenAsNSData + let token = StorageService.sharedInstance.tokenData let userID = StorageService.sharedInstance.phone let model = AuthModel(type: .LOGOUT, phoneNumber: nil, @@ -24,7 +24,7 @@ extension MQTTService { } func login(number: String) { - if let token = StorageService.sharedInstance.tokenAsNSData { + if let token = StorageService.sharedInstance.tokenData { let model = AuthModel(type: .LOGIN, phoneNumber: number, userID: nil, @@ -51,7 +51,7 @@ extension MQTTService { func update(pushToken: String) { if let phone = StorageService.sharedInstance.phone, - let token = StorageService.sharedInstance.tokenAsNSData, + let token = StorageService.sharedInstance.tokenData, let clientID = StorageService.sharedInstance.clientId { let model = AuthModel(type: .PUSH, @@ -74,6 +74,8 @@ extension MQTTService { } func checkSMS(code: String, phone: String) { + let wasRunApp = storageService.wasRun + let model = AuthModel(type: .VERIFY, phoneNumber: phone, userID: nil, diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 3696cde3f..0a0e3c3dd 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -12,7 +12,6 @@ import CocoaMQTT final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate { private var mqtt: CocoaMQTT? - var wasRunApp: Bool = false let queuePool = QueuePool() let showHandlers: Set = [] diff --git a/Nynja/Services/Models/AuthModel.swift b/Nynja/Services/Models/AuthModel.swift index d66ec20bb..d4e04abcd 100644 --- a/Nynja/Services/Models/AuthModel.swift +++ b/Nynja/Services/Models/AuthModel.swift @@ -38,7 +38,7 @@ class AuthModel: BaseMQTTModel { var smsCode: String? var languages: String? var pushID: String? - var token: NSData? + var token: Data? var settings: [Feature]? init(type: AuthType, @@ -47,7 +47,7 @@ class AuthModel: BaseMQTTModel { clientID : String? = nil, deviceToken: String? = nil, settings: [Feature]? = nil, - token: NSData? = nil, + token: Data? = nil, smsCode: String? = nil, languages: String? = nil, pushID: String? = nil) { @@ -89,7 +89,7 @@ class AuthModel: BaseMQTTModel { let pID = Bert.getBin(pushID) var tok: BertObject = BertNil() - if let toke = self.token { + if let toke = self.token.flatMap({ NSData(data: $0) }) { tok = BertBinary(fromNSData: toke) } diff --git a/Nynja/Services/StorageService.swift b/Nynja/Services/StorageService.swift index 0d214a471..3eef65d49 100644 --- a/Nynja/Services/StorageService.swift +++ b/Nynja/Services/StorageService.swift @@ -17,6 +17,10 @@ class StorageService { let userDefaults = UserDefaults(suiteName: Bundle.main.appGroupName) let keychain = KeychainService.standard + private(set) lazy var userInfo: UserInfo = { + return UserInfoImpl( + dependencies: .init(userDefaults: userDefaults)) + }() private let countriesProvider = CountriesProvider() @@ -28,9 +32,7 @@ class StorageService { } #endif - let isolationQueue = DispatchQueue( - label: String.label(withSuffix: "storage-service.isolation-queue"), - attributes: .concurrent) + private let isolationQueue = DispatchQueue(label: String.label(withSuffix: "storage-service.isolation-queue")) // MARK: - Properties @@ -52,7 +54,7 @@ class StorageService { // MARK: - Setup func setupDatabase(with name: String, application: UIApplication) { - isolationQueue.sync(flags: .barrier) { [weak self] in + isolationQueue.sync { [weak self] in self?._setupDatabase(with: name, application: application) } } @@ -113,7 +115,7 @@ class StorageService { // MARK: - Clear func clearStorage() { - isolationQueue.sync(flags: .barrier) { [weak self] in + isolationQueue.sync { [weak self] in self?._clearStorage() } } @@ -163,3 +165,102 @@ extension StorageService: DBManagerProtocol { } } #endif + + +// MARK: - UserInfo + +extension StorageService: UserInfo { + + var token: String? { + get { + return value(forKeyPath: \UserInfo.token) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.token = newValue + } + } + } + + var tokenData: Data? { + get { + var data: Data? + isolationQueue.sync { [weak self] in + data = self?.userInfo.tokenData + } + return data + } + } + + var pushToken: String? { + get { return value(forKeyPath: \UserInfo.pushToken) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.pushToken = newValue + } + } + } + + var phone: String? { + get { return value(forKeyPath: \UserInfo.phone) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.phone = newValue + } + } + } + + var rosterId: Int64? { + get { return value(forKeyPath: \UserInfo.rosterId) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.rosterId = newValue + } + } + } + + var clientId: String? { + get { return value(forKeyPath: \UserInfo.clientId) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.clientId = newValue + } + } + } + + var wasLogined: Bool { + get { return value(forKeyPath: \UserInfo.wasLogined) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.wasLogined = newValue + } + } + } + + var wasRun: Bool { + get { return value(forKeyPath: \UserInfo.wasRun) } + set { + isolationQueue.async { [weak self] in + self?.userInfo.wasRun = newValue + } + } + } + + private func value(forKeyPath keyPath: WritableKeyPath) -> T { + var value: T? + isolationQueue.sync { [weak self] in + guard let `self` = self else { return } + value = self.userInfo[keyPath: keyPath] + } + return value! + } + + func setupAuth(clientId: String, token: String) { + self.clientId = clientId + self.token = token + } + + func setupUserInfo(from roster: Roster) { + phone = roster.phone + rosterId = roster.id + } +} diff --git a/Nynja/UserInfo.swift b/Nynja/UserInfo.swift index e42e56006..c04b6179c 100644 --- a/Nynja/UserInfo.swift +++ b/Nynja/UserInfo.swift @@ -22,7 +22,7 @@ enum UserIdentifiers: String { protocol UserInfo: class { var token: String? { get set } - var tokenAsNSData: NSData? { get } + var tokenData: Data? { get } var pushToken: String? { get set } diff --git a/Nynja/StorageService+UserInfo.swift b/Nynja/UserInfoImpl.swift similarity index 50% rename from Nynja/StorageService+UserInfo.swift rename to Nynja/UserInfoImpl.swift index 6571c3e06..87dd926df 100644 --- a/Nynja/StorageService+UserInfo.swift +++ b/Nynja/UserInfoImpl.swift @@ -1,20 +1,34 @@ // -// StorageService+UserInfo.swift +// UserInfoImpl.swift // Nynja // -// Created by Volodymyr Hryhoriev on 7/26/18. +// Created by Volodymyr Hryhoriev on 11/9/18. // Copyright © 2018 TecSynt Solutions. All rights reserved. // import Foundation -extension StorageService: UserInfo { +class UserInfoImpl: UserInfo, InitializeInjectable { + + let userDefaults: UserDefaults? + + private var mqttService: MQTTService { + return .sharedInstance + } + + required init(dependencies: Dependencies) { + userDefaults = dependencies.userDefaults + _wasRun = value(forId: .wasRun) ?? false + } + + + // MARK: - UserInfo private var encoding: String.Encoding { return .utf8 } - private var tokenData: Data? { + var tokenData: Data? { return value(forId: .token) } @@ -25,26 +39,18 @@ extension StorageService: UserInfo { return token } set { - isolationQueue.async(flags: .barrier) { [weak self] in - guard let `self` = self else { return } - - guard let token = newValue, let data = token.data(using: self.encoding) else { - self.userDefaults?.removeObject(forKey: UserIdentifiers.token.rawValue) - self.userDefaults?.synchronize() - return - } - - self.set(data as NSData, forId: .token, isAsync: false) - LogService.log(topic: .userDefaults) { return "Save token: \(token)" } - MQTTService.sharedInstance.reconnect() + guard let token = newValue, let data = token.data(using: self.encoding) else { + userDefaults?.removeObject(forKey: UserIdentifiers.token.rawValue) + userDefaults?.synchronize() + return } + + set(data as NSData, forId: .token) + LogService.log(topic: .userDefaults) { return "Save token: \(token)" } + MQTTService.sharedInstance.reconnect() // FIXME: I don't think it is proper place to do such thing } } - var tokenAsNSData: NSData? { - return tokenData.flatMap { NSData(data: $0) } - } - var pushToken: String? { get { return value(forId: .pushToken) } set { set(newValue, forId: .pushToken) } @@ -70,8 +76,10 @@ extension StorageService: UserInfo { set { set(newValue, forId: .wasLogined) } } + private var _wasRun: Bool = false + var wasRun: Bool { - get { return value(forId: .wasRun) ?? false } + get { return _wasRun } set { set(newValue, forId: .wasRun) } } @@ -86,27 +94,21 @@ extension StorageService: UserInfo { } private func value(forId id: UserIdentifiers) -> T? { - var value: T? - isolationQueue.sync { [weak self] in - value = self?.userDefaults?.value(forKey: id.rawValue) as? T - } - return value + return userDefaults?.value(forKey: id.rawValue) as? T } - private func set(_ value: Any?, forId id: UserIdentifiers, isAsync: Bool = true) { - let set = { [weak self] (value: Any?, id: UserIdentifiers) in - guard let `self` = self else { return } - - self.userDefaults?.set(value, forKey: id.rawValue) - self.userDefaults?.synchronize() - } - - if isAsync { - isolationQueue.async { - set(value, id) - } - } else { - set(value, id) - } + private func set(_ value: Any?, forId id: UserIdentifiers) { + userDefaults?.set(value, forKey: id.rawValue) + userDefaults?.synchronize() + } +} + + +// MARK: - InitializeInjectable + +extension UserInfoImpl { + + struct Dependencies { + let userDefaults: UserDefaults? } } diff --git a/NynjaUnitTests/Services/UserInfo/UserInfoTest.swift b/NynjaUnitTests/Services/UserInfo/UserInfoTest.swift index f2ba00aa2..33f8f8054 100644 --- a/NynjaUnitTests/Services/UserInfo/UserInfoTest.swift +++ b/NynjaUnitTests/Services/UserInfo/UserInfoTest.swift @@ -110,7 +110,8 @@ private extension UserInfoTest { class UserInfoMock: UserInfo { var token: String? - var tokenAsNSData: NSData? + var tokenData: Data? + var pushToken: String? var phone: String? var rosterId: Int64? var clientId: String? -- GitLab From 11c192d4117b9f61f2a5216401a234dab538410a Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 9 Nov 2018 22:08:19 +0200 Subject: [PATCH 21/38] Refactor `MQTTService` extensions in order to use `storageService` property instead of `StorageService.sharedInstance`. --- Nynja/Services/MQTT/API/MQTTServiceAuth.swift | 14 +++++++------- Nynja/Services/MQTT/API/MQTTServiceChat.swift | 6 +++--- Nynja/Services/MQTT/API/MQTTServiceFriend.swift | 10 +++++----- Nynja/Services/MQTT/API/MQTTServiceProfile.swift | 4 ++-- Nynja/Services/MQTT/API/MQTTServiceStars.swift | 2 +- Nynja/Services/MQTT/API/MQTTServiceWallet.swift | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Nynja/Services/MQTT/API/MQTTServiceAuth.swift b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift index 6c67a190c..a495ab33a 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceAuth.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift @@ -11,8 +11,8 @@ import Foundation extension MQTTService { func logout() { - let token = StorageService.sharedInstance.tokenData - let userID = StorageService.sharedInstance.phone + let token = storageService.tokenData + let userID = storageService.phone let model = AuthModel(type: .LOGOUT, phoneNumber: nil, userID: userID, @@ -24,7 +24,7 @@ extension MQTTService { } func login(number: String) { - if let token = StorageService.sharedInstance.tokenData { + if let token = storageService.tokenData { let model = AuthModel(type: .LOGIN, phoneNumber: number, userID: nil, @@ -50,9 +50,9 @@ extension MQTTService { } func update(pushToken: String) { - if let phone = StorageService.sharedInstance.phone, - let token = StorageService.sharedInstance.tokenData, - let clientID = StorageService.sharedInstance.clientId { + if let phone = storageService.phone, + let token = storageService.tokenData, + let clientID = storageService.clientId { let model = AuthModel(type: .PUSH, phoneNumber: phone, @@ -69,7 +69,7 @@ extension MQTTService { } func removeTokenAndLogin(number: String) { - StorageService.sharedInstance.dropUserInfo() + storageService.dropUserInfo() login(number: number) } diff --git a/Nynja/Services/MQTT/API/MQTTServiceChat.swift b/Nynja/Services/MQTT/API/MQTTServiceChat.swift index f1129894f..5fa321e5f 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceChat.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceChat.swift @@ -168,7 +168,7 @@ extension MQTTService { func block(_ isBlock: Bool, to: String) { let friend = Friend() - friend.phone_id = StorageService.sharedInstance.phoneId + friend.phone_id = storageService.phoneId friend.friend_id = to friend.settings = [] friend.status = isBlock ? ("ban" as AnyObject) : ("unban" as AnyObject) @@ -187,7 +187,7 @@ extension MQTTService { func updateSettings(_ features: [Feature], to: String) { let friend = Friend() - friend.phone_id = StorageService.sharedInstance.phoneId + friend.phone_id = storageService.phoneId friend.friend_id = to friend.settings = features friend.status = "update" as AnyObject @@ -210,7 +210,7 @@ extension MQTTService { func ignore(_ contact: Contact) { let friend = Friend() - friend.phone_id = StorageService.sharedInstance.phoneId + friend.phone_id = storageService.phoneId friend.friend_id = contact.phoneId friend.settings = [] friend.status = ("ignore" as AnyObject) diff --git a/Nynja/Services/MQTT/API/MQTTServiceFriend.swift b/Nynja/Services/MQTT/API/MQTTServiceFriend.swift index 7d67421c6..29f24c2ab 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceFriend.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceFriend.swift @@ -11,7 +11,7 @@ import Foundation extension MQTTService { func searchContactByUsername(nick : String) { - guard let rosterId = StorageService.sharedInstance.rosterId else { + guard let rosterId = storageService.rosterId else { return } let model = SearchModel(rosterID: rosterId, numbers: [nick], reference: .USERNAME, type: .EQUALS, status: .CONTACT, field: "nick") @@ -19,7 +19,7 @@ extension MQTTService { } func tryFindContact(number: String, modelReference: SearchModelReference = .PHONE) { - guard let rosterId = StorageService.sharedInstance.rosterId else { + guard let rosterId = storageService.rosterId else { return } let model = SearchModel(rosterID: rosterId, numbers: [number], reference: modelReference, type: .EQUALS, status: .CONTACT) @@ -27,7 +27,7 @@ extension MQTTService { } func searchContacts(numbers: [String]) { - guard let rosterId = StorageService.sharedInstance.rosterId else { + guard let rosterId = storageService.rosterId else { return } let model = SearchModel(rosterID: rosterId, numbers: numbers, reference: .PHONEBOOK, type: .EQUALS, status: .CONTACT) @@ -35,7 +35,7 @@ extension MQTTService { } func friendRequest(friendPhoneId : String) { - guard let phoneId = StorageService.sharedInstance.phoneId else { + guard let phoneId = storageService.phoneId else { return } let model = FriendRequstModel(phoneId: phoneId, friendPhoneId: friendPhoneId, status: "request") @@ -43,7 +43,7 @@ extension MQTTService { } func confirmFriend(friendPhoneId : String) { - guard let phoneId = StorageService.sharedInstance.phoneId else { + guard let phoneId = storageService.phoneId else { return } let model = FriendRequstModel(phoneId: phoneId, friendPhoneId: friendPhoneId, status: "confirm") diff --git a/Nynja/Services/MQTT/API/MQTTServiceProfile.swift b/Nynja/Services/MQTT/API/MQTTServiceProfile.swift index 48f53411f..79296cb83 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceProfile.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceProfile.swift @@ -11,7 +11,7 @@ import Foundation extension MQTTService { func updateAccount(id: Int64, name: String, surname: String, phone: String) { - if let _ = StorageService.sharedInstance.token { + if let _ = storageService.token { var model:UpdateRosterModel! if surname != "" { model = UpdateRosterModel(id: id, name: name, surname: surname, avatar: nil, email: nil,nick: nil) @@ -23,7 +23,7 @@ extension MQTTService { } func updateAvatar(id: Int64, link: String) { - if let _ = StorageService.sharedInstance.token { + if let _ = storageService.token { let model = UpdateRosterModel(id: id, name: nil, surname: nil, avatar: link, email: nil,nick: nil) publish(model: model) } diff --git a/Nynja/Services/MQTT/API/MQTTServiceStars.swift b/Nynja/Services/MQTT/API/MQTTServiceStars.swift index 4c3bafde5..c5cb5d2e5 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceStars.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceStars.swift @@ -10,7 +10,7 @@ import Foundation extension MQTTService { func getFavorites() { - guard StorageService.sharedInstance.token != nil else { + guard storageService.token != nil else { return } let model = GetExtendedStarsModel() diff --git a/Nynja/Services/MQTT/API/MQTTServiceWallet.swift b/Nynja/Services/MQTT/API/MQTTServiceWallet.swift index fefee8208..600599ade 100644 --- a/Nynja/Services/MQTT/API/MQTTServiceWallet.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceWallet.swift @@ -9,7 +9,7 @@ extension MQTTService { func addWalletToProfile(walletAddress: String, balance: NYNMoney, password: String) { - guard let phoneId = StorageService.sharedInstance.phone else { + guard let phoneId = storageService.phone else { return } @@ -23,7 +23,7 @@ extension MQTTService { } func changeProfileBalance(walletAddress: String, balance: NYNMoney, password: String) { - guard let phoneId = StorageService.sharedInstance.phone else { + guard let phoneId = storageService.phone else { return } -- GitLab From 81102a14374d645bea88687c721bd1e7aaf5c116 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 10:42:40 +0200 Subject: [PATCH 22/38] Notify `MQTTServiceDelegate` in the main queue. --- Nynja/Services/MQTT/MQTTService.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 0a0e3c3dd..a6cd65499 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -210,7 +210,7 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) { printMessage(msg: message, isSent: false) - queuePool.receivingQueue.async { [weak self] in + queuePool.receivingQueue.async { HandlerService.handle(response: message) } } @@ -260,11 +260,13 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate } } - private func notifySubscribers(with eventClosure: (MQTTServiceDelegate) -> Void) { + private func notifySubscribers(with eventClosure: @escaping (MQTTServiceDelegate) -> Void) { queuePool.subscribersQueue.sync { [unowned self] in self.subscribers.forEach { (weak) in if let delegate = weak.value as? MQTTServiceDelegate { - eventClosure(delegate) + dispatchAsyncMain { + eventClosure(delegate) + } } } } -- GitLab From 4f2bb51601bf9063d185ab22f3e6a924e34ff5aa Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 10:57:29 +0200 Subject: [PATCH 23/38] Make small refactoring in `StorageService` and `UserInfoImpl`. --- Nynja/Services/StorageService.swift | 8 ++++---- Nynja/UserInfoImpl.swift | 10 ---------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Nynja/Services/StorageService.swift b/Nynja/Services/StorageService.swift index 9fa0f73bc..cd0bcfe97 100644 --- a/Nynja/Services/StorageService.swift +++ b/Nynja/Services/StorageService.swift @@ -10,7 +10,9 @@ import Foundation import GRDBCipher import CryptoSwift -//MARK: - The Game is began +// MARK: - The Game is began + +/// Thread-safe class StorageService { private let passphraseKey = KeychainService.Keys.dataBasePassphrase @@ -22,8 +24,6 @@ class StorageService { dependencies: .init(userDefaults: userDefaults)) }() - private let countriesProvider = CountriesProvider() - #if !SHARE_EXTENSION private let databaseManager = DatabaseManager() @@ -37,7 +37,7 @@ class StorageService { // MARK: - Properties lazy var countries: [CountryModel] = { - return countriesProvider.fetchCountries() + return CountriesProvider().fetchCountries() }() /// It is used only for debug purposes. diff --git a/Nynja/UserInfoImpl.swift b/Nynja/UserInfoImpl.swift index 87dd926df..6f81d898d 100644 --- a/Nynja/UserInfoImpl.swift +++ b/Nynja/UserInfoImpl.swift @@ -83,16 +83,6 @@ class UserInfoImpl: UserInfo, InitializeInjectable { set { set(newValue, forId: .wasRun) } } - func setupAuth(clientId: String, token: String) { - self.clientId = clientId - self.token = token - } - - func setupUserInfo(from roster: Roster) { - phone = roster.phone - rosterId = roster.id - } - private func value(forId id: UserIdentifiers) -> T? { return userDefaults?.value(forKey: id.rawValue) as? T } -- GitLab From 23602d80d77d0f33309a799c03c5eac1b8423420 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 11:02:27 +0200 Subject: [PATCH 24/38] Remove unused `SearchHandler`, make small refactoring of others. --- Nynja.xcodeproj/project.pbxproj | 4 --- Nynja/ExtendedStarHandler.swift | 8 +++-- Nynja/HandlerFactory.swift | 2 -- Nynja/Handlers.swift | 1 - Nynja/JobHandler.swift | 8 +++-- .../HandleServices/ContactHandler.swift | 4 +-- .../HandleServices/RosterHandler.swift | 6 +++- .../HandleServices/SearchHandler.swift | 29 ------------------- .../Services/HandleServices/StarHandler.swift | 8 +++-- Nynja/Services/MQTT/MQTTService.swift | 1 + 10 files changed, 26 insertions(+), 45 deletions(-) delete mode 100644 Nynja/Services/HandleServices/SearchHandler.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index c800ae3ff..6c974490e 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -141,7 +141,6 @@ 26053123212741C2002E1CF1 /* LogOutputWireFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26053122212741C2002E1CF1 /* LogOutputWireFrame.swift */; }; 2605312921298BEF002E1CF1 /* Logoutputcell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2605312821298BEF002E1CF1 /* Logoutputcell.swift */; }; 2605312B21299198002E1CF1 /* LogOutputDS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2605312A21299198002E1CF1 /* LogOutputDS.swift */; }; - 260552A61F9E1CD100D68DE6 /* SearchHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260552A51F9E1CD100D68DE6 /* SearchHandler.swift */; }; 260629712056EF2800CB8F65 /* LinksCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260629702056EF2800CB8F65 /* LinksCell.swift */; }; 2606F3BC20BFE20500CF7F15 /* MessageInteractor+Translation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2606F3BB20BFE20400CF7F15 /* MessageInteractor+Translation.swift */; }; 2610D4642076516900E6E2B2 /* Array+Feature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26DCB25320692237001EF0AB /* Array+Feature.swift */; }; @@ -2538,7 +2537,6 @@ 26053122212741C2002E1CF1 /* LogOutputWireFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogOutputWireFrame.swift; sourceTree = ""; }; 2605312821298BEF002E1CF1 /* Logoutputcell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logoutputcell.swift; sourceTree = ""; }; 2605312A21299198002E1CF1 /* LogOutputDS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogOutputDS.swift; sourceTree = ""; }; - 260552A51F9E1CD100D68DE6 /* SearchHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SearchHandler.swift; path = Services/HandleServices/SearchHandler.swift; sourceTree = ""; }; 260629702056EF2800CB8F65 /* LinksCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinksCell.swift; sourceTree = ""; }; 2606F3BB20BFE20400CF7F15 /* MessageInteractor+Translation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MessageInteractor+Translation.swift"; sourceTree = ""; }; 2611CEF62182090900FFD4DD /* LogWriterProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogWriterProtocol.swift; sourceTree = ""; }; @@ -5969,7 +5967,6 @@ 3A771CA91F191B38008D968A /* ProfileHandler.swift */, 3A2374D81F262A1600701045 /* ContactHandler.swift */, 3A237BCC1F30E5D400C42B6E /* RosterHandler.swift */, - 260552A51F9E1CD100D68DE6 /* SearchHandler.swift */, 26FA420F201821B400E6F6EC /* StarHandler.swift */, 0008E91A20333A38003E316E /* JobHandler.swift */, 855EF424202CCADB00541BE3 /* ExtendedStarHandler.swift */, @@ -15729,7 +15726,6 @@ 8584C90F20920F3C001A0BBB /* StickerGridCellModel.swift in Sources */, A42D51A4206A361400EEB952 /* Feature.swift in Sources */, 26D6D227212EDA6600EA2419 /* ConvertMessageDAOProtocol.swift in Sources */, - 260552A61F9E1CD100D68DE6 /* SearchHandler.swift in Sources */, F1607B1F20B21A9D00BDF60A /* CameraViewController.swift in Sources */, 853E595B20D71E6C007799B9 /* StickerPack+DB.swift in Sources */, A4CE80C720C95EE000400713 /* CollectionState.swift in Sources */, diff --git a/Nynja/ExtendedStarHandler.swift b/Nynja/ExtendedStarHandler.swift index 4ea3c670b..184b5d6a0 100644 --- a/Nynja/ExtendedStarHandler.swift +++ b/Nynja/ExtendedStarHandler.swift @@ -10,11 +10,15 @@ import Foundation final class ExtendedStarHandler: BaseHandler { + private static var storageService: StorageService { + return .sharedInstance + } + static func executeHandle(data: BertList) { let extendedStars = data.elements.compactMap { get_ExtendedStar().parse(bert: $0) as? ExtendedStar } let stars = extendedStars.compactMap { extendedStar -> DBStar? in - guard let rosterId = StorageService.sharedInstance.rosterId else { return nil } + guard let rosterId = storageService.rosterId else { return nil } if let star = extendedStar.star, StarActionDAO.containsDeleteAction(for: star) { star.starStatus = .remove @@ -22,6 +26,6 @@ final class ExtendedStarHandler: BaseHandler { return DBStar(extendedStar: extendedStar, rosterId: rosterId) } - try? StorageService.sharedInstance.perform(action: .save, with: stars) + try? storageService.perform(action: .save, with: stars) } } diff --git a/Nynja/HandlerFactory.swift b/Nynja/HandlerFactory.swift index c94fbcbee..6313b5934 100644 --- a/Nynja/HandlerFactory.swift +++ b/Nynja/HandlerFactory.swift @@ -22,8 +22,6 @@ final class HandlerFactory { return HistoryHandler.self case .message: return MessageHandler.self - case .search: - return SearchHandler.self case .room: return RoomHandler.self case .member: diff --git a/Nynja/Handlers.swift b/Nynja/Handlers.swift index 92f9b5494..fc256fa32 100644 --- a/Nynja/Handlers.swift +++ b/Nynja/Handlers.swift @@ -13,7 +13,6 @@ enum Handlers: String { case contact case history case message - case search case room case member case typing diff --git a/Nynja/JobHandler.swift b/Nynja/JobHandler.swift index 0ea1a1720..32343977d 100644 --- a/Nynja/JobHandler.swift +++ b/Nynja/JobHandler.swift @@ -8,6 +8,10 @@ final class JobHandler: BaseHandler { + private static var storageService: StorageService { + return .sharedInstance + } + static func executeHandle(data: BertTuple) { guard let job = get_Job().parse(bert: data) as? Job, let status = StringAtom.string(job.status) else { @@ -16,9 +20,9 @@ final class JobHandler: BaseHandler { switch status { case "pending", "update": - try? StorageService.sharedInstance.perform(action: .save, with: job) + try? storageService.perform(action: .save, with: job) case "complete", "delete": - try? StorageService.sharedInstance.perform(action: .delete, with: job) + try? storageService.perform(action: .delete, with: job) default: break } diff --git a/Nynja/Services/HandleServices/ContactHandler.swift b/Nynja/Services/HandleServices/ContactHandler.swift index 42104e794..42e1e46bc 100644 --- a/Nynja/Services/HandleServices/ContactHandler.swift +++ b/Nynja/Services/HandleServices/ContactHandler.swift @@ -10,11 +10,11 @@ final class ContactHandler: BaseHandler { // MARK: - Dependencies - static var storageService: StorageService { + private static var storageService: StorageService { return .sharedInstance } - static var notificationManager: NotificationManager { + private static var notificationManager: NotificationManager { return .shared } diff --git a/Nynja/Services/HandleServices/RosterHandler.swift b/Nynja/Services/HandleServices/RosterHandler.swift index ea054dddd..2596cd69d 100644 --- a/Nynja/Services/HandleServices/RosterHandler.swift +++ b/Nynja/Services/HandleServices/RosterHandler.swift @@ -8,6 +8,10 @@ final class RosterHandler: BaseHandler { + private static var storageService: StorageService { + return .sharedInstance + } + static func executeHandle(data: BertTuple) { guard let roster = get_Roster().parse(bert: data) as? Roster, let status = (roster.status as? StringAtom)?.string else { @@ -15,7 +19,7 @@ final class RosterHandler: BaseHandler { } if status == "patch" || status == "nick" { - try? StorageService.sharedInstance.perform(action: .save, with: roster) + try? storageService.perform(action: .save, with: roster) } } } diff --git a/Nynja/Services/HandleServices/SearchHandler.swift b/Nynja/Services/HandleServices/SearchHandler.swift deleted file mode 100644 index 5889095bd..000000000 --- a/Nynja/Services/HandleServices/SearchHandler.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// SearchHandler.swift -// Nynja -// -// Created by Anton Makarov on 23.10.17. -// Copyright © 2017 TecSynt Solutions. All rights reserved. -// - -final class SearchHandler: BaseHandler { - - static func executeHandle(data: BertTuple) { - guard let search = get_Search().parse(bert: data) as? Search, - let ref = search.ref, - let refType = SearchModelReference(rawValue: ref) else { - return - } - - switch refType { - case .PHONE: - break - case .PHONEBOOK: - break - case .QRCODE: - break - case .USERNAME: - break - } - } -} diff --git a/Nynja/Services/HandleServices/StarHandler.swift b/Nynja/Services/HandleServices/StarHandler.swift index 22d335905..1b830f2ad 100644 --- a/Nynja/Services/HandleServices/StarHandler.swift +++ b/Nynja/Services/HandleServices/StarHandler.swift @@ -8,6 +8,10 @@ final class StarHandler: BaseHandler { + private static var storageService: StorageService { + return .sharedInstance + } + static func executeHandle(data: BertTuple) { guard let star = get_Star().parse(bert: data) as? Star, let status = star.starStatus else { @@ -18,10 +22,10 @@ final class StarHandler: BaseHandler { switch status { case .add: if !StarActionDAO.containsDeleteAction(for: star) { - try StorageService.sharedInstance.perform(action: .save, with: star) + try storageService.perform(action: .save, with: star) } case .remove: - try StorageService.sharedInstance.perform(action: .delete, with: star) + try storageService.perform(action: .delete, with: star) } } catch { } } diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index a6cd65499..23fd5dae7 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -9,6 +9,7 @@ import Foundation import CocoaMQTT +/// Performs works in the several serial background queues final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate { private var mqtt: CocoaMQTT? -- GitLab From c45e52e65432eff3fcbc1fc18c35bd1c535748a3 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 11:59:41 +0200 Subject: [PATCH 25/38] Remove thread-safity from `StorageService` because `UserDefaults` is thread-safe. --- Nynja/Services/StorageService.swift | 86 +++++++---------------------- 1 file changed, 19 insertions(+), 67 deletions(-) diff --git a/Nynja/Services/StorageService.swift b/Nynja/Services/StorageService.swift index cd0bcfe97..fc79d14d2 100644 --- a/Nynja/Services/StorageService.swift +++ b/Nynja/Services/StorageService.swift @@ -116,15 +116,11 @@ class StorageService { func clearStorage() { isolationQueue.sync { [weak self] in - self?._clearStorage() + #if !SHARE_EXTENSION + self?.databaseManager.clear() + #endif + self?.keychain.clear() } - } - - private func _clearStorage() { - #if !SHARE_EXTENSION - databaseManager.clear() - #endif - keychain.clear() dropUserInfo() } } @@ -172,86 +168,42 @@ extension StorageService: DBManagerProtocol { extension StorageService: UserInfo { var token: String? { - get { - return value(forKeyPath: \UserInfo.token) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.token = newValue - } - } + get { return userInfo.token } + set { userInfo.token = newValue } } var tokenData: Data? { - get { - var data: Data? - isolationQueue.sync { [weak self] in - data = self?.userInfo.tokenData - } - return data - } + get { return userInfo.tokenData } } var pushToken: String? { - get { return value(forKeyPath: \UserInfo.pushToken) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.pushToken = newValue - } - } + get { return userInfo.pushToken } + set { userInfo.pushToken = newValue } } var phone: String? { - get { return value(forKeyPath: \UserInfo.phone) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.phone = newValue - } - } + get { return userInfo.phone } + set { userInfo.phone = newValue } } var rosterId: Int64? { - get { return value(forKeyPath: \UserInfo.rosterId) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.rosterId = newValue - } - } + get { return userInfo.rosterId } + set { userInfo.rosterId = newValue } } var clientId: String? { - get { return value(forKeyPath: \UserInfo.clientId) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.clientId = newValue - } - } + get { return userInfo.clientId } + set { userInfo.clientId = newValue } } var wasLogined: Bool { - get { return value(forKeyPath: \UserInfo.wasLogined) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.wasLogined = newValue - } - } + get { return userInfo.wasLogined } + set { userInfo.wasLogined = newValue } } var wasRun: Bool { - get { return value(forKeyPath: \UserInfo.wasRun) } - set { - isolationQueue.async { [weak self] in - self?.userInfo.wasRun = newValue - } - } - } - - private func value(forKeyPath keyPath: WritableKeyPath) -> T { - var value: T? - isolationQueue.sync { [weak self] in - guard let `self` = self else { return } - value = self.userInfo[keyPath: keyPath] - } - return value! + get { return userInfo.wasRun } + set { userInfo.wasRun = newValue } } func setupAuth(clientId: String, token: String) { -- GitLab From f2fce0fb91f2efa2911153c311c0f302a62447ad Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 13:09:56 +0200 Subject: [PATCH 26/38] Make working with subscribers thread-safe inside `UserSettingsService`. --- .../Service/UserSettingsService.swift | 44 ++++++++++++++----- Nynja/UserSettings/Settings/Theme.swift | 4 +- .../UserSettings/Settings/WheelPosition.swift | 4 +- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Nynja/UserSettings/Service/UserSettingsService.swift b/Nynja/UserSettings/Service/UserSettingsService.swift index 5ae2229d1..3a82323dd 100644 --- a/Nynja/UserSettings/Service/UserSettingsService.swift +++ b/Nynja/UserSettings/Service/UserSettingsService.swift @@ -46,13 +46,26 @@ final class UserSettingsService { static let theme = "theme" static let notifications = "notifications" } + + + // MARK: - Singleton + static let shared = UserSettingsService() - private let storage = UserDefaults.standard + private init() {} + + + // MARK: - Queues + + private let subscribersQueue = DispatchQueue(label: String.label(withSuffix: "user-settings-service.subscribers-queue")) // MARK: - Properties + private var storage: UserDefaults { + return .standard + } + private lazy var settings: UserSettings = { return UserSettings(wheelPosition: wheelPosition, theme: theme, notifications: notifications) }() @@ -108,23 +121,32 @@ final class UserSettingsService { private var subscribers: [UserSettingsSubscriber] = [] func addSubscriber(_ object: AnyObject, for options: UserSettingsUpdateOptions = .all, handler: @escaping UserSettingsChangeHandler) { - guard !subscribers.contains(where: { $0.object.value === object }) else { - return + subscribersQueue.sync { [unowned self] in + guard !self.subscribers.contains(where: { $0.object.value === object }) else { + return + } + let subscriber = UserSettingsSubscriber(object: object, options: options, handler: handler) + self.subscribers.append(subscriber) + + // notify subscriber with current ui settings. + subscriber.handler(settings) } - let subscriber = UserSettingsSubscriber(object: object, options: options, handler: handler) - subscribers.append(subscriber) - - // notify subscriber with current ui settings. - subscriber.handler(settings) } func removeSubscriber(_ object: AnyObject) { - subscribers = subscribers.filter { $0.object.value != nil && $0.object.value !== object } + subscribersQueue.sync { [unowned self] in + subscribers = self.subscribers.filter { $0.object.value != nil && $0.object.value !== object } + } } private func notifySubscribers(with settings: UserSettings, options: UserSettingsUpdateOptions) { - for subscriber in subscribers where subscriber.options.contains(options) { - subscriber.handler(settings) + subscribersQueue.async() { [unowned self] in + for subscriber in self.subscribers where subscriber.options.contains(options) { + + dispatchAsyncMain { + subscriber.handler(settings) + } + } } } } diff --git a/Nynja/UserSettings/Settings/Theme.swift b/Nynja/UserSettings/Settings/Theme.swift index 6bba3db89..03acaa78c 100644 --- a/Nynja/UserSettings/Settings/Theme.swift +++ b/Nynja/UserSettings/Settings/Theme.swift @@ -13,8 +13,8 @@ enum Theme: String { static let `default` = Theme.dark static let all: [Theme] = [dark, light] - case light = "light" - case dark = "dark" + case light + case dark var name: String { switch self { diff --git a/Nynja/UserSettings/Settings/WheelPosition.swift b/Nynja/UserSettings/Settings/WheelPosition.swift index 2a0c2600c..acc6de350 100644 --- a/Nynja/UserSettings/Settings/WheelPosition.swift +++ b/Nynja/UserSettings/Settings/WheelPosition.swift @@ -9,8 +9,8 @@ import Foundation enum WheelPosition: String { - case left = "left" - case right = "right" + case left + case right static let `default` = WheelPosition.right static let all: [WheelPosition] = [left, right] -- GitLab From 58f82bbebb77c29dbb9404a6f18f7e667ee51418 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 13:10:35 +0200 Subject: [PATCH 27/38] Add dependency injections to `MainInteractor`. --- Nynja.xcodeproj/project.pbxproj | 16 +++ .../Main/Interactor/MainInteractor.swift | 105 ++++++++++++------ Nynja/Modules/Main/MainProtocols.swift | 4 +- .../Main/Presenter/MainPresenter.swift | 8 +- .../Main/View/MainViewController.swift | 8 +- .../Main/WireFrame/MainWireframe.swift | 20 +++- Nynja/Services/Amazon+FileSync.swift | 2 +- Nynja/Services/PushService.swift | 17 ++- .../FileDownloaderFactory.swift | 23 ++++ .../FileDownloaderKind.swift | 11 ++ .../ServiceFactory/ServiceFactory.swift | 32 ++++++ Nynja/SyncFileManager/SyncFileManager.swift | 6 +- 12 files changed, 196 insertions(+), 56 deletions(-) create mode 100644 Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderFactory.swift create mode 100644 Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderKind.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 6c974490e..a1ddbeca3 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -553,6 +553,8 @@ 4B030F3F2195D88100F293B7 /* UserInfoImpl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */; }; 4B052CB0203614D400BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B052CB12036193900BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; + 4B055C37219C313A001FE077 /* FileDownloaderFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */; }; + 4B055C39219C3146001FE077 /* FileDownloaderKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */; }; 4B058F03204EA928004C7D9F /* DAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F02204EA928004C7D9F /* DAOProtocol.swift */; }; 4B058F0B204EAEBA004C7D9F /* RoomDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F0A204EAEBA004C7D9F /* RoomDAOProtocol.swift */; }; 4B058F0D204EAEC3004C7D9F /* RoomDAO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F0C204EAEC3004C7D9F /* RoomDAO.swift */; }; @@ -2853,6 +2855,8 @@ 4B030F3A2195CF8100F293B7 /* Host.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Host.swift; sourceTree = ""; }; 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfoImpl.swift; sourceTree = ""; }; 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAtomExtension.swift; sourceTree = ""; }; + 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloaderFactory.swift; sourceTree = ""; }; + 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloaderKind.swift; sourceTree = ""; }; 4B058EFD204EA751004C7D9F /* ProfileDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDAO.swift; sourceTree = ""; }; 4B058F00204EA7F5004C7D9F /* DBManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBManagerProtocol.swift; sourceTree = ""; }; 4B058F02204EA928004C7D9F /* DAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAOProtocol.swift; sourceTree = ""; }; @@ -6516,6 +6520,15 @@ path = Entities; sourceTree = ""; }; + 4B055C35219C30F5001FE077 /* FileDownloaderFactory */ = { + isa = PBXGroup; + children = ( + 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */, + 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */, + ); + path = FileDownloaderFactory; + sourceTree = ""; + }; 4B058EF9204EA6EE004C7D9F /* DB */ = { isa = PBXGroup; children = ( @@ -13004,6 +13017,7 @@ F11786EF20AC5474007A9A1B /* ServiceFactory */ = { isa = PBXGroup; children = ( + 4B055C35219C30F5001FE077 /* FileDownloaderFactory */, F11786F020AC5482007A9A1B /* ServiceFactory.swift */, ); name = ServiceFactory; @@ -16592,6 +16606,7 @@ 855EF423202CC85300541BE3 /* MQTTServiceStars.swift in Sources */, 3362A56D731AC1411C02D037 /* MyGroupAliasWireframe.swift in Sources */, 260313A020A0A4BA009AC66D /* SwitchableActionCell.swift in Sources */, + 4B055C37219C313A001FE077 /* FileDownloaderFactory.swift in Sources */, 8ED0F3D11FBC5CF2004916AB /* GroupsListViewController.swift in Sources */, BBF46945EB64E07C58817ACA /* EditGroupNameProtocols.swift in Sources */, 8520040020D466CE007C0036 /* StickerPack_Spec.swift in Sources */, @@ -16694,6 +16709,7 @@ 26534B25210B4BE70003B9BC /* DBMessage+Extension.swift in Sources */, 2F7C7F7837BDE6F5767A3A8C /* GroupStorageViewController.swift in Sources */, 4B1D7E012029C4BE00703228 /* OptionsItemsFactory.swift in Sources */, + 4B055C39219C3146001FE077 /* FileDownloaderKind.swift in Sources */, 4B348FFE2163850100CCB0E3 /* DeletedIndexesCalculator.swift in Sources */, C921738220BADAFC00519A2D /* TextInputValidationService.swift in Sources */, 9763CCDFE5AF7B58C21CDED9 /* GroupStoragePresenter.swift in Sources */, diff --git a/Nynja/Modules/Main/Interactor/MainInteractor.swift b/Nynja/Modules/Main/Interactor/MainInteractor.swift index b9eebeb06..9388dc693 100644 --- a/Nynja/Modules/Main/Interactor/MainInteractor.swift +++ b/Nynja/Modules/Main/Interactor/MainInteractor.swift @@ -8,7 +8,8 @@ import SDWebImage import Intercom -class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServiceDelegate { + +final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPhotoDelegate, MQTTServiceDelegate, SetInjectable { weak var presenter: MainInteractorOutputProtocol! @@ -16,53 +17,57 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic return ContactDAO.currentContact } - private var storageService: StorageService { - return StorageService.sharedInstance - } - - init() { - let notificationsSettings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil) - UIApplication.shared.registerUserNotificationSettings(notificationsSettings) - UIApplication.shared.registerForRemoteNotifications() - let _ = PushService.sharedInstance - - MQTTService.sharedInstance.addSubscriber(self) + private var storageService: StorageService! + private var mqttService: MQTTService! + private var pushService: PushService! + private var communicatorService: NynjaCommunicatorService! + private var badgeNumberService: BadgeNumberServiceProtocol! + private var notificationManager: NotificationManager! + private var userSettingsService: UserSettingsService! + private var syncFileManager: SyncFileManager! + + override func loadData() { + super.loadData() + + + pushService.registerForPushNotifications() + mqttService.addSubscriber(self) setupIntercom() } func checkSession() { - MQTTService.sharedInstance.reconnect() + mqttService.reconnect() } func call(phoneId: String) { if let ctc = ContactDAO.findContactBy(phoneId: phoneId), let name = ctc.fullName { - NynjaCommunicatorService.sharedInstance.call(userId: phoneId, name: name, withVideo: false) + communicatorService.call(userId: phoneId, name: name, withVideo: false) } } func videoCall(phoneId: String) { if let ctc = ContactDAO.findContactBy(phoneId: phoneId), let name = ctc.names { - NynjaCommunicatorService.sharedInstance.call(userId: phoneId, name: name, withVideo: true) + communicatorService.call(userId: phoneId, name: name, withVideo: true) } } func dialInGroup(name: String) { - NynjaCommunicatorService.sharedInstance.dialInGroup(groupname: name) + communicatorService.dialInGroup(groupname: name) } func createGroupCall(callId: String?, contacts: [Contact], room: Room?) { if let cid = callId { - NynjaCommunicatorService.sharedInstance.addAndStartConference(callId: cid, contacts: contacts, room: room) + communicatorService.addAndStartConference(callId: cid, contacts: contacts, room: room) } else { - NynjaCommunicatorService.sharedInstance.createConference(contacts: contacts, room: room) + communicatorService.createConference(contacts: contacts, room: room) } } func createConferenceCall(callId: String?, contacts: [Contact], room: Room?) { if let cid = callId { - NynjaCommunicatorService.sharedInstance.addAndStartConference(callId: cid, contacts: contacts, room: room) + communicatorService.addAndStartConference(callId: cid, contacts: contacts, room: room) } else { - NynjaCommunicatorService.sharedInstance.createConference(contacts: contacts, room: room) + communicatorService.createConference(contacts: contacts, room: room) } } @@ -74,27 +79,32 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic } func logout() { - MQTTService.sharedInstance.logout() + mqttService.logout() LogService.log(topic: .db) { return "Clear storage: logout" } cleanServices() } func deleteAccount() { if let phone = storageService.phone, phone != "" { - MQTTService.sharedInstance.deleteUser(number: phone) + mqttService.deleteUser(number: phone) } LogService.log(topic: .db) { return "Clear storage: delete account" } cleanServices() } private func cleanServices() { - StorageService.sharedInstance.clearStorage() + storageService.clearStorage() + clearSDWebImageCache() + + badgeNumberService.clean() + notificationManager.clean() + userSettingsService.reset() + } + + private func clearSDWebImageCache() { let cache = SDImageCache.shared() cache.clearMemory() cache.clearDisk() - BadgeNumberService.shared.clean() - NotificationManager.shared.clean() - UserSettingsService.shared.reset() } func photoEditFinished(url: URL) { @@ -122,11 +132,9 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic } private func uploadAvatar(with url: URL, rosterId: Int64) { - let sync = SyncFileManager.sharedInstance - sync.downloader = AmazonManager.shared - SyncFileManager.sharedInstance.saveExternalFileLink(localUrl: url.path) { (ext, progress, request) in + syncFileManager.saveExternalFileLink(localUrl: url.path) { [mqttService](ext, progress, request) in if ext != nil { - MQTTService.sharedInstance.updateAvatar(id: rosterId, link: String(describing: ext!)) + mqttService?.updateAvatar(id: rosterId, link: String(describing: ext!)) } } } @@ -135,15 +143,15 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic func mqttServiceDidConnect(_ mqttService: MQTTService) { - DispatchQueue.main.async { - self.presenter.hideUILocker() + dispatchAsyncMain { [weak self] in + self?.presenter.hideUILocker() } } func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) { - DispatchQueue.main.async { - self.logout() - self.presenter.changeScreenToAuth() + dispatchAsyncMain { [weak self] in + self?.logout() + self?.presenter.changeScreenToAuth() } } @@ -163,3 +171,30 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic Intercom.updateUser(userAttributes) } } + + +// MARK: - SetInjectable + +extension MainInteractor { + struct Dependencies { + let presenter: MainInteractorOutputProtocol + let storageService: StorageService + let mqttService: MQTTService + let communicatorService: NynjaCommunicatorService + let badgeNumberService: BadgeNumberServiceProtocol + let notificationManager: NotificationManager + let userSettingsService: UserSettingsService + let syncFileManager: SyncFileManager + } + + func inject(dependencies: MainInteractor.Dependencies) { + presenter = dependencies.presenter + storageService = dependencies.storageService + mqttService = dependencies.mqttService + communicatorService = dependencies.communicatorService + badgeNumberService = dependencies.badgeNumberService + notificationManager = dependencies.notificationManager + userSettingsService = dependencies.userSettingsService + syncFileManager = dependencies.syncFileManager + } +} diff --git a/Nynja/Modules/Main/MainProtocols.swift b/Nynja/Modules/Main/MainProtocols.swift index 45812c17c..7fa230b9b 100644 --- a/Nynja/Modules/Main/MainProtocols.swift +++ b/Nynja/Modules/Main/MainProtocols.swift @@ -135,7 +135,7 @@ protocol MainViewProtocol: WheelOutProtocol { func notifyAvailability(snackBar: SnackBar, isAvailable: Bool) } -protocol MainPresenterProtocol: class { +protocol MainPresenterProtocol: BasePresenterProtocol { var view: MainViewProtocol! { get set } var interactor: MainInteractorInputProtocol! { get set } @@ -225,7 +225,7 @@ protocol MainInteractorOutputProtocol: class { func changeScreenToAuth() } -protocol MainInteractorInputProtocol: class { +protocol MainInteractorInputProtocol: BaseInteractorProtocol { var contact: Contact? { get } diff --git a/Nynja/Modules/Main/Presenter/MainPresenter.swift b/Nynja/Modules/Main/Presenter/MainPresenter.swift index 1cc2cee73..029ea6c21 100644 --- a/Nynja/Modules/Main/Presenter/MainPresenter.swift +++ b/Nynja/Modules/Main/Presenter/MainPresenter.swift @@ -6,15 +6,19 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, ScheduleMessageDelegate, EditParticipantsDelegate { +final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorOutputProtocol, ScheduleMessageDelegate, EditParticipantsDelegate { func returnToCall(call: NYNCall?) { self.wireFrame.returnToCall(call: call) } weak var view: MainViewProtocol! - var interactor: MainInteractorInputProtocol! var wireFrame: MainWireFrameProtocol! + var interactor: MainInteractorInputProtocol! { + didSet { + _interactor = interactor + } + } func showQRReader() { wireFrame.showQRReader() diff --git a/Nynja/Modules/Main/View/MainViewController.swift b/Nynja/Modules/Main/View/MainViewController.swift index 36d8fc95f..2531476ff 100644 --- a/Nynja/Modules/Main/View/MainViewController.swift +++ b/Nynja/Modules/Main/View/MainViewController.swift @@ -13,11 +13,15 @@ import MobileCoreServices import AssetsLibrary import AVFoundation -class MainViewController: BaseVC, MainViewProtocol, HitTestDelegate, UINavigationControllerDelegate, WheelPreviewProtocol { +final class MainViewController: BaseVC, MainViewProtocol, HitTestDelegate, UINavigationControllerDelegate, WheelPreviewProtocol { private var cameraCoordinator: CameraFlowCoordinatorProtocol? private var galleryCoordinator: GalleryFlowCoordinatorProtocol? - var presenter: MainPresenterProtocol! + var presenter: MainPresenterProtocol! { + didSet { + _presenter = presenter + } + } var galleryFetchController: GalleryFetchController? diff --git a/Nynja/Modules/Main/WireFrame/MainWireframe.swift b/Nynja/Modules/Main/WireFrame/MainWireframe.swift index cbb1e674e..a9fc5758f 100644 --- a/Nynja/Modules/Main/WireFrame/MainWireframe.swift +++ b/Nynja/Modules/Main/WireFrame/MainWireframe.swift @@ -10,7 +10,7 @@ import UIKit import CoreLocation import SnapKit -class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { +final class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { weak var navigation : UINavigationController? weak var contentNavigation: UINavigationController! @@ -20,6 +20,8 @@ class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { weak var external: EditParticipantsDelegate? = nil func presentMain(navigation: UINavigationController, isRegistered: Bool, checkSession: Bool = false) { + let serviceFactory = ServiceFactory() + let view = MainViewController() let presenter = MainPresenter() let interactor = MainInteractor() @@ -34,7 +36,17 @@ class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { presenter.view = view presenter.wireFrame = self presenter.interactor = interactor - interactor.presenter = presenter + + interactor.inject( + dependencies: .init( + presenter: presenter, + storageService: serviceFactory.makeStorageService(), + mqttService: serviceFactory.makeMQTTService(), + communicatorService: serviceFactory.makeNynjaCommunicatorService(), + badgeNumberService: serviceFactory.makeBadgeNumberService(), + notificationManager: serviceFactory.makeNotificationManager(), + userSettingsService: serviceFactory.makeUserSettingsService(), + syncFileManager: serviceFactory.makeSyncFileManager(with: .amazon))) // set content view let contentNavigation = ContentNavigationVC() @@ -275,10 +287,6 @@ class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { isVideo = false self.showReturnToCallView() self.view?.hidePartnerVideoView() - -// if let call = self.call { -// self.view?.showReturnToCall(call: call) -// } } func returnToCall(call: NYNCall?) { diff --git a/Nynja/Services/Amazon+FileSync.swift b/Nynja/Services/Amazon+FileSync.swift index 5ccd350c3..c76edb8c5 100644 --- a/Nynja/Services/Amazon+FileSync.swift +++ b/Nynja/Services/Amazon+FileSync.swift @@ -10,7 +10,7 @@ import Foundation import AWSCore import AWSS3 -extension AmazonManager: FileNetworkProtocol { +extension AmazonManager: FileDownloader { func download(url: String, from destination: RemoteStorageDestination, result: ((_ result: String?, _ transferInfo: TransferInfo?) -> ())?) -> AWSRequest? { diff --git a/Nynja/Services/PushService.swift b/Nynja/Services/PushService.swift index 0cc420b9b..a3cac82de 100644 --- a/Nynja/Services/PushService.swift +++ b/Nynja/Services/PushService.swift @@ -16,11 +16,7 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab return .sharedInstance } - static let sharedInstance: PushService = { - let instance = PushService() - instance.registerForPushNotifications() - return instance - }() + static let sharedInstance = PushService() // MARK: - Init @@ -38,6 +34,17 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab // MARK: - Setup func registerForPushNotifications() { + registerForNativeNotifications() + registerForPushNotifications() + } + + private func registerForNativeNotifications() { + let notificationsSettings = UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil) + UIApplication.shared.registerUserNotificationSettings(notificationsSettings) + UIApplication.shared.registerForRemoteNotifications() + } + + private func registerForPushKitNotifications() { let voipRegistry = PKPushRegistry(queue: DispatchQueue.main) voipRegistry.delegate = self voipRegistry.desiredPushTypes = [.voIP] diff --git a/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderFactory.swift b/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderFactory.swift new file mode 100644 index 000000000..b7a1b8427 --- /dev/null +++ b/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderFactory.swift @@ -0,0 +1,23 @@ +// +// FileDownloaderFactory.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/14/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +final class FileDownloaderFactory { + + let serviceFactory: ServiceFactoryProtocol + + init(serviceFactory: ServiceFactoryProtocol) { + self.serviceFactory = serviceFactory + } + + func makeFileDownloader(for kind: FileDownloaderKind) -> FileDownloader { + switch kind { + case .amazon: + return serviceFactory.makeAmazonManager() + } + } +} diff --git a/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderKind.swift b/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderKind.swift new file mode 100644 index 000000000..a841644a5 --- /dev/null +++ b/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderKind.swift @@ -0,0 +1,11 @@ +// +// FileDownloaderKind.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/14/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +enum FileDownloaderKind { + case amazon +} diff --git a/Nynja/Services/ServiceFactory/ServiceFactory.swift b/Nynja/Services/ServiceFactory/ServiceFactory.swift index 99adf6859..686feb212 100644 --- a/Nynja/Services/ServiceFactory/ServiceFactory.swift +++ b/Nynja/Services/ServiceFactory/ServiceFactory.swift @@ -34,6 +34,7 @@ protocol ServiceFactoryProtocol: SharedServiceFactoryProtocol { func makeWalletService() -> WalletService func makeSyncFileManager() -> SyncFileManager + func makeSyncFileManager(with kind: FileDownloaderKind) -> SyncFileManager func makeMuteChatService() -> MuteChatServiceProtocol @@ -49,6 +50,14 @@ protocol ServiceFactoryProtocol: SharedServiceFactoryProtocol { func makeAudioSessionManager() -> AudioSessionManager func makeHomeDataProvider(limit: Int) -> HomeDataProvider + + func makeNynjaCommunicatorService() -> NynjaCommunicatorService + + func makeBadgeNumberService() -> BadgeNumberServiceProtocol + + func makeNotificationManager() -> NotificationManager + + func makeUserSettingsService() -> UserSettingsService } final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { @@ -142,6 +151,13 @@ final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { func makeSyncFileManager() -> SyncFileManager { return SyncFileManager.sharedInstance } + + func makeSyncFileManager(with kind: FileDownloaderKind) -> SyncFileManager { + let downloader = FileDownloaderFactory(serviceFactory: self).makeFileDownloader(for: kind) + let syncFileManager = makeSyncFileManager() + syncFileManager.downloader = downloader + return syncFileManager + } func makeMuteChatService() -> MuteChatServiceProtocol { let dependencies = MuteChatService.Dependencies(mqttService: makeMQTTService()) @@ -182,4 +198,20 @@ final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { fields: .init( limit: limit))) } + + func makeNynjaCommunicatorService() -> NynjaCommunicatorService { + return .sharedInstance + } + + func makeBadgeNumberService() -> BadgeNumberServiceProtocol { + return BadgeNumberService.shared + } + + func makeNotificationManager() -> NotificationManager { + return .shared + } + + func makeUserSettingsService() -> UserSettingsService { + return .shared + } } diff --git a/Nynja/SyncFileManager/SyncFileManager.swift b/Nynja/SyncFileManager/SyncFileManager.swift index 3e1263358..9dcf4275f 100644 --- a/Nynja/SyncFileManager/SyncFileManager.swift +++ b/Nynja/SyncFileManager/SyncFileManager.swift @@ -10,7 +10,7 @@ import Foundation import AWSCore import AWSS3 -protocol FileNetworkProtocol: class { +protocol FileDownloader: class { func download(url: String, from destination: RemoteStorageDestination, result: ((_ result: String?, _ transferInfo: TransferInfo?) -> ())?) -> AWSRequest? @@ -18,7 +18,7 @@ protocol FileNetworkProtocol: class { func upload(localUrl: String, result: ((_ result:String?, _ transferInfo:TransferInfo?)->())?) -> AWSRequest? } -extension FileNetworkProtocol { +extension FileDownloader { func download(url: String, result: ((_ result: String?, _ transferInfo: TransferInfo?) -> ())?) -> AWSRequest? { return download(url: url, from: .default, result: result) @@ -29,7 +29,7 @@ class SyncFileManager { static let sharedInstance = SyncFileManager() - var downloader: FileNetworkProtocol = AmazonManager.shared + var downloader: FileDownloader = AmazonManager.shared func saveExternalFileLink(localUrl: String, completion: ((_ externalUrl: URL?, _ transferInfo: TransferInfo?, _ request: AWSRequest?) ->())?) { if let shortPath = localUrl.getShortPath() { -- GitLab From 55c4631ab446089fe043e90ef9e95e6adc21340f Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 14:05:01 +0200 Subject: [PATCH 28/38] Create `MQTTServiceProtocol`. --- .../View/ForwardSelectorViewController.swift | 2 +- Nynja.xcodeproj/project.pbxproj | 6 +++++ .../Splash/Interactor/SplashInteractor.swift | 2 +- Nynja/Services/MQTT/MQTTService.swift | 10 +++---- Nynja/Services/MQTT/MQTTServiceProtocol.swift | 26 +++++++++++++++++++ 5 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 Nynja/Services/MQTT/MQTTServiceProtocol.swift diff --git a/Nynja-Share/UI/ForwardSelector/View/ForwardSelectorViewController.swift b/Nynja-Share/UI/ForwardSelector/View/ForwardSelectorViewController.swift index 19a61f0c3..1575fcb76 100644 --- a/Nynja-Share/UI/ForwardSelector/View/ForwardSelectorViewController.swift +++ b/Nynja-Share/UI/ForwardSelector/View/ForwardSelectorViewController.swift @@ -393,7 +393,7 @@ final class ForwardSelectorViewController: UIViewController, ForwardSelectorView } func closeShareExtension() { - MQTTService.sharedInstance.disconnect(shouldRemoveConnectionSubscriber: false) + MQTTService.sharedInstance.disconnect() if let context = self.extensionContext { context.completeRequest(returningItems: nil, completionHandler: nil) } diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index a1ddbeca3..44f2a9501 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -555,6 +555,8 @@ 4B052CB12036193900BC2A9B /* StringAtomExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */; }; 4B055C37219C313A001FE077 /* FileDownloaderFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */; }; 4B055C39219C3146001FE077 /* FileDownloaderKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */; }; + 4B055C3B219C4101001FE077 /* MQTTServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */; }; + 4B055C3C219C4119001FE077 /* MQTTServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */; }; 4B058F03204EA928004C7D9F /* DAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F02204EA928004C7D9F /* DAOProtocol.swift */; }; 4B058F0B204EAEBA004C7D9F /* RoomDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F0A204EAEBA004C7D9F /* RoomDAOProtocol.swift */; }; 4B058F0D204EAEC3004C7D9F /* RoomDAO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F0C204EAEC3004C7D9F /* RoomDAO.swift */; }; @@ -2857,6 +2859,7 @@ 4B052CAF203614D400BC2A9B /* StringAtomExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAtomExtension.swift; sourceTree = ""; }; 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloaderFactory.swift; sourceTree = ""; }; 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloaderKind.swift; sourceTree = ""; }; + 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTServiceProtocol.swift; sourceTree = ""; }; 4B058EFD204EA751004C7D9F /* ProfileDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDAO.swift; sourceTree = ""; }; 4B058F00204EA7F5004C7D9F /* DBManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBManagerProtocol.swift; sourceTree = ""; }; 4B058F02204EA928004C7D9F /* DAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAOProtocol.swift; sourceTree = ""; }; @@ -6094,6 +6097,7 @@ 4B030F382195CDDA00F293B7 /* Extensions */, 3A8045CD1F60C8E200AED866 /* MQTTService.swift */, 4B030F312195CD4500F293B7 /* MQTTServiceDelegate.swift */, + 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */, ); name = MQTT; path = Services/MQTT; @@ -14680,6 +14684,7 @@ A4F3DAA42084935400FF71C7 /* Constants.swift in Sources */, E7ED35131FB33806008B5704 /* CellModel.swift in Sources */, A42CE55220692EDB000889CC /* act.swift in Sources */, + 4B055C3C219C4119001FE077 /* MQTTServiceProtocol.swift in Sources */, A42CE5DA20692EDB000889CC /* p2p_Spec.swift in Sources */, A4A2424F2060390000B0A804 /* Handlers.swift in Sources */, 2610D4642076516900E6E2B2 /* Array+Feature.swift in Sources */, @@ -16699,6 +16704,7 @@ 0D520AAAA7FD1F0464C8174F /* GroupRulesInteractor.swift in Sources */, A45F115E20B422AF00F45004 /* Contact+DB.swift in Sources */, 8505445720627C7C00E0F2B3 /* HistoryCellModel.swift in Sources */, + 4B055C3B219C4101001FE077 /* MQTTServiceProtocol.swift in Sources */, 2F2A5C12A7202E7834F923DC /* GroupRulesWireframe.swift in Sources */, 2625DBF820EFC5DE00E01C05 /* FourCharCode+StringLiteralConvertible.swift in Sources */, D3A30AF05BD7C46A9A8C1FC1 /* GroupStorageProtocols.swift in Sources */, diff --git a/Nynja/Modules/Splash/Interactor/SplashInteractor.swift b/Nynja/Modules/Splash/Interactor/SplashInteractor.swift index 38422a4da..f683f5feb 100644 --- a/Nynja/Modules/Splash/Interactor/SplashInteractor.swift +++ b/Nynja/Modules/Splash/Interactor/SplashInteractor.swift @@ -45,7 +45,7 @@ class SplashInteractor: SplashInteractorInputProtocol { application.applicationIconBadgeNumber = Int(badgeNumber) } - mqttService.initialize() + mqttService.connect() callService.initialize() MediaDownloadManager.setupAppDataUsageSettingsIfNeeded() diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 23fd5dae7..eea0985b4 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -10,7 +10,7 @@ import Foundation import CocoaMQTT /// Performs works in the several serial background queues -final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate { +final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, ConnectionServiceDelegate { private var mqtt: CocoaMQTT? @@ -74,7 +74,7 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate // MARK: - Setup - func initialize() { + func connect() { queuePool.processingQueue.async { [unowned self] in self.setup() self.mqtt?.connect() @@ -125,10 +125,10 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate func reconnect() { LogService.log(topic: .MQTT) { return "Reconnect" } - initialize() + connect() } - func disconnect(shouldRemoveConnectionSubscriber: Bool = true) { + func disconnect() { queuePool.processingQueue.async { [unowned self] in LogService.log(topic: .MQTT) { return "Disconnect" } self.mqtt?.disconnect() @@ -285,7 +285,7 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate guard let networkStatus = sender.state[.networking] else { return } switch networkStatus { case .connected: self.mqtt?.connect() - case .disconnected: self.disconnect(shouldRemoveConnectionSubscriber: false) + case .disconnected: self.disconnect() case .switched: self.reconnect() default: break } diff --git a/Nynja/Services/MQTT/MQTTServiceProtocol.swift b/Nynja/Services/MQTT/MQTTServiceProtocol.swift new file mode 100644 index 000000000..a58000f49 --- /dev/null +++ b/Nynja/Services/MQTT/MQTTServiceProtocol.swift @@ -0,0 +1,26 @@ +// +// MQTTServiceProtocol.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/14/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +//import Founda + +protocol MQTTServiceProtocol { + + var isBadProtocolVersion: Bool { get } + var isConnectedSuccess: Bool { get } + + func connect() + func tryReconnect() + func reconnect() + func disconnect() + + func publish(model: BaseMQTTModel) + + func addSubscriber(_ subscriber: MQTTServiceDelegate) + func removeSubscriber(_ subscriber: MQTTServiceDelegate) + func removeAllSubscribers() +} -- GitLab From 19b57db807468e861304ae3aad2baedcebebdfc7 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 17:06:34 +0200 Subject: [PATCH 29/38] 1. Remove `ScheduleMessageDelegate`. 2. Inject dependencies inside `MessagePresenter`. 3. Remove `logout` notifying from `IOHandler`. 4. Correct handling of `Profile/Remove` API. 5. Make `MQTTService` perform publishing inside `processingQueue`. --- Nynja.xcodeproj/project.pbxproj | 14 ++++- Nynja/DBObserver.swift | 2 + .../Interactor/VerifyNumberInteractor.swift | 1 - .../Main/Interactor/MainInteractor.swift | 54 +++++++++++++++---- Nynja/Modules/Main/MainProtocols.swift | 8 +-- .../Main/Presenter/MainPresenter.swift | 42 ++++++++++----- .../Main/WireFrame/MainWireframe.swift | 20 ++++--- .../Message/WireFrame/MessageWireframe.swift | 2 +- .../Presenter/ScheduleMessagePresenter.swift | 3 -- .../ScheduleMessageProtocols.swift | 8 +-- .../WireFrame/ScheduleMessageWireframe.swift | 4 +- Nynja/ProfileHandlerDelegate.swift | 11 ++++ .../HandleServices/ProfileHandler.swift | 17 +++--- .../Extensions/MQTTService+QueuePool.swift | 8 ++- Nynja/Services/MQTT/MQTTService.swift | 5 +- Nynja/Services/PushService.swift | 4 +- .../ServiceFactory/ServiceFactory.swift | 12 +++++ .../Handlers/IoHandler/IoHandler.swift | 7 --- .../IoHandler/IoHandlerDelegate.swift | 4 +- 19 files changed, 149 insertions(+), 77 deletions(-) create mode 100644 Nynja/ProfileHandlerDelegate.swift diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 44f2a9501..26f61926e 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -557,6 +557,7 @@ 4B055C39219C3146001FE077 /* FileDownloaderKind.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */; }; 4B055C3B219C4101001FE077 /* MQTTServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */; }; 4B055C3C219C4119001FE077 /* MQTTServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */; }; + 4B055C3F219C61A2001FE077 /* ProfileHandlerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B055C3E219C61A2001FE077 /* ProfileHandlerDelegate.swift */; }; 4B058F03204EA928004C7D9F /* DAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F02204EA928004C7D9F /* DAOProtocol.swift */; }; 4B058F0B204EAEBA004C7D9F /* RoomDAOProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F0A204EAEBA004C7D9F /* RoomDAOProtocol.swift */; }; 4B058F0D204EAEC3004C7D9F /* RoomDAO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B058F0C204EAEC3004C7D9F /* RoomDAO.swift */; }; @@ -2860,6 +2861,7 @@ 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloaderFactory.swift; sourceTree = ""; }; 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDownloaderKind.swift; sourceTree = ""; }; 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MQTTServiceProtocol.swift; sourceTree = ""; }; + 4B055C3E219C61A2001FE077 /* ProfileHandlerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileHandlerDelegate.swift; sourceTree = ""; }; 4B058EFD204EA751004C7D9F /* ProfileDAO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDAO.swift; sourceTree = ""; }; 4B058F00204EA7F5004C7D9F /* DBManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBManagerProtocol.swift; sourceTree = ""; }; 4B058F02204EA928004C7D9F /* DAOProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DAOProtocol.swift; sourceTree = ""; }; @@ -5969,9 +5971,9 @@ 4B8771762195AC3C0014AD09 /* HistoryHandler */, 4B8771792195AF7E0014AD09 /* TypingHandler */, 4B0CC2002195B67D00E0BA61 /* LinkHandler */, + 4B055C3D219C618B001FE077 /* ProfileHandler */, 265AEA141FE9AFA600AC4806 /* MemberHandler.swift */, 269666171FB57963009E41C1 /* RoomHandler.swift */, - 3A771CA91F191B38008D968A /* ProfileHandler.swift */, 3A2374D81F262A1600701045 /* ContactHandler.swift */, 3A237BCC1F30E5D400C42B6E /* RosterHandler.swift */, 26FA420F201821B400E6F6EC /* StarHandler.swift */, @@ -6533,6 +6535,15 @@ path = FileDownloaderFactory; sourceTree = ""; }; + 4B055C3D219C618B001FE077 /* ProfileHandler */ = { + isa = PBXGroup; + children = ( + 3A771CA91F191B38008D968A /* ProfileHandler.swift */, + 4B055C3E219C61A2001FE077 /* ProfileHandlerDelegate.swift */, + ); + name = ProfileHandler; + sourceTree = ""; + }; 4B058EF9204EA6EE004C7D9F /* DB */ = { isa = PBXGroup; children = ( @@ -15359,6 +15370,7 @@ FEA6560E2167797E00B44029 /* WalletFundingNetworkRouter.swift in Sources */, 3AE0A84B1F20321A008A04F3 /* Wheel.swift in Sources */, 00E4A65F201A287100CEC61F /* MapSearchDS.swift in Sources */, + 4B055C3F219C61A2001FE077 /* ProfileHandlerDelegate.swift in Sources */, 2603139D20A0A4BA009AC66D /* ChatLanguageSettingsProtocols.swift in Sources */, 26142B1120472ECD004E5FE4 /* MessageLinkTable.swift in Sources */, A4679BAC20B2DD100021FE9C /* SubscribersSelectorViewController.swift in Sources */, diff --git a/Nynja/DBObserver.swift b/Nynja/DBObserver.swift index 37e28e9b0..33b411fbf 100644 --- a/Nynja/DBObserver.swift +++ b/Nynja/DBObserver.swift @@ -10,6 +10,8 @@ import GRDBCipher final class DBObserver: StorageObserver, TransactionObserver { + // TODO: Notify only if subscribers exists! + static let `default` = DBObserver() private init() {} diff --git a/Nynja/Modules/Auth/VerifyNumber/Interactor/VerifyNumberInteractor.swift b/Nynja/Modules/Auth/VerifyNumber/Interactor/VerifyNumberInteractor.swift index c525eddce..92a4a1597 100644 --- a/Nynja/Modules/Auth/VerifyNumber/Interactor/VerifyNumberInteractor.swift +++ b/Nynja/Modules/Auth/VerifyNumber/Interactor/VerifyNumberInteractor.swift @@ -174,7 +174,6 @@ final class VerifyNumberInteractor: BaseInteractor, VerifyNumberInteractorInputP } } } - } diff --git a/Nynja/Modules/Main/Interactor/MainInteractor.swift b/Nynja/Modules/Main/Interactor/MainInteractor.swift index 9388dc693..d5c63f015 100644 --- a/Nynja/Modules/Main/Interactor/MainInteractor.swift +++ b/Nynja/Modules/Main/Interactor/MainInteractor.swift @@ -9,7 +9,7 @@ import SDWebImage import Intercom -final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPhotoDelegate, MQTTServiceDelegate, SetInjectable { +final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPhotoDelegate, MQTTServiceDelegate, ProfileHandlerDelegate, SetInjectable { weak var presenter: MainInteractorOutputProtocol! @@ -17,6 +17,11 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho return ContactDAO.currentContact } + private var initialPhone: String? + + + // MARK: - Dependencies + private var storageService: StorageService! private var mqttService: MQTTService! private var pushService: PushService! @@ -25,19 +30,21 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho private var notificationManager: NotificationManager! private var userSettingsService: UserSettingsService! private var syncFileManager: SyncFileManager! + private var alertManager: AlertManager! + + + // MARK: - BaseInteractor override func loadData() { super.loadData() - - pushService.registerForPushNotifications() + pushService.registerForNotifications() mqttService.addSubscriber(self) setupIntercom() } - - func checkSession() { - mqttService.reconnect() - } + + + // MARK: - Calls func call(phoneId: String) { @@ -70,10 +77,14 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho communicatorService.createConference(contacts: contacts, room: room) } } + + + // MARK: - MainInteractorInputProtocol - func updateGroupCall(contacts: [Contact]) { + func checkSession() { + mqttService.reconnect() } - + func findContactBy(phoneId: String) -> Contact? { return ContactDAO.findContactBy(phoneId: phoneId) } @@ -82,6 +93,7 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho mqttService.logout() LogService.log(topic: .db) { return "Clear storage: logout" } cleanServices() + mqttService.reconnect() } func deleteAccount() { @@ -89,7 +101,13 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho mqttService.deleteUser(number: phone) } LogService.log(topic: .db) { return "Clear storage: delete account" } + handleProfileDeleting() + } + + private func handleProfileDeleting() { cleanServices() + alertManager.showAlertOk(message: String.localizable.authAttemptsRemoved) + mqttService.reconnect() } private func cleanServices() { @@ -170,6 +188,18 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho userAttributes.phone = contact.phoneNumber Intercom.updateUser(userAttributes) } + + + // MARK: - ProfileHandlerDelegate + + func profileDeleted(with phone: String) { + guard initialPhone == phone else { + return + } + + handleProfileDeleting() + presenter.changeScreenToAuth() + } } @@ -180,21 +210,27 @@ extension MainInteractor { let presenter: MainInteractorOutputProtocol let storageService: StorageService let mqttService: MQTTService + let pushService: PushService let communicatorService: NynjaCommunicatorService let badgeNumberService: BadgeNumberServiceProtocol let notificationManager: NotificationManager let userSettingsService: UserSettingsService let syncFileManager: SyncFileManager + let alertManager: AlertManager } func inject(dependencies: MainInteractor.Dependencies) { presenter = dependencies.presenter storageService = dependencies.storageService mqttService = dependencies.mqttService + pushService = dependencies.pushService communicatorService = dependencies.communicatorService badgeNumberService = dependencies.badgeNumberService notificationManager = dependencies.notificationManager userSettingsService = dependencies.userSettingsService syncFileManager = dependencies.syncFileManager + alertManager = dependencies.alertManager + + initialPhone = storageService.phone } } diff --git a/Nynja/Modules/Main/MainProtocols.swift b/Nynja/Modules/Main/MainProtocols.swift index 7fa230b9b..48a9e0382 100644 --- a/Nynja/Modules/Main/MainProtocols.swift +++ b/Nynja/Modules/Main/MainProtocols.swift @@ -48,8 +48,8 @@ protocol MainWireFrameProtocol: class { func showAddParticipantsToCreateConferenceCall() func showPayment(profile: Profile, to contact: Contact) - func showScheduleMessage(with mode: ScheduledMessageMode, delegate: ScheduleMessageDelegate?) - func showScheduleMessage(with inputMessage: InputScheduleMessage, delegate: ScheduleMessageDelegate?) + func showScheduleMessage(with mode: ScheduledMessageMode) + func showScheduleMessage(with inputMessage: InputScheduleMessage) func showForwardSelector(with mode: ForwardSelectorMode, delegate: ForwardSelectorDelegate?) @@ -219,7 +219,6 @@ protocol MainInteractorOutputProtocol: class { * Add here your methods for communication INTERACTOR -> PRESENTER */ - func logout() func showUILocker() func hideUILocker() func changeScreenToAuth() @@ -241,15 +240,12 @@ protocol MainInteractorInputProtocol: BaseInteractorProtocol { func dialInGroup(name: String) func createGroupCall(callId: String?, contacts: [Contact], room: Room?) func createConferenceCall(callId: String?, contacts: [Contact], room: Room?) - func updateGroupCall(contacts: [Contact]) func findContactBy(phoneId: String)->Contact? } -// Provide for compiler info, about extension MainWireFrameProtocol { func showChat(_ chat: ChatModel) { showChat(chat, initialMessage: nil) } - } diff --git a/Nynja/Modules/Main/Presenter/MainPresenter.swift b/Nynja/Modules/Main/Presenter/MainPresenter.swift index 029ea6c21..8aa2b1bfe 100644 --- a/Nynja/Modules/Main/Presenter/MainPresenter.swift +++ b/Nynja/Modules/Main/Presenter/MainPresenter.swift @@ -6,7 +6,7 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorOutputProtocol, ScheduleMessageDelegate, EditParticipantsDelegate { +final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorOutputProtocol, EditParticipantsDelegate, SetInjectable { func returnToCall(call: NYNCall?) { self.wireFrame.returnToCall(call: call) @@ -19,6 +19,8 @@ final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorO _interactor = interactor } } + + private var reachabilityService: ReachabilityService! func showQRReader() { wireFrame.showQRReader() @@ -139,12 +141,12 @@ final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorO } func logout() { - self.interactor.logout() - self.changeScreenToAuth() + interactor.logout() + changeScreenToAuth() } func changeScreenToAuth() { - self.wireFrame.logout() + wireFrame.logout() } func showMessages (room: Room, call: NYNCall, callVC: CallInProgressViewProtocol, isVideo: Bool = false) { @@ -236,8 +238,10 @@ final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorO } func deleteAccount() { - self.interactor.deleteAccount() - self.wireFrame.logout() + reachabilityService.performIfConnected { + interactor.deleteAccount() + changeScreenToAuth() + } } func showDataAndStorage() { @@ -295,13 +299,9 @@ final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorO view?.hideUILocker() } - // MARK: - ScheduleMessageDelegate - func scheduleMessageHasBeenSent() { - //TODO: -// view.cleanTextInput() - } - + // MARK: EditParticpantsDelegate + func participantsUpdated(contacts: [Contact]) { } @@ -319,5 +319,23 @@ final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorO break } } +} + + +// MARK: - SetInjectable +extension MainPresenter { + struct Dependencies { + let view: MainViewProtocol + let wireFrame: MainWireFrameProtocol + let interactor: MainInteractorInputProtocol + let reachabilityService: ReachabilityService + } + + func inject(dependencies: MainPresenter.Dependencies) { + view = dependencies.view + wireFrame = dependencies.wireFrame + interactor = dependencies.interactor + reachabilityService = dependencies.reachabilityService + } } diff --git a/Nynja/Modules/Main/WireFrame/MainWireframe.swift b/Nynja/Modules/Main/WireFrame/MainWireframe.swift index a9fc5758f..9d439b980 100644 --- a/Nynja/Modules/Main/WireFrame/MainWireframe.swift +++ b/Nynja/Modules/Main/WireFrame/MainWireframe.swift @@ -33,20 +33,26 @@ final class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelega // Connecting view.presenter = presenter - presenter.view = view - presenter.wireFrame = self - presenter.interactor = interactor + + presenter.inject( + dependencies: .init( + view: view, + wireFrame: self, + interactor: interactor, + reachabilityService: serviceFactory.makeReachabilityService())) interactor.inject( dependencies: .init( presenter: presenter, storageService: serviceFactory.makeStorageService(), mqttService: serviceFactory.makeMQTTService(), + pushService: serviceFactory.makePushService(), communicatorService: serviceFactory.makeNynjaCommunicatorService(), badgeNumberService: serviceFactory.makeBadgeNumberService(), notificationManager: serviceFactory.makeNotificationManager(), userSettingsService: serviceFactory.makeUserSettingsService(), - syncFileManager: serviceFactory.makeSyncFileManager(with: .amazon))) + syncFileManager: serviceFactory.makeSyncFileManager(with: .amazon), + alertManager: serviceFactory.makeAlertManager())) // set content view let contentNavigation = ContentNavigationVC() @@ -157,15 +163,15 @@ final class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelega HistoryWireFrame().presentHistory(navigation: contentNavigation, mainWireFrame: self) } - func showScheduleMessage(with mode: ScheduledMessageMode, delegate: ScheduleMessageDelegate? = nil) { + func showScheduleMessage(with mode: ScheduledMessageMode) { if let navigation = self.navigation { ScheduleMessageWireFrame().presentScheduleMessage(navigation: navigation, main: self, mode: mode) } } - func showScheduleMessage(with inputMessage: InputScheduleMessage, delegate: ScheduleMessageDelegate? = nil) { + func showScheduleMessage(with inputMessage: InputScheduleMessage) { if let info = messageinteractor?.scheduleInfo(for: inputMessage) { - showScheduleMessage(with: .create(info: info), delegate: delegate) + showScheduleMessage(with: .create(info: info)) } } diff --git a/Nynja/Modules/Message/WireFrame/MessageWireframe.swift b/Nynja/Modules/Message/WireFrame/MessageWireframe.swift index bdb7e114f..71987cd8c 100644 --- a/Nynja/Modules/Message/WireFrame/MessageWireframe.swift +++ b/Nynja/Modules/Message/WireFrame/MessageWireframe.swift @@ -127,7 +127,7 @@ class MessageWireFrame: MessageWireframeProtocol, DocumentInteractionWireFrame { } func openSchedule(with inputMessage: InputScheduleMessage) { - main?.showScheduleMessage(with: inputMessage, delegate: nil) + main?.showScheduleMessage(with: inputMessage) } func deleteAndLeave() { diff --git a/Nynja/Modules/ScheduleMessage/Presenter/ScheduleMessagePresenter.swift b/Nynja/Modules/ScheduleMessage/Presenter/ScheduleMessagePresenter.swift index 781e36ed9..c99265c6c 100644 --- a/Nynja/Modules/ScheduleMessage/Presenter/ScheduleMessagePresenter.swift +++ b/Nynja/Modules/ScheduleMessage/Presenter/ScheduleMessagePresenter.swift @@ -8,8 +8,6 @@ final class ScheduleMessagePresenter: BasePresenter, ScheduleMessagePresenterProtocol, ScheduleMessageInteractorOutputProtocol, DateTimePickerDelegate, TimeZoneSelectorDelegate, ForwardSelectorDelegate, ConnectionServiceDelegate { - weak var delegate: ScheduleMessageDelegate? - weak var view: ScheduleMessageViewProtocol! var wireFrame: ScheduleMessageWireFrameProtocol! var interactor: ScheduleMessageInteractorInputProtocol! { @@ -96,7 +94,6 @@ final class ScheduleMessagePresenter: BasePresenter, ScheduleMessagePresenterPro } else { self.goBack() } - self.delegate?.scheduleMessageHasBeenSent() } } diff --git a/Nynja/Modules/ScheduleMessage/ScheduleMessageProtocols.swift b/Nynja/Modules/ScheduleMessage/ScheduleMessageProtocols.swift index fb6c9a4ab..848f0670e 100644 --- a/Nynja/Modules/ScheduleMessage/ScheduleMessageProtocols.swift +++ b/Nynja/Modules/ScheduleMessage/ScheduleMessageProtocols.swift @@ -13,15 +13,9 @@ enum ScheduledMessageMode { case edit(jobId: Int64) } -protocol ScheduleMessageDelegate: class { - - func scheduleMessageHasBeenSent() - -} - protocol ScheduleMessageWireFrameProtocol: class { - func presentScheduleMessage(navigation: UINavigationController, main: MainWireFrameProtocol?, mode: ScheduledMessageMode, delegate: ScheduleMessageDelegate?) + func presentScheduleMessage(navigation: UINavigationController, main: MainWireFrameProtocol?, mode: ScheduledMessageMode) /** * Add here your methods for communication PRESENTER -> WIREFRAME diff --git a/Nynja/Modules/ScheduleMessage/WireFrame/ScheduleMessageWireframe.swift b/Nynja/Modules/ScheduleMessage/WireFrame/ScheduleMessageWireframe.swift index 179084cb6..6de7d02c2 100644 --- a/Nynja/Modules/ScheduleMessage/WireFrame/ScheduleMessageWireframe.swift +++ b/Nynja/Modules/ScheduleMessage/WireFrame/ScheduleMessageWireframe.swift @@ -13,14 +13,12 @@ final class ScheduleMessageWireFrame: ScheduleMessageWireFrameProtocol { weak var main: MainWireFrameProtocol? weak var navigation: UINavigationController? - func presentScheduleMessage(navigation: UINavigationController, main: MainWireFrameProtocol?, mode: ScheduledMessageMode, delegate: ScheduleMessageDelegate? = nil) { + func presentScheduleMessage(navigation: UINavigationController, main: MainWireFrameProtocol?, mode: ScheduledMessageMode) { let view = ScheduleMessageViewController() let presenter = ScheduleMessagePresenter() let interactor = ScheduleMessageInteractor(mode: mode) - presenter.delegate = delegate - self.main = main self.navigation = navigation diff --git a/Nynja/ProfileHandlerDelegate.swift b/Nynja/ProfileHandlerDelegate.swift new file mode 100644 index 000000000..9fdd8ef67 --- /dev/null +++ b/Nynja/ProfileHandlerDelegate.swift @@ -0,0 +1,11 @@ +// +// ProfileHandlerDelegate.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/14/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +protocol ProfileHandlerDelegate: class { + func profileDeleted(with phone: String) +} diff --git a/Nynja/Services/HandleServices/ProfileHandler.swift b/Nynja/Services/HandleServices/ProfileHandler.swift index 72d0ba98a..9af1da022 100644 --- a/Nynja/Services/HandleServices/ProfileHandler.swift +++ b/Nynja/Services/HandleServices/ProfileHandler.swift @@ -6,7 +6,9 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -final class ProfileHandler: BaseHandler { +final class ProfileHandler: BaseHandler, StaticDelegating { + + static weak var delegate: ProfileHandlerDelegate? // MARK: - Dependencies @@ -25,10 +27,6 @@ final class ProfileHandler: BaseHandler { static var messageBackgroundTaskHandler: BackgroundTaskHandler { return MessageBackgroundTaskHandler() } - - static var alertManager: AlertManager { - return AlertManager.sharedInstance - } // MARK: - Handler @@ -183,9 +181,10 @@ final class ProfileHandler: BaseHandler { // MARK: Remove private static func handleRemove(_ profile: Profile) { - try? storageService.perform(action: .delete, with: profile) - storageService.phone = nil - alertManager.showAlertOk(message: String.localizable.authAttemptsRemoved) - mqttService.reconnect() + guard let phone = profile.phone else { + return + } + + delegate { $0.profileDeleted(with: phone) } } } diff --git a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift index 0f29b39d9..dcbe6b5bd 100644 --- a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift +++ b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift @@ -16,13 +16,11 @@ extension MQTTService { attributes: .concurrent) let loggingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.logging-queue")) - let processingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.processing-queue")) + let processingQueue = DispatchQueue( + label: String.label(withSuffix: "mqtt-service.processing-queue"), + qos: .utility) let receivingQueue = DispatchQueue( label: String.label(withSuffix: "mqtt-service.receiving-queue"), qos: .utility) - - let publishingQueue = DispatchQueue( - label: String.label(withSuffix: "mqtt-service.publishing-queue"), - qos: .utility) } } diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index eea0985b4..df19f0adf 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -125,6 +125,7 @@ final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, Conne func reconnect() { LogService.log(topic: .MQTT) { return "Reconnect" } + disconnect() connect() } @@ -139,8 +140,8 @@ final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, Conne // MARK: - Publish func publish(model: BaseMQTTModel) { - queuePool.publishingQueue.async { [weak self] in - guard let mqtt = self?.mqtt, mqtt.connState == .connected else { + queuePool.processingQueue.async { [mqtt] in + guard let mqtt = mqtt, mqtt.connState == .connected else { return } diff --git a/Nynja/Services/PushService.swift b/Nynja/Services/PushService.swift index a3cac82de..1525a106b 100644 --- a/Nynja/Services/PushService.swift +++ b/Nynja/Services/PushService.swift @@ -33,9 +33,9 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab // MARK: - Setup - func registerForPushNotifications() { + func registerForNotifications() { registerForNativeNotifications() - registerForPushNotifications() + registerForPushKitNotifications() } private func registerForNativeNotifications() { diff --git a/Nynja/Services/ServiceFactory/ServiceFactory.swift b/Nynja/Services/ServiceFactory/ServiceFactory.swift index 686feb212..6ca43a469 100644 --- a/Nynja/Services/ServiceFactory/ServiceFactory.swift +++ b/Nynja/Services/ServiceFactory/ServiceFactory.swift @@ -51,6 +51,8 @@ protocol ServiceFactoryProtocol: SharedServiceFactoryProtocol { func makeHomeDataProvider(limit: Int) -> HomeDataProvider + func makePushService() -> PushService + func makeNynjaCommunicatorService() -> NynjaCommunicatorService func makeBadgeNumberService() -> BadgeNumberServiceProtocol @@ -58,6 +60,8 @@ protocol ServiceFactoryProtocol: SharedServiceFactoryProtocol { func makeNotificationManager() -> NotificationManager func makeUserSettingsService() -> UserSettingsService + + func makeReachabilityService() -> ReachabilityService } final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { @@ -199,6 +203,10 @@ final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { limit: limit))) } + func makePushService() -> PushService { + return .sharedInstance + } + func makeNynjaCommunicatorService() -> NynjaCommunicatorService { return .sharedInstance } @@ -214,4 +222,8 @@ final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { func makeUserSettingsService() -> UserSettingsService { return .shared } + + func makeReachabilityService() -> ReachabilityService { + return .sharedInstance + } } diff --git a/Shared/Services/Handlers/IoHandler/IoHandler.swift b/Shared/Services/Handlers/IoHandler/IoHandler.swift index 4ee13a7eb..58a1b1f52 100644 --- a/Shared/Services/Handlers/IoHandler/IoHandler.swift +++ b/Shared/Services/Handlers/IoHandler/IoHandler.swift @@ -69,13 +69,6 @@ final class IoHandler: BaseHandler, StaticDelegating { delegate { $0.attemptsExpired() } case "number_not_allowed": delegate { $0.numberNotAllowed() } - case "logout": - LogService.log(topic: .db) { return "Clear storage: IoHandler" } - storageService.clearStorage() - - mqttService.disconnect() - mqttService.reconnect() - delegate { $0.logout() } case "phone": if let roster = IO.data as? Roster { if let contact = roster.userlist?.first { diff --git a/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift b/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift index 47393593b..7620fa52b 100644 --- a/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift +++ b/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift @@ -19,7 +19,7 @@ protocol IoHandlerDelegate: class { func added() func invalidData() func callInProgress() - func logout() + func didLogout() func numberNotAllowed() func sessionsCleared() func sessionDeleted() @@ -46,7 +46,7 @@ extension IoHandlerDelegate { func added() {} func invalidData() {} func callInProgress() {} - func logout() {} + func didLogout() {} func sessionsCleared() {} func sessionDeleted() {} -- GitLab From 1b6f31dd21de9a1129e874ea3bf54dda896fc90d Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 17:53:06 +0200 Subject: [PATCH 30/38] Correct prev commit. --- .../Main/Interactor/MainInteractor.swift | 6 ++++-- .../Main/Presenter/MainPresenter.swift | 1 - .../Main/WireFrame/MainWireframe.swift | 20 +++++++++---------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Nynja/Modules/Main/Interactor/MainInteractor.swift b/Nynja/Modules/Main/Interactor/MainInteractor.swift index d5c63f015..16e1aa743 100644 --- a/Nynja/Modules/Main/Interactor/MainInteractor.swift +++ b/Nynja/Modules/Main/Interactor/MainInteractor.swift @@ -38,6 +38,7 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho override func loadData() { super.loadData() + ProfileHandler.delegate = self pushService.registerForNotifications() mqttService.addSubscriber(self) setupIntercom() @@ -101,13 +102,14 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho mqttService.deleteUser(number: phone) } LogService.log(topic: .db) { return "Clear storage: delete account" } - handleProfileDeleting() + presenter.showUILocker() } private func handleProfileDeleting() { cleanServices() alertManager.showAlertOk(message: String.localizable.authAttemptsRemoved) mqttService.reconnect() + presenter.hideUILocker() } private func cleanServices() { @@ -157,8 +159,8 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho } } - // MARK: MQTT subscribing + // MARK: - MQTTServiceDelegate func mqttServiceDidConnect(_ mqttService: MQTTService) { dispatchAsyncMain { [weak self] in diff --git a/Nynja/Modules/Main/Presenter/MainPresenter.swift b/Nynja/Modules/Main/Presenter/MainPresenter.swift index 8aa2b1bfe..6a2574f2f 100644 --- a/Nynja/Modules/Main/Presenter/MainPresenter.swift +++ b/Nynja/Modules/Main/Presenter/MainPresenter.swift @@ -240,7 +240,6 @@ final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorO func deleteAccount() { reachabilityService.performIfConnected { interactor.deleteAccount() - changeScreenToAuth() } } diff --git a/Nynja/Modules/Main/WireFrame/MainWireframe.swift b/Nynja/Modules/Main/WireFrame/MainWireframe.swift index 9d439b980..2b962c3fd 100644 --- a/Nynja/Modules/Main/WireFrame/MainWireframe.swift +++ b/Nynja/Modules/Main/WireFrame/MainWireframe.swift @@ -43,16 +43,16 @@ final class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelega interactor.inject( dependencies: .init( - presenter: presenter, - storageService: serviceFactory.makeStorageService(), - mqttService: serviceFactory.makeMQTTService(), - pushService: serviceFactory.makePushService(), - communicatorService: serviceFactory.makeNynjaCommunicatorService(), - badgeNumberService: serviceFactory.makeBadgeNumberService(), - notificationManager: serviceFactory.makeNotificationManager(), - userSettingsService: serviceFactory.makeUserSettingsService(), - syncFileManager: serviceFactory.makeSyncFileManager(with: .amazon), - alertManager: serviceFactory.makeAlertManager())) + presenter: presenter, + storageService: serviceFactory.makeStorageService(), + mqttService: serviceFactory.makeMQTTService(), + pushService: serviceFactory.makePushService(), + communicatorService: serviceFactory.makeNynjaCommunicatorService(), + badgeNumberService: serviceFactory.makeBadgeNumberService(), + notificationManager: serviceFactory.makeNotificationManager(), + userSettingsService: serviceFactory.makeUserSettingsService(), + syncFileManager: serviceFactory.makeSyncFileManager(with: .amazon), + alertManager: serviceFactory.makeAlertManager())) // set content view let contentNavigation = ContentNavigationVC() -- GitLab From e26ad6a9788fdd6fafe570348c74997f07c03d1e Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 17:53:28 +0200 Subject: [PATCH 31/38] Fix crash in `MQTTService` subscription. --- Nynja/Services/MQTT/MQTTService.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index df19f0adf..bf6a52ce3 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -245,14 +245,18 @@ final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, Conne // MARK: Subscribers func addSubscriber(_ subscriber: MQTTServiceDelegate) { - queuePool.subscribersQueue.async(flags: .barrier) { [unowned self] in - self.subscribers.append(WeakRef(value: subscriber)) + queuePool.subscribersQueue.async(flags: .barrier) { [unowned self, weak subscriber] in + if let subscriber = subscriber { + self.subscribers.append(WeakRef(value: subscriber)) + } } } func removeSubscriber(_ subscriber: MQTTServiceDelegate) { - queuePool.subscribersQueue.async(flags: .barrier) { [unowned self] in - self.subscribers = self.subscribers.filter { $0.value !== subscriber } + queuePool.subscribersQueue.async(flags: .barrier) { [unowned self, weak subscriber] in + if let subscriber = subscriber { + self.subscribers = self.subscribers.filter { $0.value !== subscriber } + } } } -- GitLab From e7ed3ab2bec2a235e9e787a246a988527c52e897 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 18:08:14 +0200 Subject: [PATCH 32/38] Make small refactoring inside some handlers. --- Nynja/MemberHandler.swift | 6 +++++- .../HandleServices/ProfileHandler.swift | 19 +++++++++++-------- .../Services/HandleServices/RoomHandler.swift | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Nynja/MemberHandler.swift b/Nynja/MemberHandler.swift index 2332ee5a9..d6a524011 100644 --- a/Nynja/MemberHandler.swift +++ b/Nynja/MemberHandler.swift @@ -8,6 +8,10 @@ class MemberHandler: BaseHandler { + private static var storageService: StorageService { + return .sharedInstance + } + static func executeHandle(data: BertTuple) { guard let member = get_Member().parse(bert: data) as? Member, let status = (member.status as? StringAtom)?.string else { @@ -20,7 +24,7 @@ class MemberHandler: BaseHandler { member.status = oldMember.status } - try? StorageService.sharedInstance.perform(action: .save, with: member) + try? storageService.perform(action: .save, with: member) default: return } diff --git a/Nynja/Services/HandleServices/ProfileHandler.swift b/Nynja/Services/HandleServices/ProfileHandler.swift index 9af1da022..88d150871 100644 --- a/Nynja/Services/HandleServices/ProfileHandler.swift +++ b/Nynja/Services/HandleServices/ProfileHandler.swift @@ -12,22 +12,25 @@ final class ProfileHandler: BaseHandler, StaticDelegating { // MARK: - Dependencies - static var mqttService: MQTTService { - return MQTTService.sharedInstance + private static var mqttService: MQTTService { + return .sharedInstance } - static var historyFactory: HistoryRequestModelFactoryProtocol { + private static var historyFactory: HistoryRequestModelFactoryProtocol { return HistoryRequestModelFactory() } - static var storageService: StorageService { - return StorageService.sharedInstance + private static var storageService: StorageService { + return .sharedInstance } - static var messageBackgroundTaskHandler: BackgroundTaskHandler { + private static var messageBackgroundTaskHandler: BackgroundTaskHandler { return MessageBackgroundTaskHandler() } + private static var communicatorService: NynjaCommunicatorService { + return .sharedInstance + } // MARK: - Handler @@ -156,7 +159,7 @@ final class ProfileHandler: BaseHandler, StaticDelegating { return } - NynjaCommunicatorService.sharedInstance.initialize() + communicatorService.initialize() } private static func requestJobs(with phoneId: String) { @@ -177,7 +180,7 @@ final class ProfileHandler: BaseHandler, StaticDelegating { } } - + // MARK: Remove private static func handleRemove(_ profile: Profile) { diff --git a/Nynja/Services/HandleServices/RoomHandler.swift b/Nynja/Services/HandleServices/RoomHandler.swift index 64928d097..a29be4c96 100644 --- a/Nynja/Services/HandleServices/RoomHandler.swift +++ b/Nynja/Services/HandleServices/RoomHandler.swift @@ -10,11 +10,11 @@ final class RoomHandler: BaseHandler { // MARK: - Dependencies - static var storageService: StorageService { + private static var storageService: StorageService { return .sharedInstance } - static var notificationManager: NotificationManager { + private static var notificationManager: NotificationManager { return .shared } -- GitLab From 11ac03a801db63c1860e138cc708fed70c1f9e19 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 18:26:45 +0200 Subject: [PATCH 33/38] Make small changes inside `ChatService` and `SystemSoundManager`. --- Nynja/ChatService/ChatService.swift | 4 +++- .../Audio/SystemSoundManager/SystemSoundManager.swift | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Nynja/ChatService/ChatService.swift b/Nynja/ChatService/ChatService.swift index 622c682f0..2cfad147c 100644 --- a/Nynja/ChatService/ChatService.swift +++ b/Nynja/ChatService/ChatService.swift @@ -10,7 +10,9 @@ final class ChatService { // MARK: - Dependencies - private static let storageService = StorageService.sharedInstance + private static var storageService: StorageService { + return .sharedInstance + } private static let messageParser = MessageParser(dependencies: .init(storageService: storageService)) diff --git a/Nynja/Services/Audio/SystemSoundManager/SystemSoundManager.swift b/Nynja/Services/Audio/SystemSoundManager/SystemSoundManager.swift index 8291eea75..bb06789be 100644 --- a/Nynja/Services/Audio/SystemSoundManager/SystemSoundManager.swift +++ b/Nynja/Services/Audio/SystemSoundManager/SystemSoundManager.swift @@ -47,11 +47,11 @@ final class SystemSoundManager { // MARK: - Play Sound func playSound(with url: URL) { - guard canPlaySound(with: url) else { - return - } - - dispatchAsyncMain { + dispatchAsyncMain { [unowned self] in + guard self.canPlaySound(with: url) else { + return + } + let soundId = self.makeSoundId(with: url) self.cachedSounds[url] = SoundInfo(soundId: soundId, lastTimeSoundPlayed: CFAbsoluteTimeGetCurrent()) AudioServicesPlaySystemSound(soundId) -- GitLab From d04b4a3a94c85d428ad70837fa1cbb8bc44c143d Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Wed, 14 Nov 2018 18:33:09 +0200 Subject: [PATCH 34/38] 1. Update `HistoryHandler`. 2. Remove unused code from `StickersDownloadingService`. --- Nynja/Services/HandleServices/HistoryHandler.swift | 6 +++--- .../StickersDownloadingService.swift | 13 ------------- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/Nynja/Services/HandleServices/HistoryHandler.swift b/Nynja/Services/HandleServices/HistoryHandler.swift index 4b8bb4a73..4a7180294 100644 --- a/Nynja/Services/HandleServices/HistoryHandler.swift +++ b/Nynja/Services/HandleServices/HistoryHandler.swift @@ -42,15 +42,15 @@ final class HistoryHandler: BaseHandler { // MARK: - Dependencies - static var storageService: StorageService { + private static var storageService: StorageService { return StorageService.sharedInstance } - static var messageEditService: MessageEditServiceProtocol { + private static var messageEditService: MessageEditServiceProtocol { return MessageEditService(dependencies: .init(storageService: storageService)) } - static let stickersDownloadingService: StickersDownloadingService = { + private static let stickersDownloadingService: StickersDownloadingService = { return StickersDownloadingService() }() diff --git a/Nynja/Services/StickersDownloadingService/StickersDownloadingService.swift b/Nynja/Services/StickersDownloadingService/StickersDownloadingService.swift index 438562db6..5eb64229b 100644 --- a/Nynja/Services/StickersDownloadingService/StickersDownloadingService.swift +++ b/Nynja/Services/StickersDownloadingService/StickersDownloadingService.swift @@ -11,19 +11,6 @@ import SDWebImage final class StickersDownloadingService { - private let operationQueue: OperationQueue - - - // MARK: - Init - - init() { - operationQueue = OperationQueue() - operationQueue.maxConcurrentOperationCount = 1 - } - - - // MARK: - Prefetching - func download(_ packages: [StickerPack]) { var urls = [URL]() for package in packages { -- GitLab From 2dcafe9b1d7446b8e283e71a2377d4807d9ffe1a Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 16 Nov 2018 11:15:31 +0200 Subject: [PATCH 35/38] Add `Release-Debug` scheme. --- .../NynjaUIKit.xcodeproj/project.pbxproj | 178 +++++++++++++++++ Nynja.xcodeproj/project.pbxproj | 182 ++++++++++++++++++ Nynja/Resources/ReleaseConfig.xcconfig | 2 +- 3 files changed, 361 insertions(+), 1 deletion(-) diff --git a/Frameworks/NynjaUIKit/NynjaUIKit.xcodeproj/project.pbxproj b/Frameworks/NynjaUIKit/NynjaUIKit.xcodeproj/project.pbxproj index 4b37699ee..6c1fa3dd9 100644 --- a/Frameworks/NynjaUIKit/NynjaUIKit.xcodeproj/project.pbxproj +++ b/Frameworks/NynjaUIKit/NynjaUIKit.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ /* Begin PBXFileReference section */ 1820AD65D6897E3E306C16A2 /* Pods-NynjaUIKit.translate.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.translate.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.translate.xcconfig"; sourceTree = ""; }; + 1D38BAE43B22E6C930DB3980 /* Pods-NynjaUIKit.release-debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.release-debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.release-debug.xcconfig"; sourceTree = ""; }; 600B9308D041B8E4DE0DBEF1 /* Pods-NynjaUIKit.loaddb.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.loaddb.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.loaddb.xcconfig"; sourceTree = ""; }; 7336042AC840197E622730FD /* Pods-NynjaUIKit.prerelease.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.prerelease.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.prerelease.xcconfig"; sourceTree = ""; }; 8514D4C120EE27080002378A /* NynjaUIKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NynjaUIKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -67,6 +68,7 @@ B90E6396110C47D18FB00838 /* Pods-NynjaUIKit.dev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.dev.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.dev.xcconfig"; sourceTree = ""; }; C6C80841C9BA48F16147BAAE /* Pods_NynjaUIKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NynjaUIKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C90742AD8E6E2E817F7DB1E9 /* Pods-NynjaUIKit.channels.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.channels.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.channels.xcconfig"; sourceTree = ""; }; + E05C445073991174833FDBC7 /* Pods-NynjaUIKit.spotify.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.spotify.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.spotify.xcconfig"; sourceTree = ""; }; E966C049045184395EBB9166 /* Pods-NynjaUIKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.release.xcconfig"; sourceTree = ""; }; F6A55196057E1D4A2F24AC17 /* Pods-NynjaUIKit.devautotests.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUIKit.devautotests.xcconfig"; path = "../../Pods/Target Support Files/Pods-NynjaUIKit/Pods-NynjaUIKit.devautotests.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -93,6 +95,8 @@ E966C049045184395EBB9166 /* Pods-NynjaUIKit.release.xcconfig */, 7336042AC840197E622730FD /* Pods-NynjaUIKit.prerelease.xcconfig */, 600B9308D041B8E4DE0DBEF1 /* Pods-NynjaUIKit.loaddb.xcconfig */, + E05C445073991174833FDBC7 /* Pods-NynjaUIKit.spotify.xcconfig */, + 1D38BAE43B22E6C930DB3980 /* Pods-NynjaUIKit.release-debug.xcconfig */, ); name = Pods; sourceTree = ""; @@ -521,6 +525,176 @@ }; name = LoadDB; }; + 4B31B845219DE57F00837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E966C049045184395EBB9166 /* Pods-NynjaUIKit.release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Release-Debug"; + }; + 4B31B846219DE57F00837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1D38BAE43B22E6C930DB3980 /* Pods-NynjaUIKit.release-debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = NynjaUIKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.nynja.mobile.communicator.NynjaUIKit; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Release-Debug"; + }; + 4B31B847219DE58D00837B59 /* Spotify */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B90E6396110C47D18FB00838 /* Pods-NynjaUIKit.dev.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Spotify; + }; + 4B31B848219DE58D00837B59 /* Spotify */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E05C445073991174833FDBC7 /* Pods-NynjaUIKit.spotify.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = NynjaUIKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.nynja.mobile.communicator.NynjaUIKit; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Spotify; + }; 8514D4C820EE27080002378A /* Dev */ = { isa = XCBuildConfiguration; baseConfigurationReference = B90E6396110C47D18FB00838 /* Pods-NynjaUIKit.dev.xcconfig */; @@ -868,9 +1042,11 @@ isa = XCConfigurationList; buildConfigurations = ( 8514D4C820EE27080002378A /* Dev */, + 4B31B847219DE58D00837B59 /* Spotify */, 2611CEEC21807A6E00FFD4DD /* LoadDB */, 85631BF220EFC50F0002BE51 /* DevAutoTests */, 85631BF020EFC4FC0002BE51 /* Release */, + 4B31B845219DE57F00837B59 /* Release-Debug */, 85631BEE20EFC4F30002BE51 /* Prerelease */, ); defaultConfigurationIsVisible = 0; @@ -880,9 +1056,11 @@ isa = XCConfigurationList; buildConfigurations = ( 8514D4CB20EE27080002378A /* Dev */, + 4B31B848219DE58D00837B59 /* Spotify */, 2611CEED21807A6E00FFD4DD /* LoadDB */, 85631BF320EFC50F0002BE51 /* DevAutoTests */, 85631BF120EFC4FC0002BE51 /* Release */, + 4B31B846219DE57F00837B59 /* Release-Debug */, 85631BEF20EFC4F30002BE51 /* Prerelease */, ); defaultConfigurationIsVisible = 0; diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index b1b2af8e0..5e4df7aa5 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -3473,6 +3473,7 @@ 9BD8E41220F3A2E2001384EC /* CallInProgressInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInProgressInteractor.swift; sourceTree = ""; }; 9BE521212189B2E10070C664 /* ThreeButtonHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreeButtonHeaderView.swift; sourceTree = ""; }; 9BFFE61A2178DCFF004FE2CA /* BannerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BannerView.swift; sourceTree = ""; }; + 9C2E07BBF40570582F4258A3 /* Pods-Nynja.release-debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nynja.release-debug.xcconfig"; path = "Pods/Target Support Files/Pods-Nynja/Pods-Nynja.release-debug.xcconfig"; sourceTree = ""; }; 9C4192D925259B75441492A9 /* FavoritesPresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FavoritesPresenter.swift; sourceTree = ""; }; 9DE44A136617140435B23343 /* GroupStorageWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GroupStorageWireframe.swift; sourceTree = ""; }; 9E82188EE0AC1D1C05470692 /* Pods-NynjaUnitTests.channels.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUnitTests.channels.xcconfig"; path = "Pods/Target Support Files/Pods-NynjaUnitTests/Pods-NynjaUnitTests.channels.xcconfig"; sourceTree = ""; }; @@ -3891,6 +3892,7 @@ B28D1FE755A0457DBEDAC068 /* MapSearchProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MapSearchProtocols.swift; sourceTree = ""; }; B2B221F69CB3D5C6A1B12456 /* VideoPreviewInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = VideoPreviewInteractor.swift; sourceTree = ""; }; B2EF4EFCD3C9DE0B69FC40F9 /* TimeZoneSelectorWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimeZoneSelectorWireframe.swift; sourceTree = ""; }; + B3D64F28A0B75CE6D74100B1 /* Pods-Nynja-Share.release-debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nynja-Share.release-debug.xcconfig"; path = "Pods/Target Support Files/Pods-Nynja-Share/Pods-Nynja-Share.release-debug.xcconfig"; sourceTree = ""; }; B4DC9EF9D78D3F5C48B00EF3 /* ScheduleMessageWireframe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ScheduleMessageWireframe.swift; sourceTree = ""; }; B62646CA6345B6C5AD0C87A0 /* ScheduleMessagePresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ScheduleMessagePresenter.swift; sourceTree = ""; }; B7121EB7205045F300AABBE6 /* MediaDownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaDownloadManager.swift; sourceTree = ""; }; @@ -3997,6 +3999,7 @@ CBE3BAC9B7EA418FB463EF04 /* EditUsernameInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = EditUsernameInteractor.swift; sourceTree = ""; }; CCA291E1CE928BC100DD6353 /* Pods-Nynja-Share.translate.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Nynja-Share.translate.xcconfig"; path = "Pods/Target Support Files/Pods-Nynja-Share/Pods-Nynja-Share.translate.xcconfig"; sourceTree = ""; }; CDF62E1A004579220E231142 /* LoginProtocols.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LoginProtocols.swift; sourceTree = ""; }; + CEBE788F463F17C3CCD8302A /* Pods-NynjaUnitTests.release-debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NynjaUnitTests.release-debug.xcconfig"; path = "Pods/Target Support Files/Pods-NynjaUnitTests/Pods-NynjaUnitTests.release-debug.xcconfig"; sourceTree = ""; }; D1AE7296B9A53355289740D1 /* ProfilePresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProfilePresenter.swift; sourceTree = ""; }; D1D5302025583482829BBF2E /* GroupStorageViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = GroupStorageViewController.swift; sourceTree = ""; }; D270F638DBB2D8FC1BDEB633 /* ProfileViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = ""; }; @@ -7727,6 +7730,9 @@ 7ADCB0C891B31AF691307B4F /* Pods-Nynja.spotify.xcconfig */, 7F7FC209C7703E3E7617D782 /* Pods-Nynja-Share.spotify.xcconfig */, A0A57BD401783039D49B7B75 /* Pods-NynjaUnitTests.spotify.xcconfig */, + 9C2E07BBF40570582F4258A3 /* Pods-Nynja.release-debug.xcconfig */, + B3D64F28A0B75CE6D74100B1 /* Pods-Nynja-Share.release-debug.xcconfig */, + CEBE788F463F17C3CCD8302A /* Pods-NynjaUnitTests.release-debug.xcconfig */, ); name = Pods; sourceTree = ""; @@ -17359,6 +17365,7 @@ PROVISIONING_PROFILE = "2a318f9e-d0ab-41dc-968a-e1cb13de4de5"; PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_AppstoreExt; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = RELEASE; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; @@ -17546,6 +17553,176 @@ }; name = Release; }; + 4B31B83F219DE52000837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F1313B0020888CC400E04092 /* ReleaseConfig.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_WHOLE_MODULE_OPTIMIZATION = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = "Release-Debug"; + }; + 4B31B840219DE52000837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9C2E07BBF40570582F4258A3 /* Pods-Nynja.release-debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Nynja/Resources/Nynja.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 9GKQ5AMF2B; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = "$(SRCROOT)/Nynja/Resources/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "$(BundleIdentifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "1971b115-2b2c-48b6-a20f-3686249e0a88"; + PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_Appstore; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_BRIDGING_HEADER = "Nynja-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; + SWIFT_WHOLE_MODULE_OPTIMIZATION = YES; + }; + name = "Release-Debug"; + }; + 4B31B841219DE52000837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B3D64F28A0B75CE6D74100B1 /* Pods-Nynja-Share.release-debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = "Nynja-Share/Resources/Nynja-Share.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CODE_SIGN_STYLE = Manual; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 9GKQ5AMF2B; + ENABLE_BITCODE = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = "Nynja-Share/Resources/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" -DSHARE_EXTENSION"; + PRODUCT_BUNDLE_IDENTIFIER = "$(ExtensionBundleIdentifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "2a318f9e-d0ab-41dc-968a-e1cb13de4de5"; + PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_AppstoreExt; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Release-Debug"; + }; + 4B31B842219DE52000837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CEBE788F463F17C3CCD8302A /* Pods-NynjaUnitTests.release-debug.xcconfig */; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 9GKQ5AMF2B; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = NynjaUnitTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.nynja.mobile.communicator.NynjaUnitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = "Release-Debug"; + }; + 4B31B843219DE52000837B59 /* Release-Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 9GKQ5AMF2B; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = NynjaIntegrationTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.nynja.dev.mobile.communicator.NynjaIntegrationTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nynja.app/Nynja"; + }; + name = "Release-Debug"; + }; 5B4DFF6D2191A08E00E89D17 /* Spotify */ = { isa = XCBuildConfiguration; baseConfigurationReference = 5B4DFF6C21919FA000E89D17 /* SpotifyConfig.xcconfig */; @@ -18400,6 +18577,7 @@ F10AFE9E20EF8BBE00C7CE83 /* DevAutoTests */, F1313AFD20888BD300E04092 /* Prerelease */, 357809AF1F9765CF00C9680C /* Release */, + 4B31B841219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18413,6 +18591,7 @@ F10AFE9C20EF8BBE00C7CE83 /* DevAutoTests */, F1313AFB20888BD300E04092 /* Prerelease */, 3ABCE8FE1EC9330D00A80B15 /* Release */, + 4B31B83F219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18426,6 +18605,7 @@ F10AFE9D20EF8BBE00C7CE83 /* DevAutoTests */, F1313AFC20888BD300E04092 /* Prerelease */, 3ABCE9011EC9330D00A80B15 /* Release */, + 4B31B840219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18439,6 +18619,7 @@ F10AFE9F20EF8BBE00C7CE83 /* DevAutoTests */, F1C37AB1209A1BF4005EA197 /* Prerelease */, F1C37AB2209A1BF4005EA197 /* Release */, + 4B31B842219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18452,6 +18633,7 @@ FE21ACB02113AA7F006010A0 /* DevAutoTests */, FE21ACB32113AA7F006010A0 /* Prerelease */, FE21ACB42113AA7F006010A0 /* Release */, + 4B31B843219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Nynja/Resources/ReleaseConfig.xcconfig b/Nynja/Resources/ReleaseConfig.xcconfig index f8b763d10..f65b25f2e 100644 --- a/Nynja/Resources/ReleaseConfig.xcconfig +++ b/Nynja/Resources/ReleaseConfig.xcconfig @@ -14,7 +14,7 @@ AppName = NYNJA ServerPort = 8443 Config = release AppGroup = group.com.nynja.mobile.communicator -ModelsVersion = 9 +ModelsVersion = 10 isServerConnectionSecure = true ConfServerAddress = call.nynja.net ConfServerPort = 443 -- GitLab From 0f37d305d5eed8f4cb5c182642f223d133332ca6 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 16 Nov 2018 20:58:32 +0200 Subject: [PATCH 36/38] Make working with subscribers thread-safe inside `DBObserver`. --- Nynja/DBObserver.swift | 4 ++ Nynja/Improvements/StorageObserver.swift | 47 +++++++++++++++++------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Nynja/DBObserver.swift b/Nynja/DBObserver.swift index 33b411fbf..d7efa23fb 100644 --- a/Nynja/DBObserver.swift +++ b/Nynja/DBObserver.swift @@ -20,9 +20,13 @@ final class DBObserver: StorageObserver, TransactionObserver { label: String.label(withSuffix: "db-observer.processing-queue"), qos: .utility) + // MARK: - Properties + var subscribers: [SubscribeType: [StorageSubscriberReference]] = [:] + let isolationQueue = DispatchQueue(label: String.label(withSuffix: "db-observer.isolation-queue")) + private var allChanges: Dictionary = [:] private let tableNames: [String] = { diff --git a/Nynja/Improvements/StorageObserver.swift b/Nynja/Improvements/StorageObserver.swift index 83d8b76a8..299312bc0 100644 --- a/Nynja/Improvements/StorageObserver.swift +++ b/Nynja/Improvements/StorageObserver.swift @@ -9,6 +9,8 @@ protocol StorageObserver : class { var subscribers: [SubscribeType: [StorageSubscriberReference]] { get set } + var isolationQueue: DispatchQueue { get } + func register(subscriber: StorageSubscriber, type: SubscribeType) func unregister(subscriber: StorageSubscriber, type: SubscribeType) func unregister(subscribers type: SubscribeType) @@ -19,12 +21,18 @@ protocol StorageObserver : class { extension StorageObserver { func register(subscriber: StorageSubscriber, type: SubscribeType) { - let reference = StorageSubscriberReference(subscriber) - if var subs = subscribers[type] { - subs.append(reference) - subscribers[type] = subs - } else { - subscribers[type] = [reference] + isolationQueue.async { [weak self] in + guard let `self` = self else { + return + } + + let reference = StorageSubscriberReference(subscriber) + if var subs = self.subscribers[type] { + subs.append(reference) + self.subscribers[type] = subs + } else { + self.subscribers[type] = [reference] + } } } @@ -35,11 +43,19 @@ extension StorageObserver { } func unregister(subscriber: StorageSubscriber, type: SubscribeType) { - subscribers[type] = subscribers[type]?.filter { $0.subscriber != nil && $0.subscriber?.id != subscriber.id } + isolationQueue.async { [weak self] in + guard let `self` = self else { + return + } + + self.subscribers[type] = self.subscribers[type]?.filter { $0.subscriber != nil && $0.subscriber?.id != subscriber.id } + } } func unregister(subscribers type: SubscribeType) { - subscribers.removeValue(forKey: type) + isolationQueue.async { [weak self] in + self?.subscribers.removeValue(forKey: type) + } } func unregister(subscriber: StorageSubscriber) { @@ -49,12 +65,15 @@ extension StorageObserver { } func notify(with changes: [StorageChange], type: SubscribeType) { - guard let subscribers = subscribers[type] else { - return - } - for subscriberRef in subscribers { - dispatchAsyncMain { - subscriberRef.subscriber?.update(with: changes, type: type) + isolationQueue.sync { [weak self] in + guard let subscribers = self?.subscribers[type] else { + return + } + + for subscriberRef in subscribers { + dispatchAsyncMain { + subscriberRef.subscriber?.update(with: changes, type: type) + } } } } -- GitLab From f9cc47d277512949947ddab6f37a7998f985a400 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Fri, 16 Nov 2018 21:01:14 +0200 Subject: [PATCH 37/38] 1. Correct usage of `subscribersQueue` inside `MQTTService`. 2. Remove unnecessary usage of `dispatchMainAsync`. --- Nynja.xcodeproj/project.pbxproj | 1 + Nynja/Modules/Main/Interactor/MainInteractor.swift | 10 +++------- .../MQTT/Extensions/MQTTService+QueuePool.swift | 5 +---- Nynja/Services/MQTT/MQTTService.swift | 6 +++--- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index 5e4df7aa5..e2f9099bb 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -17626,6 +17626,7 @@ INFOPLIST_FILE = "$(SRCROOT)/Nynja/Resources/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + OTHER_SWIFT_FLAGS = "$(inherited) -D SQLITE_HAS_CODEC -D GRDBCIPHER $(inherited) \"-D\" \"COCOAPODS\" -Xfrontend -debug-time-function-bodies -Xfrontend -warn-long-expression-type-checking=20 -Xfrontend -warn-long-function-bodies=20"; PRODUCT_BUNDLE_IDENTIFIER = "$(BundleIdentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "1971b115-2b2c-48b6-a20f-3686249e0a88"; diff --git a/Nynja/Modules/Main/Interactor/MainInteractor.swift b/Nynja/Modules/Main/Interactor/MainInteractor.swift index 16e1aa743..244af25b0 100644 --- a/Nynja/Modules/Main/Interactor/MainInteractor.swift +++ b/Nynja/Modules/Main/Interactor/MainInteractor.swift @@ -163,16 +163,12 @@ final class MainInteractor: BaseInteractor, MainInteractorInputProtocol, EditPho // MARK: - MQTTServiceDelegate func mqttServiceDidConnect(_ mqttService: MQTTService) { - dispatchAsyncMain { [weak self] in - self?.presenter.hideUILocker() - } + presenter.hideUILocker() } func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) { - dispatchAsyncMain { [weak self] in - self?.logout() - self?.presenter.changeScreenToAuth() - } + logout() + presenter.changeScreenToAuth() } private func setupIntercom() { diff --git a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift index dcbe6b5bd..81257299c 100644 --- a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift +++ b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift @@ -11,10 +11,7 @@ import Foundation extension MQTTService { struct QueuePool { - let subscribersQueue = DispatchQueue( - label: String.label(withSuffix: "mqtt-service.subscribers-queue"), - attributes: .concurrent) - + let subscribersQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.subscribers-queue")) let loggingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.logging-queue")) let processingQueue = DispatchQueue( label: String.label(withSuffix: "mqtt-service.processing-queue"), diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index bf6a52ce3..9272ea851 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -245,7 +245,7 @@ final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, Conne // MARK: Subscribers func addSubscriber(_ subscriber: MQTTServiceDelegate) { - queuePool.subscribersQueue.async(flags: .barrier) { [unowned self, weak subscriber] in + queuePool.subscribersQueue.async { [unowned self, weak subscriber] in if let subscriber = subscriber { self.subscribers.append(WeakRef(value: subscriber)) } @@ -253,7 +253,7 @@ final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, Conne } func removeSubscriber(_ subscriber: MQTTServiceDelegate) { - queuePool.subscribersQueue.async(flags: .barrier) { [unowned self, weak subscriber] in + queuePool.subscribersQueue.async { [unowned self, weak subscriber] in if let subscriber = subscriber { self.subscribers = self.subscribers.filter { $0.value !== subscriber } } @@ -261,7 +261,7 @@ final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, Conne } func removeAllSubscribers() { - queuePool.subscribersQueue.async(flags: .barrier) { [unowned self] in + queuePool.subscribersQueue.async { [unowned self] in self.subscribers.removeAll() } } -- GitLab From 8c67d39b79d8d691a2152b2c16aef4cc28385f69 Mon Sep 17 00:00:00 2001 From: Volodymyr Hryhoriev Date: Mon, 19 Nov 2018 17:13:16 +0200 Subject: [PATCH 38/38] Use 'main queue' for work with responses. --- Nynja.xcodeproj/project.pbxproj | 14 +++++++------- .../MQTT/Extensions/MQTTService+QueuePool.swift | 8 +++++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index e2f9099bb..0f0747971 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -17349,7 +17349,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = "Nynja-Share/Resources/Nynja-Share.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -17529,7 +17529,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Nynja/Resources/Nynja.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -17617,7 +17617,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Nynja/Resources/Nynja.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; @@ -17629,8 +17629,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) -D SQLITE_HAS_CODEC -D GRDBCIPHER $(inherited) \"-D\" \"COCOAPODS\" -Xfrontend -debug-time-function-bodies -Xfrontend -warn-long-expression-type-checking=20 -Xfrontend -warn-long-function-bodies=20"; PRODUCT_BUNDLE_IDENTIFIER = "$(BundleIdentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "1971b115-2b2c-48b6-a20f-3686249e0a88"; - PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_Appstore; + PROVISIONING_PROFILE = "e08a86e7-d3c6-4351-bfa9-7e563b2b7cba"; + PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_Dev; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OBJC_BRIDGING_HEADER = "Nynja-Bridging-Header.h"; @@ -17662,8 +17662,8 @@ OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" -DSHARE_EXTENSION"; PRODUCT_BUNDLE_IDENTIFIER = "$(ExtensionBundleIdentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "2a318f9e-d0ab-41dc-968a-e1cb13de4de5"; - PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_AppstoreExt; + PROVISIONING_PROFILE = "3e08568d-8d8f-426c-bf4c-0f12f19252e5"; + PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_DevExt; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift index 81257299c..077d7db17 100644 --- a/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift +++ b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift @@ -16,8 +16,10 @@ extension MQTTService { let processingQueue = DispatchQueue( label: String.label(withSuffix: "mqtt-service.processing-queue"), qos: .utility) - let receivingQueue = DispatchQueue( - label: String.label(withSuffix: "mqtt-service.receiving-queue"), - qos: .utility) + let receivingQueue = DispatchQueue.main + // NOTE: can't use background queue because of undetermined crash. +// DispatchQueue( +// label: String.label(withSuffix: "mqtt-service.receiving-queue"), +// qos: .utility) } } -- GitLab