|
1 | 1 | import Cocoa |
2 | 2 | import FlutterMacOS |
3 | | -import WebKit |
| 3 | +@preconcurrency import WebKit |
4 | 4 | import SwiftUI |
5 | 5 | import UserNotifications |
6 | 6 | import AVFoundation |
@@ -663,7 +663,7 @@ public class TwilioVoicePlugin: NSObject, FlutterPlugin, FlutterStreamHandler, T |
663 | 663 |
|
664 | 664 | // TODO: toggle bluetooth |
665 | 665 | // toggleAudioRoute(toSpeaker: speakerIsOn) |
666 | | - guard let eventSink = eventSink else { |
| 666 | + guard eventSink != nil else { |
667 | 667 | return |
668 | 668 | } |
669 | 669 | logEvent(description: bluetoothOn ? "Bluetooth On" : "Bluetooth Off") |
@@ -1142,9 +1142,9 @@ public class TwilioVoicePlugin: NSObject, FlutterPlugin, FlutterStreamHandler, T |
1142 | 1142 | if let category = NotificationCategory(rawValue: notification.request.content.categoryIdentifier) { |
1143 | 1143 | switch category { |
1144 | 1144 | case .incoming: |
1145 | | - completionHandler([.alert, .banner, .sound]) |
| 1145 | + completionHandler([.banner, .sound]) |
1146 | 1146 | case .missed: |
1147 | | - completionHandler([.alert, .banner, .sound]) |
| 1147 | + completionHandler([.banner, .sound]) |
1148 | 1148 | // default: |
1149 | 1149 | // completionHandler([]) |
1150 | 1150 | } |
@@ -1436,8 +1436,34 @@ public class TwilioVoicePlugin: NSObject, FlutterPlugin, FlutterStreamHandler, T |
1436 | 1436 | } |
1437 | 1437 |
|
1438 | 1438 | @available(macOS 12.0, *) |
1439 | | - public func webView(_ webView: WKWebView, decideMediaCapturePermissionsFor origin: WKSecurityOrigin, initiatedBy frame: WKFrameInfo, type: WKMediaCaptureType) async -> WKPermissionDecision { |
1440 | | - WKPermissionDecision.grant |
| 1439 | + public func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping @MainActor (WKPermissionDecision) -> Void) { |
| 1440 | + switch type { |
| 1441 | + case .microphone: |
| 1442 | + // For microphone access, we'll check the current permission status |
| 1443 | + switch AVCaptureDevice.authorizationStatus(for: .audio) { |
| 1444 | + case .authorized: |
| 1445 | + decisionHandler(.grant) |
| 1446 | + case .notDetermined: |
| 1447 | + // Request permission and handle the result |
| 1448 | + AVCaptureDevice.requestAccess(for: .audio) { granted in |
| 1449 | + Task { @MainActor in |
| 1450 | + decisionHandler(granted ? .grant : .deny) |
| 1451 | + } |
| 1452 | + } |
| 1453 | + case .denied, .restricted: |
| 1454 | + decisionHandler(.deny) |
| 1455 | + @unknown default: |
| 1456 | + decisionHandler(.deny) |
| 1457 | + } |
| 1458 | + case .camera: |
| 1459 | + // We don't need camera access for Twilio Voice |
| 1460 | + decisionHandler(.deny) |
| 1461 | + case .cameraAndMicrophone: |
| 1462 | + // We don't need camera and microphone access for Twilio Voice |
| 1463 | + decisionHandler(.deny) |
| 1464 | + @unknown default: |
| 1465 | + decisionHandler(.deny) |
| 1466 | + } |
1441 | 1467 | } |
1442 | 1468 | } |
1443 | 1469 |
|
|
0 commit comments