Skip to content

Commit

Permalink
Fix unexpected capturing in EngagementLauncher
Browse files Browse the repository at this point in the history
This commit fixes the issue when Interactor instance and media are captured during EngagementLauncher creation.

MOB-3963
  • Loading branch information
Egor Egorov authored and EgorovEI committed Jan 21, 2025
1 parent efb3beb commit c4310c8
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 17 deletions.
35 changes: 32 additions & 3 deletions GliaWidgets/Public/Glia/Glia+EngagementLauncher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,39 @@ extension Glia {
/// - Returns:
/// - `EngagementLauncher` instance.
public func getEngagementLauncher(queueIds: [String]) throws -> EngagementLauncher {
let parameters = try getEngagementParameters(in: queueIds)
@discardableResult
func getConfiguration() throws -> Configuration {
guard let configuration else {
throw GliaError.sdkIsNotConfigured
}
return configuration
}

@discardableResult
func getInteractor() throws -> Interactor {
guard let interactor else {
loggerPhase.logger.prefixed(Self.self).warning("Interactor is missing")
throw GliaError.sdkIsNotConfigured
}
return interactor
}

// In order to align behaviour between platforms,
// `GliaError.engagementExists` is no longer thrown,
// instead engagement is getting restored.
try getConfiguration()
try getInteractor()

loggerPhase.logger.info("Returning an Engagement Launcher")
return try EngagementLauncher { [weak self] engagementKind, sceneProvider in
try self?.resolveEngagementState(

return EngagementLauncher { [weak self] engagementKind, sceneProvider in
guard let self else { return }
let parameters = try getEngagementParameters(
configuration: getConfiguration(),
interactor: getInteractor(),
queueIds: queueIds
)
try self.resolveEngagementState(
engagementKind: engagementKind,
sceneProvider: sceneProvider,
configuration: parameters.configuration,
Expand Down
18 changes: 5 additions & 13 deletions GliaWidgets/Public/Glia/Glia+EngagementSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,11 @@ import GliaCoreSDK

extension Glia {
/// Set up and returns parameters needed to start or restore engagement
func getEngagementParameters(in queueIds: [String] = []) throws -> EngagementParameters {
// In order to align behaviour between platforms,
// `GliaError.engagementExists` is no longer thrown,
// instead engagement is getting restored.
guard let configuration else {
throw GliaError.sdkIsNotConfigured
}

guard let interactor else {
loggerPhase.logger.prefixed(Self.self).warning("Interactor is missing")
throw GliaError.sdkIsNotConfigured
}

func getEngagementParameters(
configuration: Configuration,
interactor: Interactor,
queueIds: [String] = []
) -> EngagementParameters {
// Interactor is initialized during configuration, which means that queueIds need
// to be set in interactor when startEngagement is called.
interactor.setQueuesIds(queueIds)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public final class EngagementLauncher {

private var startEngagement: StartEngagementAction

init(startEngagement: @escaping StartEngagementAction) rethrows {
init(startEngagement: @escaping StartEngagementAction) {
self.startEngagement = startEngagement
}

Expand Down
54 changes: 54 additions & 0 deletions GliaWidgetsTests/Sources/Glia/GliaTests+StartEngagement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,60 @@ extension GliaTests {

XCTAssertEqual(engagementLaunching.currentKind, .messaging(.chatTranscript))
}

func testEngagementParamsDoNotLeakThroughEngagements() throws {
var environment = Glia.Environment.failing
var logger = CoreSdkClient.Logger.failing
logger.configureLocalLogLevelClosure = { _ in }
logger.configureRemoteLogLevelClosure = { _ in }
logger.infoClosure = { _, _, _, _ in }
logger.prefixedClosure = { _ in logger }
environment.coreSdk.createLogger = { _ in logger }
environment.print = .mock
environment.conditionalCompilation.isDebug = { true }
environment.gcd.mainQueue.async = { $0() }

var engagementLaunching: EngagementCoordinator.EngagementLaunching = .direct(kind: .audioCall)

environment.createRootCoordinator = { _, _, _, launching, _, _, _ in
engagementLaunching = launching
return .mock(environment: .engagementCoordEnvironmentWithKeyWindow)
}

environment.coreSdk.localeProvider.getRemoteString = { _ in "" }
environment.coreSdk.pendingSecureConversationStatus = { $0(.success(false)) }
environment.coreSDKConfigurator.configureWithInteractor = { _ in }
environment.coreSDKConfigurator.configureWithConfiguration = { _, completion in
completion(.success(()))
}
environment.coreSdk.getSecureUnreadMessageCount = { $0(.success(0)) }
environment.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
environment.coreSdk.observePendingSecureConversationStatus = { _ in nil }
environment.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
environment.coreSdk.unsubscribeFromUnreadCount = { _ in }
environment.coreSdk.fetchSiteConfigurations = { _ in }

let sdk = Glia(environment: environment)
sdk.queuesMonitor = .mock()
try sdk.configure(
with: .mock(),
theme: .mock()
) { _ in }
// Mock ongoing Audio engagement
sdk.environment.coreSdk.getCurrentEngagement = { .mock(media: .init(audio: .twoWay, video: nil)) }

let engagementLauncher = try sdk.getEngagementLauncher(queueIds: ["queueId"])
try engagementLauncher.startChat()
XCTAssertEqual(engagementLaunching.currentKind, .audioCall)

// End audio engagement
sdk.environment.coreSdk.getCurrentEngagement = { nil }
sdk.interactor?.end(with: .operatorHungUp)

try engagementLauncher.startChat()

XCTAssertEqual(engagementLaunching.currentKind, .chat)
}
}

extension EngagementCoordinator.Environment: Transformable {
Expand Down

0 comments on commit c4310c8

Please sign in to comment.