🐛 Bug fixes on macos
This commit is contained in:
parent
657b497370
commit
34dee3773d
@ -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();
|
||||||
@ -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,29 +318,24 @@ 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/>
|
<true/>
|
||||||
<key>com.apple.security.network.client</key>
|
<key>com.apple.security.device.bluetooth</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.device.camera</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.server</key>
|
||||||
|
<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.network.client</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/>
|
<true/>
|
||||||
<key>com.apple.security.files.user-selected.read-only</key>
|
<key>com.apple.security.files.user-selected.read-only</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
<key>keychain-access-groups</key>
|
||||||
|
<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:
|
||||||
|
Loading…
Reference in New Issue
Block a user