* EC: native switch for audio outputs/inputs and earpiece also includes proximity sensor enabling when the earpiece is used. * test disabling and re-enabling audio on audio change * Revert "test disabling and re-enabling audio on audio change" This reverts commit 907c791b8df7009214f5c164ecf8fe7d90a8addc. * pr suggestions * pr suggestion and small refactor of the widgetAction handler
97 lines
3.0 KiB
Swift
97 lines
3.0 KiB
Swift
//
|
|
// Copyright 2022-2024 New Vector Ltd.
|
|
//
|
|
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
// Please see LICENSE files in the repository root for full details.
|
|
//
|
|
|
|
import AVKit
|
|
import Foundation
|
|
|
|
enum CallScreenViewModelAction {
|
|
case pictureInPictureIsAvailable(AVPictureInPictureController)
|
|
case pictureInPictureStarted
|
|
case pictureInPictureStopped
|
|
case dismiss
|
|
}
|
|
|
|
struct CallScreenViewState: BindableState {
|
|
let script: String?
|
|
var url: URL?
|
|
|
|
let certificateValidator: CertificateValidatorHookProtocol
|
|
|
|
var bindings = Bindings()
|
|
}
|
|
|
|
struct Bindings {
|
|
var javaScriptEvaluator: ((String) async throws -> Any)?
|
|
var requestPictureInPictureHandler: (() async -> Result<Void, CallScreenError>)?
|
|
|
|
var alertInfo: AlertInfo<UUID>?
|
|
}
|
|
|
|
enum CallScreenViewAction {
|
|
case urlChanged(URL?)
|
|
case pictureInPictureIsAvailable(AVPictureInPictureController)
|
|
case navigateBack
|
|
case pictureInPictureWillStop
|
|
case endCall
|
|
case mediaCapturePermissionGranted
|
|
case outputDeviceSelected(deviceID: String)
|
|
case widgetAction(message: String)
|
|
}
|
|
|
|
enum CallScreenError: Error {
|
|
case pictureInPictureNotAvailable
|
|
}
|
|
|
|
/// Identifies each event handler used by the CallScreen webview
|
|
///
|
|
/// The names of the enum need to always match the name of the handlers on the webview.
|
|
enum CallScreenJavaScriptMessageName: String, CaseIterable {
|
|
/// Widget actions's handler.
|
|
case widgetAction
|
|
/// Used to show the native AVRoutePickerView.
|
|
case showNativeOutputDevicePicker
|
|
/// Used to determine if the webview has selected the earpiece or not.
|
|
case onOutputDeviceSelect
|
|
|
|
private var postMessageScript: String {
|
|
switch self {
|
|
case .widgetAction:
|
|
"""
|
|
window.addEventListener(
|
|
"message",
|
|
(event) => {
|
|
let message = {data: event.data, origin: event.origin};
|
|
if (message.data.response && message.data.api == "toWidget"
|
|
|| !message.data.response && message.data.api == "fromWidget") {
|
|
window.webkit.messageHandlers.\(rawValue).postMessage(JSON.stringify(message.data));
|
|
} else {
|
|
console.log("-- skipped event handling by the client because it is send from the client itself.");
|
|
}
|
|
},
|
|
false,
|
|
);
|
|
"""
|
|
case .showNativeOutputDevicePicker:
|
|
"""
|
|
window.controls.\(rawValue) = () => {
|
|
window.webkit.messageHandlers.\(rawValue).postMessage("");
|
|
};
|
|
"""
|
|
case .onOutputDeviceSelect:
|
|
"""
|
|
window.controls.\(rawValue) = (id) => {
|
|
window.webkit.messageHandlers.\(rawValue).postMessage(id);
|
|
};
|
|
"""
|
|
}
|
|
}
|
|
|
|
static var allCasesInjectionScript: String {
|
|
allCases.map(\.postMessageScript).joined(separator: "\n")
|
|
}
|
|
}
|