mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 20:09:04 +00:00
Stop delaying ElementCall until the next sync loop and only notify other participants when presumed to already be up to date. (#3559)
This commit is contained in:
@@ -201,7 +201,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
case .userProfile(let userID):
|
case .userProfile(let userID):
|
||||||
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
|
stateMachine.processEvent(.showUserProfileScreen(userID: userID), userInfo: .init(animated: animated))
|
||||||
case .call(let roomID):
|
case .call(let roomID):
|
||||||
Task { await presentCallScreen(roomID: roomID) }
|
Task { await presentCallScreen(roomID: roomID, notifyOtherParticipants: false) }
|
||||||
case .genericCallLink(let url):
|
case .genericCallLink(let url):
|
||||||
presentCallScreen(genericCallLink: url)
|
presentCallScreen(genericCallLink: url)
|
||||||
case .settings, .chatBackupSettings:
|
case .settings, .chatBackupSettings:
|
||||||
@@ -579,7 +579,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .presentCallScreen(let roomProxy):
|
case .presentCallScreen(let roomProxy):
|
||||||
presentCallScreen(roomProxy: roomProxy)
|
// Here we assume that the app is running and the call state is already up to date
|
||||||
|
presentCallScreen(roomProxy: roomProxy, notifyOtherParticipants: !roomProxy.infoPublisher.value.hasRoomCall)
|
||||||
case .finished:
|
case .finished:
|
||||||
stateMachine.processEvent(.deselectRoom)
|
stateMachine.processEvent(.deselectRoom)
|
||||||
}
|
}
|
||||||
@@ -657,22 +658,23 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
presentCallScreen(configuration: .init(genericCallLink: url))
|
presentCallScreen(configuration: .init(genericCallLink: url))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentCallScreen(roomID: String) async {
|
private func presentCallScreen(roomID: String, notifyOtherParticipants: Bool) async {
|
||||||
guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
guard case let .joined(roomProxy) = await userSession.clientProxy.roomForIdentifier(roomID) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
presentCallScreen(roomProxy: roomProxy)
|
presentCallScreen(roomProxy: roomProxy, notifyOtherParticipants: notifyOtherParticipants)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentCallScreen(roomProxy: JoinedRoomProxyProtocol) {
|
private func presentCallScreen(roomProxy: JoinedRoomProxyProtocol, notifyOtherParticipants: Bool) {
|
||||||
let colorScheme: ColorScheme = appMediator.windowManager.mainWindow.traitCollection.userInterfaceStyle == .light ? .light : .dark
|
let colorScheme: ColorScheme = appMediator.windowManager.mainWindow.traitCollection.userInterfaceStyle == .light ? .light : .dark
|
||||||
presentCallScreen(configuration: .init(roomProxy: roomProxy,
|
presentCallScreen(configuration: .init(roomProxy: roomProxy,
|
||||||
clientProxy: userSession.clientProxy,
|
clientProxy: userSession.clientProxy,
|
||||||
clientID: InfoPlistReader.main.bundleIdentifier,
|
clientID: InfoPlistReader.main.bundleIdentifier,
|
||||||
elementCallBaseURL: appSettings.elementCallBaseURL,
|
elementCallBaseURL: appSettings.elementCallBaseURL,
|
||||||
elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride,
|
elementCallBaseURLOverride: appSettings.elementCallBaseURLOverride,
|
||||||
colorScheme: colorScheme))
|
colorScheme: colorScheme,
|
||||||
|
notifyOtherParticipants: notifyOtherParticipants))
|
||||||
}
|
}
|
||||||
|
|
||||||
private var callScreenPictureInPictureController: AVPictureInPictureController?
|
private var callScreenPictureInPictureController: AVPictureInPictureController?
|
||||||
@@ -899,7 +901,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
|||||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||||
stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room))
|
stateMachine.processEvent(.selectRoom(roomID: roomID, via: [], entryPoint: .room))
|
||||||
case .startCall(let roomID):
|
case .startCall(let roomID):
|
||||||
Task { await self.presentCallScreen(roomID: roomID) }
|
Task { await self.presentCallScreen(roomID: roomID, notifyOtherParticipants: false) }
|
||||||
case .dismiss:
|
case .dismiss:
|
||||||
navigationSplitCoordinator.setSheetCoordinator(nil)
|
navigationSplitCoordinator.setSheetCoordinator(nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
actionsSubject.eraseToAnyPublisher()
|
actionsSubject.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var syncUpdateCancellable: AnyCancellable?
|
|
||||||
|
|
||||||
/// Designated initialiser
|
/// Designated initialiser
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - elementCallService: service responsible for setting up CallKit
|
/// - elementCallService: service responsible for setting up CallKit
|
||||||
@@ -43,7 +41,7 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
switch configuration.kind {
|
switch configuration.kind {
|
||||||
case .genericCallLink(let url):
|
case .genericCallLink(let url):
|
||||||
widgetDriver = GenericCallLinkWidgetDriver(url: url)
|
widgetDriver = GenericCallLinkWidgetDriver(url: url)
|
||||||
case .roomCall(let roomProxy, let clientProxy, _, _, _, _):
|
case .roomCall(let roomProxy, let clientProxy, _, _, _, _, _):
|
||||||
guard let deviceID = clientProxy.deviceID else { fatalError("Missing device ID for the call.") }
|
guard let deviceID = clientProxy.deviceID else { fatalError("Missing device ID for the call.") }
|
||||||
widgetDriver = roomProxy.elementCallWidgetDriver(deviceID: deviceID)
|
widgetDriver = roomProxy.elementCallWidgetDriver(deviceID: deviceID)
|
||||||
}
|
}
|
||||||
@@ -137,47 +135,39 @@ class CallScreenViewModel: CallScreenViewModelType, CallScreenViewModelProtocol
|
|||||||
case .genericCallLink(let url):
|
case .genericCallLink(let url):
|
||||||
state.url = url
|
state.url = url
|
||||||
// We need widget messaging to work before enabling CallKit, otherwise mute, hangup etc do nothing.
|
// We need widget messaging to work before enabling CallKit, otherwise mute, hangup etc do nothing.
|
||||||
|
|
||||||
case .roomCall(let roomProxy, let clientProxy, let clientID, let elementCallBaseURL, let elementCallBaseURLOverride, let colorScheme):
|
case .roomCall(let roomProxy, let clientProxy, let clientID, let elementCallBaseURL, let elementCallBaseURLOverride, let colorScheme, let notifyOtherParticipants):
|
||||||
// Wait for room states to be up to date before starting the call and notifying others
|
Task { [weak self] in
|
||||||
syncUpdateCancellable = clientProxy.actionsPublisher
|
guard let self else { return }
|
||||||
.filter(\.isSyncUpdate)
|
|
||||||
.timeout(.seconds(5), scheduler: DispatchQueue.main)
|
let baseURL = if let elementCallBaseURLOverride {
|
||||||
.first() // Timeout will make the publisher complete, use first to handle both branches in the same place
|
elementCallBaseURLOverride
|
||||||
.sink(receiveCompletion: { [weak self] _ in
|
} else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCall = wellKnown?.call {
|
||||||
Task { [weak self] in
|
wellKnownCall.widgetURL
|
||||||
guard let self else { return }
|
} else {
|
||||||
|
elementCallBaseURL
|
||||||
let baseURL = if let elementCallBaseURLOverride {
|
}
|
||||||
elementCallBaseURLOverride
|
|
||||||
} else if case .success(let wellKnown) = await clientProxy.getElementWellKnown(), let wellKnownCall = wellKnown?.call {
|
switch await widgetDriver.start(baseURL: baseURL, clientID: clientID, colorScheme: colorScheme) {
|
||||||
wellKnownCall.widgetURL
|
case .success(let url):
|
||||||
} else {
|
state.url = url
|
||||||
elementCallBaseURL
|
case .failure(let error):
|
||||||
}
|
MXLog.error("Failed starting ElementCall Widget Driver with error: \(error)")
|
||||||
|
state.bindings.alertInfo = .init(id: UUID(),
|
||||||
switch await widgetDriver.start(baseURL: baseURL, clientID: clientID, colorScheme: colorScheme) {
|
title: L10n.errorUnknown,
|
||||||
case .success(let url):
|
primaryButton: .init(title: L10n.actionOk) {
|
||||||
state.url = url
|
self.actionsSubject.send(.dismiss)
|
||||||
case .failure(let error):
|
})
|
||||||
MXLog.error("Failed starting ElementCall Widget Driver with error: \(error)")
|
return
|
||||||
state.bindings.alertInfo = .init(id: UUID(),
|
}
|
||||||
title: L10n.errorUnknown,
|
|
||||||
primaryButton: .init(title: L10n.actionOk) {
|
await elementCallService.setupCallSession(roomID: roomProxy.id,
|
||||||
self.actionsSubject.send(.dismiss)
|
roomDisplayName: roomProxy.infoPublisher.value.displayName ?? roomProxy.id)
|
||||||
})
|
|
||||||
|
if notifyOtherParticipants {
|
||||||
return
|
_ = await roomProxy.sendCallNotificationIfNeeded()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
await elementCallService.setupCallSession(roomID: roomProxy.id,
|
|
||||||
roomDisplayName: roomProxy.infoPublisher.value.displayName ?? roomProxy.id)
|
|
||||||
|
|
||||||
_ = await roomProxy.sendCallNotificationIfNeeded()
|
|
||||||
|
|
||||||
syncUpdateCancellable = nil
|
|
||||||
}
|
|
||||||
}, receiveValue: { _ in })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -303,7 +303,8 @@ struct CallScreen_Previews: PreviewProvider {
|
|||||||
clientID: "io.element.elementx",
|
clientID: "io.element.elementx",
|
||||||
elementCallBaseURL: "https://call.element.io",
|
elementCallBaseURL: "https://call.element.io",
|
||||||
elementCallBaseURLOverride: nil,
|
elementCallBaseURLOverride: nil,
|
||||||
colorScheme: .light),
|
colorScheme: .light,
|
||||||
|
notifyOtherParticipants: false),
|
||||||
allowPictureInPicture: false,
|
allowPictureInPicture: false,
|
||||||
appHooks: AppHooks())
|
appHooks: AppHooks())
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ struct ElementCallConfiguration {
|
|||||||
clientID: String,
|
clientID: String,
|
||||||
elementCallBaseURL: URL,
|
elementCallBaseURL: URL,
|
||||||
elementCallBaseURLOverride: URL?,
|
elementCallBaseURLOverride: URL?,
|
||||||
colorScheme: ColorScheme)
|
colorScheme: ColorScheme,
|
||||||
|
notifyOtherParticipants: Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of call being configured i.e. whether it's an external URL or an internal room call.
|
/// The type of call being configured i.e. whether it's an external URL or an internal room call.
|
||||||
@@ -58,13 +59,15 @@ struct ElementCallConfiguration {
|
|||||||
clientID: String,
|
clientID: String,
|
||||||
elementCallBaseURL: URL,
|
elementCallBaseURL: URL,
|
||||||
elementCallBaseURLOverride: URL?,
|
elementCallBaseURLOverride: URL?,
|
||||||
colorScheme: ColorScheme) {
|
colorScheme: ColorScheme,
|
||||||
|
notifyOtherParticipants: Bool) {
|
||||||
kind = .roomCall(roomProxy: roomProxy,
|
kind = .roomCall(roomProxy: roomProxy,
|
||||||
clientProxy: clientProxy,
|
clientProxy: clientProxy,
|
||||||
clientID: clientID,
|
clientID: clientID,
|
||||||
elementCallBaseURL: elementCallBaseURL,
|
elementCallBaseURL: elementCallBaseURL,
|
||||||
elementCallBaseURLOverride: elementCallBaseURLOverride,
|
elementCallBaseURLOverride: elementCallBaseURLOverride,
|
||||||
colorScheme: colorScheme)
|
colorScheme: colorScheme,
|
||||||
|
notifyOtherParticipants: notifyOtherParticipants)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A string representing the call being configured.
|
/// A string representing the call being configured.
|
||||||
@@ -72,7 +75,7 @@ struct ElementCallConfiguration {
|
|||||||
switch kind {
|
switch kind {
|
||||||
case .genericCallLink(let url):
|
case .genericCallLink(let url):
|
||||||
url.absoluteString
|
url.absoluteString
|
||||||
case .roomCall(let roomProxy, _, _, _, _, _):
|
case .roomCall(let roomProxy, _, _, _, _, _, _):
|
||||||
roomProxy.id
|
roomProxy.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user