Skip to content

Commit

Permalink
Isolate pending interaction logic in separate model
Browse files Browse the repository at this point in the history
Introduce 'PendingInteraction' model to determine pending interaction for SC 2.0.

MOB-3850
  • Loading branch information
igorkravchenko authored and Egor Egorov committed Dec 3, 2024
1 parent 62a2a13 commit 50ee073
Show file tree
Hide file tree
Showing 19 changed files with 460 additions and 67 deletions.
12 changes: 12 additions & 0 deletions GliaWidgets.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,9 @@
AFBBF5782851C391004993B3 /* Glia.Deprecated.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFBBF5772851C391004993B3 /* Glia.Deprecated.swift */; };
AFC40C1C29965F0F001B4C53 /* SecureConversations.ChatWithTranscriptModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFC40C1B29965F0F001B4C53 /* SecureConversations.ChatWithTranscriptModel.swift */; };
AFC7ABB82C2D93A0006F15AA /* Glia+RestoreEngagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFC7ABB72C2D93A0006F15AA /* Glia+RestoreEngagement.swift */; };
AFCDA7242CF8EC2C006E339B /* SecureConversations.PendingInteraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCDA7232CF8EC2C006E339B /* SecureConversations.PendingInteraction.swift */; };
AFCDA7262CFA250A006E339B /* SecureConversations.PendingInteractionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCDA7252CFA250A006E339B /* SecureConversations.PendingInteractionTests.swift */; };
AFCDA7282CFA2ACB006E339B /* SecureConversations.PendingInteraction.Failing.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCDA7272CFA2ACB006E339B /* SecureConversations.PendingInteraction.Failing.swift */; };
AFCF8A5A2A02A97100B7ABB3 /* ChatItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCF8A592A02A97100B7ABB3 /* ChatItemTests.swift */; };
AFCF8A5C2A02AB3000B7ABB3 /* OutgoingMessage.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFCF8A5B2A02AB3000B7ABB3 /* OutgoingMessage.Mock.swift */; };
AFD3C52C2A472B7500BC37A9 /* VisitorInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD3C52B2A472B7500BC37A9 /* VisitorInfoModel.swift */; };
Expand Down Expand Up @@ -1782,6 +1785,9 @@
AFBBF5772851C391004993B3 /* Glia.Deprecated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Glia.Deprecated.swift; sourceTree = "<group>"; };
AFC40C1B29965F0F001B4C53 /* SecureConversations.ChatWithTranscriptModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.ChatWithTranscriptModel.swift; sourceTree = "<group>"; };
AFC7ABB72C2D93A0006F15AA /* Glia+RestoreEngagement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Glia+RestoreEngagement.swift"; sourceTree = "<group>"; };
AFCDA7232CF8EC2C006E339B /* SecureConversations.PendingInteraction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.PendingInteraction.swift; sourceTree = "<group>"; };
AFCDA7252CFA250A006E339B /* SecureConversations.PendingInteractionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.PendingInteractionTests.swift; sourceTree = "<group>"; };
AFCDA7272CFA2ACB006E339B /* SecureConversations.PendingInteraction.Failing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureConversations.PendingInteraction.Failing.swift; sourceTree = "<group>"; };
AFCF8A592A02A97100B7ABB3 /* ChatItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatItemTests.swift; sourceTree = "<group>"; };
AFCF8A5B2A02AB3000B7ABB3 /* OutgoingMessage.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutgoingMessage.Mock.swift; sourceTree = "<group>"; };
AFD3C52B2A472B7500BC37A9 /* VisitorInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitorInfoModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3492,6 +3498,7 @@
AF10ED8C29BA210500E85309 /* SecureConversations.MessagesWithUnreadCountLoader.swift */,
C0D6CA142C184F1900D4709B /* SecureConversations.MessagesWithUnreadCountLoader.Environment.swift */,
3115D45B29A4FD3F00D99561 /* SecureConversations.Availability.swift */,
AFCDA7232CF8EC2C006E339B /* SecureConversations.PendingInteraction.swift */,
);
path = SecureConversations;
sourceTree = "<group>";
Expand Down Expand Up @@ -4759,6 +4766,8 @@
AF29811129E42F3C0005BD55 /* AvailabilityTests.swift */,
AF29810F29E06E830005BD55 /* Availability.Environment.Failing.swift */,
3197F7AC29E6A5C8008EE9F7 /* SecureConversations.FileUploadListView.Mock.swift */,
AFCDA7252CFA250A006E339B /* SecureConversations.PendingInteractionTests.swift */,
AFCDA7272CFA2ACB006E339B /* SecureConversations.PendingInteraction.Failing.swift */,
);
path = SecureConversations;
sourceTree = "<group>";
Expand Down Expand Up @@ -6150,6 +6159,7 @@
AF6291132B0813B000D3D76B /* SwiftBased.Mock.swift in Sources */,
1AC7A74F2582571100567FF8 /* Interactor.swift in Sources */,
AF552EDD2BEE954500FD5653 /* FlipCameraButtonStyle.swift in Sources */,
AFCDA7242CF8EC2C006E339B /* SecureConversations.PendingInteraction.swift in Sources */,
84C24CFC2B8354A80089A388 /* ProcessInfoHandling.Live.swift in Sources */,
AFB6A0792CCBF3B700A1ED9A /* MediaTypeItemStyle.Loading.swift in Sources */,
845E2F72283D068000C04D56 /* HeaderStyle.Accessibility.swift in Sources */,
Expand Down Expand Up @@ -6681,6 +6691,7 @@
7512A57727BE8A6700319DF1 /* InteractorTests.swift in Sources */,
31CCE3E92BCE8F3A00F92535 /* CallVisualizer.VideoCallCoordinator.Environment.Mock.swift in Sources */,
AF29811529E6D76A0005BD55 /* FileDownloadTests.swift in Sources */,
AFCDA7262CFA250A006E339B /* SecureConversations.PendingInteractionTests.swift in Sources */,
C096B40B297EBDE400F0C552 /* VisitorCodeTests.swift in Sources */,
31FF0DD12B5A89A600834AFB /* CallCoordinator.Environment.Mock.swift in Sources */,
9ACC25D427B474E800BC5335 /* Glia.Environment.Failing.swift in Sources */,
Expand Down Expand Up @@ -6742,6 +6753,7 @@
EB7A1508286D98000035AC62 /* FileUploader.Environment.Failing.swift in Sources */,
AF993B3D2C8F5E7000DC5E69 /* EngagementCoordinatorCallTests.swift in Sources */,
AF2355A229C9EC7E007D9896 /* IdCollectionTests.swift in Sources */,
AFCDA7282CFA2ACB006E339B /* SecureConversations.PendingInteraction.Failing.swift in Sources */,
8491AF572AA0964800CC3E72 /* ChatItem.Kind.Mock.swift in Sources */,
84C24CFF2B8357BB0089A388 /* ProcessInfoHandling.Failing.swift in Sources */,
AFFA99822C57D658004A2825 /* GliaTests+RestoreEngagement.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion GliaWidgets/Public/Glia/Glia+EngagementSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ extension Glia {
) {
let engagementLaunching: EngagementCoordinator.EngagementLaunching

switch (hasPendingInteraction, engagementKind) {
switch (pendingInteraction.hasPendingInteraction, engagementKind) {
case (false, _):
// if there is no pending Secure Conversation, open regular flow.
engagementLaunching = .direct(kind: engagementKind)
Expand Down
3 changes: 2 additions & 1 deletion GliaWidgets/Public/Glia/Glia+EntryWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ extension Glia {
log: loggerPhase.logger,
isAuthenticated: environment.isAuthenticated,
hasPendingInteraction: { [weak self] in
self?.hasPendingInteraction ?? false
guard let self else { return false }
return pendingInteraction.hasPendingInteraction
}
)
)
Expand Down
15 changes: 2 additions & 13 deletions GliaWidgets/Public/Glia/Glia.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,7 @@ public class Glia {
//
// Currently it's used to know if we have to force a visitor to SecureMessaging screen,
// once they try to start an engagement with media type other than `messaging`.
var hasPendingInteraction: Bool {
var pendingConversationExists = false
environment.coreSdk.pendingSecureConversationStatusUpdates { hasPendingConversationResult in
pendingConversationExists = (try? hasPendingConversationResult.get()) ?? false
}

var unreadMessageCount = 0
environment.coreSdk.getSecureUnreadMessageCount {
unreadMessageCount = (try? $0.get()) ?? 0
}

return unreadMessageCount > 0 || pendingConversationExists
}
let pendingInteraction: SecureConversations.PendingInteraction

init(environment: Environment) {
self.environment = environment
Expand Down Expand Up @@ -191,6 +179,7 @@ public class Glia {
viewFactory: viewFactory
)
)
pendingInteraction = .init(environment: .init(with: environment.coreSdk))
}

/// Setup SDK using specific engagement configuration without starting the engagement.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Combine

extension SecureConversations {
final class PendingInteraction: ObservableObject {
@Published private(set) var pendingStatus = false
@Published private(set) var unreadMessageCount = 0
@Published private(set) var hasPendingInteraction = false
private let environment: Environment
private(set) var pendingStatusCancellationToken: String?
private(set) var unreadMessageCountCancellationToken: String?

init(environment: Environment) {
self.environment = environment
self.pendingStatusCancellationToken = environment.observePendingSecureConversationsStatus { [weak self] result in
guard let self else { return }
// At this point it is enough to know if there is a pending conversation,
// so no need to handle error.
pendingStatus = (try? result.get()) ?? false
}
self.unreadMessageCountCancellationToken = environment.observeSecureConversationsUnreadMessageCount { [weak self] result in
guard let self else { return }
// At this point it is enough to know if there is an unread message count,
// so no need to handle error.
unreadMessageCount = (try? result.get()) ?? 0
}

$pendingStatus.combineLatest($unreadMessageCount)
.map { hasPending, unreadCount in
hasPending || unreadCount > 0
}
.assign(to: &$hasPendingInteraction)
}

deinit {
if let unreadMessageCountCancellationToken {
environment.unsubscribeFromUnreadCount(unreadMessageCountCancellationToken)
}

if let pendingStatusCancellationToken {
environment.unsubscribeFromPendingStatus(pendingStatusCancellationToken)
}
}
}
}

extension SecureConversations.PendingInteraction {
struct Environment {
var observePendingSecureConversationsStatus: CoreSdkClient.ObservePendingSecureConversationStatus
var observeSecureConversationsUnreadMessageCount: CoreSdkClient.SubscribeForUnreadSCMessageCount
var unsubscribeFromUnreadCount: CoreSdkClient.UnsubscribeFromUnreadCount
var unsubscribeFromPendingStatus: CoreSdkClient.UnsubscribeFromPendingSCStatus
}
}

extension SecureConversations.PendingInteraction.Environment {
init(with client: CoreSdkClient) {
self.observePendingSecureConversationsStatus = client.observePendingSecureConversationStatus
self.observeSecureConversationsUnreadMessageCount = client.subscribeForUnreadSCMessageCount
self.unsubscribeFromPendingStatus = client.unsubscribeFromPendingSecureConversationStatus
self.unsubscribeFromUnreadCount = client.unsubscribeFromUnreadCount
}
}

#if DEBUG
extension SecureConversations.PendingInteraction.Environment {
static let mock = Self(
observePendingSecureConversationsStatus: { _ in nil },
observeSecureConversationsUnreadMessageCount: { _ in nil },
unsubscribeFromUnreadCount: { _ in },
unsubscribeFromPendingStatus: { _ in }
)
}

extension SecureConversations.PendingInteraction {
static func mock(environment: Environment = .mock) -> Self {
.init(environment: environment)
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ extension EngagementCoordinator.Environment {
flipCameraButtonStyle: .nop,
alertManager: .mock(),
queuesMonitor: .mock(),
pendingSecureConversationStatusUpdates: { $0(.success(false)) },
pendingSecureConversationStatus: { $0(.success(false)) },
createEntryWidget: { _ in .mock() },
dismissManager: .init { _, _, _ in }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ extension EngagementCoordinator {
var flipCameraButtonStyle: FlipCameraButtonStyle
var alertManager: AlertManager
var queuesMonitor: QueuesMonitor
var pendingSecureConversationStatusUpdates: CoreSdkClient.PendingSecureConversationStatusUpdates
var pendingSecureConversationStatus: CoreSdkClient.PendingSecureConversationStatus
var createEntryWidget: EntryWidgetBuilder
var dismissManager: GliaPresenter.DismissManager
}
Expand Down Expand Up @@ -103,7 +103,7 @@ extension EngagementCoordinator.Environment {
flipCameraButtonStyle: viewFactory.theme.call.flipCameraButtonStyle,
alertManager: alertManager,
queuesMonitor: queuesMonitor,
pendingSecureConversationStatusUpdates: environment.coreSdk.pendingSecureConversationStatusUpdates,
pendingSecureConversationStatus: environment.coreSdk.pendingSecureConversationStatus,
createEntryWidget: createEntryWidget,
dismissManager: environment.dismissManager
)
Expand Down
16 changes: 14 additions & 2 deletions GliaWidgets/Sources/CoreSDKClient/CoreSDKClient.Interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,21 @@ struct CoreSdkClient {

var subscribeForUnreadSCMessageCount: SubscribeForUnreadSCMessageCount

typealias PendingSecureConversationStatusUpdates = (_ callback: @escaping (Result<Bool, Error>) -> Void) -> Void
typealias PendingSecureConversationStatus = (_ callback: @escaping (Result<Bool, Error>) -> Void) -> Void

var pendingSecureConversationStatusUpdates: PendingSecureConversationStatusUpdates
var pendingSecureConversationStatus: PendingSecureConversationStatus

typealias ObservePendingSecureConversationStatus = (_ callback: @escaping (Result<Bool, Error>) -> Void) -> String?

var observePendingSecureConversationStatus: ObservePendingSecureConversationStatus

typealias UnsubscribeFromPendingSCStatus = (String) -> Void

var unsubscribeFromPendingSecureConversationStatus: UnsubscribeFromPendingSCStatus

typealias UnsubscribeFromUnreadCount = (String) -> Void

var unsubscribeFromUnreadCount: UnsubscribeFromUnreadCount
}

extension CoreSdkClient {
Expand Down
7 changes: 6 additions & 1 deletion GliaWidgets/Sources/CoreSDKClient/CoreSDKClient.Live.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ extension CoreSdkClient {
subscribeForQueuesUpdates: GliaCore.sharedInstance.subscribeForQueuesUpdates(forQueues:completion:),
unsubscribeFromUpdates: GliaCore.sharedInstance.unsubscribeFromUpdates(queueCallbackId:onError:),
subscribeForUnreadSCMessageCount: GliaCore.sharedInstance.secureConversations.subscribeToUnreadMessageCount(completion:),
pendingSecureConversationStatusUpdates: GliaCore.sharedInstance.secureConversations.pendingSecureConversationStatus
pendingSecureConversationStatus: GliaCore.sharedInstance.secureConversations.pendingSecureConversationStatus,
observePendingSecureConversationStatus: GliaCore.sharedInstance.secureConversations.subscribeToPendingSecureConversationStatus,
unsubscribeFromPendingSecureConversationStatus: {
GliaCore.sharedInstance.secureConversations.unsubscribeFromPendingSecureConversationStatus($0)
},
unsubscribeFromUnreadCount: GliaCore.sharedInstance.secureConversations.unsubscribeFromUnreadMessageCount
)
}()
}
Expand Down
5 changes: 4 additions & 1 deletion GliaWidgets/Sources/CoreSDKClient/CoreSDKClient.Mock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ extension CoreSdkClient {
subscribeForQueuesUpdates: { _, _ in UUID.mock.uuidString },
unsubscribeFromUpdates: { _, _ in },
subscribeForUnreadSCMessageCount: { _ in UUID.mock.uuidString },
pendingSecureConversationStatusUpdates: { $0(.success(false)) }
pendingSecureConversationStatus: { $0(.success(false)) },
observePendingSecureConversationStatus: { _ in nil },
unsubscribeFromPendingSecureConversationStatus: { _ in },
unsubscribeFromUnreadCount: { _ in }
)
}

Expand Down
24 changes: 24 additions & 0 deletions GliaWidgetsTests/CallVisualizer/CallVisualizerTests+LO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ extension CallVisualizerTests {
gliaEnv.snackBar.present = { _, _, _, _, _, _, _ in
calls.append(.presentSnackBar)
}
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
let sdk = Glia(environment: gliaEnv)
try sdk.configure(with: .mock(), theme: .mock(), completion: { _ in })

Expand Down Expand Up @@ -66,6 +70,10 @@ extension CallVisualizerTests {
gliaEnv.snackBar.present = { _, _, _, _, _, _, _ in
calls.append(.presentSnackBar)
}
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
let sdk = Glia(environment: gliaEnv)
try sdk.configure(with: .mock(), theme: .mock(), completion: { _ in })

Expand Down Expand Up @@ -102,6 +110,10 @@ extension CallVisualizerTests {
gliaEnv.snackBar.present = { _, _, _, _, _, _, _ in
calls.append(.presentSnackBar)
}
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
let sdk = Glia(environment: gliaEnv)
try sdk.configure(with: .mock(), theme: .mock(), completion: { _ in })

Expand Down Expand Up @@ -132,6 +144,10 @@ extension CallVisualizerTests {
gliaEnv.callVisualizerPresenter = .init(presenter: { nil })
gliaEnv.gcd.mainQueue.asyncIfNeeded = { $0() }
gliaEnv.coreSDKConfigurator.configureWithInteractor = { _ in }
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
let sdk = Glia(environment: gliaEnv)
sdk.environment.coreSDKConfigurator.configureWithConfiguration = { _, completion in
sdk.environment.coreSdk.getCurrentEngagement = {
Expand Down Expand Up @@ -165,6 +181,10 @@ extension CallVisualizerTests {
gliaEnv.callVisualizerPresenter = .init(presenter: { nil })
gliaEnv.gcd.mainQueue.asyncIfNeeded = { $0() }
gliaEnv.coreSDKConfigurator.configureWithInteractor = { _ in }
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
let sdk = Glia(environment: gliaEnv)
sdk.environment.coreSDKConfigurator.configureWithConfiguration = { _, completion in
sdk.environment.coreSdk.getCurrentEngagement = {
Expand Down Expand Up @@ -198,6 +218,10 @@ extension CallVisualizerTests {
gliaEnv.callVisualizerPresenter = .init(presenter: { nil })
gliaEnv.gcd.mainQueue.asyncIfNeeded = { $0() }
gliaEnv.coreSDKConfigurator.configureWithInteractor = { _ in }
gliaEnv.coreSdk.subscribeForUnreadSCMessageCount = { _ in nil }
gliaEnv.coreSdk.observePendingSecureConversationStatus = { _ in nil }
gliaEnv.coreSdk.unsubscribeFromPendingSecureConversationStatus = { _ in }
gliaEnv.coreSdk.unsubscribeFromUnreadCount = { _ in }
let sdk = Glia(environment: gliaEnv)
sdk.environment.coreSDKConfigurator.configureWithConfiguration = { _, completion in
sdk.environment.coreSdk.getCurrentEngagement = {
Expand Down
Loading

0 comments on commit 50ee073

Please sign in to comment.