diff --git a/Frameworks/NynjaUIKit/NynjaUIKit.xcodeproj/project.pbxproj b/Frameworks/NynjaUIKit/NynjaUIKit.xcodeproj/project.pbxproj index 4b37699eec6e4ffcb4841a7193948e4d8df98971..6c1fa3dd90b9fea6199b109577608d13731cf863 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-Share/UI/ForwardSelector/View/ForwardSelectorViewController.swift b/Nynja-Share/UI/ForwardSelector/View/ForwardSelectorViewController.swift index 19a61f0c3baf93177b8fc5fa5a88e5983fdd1b13..1575fcb7680f5d9e15adbd137ffc981e3ea2e21f 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 762c283e46d7c3be97af03481f0e6d645e5c6c56..0f0747971d09db74eb890e498054de5e8e406c4e 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 */; }; @@ -143,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 */; }; @@ -470,7 +467,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 */; }; @@ -519,7 +516,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 */; }; @@ -542,8 +539,25 @@ 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 */; }; + 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 */; }; + 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 */; }; + 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 */; }; + 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 */; }; @@ -560,6 +574,10 @@ 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 */; }; + 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 */; }; @@ -655,6 +673,9 @@ 4B877137219315770014AD09 /* QueryInterfaceRequestExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B877136219315770014AD09 /* QueryInterfaceRequestExtension.swift */; }; 4B877139219315AA0014AD09 /* SercerModelConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B877138219315AA0014AD09 /* SercerModelConvertible.swift */; }; 4B87713B219328780014AD09 /* QueryArgs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B87713A219328780014AD09 /* QueryArgs.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 */; }; @@ -1491,8 +1512,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 */; }; @@ -2448,7 +2467,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 = ""; }; @@ -2525,7 +2543,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 = ""; }; @@ -2804,7 +2821,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 = ""; }; @@ -2835,7 +2852,17 @@ 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 = ""; }; + 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 = ""; }; + 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 = ""; }; @@ -2855,6 +2882,8 @@ 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 = ""; }; + 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 = ""; }; @@ -2937,6 +2966,9 @@ 4B877136219315770014AD09 /* QueryInterfaceRequestExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryInterfaceRequestExtension.swift; sourceTree = ""; }; 4B877138219315AA0014AD09 /* SercerModelConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SercerModelConvertible.swift; sourceTree = ""; }; 4B87713A219328780014AD09 /* QueryArgs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryArgs.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 = ""; }; @@ -3441,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 = ""; }; @@ -3604,7 +3637,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 = ""; }; @@ -3860,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 = ""; }; @@ -3966,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 = ""; }; @@ -5943,21 +5977,18 @@ isa = PBXGroup; children = ( A497F56520EFA517005CC60F /* Base */, + 4B8771752195ABE80014AD09 /* MessageHandler */, + 4B8771762195AC3C0014AD09 /* HistoryHandler */, + 4B8771792195AF7E0014AD09 /* TypingHandler */, + 4B0CC2002195B67D00E0BA61 /* LinkHandler */, + 4B055C3D219C618B001FE077 /* ProfileHandler */, 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 */, 0008E91A20333A38003E316E /* JobHandler.swift */, 855EF424202CCADB00541BE3 /* ExtendedStarHandler.swift */, - 00E9825B205FD351008BF03D /* AuthHandler.swift */, - A48C154320EF7A15002DA994 /* LinkHandler.swift */, ); name = Handlers; sourceTree = ""; @@ -6073,16 +6104,12 @@ 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 */, + 4B055C3A219C4101001FE077 /* MQTTServiceProtocol.swift */, ); name = MQTT; path = Services/MQTT; @@ -6469,6 +6496,65 @@ path = DateTime; sourceTree = ""; }; + 4B030F2A2195BFF300F293B7 /* AuthHandler */ = { + isa = PBXGroup; + children = ( + 4B030F2B2195BFF300F293B7 /* AuthHandlerDelegate.swift */, + 4B030F2C2195BFF300F293B7 /* AuthHandler.swift */, + ); + 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 = ""; + }; + 4B055C35219C30F5001FE077 /* FileDownloaderFactory */ = { + isa = PBXGroup; + children = ( + 4B055C36219C313A001FE077 /* FileDownloaderFactory.swift */, + 4B055C38219C3146001FE077 /* FileDownloaderKind.swift */, + ); + path = FileDownloaderFactory; + sourceTree = ""; + }; + 4B055C3D219C618B001FE077 /* ProfileHandler */ = { + isa = PBXGroup; + children = ( + 3A771CA91F191B38008D968A /* ProfileHandler.swift */, + 4B055C3E219C61A2001FE077 /* ProfileHandlerDelegate.swift */, + ); + name = ProfileHandler; + sourceTree = ""; + }; 4B058EF9204EA6EE004C7D9F /* DB */ = { isa = PBXGroup; children = ( @@ -6601,6 +6687,24 @@ name = Chat; sourceTree = ""; }; + 4B0CC1FB2195B3C200E0BA61 /* IoHandler */ = { + isa = PBXGroup; + children = ( + 3A1DC73E1EF15B65006A8E9F /* IoHandler.swift */, + 4B0CC1FC2195B52000E0BA61 /* IoHandlerDelegate.swift */, + ); + path = IoHandler; + sourceTree = ""; + }; + 4B0CC2002195B67D00E0BA61 /* LinkHandler */ = { + isa = PBXGroup; + children = ( + A48C154320EF7A15002DA994 /* LinkHandler.swift */, + 4B0CC2012195B69900E0BA61 /* LinkHandlerDelegate.swift */, + ); + name = LinkHandler; + sourceTree = ""; + }; 4B0DBA892137F6F800D79163 /* ChatService */ = { isa = PBXGroup; children = ( @@ -6981,6 +7085,33 @@ path = ServiceFactory; 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 = ""; + }; + 4B8771792195AF7E0014AD09 /* TypingHandler */ = { + isa = PBXGroup; + children = ( + 263D66321FE8D95100A509F8 /* TypingHandler.swift */, + 4B87717A2195AF9D0014AD09 /* TypingHandlerDelegate.swift */, + ); + name = TypingHandler; + sourceTree = ""; + }; 4B8996C6204ECE8500DCB183 /* Contact */ = { isa = PBXGroup; children = ( @@ -7599,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 = ""; @@ -10035,7 +10169,7 @@ isa = PBXGroup; children = ( A4330A642109DFA00060BD93 /* UserInfo.swift */, - A4330A732109F0D40060BD93 /* StorageService+UserInfo.swift */, + 4B030F3D2195D88100F293B7 /* UserInfoImpl.swift */, ); name = UserInfo; sourceTree = ""; @@ -10875,6 +11009,7 @@ A49E1BCA20A9A6880074DFD3 /* Library */ = { isa = PBXGroup; children = ( + 4B87717C2195AFF50014AD09 /* StaticDelegating.swift */, A4C92FFC20B323B600D6FB0F /* Extensions */, A49E1BCB20A9A68D0074DFD3 /* Models */, ); @@ -10929,8 +11064,9 @@ isa = PBXGroup; children = ( A497F56C20EFA86F005CC60F /* Base */, + 4B0CC1FB2195B3C200E0BA61 /* IoHandler */, + 4B030F2A2195BFF300F293B7 /* AuthHandler */, A497F56D20EFA8B6005CC60F /* ErrorsHandler.swift */, - 3A1DC73E1EF15B65006A8E9F /* IoHandler.swift */, ); path = Handlers; sourceTree = ""; @@ -12913,6 +13049,7 @@ F11786EF20AC5474007A9A1B /* ServiceFactory */ = { isa = PBXGroup; children = ( + 4B055C35219C30F5001FE077 /* FileDownloaderFactory */, F11786F020AC5482007A9A1B /* ServiceFactory.swift */, ); name = ServiceFactory; @@ -14563,6 +14700,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 */, @@ -14574,6 +14712,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 */, @@ -14603,6 +14742,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 */, @@ -14635,8 +14775,7 @@ 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 */, + 359EB27C1F9A2C8C00147437 /* MQTTService+Helper.swift in Sources */, 4B5A0B74216E3BDD002C4160 /* ForwardAvatarViewModel.swift in Sources */, A4B544F020EFB4EC00EB7B0F /* BertTupleExtension.swift in Sources */, 4BF090CF2163601400DCCA5C /* Message+LinkedId.swift in Sources */, @@ -14677,6 +14816,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 */, @@ -14685,10 +14825,10 @@ 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 */, - A4330A752109F0D40060BD93 /* StorageService+UserInfo.swift in Sources */, 26C0C1CA2073C93400C530DA /* ForwardContent.swift in Sources */, 263529132075725200DC6FBD /* SendJob.swift in Sources */, 35B98F9B1F9B956F009B8DEC /* StringExtensions.swift in Sources */, @@ -14700,6 +14840,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 */, @@ -14748,6 +14889,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 */, @@ -14770,6 +14912,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 */, @@ -14871,6 +15014,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 */, @@ -14927,7 +15071,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 */, @@ -14970,6 +15114,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 */, @@ -15242,6 +15387,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 */, @@ -15327,6 +15473,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 */, @@ -15383,7 +15530,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 */, @@ -15539,6 +15685,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 */, @@ -15627,7 +15774,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 */, @@ -15662,6 +15808,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 */, @@ -15742,6 +15889,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 */, @@ -15784,12 +15932,14 @@ 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 */, 85D66A1220BD965300FBD803 /* UserMentionTableViewCell.swift in Sources */, 4BB35E23219AF46E0007C18E /* RosterRelatedQueryArgs.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 */, @@ -16119,6 +16269,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 */, @@ -16278,6 +16429,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 */, @@ -16337,6 +16489,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 */, @@ -16488,6 +16641,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 */, @@ -16571,7 +16725,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 */, @@ -16581,6 +16734,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 */, @@ -16591,6 +16745,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 */, @@ -16605,6 +16760,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 */, @@ -17193,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"; @@ -17209,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; @@ -17372,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"; @@ -17396,6 +17553,177 @@ }; 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 Developer"; + 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"; + 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 = "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"; + 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 = "3e08568d-8d8f-426c-bf4c-0f12f19252e5"; + PROVISIONING_PROFILE_SPECIFIER = ProductionBundle_DevExt; + 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 */; @@ -18250,6 +18578,7 @@ F10AFE9E20EF8BBE00C7CE83 /* DevAutoTests */, F1313AFD20888BD300E04092 /* Prerelease */, 357809AF1F9765CF00C9680C /* Release */, + 4B31B841219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18263,6 +18592,7 @@ F10AFE9C20EF8BBE00C7CE83 /* DevAutoTests */, F1313AFB20888BD300E04092 /* Prerelease */, 3ABCE8FE1EC9330D00A80B15 /* Release */, + 4B31B83F219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18276,6 +18606,7 @@ F10AFE9D20EF8BBE00C7CE83 /* DevAutoTests */, F1313AFC20888BD300E04092 /* Prerelease */, 3ABCE9011EC9330D00A80B15 /* Release */, + 4B31B840219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18289,6 +18620,7 @@ F10AFE9F20EF8BBE00C7CE83 /* DevAutoTests */, F1C37AB1209A1BF4005EA197 /* Prerelease */, F1C37AB2209A1BF4005EA197 /* Release */, + 4B31B842219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -18302,6 +18634,7 @@ FE21ACB02113AA7F006010A0 /* DevAutoTests */, FE21ACB32113AA7F006010A0 /* Prerelease */, FE21ACB42113AA7F006010A0 /* Release */, + 4B31B843219DE52000837B59 /* Release-Debug */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Nynja/AppDelegate.swift b/Nynja/AppDelegate.swift index 332ecf388e8093ea60d5c0bc18587aecc72f37e8..7ce25040daffd7af49c913415f1a448bce452024 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/ChatService/ChatService.swift b/Nynja/ChatService/ChatService.swift index 622c682f04b9a2ba04e6e7539a7ad9328715f293..2cfad147cc51bc7e760440d2f50fb1c32cbd3523 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/DBObserver.swift b/Nynja/DBObserver.swift index 37e28e9b08f31ef12889ea0760728652e9e833a6..d7efa23fb54128a856969c4f948c2166b862a346 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() {} @@ -18,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/ExtendedStarHandler.swift b/Nynja/ExtendedStarHandler.swift index 0322062f2e031322ad7f8afdbbb6ff2e5b64bf09..184b5d6a093c462ff1dd25e627971968f3473d87 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,7 +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 c94fbcbee74bc48dd6bffb23471d432beba6e071..6313b5934bd936ade160a0f24d101b126c343010 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 92f9b54947e0d1249403346a160f3fdfae37ca5c..fc256fa32a707c08ba3bc72a26362f5678408438 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/HistoryHandlerSubscriber.swift b/Nynja/HistoryHandlerSubscriber.swift new file mode 100644 index 0000000000000000000000000000000000000000..08580e95082b0d631cb3901067284a82b2c2caeb --- /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/Improvements/StorageObserver.swift b/Nynja/Improvements/StorageObserver.swift index 83d8b76a878e332fe3dd6336f2bbea11241ae9a0..299312bc0e6d0b9b2e66cb8272baa1904b6d0230 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) + } } } } diff --git a/Nynja/JobHandler.swift b/Nynja/JobHandler.swift index cbf72bb791a2cebc289622668adfc32f874e154b..32343977dfa260d929574bd390e964fc11b93cf2 100644 --- a/Nynja/JobHandler.swift +++ b/Nynja/JobHandler.swift @@ -6,7 +6,11 @@ // Copyright © 2018 TecSynt Solutions. All rights reserved. // -class JobHandler: BaseHandler { +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, @@ -16,13 +20,12 @@ 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/Library/UI/AlertManager.swift b/Nynja/Library/UI/AlertManager.swift index f0519ed17d6365548da9f8d33f65fa2804db9291..c013d0aa9dc3d55a563ad48f5854d391470fb028 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) + } } } diff --git a/Nynja/LinkHandler.swift b/Nynja/LinkHandler.swift index feebe3ae1ff00831ed081dc9d607ddb0b5965a44..620ad386d0779de2aacb8a9d9822e069f01263ba 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 0000000000000000000000000000000000000000..dd65b2588921bc01a4c9eb79bf1deaf9291293ec --- /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) +} diff --git a/Nynja/MemberHandler.swift b/Nynja/MemberHandler.swift index 361d24a8bb912bcf30904ab72ba52ca8e1b1c7b1..d6a52401101fdda7b713af00474762979ca4053a 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,12 +24,10 @@ 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/Modules/Auth/VerifyNumber/Interactor/VerifyNumberInteractor.swift b/Nynja/Modules/Auth/VerifyNumber/Interactor/VerifyNumberInteractor.swift index c525eddceaeb5054e4b5b97831a66489fafe8be4..92a4a15970b74f91ae75db4c76a3ea54a554318e 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 6952408d4910d14ec40fdfc18eb4f5e874bffc1e..244af25b0b4a4c74f89e9e7161a96ca7a9d55b70 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, ProfileHandlerDelegate, SetInjectable { weak var presenter: MainInteractorOutputProtocol! @@ -16,85 +17,114 @@ 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 initialPhone: String? + + + // MARK: - Dependencies + + 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! + private var alertManager: AlertManager! + + + // MARK: - BaseInteractor + + override func loadData() { + super.loadData() + + ProfileHandler.delegate = self + pushService.registerForNotifications() + mqttService.addSubscriber(self) setupIntercom() } - - func checkSession() { - MQTTService.sharedInstance.reconnect() - } + + + // MARK: - Calls 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) } } + + + // MARK: - MainInteractorInputProtocol - func updateGroupCall(contacts: [Contact]) { + func checkSession() { + mqttService.reconnect() } - + func findContactBy(phoneId: String) -> Contact? { return ContactDAO.findContactBy(phoneId: phoneId) } func logout() { - MQTTService.sharedInstance.logout() + mqttService.logout() LogService.log(topic: .db) { return "Clear storage: logout" } cleanServices() + mqttService.reconnect() } 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" } + presenter.showUILocker() + } + + private func handleProfileDeleting() { cleanServices() + alertManager.showAlertOk(message: String.localizable.authAttemptsRemoved) + mqttService.reconnect() + presenter.hideUILocker() } 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,33 +152,23 @@ 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!)) } } } - // MARK: MQTT subscribing + // MARK: - MQTTServiceDelegate func mqttServiceDidConnect(_ mqttService: MQTTService) { - DispatchQueue.main.async { - self.presenter.hideUILocker() - } + presenter.hideUILocker() } func mqttServiceDidReceiveAuthenticationFailure(_ mqttService: MQTTService) { - DispatchQueue.main.async { - self.logout() - self.presenter.changeScreenToAuth() - } - } - - func saveLogoutState() { - MQTTService.sharedInstance.state = .notAuthenticated(isLoggedOutFromServer: false) + logout() + presenter.changeScreenToAuth() } private func setupIntercom() { @@ -166,5 +186,49 @@ class MainInteractor: MainInteractorInputProtocol, EditPhotoDelegate, MQTTServic userAttributes.phone = contact.phoneNumber Intercom.updateUser(userAttributes) } + + + // MARK: - ProfileHandlerDelegate + + func profileDeleted(with phone: String) { + guard initialPhone == phone else { + return + } + + handleProfileDeleting() + presenter.changeScreenToAuth() + } +} + +// MARK: - SetInjectable + +extension MainInteractor { + struct Dependencies { + 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 98d9743d629afc3b07f5e446db94b1c08230b531..48a9e0382f33ac5202f7c18610e72afd17441cab 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?) @@ -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 } @@ -219,13 +219,12 @@ protocol MainInteractorOutputProtocol: class { * Add here your methods for communication INTERACTOR -> PRESENTER */ - func logout() func showUILocker() func hideUILocker() func changeScreenToAuth() } -protocol MainInteractorInputProtocol: class { +protocol MainInteractorInputProtocol: BaseInteractorProtocol { var contact: Contact? { get } @@ -238,19 +237,15 @@ 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?) - 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 5292588ec19362b679ba34d43d2077e74897c3bb..6a2574f2f3c4c9468accede9ec07229b1eae48a2 100644 --- a/Nynja/Modules/Main/Presenter/MainPresenter.swift +++ b/Nynja/Modules/Main/Presenter/MainPresenter.swift @@ -6,15 +6,21 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, ScheduleMessageDelegate, EditParticipantsDelegate { +final class MainPresenter: BasePresenter, MainPresenterProtocol, MainInteractorOutputProtocol, EditParticipantsDelegate, SetInjectable { 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 + } + } + + private var reachabilityService: ReachabilityService! func showQRReader() { wireFrame.showQRReader() @@ -135,13 +141,12 @@ class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, Schedu } func logout() { - self.interactor.saveLogoutState() - 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) { @@ -233,8 +238,9 @@ class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, Schedu } func deleteAccount() { - self.interactor.deleteAccount() - self.wireFrame.logout() + reachabilityService.performIfConnected { + interactor.deleteAccount() + } } func showDataAndStorage() { @@ -292,13 +298,9 @@ class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, Schedu view?.hideUILocker() } - // MARK: - ScheduleMessageDelegate - func scheduleMessageHasBeenSent() { - //TODO: -// view.cleanTextInput() - } - + // MARK: EditParticpantsDelegate + func participantsUpdated(contacts: [Contact]) { } @@ -316,5 +318,23 @@ class MainPresenter: MainPresenterProtocol, MainInteractorOutputProtocol, Schedu 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/View/MainViewController.swift b/Nynja/Modules/Main/View/MainViewController.swift index 36d8fc95ffb81febca43d1bfca7ba9b69bb74448..2531476ff639e3b43c5db80f84b15721fb8e1f80 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 be8b325b8c8e32faec0470ebff160a241e91b914..e7e186cf71919a553355b98f720d01edc5ab96dc 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() @@ -31,10 +33,26 @@ class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { // Connecting view.presenter = presenter - presenter.view = view - presenter.wireFrame = self - presenter.interactor = interactor - interactor.presenter = presenter + + 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), + alertManager: serviceFactory.makeAlertManager())) // set content view let contentNavigation = ContentNavigationVC() @@ -145,15 +163,15 @@ class MainWireFrame: MainWireFrameProtocol, NynjaCommunicatorServiceDelegate { 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)) } } @@ -275,10 +293,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/Modules/Message/Interactor/MessageInteractor.swift b/Nynja/Modules/Message/Interactor/MessageInteractor.swift index d455ff61bb155d1ae3b1223047236d17fb0d0cf5..686bad549bf6bea715adb3ff57d8750e031de29e 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/Modules/Message/WireFrame/MessageWireframe.swift b/Nynja/Modules/Message/WireFrame/MessageWireframe.swift index bdb7e114f5512109a9dcfeb8024767863cd48199..71987cd8cb5f6cfbdcb08beb1386e8ef126d680d 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 781e36ed9e694223a911afb5e1b48bd16b118ba9..c99265c6c6ed1a0d14788852461a81efa462e6f5 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 fb6c9a4ab37bda58094e0448e055400f28497e96..848f0670e7c9a96f128f5d0c479b7ea0eef15917 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 179084cb606b881203ee856a0ca51e94deb322e0..6de7d02c2a60ae3d4034d919e98ad77caf6053b3 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/Modules/Splash/Interactor/SplashInteractor.swift b/Nynja/Modules/Splash/Interactor/SplashInteractor.swift index 38422a4da00df515ef0039ee9828398006eb6a08..f683f5febe573d05aaf2002f5109fa30a1ca6b5f 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/Modules/Splash/View/SplashViewController.swift b/Nynja/Modules/Splash/View/SplashViewController.swift index 5ad891dfd7de0bff951df4c5c207f1e6cc20438a..43a74e7c4d9f7dd4ab61bb029abd3b671f12db33 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)" } } diff --git a/Nynja/NotificationManager.swift b/Nynja/NotificationManager.swift index 4059601d62ab7155da847a3cc6fadd0c2b30b8b7..16778475e3166dfccae989cad19d9a2a2b675e99 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,15 +111,19 @@ final class NotificationManager { return } - handleNavigation(presenter: mainPresenter) + processingQueue.async { [weak self] in + self?.handleNavigation(presenter: mainPresenter) + } } // MARK: - Handle BERT func handle(bert: BertTuple, type: InAppNotificationType) { - tupleForNavigate = bert - typeForNavigate = type + processingQueue.async { [weak self] in + self?.tupleForNavigate = bert + self?.typeForNavigate = type + } } @@ -138,10 +146,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 +164,6 @@ final class NotificationManager { navigateToHistory(presenter: presenter) case .friend(let requestType): navigateToFriend(presenter: presenter, requestType: requestType) - default: break } } @@ -205,7 +214,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 +368,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 @@ -427,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 + } } } diff --git a/Nynja/ProfileHandlerDelegate.swift b/Nynja/ProfileHandlerDelegate.swift new file mode 100644 index 0000000000000000000000000000000000000000..9fdd8ef6706afaea59e46a220816528a41c526f7 --- /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/Resources/ReleaseConfig.xcconfig b/Nynja/Resources/ReleaseConfig.xcconfig index f8b763d10d53ab772501aae33538bbfb15346308..f65b25f2e8785121a37b607380cc213fcad8e8e6 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 diff --git a/Nynja/Services/Amazon+FileSync.swift b/Nynja/Services/Amazon+FileSync.swift index 5ccd350c3188f0b9f1076cd3052b1580b7bf35a0..c76edb8c5202796ff4a6956118ef32f76e365374 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/Aps.swift b/Nynja/Services/Aps.swift index 371112e55b17bb06f1a7a305feeb43a639955230..dc39a64b1f61552d0a54f829448fb31f819a22dd 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? { diff --git a/Nynja/Services/Audio/SystemSoundManager/SystemSoundManager.swift b/Nynja/Services/Audio/SystemSoundManager/SystemSoundManager.swift index 8291eea75f59f234ef2ffc39823808bc987bb448..bb06789be99093d737ca7768d199d84d3003f3e7 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) diff --git a/Nynja/Services/HandleServices/ContactHandler.swift b/Nynja/Services/HandleServices/ContactHandler.swift index 8a6aa1cfee40e159df9bea6d0fac0f7605583454..42e1e46bc286f04702f8a5b1a22cd95693633b22 100644 --- a/Nynja/Services/HandleServices/ContactHandler.swift +++ b/Nynja/Services/HandleServices/ContactHandler.swift @@ -6,16 +6,18 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -import Foundation - -class ContactHandler: BaseHandler { +final class ContactHandler: BaseHandler { // MARK: - Dependencies - static var storageService: StorageService { + private static var storageService: StorageService { return .sharedInstance } + private static var notificationManager: NotificationManager { + return .shared + } + // MARK: - Handler @@ -79,7 +81,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 +92,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'" } } diff --git a/Nynja/Services/HandleServices/HistoryHandler.swift b/Nynja/Services/HandleServices/HistoryHandler.swift index 11d6bf8246d6aeeb6d5450abd9f793e983d53fb8..4a7180294520a8097d7df1f66750aaeb067717c0 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() @@ -54,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/HandleServices/MessageHandlerSubscriber.swift b/Nynja/Services/HandleServices/MessageHandlerSubscriber.swift index 35f8bf9ef5aef7bf8aa057718292095f2fd44f14..08e51eb721215fe9428b3c258817fbef29ce12d0 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/Nynja/Services/HandleServices/ProfileHandler.swift b/Nynja/Services/HandleServices/ProfileHandler.swift index a1fa7952fe9081226a9af0f2401170d744765552..88d1508715738346662fded765d1f189190be8f1 100644 --- a/Nynja/Services/HandleServices/ProfileHandler.swift +++ b/Nynja/Services/HandleServices/ProfileHandler.swift @@ -6,30 +6,31 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -class ProfileHandler: BaseHandler { +final class ProfileHandler: BaseHandler, StaticDelegating { + + static weak var delegate: ProfileHandlerDelegate? // 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() } - - static var alertManager: AlertManager { - return AlertManager.sharedInstance - } + private static var communicatorService: NynjaCommunicatorService { + return .sharedInstance + } // MARK: - Handler @@ -158,7 +159,7 @@ class ProfileHandler: BaseHandler { return } - NynjaCommunicatorService.sharedInstance.initialize() + communicatorService.initialize() } private static func requestJobs(with phoneId: String) { @@ -179,13 +180,14 @@ 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/HandleServices/RoomHandler.swift b/Nynja/Services/HandleServices/RoomHandler.swift index 8fb79ae803777d963533eddb3dd99c0c1c41179b..a29be4c96b26654494420b2fb87d193631c184b2 100644 --- a/Nynja/Services/HandleServices/RoomHandler.swift +++ b/Nynja/Services/HandleServices/RoomHandler.swift @@ -6,15 +6,15 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -class RoomHandler: BaseHandler { +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 } @@ -228,5 +228,4 @@ class RoomHandler: BaseHandler { oldRoom.readers = room.readers oldRoom.status = room.status } - } diff --git a/Nynja/Services/HandleServices/RosterHandler.swift b/Nynja/Services/HandleServices/RosterHandler.swift index 51ac27f172177e39d11e19f2baa952a2300e6ff1..2596cd69d26737090de3058ebcc3ed5c001090bd 100644 --- a/Nynja/Services/HandleServices/RosterHandler.swift +++ b/Nynja/Services/HandleServices/RosterHandler.swift @@ -6,9 +6,11 @@ // Copyright © 2017 TecSynt Solutions. All rights reserved. // -import Foundation - -class RosterHandler: BaseHandler { +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, @@ -17,7 +19,7 @@ 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 9d8570b15de66e722bcc946a1585f1b35d51705d..0000000000000000000000000000000000000000 --- a/Nynja/Services/HandleServices/SearchHandler.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// SearchHandler.swift -// Nynja -// -// Created by Anton Makarov on 23.10.17. -// Copyright © 2017 TecSynt Solutions. All rights reserved. -// - -import Foundation - -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 41665196251603d483d7086d284b8761f1057901..1b830f2ad78939afaff056afeeb32639e4406562 100644 --- a/Nynja/Services/HandleServices/StarHandler.swift +++ b/Nynja/Services/HandleServices/StarHandler.swift @@ -6,20 +6,26 @@ // Copyright © 2018 TecSynt Solutions. All rights reserved. // -class StarHandler: BaseHandler { +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 { - return + guard let star = get_Star().parse(bert: data) as? Star, + let status = star.starStatus else { + return } + do { 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/HandleServices/TypingHandler.swift b/Nynja/Services/HandleServices/TypingHandler.swift index e9023cba80c1b03a0e44589a87eb7567a1a43e88..ce19b3bb3e1215e366ea4d7d43aa6c4707d7ce80 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 { - +final 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/Services/MQTT/MQTTServiceAuth.swift b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift similarity index 86% rename from Nynja/Services/MQTT/MQTTServiceAuth.swift rename to Nynja/Services/MQTT/API/MQTTServiceAuth.swift index 30e1c90945a782ecaa173c455fbd7b110ca405f1..a495ab33a22596f65f305aa95ac2b94a78e65a99 100644 --- a/Nynja/Services/MQTT/MQTTServiceAuth.swift +++ b/Nynja/Services/MQTT/API/MQTTServiceAuth.swift @@ -11,8 +11,8 @@ import Foundation extension MQTTService { func logout() { - let token = StorageService.sharedInstance.tokenAsNSData - 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.tokenAsNSData { + if let token = storageService.tokenData { let model = AuthModel(type: .LOGIN, phoneNumber: number, userID: nil, @@ -49,11 +49,11 @@ extension MQTTService { publish(model: model) } - func updatePushToken(push_token: String) { - if - let phone = StorageService.sharedInstance.phone, - let token = StorageService.sharedInstance.tokenAsNSData, - let clientID = StorageService.sharedInstance.clientId { + func update(pushToken: String) { + if let phone = storageService.phone, + let token = storageService.tokenData, + let clientID = storageService.clientId { + let model = AuthModel(type: .PUSH, phoneNumber: phone, userID: nil, @@ -63,17 +63,19 @@ extension MQTTService { token: token, smsCode: nil, languages: nil, - pushID: push_token) + pushID: pushToken) publish(model: model) } } func removeTokenAndLogin(number: String) { - StorageService.sharedInstance.dropUserInfo() + storageService.dropUserInfo() login(number: number) } 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/MQTTServiceChat.swift b/Nynja/Services/MQTT/API/MQTTServiceChat.swift similarity index 96% rename from Nynja/Services/MQTT/MQTTServiceChat.swift rename to Nynja/Services/MQTT/API/MQTTServiceChat.swift index f1129894f0ee9ed998d63fcbe5675e95be6de4db..5fa321e5fa6ef1dd8cefe16f02837d0d642d49b3 100644 --- a/Nynja/Services/MQTT/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/MQTTServiceFriend.swift b/Nynja/Services/MQTT/API/MQTTServiceFriend.swift similarity index 79% rename from Nynja/Services/MQTT/MQTTServiceFriend.swift rename to Nynja/Services/MQTT/API/MQTTServiceFriend.swift index 7d67421c60636c351eb253c83549cfe07e733efe..29f24c2abb64c585b79ea8207650a2bb09306f07 100644 --- a/Nynja/Services/MQTT/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/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 90% rename from Nynja/Services/MQTT/MQTTServiceProfile.swift rename to Nynja/Services/MQTT/API/MQTTServiceProfile.swift index 93221a3ae9af90d981e85ade211db748d7f76c58..b30cbb93aadfc6b607866d26a0252cd594497e0c 100644 --- a/Nynja/Services/MQTT/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! model = UpdateRosterModel(id: id, name: name, surname: nil, avatar: nil, email: nil,nick: nil) publish(model: model) @@ -19,7 +19,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/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 84% rename from Nynja/Services/MQTT/MQTTServiceStars.swift rename to Nynja/Services/MQTT/API/MQTTServiceStars.swift index 4c3bafde5175cf2c36a4e0e201e4dbbcee988c4a..c5cb5d2e58560db8b5ca14540bce458719df7f4a 100644 --- a/Nynja/Services/MQTT/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/MQTTServiceWallet.swift b/Nynja/Services/MQTT/API/MQTTServiceWallet.swift similarity index 90% rename from Nynja/Services/MQTT/MQTTServiceWallet.swift rename to Nynja/Services/MQTT/API/MQTTServiceWallet.swift index fefee8208aedeac6446d2407a9cc4665310ed94c..600599ade396f2cb3e1940abc77acb52340d2ef5 100644 --- a/Nynja/Services/MQTT/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 } diff --git a/Nynja/Services/MQTT/Entities/Host.swift b/Nynja/Services/MQTT/Entities/Host.swift new file mode 100644 index 0000000000000000000000000000000000000000..1ce1d6f21a918902e326dd29c5cc687cc829afdc --- /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 70% rename from Nynja/Services/MQTT/MQTTServiceHelper.swift rename to Nynja/Services/MQTT/Extensions/MQTTService+Helper.swift index 41e228ac7aa8a5c3f8e63103c73e744f4a953898..052f202458fef5b816c8ed0c2247f985b5b585d6 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,24 +11,19 @@ import CocoaMQTT extension MQTTService { - func publish(model: BaseMQTTModel) { - guard let mqtt = self.mqtt, mqtt.connState == .connected else { - return - } - - 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 + queuePool.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/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift new file mode 100644 index 0000000000000000000000000000000000000000..077d7db174373c00e75ba95cd7780800ce43e692 --- /dev/null +++ b/Nynja/Services/MQTT/Extensions/MQTTService+QueuePool.swift @@ -0,0 +1,25 @@ +// +// 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")) + let loggingQueue = DispatchQueue(label: String.label(withSuffix: "mqtt-service.logging-queue")) + let processingQueue = DispatchQueue( + label: String.label(withSuffix: "mqtt-service.processing-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) + } +} diff --git a/Nynja/Services/MQTT/MQTTService.swift b/Nynja/Services/MQTT/MQTTService.swift index 12002089518a4e267140700d759c08924b9d1c24..9272ea8511ee956ebd58fccfa913137d9477c39a 100644 --- a/Nynja/Services/MQTT/MQTTService.swift +++ b/Nynja/Services/MQTT/MQTTService.swift @@ -9,44 +9,21 @@ import Foundation import CocoaMQTT -struct Host { - let url: String - let port: UInt16 +/// Performs works in the several serial background queues +final class MQTTService: NSObject, MQTTServiceProtocol, CocoaMQTTDelegate, ConnectionServiceDelegate { - init() { - url = Bundle.main.serverUrl - port = Bundle.main.serverPort - } -} - -final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate { + private var mqtt: CocoaMQTT? - enum ConnectionState { - case connected - case disconnected + let queuePool = QueuePool() + let showHandlers: Set = [] + + var deviceId: String { + return UIDevice.current.persistentIdentifier } - var mqtt: CocoaMQTT? - - static let version = Bundle.main.modelsVersion - - let host = Host() - - var push: String? - - let deviceId = UIDevice.current.persistentIdentifier - - 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") - - let showHandlers : Set = [] - - static let sharedInstance = MQTTService() + var storageService: StorageService { + return .sharedInstance + } private var autoReconnectTimeInterval: UInt16? { willSet { @@ -80,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() - } - func initialize() { - self.setup() - myConnect() - } - - func myConnect() { - semaphore.wait() - mqtt?.connect() - semaphore.signal() + // MARK: - Setup + + func connect() { + 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 @@ -151,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 @@ -163,105 +114,125 @@ 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?.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" } + disconnect() + connect() + } + + func disconnect() { + queuePool.processingQueue.async { [unowned self] in + LogService.log(topic: .MQTT) { return "Disconnect" } + self.mqtt?.disconnect() + } + } + + + // MARK: - Publish + + func publish(model: BaseMQTTModel) { + queuePool.processingQueue.async { [mqtt] in + guard let mqtt = 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) - HandlerService.handle(response: message) + queuePool.receivingQueue.async { + 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) {} @@ -270,33 +241,38 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate func mqttDidPing(_ mqtt: CocoaMQTT) {} func mqttDidReceivePong(_ mqtt: CocoaMQTT) {} + // MARK: Subscribers + func addSubscriber(_ subscriber: MQTTServiceDelegate) { - subscribersQueue.sync { - subscribers.append(WeakRef(value: subscriber)) + queuePool.subscribersQueue.async { [unowned self, weak subscriber] in + if let subscriber = subscriber { + self.subscribers.append(WeakRef(value: subscriber)) + } } } func removeSubscriber(_ subscriber: MQTTServiceDelegate) { - subscribersQueue.sync { - subscribers = subscribers.filter { $0.value !== subscriber } + queuePool.subscribersQueue.async { [unowned self, weak subscriber] in + if let subscriber = subscriber { + self.subscribers = self.subscribers.filter { $0.value !== subscriber } + } } } func removeAllSubscribers() { - subscribersQueue.sync { - subscribers.removeAll() + queuePool.subscribersQueue.async { [unowned self] in + self.subscribers.removeAll() } } - /* Notify all subscribers that reachbility status changed */ - - private func notifySubscribers(with eventClosure: (MQTTServiceDelegate) -> Void) { - - subscribersQueue.sync { - subscribers.forEach { (weak) in + 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) + } } } } @@ -305,31 +281,20 @@ final class MQTTService: NSObject, CocoaMQTTDelegate, ConnectionServiceDelegate // MARK: - ConnectionServiceDelegate - func connectionStatusChanged(_ sender: ConnectionService, service: ConnectionService.Service, oldValue: ConnectionService.ConnectionServiceState) { + 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 + 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() + 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 0000000000000000000000000000000000000000..9a2ab23ffe74f0c4e9beca546f6a1e3b65a76155 --- /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/MQTT/MQTTServiceProtocol.swift b/Nynja/Services/MQTT/MQTTServiceProtocol.swift new file mode 100644 index 0000000000000000000000000000000000000000..a58000f493c6ddca7d37e6e967381b32d3e7c6e5 --- /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() +} diff --git a/Nynja/Services/Models/AuthModel.swift b/Nynja/Services/Models/AuthModel.swift index d66ec20bb35ce0d2e5376566619739a8f37051d5..d4e04abcd91f0e9c61137fdbeb784738d663b9d4 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/PushService.swift b/Nynja/Services/PushService.swift index 91c423ae4f43f68dfed1c24e1f8b8554d48e70b9..1525a106be0fa22b11fbd56177d88643b141a6f5 100644 --- a/Nynja/Services/PushService.swift +++ b/Nynja/Services/PushService.swift @@ -12,11 +12,11 @@ import UserNotifications final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondable { - static let sharedInstance: PushService = { - let instance = PushService() - instance.registerForPushNotifications() - return instance - }() + private var storageService: StorageService { + return .sharedInstance + } + + static let sharedInstance = PushService() // MARK: - Init @@ -33,7 +33,18 @@ final class PushService: NSObject, PKPushRegistryDelegate, UserSettingsRespondab // MARK: - Setup - func registerForPushNotifications() { + func registerForNotifications() { + registerForNativeNotifications() + registerForPushKitNotifications() + } + + 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] @@ -45,14 +56,13 @@ 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)" } } @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, @@ -75,8 +85,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 @@ -214,7 +224,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 +262,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 +273,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 } } diff --git a/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderFactory.swift b/Nynja/Services/ServiceFactory/FileDownloaderFactory/FileDownloaderFactory.swift new file mode 100644 index 0000000000000000000000000000000000000000..b7a1b8427c311b6d199aaa4a2e21d032df2095be --- /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 0000000000000000000000000000000000000000..a841644a5185ef5443e0940f8758daa74af1d756 --- /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 99adf6859ee2ef4e9c5c40800578c4a851a22cd0..6ca43a469692ae64dfb435eefc26afb75e440208 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,18 @@ protocol ServiceFactoryProtocol: SharedServiceFactoryProtocol { func makeAudioSessionManager() -> AudioSessionManager func makeHomeDataProvider(limit: Int) -> HomeDataProvider + + func makePushService() -> PushService + + func makeNynjaCommunicatorService() -> NynjaCommunicatorService + + func makeBadgeNumberService() -> BadgeNumberServiceProtocol + + func makeNotificationManager() -> NotificationManager + + func makeUserSettingsService() -> UserSettingsService + + func makeReachabilityService() -> ReachabilityService } final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { @@ -142,6 +155,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 +202,28 @@ final class ServiceFactory: SharedServiceFactory, ServiceFactoryProtocol { fields: .init( limit: limit))) } + + func makePushService() -> PushService { + return .sharedInstance + } + + func makeNynjaCommunicatorService() -> NynjaCommunicatorService { + return .sharedInstance + } + + func makeBadgeNumberService() -> BadgeNumberServiceProtocol { + return BadgeNumberService.shared + } + + func makeNotificationManager() -> NotificationManager { + return .shared + } + + func makeUserSettingsService() -> UserSettingsService { + return .shared + } + + func makeReachabilityService() -> ReachabilityService { + return .sharedInstance + } } diff --git a/Nynja/Services/StickersDownloadingService/StickersDownloadingService.swift b/Nynja/Services/StickersDownloadingService/StickersDownloadingService.swift index 438562db631d892f33e9c50e485831a25c8e2833..5eb64229bdf3a9d1fcf5ccbde89c118d9b54fcfc 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 { diff --git a/Nynja/Services/StorageService.swift b/Nynja/Services/StorageService.swift index ec1b3ea6b96a2227d146911a0a38fd38f5d7e6a5..fc79d14d2951c5819df772eb736ed0a0ace085f0 100644 --- a/Nynja/Services/StorageService.swift +++ b/Nynja/Services/StorageService.swift @@ -10,15 +10,19 @@ 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 let userDefaults = UserDefaults(suiteName: Bundle.main.appGroupName) let keychain = KeychainService.standard - - private let countriesProvider = CountriesProvider() + private(set) lazy var userInfo: UserInfo = { + return UserInfoImpl( + dependencies: .init(userDefaults: userDefaults)) + }() #if !SHARE_EXTENSION private let databaseManager = DatabaseManager() @@ -28,10 +32,12 @@ class StorageService { } #endif + private let isolationQueue = DispatchQueue(label: String.label(withSuffix: "storage-service.isolation-queue")) + // MARK: - Properties lazy var countries: [CountryModel] = { - return countriesProvider.fetchCountries() + return CountriesProvider().fetchCountries() }() /// It is used only for debug purposes. @@ -48,6 +54,12 @@ class StorageService { // MARK: - Setup func setupDatabase(with name: String, application: UIApplication) { + isolationQueue.sync { [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,10 +115,12 @@ class StorageService { // MARK: - Clear func clearStorage() { - #if !SHARE_EXTENSION - databaseManager.clear() - #endif - keychain.clear() + isolationQueue.sync { [weak self] in + #if !SHARE_EXTENSION + self?.databaseManager.clear() + #endif + self?.keychain.clear() + } dropUserInfo() } } @@ -145,6 +159,60 @@ extension StorageService: DBManagerProtocol { func perform(action: DatabaseAction, with models: [DBModel]) throws { try databaseManager.perform(action: action, with: models) } - } #endif + + +// MARK: - UserInfo + +extension StorageService: UserInfo { + + var token: String? { + get { return userInfo.token } + set { userInfo.token = newValue } + } + + var tokenData: Data? { + get { return userInfo.tokenData } + } + + var pushToken: String? { + get { return userInfo.pushToken } + set { userInfo.pushToken = newValue } + } + + var phone: String? { + get { return userInfo.phone } + set { userInfo.phone = newValue } + } + + var rosterId: Int64? { + get { return userInfo.rosterId } + set { userInfo.rosterId = newValue } + } + + var clientId: String? { + get { return userInfo.clientId } + set { userInfo.clientId = newValue } + } + + var wasLogined: Bool { + get { return userInfo.wasLogined } + set { userInfo.wasLogined = newValue } + } + + var wasRun: Bool { + get { return userInfo.wasRun } + set { userInfo.wasRun = newValue } + } + + 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/SyncFileManager/SyncFileManager.swift b/Nynja/SyncFileManager/SyncFileManager.swift index 3e1263358e559876742c3ead381246d333796e38..9dcf4275fac68ab9224ce55effc331194fa2ecb1 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() { diff --git a/Nynja/TypingHandlerDelegate.swift b/Nynja/TypingHandlerDelegate.swift new file mode 100644 index 0000000000000000000000000000000000000000..de1844d5f079ea07d68d21f78f5c0327a805d40f --- /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/Nynja/UserInfo.swift b/Nynja/UserInfo.swift index b54af5b579a0e50aff165d9f80843c3feada2150..c04b6179c28ad7d5dda587fa0f97ff862c504a3d 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" @@ -20,7 +22,9 @@ enum UserIdentifiers: String { protocol UserInfo: class { var token: String? { get set } - var tokenAsNSData: NSData? { get } + var tokenData: Data? { get } + + var pushToken: String? { get set } var phone: String? { get set } var rosterId: Int64? { get set } @@ -61,5 +65,4 @@ extension UserInfo { rosterId = nil clientId = nil } - } diff --git a/Nynja/StorageService+UserInfo.swift b/Nynja/UserInfoImpl.swift similarity index 53% rename from Nynja/StorageService+UserInfo.swift rename to Nynja/UserInfoImpl.swift index 2e7b6d7b51e9628213b2083a5f13fea58cc9f3ed..6f81d898d6b05ffa0cfc7f92608b69b33b386586 100644 --- a/Nynja/StorageService+UserInfo.swift +++ b/Nynja/UserInfoImpl.swift @@ -1,21 +1,35 @@ // -// 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? { - return userDefaults?.data(forKey: UserIdentifiers.token.rawValue) + var tokenData: Data? { + return value(forId: .token) } var token: String? { @@ -25,7 +39,7 @@ extension StorageService: UserInfo { return token } set { - guard let token = newValue, let data = token.data(using: encoding) else { + guard let token = newValue, let data = token.data(using: self.encoding) else { userDefaults?.removeObject(forKey: UserIdentifiers.token.rawValue) userDefaults?.synchronize() return @@ -33,55 +47,58 @@ extension StorageService: UserInfo { set(data as NSData, forId: .token) LogService.log(topic: .userDefaults) { return "Save token: \(token)" } - MQTTService.sharedInstance.reconnect() + 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) } } 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) } } + private var _wasRun: Bool = false + var wasRun: Bool { - get { return userDefaults?.bool(forKey: UserIdentifiers.wasRun.rawValue) ?? false } + get { return _wasRun } 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 } 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/Nynja/UserSettings/Service/UserSettingsService.swift b/Nynja/UserSettings/Service/UserSettingsService.swift index 5ae2229d1cfe365ba204e65451fb9d4d57140440..3a82323ddf5e238d5d4dde28b4239331284261e7 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 6bba3db8926b37ff7a37d3ec271bb093a893401a..03acaa78c22ce1473c782ad3169b2a65a081dbb0 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 2a0c2600cf4f464ed2a9bc4c6df92e41907e609b..acc6de35085d4148ad8ca910d4826fdc34e07c86 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] diff --git a/NynjaUnitTests/Services/UserInfo/UserInfoTest.swift b/NynjaUnitTests/Services/UserInfo/UserInfoTest.swift index f2ba00aa2716621ef239bede0952240de8e71ab3..33f8f8054f868343c1a409bb110bbb3ea5a4ecfa 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? diff --git a/Shared/Library/StaticDelegating.swift b/Shared/Library/StaticDelegating.swift new file mode 100644 index 0000000000000000000000000000000000000000..39173973ea109dfad29d557c7f20831309d2b23c --- /dev/null +++ b/Shared/Library/StaticDelegating.swift @@ -0,0 +1,30 @@ +// +// StaticDelegating.swift +// Nynja +// +// Created by Volodymyr Hryhoriev on 11/9/18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import Foundation + +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) + } + } +} 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 c5ec8f5f2faab78ae37eaca7954d6a64fae8cd6f..ef1dd76f4744da0c549c305fbdc4cdafb5678b78 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 0000000000000000000000000000000000000000..aa69442894dd10bb97230d1baa8c394e9ea7b729 --- /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) {} +} diff --git a/Shared/Services/Handlers/Base/HandlerService.swift b/Shared/Services/Handlers/Base/HandlerService.swift index 7d5c1fee45085c9400f12386f60b301652c06312..efbb47e2319c8290a194944f420ddd67a199ff39 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) } - } diff --git a/Shared/Services/Handlers/ErrorsHandler.swift b/Shared/Services/Handlers/ErrorsHandler.swift index d284a35cb0d3164681243317b280771cd59427e1..5465d157167da9920916064ac0282c45cbe45cfe 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)) } - } diff --git a/Shared/Services/Handlers/IoHandler.swift b/Shared/Services/Handlers/IoHandler.swift deleted file mode 100644 index f6fd64282f4d4fac0dc2b03406c96230694292c5..0000000000000000000000000000000000000000 --- a/Shared/Services/Handlers/IoHandler.swift +++ /dev/null @@ -1,184 +0,0 @@ -// -// IoHandler.swift -// Nynja -// -// Created by Anton Makarov on 14.06.2017. -// Copyright © 2017 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() {} - - -} - -class IoHandler:BaseHandler { - - static weak var delegate: IoHandlerDelegate? - - static var storageService: StorageService { - return .sharedInstance - } - - static var mqttService: MQTTService { - 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 - if let value = ((IO.code as? ok)?.code as? StringAtom)?.string { - code = value - } - if let value = ((IO.code as? error)?.code as? StringAtom)?.string { - code = value - } - if let value = (IO.code as? ok)?.code as? String { - code = value - } - if let value = (IO.code as? error2)?.code?.string { - code = value - } - if let ok2 = IO.code as? ok2 { - code = ok2.code?.string - if let src = (IO.code as? ok2)?.src as? [AnyObject] { - if src.count > 1 { - if let clientId = src[0] as? String, let token = src[1] as? String { - storageService.setupAuth(clientId: clientId, token: token) - } - } - } - } - if let action = code { - switch action { - case "deleted": - self.delegate?.sessionDeleted() - case "cleared": - self.delegate?.sessionsCleared() - case "sms_sent": - self.delegate?.smsSent() - case "invalid_data": - self.delegate?.invalidData() - case "session_not_found": - self.delegate?.sessionNotFound() - case "call_in_progress": - self.delegate?.callInProgress() - case "login": - StorageService.sharedInstance.wasLogined = true - case "mismatch_user_data": - self.delegate?.mismatchUserData() - case "invalid_sms_code": - self.delegate?.wrongCode() - case "attempts_expired": - self.delegate?.attemptsExpired() - case "number_not_allowed": - self.delegate?.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() - case "phone": - if let roster = IO.data as? Roster { - if let contact = roster.userlist?.first { - self.delegate?.getContactSuccess(contact: contact) - } else { - self.delegate?.contactNotFound() - } - } - case "phonebook": - if let roster = IO.data as? Roster { - if let contacts = roster.userlist { - self.delegate?.getContactsSuccess(contacts: contacts) - } else { - self.delegate?.contactsNotFound() - } - } - case "qrcode": - if let roster = IO.data as? Roster { - if let contact = roster.userlist?.first { - self.delegate?.getContactQRSuccess(contact: contact) - } else { - self.delegate?.contactQRNotFound() - } - } - case "nick": - self.delegate?.usernameIsBusy() - case "username": - if let roster = IO.data as? Roster { - if let contact = roster.userlist?.first { - self.delegate?.getContactByUsernameSucces(contact: contact) - } else { - self.delegate?.contactByUsernameNotFound() - } - } - default: - break - } - } - } - } - -} diff --git a/Shared/Services/Handlers/IoHandler/IoHandler.swift b/Shared/Services/Handlers/IoHandler/IoHandler.swift new file mode 100644 index 0000000000000000000000000000000000000000..58a1b1f52cfc551f3b5c3730b9ca9d372e520d45 --- /dev/null +++ b/Shared/Services/Handlers/IoHandler/IoHandler.swift @@ -0,0 +1,122 @@ +// +// IoHandler.swift +// Nynja +// +// Created by Anton Makarov on 14.06.2017. +// Copyright © 2017 TecSynt Solutions. All rights reserved. +// + +import Foundation + +final class IoHandler: BaseHandler, StaticDelegating { + + static weak var delegate: IoHandlerDelegate? + + static var storageService: StorageService { + return .sharedInstance + } + + static var mqttService: MQTTService { + return .sharedInstance + } + + static func executeHandle(data: BertTuple) { + if let IO = get_io().parse(bert: data) as? io { + var code: String? = nil + if let value = ((IO.code as? ok)?.code as? StringAtom)?.string { + code = value + } + if let value = ((IO.code as? error)?.code as? StringAtom)?.string { + code = value + } + if let value = (IO.code as? ok)?.code as? String { + code = value + } + if let value = (IO.code as? error2)?.code?.string { + code = value + } + if let ok2 = IO.code as? ok2 { + code = ok2.code?.string + if let src = (IO.code as? ok2)?.src as? [AnyObject] { + if src.count > 1 { + if let clientId = src[0] as? String, let token = src[1] as? String { + storageService.setupAuth(clientId: clientId, token: token) + } + } + } + } + if let action = code { + switch action { + case "deleted": + delegate { $0.sessionDeleted() } + case "cleared": + delegate { $0.sessionsCleared() } + case "sms_sent": + delegate { $0.smsSent() } + case "invalid_data": + delegate { $0.invalidData() } + case "session_not_found": + delegate { $0.sessionNotFound() } + case "call_in_progress": + delegate { $0.callInProgress() } + case "login": + StorageService.sharedInstance.wasLogined = true + case "mismatch_user_data": + delegate { $0.mismatchUserData() } + case "invalid_sms_code": + delegate { $0.wrongCode() } + case "attempts_expired": + delegate { $0.attemptsExpired() } + case "number_not_allowed": + delegate { $0.numberNotAllowed() } + case "phone": + if let roster = IO.data as? Roster { + if let contact = roster.userlist?.first { + delegate { $0.getContactSuccess(contact: contact) } + } else { + delegate { $0.contactNotFound() } + } + } + case "phonebook": + if let roster = IO.data as? Roster { + if let contacts = roster.userlist { + delegate { $0.getContactsSuccess(contacts: contacts) } + } else { + delegate { $0.contactsNotFound() } + } + } + case "qrcode": + if let roster = IO.data as? Roster { + if let contact = roster.userlist?.first { + delegate { $0.getContactQRSuccess(contact: contact) } + } else { + delegate { $0.contactQRNotFound() } + } + } + case "nick": + delegate { $0.usernameIsBusy() } + case "username": + if let roster = IO.data as? Roster { + if let contact = roster.userlist?.first { + delegate { $0.getContactByUsernameSucces(contact: contact) } + } else { + delegate { $0.contactByUsernameNotFound() } + } + } + default: + break + } + } + } + } + + static func delegate(_ closure: @escaping (IoHandlerDelegate) -> Void) { + guard let delegate = self.delegate else { + return + } + + dispatchAsyncMain { + closure(delegate) + } + } +} diff --git a/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift b/Shared/Services/Handlers/IoHandler/IoHandlerDelegate.swift new file mode 100644 index 0000000000000000000000000000000000000000..7620fa52bbbf27ad4288e4a40ed4af9f177cab94 --- /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 didLogout() + 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 didLogout() {} + 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() {} +}