|
|
|
@ -1,17 +1,22 @@ |
|
|
|
import 'package:app_settings/app_settings.dart'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
|
|
import 'dart:ui'; |
|
|
|
import '../../../core/theme/app_colors.dart'; |
|
|
|
import '../controllers/settings_controller.dart'; |
|
|
|
import '../../../core/widgets/common_bottom_nav.dart'; |
|
|
|
import '../../../routes/app_routes.dart'; |
|
|
|
import 'dart:io'; |
|
|
|
import '../../login/bindings/user_Info.dart'; |
|
|
|
|
|
|
|
class SettingsView extends GetView<SettingsController> { |
|
|
|
const SettingsView({Key? key}) : super(key: key); |
|
|
|
|
|
|
|
// 正确获取用户名方式 |
|
|
|
String get userName => User.getname(); |
|
|
|
|
|
|
|
String get deviceInfo => User.getdeviceInfo(); |
|
|
|
String get userId => User.getuserId(); |
|
|
|
String get standing => User.getstanding(); |
|
|
|
String get avatar => User.getnavatar(); |
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
// 直接使用 Theme.of(context) 获取当前主题 |
|
|
|
@ -23,7 +28,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
backgroundColor: isDarkMode ? Colors.black : Colors.white, |
|
|
|
elevation: 0.5, |
|
|
|
title: Text( |
|
|
|
'settings'.tr, // 设置 |
|
|
|
'设置', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 17.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
@ -73,7 +78,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: ClipRRect(//裁剪圆角矩形 |
|
|
|
child: ClipRRect( |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
child: BackdropFilter( |
|
|
|
filter: isDarkMode |
|
|
|
@ -81,9 +86,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Obx(()=>GestureDetector( |
|
|
|
//onTap: ()=>controller.updateUserAvatar(), |
|
|
|
child:Container(//用户头像部分 |
|
|
|
Container( |
|
|
|
width: 60.w, |
|
|
|
height: 60.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
@ -96,33 +99,26 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: ClipRRect(// 裁剪圆形头像 |
|
|
|
child: ClipRRect( |
|
|
|
borderRadius: BorderRadius.circular(30.r), |
|
|
|
child: controller.userInfo.value.avatar.isEmpty |
|
|
|
? Image.network( |
|
|
|
'https://images.unsplash.com/photo-1534528741775-53994a69daeb?ixlib=rb-1.2.1&auto=format&fit=crop&w=200&q=80', |
|
|
|
fit: BoxFit.cover,// 图片填充方式 |
|
|
|
) |
|
|
|
:Image.file( |
|
|
|
File(controller.userInfo.value.avatar), |
|
|
|
fit: BoxFit.cover,// 图片填充方式 |
|
|
|
) |
|
|
|
child: Image.network( |
|
|
|
avatar, |
|
|
|
fit: BoxFit.cover, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
)), |
|
|
|
SizedBox(width: 16.w), |
|
|
|
Expanded(// 占据剩余空间 |
|
|
|
child: Obx(()=>Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,// 左对齐 |
|
|
|
Expanded( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text(//用户名 |
|
|
|
controller.userInfo.value.name, |
|
|
|
Text( |
|
|
|
userName, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
SizedBox(height: 4.h), |
|
|
|
Row( |
|
|
|
@ -135,7 +131,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
borderRadius: BorderRadius.circular(10.r), |
|
|
|
), |
|
|
|
child: Text( |
|
|
|
controller.userInfo.value.membershipLevel, |
|
|
|
standing, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 10.sp, |
|
|
|
color: Colors.white, |
|
|
|
@ -145,7 +141,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Flexible( |
|
|
|
child: Text( |
|
|
|
'${'joinDevice'.tr} DeepSound Pro', // 已连接设备: |
|
|
|
deviceInfo, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: |
|
|
|
@ -158,7 +154,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
SizedBox(height: 4.h), |
|
|
|
Text( |
|
|
|
controller.userInfo.value.id, |
|
|
|
userId, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
@ -166,8 +162,8 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
),), |
|
|
|
Container(// 编辑按钮 |
|
|
|
), |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
@ -183,15 +179,11 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: InkWell( |
|
|
|
onTap: () => Get.toNamed(Routes.editProfile), |
|
|
|
child: Icon( |
|
|
|
Icons.edit, |
|
|
|
size: 16.w, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[600], |
|
|
|
), |
|
|
|
) |
|
|
|
|
|
|
|
child: Icon( |
|
|
|
Icons.edit, |
|
|
|
size: 16.w, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[600], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
@ -208,7 +200,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
Padding( |
|
|
|
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), |
|
|
|
child: Text( |
|
|
|
'systemSetting'.tr, // 系统设置 |
|
|
|
'系统设置', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
@ -239,25 +231,22 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
: ImageFilter.blur(sigmaX: 0, sigmaY: 0), |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
// 语言设置 |
|
|
|
Obx( |
|
|
|
() => _buildSimpleNavigationSetting( |
|
|
|
title: 'languageSetting'.tr, // 语言设置 |
|
|
|
subtitle: controller.language.value.name.tr, |
|
|
|
icon: Icons.language, |
|
|
|
iconBgColor: isDarkMode |
|
|
|
? Colors.indigo[900]!.withOpacity(0.3) |
|
|
|
: Colors.indigo[100]!, |
|
|
|
iconColor: isDarkMode |
|
|
|
? Colors.indigo[300]! |
|
|
|
: Colors.indigo[600]!, |
|
|
|
titleColor: isDarkMode ? Colors.white : null, |
|
|
|
subtitleColor: isDarkMode ? Colors.white70 : null, |
|
|
|
onTap: () { |
|
|
|
_showLanguageSelectionDialog(isDarkMode); |
|
|
|
}, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
), |
|
|
|
// 通知设置 |
|
|
|
_buildSimpleNavigationSetting( |
|
|
|
title: '通知设置', |
|
|
|
subtitle: '管理应用推送和提醒', |
|
|
|
icon: Icons.notifications_none, |
|
|
|
iconBgColor: isDarkMode |
|
|
|
? Colors.indigo[900]!.withOpacity(0.3) |
|
|
|
: Colors.indigo[100]!, |
|
|
|
iconColor: |
|
|
|
isDarkMode ? Colors.indigo[300]! : Colors.indigo[600]!, |
|
|
|
titleColor: isDarkMode ? Colors.white : null, |
|
|
|
subtitleColor: isDarkMode ? Colors.white70 : null, |
|
|
|
onTap: () { |
|
|
|
// 打开通知设置页面 |
|
|
|
}, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
), |
|
|
|
Divider( |
|
|
|
height: 1, |
|
|
|
@ -267,8 +256,8 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
|
|
|
|
// 主题设置 |
|
|
|
_buildToggleSetting( |
|
|
|
title: 'darkMode'.tr, // 暗黑模式 |
|
|
|
subtitle: 'darkModeInfo'.tr, // 切换应用的明暗主题 |
|
|
|
title: '暗黑模式', |
|
|
|
subtitle: '切换应用的明暗主题', |
|
|
|
icon: isDarkMode ? Icons.dark_mode : Icons.light_mode, |
|
|
|
iconBgColor: isDarkMode |
|
|
|
? Colors.indigo[900]!.withOpacity(0.3) |
|
|
|
@ -289,15 +278,15 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
|
|
|
|
// 备份与恢复 |
|
|
|
_buildNavigationSetting( |
|
|
|
title: 'backups'.tr, // 备份与恢复 |
|
|
|
subtitle: 'backupsInfo'.tr, // 备份设置和AI互动历史 |
|
|
|
title: '备份与恢复', |
|
|
|
subtitle: '备份设置和AI互动历史', |
|
|
|
icon: Icons.cloud_upload_outlined, |
|
|
|
iconBgColor: isDarkMode |
|
|
|
? Colors.cyan[900]!.withOpacity(0.3) |
|
|
|
: Colors.cyan[100]!, |
|
|
|
iconColor: |
|
|
|
isDarkMode ? Colors.cyan[300]! : Colors.cyan[600]!, |
|
|
|
value: '${'lastBackup'.tr} 今天', // 上次备份: |
|
|
|
value: '上次备份: 今天', |
|
|
|
valueStyle: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[500], |
|
|
|
@ -307,15 +296,6 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
}, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
), |
|
|
|
Divider( |
|
|
|
height: 1, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white.withOpacity(0.1) |
|
|
|
: Colors.grey[200]), |
|
|
|
|
|
|
|
// 语音服务选择 |
|
|
|
_buildSpeechServiceSetting(isDarkMode), |
|
|
|
|
|
|
|
Divider( |
|
|
|
height: 1, |
|
|
|
color: isDarkMode |
|
|
|
@ -324,8 +304,8 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
|
|
|
|
// 隐私设置 |
|
|
|
_buildSimpleNavigationSetting( |
|
|
|
title: 'privacySettings'.tr, // 隐私设置 |
|
|
|
subtitle: 'privacySettingsInfo'.tr, // 管理数据收集和权限 |
|
|
|
title: '隐私设置', |
|
|
|
subtitle: '管理数据收集和权限', |
|
|
|
icon: Icons.shield_outlined, |
|
|
|
iconBgColor: isDarkMode |
|
|
|
? Colors.purple[900]!.withOpacity(0.3) |
|
|
|
@ -335,7 +315,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
titleColor: isDarkMode ? Colors.white : null, |
|
|
|
subtitleColor: isDarkMode ? Colors.white70 : null, |
|
|
|
onTap: () { |
|
|
|
AppSettings.openAppSettings(); |
|
|
|
// 打开隐私设置页面 |
|
|
|
}, |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
), |
|
|
|
@ -347,7 +327,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
|
|
|
|
// 退出登录 |
|
|
|
_buildSimpleNavigationSetting( |
|
|
|
title: 'logout'.tr, // 退出登录 |
|
|
|
title: '退出登录', |
|
|
|
icon: Icons.logout, |
|
|
|
iconBgColor: isDarkMode |
|
|
|
? Colors.red[900]!.withOpacity(0.3) |
|
|
|
@ -362,13 +342,13 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
backgroundColor: |
|
|
|
isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
title: Text( |
|
|
|
'logout'.tr, // 退出登录 |
|
|
|
'退出登录', |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
content: Text( |
|
|
|
'logoutTips'.tr, // 确定要退出当前账号吗? |
|
|
|
'确定要退出当前账号吗?', |
|
|
|
style: TextStyle( |
|
|
|
color: |
|
|
|
isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
@ -378,7 +358,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
TextButton( |
|
|
|
onPressed: () => Get.back(), |
|
|
|
child: Text( |
|
|
|
'cancel'.tr, // 取消 |
|
|
|
'取消', |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white70 |
|
|
|
@ -392,7 +372,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
controller.signOut(); |
|
|
|
}, |
|
|
|
child: Text( |
|
|
|
'confirm'.tr, // 确定 |
|
|
|
'确定', |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.red[300] |
|
|
|
@ -423,7 +403,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
Padding( |
|
|
|
padding: EdgeInsets.only(left: 4.w, bottom: 8.h), |
|
|
|
child: Text( |
|
|
|
'aboutApplication'.tr, // 关于应用 |
|
|
|
'关于应用', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
@ -485,7 +465,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'DeepSound', |
|
|
|
'DeepVoice', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
@ -494,7 +474,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
SizedBox(height: 2.h), |
|
|
|
Text( |
|
|
|
'${'versions'.tr} 2.4.1 (Build 87)', // 版本 |
|
|
|
'版本 2.4.1 (Build 87)', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: |
|
|
|
@ -515,7 +495,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Text( |
|
|
|
'checkUpdates'.tr, // 检查更新 |
|
|
|
'检查更新', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.blue[300] : Colors.blue[600], |
|
|
|
@ -532,7 +512,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'© 2025 DeepSound Technologies', |
|
|
|
'© 2023 DeepVoice Technologies', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[500], |
|
|
|
@ -540,7 +520,7 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
), |
|
|
|
SizedBox(height: 4.h), |
|
|
|
Text( |
|
|
|
'homeSlogan'.tr, // 连接世界,超越声音 |
|
|
|
'连接世界,超越声音', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[500], |
|
|
|
@ -569,51 +549,45 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
child: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: iconBgColor, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
icon, |
|
|
|
size: 16.w, |
|
|
|
color: iconColor, |
|
|
|
), |
|
|
|
Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: iconBgColor, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Flexible( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
if (subtitle != null) SizedBox(height: 2.h), |
|
|
|
if (subtitle != null) |
|
|
|
Text( |
|
|
|
subtitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
icon, |
|
|
|
size: 16.w, |
|
|
|
color: iconColor, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
if (subtitle != null) SizedBox(height: 2.h), |
|
|
|
if (subtitle != null) |
|
|
|
Text( |
|
|
|
subtitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
Switch( |
|
|
|
value: value, |
|
|
|
@ -644,66 +618,55 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
child: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: iconBgColor, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
icon, |
|
|
|
size: 16.w, |
|
|
|
color: iconColor, |
|
|
|
), |
|
|
|
Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: iconBgColor, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Flexible( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
if (subtitle != null) SizedBox(height: 2.h), |
|
|
|
if (subtitle != null) |
|
|
|
Text( |
|
|
|
subtitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: |
|
|
|
isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
icon, |
|
|
|
size: 16.w, |
|
|
|
color: iconColor, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
if (subtitle != null) SizedBox(height: 2.h), |
|
|
|
if (subtitle != null) |
|
|
|
Text( |
|
|
|
subtitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
Row( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
Flexible( |
|
|
|
child: Text( |
|
|
|
value, |
|
|
|
style: valueStyle ?? |
|
|
|
TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
Text( |
|
|
|
value, |
|
|
|
style: valueStyle ?? |
|
|
|
TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Container( |
|
|
|
@ -748,391 +711,64 @@ class SettingsView extends GetView<SettingsController> { |
|
|
|
child: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: iconBgColor, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
icon, |
|
|
|
size: 16.w, |
|
|
|
color: iconColor, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Flexible( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: titleColor ?? |
|
|
|
(isDarkMode ? Colors.white : Colors.black87), |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
if (subtitle != null) SizedBox(height: 2.h), |
|
|
|
if (subtitle != null) |
|
|
|
Text( |
|
|
|
subtitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: subtitleColor ?? |
|
|
|
(isDarkMode |
|
|
|
? Colors.white70 |
|
|
|
: Colors.black54), |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white.withOpacity(0.05) |
|
|
|
: Colors.grey[100], |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.chevron_right, |
|
|
|
size: 16.w, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[500], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 语音服务设置项 |
|
|
|
Widget _buildSpeechServiceSetting(bool isDarkMode) { |
|
|
|
return InkWell( |
|
|
|
onTap: () { |
|
|
|
_showSpeechServiceSelectionDialog(isDarkMode); |
|
|
|
}, |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(16.w), |
|
|
|
child: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.teal[900]!.withOpacity(0.3) |
|
|
|
: Colors.teal[100]!, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.record_voice_over, |
|
|
|
size: 16.w, |
|
|
|
color: isDarkMode ? Colors.teal[300]! : Colors.teal[600]!, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Flexible( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'voiceService'.tr, // 语音服务 |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 2.h), |
|
|
|
Text( |
|
|
|
'voiceServiceInfo'.tr, // 选择语音识别和合成服务 |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
Row( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
Obx(() { |
|
|
|
final serviceType = controller.speechServiceType.value; |
|
|
|
final serviceName = controller.availableSpeechServices |
|
|
|
.firstWhere( |
|
|
|
(service) => service['type'] == serviceType)['name']; |
|
|
|
|
|
|
|
return Flexible( |
|
|
|
child: Text( |
|
|
|
'$serviceName'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[600], |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
); |
|
|
|
}), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white.withOpacity(0.05) |
|
|
|
: Colors.grey[100], |
|
|
|
color: iconBgColor, |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.chevron_right, |
|
|
|
icon, |
|
|
|
size: 16.w, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[500], |
|
|
|
color: iconColor, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 显示语音服务选择对话框 |
|
|
|
void _showSpeechServiceSelectionDialog(bool isDarkMode) { |
|
|
|
Get.dialog( |
|
|
|
Dialog( |
|
|
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(16.w), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'selectVoiceService'.tr, // 选择语音服务 |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
...controller.availableSpeechServices.map((service) { |
|
|
|
return Obx(() { |
|
|
|
final isSelected = |
|
|
|
controller.speechServiceType.value == service['type']; |
|
|
|
|
|
|
|
return InkWell( |
|
|
|
onTap: () { |
|
|
|
controller.setSpeechServiceType(service['type']); |
|
|
|
Get.back(); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
margin: EdgeInsets.only(bottom: 12.h), |
|
|
|
padding: EdgeInsets.all(12.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode |
|
|
|
? Colors.teal[900]!.withOpacity(0.3) |
|
|
|
: Colors.teal[50]!) |
|
|
|
: (isDarkMode |
|
|
|
? Colors.white.withOpacity(0.05) |
|
|
|
: Colors.grey[100]!), |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
border: Border.all( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode |
|
|
|
? Colors.teal[300]! |
|
|
|
: Colors.teal[600]!) |
|
|
|
: Colors.transparent, |
|
|
|
width: 1, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 24.w, |
|
|
|
height: 24.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode |
|
|
|
? Colors.teal[300] |
|
|
|
: Colors.teal[600]) |
|
|
|
: (isDarkMode |
|
|
|
? Colors.white.withOpacity(0.1) |
|
|
|
: Colors.grey[300]), |
|
|
|
shape: BoxShape.circle, |
|
|
|
), |
|
|
|
child: isSelected |
|
|
|
? Icon( |
|
|
|
Icons.check, |
|
|
|
size: 16.w, |
|
|
|
color: Colors.white, |
|
|
|
) |
|
|
|
: null, |
|
|
|
), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Expanded( |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'${service['name']}'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white |
|
|
|
: Colors.black87, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
SizedBox(height: 4.h), |
|
|
|
Text( |
|
|
|
'${service['description']}'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white70 |
|
|
|
: Colors.black54, |
|
|
|
), |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
maxLines: 2, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
}); |
|
|
|
}).toList(), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.end, |
|
|
|
children: [ |
|
|
|
TextButton( |
|
|
|
onPressed: () => Get.back(), |
|
|
|
child: Text( |
|
|
|
'cancel'.tr, // 取消 |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
title, |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.black54, |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: titleColor ?? |
|
|
|
(isDarkMode ? Colors.white : Colors.black87), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 显示语言选择对话框 |
|
|
|
void _showLanguageSelectionDialog(bool isDarkMode) { |
|
|
|
Get.dialog( |
|
|
|
Dialog( |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(24.r), |
|
|
|
), |
|
|
|
insetPadding: EdgeInsets.symmetric(horizontal: 20.w), |
|
|
|
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white, |
|
|
|
child: Container( |
|
|
|
width: 0.9.sw, |
|
|
|
padding: EdgeInsets.only(top: 32.h, bottom: 16.h), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Padding( |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 24.w), |
|
|
|
child: Text( |
|
|
|
'selectLanguage'.tr, // 选择语言 |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 20.sp, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
Container( |
|
|
|
constraints: BoxConstraints(maxHeight: 0.5.sh), |
|
|
|
child: SingleChildScrollView( |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: controller.languageList.map((language) { |
|
|
|
return ListTile( |
|
|
|
title: Text( |
|
|
|
language.name.tr, |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode ? Colors.white : Colors.black, |
|
|
|
), |
|
|
|
if (subtitle != null) SizedBox(height: 2.h), |
|
|
|
if (subtitle != null) |
|
|
|
Text( |
|
|
|
subtitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: subtitleColor ?? |
|
|
|
(isDarkMode ? Colors.white70 : Colors.black54), |
|
|
|
), |
|
|
|
trailing: |
|
|
|
controller.language.value.value == language.value |
|
|
|
? Icon( |
|
|
|
Icons.check_circle, |
|
|
|
color: isDarkMode |
|
|
|
? AppColors.primary |
|
|
|
: Colors.blue, |
|
|
|
) |
|
|
|
: const SizedBox.shrink(), |
|
|
|
onTap: () { |
|
|
|
controller.setLanguage(language); |
|
|
|
}, |
|
|
|
); |
|
|
|
}).toList(), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
Align( |
|
|
|
alignment: Alignment.centerRight, |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.only(right: 24.w), |
|
|
|
child: TextButton( |
|
|
|
onPressed: () => Get.back(), |
|
|
|
child: Text( |
|
|
|
'cancel'.tr, // 取消 |
|
|
|
style: TextStyle( |
|
|
|
color: isDarkMode ? AppColors.primary : Colors.blue, |
|
|
|
fontSize: 16.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
Container( |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white.withOpacity(0.05) |
|
|
|
: Colors.grey[100], |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.chevron_right, |
|
|
|
size: 16.w, |
|
|
|
color: isDarkMode ? Colors.white70 : Colors.grey[500], |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
|