diff --git a/.github/workflows/swift-sdk.yml b/.github/workflows/swift-sdk.yml index 084e0fc3..9dd9ab8b 100644 --- a/.github/workflows/swift-sdk.yml +++ b/.github/workflows/swift-sdk.yml @@ -23,11 +23,6 @@ jobs: - name: Force Xcode 11 run: sudo xcode-select -switch /Applications/Xcode_11.4.app - - name: Install Tools - run: | - gem install ocunit2junit - gem install xcpretty - - name: Install Cocoapods run: pod update @@ -35,7 +30,7 @@ jobs: run: xcodebuild clean - name: Build SDK - run: xcodebuild -workspace NinchatSDKSwift.xcworkspace -scheme NinchatSDKSwift -configuration "Release" -destination "platform=iOS Simulator,name=iPhone 8" CODE_SIGNING_ALLOWED=NO | tee raw.txt | xcpretty -c cat raw.txt | ocunit2junit + run: xcodebuild -workspace NinchatSDKSwift.xcworkspace -scheme NinchatSDKSwift -configuration "Release" -destination "platform=iOS Simulator,name=iPhone 8" CODE_SIGNING_ALLOWED=NO - name: Run SDK Tests - run: xcodebuild test -workspace NinchatSDKSwift.xcworkspace -scheme NinchatSDKSwift -destination "platform=iOS Simulator,name=iPhone 8" | tee rawTest.txt | xcpretty -c cat rawTest.txt | ocunit2junit + run: xcodebuild test -workspace NinchatSDKSwift.xcworkspace -scheme NinchatSDKSwift -destination "platform=iOS Simulator,name=iPhone 8" diff --git a/NinchatSDKSwift.xcodeproj/project.pbxproj b/NinchatSDKSwift.xcodeproj/project.pbxproj index f83a7181..2ee7b76b 100644 --- a/NinchatSDKSwift.xcodeproj/project.pbxproj +++ b/NinchatSDKSwift.xcodeproj/project.pbxproj @@ -94,7 +94,7 @@ 85CC096423DC66D300482956 /* Encodable+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85CC096323DC66D300482956 /* Encodable+Extension.swift */; }; 85D245352408F3470081F575 /* ChatTypingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 85D245342408F3470081F575 /* ChatTypingCell.xib */; }; 85DC59CC239E4C42007ABAE3 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DC59CB239E4C42007ABAE3 /* Button.swift */; }; - 85DC59D0239E6A38007ABAE3 /* NINChatSessionClosure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DC59CF239E6A38007ABAE3 /* NINChatSessionClosure.swift */; }; + 85DC59D0239E6A38007ABAE3 /* NINSiteConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DC59CF239E6A38007ABAE3 /* NINSiteConfiguration.swift */; }; 85DC59D2239E7850007ABAE3 /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 85DC59D1239E7850007ABAE3 /* Media.xcassets */; }; 85DC59D5239E7C3B007ABAE3 /* NINQueueViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DC59D4239E7C3B007ABAE3 /* NINQueueViewModel.swift */; }; 85DD6C5523AE0CBC0023FFEF /* SourceSansPro-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 85DD6C4923AE0CBC0023FFEF /* SourceSansPro-BlackItalic.ttf */; }; @@ -288,7 +288,7 @@ 85CC096323DC66D300482956 /* Encodable+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Encodable+Extension.swift"; sourceTree = ""; }; 85D245342408F3470081F575 /* ChatTypingCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ChatTypingCell.xib; sourceTree = ""; }; 85DC59CB239E4C42007ABAE3 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; - 85DC59CF239E6A38007ABAE3 /* NINChatSessionClosure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NINChatSessionClosure.swift; sourceTree = ""; }; + 85DC59CF239E6A38007ABAE3 /* NINSiteConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NINSiteConfiguration.swift; sourceTree = ""; }; 85DC59D1239E7850007ABAE3 /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; 85DC59D4239E7C3B007ABAE3 /* NINQueueViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NINQueueViewModel.swift; sourceTree = ""; }; 85DD6C4923AE0CBC0023FFEF /* SourceSansPro-BlackItalic.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SourceSansPro-BlackItalic.ttf"; sourceTree = ""; }; @@ -515,7 +515,7 @@ children = ( 855B9F2D238ECE650081A9C6 /* NINChatSession.swift */, 91A16FA13B1F62E386352B88 /* NINSessionCredentials.swift */, - 85DC59CF239E6A38007ABAE3 /* NINChatSessionClosure.swift */, + 85DC59CF239E6A38007ABAE3 /* NINSiteConfiguration.swift */, 855B9F2E238ECE650081A9C6 /* NINChatSessionDelegate.swift */, 8543414B239655200078D11A /* Implementations */, 85DD6C4723AE0C8A0023FFEF /* Resources */, @@ -1191,7 +1191,7 @@ 8561EAD623C2805900943C72 /* NINChatSessionManager.swift in Sources */, 85DC59CC239E4C42007ABAE3 /* Button.swift in Sources */, 855FA2A123C735CD00A2FB41 /* MetaCell.swift in Sources */, - 85DC59D0239E6A38007ABAE3 /* NINChatSessionClosure.swift in Sources */, + 85DC59D0239E6A38007ABAE3 /* NINSiteConfiguration.swift in Sources */, 8563004923B286360098A7B0 /* NINRatingViewController.swift in Sources */, 8561EAD923C2805900943C72 /* NINChatSessionManagerEventHandlers.swift in Sources */, 8561EADE23C37C3000943C72 /* UITableView+Extension.swift in Sources */, diff --git a/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManager.swift b/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManager.swift index 9cd2c512..2514a497 100644 --- a/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManager.swift +++ b/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManager.swift @@ -7,9 +7,9 @@ import Foundation import NinchatLowLevelClient -typealias CompletionWithError = ((Error?) -> Void) -typealias CompletionWithCredentials = ((NINSessionCredentials?, _ willResume: Bool, Error?) -> Void) -typealias Completion = (() -> Void) +typealias CompletionWithError = (Error?) -> Void +typealias CompletionWithCredentials = (NINSessionCredentials?, _ willResume: Bool, Error?) -> Void +typealias Completion = () -> Void /* Available ratings and assigned status codes for finishing the chat from our end */ enum ChatStatus: Int { @@ -38,13 +38,13 @@ protocol NINChatSessionConnectionManager { func list(queues ID: [String]?, completion: @escaping CompletionWithError) throws /** Joins a chat queue. */ - func join(queue ID: String, progress: @escaping ((Queue?, Error?, Int) -> Void), completion: @escaping Completion) throws + func join(queue ID: String, progress: @escaping (Queue?, Error?, Int) -> Void, completion: @escaping Completion) throws /** Deallocate a session by resetting local variables */ func deallocateSession() /** Runs ICE (Interactive Connectivity Establishment) for WebRTC connection negotiations. */ - func beginICE(completion: @escaping ((Error?, [WebRTCServerInfo]?, [WebRTCServerInfo]?) -> Void)) throws + func beginICE(completion: @escaping (Error?, [WebRTCServerInfo]?, [WebRTCServerInfo]?) -> Void) throws /** Closes the chat by shutting down the session. Triggers the API delegate method -ninchatDidEndChatSession:. */ func closeChat() throws @@ -85,7 +85,7 @@ protocol NINChatSessionMessenger { protocol NINChatSessionAttachment { /** Describe a file by its ID. */ - func describe(file id: String, completion: @escaping ((Error?, [String:Any]?) -> Void)) throws + func describe(file id: String, completion: @escaping (Error?, [String:Any]?) -> Void) throws } protocol NINChatSessionTranslation { @@ -109,7 +109,7 @@ protocol NINChatSessionManagerDelegate { var onRTCSignal: ((MessageType, ChannelUser?, _ signal: RTCSignal?) -> Void)? { get set } var onRTCClientSignal: ((MessageType, ChannelUser?, _ signal: RTCSignal?) -> Void)? { get set } - func bindQueueUpdate(closure: @escaping ((Events, Queue, Error?) -> Void), to receiver: T) + func bindQueueUpdate(closure: @escaping (Events, Queue, Error?) -> Void, to receiver: T) func unbindQueueUpdateClosure(from receiver: T) } @@ -132,5 +132,5 @@ protocol NINChatSessionManager: class, NINChatSessionConnectionManager, NINChatS var appDetails: String? { get set } /** Default initializer for NinchatSessionManager. */ - init(session: NINChatSessionInternalDelegate?, serverAddress: String, audienceMetadata: NINLowLevelClientProps?) + init(session: NINChatSessionInternalDelegate?, serverAddress: String, audienceMetadata: NINLowLevelClientProps?, configuration: NINSiteConfiguration?) } diff --git a/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManagerImpl.swift b/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManagerImpl.swift index e78f1567..251a1cc9 100644 --- a/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManagerImpl.swift +++ b/NinchatSDKSwift/Implementations/Managers/Session Manager/NINChatSessionManagerImpl.swift @@ -44,11 +44,11 @@ final class NINChatSessionManagerImpl: NSObject, NINChatSessionManager, NINChatD // MARK: - NINChatSessionManagerClosureHandler - internal var actionBoundClosures: [Int:((Error?) -> Void)] = [:] - internal var actionFileBoundClosures: [Int:((Error?, [String:Any]?) -> Void)] = [:] - internal var actionChannelBoundClosures: [Int:((Error?) -> Void)] = [:] - internal var actionICEServersBoundClosures: [Int:((Error?, [WebRTCServerInfo]?, [WebRTCServerInfo]?) -> Void)] = [:] - internal var queueUpdateBoundClosures: [String:((Events, Queue, Error?) -> Void)] = [:] + internal var actionBoundClosures: [Int: (Error?) -> Void] = [:] + internal var actionFileBoundClosures: [Int: (Error?, [String:Any]?) -> Void] = [:] + internal var actionChannelBoundClosures: [Int: (Error?) -> Void] = [:] + internal var actionICEServersBoundClosures: [Int: (Error?, [WebRTCServerInfo]?, [WebRTCServerInfo]?) -> Void] = [:] + internal var queueUpdateBoundClosures: [String: (Events, Queue, Error?) -> Void] = [:] // MARK: - NINChatSessionConnectionManager variables @@ -71,7 +71,7 @@ final class NINChatSessionManagerImpl: NSObject, NINChatSessionManager, NINChatD var onRTCSignal: ((MessageType, ChannelUser?, _ signal: RTCSignal?) -> Void)? var onRTCClientSignal: ((MessageType, ChannelUser?, _ signal: RTCSignal?) -> Void)? - func bindQueueUpdate(closure: @escaping ((Events, Queue, Error?) -> Void), to receiver: T) { + func bindQueueUpdate(closure: @escaping (Events, Queue, Error?) -> Void, to receiver: T) { guard queueUpdateBoundClosures.keys.filter({ $0 == receiver.desc }).count == 0 else { return } queueUpdateBoundClosures[receiver.desc] = closure } @@ -90,6 +90,7 @@ final class NINChatSessionManagerImpl: NSObject, NINChatSessionManager, NINChatD } var audienceQueues: [Queue]! = [] var siteConfiguration: SiteConfiguration! + var givenConfiguration: NINSiteConfiguration? var appDetails: String? // MARK: - NINChatSessionManagerDevTools @@ -97,15 +98,16 @@ final class NINChatSessionManagerImpl: NSObject, NINChatSessionManager, NINChatD var serverAddress: String! var siteSecret: String? - init(session: NINChatSessionInternalDelegate?, serverAddress: String, audienceMetadata: NINLowLevelClientProps? = nil) { + init(session: NINChatSessionInternalDelegate?, serverAddress: String, audienceMetadata: NINLowLevelClientProps? = nil, configuration: NINSiteConfiguration?) { self.delegate = session self.serverAddress = serverAddress self.audienceMetadata = audienceMetadata + self.givenConfiguration = configuration } /** Designed for test and internal purposes. */ - convenience init(session: NINChatSessionInternalDelegate?, serverAddress: String, siteSecret: String?, audienceMetadata: NINLowLevelClientProps? = nil) { - self.init(session: session, serverAddress: serverAddress, audienceMetadata: audienceMetadata) + convenience init(session: NINChatSessionInternalDelegate?, serverAddress: String, siteSecret: String?, audienceMetadata: NINLowLevelClientProps? = nil, configuration: NINSiteConfiguration? = nil) { + self.init(session: session, serverAddress: serverAddress, audienceMetadata: audienceMetadata, configuration: configuration) self.siteSecret = siteSecret } @@ -147,6 +149,7 @@ extension NINChatSessionManagerImpl { case .success(let config): debugger("Got site config: \(String(describing: config.toDictionary))") self.siteConfiguration = SiteConfigurationImpl(configuration: config.toDictionary, environments: environments) + self.siteConfiguration.override(configuration: self.givenConfiguration) completion(nil) case .failure(let error): completion(error) @@ -210,7 +213,7 @@ extension NINChatSessionManagerImpl { try self.describe(realm: realmID, queuesID: ID, completion: completion) } - func join(queue ID: String, progress: @escaping ((Queue?, Error?, Int) -> Void), completion: @escaping Completion) throws { + func join(queue ID: String, progress: @escaping (Queue?, Error?, Int) -> Void, completion: @escaping Completion) throws { func performJoin() throws { delegate?.log(value: "Joining queue \(ID)..") @@ -283,11 +286,12 @@ extension NINChatSessionManagerImpl { self.currentQueueID = nil self.myUserID = nil + self.disconnect() self.onSessionDeallocated?() } /// Retrieves the WebRTC ICE STUN/TURN server details - func beginICE(completion: @escaping ((Error?, [WebRTCServerInfo]?, [WebRTCServerInfo]?) -> Void)) throws { + func beginICE(completion: @escaping (Error?, [WebRTCServerInfo]?, [WebRTCServerInfo]?) -> Void) throws { guard let session = self.session else { throw NINSessionExceptions.noActiveSession } let param = NINLowLevelClientProps.initiate(action: .beginICE) @@ -302,13 +306,24 @@ extension NINChatSessionManagerImpl { /// Low-level shutdown of the chat's session; invalidates session resource. func closeChat() throws { delegate?.log(value: "Shutting down chat Session..") - try self.deleteCurrentUser { [unowned self] error in + + func endSession() { self.disconnect() - + /// Signal the delegate that our session has ended self.delegate?.onDidEnd() self.didEndSession?() } + + if self.myUserID == nil { + endSession() + } else if let userID = self.myUserID, let user = self.channelUsers[userID], user.guest { + endSession() + } else { + try self.deleteCurrentUser { error in + endSession() + } + } } /// High-level chat ending; sends channel metadata and then closes session. diff --git a/NinchatSDKSwift/Implementations/Models/SiteConfiguration.swift b/NinchatSDKSwift/Implementations/Models/SiteConfiguration.swift index 8d34e2c9..b4dbe1d5 100644 --- a/NinchatSDKSwift/Implementations/Models/SiteConfiguration.swift +++ b/NinchatSDKSwift/Implementations/Models/SiteConfiguration.swift @@ -20,79 +20,95 @@ protocol SiteConfiguration { var userAvatar: AnyHashable? { get } var userName: String? { get } var noQueueText: String? { get } + var audienceAutoQueue: String? { get } init(configuration: [AnyHashable : Any]?, environments: [String]?) + mutating func override(configuration: NINSiteConfiguration?) } struct SiteConfigurationImpl: SiteConfiguration { private let configuration: [AnyHashable : Any]? private let environments: [String] - init(configuration: [AnyHashable : Any]?, environments: [String]?) { - self.configuration = configuration ?? [:] - self.environments = environments ?? [] + // MARK: - NINSiteConfiguration + + private var _userName: String? + var userName: String? { + get { + if _userName != nil { + return _userName + } + return self.value(for: "userName") + } + set { + _userName = newValue + } } - + + // MARK: - SiteConfiguration + var welcome: String? { self.value(for: "welcome") } - var motd: String? { self.value(for: "motd") } - var inQueue: String? { self.value(for: "inQueueText") } - var sendButtonTitle: String? { self.value(for: "sendButtonText") } - var confirmDialogTitle: String? { self.value(for: "closeConfirmText") } - var audienceRealm: String? { self.value(for: "audienceRealmId") } - var audienceQueues: [String]? { self.value(for: "audienceQueues") } - var translation: [String:String]? { self.value(for: "translations") } - var agentAvatar: AnyHashable? { self.value(for: "agentAvatar") } - var agentName: String? { self.value(for: "agentName") } - var userAvatar: AnyHashable? { self.value(for: "userAvatar") } - - var userName: String? { - self.value(for: "userName") - } - var noQueueText: String? { self.value(for: "noQueuesText") } + + var audienceAutoQueue: String? { + self.value(for: "audienceAutoQueue") + } + + init(configuration: [AnyHashable : Any]?, environments: [String]?) { + self.configuration = configuration ?? [:] + self.environments = environments ?? [] + } + + mutating func override(configuration: NINSiteConfiguration?) { + guard let configuration = configuration else { return } + self.userName = configuration.userName + } } extension SiteConfigurationImpl { private func value(for key: String) -> T? { - guard let configuration = configuration as? [String : Any] else { return nil } - - if let value = self.environments.compactMap({ (configuration[$0] as? [String : Any])?[key] }).first as? T { + guard let configuration = configuration as? [String:Any] else { return nil } + + /// Use given environments first, if any + if let value = self.environments.compactMap({ (configuration[$0] as? [String:Any])?[key] }).first as? T { return value } + + /// Return value from default environment return (configuration["default"] as? [String : Any])?[key] as? T } } \ No newline at end of file diff --git a/NinchatSDKSwift/Implementations/View/ViewController/NINChatViewController.swift b/NinchatSDKSwift/Implementations/View/ViewController/NINChatViewController.swift index 42bb5cc0..e5810132 100644 --- a/NinchatSDKSwift/Implementations/View/ViewController/NINChatViewController.swift +++ b/NinchatSDKSwift/Implementations/View/ViewController/NINChatViewController.swift @@ -291,7 +291,7 @@ final class NINChatViewController: UIViewController, ViewController, KeyboardHan } private func deallocViewModel() { - debugger("** ** - deallocate view model") + debugger("** ** deallocate view model") self.viewModel.onChannelClosed = nil self.viewModel.onQueueUpdated = nil diff --git a/NinchatSDKSwift/Implementations/View/ViewController/NINQueueViewController.swift b/NinchatSDKSwift/Implementations/View/ViewController/NINQueueViewController.swift index 95d1d8e1..a33918a9 100644 --- a/NinchatSDKSwift/Implementations/View/ViewController/NINQueueViewController.swift +++ b/NinchatSDKSwift/Implementations/View/ViewController/NINQueueViewController.swift @@ -70,11 +70,18 @@ final class NINQueueViewController: UIViewController, ViewController { super.viewDidLoad() self.setupViewModel() self.overrideAssets() + + NotificationCenter.default.addObserver(self, selector: #selector(spin(notification:)), name: UIApplication.willEnterForegroundNotification, object: nil) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - self.spin() + self.spin(notification: nil) + } + + deinit { + debugger("`NINQueueViewController` deallocated") + NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) } private func setupViewModel() { @@ -96,7 +103,8 @@ final class NINQueueViewController: UIViewController, ViewController { // MARK: - Helper methods extension NINQueueViewController { - private func spin() { + @objc + private func spin(notification: Notification?) { guard spinnerImageView.layer.animation(forKey: "SpinAnimation") == nil else { return } let animation = CABasicAnimation(keyPath: "transform.rotation.z") diff --git a/NinchatSDKSwift/NINChatSession.swift b/NinchatSDKSwift/NINChatSession.swift index ae3cecbb..21b51a9a 100644 --- a/NinchatSDKSwift/NINChatSession.swift +++ b/NinchatSDKSwift/NINChatSession.swift @@ -25,12 +25,17 @@ public protocol NINChatSessionProtocol { var session: NINResult { get } var delegate: NINChatSessionDelegate? { get set } - init(configKey: String, queueID: String?, environments: [String]?, metadata: NINLowLevelClientProps?) + init(configKey: String, queueID: String?, environments: [String]?, metadata: NINLowLevelClientProps?, configuration: NINSiteConfiguration?) func start(completion: @escaping NinchatSessionCompletion) throws func start(credentials: NINSessionCredentials, completion: @escaping NinchatSessionCompletion) throws func chatSession(within navigationController: UINavigationController?) throws -> UIViewController? func deallocate() } +extension NINChatSessionProtocol { + init(configKey: String, queueID: String?, environments: [String]?, metadata: NINLowLevelClientProps?) { + self.init(configKey: configKey, queueID: queueID, environments: environments, metadata: metadata, configuration: nil) + } +} public final class NINChatSession: NINChatSessionProtocol, NINChatDevHelper { var sessionManager: NINChatSessionManager! @@ -74,14 +79,14 @@ public final class NINChatSession: NINChatSessionProtocol, NINChatDevHelper { } } - public init(configKey: String, queueID: String? = nil, environments: [String]? = nil, metadata: NINLowLevelClientProps? = nil) { + public init(configKey: String, queueID: String? = nil, environments: [String]? = nil, metadata: NINLowLevelClientProps? = nil, configuration: NINSiteConfiguration? = nil) { self.configKey = configKey self.queueID = queueID self.environments = environments self.started = false self.coordinator = NINCoordinator(with: self) - self.sessionManager = NINChatSessionManagerImpl(session: self, serverAddress: defaultServerAddress, audienceMetadata: metadata) + self.sessionManager = NINChatSessionManagerImpl(session: self, serverAddress: defaultServerAddress, audienceMetadata: metadata, configuration: configuration) } /// Performs these steps: @@ -115,16 +120,14 @@ public final class NINChatSession: NINChatSessionProtocol, NINChatDevHelper { guard Thread.isMainThread else { throw NINExceptions.mainThread } guard self.started else { throw NINExceptions.apiNotStarted } - return coordinator.start(with: self.queueID, resumeSession: self.resumed, within: navigationController) + return coordinator.start(with: self.queueID ?? self.sessionManager.siteConfiguration.audienceAutoQueue, resumeSession: self.resumed, within: navigationController) } public func deallocate() { - self.sessionManager?.deallocateSession() - self.sessionManager = nil - self.coordinator?.deallocate() self.coordinator = nil - + self.sessionManager?.deallocateSession() + self.sessionManager = nil self.started = false } } diff --git a/NinchatSDKSwift/NINChatSessionClosure.swift b/NinchatSDKSwift/NINChatSessionClosure.swift deleted file mode 100644 index 44ae55c6..00000000 --- a/NinchatSDKSwift/NINChatSessionClosure.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 9.12.2019 Somia Reality Oy. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// - -import UIKit -import NinchatLowLevelClient - -/// Having Closures and Delegates together might result in confusion for the customers -/// Additionally, the consistency might be violated when both patterns are usable. -/// Thus, the following would be dismissed. - -/* -public protocol NINChatSessionClosure { - var didOutputSDKLog: ((NINChatSession, String) -> Void)? { get set } - var onLowLevelEvent: ((NINChatSession, NINLowLevelClientProps, NINLowLevelClientPayload, Bool) -> Void)? { get set } - var overrideImageAsset: ((NINChatSession, AssetConstants) -> UIImage?)? { get set } - var overrideColorAsset: ((NINChatSession, ColorConstants) -> UIColor?)? { get set } - var didEndSession: ((NINChatSession) -> Void)? { get set } - var didFailToResume: ((NINChatSession?) -> Bool)? { get set } -} -*/ \ No newline at end of file diff --git a/NinchatSDKSwift/NINSiteConfiguration.swift b/NinchatSDKSwift/NINSiteConfiguration.swift new file mode 100644 index 00000000..39a69bdc --- /dev/null +++ b/NinchatSDKSwift/NINSiteConfiguration.swift @@ -0,0 +1,20 @@ +// +// Copyright (c) 9.12.2019 Somia Reality Oy. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +import UIKit + +public protocol NINSiteConfiguration { + var userName: String? { get } + init(userName: String?) +} + +public struct NINSiteConfigurationImpl: NINSiteConfiguration { + public var userName: String? + + public init(userName: String?) { + self.userName = userName + } +} \ No newline at end of file diff --git a/NinchatSDKSwiftServerTests/NinchatSDKSwiftServerSessionTests.swift b/NinchatSDKSwiftServerTests/NinchatSDKSwiftServerSessionTests.swift index 4a99a4f7..3e1ede2c 100644 --- a/NinchatSDKSwiftServerTests/NinchatSDKSwiftServerSessionTests.swift +++ b/NinchatSDKSwiftServerTests/NinchatSDKSwiftServerSessionTests.swift @@ -31,6 +31,8 @@ final class NinchatSDKSwiftServerSessionTests: XCTestCase { expect_leave.assertForOverFulfill = false self.sessionManager.fetchSiteConfiguration(config: Session.configurationKey, environments: []) { _ in + XCTAssertEqual(self.sessionManager.siteConfiguration.userName, "Asiakas (öäå)") + self.openSession { credentials1 in /// A useless session, to be closed once the other is opened. XCTAssertNotNil(credentials1) @@ -92,6 +94,29 @@ final class NinchatSDKSwiftServerSessionTests: XCTestCase { /// The test needs a manual interaction from server to fulfills all expectations waitForExpectations(timeout: 10.0) } + + func testServer_dynamicUserName() { + let expect = self.expectation(description: "Expected to override configurations") + + self.sessionManager = Session.initiate(NINSiteConfigurationImpl(userName: "Hassan - iPhone")) + XCTAssertNotNil(self.sessionManager.givenConfiguration?.userName) + XCTAssertEqual(self.sessionManager.givenConfiguration?.userName, "Hassan - iPhone") + + self.sessionManager.fetchSiteConfiguration(config: Session.configurationKey, environments: []) { error in + do { + try self.sessionManager.openSession { _, _, error in + XCTAssertNil(error) + + XCTAssertNotNil(self.sessionManager.siteConfiguration.userName) + XCTAssertEqual(self.sessionManager.siteConfiguration.userName, "Hassan - iPhone") + expect.fulfill() + } + } catch { + XCTFail(error.localizedDescription) + } + } + waitForExpectations(timeout: 10.0) + } } extension NinchatSDKSwiftServerSessionTests: QueueUpdateCapture { @@ -115,16 +140,6 @@ extension NinchatSDKSwiftServerSessionTests { } } - private func resumeSession(credentials: NINSessionCredentials, completion: @escaping (NINSessionCredentials?, Error?) -> Void) { - do { - try self.sessionManager.continueSession(credentials: credentials) { credentials, _, error in - completion(credentials, error) - } - } catch { - XCTFail(error.localizedDescription) - } - } - private func closeSession(completion: @escaping (Error?) -> Void) { do { try self.sessionManager.deleteCurrentUser { error in @@ -139,4 +154,4 @@ extension NinchatSDKSwiftServerSessionTests { internal func simulateTextMessage(_ message: String) throws { try self.sessionManager.send(message: message, completion: { _ in }) } -} \ No newline at end of file +} diff --git a/NinchatSDKSwiftServerTests/NinchatSDKSwiftTests.swift b/NinchatSDKSwiftServerTests/NinchatSDKSwiftTests.swift index b5b6465d..fc355bd6 100644 --- a/NinchatSDKSwiftServerTests/NinchatSDKSwiftTests.swift +++ b/NinchatSDKSwiftServerTests/NinchatSDKSwiftTests.swift @@ -39,8 +39,8 @@ struct Configuration: Codable { final class Session { static var Manager = NINChatSessionManagerImpl(session: nil, serverAddress: serverAddress, siteSecret: siteSecret) - static func initiate() -> NINChatSessionManagerImpl { - NINChatSessionManagerImpl(session: nil, serverAddress: serverAddress, siteSecret: siteSecret) + static func initiate(_ configuration: NINSiteConfiguration? = nil) -> NINChatSessionManagerImpl { + NINChatSessionManagerImpl(session: nil, serverAddress: serverAddress, siteSecret: siteSecret, configuration: configuration) } private static var configuration: Configuration { @@ -65,4 +65,4 @@ final class Session { static var closedQueue: String? { configuration.closedQueue } -} \ No newline at end of file +} diff --git a/NinchatSDKSwiftTests/NINChatViewModelTests.swift b/NinchatSDKSwiftTests/NINChatViewModelTests.swift index 1d243d1e..a6f76193 100644 --- a/NinchatSDKSwiftTests/NINChatViewModelTests.swift +++ b/NinchatSDKSwiftTests/NINChatViewModelTests.swift @@ -21,7 +21,7 @@ class NINChatViewModelTests: XCTestCase, NINChatWebRTCClientDelegate { override func setUp() { let delegate = NINChatSession(configKey: "") - sessionManager = NINChatSessionManagerImpl(session: delegate, serverAddress: "") + sessionManager = NINChatSessionManagerImpl(session: delegate, serverAddress: "", configuration: nil) viewModel = NINChatViewModelImpl(sessionManager: sessionManager) } diff --git a/NinchatSDKSwiftTests/NinchatSessionManagerTests.swift b/NinchatSDKSwiftTests/NinchatSessionManagerTests.swift index 0a2342a3..2642b5d6 100644 --- a/NinchatSDKSwiftTests/NinchatSessionManagerTests.swift +++ b/NinchatSDKSwiftTests/NinchatSessionManagerTests.swift @@ -15,7 +15,7 @@ class NinchatSessionManagerTests: XCTestCase { override func setUp() { sessionSwift = NINChatSession(configKey: "") - sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "") + sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "", configuration: nil) } override func tearDown() { } @@ -37,7 +37,7 @@ class NinchatSessionManagerPrivateTests: XCTestCase { override func setUp() { sessionSwift = NINChatSession(configKey: "") - sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "") + sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "", configuration: nil) } func testIndexOfItem() { @@ -145,7 +145,7 @@ class NinchatSessionManagerClosureHandlersTests: XCTestCase { override func setUp() { sessionSwift = NINChatSession(configKey: "") - sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "") + sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "", configuration: nil) } func testBindFailure() { diff --git a/NinchatSDKSwiftTests/UIKitTests.swift b/NinchatSDKSwiftTests/UIKitTests.swift index 2cfd012f..2ffd2ed8 100644 --- a/NinchatSDKSwiftTests/UIKitTests.swift +++ b/NinchatSDKSwiftTests/UIKitTests.swift @@ -15,7 +15,7 @@ final class UIKitTests: XCTestCase { override func setUp() { sessionSwift = NINChatSession(configKey: "") - sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "") + sessionManager = NINChatSessionManagerImpl(session: sessionSwift, serverAddress: "", configuration: nil) } func test_confirmView() {