Browse Source
将权限管理功能从设置模块分离为独立模块,新增蓝牙、通知、存储和麦克风权限支持。优化权限分组显示逻辑,根据平台显示不同权限组,并完善权限状态管理和多语言支持。 - 新增权限分组模型和独立控制器 - 添加蓝牙、通知等新权限支持 - 优化权限请求流程和状态显示 - 完善中英文多语言翻译 - 移除旧版权限视图并更新路由配置weicu
14 changed files with 622 additions and 517 deletions
@ -0,0 +1,9 @@ |
|||
import 'package:get/get.dart'; |
|||
import '../controllers/permissions_controller.dart'; |
|||
|
|||
class PermissionsBinding extends Bindings { |
|||
@override |
|||
void dependencies() { |
|||
Get.lazyPut<PermissionsController>(() => PermissionsController()); |
|||
} |
|||
} |
|||
@ -0,0 +1,222 @@ |
|||
import 'package:get/get.dart'; |
|||
import 'package:permission_handler/permission_handler.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'dart:io' show Platform; |
|||
import '../../../core/utils/permission_util.dart'; |
|||
|
|||
class PermissionsController extends GetxController { |
|||
// 权限状态映射 |
|||
final RxMap<Permission, PermissionStatus> permissionStatuses = |
|||
<Permission, PermissionStatus>{}.obs; |
|||
|
|||
// 是否正在请求权限 |
|||
final RxBool isRequestingPermission = false.obs; |
|||
|
|||
@override |
|||
void onInit() { |
|||
super.onInit(); |
|||
checkAllPermissions(); |
|||
} |
|||
|
|||
/// 检查所有权限状态 |
|||
Future<Map<Permission, PermissionStatus>> checkAllPermissions() async { |
|||
final Map<Permission, PermissionStatus> statuses = {}; |
|||
|
|||
// 根据平台获取需要检查的权限列表 |
|||
final permissions = _getPlatformPermissions(); |
|||
|
|||
for (final permission in permissions) { |
|||
try { |
|||
statuses[permission] = await permission.status; |
|||
} catch (e) { |
|||
// 某些权限在特定平台可能不支持,设置为拒绝状态 |
|||
statuses[permission] = PermissionStatus.denied; |
|||
} |
|||
} |
|||
|
|||
permissionStatuses.value = statuses; |
|||
return statuses; |
|||
} |
|||
|
|||
/// 获取平台特定的权限列表 |
|||
List<Permission> _getPlatformPermissions() { |
|||
if (Platform.isIOS) { |
|||
return [ |
|||
Permission.calendarFullAccess, |
|||
Permission.location, |
|||
Permission.contacts, |
|||
Permission.bluetooth, |
|||
Permission.notification, |
|||
Permission.storage, |
|||
Permission.microphone, |
|||
]; |
|||
} else if (Platform.isAndroid) { |
|||
return [ |
|||
Permission.calendarFullAccess, |
|||
Permission.location, |
|||
Permission.phone, |
|||
Permission.sms, |
|||
Permission.contacts, |
|||
Permission.bluetooth, |
|||
Permission.notification, |
|||
Permission.scheduleExactAlarm, |
|||
Permission.storage, |
|||
Permission.microphone, |
|||
]; |
|||
} |
|||
return []; |
|||
} |
|||
|
|||
/// 请求单个权限 |
|||
Future<bool> requestPermission(Permission permission) async { |
|||
if (isRequestingPermission.value) return false; |
|||
|
|||
isRequestingPermission.value = true; |
|||
|
|||
try { |
|||
final permissionName = getPermissionName(permission); |
|||
final explanationText = _getDetailedDescription(permission); |
|||
|
|||
final hasPermission = await PermissionUtil.instance.requestPermission( |
|||
permissionType: permission, |
|||
permissionName: permissionName, |
|||
explanationText: explanationText, |
|||
permanentDenialText: 'permanentDenialText'.tr.replaceAll( |
|||
'{permission}', permissionName), |
|||
settingsButtonText: 'goToSettings'.tr, |
|||
cancelButtonText: 'cancel'.tr, |
|||
); |
|||
|
|||
if (hasPermission) { |
|||
_showSuccessMessage(); |
|||
} |
|||
|
|||
// 刷新权限状态 |
|||
await checkAllPermissions(); |
|||
|
|||
return hasPermission; |
|||
} catch (e) { |
|||
_showErrorMessage(); |
|||
return false; |
|||
} finally { |
|||
isRequestingPermission.value = false; |
|||
} |
|||
} |
|||
|
|||
/// 打开系统设置 |
|||
void openSettings() { |
|||
openAppSettings(); |
|||
} |
|||
|
|||
/// 获取权限的用户友好名称 |
|||
String getPermissionName(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phone'.tr; |
|||
case Permission.sms: |
|||
return 'sms'.tr; |
|||
case Permission.contacts: |
|||
return 'contacts'.tr; |
|||
case Permission.bluetooth: |
|||
return 'bluetooth'.tr; |
|||
case Permission.notification: |
|||
return 'notification'.tr; |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWrite'.tr; |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccess'.tr; |
|||
case Permission.location: |
|||
return 'locationInfo'.tr; |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarm'.tr; |
|||
case Permission.storage: |
|||
return 'storagePermission'.tr; |
|||
case Permission.microphone: |
|||
return 'microphonePermission'.tr; |
|||
default: |
|||
return permission.toString(); |
|||
} |
|||
} |
|||
|
|||
/// 获取权限说明文本 |
|||
String _getDetailedDescription(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phonePermissionDetailDesc'.tr; |
|||
case Permission.sms: |
|||
return 'smsPermissionDetailDesc'.tr; |
|||
case Permission.contacts: |
|||
return 'contactsPermissionDetailDesc'.tr; |
|||
case Permission.bluetooth: |
|||
return 'bluetoothPermissionDetailDesc'.tr; |
|||
case Permission.notification: |
|||
return 'notificationPermissionDetailDesc'.tr; |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWritePermissionDetailDesc'.tr; |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccessPermissionDetailDesc'.tr; |
|||
case Permission.location: |
|||
return 'locationPermissionDetailDesc'.tr; |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarmPermissionDetailDesc'.tr; |
|||
case Permission.storage: |
|||
return 'storagePermissionExplanation'.tr; |
|||
case Permission.microphone: |
|||
return 'microphonePermissionExplanation'.tr; |
|||
default: |
|||
return 'appNeedsPermissionForFullFunction'.tr; |
|||
} |
|||
} |
|||
|
|||
/// 获取权限描述 |
|||
String getPermissionDescription(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phonePermissionDesc'.tr; |
|||
case Permission.sms: |
|||
return 'smsPermissionDesc'.tr; |
|||
case Permission.contacts: |
|||
return 'contactsPermissionDesc'.tr; |
|||
case Permission.bluetooth: |
|||
return 'bluetoothPermissionDesc'.tr; |
|||
case Permission.notification: |
|||
return 'notificationPermissionDesc'.tr; |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWritePermissionDesc'.tr; |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccessPermissionDesc'.tr; |
|||
case Permission.location: |
|||
return 'locationPermissionDesc'.tr; |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarmPermissionDesc'.tr; |
|||
case Permission.storage: |
|||
return 'storagePermissionExplanation'.tr; |
|||
case Permission.microphone: |
|||
return 'microphonePermissionExplanation'.tr; |
|||
default: |
|||
return 'appFunctionNeeds'.tr; |
|||
} |
|||
} |
|||
|
|||
/// 显示成功消息 |
|||
void _showSuccessMessage() { |
|||
Get.snackbar( |
|||
'success'.tr, |
|||
'permissionGranted'.tr, |
|||
snackPosition: SnackPosition.BOTTOM, |
|||
backgroundColor: Colors.green, |
|||
colorText: Colors.white, |
|||
); |
|||
} |
|||
|
|||
/// 显示错误消息 |
|||
void _showErrorMessage() { |
|||
Get.snackbar( |
|||
'error'.tr, |
|||
'permissionRequestError'.tr, |
|||
snackPosition: SnackPosition.BOTTOM, |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
); |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:permission_handler/permission_handler.dart'; |
|||
|
|||
class PermissionGroup { |
|||
final String titleKey; |
|||
final IconData icon; |
|||
final List<Permission> permissions; |
|||
|
|||
const PermissionGroup({ |
|||
required this.titleKey, |
|||
required this.icon, |
|||
required this.permissions, |
|||
}); |
|||
|
|||
static List<PermissionGroup> getPlatformGroups() { |
|||
return [ |
|||
// 通讯权限组 - 仅Android(包含联系人权限) |
|||
const PermissionGroup( |
|||
titleKey: 'communicationPermissions', |
|||
icon: Icons.phone_android, |
|||
permissions: [Permission.phone, Permission.sms, Permission.contacts], |
|||
), |
|||
// 蓝牙权限组 |
|||
const PermissionGroup( |
|||
titleKey: 'bluetoothPermissions', |
|||
icon: Icons.bluetooth, |
|||
permissions: [Permission.bluetooth], |
|||
), |
|||
// 通知权限组 |
|||
const PermissionGroup( |
|||
titleKey: 'notificationPermissions', |
|||
icon: Icons.notifications, |
|||
permissions: [Permission.notification], |
|||
), |
|||
// 闹钟权限组 - 仅Android |
|||
const PermissionGroup( |
|||
titleKey: 'alarmPermissions', |
|||
icon: Icons.alarm, |
|||
permissions: [Permission.scheduleExactAlarm], |
|||
), |
|||
// 日历权限组 |
|||
const PermissionGroup( |
|||
titleKey: 'calendarPermissions', |
|||
icon: Icons.calendar_today, |
|||
permissions: [Permission.calendarFullAccess], |
|||
), |
|||
// 位置权限组 |
|||
const PermissionGroup( |
|||
titleKey: 'locationPermissions', |
|||
icon: Icons.location_on, |
|||
permissions: [Permission.location], |
|||
), |
|||
// 存储权限组 |
|||
const PermissionGroup( |
|||
titleKey: 'storagePermissions', |
|||
icon: Icons.storage, |
|||
permissions: [Permission.storage], |
|||
), |
|||
// 麦克风权限组 |
|||
const PermissionGroup( |
|||
titleKey: 'microphonePermissions', |
|||
icon: Icons.mic, |
|||
permissions: [Permission.microphone], |
|||
), |
|||
]; |
|||
} |
|||
} |
|||
@ -0,0 +1,276 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:permission_handler/permission_handler.dart'; |
|||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|||
import 'dart:ui'; |
|||
import 'dart:io' show Platform; |
|||
|
|||
import '../controllers/permissions_controller.dart'; |
|||
import '../models/permission_group.dart'; |
|||
|
|||
class PermissionsView extends GetView<PermissionsController> { |
|||
const PermissionsView({Key? key}) : super(key: key); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
|||
|
|||
return Scaffold( |
|||
backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], |
|||
appBar: AppBar( |
|||
backgroundColor: isDarkMode ? Colors.black : Colors.white, |
|||
elevation: 0.5, |
|||
leading: IconButton( |
|||
icon: Icon( |
|||
Icons.arrow_back_ios, |
|||
size: 20.w, |
|||
color: isDarkMode ? Colors.white : Colors.black87, |
|||
), |
|||
onPressed: () => Get.back(), |
|||
), |
|||
title: Text( |
|||
'permissionManagement'.tr, |
|||
style: TextStyle( |
|||
fontSize: 17.sp, |
|||
fontWeight: FontWeight.w600, |
|||
color: isDarkMode ? Colors.white : Colors.black, |
|||
), |
|||
), |
|||
centerTitle: true, |
|||
), |
|||
body: Obx(() { |
|||
if (controller.permissionStatuses.isEmpty) { |
|||
return const Center(child: CircularProgressIndicator()); |
|||
} |
|||
|
|||
return RefreshIndicator( |
|||
onRefresh: controller.checkAllPermissions, |
|||
child: ListView( |
|||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), |
|||
children: _buildPermissionGroups(isDarkMode), |
|||
), |
|||
); |
|||
}), |
|||
); |
|||
} |
|||
|
|||
List<Widget> _buildPermissionGroups(bool isDarkMode) { |
|||
final groups = PermissionGroup.getPlatformGroups(); |
|||
final List<Widget> widgets = []; |
|||
|
|||
for (int i = 0; i < groups.length; i++) { |
|||
final group = groups[i]; |
|||
|
|||
// 过滤平台特定权限 |
|||
if (_shouldShowGroup(group)) { |
|||
widgets.add(_buildPermissionSection( |
|||
group.titleKey, |
|||
group.icon, |
|||
group.permissions, |
|||
controller.permissionStatuses, |
|||
isDarkMode, |
|||
)); |
|||
|
|||
if (i < groups.length - 1) { |
|||
widgets.add(SizedBox(height: 20.h)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return widgets; |
|||
} |
|||
|
|||
bool _shouldShowGroup(PermissionGroup group) { |
|||
// Android特定权限组 |
|||
if (group.titleKey == 'communicationPermissions' || |
|||
group.titleKey == 'alarmPermissions') { |
|||
return Platform.isAndroid; |
|||
} |
|||
// 蓝牙权限、通知权限、存储权限和麦克风权限在所有平台显示 |
|||
if (group.titleKey == 'bluetoothPermissions' || |
|||
group.titleKey == 'notificationPermissions' || |
|||
group.titleKey == 'storagePermissions' || |
|||
group.titleKey == 'microphonePermissions') { |
|||
return true; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
Widget _buildPermissionSection( |
|||
String titleKey, |
|||
IconData icon, |
|||
List<Permission> permissions, |
|||
Map<Permission, PermissionStatus> statuses, |
|||
bool isDarkMode, |
|||
) { |
|||
return Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
// 组标题 |
|||
Padding( |
|||
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), |
|||
child: Text( |
|||
titleKey.tr, |
|||
style: TextStyle( |
|||
fontSize: 12.sp, |
|||
fontWeight: FontWeight.w500, |
|||
color: isDarkMode ? Colors.blue[400] : Colors.blue[600], |
|||
letterSpacing: 1, |
|||
), |
|||
), |
|||
), |
|||
|
|||
// 权限项容器 |
|||
Container( |
|||
decoration: BoxDecoration( |
|||
color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white, |
|||
borderRadius: BorderRadius.circular(16.r), |
|||
boxShadow: [ |
|||
BoxShadow( |
|||
color: isDarkMode |
|||
? Colors.black.withOpacity(0.2) |
|||
: Colors.black.withOpacity(0.05), |
|||
blurRadius: 10, |
|||
offset: const Offset(0, 2), |
|||
), |
|||
], |
|||
), |
|||
child: ClipRRect( |
|||
borderRadius: BorderRadius.circular(16.r), |
|||
child: BackdropFilter( |
|||
filter: isDarkMode |
|||
? ImageFilter.blur(sigmaX: 5, sigmaY: 5) |
|||
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), |
|||
child: Column( |
|||
children: _buildPermissionItems(permissions, statuses, isDarkMode), |
|||
), |
|||
), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
|
|||
List<Widget> _buildPermissionItems( |
|||
List<Permission> permissions, |
|||
Map<Permission, PermissionStatus> statuses, |
|||
bool isDarkMode, |
|||
) { |
|||
final List<Widget> items = []; |
|||
|
|||
for (int i = 0; i < permissions.length; i++) { |
|||
final permission = permissions[i]; |
|||
final status = statuses[permission] ?? PermissionStatus.denied; |
|||
|
|||
items.add( |
|||
_buildPermissionItem( |
|||
permission: permission, |
|||
status: status, |
|||
isDarkMode: isDarkMode, |
|||
), |
|||
); |
|||
|
|||
// 添加分隔线,最后一个不加 |
|||
if (i < permissions.length - 1) { |
|||
items.add(Divider( |
|||
height: 1, |
|||
color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200], |
|||
)); |
|||
} |
|||
} |
|||
|
|||
return items; |
|||
} |
|||
|
|||
Widget _buildPermissionItem({ |
|||
required Permission permission, |
|||
required PermissionStatus status, |
|||
required bool isDarkMode, |
|||
}) { |
|||
return Padding( |
|||
padding: EdgeInsets.all(16.w), |
|||
child: Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|||
children: [ |
|||
Expanded( |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
Text( |
|||
controller.getPermissionName(permission), |
|||
style: TextStyle( |
|||
fontSize: 16.sp, |
|||
fontWeight: FontWeight.w500, |
|||
color: isDarkMode ? Colors.white : Colors.black87, |
|||
), |
|||
), |
|||
SizedBox(height: 4.h), |
|||
Text( |
|||
controller.getPermissionDescription(permission), |
|||
style: TextStyle( |
|||
fontSize: 12.sp, |
|||
color: isDarkMode ? Colors.white70 : Colors.grey[600], |
|||
), |
|||
), |
|||
SizedBox(height: 4.h), |
|||
_buildStatusText(status, isDarkMode), |
|||
], |
|||
), |
|||
), |
|||
Obx(() => Switch( |
|||
value: status.isGranted, |
|||
onChanged: controller.isRequestingPermission.value |
|||
? null |
|||
: (value) => _handlePermissionToggle(permission, status, value), |
|||
activeColor: Colors.blue[600], |
|||
)), |
|||
], |
|||
), |
|||
); |
|||
} |
|||
|
|||
Widget _buildStatusText(PermissionStatus status, bool isDarkMode) { |
|||
String text; |
|||
Color color; |
|||
|
|||
if (status.isGranted) { |
|||
text = 'authorized'.tr; |
|||
color = Colors.green; |
|||
} else if (status.isDenied) { |
|||
text = 'unauthorized'.tr; |
|||
color = Colors.red; |
|||
} else if (status.isPermanentlyDenied) { |
|||
text = 'needOpenInSystemSettings'.tr; |
|||
color = Colors.orange; |
|||
} else if (status.isLimited) { |
|||
text = 'partialAuthorization'.tr; |
|||
color = Colors.orange; |
|||
} else { |
|||
text = 'unknownStatus'.tr; |
|||
color = Colors.grey; |
|||
} |
|||
|
|||
return Text( |
|||
text, |
|||
style: TextStyle( |
|||
color: color, |
|||
fontSize: 12.sp, |
|||
fontWeight: FontWeight.w500, |
|||
), |
|||
); |
|||
} |
|||
|
|||
void _handlePermissionToggle( |
|||
Permission permission, |
|||
PermissionStatus status, |
|||
bool value, |
|||
) { |
|||
if (value) { |
|||
// 请求权限 |
|||
controller.requestPermission(permission); |
|||
} else if (status.isGranted) { |
|||
// 已授权但用户想关闭,引导到系统设置 |
|||
controller.openSettings(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,402 +0,0 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:permission_handler/permission_handler.dart'; |
|||
import '../controllers/settings_controller.dart'; |
|||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|||
import 'dart:ui'; |
|||
import 'dart:io' show Platform; |
|||
|
|||
import '../../../core/utils/permission_util.dart'; // 引入PermissionUtil |
|||
|
|||
class PermissionsView extends GetView<SettingsController> { |
|||
const PermissionsView({Key? key}) : super(key: key); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
|||
|
|||
return Scaffold( |
|||
backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], |
|||
appBar: AppBar( |
|||
backgroundColor: isDarkMode ? Colors.black : Colors.white, |
|||
elevation: 0.5, |
|||
leading: IconButton( |
|||
icon: Icon( |
|||
Icons.arrow_back_ios, |
|||
size: 20.w, |
|||
color: isDarkMode ? Colors.white : Colors.black87, |
|||
), |
|||
onPressed: () => Get.back(), |
|||
), |
|||
title: Text( |
|||
'permissionManagement'.tr, // 权限管理 |
|||
style: TextStyle( |
|||
fontSize: 17.sp, |
|||
fontWeight: FontWeight.w600, |
|||
color: isDarkMode ? Colors.white : Colors.black, |
|||
), |
|||
), |
|||
centerTitle: true, |
|||
), |
|||
body: FutureBuilder<Map<Permission, PermissionStatus>>( |
|||
future: controller.checkAllPermissions(), //检查权限当前状态 |
|||
builder: (context, snapshot) { |
|||
if (snapshot.connectionState == ConnectionState.waiting) { |
|||
return const Center(child: CircularProgressIndicator()); |
|||
} |
|||
|
|||
if (snapshot.hasError) { |
|||
return Center( |
|||
child: Text( |
|||
'${'getPermissionStatusFailed'.tr}: ${snapshot.error}')); // 获取权限状态失败 |
|||
} |
|||
|
|||
final permissionStatuses = snapshot.data ?? {}; |
|||
|
|||
return ListView( |
|||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), |
|||
children: [ |
|||
// 通讯权限组- iOS平台没有通讯权限 |
|||
if (Platform.isAndroid) ...[ |
|||
_buildPermissionSection( |
|||
'communicationPermissions'.tr, // 通讯权限 |
|||
Icons.phone_android, |
|||
[Permission.phone, Permission.sms], |
|||
permissionStatuses, |
|||
isDarkMode), |
|||
SizedBox(height: 20.h), |
|||
], |
|||
// 闹钟权限组 |
|||
if (Platform.isAndroid) ...[ |
|||
_buildPermissionSection( |
|||
'alarmPermissions'.tr, // 闹钟权限 |
|||
Icons.alarm, |
|||
[Permission.scheduleExactAlarm], |
|||
permissionStatuses, |
|||
isDarkMode, |
|||
), |
|||
SizedBox(height: 20.h), |
|||
], |
|||
|
|||
// 日历权限组 |
|||
_buildPermissionSection( |
|||
'calendarPermissions'.tr, // 日历权限 |
|||
Icons.calendar_today, |
|||
[Permission.calendarFullAccess], |
|||
permissionStatuses, |
|||
isDarkMode), |
|||
|
|||
SizedBox(height: 20.h), |
|||
|
|||
// 位置权限组 |
|||
_buildPermissionSection( |
|||
'locationPermissions'.tr, // 位置权限 |
|||
Icons.location_on, |
|||
[Permission.location], |
|||
permissionStatuses, |
|||
isDarkMode), |
|||
], |
|||
); |
|||
}, |
|||
), |
|||
); |
|||
} |
|||
|
|||
// 构建权限组区域 |
|||
Widget _buildPermissionSection( |
|||
String title, |
|||
IconData icon, |
|||
List<Permission> permissions, |
|||
Map<Permission, PermissionStatus> statuses, |
|||
bool isDarkMode) { |
|||
return Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
// 组标题 |
|||
Padding( |
|||
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), |
|||
child: Text( |
|||
title.tr, |
|||
style: TextStyle( |
|||
fontSize: 12.sp, |
|||
fontWeight: FontWeight.w500, |
|||
color: isDarkMode ? Colors.blue[400] : Colors.blue[600], |
|||
letterSpacing: 1, |
|||
), |
|||
), |
|||
), |
|||
|
|||
// 权限项容器 |
|||
Container( |
|||
decoration: BoxDecoration( |
|||
color: isDarkMode ? Colors.white.withOpacity(0.05) : Colors.white, |
|||
borderRadius: BorderRadius.circular(16.r), |
|||
boxShadow: [ |
|||
BoxShadow( |
|||
color: isDarkMode |
|||
? Colors.black.withOpacity(0.2) |
|||
: Colors.black.withOpacity(0.05), |
|||
blurRadius: 10, |
|||
offset: const Offset(0, 2), |
|||
), |
|||
], |
|||
), |
|||
child: ClipRRect( |
|||
borderRadius: BorderRadius.circular(16.r), |
|||
child: BackdropFilter( |
|||
filter: isDarkMode |
|||
? ImageFilter.blur(sigmaX: 5, sigmaY: 5) |
|||
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), |
|||
child: Column( |
|||
children: |
|||
_buildPermissionItems(permissions, statuses, isDarkMode), |
|||
), |
|||
), |
|||
), |
|||
), |
|||
], |
|||
); |
|||
} |
|||
|
|||
// 构建权限项列表 |
|||
List<Widget> _buildPermissionItems(List<Permission> permissions, |
|||
Map<Permission, PermissionStatus> statuses, bool isDarkMode) { |
|||
final List<Widget> items = []; |
|||
|
|||
// 获取名称 |
|||
String getName(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phone'.tr; // 电话 |
|||
case Permission.sms: |
|||
return 'sms'.tr; // 短信 |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWrite'.tr; // 日历写入 |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccess'.tr; // 日历完整访问 |
|||
case Permission.location: |
|||
return 'locationInfo'.tr; // 位置信息 |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarm'.tr; // 闹钟 |
|||
default: |
|||
return permission.toString(); |
|||
} |
|||
} |
|||
|
|||
// 获取描述文本 |
|||
String getDescription(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phonePermissionDesc'.tr; // 用于拨打电话功能 |
|||
case Permission.sms: |
|||
return 'smsPermissionDesc'.tr; // 用于发送短信功能 |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWritePermissionDesc'.tr; // 用于创建日历事件和提醒 |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccessPermissionDesc'.tr; // 用于读取和管理日历事件及提醒 |
|||
case Permission.location: |
|||
return 'locationPermissionDesc'.tr; // 用于获取当前位置信息 |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarmPermissionDesc'.tr; // 设置精确闹钟需要此权限 |
|||
default: |
|||
return 'appFunctionNeeds'.tr; // 应用功能需要 |
|||
} |
|||
} |
|||
|
|||
for (int i = 0; i < permissions.length; i++) { |
|||
final permission = permissions[i]; |
|||
final status = statuses[permission] ?? PermissionStatus.denied; |
|||
|
|||
items.add( |
|||
_buildPermissionItem( |
|||
name: getName(permission), |
|||
description: getDescription(permission), |
|||
status: status, |
|||
permission: permission, |
|||
isDarkMode: isDarkMode, |
|||
), |
|||
); |
|||
|
|||
// 添加分隔线,最后一个不加 |
|||
if (i < permissions.length - 1) { |
|||
items.add(Divider( |
|||
height: 1, |
|||
color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[200], |
|||
)); |
|||
} |
|||
} |
|||
|
|||
return items; |
|||
} |
|||
|
|||
// 构建单个权限项 |
|||
Widget _buildPermissionItem({ |
|||
required String name, |
|||
required String description, |
|||
required PermissionStatus status, |
|||
required Permission permission, |
|||
required bool isDarkMode, |
|||
}) { |
|||
return Padding( |
|||
padding: EdgeInsets.all(16.w), |
|||
child: Row( |
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|||
children: [ |
|||
Expanded( |
|||
child: Column( |
|||
crossAxisAlignment: CrossAxisAlignment.start, |
|||
children: [ |
|||
Text( |
|||
name.tr, |
|||
style: TextStyle( |
|||
fontSize: 16.sp, |
|||
fontWeight: FontWeight.w500, |
|||
color: isDarkMode ? Colors.white : Colors.black87, |
|||
), |
|||
), |
|||
SizedBox(height: 4.h), |
|||
Text( |
|||
description.tr, |
|||
style: TextStyle( |
|||
fontSize: 12.sp, |
|||
color: isDarkMode ? Colors.white70 : Colors.grey[600], |
|||
), |
|||
), |
|||
SizedBox(height: 4.h), |
|||
_buildStatusText(status, isDarkMode), |
|||
], |
|||
), |
|||
), |
|||
Switch( |
|||
value: status.isGranted, |
|||
onChanged: (value) { |
|||
if (value) { |
|||
_handlePermissionAction(permission, status); |
|||
} else if (status.isGranted) { |
|||
controller.openSettings(); |
|||
} |
|||
}, |
|||
activeColor: Colors.blue[600], |
|||
), |
|||
], |
|||
), |
|||
); |
|||
} |
|||
|
|||
// 状态文本 |
|||
Widget _buildStatusText(PermissionStatus status, bool isDarkMode) { |
|||
String text; |
|||
Color color; |
|||
|
|||
if (status.isGranted) { |
|||
text = 'authorized'.tr; // 已授权 |
|||
color = Colors.green; |
|||
} else if (status.isDenied) { |
|||
text = 'unauthorized'.tr; // 未授权 |
|||
color = Colors.red; |
|||
} else if (status.isPermanentlyDenied) { |
|||
text = 'needOpenInSystemSettings'.tr; // 需要在系统设置中开启 |
|||
color = Colors.orange; |
|||
} else if (status.isLimited) { |
|||
text = 'partialAuthorization'.tr; // 部分授权 |
|||
color = Colors.orange; |
|||
} else { |
|||
text = 'unknownStatus'.tr; // 未知状态 |
|||
color = Colors.grey; |
|||
} |
|||
|
|||
return Text( |
|||
text, |
|||
style: TextStyle( |
|||
color: color, |
|||
fontSize: 12.sp, |
|||
fontWeight: FontWeight.w500, |
|||
), |
|||
); |
|||
} |
|||
|
|||
// 处理权限请求 |
|||
Future<void> _handlePermissionAction( |
|||
Permission permission, PermissionStatus status) async { |
|||
try { |
|||
// final context = Get.context; |
|||
// if (context == null) return; |
|||
|
|||
final permissionName = _getPermissionName(permission); |
|||
final explanationText = getDetailedDescription(permission); |
|||
|
|||
// 使用 PermissionUtil 请求权限 |
|||
final hasPermission = await PermissionUtil.instance.requestPermission( |
|||
// context: context, |
|||
permissionType: permission, |
|||
permissionName: permissionName, |
|||
explanationText: explanationText, |
|||
permanentDenialText: 'permanentDenialText'.tr.replaceAll( |
|||
'{permission}', permissionName), // 您已永久拒绝{permission}权限,请前往应用设置开启 |
|||
settingsButtonText: 'goToSettings'.tr, // 去设置 |
|||
cancelButtonText: 'cancel'.tr, // 取消 |
|||
); |
|||
|
|||
if (hasPermission) { |
|||
Get.snackbar( |
|||
'success'.tr, // 成功 |
|||
'permissionGranted'.tr, // 权限已授予 |
|||
snackPosition: SnackPosition.BOTTOM, |
|||
backgroundColor: Colors.green, |
|||
colorText: Colors.white, |
|||
); |
|||
} |
|||
|
|||
// 刷新界面,重新获取权限状态 |
|||
Get.forceAppUpdate(); |
|||
} catch (e) { |
|||
Get.snackbar( |
|||
'error'.tr, // 错误 |
|||
'permissionRequestError'.tr, // 请求权限时出错 |
|||
snackPosition: SnackPosition.BOTTOM, |
|||
backgroundColor: Colors.red, |
|||
colorText: Colors.white, |
|||
); |
|||
} |
|||
} |
|||
|
|||
// 获取权限的用户友好名称 |
|||
String _getPermissionName(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phone'.tr; // 电话 |
|||
case Permission.sms: |
|||
return 'sms'.tr; // 短信 |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWrite'.tr; // 日历写入 |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccess'.tr; // 日历完整访问 |
|||
case Permission.location: |
|||
return 'locationInfo'.tr; // 位置信息 |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarm'.tr; // 闹钟 |
|||
default: |
|||
return permission.toString(); |
|||
} |
|||
} |
|||
|
|||
// 获取权限说明文本 |
|||
String getDetailedDescription(Permission permission) { |
|||
switch (permission) { |
|||
case Permission.phone: |
|||
return 'phonePermissionDetailDesc'.tr; // 拨打电话功能需要电话权限 |
|||
case Permission.sms: |
|||
return 'smsPermissionDetailDesc'.tr; // 发送短信功能需要短信权限 |
|||
case Permission.calendarWriteOnly: |
|||
return 'calendarWritePermissionDetailDesc'.tr; // 创建日历事件需要日历写入权限 |
|||
case Permission.calendarFullAccess: |
|||
return 'calendarFullAccessPermissionDetailDesc'.tr; // 管理日历事件需要完整日历权限 |
|||
case Permission.location: |
|||
return 'locationPermissionDetailDesc'.tr; // 获取位置信息需要位置权限 |
|||
case Permission.scheduleExactAlarm: |
|||
return 'alarmPermissionDetailDesc'.tr; // 设置精确闹钟需要此权限 |
|||
default: |
|||
return 'appNeedsPermissionForFullFunction'.tr; // 应用需要此权限以提供完整功能 |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue