diff --git a/GliaWidgets/Sources/Interactor/Interactor.swift b/GliaWidgets/Sources/Interactor/Interactor.swift index 95ab3e77e..4b6bea2ec 100644 --- a/GliaWidgets/Sources/Interactor/Interactor.swift +++ b/GliaWidgets/Sources/Interactor/Interactor.swift @@ -56,7 +56,7 @@ class Interactor { } let configuration: Configuration - var currentEngagement: CoreSdkClient.Engagement? + weak var currentEngagement: CoreSdkClient.Engagement? /// Flag indicating if configuration was already performed. var isConfigurationPerformed: Bool = false diff --git a/GliaWidgets/Sources/ViewModel/Call/CallViewModel.swift b/GliaWidgets/Sources/ViewModel/Call/CallViewModel.swift index ec2f08e4d..86a705cb5 100644 --- a/GliaWidgets/Sources/ViewModel/Call/CallViewModel.swift +++ b/GliaWidgets/Sources/ViewModel/Call/CallViewModel.swift @@ -72,7 +72,20 @@ class CallViewModel: EngagementViewModel, ViewModel { super.start() update(for: call.kind.value) - update(for: interactor.state) + + // In the case when SDK is configured once and then + // visitor has several Audio/Video engagements in a raw, + // after ending each of them, `interactor.state` has `.ended` value, + // which causes calling `call.end()` on the start of the next + // Audio/Video engagement. That `call.end()` breaks the flow and SDK does not + // handle `connected` state properly. So we need to skip handling `.ended` state + // on the start of a new engagement. + switch interactor.state { + case .ended: + break + default: + update(for: interactor.state) + } switch startWith { case .engagement(let mediaType): diff --git a/GliaWidgets/Sources/ViewModel/EngagementViewModel.swift b/GliaWidgets/Sources/ViewModel/EngagementViewModel.swift index e1e615749..17353e12e 100644 --- a/GliaWidgets/Sources/ViewModel/EngagementViewModel.swift +++ b/GliaWidgets/Sources/ViewModel/EngagementViewModel.swift @@ -11,7 +11,7 @@ class EngagementViewModel: CommonEngagementModel { let alertConfiguration: AlertConfiguration let environment: Environment let screenShareHandler: ScreenShareHandler - var activeEngagement: CoreSdkClient.Engagement? + weak var activeEngagement: CoreSdkClient.Engagement? private(set) var isViewActive = ObservableValue(with: false) @@ -225,10 +225,10 @@ class EngagementViewModel: CommonEngagementModel { } func endSession() { - interactor.endSession { - self.engagementDelegate?(.finished) - } failure: { _ in - self.engagementDelegate?(.finished) + interactor.endSession { [weak self] in + self?.engagementDelegate?(.finished) + } failure: { [weak self] _ in + self?.engagementDelegate?(.finished) } self.screenShareHandler.stop(nil) } diff --git a/GliaWidgetsTests/Sources/CallViewModelTests.swift b/GliaWidgetsTests/Sources/CallViewModelTests.swift index b3500afff..68b97d7e4 100644 --- a/GliaWidgetsTests/Sources/CallViewModelTests.swift +++ b/GliaWidgetsTests/Sources/CallViewModelTests.swift @@ -335,4 +335,16 @@ class CallViewModelTests: XCTestCase { XCTAssertEqual(call.kind.value, .audio) } + + func test_startMethodDoesNotHandleInteractorStateEnded() { + let interactor: Interactor = .mock() + interactor.state = .ended(.byOperator) + let call: Call = .mock() + let viewModel: CallViewModel = .mock(interactor: interactor, call: call) + + XCTAssertEqual(call.state.value, .none) + viewModel.start() + + XCTAssertEqual(call.state.value, .none) + } } diff --git a/TestingApp/Main.storyboard b/TestingApp/Main.storyboard index f573b303d..dea23e613 100644 --- a/TestingApp/Main.storyboard +++ b/TestingApp/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -21,7 +21,7 @@ - + + + + + + + + + + + - + - +