Browse Source

Merge branch 'dev' of github.com:deepcloud2048/deep_voice into dev

newdev_shunjiawei
wolfplus 1 year ago
parent
commit
bc0a6a2c8d
  1. 181
      lib/core/utils/permission_util.dart
  2. 46
      lib/data/services/music_manager.dart
  3. 4
      lib/modules/agent/controllers/agent_controller.dart
  4. 4
      lib/modules/meeting/controllers/meeting_controller.dart
  5. 12
      lib/modules/pairing/controllers/pairing_controller.dart
  6. 6
      lib/modules/settings/views/permissions_view.dart

181
lib/core/utils/permission_util.dart

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:app_settings/app_settings.dart';
import 'logger.dart';
import 'package:get/get.dart';
/// 权限请求工具类
///
@ -21,7 +22,7 @@ class PermissionUtil {
PermissionUtil._();
/// 权限解释横幅的叠加层入口
OverlayEntry? _explanationOverlayEntry;
//OverlayEntry? _explanationOverlayEntry;
/// 请求指定权限
///
@ -36,7 +37,7 @@ class PermissionUtil {
///
/// 返回值:`Future<bool>` 权限是否最终授予
Future<bool> requestPermission({
required BuildContext context,
// required BuildContext context,
required Permission permissionType,
required String permissionName,
required String explanationText,
@ -58,7 +59,7 @@ class PermissionUtil {
// 显示权限解释横幅(覆盖所有状态的处理)
_showExplanationOverlay(
context: context,
//context: context,
permissionName: permissionName,
explanationText: explanationText,
);
@ -69,7 +70,7 @@ class PermissionUtil {
// 显示永久拒绝对话框(在解释横幅下方显示)
final result = await _showPermanentDenialDialog(
context: context,
// context: context,
permissionName: permissionName,
permanentDenialText: permanentDenialText,
settingsButtonText: settingsButtonText,
@ -105,7 +106,7 @@ class PermissionUtil {
else if (newStatus == PermissionStatus.permanentlyDenied) {
Logger.w('PermissionUtil', '$permissionName 权限在请求后被永久拒绝');
final result = await _showPermanentDenialDialog(
context: context,
// context: context,
permissionName: permissionName,
permanentDenialText: permanentDenialText,
settingsButtonText: settingsButtonText,
@ -123,7 +124,7 @@ class PermissionUtil {
if (status == PermissionStatus.restricted ||
status == PermissionStatus.limited) {
Logger.w('PermissionUtil', '$permissionName 权限受限或受限访问: $status');
await _showRestrictedPermissionDialog(context, permissionName);
await _showRestrictedPermissionDialog(permissionName);
_hideExplanationOverlay();
return false;
}
@ -148,69 +149,104 @@ class PermissionUtil {
///
/// 在请求权限前显示,向用户解释为什么需要这个权限
void _showExplanationOverlay({
required BuildContext context,
required String permissionName,
required String explanationText,
}) {
_hideExplanationOverlay(); // 确保移除旧叠加层
_explanationOverlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: MediaQuery.of(context).padding.top + 10,
left: 16,
right: 16,
child: Material(
borderRadius: BorderRadius.circular(12),
elevation: 8,
color: Theme.of(context).colorScheme.background,
shadowColor: Colors.black.withOpacity(0.3),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'需要$permissionName权限',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
const SizedBox(height: 8),
Text(
explanationText,
style: const TextStyle(fontSize: 14),
Get.dialog(
Stack(
children: [
Positioned(
top: 10,
left: 16,
right: 16,
child: Material(
borderRadius: BorderRadius.circular(12),
elevation: 8,
color: Colors.grey[300],
shadowColor: Colors.black.withOpacity(0.3),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'需要$permissionName权限',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
const SizedBox(height: 8),
Text(
explanationText,
style: const TextStyle(fontSize: 14),
),
],
),
],
),
),
),
),
],
),
);
// _hideExplanationOverlay(); // 确保移除旧叠加层
Future.delayed(Duration.zero, () {
if (_explanationOverlayEntry != null) {
Overlay.of(context).insert(_explanationOverlayEntry!);
Logger.i('PermissionUtil', '权限说明叠加层已显示 ($permissionName)');
}
});
// _explanationOverlayEntry = OverlayEntry(
// builder: (context) => Positioned(
// top: MediaQuery.of(context).padding.top + 10,
// left: 16,
// right: 16,
// child: Material(
// borderRadius: BorderRadius.circular(12),
// elevation: 8,
// color: Theme.of(context).colorScheme.background,
// shadowColor: Colors.black.withOpacity(0.3),
// child: Padding(
// padding: const EdgeInsets.all(16),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// '需要$permissionName权限',
// style: const TextStyle(
// fontWeight: FontWeight.bold,
// fontSize: 16,
// ),
// ),
// const SizedBox(height: 8),
// Text(
// explanationText,
// style: const TextStyle(fontSize: 14),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// Future.delayed(Duration.zero, () {
// if (_explanationOverlayEntry != null) {
// Overlay.of(context).insert(_explanationOverlayEntry!);
// Logger.i('PermissionUtil', '权限说明叠加层已显示 ($permissionName)');
// }
// });
}
/// 隐藏权限解释横幅
void _hideExplanationOverlay() {
if (_explanationOverlayEntry != null) {
_explanationOverlayEntry?.remove();
_explanationOverlayEntry = null;
Logger.d('PermissionUtil', '权限说明叠加层已移除');
}
Get.back();
//_explanationOverlayEntry!.remove();
Logger.d('PermissionUtil', '权限说明叠加层已移除');
}
/// 显示永久拒绝后的设置引导对话框
///
/// 在权限被永久拒绝时调用,提示用户前往设置手动开启权限
Future<bool> _showPermanentDenialDialog({
required BuildContext context,
//required BuildContext context,
required String permissionName,
required String permanentDenialText,
required String settingsButtonText,
@ -218,31 +254,36 @@ class PermissionUtil {
}) async {
Logger.i('PermissionUtil', '显示永久拒绝对话框 ($permissionName)');
bool? userChoice = await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
bool? userChoice = await Get.dialog(
AlertDialog(
title: Text('需要$permissionName权限'),
content: Text(permanentDenialText),
actions: [
TextButton(
onPressed: () {
Logger.d('PermissionUtil', '用户取消设置 ($permissionName)');
Navigator.pop(context, false);
Get.back(result: false);
},
child: Text(cancelButtonText),
),
ElevatedButton(
onPressed: () {
Logger.d('PermissionUtil', '用户同意前往设置 ($permissionName)');
Navigator.pop(context, true);
Get.back(result: true);
},
child: Text(settingsButtonText),
),
],
),
barrierDismissible: false,
);
// bool? userChoice = await showDialog<bool>(
// context: context,
// barrierDismissible: false,
// builder: (context) =>
// );
// 用户选择前往设置
if (userChoice == true) {
AppSettings.openAppSettings();
@ -256,24 +297,40 @@ class PermissionUtil {
/// 显示受限权限对话框
///
/// 在权限受限状态(如iOS上的受限照片访问)时调用
Future<void> _showRestrictedPermissionDialog(
BuildContext context, String permissionName) async {
Future<void> _showRestrictedPermissionDialog(String permissionName) async {
Logger.w('PermissionUtil', '显示受限权限对话框 ($permissionName)');
await showDialog(
context: context,
builder: (context) => AlertDialog(
Get.dialog(
AlertDialog(
title: Text('$permissionName权限受限'),
content: const Text('此功能在当前设备上不可用或受限,请检查设备设置或系统限制'),
actions: [
TextButton(
onPressed: () {
Logger.d('PermissionUtil', '用户确认受限权限 ($permissionName)');
Navigator.pop(context);
// Navigator.pop(context);
Get.back();
},
child: const Text('确定'),
),
],
),
);
// await showDialog(
// context: context,
// builder: (context) => AlertDialog(
// title: Text('$permissionName权限受限'),
// content: const Text('此功能在当前设备上不可用或受限,请检查设备设置或系统限制'),
// actions: [
// TextButton(
// onPressed: () {
// Logger.d('PermissionUtil', '用户确认受限权限 ($permissionName)');
// Navigator.pop(context);
// },
// child: const Text('确定'),
// ),
// ],
// ),
// );
}
}

46
lib/data/services/music_manager.dart

@ -16,34 +16,34 @@ class MusicManager extends GetxService {
@override
void onInit() {
super.onInit();
final context = Get.context;
if (context == null) {
Logger.error('无法获取 BuildContext');
return;
}
requestNotificationPermission(context);
// final context = Get.context;
// if (context == null) {
// Logger.error('无法获取 BuildContext');
// return;
// }
requestNotificationPermission();
Logger.info('初始化权限请求');
}
Future<void> requestNotificationPermission(BuildContext context) async {
final granted = await PermissionUtil.instance.requestPermission(
context: context,
permissionType: Permission.notification,
permissionName: '通知',
explanationText: '需要通知权限来显示音乐播放状态。',
permanentDenialText: '您已永久拒绝通知权限,请前往设置开启权限。',
settingsButtonText: '去设置',
cancelButtonText: '取消',
);
Future<void> requestNotificationPermission() async {
final granted = await PermissionUtil.instance.requestPermission(
// context: context,
permissionType: Permission.notification,
permissionName: '通知',
explanationText: '需要通知权限来显示音乐播放状态。',
permanentDenialText: '您已永久拒绝通知权限,请前往设置开启权限。',
settingsButtonText: '去设置',
cancelButtonText: '取消',
);
if (!granted) {
Logger.warning('通知权限未被授予');
return;
}
if (!granted) {
Logger.warning('通知权限未被授予');
return;
}
Logger.info('通知权限已授予');
}
Logger.info('通知权限已授予');
}
/// 释放资源
@override

4
lib/modules/agent/controllers/agent_controller.dart

@ -700,7 +700,7 @@ class AgentController extends GetxController {
if (isTextInputMode.value) {
// 使用 PermissionUtil 检查麦克风权限
final hasPermission = await PermissionUtil.instance.requestPermission(
context: Get.context!,
// context: Get.context!,
permissionType: Permission.microphone,
permissionName: '麦克风',
explanationText: '语音识别与翻译功能需要访问麦克风。',
@ -881,7 +881,7 @@ class AgentController extends GetxController {
// 检查麦克风权限
final hasPermission = await PermissionUtil.instance.requestPermission(
context: Get.context!,
// context: Get.context!,
permissionType: Permission.microphone,
permissionName: '麦克风',
explanationText: '语音识别与翻译功能需要访问麦克风。',

4
lib/modules/meeting/controllers/meeting_controller.dart

@ -87,11 +87,11 @@ class MeetingController extends GetxController {
// 请求录音权限
void _requestStoragePermission() async {
final BuildContext context = Get.overlayContext!;
// final BuildContext context = Get.overlayContext!;
PermissionUtil.instance
.requestPermission(
context: context,
// context: context,
permissionType: Permission.storage,
permissionName: "存储",
explanationText: "我们需要访问存储权限,以便您可以选择并上传音频文件。",

12
lib/modules/pairing/controllers/pairing_controller.dart

@ -529,11 +529,11 @@ class PairingController extends GetxController {
}
// Android权限检查 - 使用 PermissionUtil
final context = Get.context;
if (context == null) {
Logger.e(_tag, '无法获取有效上下文,跳过权限请求');
return false;
}
// final context = Get.context;
// if (context == null) {
// Logger.e(_tag, '无法获取有效上下文,跳过权限请求');
// return false;
// }
// 根据 Android 版本确定需要的权限
List<Permission> requiredPermissions = [
@ -551,7 +551,7 @@ class PairingController extends GetxController {
Logger.d(_tag, '正在请求 $permissionName 权限');
final granted = await PermissionUtil.instance.requestPermission(
context: context,
// context: context,
permissionType: permission,
permissionName: permissionName,
explanationText: _getExplanationText(permission),

6
lib/modules/settings/views/permissions_view.dart

@ -295,15 +295,15 @@ class PermissionsView extends GetView<SettingsController> {
Future<void> _handlePermissionAction(
Permission permission, PermissionStatus status) async {
try {
final context = Get.context;
if (context == null) return;
// final context = Get.context;
// if (context == null) return;
final permissionName = _getPermissionName(permission);
final explanationText = _getExplanationText(permission);
// 使用 PermissionUtil 请求权限
final hasPermission = await PermissionUtil.instance.requestPermission(
context: context,
// context: context,
permissionType: permission,
permissionName: permissionName,
explanationText: explanationText,

Loading…
Cancel
Save