Browse Source

feat(core): 添加权限请求工具类并优化消息气泡布局

- 新增 PermissionUtil 工具类,用于检查和请求权限
- 修改 AgentController,引入 PermissionUtil
- 调整 MessageBubble 布局,优化 AI 消息显示
newdev_shunjiawei
lxm 1 year ago
parent
commit
bdc35bead7
  1. 134
      lib/core/utils/permission_util.dart
  2. 1
      lib/modules/agent/controllers/agent_controller.dart
  3. 3
      lib/modules/agent/views/message_bubble.dart

134
lib/core/utils/permission_util.dart

@ -0,0 +1,134 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:app_settings/app_settings.dart';
class PermissionUtil {
/// 检查并请求多个权限
///
/// [permissions] 要检查的权限列表,如 [Permission.microphone, Permission.location]
/// [rationaleTitle] 弹窗标题
/// [rationaleMessage] 权限用途说明内容(支持多行)
///
/// 返回是否所有权限都已被授予
static Future<bool> checkAndRequestPermissions({
required List<Permission> permissions,
required String rationaleTitle,
required List<String> rationaleMessage,
}) async {
try {
Map<Permission, PermissionStatus> statuses = {};
// 检查是否都已授权
bool allGranted = true;
for (var permission in permissions) {
final status = await permission.status;
if (!status.isGranted) {
allGranted = false;
statuses[permission] = status;
}
}
if (allGranted) return true;
// 判断是否包含永久拒绝
bool hasPermanentDenied =
statuses.values.any((status) => status.isPermanentlyDenied);
// 显示提示弹窗
_showPermissionDialog(
isPermanent: hasPermanentDenied,
title: rationaleTitle,
messages: rationaleMessage,
onConfirm: () async {
if (hasPermanentDenied) {
AppSettings.openAppSettings();
} else {
final newStatuses = await permissions.request();
final allGrantedNow =
newStatuses.values.every((status) => status.isGranted);
if (!allGrantedNow) {
print("部分权限被拒绝: $newStatuses");
}
}
},
);
return false;
} catch (e) {
print("权限检查异常: $e");
return false;
}
}
/// 权限说明弹窗
static void _showPermissionDialog({
required bool isPermanent,
required String title,
required List<String> messages,
required VoidCallback onConfirm,
}) {
Get.generalDialog(
barrierDismissible: false,
barrierLabel: '权限提示',
transitionBuilder: (context, anim1, anim2, child) {
return SlideTransition(
position: Tween<Offset>(
begin: Offset(0, -1),
end: Offset(0, 0),
).animate(CurvedAnimation(parent: anim1, curve: Curves.easeOut)),
child: child,
);
},
pageBuilder: (context, anim1, anim2) {
return SafeArea(
child: Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 80, left: 24, right: 24),
child: Material(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
...messages.map((msg) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text("• $msg"),
)),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () => Get.back(),
child: const Text('取消'),
),
const SizedBox(width: 8),
TextButton(
onPressed: () {
Get.back();
onConfirm();
},
child: Text(isPermanent ? '前往设置' : '授权'),
),
],
),
],
),
),
),
),
),
);
},
);
}
}

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

@ -16,6 +16,7 @@ import 'package:app_settings/app_settings.dart';
import 'package:deep_voice/core/utils/logger.dart'; import 'package:deep_voice/core/utils/logger.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view.dart';
import '../../../core/utils/permission_util.dart';
class Message { class Message {
final bool isUser; //标识信息是否来自用户还是AI final bool isUser; //标识信息是否来自用户还是AI

3
lib/modules/agent/views/message_bubble.dart

@ -91,7 +91,7 @@ class MessageBubble extends GetView<AgentController> {
Row( Row(
mainAxisAlignment: isUser mainAxisAlignment: isUser
? MainAxisAlignment.end ? MainAxisAlignment.end
: MainAxisAlignment.start, : MainAxisAlignment.spaceBetween,
children: [ children: [
// 时间戳(左对齐或右对齐) // 时间戳(左对齐或右对齐)
Text( Text(
@ -104,7 +104,6 @@ class MessageBubble extends GetView<AgentController> {
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
), ),
), ),
const Spacer(),
// AI标识(仅在AI消息时显示) // AI标识(仅在AI消息时显示)
if (!isUser) if (!isUser)
Padding( Padding(

Loading…
Cancel
Save