diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index b8498fb461..7d69f49b1e 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -1190,6 +1190,16 @@ "type": "text", "placeholders": {} }, + "phonePermissionDeniedNotice": "Phone permission denied. Please grant it to be able to properly send and recieve calls.", + "@phonePermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "phonePermissionPermanentlyDeniedNotice": "Phone permission permanently denied. Calling functionality will not work as intended. Visit settings to set the right permission.", + "@phonePermissionPermanentlyDeniedNotice": { + "type": "text", + "placeholders": {} + }, "login": "Login", "@login": { "type": "text", diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 8828081bf2..2d4c399ef7 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -378,7 +378,7 @@ class ChatListController extends State scrollController.addListener(_onScroll); _waitForFirstSync(); _hackyWebRTCFixForWeb(); - CallKeepManager().initialize(); + CallKeepManager().initialize(context: context); WidgetsBinding.instance.addPostFrameCallback((_) async { if (mounted) { searchServer = diff --git a/lib/utils/voip/callkeep_manager.dart b/lib/utils/voip/callkeep_manager.dart index 6de7cb6e3a..df151c7e99 100644 --- a/lib/utils/voip/callkeep_manager.dart +++ b/lib/utils/voip/callkeep_manager.dart @@ -1,13 +1,16 @@ import 'dart:async'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:callkeep/callkeep.dart'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter_foreground_task/flutter_foreground_task.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/voip_plugin.dart'; class CallKeeper { @@ -167,7 +170,33 @@ class CallKeepManager { Logs().v('[onPushKitToken] token => ${event.token}'); } - Future initialize() async { + Future initialize({BuildContext? context}) async { + if (PlatformInfos.isAndroid) { + tryReadPhoneStatePermission().then((pStatus) { + log(pStatus.toString()); + if (context != null) { + if (pStatus == PermissionStatus.denied || + pStatus == PermissionStatus.permanentlyDenied) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + duration: const Duration(seconds: 4), + content: Text( + pStatus == PermissionStatus.denied + ? L10n.of(context)!.phonePermissionDeniedNotice + : L10n.of(context)! + .phonePermissionPermanentlyDeniedNotice, + ), + action: SnackBarAction( + label: L10n.of(context)!.settings, + onPressed: openAppSettings, + ), + ), + ); + } + } + }); + } + _callKeep.on(CallKeepPerformAnswerCallAction(), answerCall); _callKeep.on(CallKeepDidPerformDTMFAction(), didPerformDTMFAction); _callKeep.on( @@ -365,3 +394,8 @@ class CallKeepManager { setCallHeld(event.callUUID, event.hold); } } + +Future tryReadPhoneStatePermission() async { + final info = await DeviceInfoPlugin().androidInfo; + return info.version.sdkInt > 30 ? await Permission.phone.request() : null; +}