diff --git a/packages/hms_room_kit/lib/src/widgets/bottom_sheets/local_peer_bottom_sheet.dart b/packages/hms_room_kit/lib/src/widgets/bottom_sheets/local_peer_bottom_sheet.dart index 3095335f3..25a14fb38 100644 --- a/packages/hms_room_kit/lib/src/widgets/bottom_sheets/local_peer_bottom_sheet.dart +++ b/packages/hms_room_kit/lib/src/widgets/bottom_sheets/local_peer_bottom_sheet.dart @@ -4,6 +4,7 @@ library; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:hms_room_kit/src/widgets/common_widgets/hms_cross_button.dart'; +import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:provider/provider.dart'; ///Project imports @@ -51,7 +52,7 @@ class _LocalPeerBottomSheetState extends State { @override Widget build(BuildContext context) { return FractionallySizedBox( - heightFactor: widget.isInsetTile ? 0.26 : 0.2, + heightFactor: widget.isInsetTile ? 0.46 : 0.4, child: Padding( padding: const EdgeInsets.only(top: 16.0, left: 24, right: 24), child: Column( @@ -228,6 +229,44 @@ class _LocalPeerBottomSheetState extends State { widget.meetingStore.peerTracks.length > 1 ? HMSThemeColors.onSurfaceHighEmphasis : HMSThemeColors.onSurfaceLowEmphasis)), + ListTile( + horizontalTitleGap: 2, + onTap: () async { + Navigator.pop(context); + HMSCameraControls.setZoom(zoomValue: 2); + }, + contentPadding: EdgeInsets.zero, + leading: SvgPicture.asset( + "packages/hms_room_kit/lib/src/assets/icons/maximize.svg", + semanticsLabel: "fl_local_pin_tile", + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + HMSThemeColors.onSurfaceHighEmphasis, + BlendMode.srcIn), + ), + title: HMSSubheadingText( + text: "Zoom In (2x)", + textColor: HMSThemeColors.onSurfaceHighEmphasis)), + ListTile( + horizontalTitleGap: 2, + onTap: () async { + Navigator.pop(context); + HMSCameraControls.resetZoom(); + }, + contentPadding: EdgeInsets.zero, + leading: SvgPicture.asset( + "packages/hms_room_kit/lib/src/assets/icons/minimize.svg", + semanticsLabel: "fl_local_pin_tile", + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + HMSThemeColors.onSurfaceHighEmphasis, + BlendMode.srcIn), + ), + title: HMSSubheadingText( + text: "Reset zoom", + textColor: HMSThemeColors.onSurfaceHighEmphasis)), ], ), ), diff --git a/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/methods/HMSCameraControlsAction.kt b/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/methods/HMSCameraControlsAction.kt index 387fd8ec0..957094dba 100644 --- a/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/methods/HMSCameraControlsAction.kt +++ b/packages/hmssdk_flutter/android/src/main/kotlin/live/hms/hmssdk_flutter/methods/HMSCameraControlsAction.kt @@ -216,14 +216,13 @@ class HMSCameraControlsAction { result: Result, hmssdk: HMSSDK ){ - val zoomValue = call.argument("zoom_value") + val zoomValue = call.argument("zoom_value") zoomValue?.let { _zoomValue -> hmssdk.getLocalPeer()?.let { localPeer -> localPeer.videoTrack?.let { localVideoTrack -> - localVideoTrack.getCameraControl()?.setZoom(_zoomValue) ?: run { - result.success(HMSResultExtension.toDictionary(false, HMSExceptionExtension.getError("cameraControl is null"))) - return - } + localVideoTrack.getCameraControl()?.setZoom( + _zoomValue.toFloat() + ) } ?: run { result.success(HMSResultExtension.toDictionary(false, HMSExceptionExtension.getError("local video track is null"))) return @@ -232,6 +231,9 @@ class HMSCameraControlsAction { result.success(HMSResultExtension.toDictionary(false, HMSExceptionExtension.getError("local peer is null"))) return } + }?:run{ + HMSErrorLogger.returnArgumentsError("zoom value parameter is null in setZoom method") + return } } @@ -241,10 +243,7 @@ class HMSCameraControlsAction { ){ hmssdk.getLocalPeer()?.let { localPeer -> localPeer.videoTrack?.let { localVideoTrack -> - localVideoTrack.getCameraControl()?.let { cameraControl -> - result.success(HMSResultExtension.toDictionary(true, cameraControl.resetZoom())) - return - } ?: run { + localVideoTrack.getCameraControl()?.resetZoom() ?: run { result.success(HMSResultExtension.toDictionary(false, HMSExceptionExtension.getError("cameraControl is null"))) return } diff --git a/packages/hmssdk_flutter/example/ios/Podfile.lock b/packages/hmssdk_flutter/example/ios/Podfile.lock index 56ece5a0b..c7f975b7c 100644 --- a/packages/hmssdk_flutter/example/ios/Podfile.lock +++ b/packages/hmssdk_flutter/example/ios/Podfile.lock @@ -303,7 +303,7 @@ SPEC CHECKSUMS: FirebaseRemoteConfigInterop: 6efda51fb5e2f15b16585197e26eaa09574e8a4d FirebaseSessions: dbd14adac65ce996228652c1fc3a3f576bdf3ecc FirebaseSharedSwift: 20530f495084b8d840f78a100d8c5ee613375f6e - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_foreground_task: 21ef182ab0a29a3005cc72cd70e5f45cb7f7f817 GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleMLKit: 2bd0dc6253c4d4f227aad460f69215a504b2980e diff --git a/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/project.pbxproj b/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/project.pbxproj index fc0c44fb7..37fb2667c 100644 --- a/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -248,7 +248,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1340; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = 100ms; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a6b826db2..5e31d3d34 100644 --- a/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/hmssdk_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ =3.1.0 <4.0.0" - flutter: ">=3.13.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/packages/hmssdk_flutter/ios/Classes/Actions/HMSCameraControlsAction.swift b/packages/hmssdk_flutter/ios/Classes/Actions/HMSCameraControlsAction.swift index 3d8c2b185..e519c3e23 100644 --- a/packages/hmssdk_flutter/ios/Classes/Actions/HMSCameraControlsAction.swift +++ b/packages/hmssdk_flutter/ios/Classes/Actions/HMSCameraControlsAction.swift @@ -32,9 +32,15 @@ class HMSCameraControlsAction { case "toggle_flash": toggleFlash(result, hmsSDK) + + case "set_zoom": + setZoom(call, result, hmsSDK) + + case "reset_zoom": + resetZoom(result, hmsSDK) // these method calls return FlutterMethodNotImplemented to indicate that the requested functionality is not yet implemented. - case "is_tap_to_focus_supported", "is_zoom_supported": + case "is_tap_to_focus_supported", "is_zoom_supported", "get_max_zoom", "get_min_zoom": result(FlutterMethodNotImplemented) // If the method call does not match any of the above cases, also return FlutterMethodNotImplemented. @@ -170,4 +176,51 @@ class HMSCameraControlsAction { formatter.timeStyle = .medium return formatter.string(from: Date()) } + + static private func setZoom(_ call: FlutterMethodCall, _ result: @escaping FlutterResult, _ hmsSDK: HMSSDK?){ + guard let localPeer = hmsSDK?.localPeer else { + result(HMSResultExtension.toDictionary(false, HMSErrorExtension.getError("\(#function) An instance of Local Peer could not be found. Please check if a Room is joined."))) + return + } + + guard let localVideoTrack = localPeer.localVideoTrack() + else { + result(HMSResultExtension.toDictionary(false, HMSErrorExtension.getError("\(#function) Video Track of Local Peer could not be found. Please check if the Local Peer has permission to publish video & video is unmuted currently."))) + return + } + + let arguments = call.arguments as? [AnyHashable: Any] + + guard let zoomValue = arguments?["zoom_value"] as? CGFloat + else{ + HMSErrorLogger.returnArgumentsError("zoom value can't be empty") + return + } + + localVideoTrack.modifyCaptureDevice { device in + + guard let device = device else { return } + + device.videoZoomFactor = zoomValue + } + } + + static private func resetZoom(_ result: @escaping FlutterResult, _ hmsSDK: HMSSDK?){ + guard let localPeer = hmsSDK?.localPeer else { + result(HMSResultExtension.toDictionary(false, HMSErrorExtension.getError("\(#function) An instance of Local Peer could not be found. Please check if a Room is joined."))) + return + } + + guard let localVideoTrack = localPeer.localVideoTrack() + else { + result(HMSResultExtension.toDictionary(false, HMSErrorExtension.getError("\(#function) Video Track of Local Peer could not be found. Please check if the Local Peer has permission to publish video & video is unmuted currently."))) + return + } + + localVideoTrack.modifyCaptureDevice { device in + + guard let device = device else { return } + device.videoZoomFactor = 1.0 + } + } } diff --git a/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift b/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift index 9d56521d1..9db792145 100644 --- a/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift +++ b/packages/hmssdk_flutter/ios/Classes/SwiftHmssdkFlutterPlugin.swift @@ -315,7 +315,7 @@ public class SwiftHmssdkFlutterPlugin: NSObject, FlutterPlugin, HMSUpdateListene // MARK: - Advanced Camera Controls - case "capture_image_at_max_supported_resolution", "is_tap_to_focus_supported", "is_zoom_supported", "is_flash_supported", "toggle_flash": + case "capture_image_at_max_supported_resolution", "is_tap_to_focus_supported", "is_zoom_supported", "is_flash_supported", "toggle_flash", "set_zoom", "reset_zoom", "get_max_zoom", "get_min_zoom": HMSCameraControlsAction.cameraControlsAction(call, result, hmsSDK) // MARK: - Session Store diff --git a/packages/hmssdk_flutter/lib/src/model/hms_camera_controls.dart b/packages/hmssdk_flutter/lib/src/model/hms_camera_controls.dart index 75b8eb8d0..c1c439ef7 100644 --- a/packages/hmssdk_flutter/lib/src/model/hms_camera_controls.dart +++ b/packages/hmssdk_flutter/lib/src/model/hms_camera_controls.dart @@ -1,3 +1,6 @@ +import 'dart:developer'; +import 'dart:io'; + import 'package:hmssdk_flutter/src/common/platform_methods.dart'; import 'package:hmssdk_flutter/src/exceptions/hms_exception.dart'; import 'package:hmssdk_flutter/src/service/platform_service.dart'; @@ -63,17 +66,24 @@ class HMSCameraControls { } static Future isZoomSupported() async { - var result = - await PlatformService.invokeMethod(PlatformMethod.isZoomSupported); - if (result["success"]) { - return result["data"]; + if (Platform.isAndroid) { + var result = + await PlatformService.invokeMethod(PlatformMethod.isZoomSupported); + if (result["success"]) { + return result["data"]; + } else { + return false; + } } else { - return false; + return true; } } - static Future setZoom() async { - var result = await PlatformService.invokeMethod(PlatformMethod.setZoom); + static Future setZoom({required double zoomValue}) async { + var result = + await PlatformService.invokeMethod(PlatformMethod.setZoom, arguments: { + "zoom_value": zoomValue, + }); if (result["success"]) { return result["data"]; } else { @@ -91,20 +101,30 @@ class HMSCameraControls { } static Future getMinZoom() async { - var result = await PlatformService.invokeMethod(PlatformMethod.getMinZoom); - if (result["success"]) { - return result["data"]; + if (Platform.isAndroid) { + var result = + await PlatformService.invokeMethod(PlatformMethod.getMinZoom); + if (result["success"]) { + return result["data"]; + } else { + return HMSException.fromMap(result["data"]["error"]); + } } else { - return HMSException.fromMap(result["data"]["error"]); + log("getMinZoom is only available on android"); } } static Future getMaxZoom() async { - var result = await PlatformService.invokeMethod(PlatformMethod.getMaxZoom); - if (result["success"]) { - return result["data"]; + if (Platform.isAndroid) { + var result = + await PlatformService.invokeMethod(PlatformMethod.getMaxZoom); + if (result["success"]) { + return result["data"]; + } else { + return HMSException.fromMap(result["data"]["error"]); + } } else { - return HMSException.fromMap(result["data"]["error"]); + log("getMaxZoom is only available on android"); } } }