diff --git a/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift b/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift index b7247e83e..c54f20898 100644 --- a/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift +++ b/ElementX/Sources/Application/Windowing/WindowManagerProtocol.swift @@ -11,6 +11,7 @@ import SwiftUI enum SecondaryWindowType: Hashable, Codable { case room(roomID: String) case settings + case call } protocol SecureWindowManagerDelegate: AnyObject { diff --git a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift index 877086a68..c2f8e82c0 100644 --- a/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/RoomFlowCoordinator.swift @@ -940,6 +940,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol { private func presentRoomDetails(isRoot: Bool, animated: Bool) async { let params = RoomDetailsScreenCoordinatorParameters(roomProxy: roomProxy, userSession: userSession, + appSettings: flowParameters.appSettings, appHooks: flowParameters.appHooks, analyticsService: flowParameters.analytics, userIndicatorController: flowParameters.userIndicatorController, diff --git a/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift index fe0326329..83a60f9b8 100644 --- a/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/SpaceSettingsFlowCoordinator.swift @@ -211,6 +211,7 @@ final class SpaceSettingsFlowCoordinator: FlowCoordinatorProtocol { private func presentSpaceSettings(animated: Bool) { let coordinator = RoomDetailsScreenCoordinator(parameters: .init(roomProxy: roomProxy, userSession: flowParameters.userSession, + appSettings: flowParameters.appSettings, appHooks: flowParameters.appHooks, analyticsService: flowParameters.analytics, userIndicatorController: flowParameters.userIndicatorController, diff --git a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift index 0d9d54da0..168f57941 100644 --- a/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift +++ b/ElementX/Sources/FlowCoordinators/UserSessionFlowCoordinator.swift @@ -578,8 +578,13 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } let coordinator = NativeCallScreenCoordinator(parameters: .init(controller: controller)) - navigationTabCoordinator.setOverlayCoordinator(coordinator, animated: true) - flowParameters.analytics.track(screen: .RoomCall) + + if ProcessInfo.processInfo.isiOSAppOnMac { + flowParameters.appMediator.windowManager.registerCoordinator(coordinator, flowCoordinator: nil, forWindowType: .call) + } else { + navigationTabCoordinator.setOverlayCoordinator(coordinator, animated: true) + flowParameters.analytics.track(screen: .RoomCall) + } } private func restoreNativeCallScreen() { @@ -588,12 +593,16 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol { } private func dismissCallScreenIfNeeded() { - guard navigationTabCoordinator.overlayCoordinator is CallScreenCoordinator - || navigationTabCoordinator.overlayCoordinator is NativeCallScreenCoordinator else { - return + if ProcessInfo.processInfo.isiOSAppOnMac { + flowParameters.appMediator.windowManager.closeSecondaryWindow(forType: .call) + } else { + guard navigationTabCoordinator.overlayCoordinator is CallScreenCoordinator + || navigationTabCoordinator.overlayCoordinator is NativeCallScreenCoordinator else { + return + } + + navigationTabCoordinator.setOverlayCoordinator(nil) } - - navigationTabCoordinator.setOverlayCoordinator(nil) } // MARK: - Logout diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift index 16774e69e..5b289b858 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenCoordinator.swift @@ -12,6 +12,7 @@ import SwiftUI struct RoomDetailsScreenCoordinatorParameters { let roomProxy: JoinedRoomProxyProtocol let userSession: UserSessionProtocol + let appSettings: AppSettings let appHooks: AppHooks let analyticsService: AnalyticsServiceProtocol let userIndicatorController: UserIndicatorControllerProtocol @@ -53,6 +54,7 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol { isSpace = parameters.roomProxy.infoPublisher.value.isSpace viewModel = RoomDetailsScreenViewModel(roomProxy: parameters.roomProxy, userSession: parameters.userSession, + appSettings: parameters.appSettings, appHooks: parameters.appHooks, analyticsService: parameters.analyticsService, userIndicatorController: parameters.userIndicatorController, diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift index a89dcd041..e77b52b88 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenModels.swift @@ -63,6 +63,7 @@ struct RoomDetailsScreenViewState: BindableState { var canBanUsers = false var notificationSettingsState: RoomDetailsNotificationSettingsState = .loading var isCallingEnabled = true + var isNativeCallingEnabled = false var canJoinCall = false var pinnedEventsActionState = RoomDetailsScreenPinnedEventsActionState.loading @@ -94,7 +95,7 @@ struct RoomDetailsScreenViewState: BindableState { var shortcuts: [RoomDetailsScreenViewShortcut] { var shortcuts: [RoomDetailsScreenViewShortcut] = [.mute] - if !ProcessInfo.processInfo.isiOSAppOnMac, isCallingEnabled, canJoinCall { + if !ProcessInfo.processInfo.isiOSAppOnMac || isNativeCallingEnabled, isCallingEnabled, canJoinCall { if isDirect { shortcuts.append(.voiceCall) } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift index e86a1e08f..5ade0c174 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/RoomDetailsScreenViewModel.swift @@ -45,6 +45,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr init(roomProxy: JoinedRoomProxyProtocol, userSession: UserSessionProtocol, + appSettings: AppSettings, appHooks: AppHooks, analyticsService: AnalyticsServiceProtocol, userIndicatorController: UserIndicatorControllerProtocol, @@ -66,6 +67,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr topicSummary: topic?.unattributedStringByReplacingNewlinesWithSpaces(), joinedMembersCount: roomProxy.infoPublisher.value.joinedMembersCount, notificationSettingsState: .loading, + isNativeCallingEnabled: appSettings.nativeCallEnabled, bindings: .init()) super.init(initialViewState: appHooks.roomDetailsScreenHook.update(viewState), mediaProvider: userSession.mediaProvider) diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index ec8529e8e..0eabffbb1 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -441,6 +441,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { return .init(roomProxy: roomProxy, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -469,6 +470,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { return .init(roomProxy: roomProxy, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -507,6 +509,7 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview { return .init(roomProxy: roomProxy, userSession: UserSessionMock(.init(clientProxy: clientProxyMock)), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift index 71e67b4a3..4cb401d63 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenModels.swift @@ -57,6 +57,8 @@ struct RoomScreenViewState: BindableState { /// Whether or not starting a call is supported. var isCallingEnabled = true + /// Whether or not calls are using the experimental native implementation. + var isNativeCallingEnabled = false /// Whether or not the user is allowed to join calls in this room. var canJoinCall = false /// Whether or not this room currently has a call in progress. diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index 539eb609d..7462844f3 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -69,6 +69,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol let viewState = RoomScreenViewState(roomTitle: roomProxy.infoPublisher.value.displayNameOrID, roomAvatar: roomProxy.infoPublisher.value.avatar, + isNativeCallingEnabled: appSettings.nativeCallEnabled, hasOngoingCall: roomProxy.infoPublisher.value.hasRoomCall, isDM: roomProxy.infoPublisher.value.isDM, hasSuccessor: roomProxy.infoPublisher.value.successor != nil, diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 8c2671c0b..395bd2d47 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -316,7 +316,7 @@ struct RoomScreen: View { } } - if !ProcessInfo.processInfo.isiOSAppOnMac { + if !ProcessInfo.processInfo.isiOSAppOnMac || context.viewState.isNativeCallingEnabled { if context.viewState.shouldShowCallButton { RoomCallControlsToolbar(viewState: context.viewState) { isVoiceCall in context.send(viewAction: .displayCall(isVoiceCall: isVoiceCall)) diff --git a/ElementX/Sources/Screens/Spaces/SpaceSettingsScreen/View/SpaceSettingsScreen.swift b/ElementX/Sources/Screens/Spaces/SpaceSettingsScreen/View/SpaceSettingsScreen.swift index 0a864ab1d..000ba732e 100644 --- a/ElementX/Sources/Screens/Spaces/SpaceSettingsScreen/View/SpaceSettingsScreen.swift +++ b/ElementX/Sources/Screens/Spaces/SpaceSettingsScreen/View/SpaceSettingsScreen.swift @@ -132,6 +132,7 @@ struct SpaceSettingsScreen_Previews: PreviewProvider, TestablePreview { canonicalAlias: "#space:matrix.org", members: members)), userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), diff --git a/Enterprise b/Enterprise index be536ca83..0c0c2f79f 160000 --- a/Enterprise +++ b/Enterprise @@ -1 +1 @@ -Subproject commit be536ca83c346e7b24545b225ddbadd7f7a4f2fc +Subproject commit 0c0c2f79f1f7bd9dcee0cad156a5518ef5ad482d diff --git a/UnitTests/Sources/RoomDetailsScreenViewModelTests.swift b/UnitTests/Sources/RoomDetailsScreenViewModelTests.swift index 9ebbfeb77..30df628bc 100644 --- a/UnitTests/Sources/RoomDetailsScreenViewModelTests.swift +++ b/UnitTests/Sources/RoomDetailsScreenViewModelTests.swift @@ -30,6 +30,7 @@ struct RoomDetailsScreenViewModelTests { notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration()) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -43,6 +44,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -63,6 +65,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -84,6 +87,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -142,6 +146,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -163,6 +168,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -195,6 +201,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init(clientProxy: clientProxy)), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -226,6 +233,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -258,6 +266,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, isEncrypted: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init(clientProxy: clientProxy)), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -291,6 +300,7 @@ struct RoomDetailsScreenViewModelTests { powerLevelsConfiguration: .init(canUserInvite: false))) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -308,6 +318,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", members: mockedMembers, joinRule: .public)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -356,6 +367,7 @@ struct RoomDetailsScreenViewModelTests { viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -391,6 +403,7 @@ struct RoomDetailsScreenViewModelTests { viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -426,6 +439,7 @@ struct RoomDetailsScreenViewModelTests { viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -446,6 +460,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -466,6 +481,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -484,6 +500,7 @@ struct RoomDetailsScreenViewModelTests { notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(msg: "error") viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -692,6 +709,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -713,6 +731,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: false, knockRequestsState: .loading, joinRule: .knock)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -736,6 +755,7 @@ struct RoomDetailsScreenViewModelTests { powerLevelsConfiguration: .init(canUserInvite: false))) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -759,6 +779,7 @@ struct RoomDetailsScreenViewModelTests { roomProxyMock = JoinedRoomProxyMock(.init(name: "Test", isDirect: true, members: mockedMembers, knockRequestsState: .loaded(mockedRequests), joinRule: .knock)) viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(), @@ -786,6 +807,7 @@ struct RoomDetailsScreenViewModelTests { viewModel = RoomDetailsScreenViewModel(roomProxy: roomProxyMock, userSession: UserSessionMock(.init()), + appSettings: AppSettings.volatile(), appHooks: AppHooks(), analyticsService: AnalyticsServiceMock(.init()), userIndicatorController: UserIndicatorControllerMock(),