🐛 Bug fixes on macos
This commit is contained in:
		| @@ -78,6 +78,14 @@ | |||||||
|   "chatCall": "Call", |   "chatCall": "Call", | ||||||
|   "chatCallOngoing": "A call is ongoing", |   "chatCallOngoing": "A call is ongoing", | ||||||
|   "chatCallJoin": "Join", |   "chatCallJoin": "Join", | ||||||
|  |   "chatCallMute": "Mute", | ||||||
|  |   "chatCallUnMute": "Un-mute", | ||||||
|  |   "chatCallVideoOff": "Turn Off Video", | ||||||
|  |   "chatCallVideoOn": "Turn On Video", | ||||||
|  |   "chatCallVideoFlip": "Flip Camera", | ||||||
|  |   "chatCallScreenOn": "Start Screen Share", | ||||||
|  |   "chatCallScreenOff": "Stop Screen Share", | ||||||
|  |   "chatCallChangeSpeaker": "Change Speaker", | ||||||
|   "chatMessagePlaceholder": "Write a message...", |   "chatMessagePlaceholder": "Write a message...", | ||||||
|   "chatMessageEditNotify": "You are about editing a message.", |   "chatMessageEditNotify": "You are about editing a message.", | ||||||
|   "chatMessageReplyNotify": "You are about replying a message.", |   "chatMessageReplyNotify": "You are about replying a message.", | ||||||
|   | |||||||
| @@ -76,6 +76,14 @@ | |||||||
|   "chatChannelLeaveConfirm": "你确定你要离开这个频道吗?你在这个频道里的消息将被存储下来,但是当你重新加入本频道后你将会失去对你之前消息的权限。", |   "chatChannelLeaveConfirm": "你确定你要离开这个频道吗?你在这个频道里的消息将被存储下来,但是当你重新加入本频道后你将会失去对你之前消息的权限。", | ||||||
|   "chatChannelDeleteConfirm": "你确定你要删除这个频道吗?这个频道里的所有消息都将消失,并且不可被反转!", |   "chatChannelDeleteConfirm": "你确定你要删除这个频道吗?这个频道里的所有消息都将消失,并且不可被反转!", | ||||||
|   "chatCall": "通话", |   "chatCall": "通话", | ||||||
|  |   "chatCallMute": "静音", | ||||||
|  |   "chatCallUnMute": "取消静音", | ||||||
|  |   "chatCallVideoOff": "关闭摄像头", | ||||||
|  |   "chatCallVideoOn": "启动摄像头", | ||||||
|  |   "chatCallVideoFlip": "翻转视频输出", | ||||||
|  |   "chatCallScreenOn": "开启屏幕分享", | ||||||
|  |   "chatCallScreenOff": "停止屏幕分享", | ||||||
|  |   "chatCallChangeSpeaker": "切换扬声器", | ||||||
|   "chatCallOngoing": "一则通话正在进行中", |   "chatCallOngoing": "一则通话正在进行中", | ||||||
|   "chatCallJoin": "加入", |   "chatCallJoin": "加入", | ||||||
|   "chatMessagePlaceholder": "发条消息……", |   "chatMessagePlaceholder": "发条消息……", | ||||||
|   | |||||||
| @@ -12,6 +12,8 @@ import 'package:solian/utils/video_player.dart'; | |||||||
| import 'package:solian/widgets/notification_notifier.dart'; | import 'package:solian/widgets/notification_notifier.dart'; | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
|  |   WidgetsFlutterBinding.ensureInitialized(); | ||||||
|  |  | ||||||
|   initVideo(); |   initVideo(); | ||||||
|   initTimeAgo(); |   initTimeAgo(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ import 'package:solian/widgets/chat/call/participant.dart'; | |||||||
| import 'package:solian/widgets/indent_wrapper.dart'; | import 'package:solian/widgets/indent_wrapper.dart'; | ||||||
| import 'package:permission_handler/permission_handler.dart'; | import 'package:permission_handler/permission_handler.dart'; | ||||||
| import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  | import 'package:wakelock_plus/wakelock_plus.dart'; | ||||||
| import 'dart:math' as math; | import 'dart:math' as math; | ||||||
|  |  | ||||||
| import '../../widgets/chat/call/controls.dart'; | import '../../widgets/chat/call/controls.dart'; | ||||||
| @@ -50,9 +51,8 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|  |  | ||||||
|   List<ParticipantTrack> _participantTracks = []; |   List<ParticipantTrack> _participantTracks = []; | ||||||
|  |  | ||||||
|   bool get _fastConnection => _callRoom.engine.fastConnectOptions != null; |  | ||||||
|  |  | ||||||
|   Future<void> checkPermissions() async { |   Future<void> checkPermissions() async { | ||||||
|  |     if (lkPlatformIs(PlatformType.macOS) || lkPlatformIs(PlatformType.linux)) return; | ||||||
|     await Permission.camera.request(); |     await Permission.camera.request(); | ||||||
|     await Permission.microphone.request(); |     await Permission.microphone.request(); | ||||||
|     await Permission.bluetooth.request(); |     await Permission.bluetooth.request(); | ||||||
| @@ -87,7 +87,7 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void joinRoom(String url, String token) async { |   void joinRoom(String url, String token) async { | ||||||
|     if(_isMounted) { |     if (_isMounted) { | ||||||
|       return; |       return; | ||||||
|     } else { |     } else { | ||||||
|       _isMounted = true; |       _isMounted = true; | ||||||
| @@ -145,16 +145,14 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void askPublish() async { |   void autoPublish() async { | ||||||
|     final result = await context.showPublishDialog(); |  | ||||||
|     if (result != true) return; |  | ||||||
|     try { |     try { | ||||||
|       await _callRoom.localParticipant?.setCameraEnabled(true); |       if (_enableVideo) await _callRoom.localParticipant?.setCameraEnabled(true); | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|       await context.showErrorDialog(error); |       await context.showErrorDialog(error); | ||||||
|     } |     } | ||||||
|     try { |     try { | ||||||
|       await _callRoom.localParticipant?.setMicrophoneEnabled(true); |       if (_enableAudio) await _callRoom.localParticipant?.setMicrophoneEnabled(true); | ||||||
|     } catch (error) { |     } catch (error) { | ||||||
|       await context.showErrorDialog(error); |       await context.showErrorDialog(error); | ||||||
|     } |     } | ||||||
| @@ -164,11 +162,7 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|     _callRoom.addListener(onRoomDidUpdate); |     _callRoom.addListener(onRoomDidUpdate); | ||||||
|     setupRoomListeners(); |     setupRoomListeners(); | ||||||
|     sortParticipants(); |     sortParticipants(); | ||||||
|     WidgetsBindingCompatible.instance?.addPostFrameCallback((_) { |     WidgetsBindingCompatible.instance?.addPostFrameCallback((_) => autoPublish()); | ||||||
|       if (!_fastConnection) { |  | ||||||
|         askPublish(); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     if (lkPlatformIsMobile()) { |     if (lkPlatformIsMobile()) { | ||||||
|       Hardware.instance.setSpeakerphoneOn(true); |       Hardware.instance.setSpeakerphoneOn(true); | ||||||
| @@ -362,6 +356,7 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|     _callRoom = Room(); |     _callRoom = Room(); | ||||||
|     _callListener = _callRoom.createListener(); |     _callListener = _callRoom.createListener(); | ||||||
|     Hardware.instance.enumerateDevices().then(revertDevices); |     Hardware.instance.enumerateDevices().then(revertDevices); | ||||||
|  |     WakelockPlus.enable(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -425,6 +420,7 @@ class _ChatCallState extends State<ChatCall> { | |||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void dispose() { |   void dispose() { | ||||||
|  |     WakelockPlus.disable(); | ||||||
|     (() async { |     (() async { | ||||||
|       _callRoom.removeListener(onRoomDidUpdate); |       _callRoom.removeListener(onRoomDidUpdate); | ||||||
|       await _callRoom.disconnect(); |       await _callRoom.disconnect(); | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; | |||||||
| import 'package:flutter_background/flutter_background.dart'; | import 'package:flutter_background/flutter_background.dart'; | ||||||
| import 'package:flutter_webrtc/flutter_webrtc.dart'; | import 'package:flutter_webrtc/flutter_webrtc.dart'; | ||||||
| import 'package:livekit_client/livekit_client.dart'; | import 'package:livekit_client/livekit_client.dart'; | ||||||
| import 'package:solian/widgets/chat/call/exts.dart'; | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | ||||||
|  |  | ||||||
| class ControlsWidget extends StatefulWidget { | class ControlsWidget extends StatefulWidget { | ||||||
|   final Room room; |   final Room room; | ||||||
| @@ -61,11 +61,6 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|  |  | ||||||
|   void onChange() => setState(() {}); |   void onChange() => setState(() {}); | ||||||
|  |  | ||||||
|   void unpublishAll() async { |  | ||||||
|     final result = await context.showUnPublishDialog(); |  | ||||||
|     if (result == true) await participant.unpublishAllTracks(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   bool get isMuted => participant.isMuted; |   bool get isMuted => participant.isMuted; | ||||||
|  |  | ||||||
|   void disableAudio() async { |   void disableAudio() async { | ||||||
| @@ -106,7 +101,6 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void toggleCamera() async { |   void toggleCamera() async { | ||||||
|     // |  | ||||||
|     final track = participant.videoTrackPublications.firstOrNull?.track; |     final track = participant.videoTrackPublications.firstOrNull?.track; | ||||||
|     if (track == null) return; |     if (track == null) return; | ||||||
|  |  | ||||||
| @@ -202,22 +196,6 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void onTapUpdateSubscribePermission() async { |  | ||||||
|     final result = await context.showSubscribePermissionDialog(); |  | ||||||
|     if (result != null) { |  | ||||||
|       try { |  | ||||||
|         widget.room.localParticipant?.setTrackSubscriptionPermissions( |  | ||||||
|           allParticipantsAllowed: result, |  | ||||||
|         ); |  | ||||||
|       } catch (e) { |  | ||||||
|         final message = e.toString(); |  | ||||||
|         ScaffoldMessenger.of(context).showSnackBar(SnackBar( |  | ||||||
|           content: Text('Something went wrong... $message'), |  | ||||||
|         )); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return Padding( |     return Padding( | ||||||
| @@ -230,17 +208,12 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|         spacing: 5, |         spacing: 5, | ||||||
|         runSpacing: 5, |         runSpacing: 5, | ||||||
|         children: [ |         children: [ | ||||||
|           IconButton( |  | ||||||
|             onPressed: unpublishAll, |  | ||||||
|             icon: const Icon(Icons.cancel), |  | ||||||
|             tooltip: 'Unpublish all', |  | ||||||
|           ), |  | ||||||
|           if (participant.isMicrophoneEnabled()) |           if (participant.isMicrophoneEnabled()) | ||||||
|             if (lkPlatformIs(PlatformType.android)) |             if (lkPlatformIs(PlatformType.android)) | ||||||
|               IconButton( |               IconButton( | ||||||
|                 onPressed: disableAudio, |                 onPressed: disableAudio, | ||||||
|                 icon: const Icon(Icons.mic), |                 icon: const Icon(Icons.mic), | ||||||
|                 tooltip: 'mute audio', |                 tooltip: AppLocalizations.of(context)!.chatCallMute, | ||||||
|               ) |               ) | ||||||
|             else |             else | ||||||
|               PopupMenuButton<MediaDevice>( |               PopupMenuButton<MediaDevice>( | ||||||
| @@ -250,9 +223,9 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|                     PopupMenuItem<MediaDevice>( |                     PopupMenuItem<MediaDevice>( | ||||||
|                       value: null, |                       value: null, | ||||||
|                       onTap: isMuted ? enableAudio : disableAudio, |                       onTap: isMuted ? enableAudio : disableAudio, | ||||||
|                       child: const ListTile( |                       child: ListTile( | ||||||
|                         leading: Icon(Icons.mic_off), |                         leading: const Icon(Icons.mic_off), | ||||||
|                         title: Text('Mute Microphone'), |                         title: Text(AppLocalizations.of(context)!.chatCallMute), | ||||||
|                       ), |                       ), | ||||||
|                     ), |                     ), | ||||||
|                     if (_audioInputs != null) |                     if (_audioInputs != null) | ||||||
| @@ -275,7 +248,7 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|             IconButton( |             IconButton( | ||||||
|               onPressed: enableAudio, |               onPressed: enableAudio, | ||||||
|               icon: const Icon(Icons.mic_off), |               icon: const Icon(Icons.mic_off), | ||||||
|               tooltip: 'un-mute audio', |               tooltip: AppLocalizations.of(context)!.chatCallUnMute, | ||||||
|             ), |             ), | ||||||
|           if (!lkPlatformIs(PlatformType.iOS)) |           if (!lkPlatformIs(PlatformType.iOS)) | ||||||
|             PopupMenuButton<MediaDevice>( |             PopupMenuButton<MediaDevice>( | ||||||
| @@ -310,7 +283,7 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|               disabledColor: Colors.grey, |               disabledColor: Colors.grey, | ||||||
|               onPressed: Hardware.instance.canSwitchSpeakerphone ? setSpeakerphoneOn : null, |               onPressed: Hardware.instance.canSwitchSpeakerphone ? setSpeakerphoneOn : null, | ||||||
|               icon: Icon(_speakerphoneOn ? Icons.speaker_phone : Icons.phone_android), |               icon: Icon(_speakerphoneOn ? Icons.speaker_phone : Icons.phone_android), | ||||||
|               tooltip: 'Switch SpeakerPhone', |               tooltip: AppLocalizations.of(context)!.chatCallChangeSpeaker, | ||||||
|             ), |             ), | ||||||
|           if (participant.isCameraEnabled()) |           if (participant.isCameraEnabled()) | ||||||
|             PopupMenuButton<MediaDevice>( |             PopupMenuButton<MediaDevice>( | ||||||
| @@ -320,12 +293,9 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|                   PopupMenuItem<MediaDevice>( |                   PopupMenuItem<MediaDevice>( | ||||||
|                     value: null, |                     value: null, | ||||||
|                     onTap: disableVideo, |                     onTap: disableVideo, | ||||||
|                     child: const ListTile( |                     child: ListTile( | ||||||
|                       leading: Icon( |                       leading: const Icon(Icons.videocam_off, color: Colors.white), | ||||||
|                         Icons.videocam_off, |                       title: Text(AppLocalizations.of(context)!.chatCallVideoOff), | ||||||
|                         color: Colors.white, |  | ||||||
|                       ), |  | ||||||
|                       title: Text('Disable Camera'), |  | ||||||
|                     ), |                     ), | ||||||
|                   ), |                   ), | ||||||
|                   if (_videoInputs != null) |                   if (_videoInputs != null) | ||||||
| @@ -348,30 +318,25 @@ class _ControlsWidgetState extends State<ControlsWidget> { | |||||||
|             IconButton( |             IconButton( | ||||||
|               onPressed: enableVideo, |               onPressed: enableVideo, | ||||||
|               icon: const Icon(Icons.videocam_off), |               icon: const Icon(Icons.videocam_off), | ||||||
|               tooltip: 'un-mute video', |               tooltip: AppLocalizations.of(context)!.chatCallVideoOn, | ||||||
|             ), |             ), | ||||||
|           IconButton( |           IconButton( | ||||||
|             icon: Icon(position == CameraPosition.back ? Icons.video_camera_back : Icons.video_camera_front), |             icon: Icon(position == CameraPosition.back ? Icons.video_camera_back : Icons.video_camera_front), | ||||||
|             onPressed: () => toggleCamera(), |             onPressed: () => toggleCamera(), | ||||||
|             tooltip: 'toggle camera', |             tooltip: AppLocalizations.of(context)!.chatCallVideoFlip, | ||||||
|           ), |           ), | ||||||
|           if (participant.isScreenShareEnabled()) |           if (participant.isScreenShareEnabled()) | ||||||
|             IconButton( |             IconButton( | ||||||
|               icon: const Icon(Icons.monitor_outlined), |               icon: const Icon(Icons.monitor_outlined), | ||||||
|               onPressed: () => disableScreenShare(), |               onPressed: () => disableScreenShare(), | ||||||
|               tooltip: 'unshare screen (experimental)', |               tooltip: AppLocalizations.of(context)!.chatCallScreenOff, | ||||||
|             ) |             ) | ||||||
|           else |           else | ||||||
|             IconButton( |             IconButton( | ||||||
|               icon: const Icon(Icons.monitor), |               icon: const Icon(Icons.monitor), | ||||||
|               onPressed: () => enableScreenShare(), |               onPressed: () => enableScreenShare(), | ||||||
|               tooltip: 'share screen (experimental)', |               tooltip: AppLocalizations.of(context)!.chatCallScreenOn, | ||||||
|             ), |             ), | ||||||
|           IconButton( |  | ||||||
|             onPressed: onTapUpdateSubscribePermission, |  | ||||||
|             icon: const Icon(Icons.settings), |  | ||||||
|             tooltip: 'Subscribe permission', |  | ||||||
|           ), |  | ||||||
|         ], |         ], | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -156,7 +156,6 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget> extends Stat | |||||||
|                         _firstAudioPublication?.muted == false && _firstAudioPublication?.subscribed == true, |                         _firstAudioPublication?.muted == false && _firstAudioPublication?.subscribed == true, | ||||||
|                     connectionQuality: widget.participant.connectionQuality, |                     connectionQuality: widget.participant.connectionQuality, | ||||||
|                     isScreenShare: widget.isScreenShare, |                     isScreenShare: widget.isScreenShare, | ||||||
|                     enabledE2EE: widget.participant.isEncrypted, |  | ||||||
|                   ), |                   ), | ||||||
|                 ], |                 ], | ||||||
|               ), |               ), | ||||||
|   | |||||||
| @@ -6,7 +6,6 @@ class ParticipantInfoWidget extends StatelessWidget { | |||||||
|   final bool audioAvailable; |   final bool audioAvailable; | ||||||
|   final ConnectionQuality connectionQuality; |   final ConnectionQuality connectionQuality; | ||||||
|   final bool isScreenShare; |   final bool isScreenShare; | ||||||
|   final bool enabledE2EE; |  | ||||||
|  |  | ||||||
|   const ParticipantInfoWidget({ |   const ParticipantInfoWidget({ | ||||||
|     super.key, |     super.key, | ||||||
| @@ -14,7 +13,6 @@ class ParticipantInfoWidget extends StatelessWidget { | |||||||
|     this.audioAvailable = true, |     this.audioAvailable = true, | ||||||
|     this.connectionQuality = ConnectionQuality.unknown, |     this.connectionQuality = ConnectionQuality.unknown, | ||||||
|     this.isScreenShare = false, |     this.isScreenShare = false, | ||||||
|     this.enabledE2EE = false, |  | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @@ -65,14 +63,6 @@ class ParticipantInfoWidget extends StatelessWidget { | |||||||
|                   size: 16, |                   size: 16, | ||||||
|                 ), |                 ), | ||||||
|               ), |               ), | ||||||
|             Padding( |  | ||||||
|               padding: const EdgeInsets.only(left: 5), |  | ||||||
|               child: Icon( |  | ||||||
|                 enabledE2EE ? Icons.lock : Icons.lock_open, |  | ||||||
|                 color: enabledE2EE ? Colors.green : Colors.red, |  | ||||||
|                 size: 16, |  | ||||||
|               ), |  | ||||||
|             ), |  | ||||||
|           ], |           ], | ||||||
|         ), |         ), | ||||||
|       ); |       ); | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ class _ChatMessageEditorState extends State<ChatMessageEditor> { | |||||||
|   final _textController = TextEditingController(); |   final _textController = TextEditingController(); | ||||||
|  |  | ||||||
|   bool _isSubmitting = false; |   bool _isSubmitting = false; | ||||||
|  |   int? _prevEditingId; | ||||||
|  |  | ||||||
|   List<Attachment> _attachments = List.empty(growable: true); |   List<Attachment> _attachments = List.empty(growable: true); | ||||||
|  |  | ||||||
| @@ -80,8 +81,9 @@ class _ChatMessageEditorState extends State<ChatMessageEditor> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void syncWidget() { |   void syncWidget() { | ||||||
|     if (widget.editing != null) { |     if (widget.editing != null && _prevEditingId != widget.editing!.id) { | ||||||
|       setState(() { |       setState(() { | ||||||
|  |         _prevEditingId = widget.editing!.id; | ||||||
|         _textController.text = widget.editing!.content; |         _textController.text = widget.editing!.content; | ||||||
|         _attachments = widget.editing!.attachments ?? List.empty(growable: true); |         _attachments = widget.editing!.attachments ?? List.empty(growable: true); | ||||||
|       }); |       }); | ||||||
|   | |||||||
| @@ -6,11 +6,19 @@ | |||||||
| 	<true/> | 	<true/> | ||||||
| 	<key>com.apple.security.cs.allow-jit</key> | 	<key>com.apple.security.cs.allow-jit</key> | ||||||
| 	<true/> | 	<true/> | ||||||
| 	<key>com.apple.security.network.server</key> | 	<key>com.apple.security.device.audio-input</key> | ||||||
|  | 	<true/> | ||||||
|  | 	<key>com.apple.security.device.bluetooth</key> | ||||||
|  | 	<true/> | ||||||
|  | 	<key>com.apple.security.device.camera</key> | ||||||
|  | 	<true/> | ||||||
|  | 	<key>com.apple.security.files.user-selected.read-only</key> | ||||||
| 	<true/> | 	<true/> | ||||||
| 	<key>com.apple.security.network.client</key> | 	<key>com.apple.security.network.client</key> | ||||||
|     <true/> | 	<true/> | ||||||
|     <key>com.apple.security.files.user-selected.read-only</key> | 	<key>com.apple.security.network.server</key> | ||||||
|     <true/> | 	<true/> | ||||||
|  | 	<key>keychain-access-groups</key> | ||||||
|  | 	<array/> | ||||||
| </dict> | </dict> | ||||||
| </plist> | </plist> | ||||||
|   | |||||||
| @@ -4,9 +4,17 @@ | |||||||
| <dict> | <dict> | ||||||
| 	<key>com.apple.security.app-sandbox</key> | 	<key>com.apple.security.app-sandbox</key> | ||||||
| 	<true/> | 	<true/> | ||||||
|  | 	<key>com.apple.security.device.audio-input</key> | ||||||
|  | 	<true/> | ||||||
|  | 	<key>com.apple.security.device.bluetooth</key> | ||||||
|  | 	<true/> | ||||||
|  | 	<key>com.apple.security.device.camera</key> | ||||||
|  | 	<true/> | ||||||
|  | 	<key>com.apple.security.files.user-selected.read-only</key> | ||||||
|  | 	<true/> | ||||||
| 	<key>com.apple.security.network.client</key> | 	<key>com.apple.security.network.client</key> | ||||||
|     <true/> | 	<true/> | ||||||
|     <key>com.apple.security.files.user-selected.read-only</key> | 	<key>keychain-access-groups</key> | ||||||
|     <true/> | 	<array/> | ||||||
| </dict> | </dict> | ||||||
| </plist> | </plist> | ||||||
|   | |||||||
| @@ -1163,7 +1163,7 @@ packages: | |||||||
|     source: hosted |     source: hosted | ||||||
|     version: "2.0.7" |     version: "2.0.7" | ||||||
|   wakelock_plus: |   wakelock_plus: | ||||||
|     dependency: transitive |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
|       name: wakelock_plus |       name: wakelock_plus | ||||||
|       sha256: c8b7cc80f045533b40a0e6c9109905494e3cf32c0fbd5c62616998e0de44003f |       sha256: c8b7cc80f045533b40a0e6c9109905494e3cf32c0fbd5c62616998e0de44003f | ||||||
|   | |||||||
| @@ -64,6 +64,7 @@ dependencies: | |||||||
|   permission_handler: ^11.3.1 |   permission_handler: ^11.3.1 | ||||||
|   flutter_webrtc: ^0.10.3 |   flutter_webrtc: ^0.10.3 | ||||||
|   flutter_background: ^1.2.0 |   flutter_background: ^1.2.0 | ||||||
|  |   wakelock_plus: ^1.2.4 | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user