Skip to content

Commit

Permalink
Remove GenericCallLinkCoordinator, merging it into CallScreen.
Browse files Browse the repository at this point in the history
This will allow for picture in picture on call links when available.
  • Loading branch information
pixlwave committed Aug 19, 2024
1 parent c5fcca6 commit ec11df8
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 265 deletions.
36 changes: 24 additions & 12 deletions ElementX.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

27 changes: 26 additions & 1 deletion ElementX/Sources/Application/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
if let userSessionFlowCoordinator {
userSessionFlowCoordinator.handleAppRoute(route, animated: true)
} else {
navigationRootCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url)))
presentCallScreen(genericCallLink: url)
}
case .userProfile(let userID):
if isExternalURL {
Expand Down Expand Up @@ -648,6 +648,31 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg

elementCallService.setClientProxy(userSession.clientProxy)
}

private func presentCallScreen(genericCallLink url: URL) {
let configuration = ElementCallConfiguration(genericCallLink: url)

let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: elementCallService,
configuration: configuration,
elementCallPictureInPictureEnabled: false,
appHooks: appHooks))

callScreenCoordinator.actions
.sink { [weak self] action in
guard let self else { return }
switch action {
case .pictureInPictureStarted, .pictureInPictureStopped:
// Don't allow PiP when signed out - the user could login at which point we'd
// need to hand over the call from here to the user session flow coordinator.
MXLog.error("Picture in Picture not supported before login.")
case .dismiss:
navigationRootCoordinator.setOverlayCoordinator(nil)
}
}
.store(in: &cancellables)

navigationRootCoordinator.setOverlayCoordinator(callScreenCoordinator, animated: false)
}

private func configureNotificationManager() {
notificationManager.setUserSession(userSession)
Expand Down
48 changes: 27 additions & 21 deletions ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,9 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
case .userProfile(let userID):
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
case .call(let roomID):
Task {
await presentCallScreen(roomID: roomID)
}
Task { await presentCallScreen(roomID: roomID) }
case .genericCallLink(let url):
navigationSplitCoordinator.setSheetCoordinator(GenericCallLinkCoordinator(parameters: .init(url: url)), animated: animated)
presentCallScreen(genericCallLink: url)
case .settings, .chatBackupSettings:
settingsFlowCoordinator.handleAppRoute(appRoute, animated: animated)
case .oidcCallback:
Expand Down Expand Up @@ -558,23 +556,39 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {

// MARK: Calls

private var callScreenPictureInPictureController: AVPictureInPictureController?
private func presentCallScreen(genericCallLink url: URL) {
presentCallScreen(configuration: .init(genericCallLink: url))
}

private func presentCallScreen(roomID: String) async {
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
return
}

presentCallScreen(roomProxy: roomProxy)
}

private func presentCallScreen(roomProxy: RoomProxyProtocol) {
guard elementCallService.ongoingCallRoomID != roomProxy.id else {
let colorScheme: ColorScheme = appMediator.windowManager.mainWindow.traitCollection.userInterfaceStyle == .light ? .light : .dark
presentCallScreen(configuration: .init(roomProxy: roomProxy,
clientProxy: userSession.clientProxy,
clientID: InfoPlistReader.main.bundleIdentifier,
elementCallBaseURL: appSettings.elementCallBaseURL,
elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride,
colorScheme: colorScheme))
}

private var callScreenPictureInPictureController: AVPictureInPictureController?
private func presentCallScreen(configuration: ElementCallConfiguration) {
guard elementCallService.ongoingCallRoomID != configuration.callID else {
MXLog.info("Returning to existing call.")
callScreenPictureInPictureController?.stopPictureInPicture()
return
}

let colorScheme: ColorScheme = appMediator.windowManager.mainWindow.traitCollection.userInterfaceStyle == .light ? .light : .dark
let callScreenCoordinator = CallScreenCoordinator(parameters: .init(elementCallService: elementCallService,
clientProxy: userSession.clientProxy,
roomProxy: roomProxy,
clientID: InfoPlistReader.main.bundleIdentifier,
elementCallBaseURL: appSettings.elementCallBaseURL,
elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride,
configuration: configuration,
elementCallPictureInPictureEnabled: appSettings.elementCallPictureInPictureEnabled,
colorScheme: colorScheme,
appHooks: appHooks))

callScreenCoordinator.actions
Expand All @@ -600,14 +614,6 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
analytics.track(screen: .RoomCall)
}

private func presentCallScreen(roomID: String) async {
guard let roomProxy = await userSession.clientProxy.roomForIdentifier(roomID) else {
return
}

presentCallScreen(roomProxy: roomProxy)
}

private func dismissCallScreenIfNeeded() {
guard navigationSplitCoordinator.sheetCoordinator is CallScreenCoordinator else {
return
Expand Down
50 changes: 25 additions & 25 deletions ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5142,74 +5142,74 @@ class ElementCallWidgetDriverMock: ElementCallWidgetDriverProtocol {
return startBaseURLClientIDColorSchemeReturnValue
}
}
//MARK: - sendMessage
//MARK: - handleMessage

var sendMessageUnderlyingCallsCount = 0
var sendMessageCallsCount: Int {
var handleMessageUnderlyingCallsCount = 0
var handleMessageCallsCount: Int {
get {
if Thread.isMainThread {
return sendMessageUnderlyingCallsCount
return handleMessageUnderlyingCallsCount
} else {
var returnValue: Int? = nil
DispatchQueue.main.sync {
returnValue = sendMessageUnderlyingCallsCount
returnValue = handleMessageUnderlyingCallsCount
}

return returnValue!
}
}
set {
if Thread.isMainThread {
sendMessageUnderlyingCallsCount = newValue
handleMessageUnderlyingCallsCount = newValue
} else {
DispatchQueue.main.sync {
sendMessageUnderlyingCallsCount = newValue
handleMessageUnderlyingCallsCount = newValue
}
}
}
}
var sendMessageCalled: Bool {
return sendMessageCallsCount > 0
var handleMessageCalled: Bool {
return handleMessageCallsCount > 0
}
var sendMessageReceivedMessage: String?
var sendMessageReceivedInvocations: [String] = []
var handleMessageReceivedMessage: String?
var handleMessageReceivedInvocations: [String] = []

var sendMessageUnderlyingReturnValue: Result<Bool, ElementCallWidgetDriverError>!
var sendMessageReturnValue: Result<Bool, ElementCallWidgetDriverError>! {
var handleMessageUnderlyingReturnValue: Result<Bool, ElementCallWidgetDriverError>!
var handleMessageReturnValue: Result<Bool, ElementCallWidgetDriverError>! {
get {
if Thread.isMainThread {
return sendMessageUnderlyingReturnValue
return handleMessageUnderlyingReturnValue
} else {
var returnValue: Result<Bool, ElementCallWidgetDriverError>? = nil
DispatchQueue.main.sync {
returnValue = sendMessageUnderlyingReturnValue
returnValue = handleMessageUnderlyingReturnValue
}

return returnValue!
}
}
set {
if Thread.isMainThread {
sendMessageUnderlyingReturnValue = newValue
handleMessageUnderlyingReturnValue = newValue
} else {
DispatchQueue.main.sync {
sendMessageUnderlyingReturnValue = newValue
handleMessageUnderlyingReturnValue = newValue
}
}
}
}
var sendMessageClosure: ((String) async -> Result<Bool, ElementCallWidgetDriverError>)?
var handleMessageClosure: ((String) async -> Result<Bool, ElementCallWidgetDriverError>)?

func sendMessage(_ message: String) async -> Result<Bool, ElementCallWidgetDriverError> {
sendMessageCallsCount += 1
sendMessageReceivedMessage = message
func handleMessage(_ message: String) async -> Result<Bool, ElementCallWidgetDriverError> {
handleMessageCallsCount += 1
handleMessageReceivedMessage = message
DispatchQueue.main.async {
self.sendMessageReceivedInvocations.append(message)
self.handleMessageReceivedInvocations.append(message)
}
if let sendMessageClosure = sendMessageClosure {
return await sendMessageClosure(message)
if let handleMessageClosure = handleMessageClosure {
return await handleMessageClosure(message)
} else {
return sendMessageReturnValue
return handleMessageReturnValue
}
}
}
Expand Down
14 changes: 2 additions & 12 deletions ElementX/Sources/Screens/CallScreen/CallScreenCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,8 @@ import SwiftUI

struct CallScreenCoordinatorParameters {
let elementCallService: ElementCallServiceProtocol
let clientProxy: ClientProxyProtocol
let roomProxy: RoomProxyProtocol
let clientID: String
let elementCallBaseURL: URL
let elementCallBaseURLOverride: URL?
let configuration: ElementCallConfiguration
let elementCallPictureInPictureEnabled: Bool
let colorScheme: ColorScheme
let appHooks: AppHooks
}

Expand All @@ -50,13 +45,8 @@ final class CallScreenCoordinator: CoordinatorProtocol {

init(parameters: CallScreenCoordinatorParameters) {
viewModel = CallScreenViewModel(elementCallService: parameters.elementCallService,
clientProxy: parameters.clientProxy,
roomProxy: parameters.roomProxy,
clientID: parameters.clientID,
elementCallBaseURL: parameters.elementCallBaseURL,
elementCallBaseURLOverride: parameters.elementCallBaseURLOverride,
configuration: parameters.configuration,
elementCallPictureInPictureEnabled: parameters.elementCallPictureInPictureEnabled,
colorScheme: parameters.colorScheme,
appHooks: parameters.appHooks)
}

Expand Down
Loading

0 comments on commit ec11df8

Please sign in to comment.