Files
wushu/lib/views/profile/settings/app_fun.dart
Developer cba04235c8 release
2026-04-03 03:26:06 +08:00

743 lines
23 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../../constants/app_constants.dart';
import '../../../services/get/theme_controller.dart';
import '../../../services/get/tap_liquid_glass_controller.dart';
import '../../../utils/audio_manager.dart';
import './widgets.dart';
import '../../home/set/home-load.dart';
import '../../../controllers/settings/suggestions.dart';
import '../../../controllers/load/locally.dart';
/// 时间: 2026-03-26
/// 功能: 功能设置页面
/// 介绍: 应用功能开关和设置项管理
/// 最新变化: 添加自动刷新功能
class AppFunSettingsPage extends StatefulWidget {
const AppFunSettingsPage({super.key});
@override
State<AppFunSettingsPage> createState() => _AppFunSettingsPageState();
}
class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
final ThemeController _themeController = Get.find<ThemeController>();
final TapLiquidGlassController _glassController = Get.put(
TapLiquidGlassController(),
);
bool _autoRefreshEnabled = false;
bool _debugInfoEnabled = false;
bool _soundEnabled = false; // 默认关闭
bool _vibrationEnabled = true;
bool _preloadEnabled = true;
bool _globalTipsEnabled = true; // 添加全局Tips开关状态
bool _hideSecondaryButtons = false; // 隐藏次要按钮
static const String _autoRefreshKey = 'auto_refresh_enabled';
static const String _debugInfoKey = 'debug_info_enabled';
static const String _soundEnabledKey = 'sound_enabled'; // 声音反馈开关key
static const String _hideSecondaryButtonsKey =
'hide_secondary_buttons'; // 隐藏次要按钮key
@override
void initState() {
super.initState();
_loadSettings();
}
Future<void> _loadSettings() async {
final prefs = await SharedPreferences.getInstance();
await GlobalTipsManager().init();
await AudioManager().init(); // 确保 AudioManager 已初始化
if (mounted) {
setState(() {
_autoRefreshEnabled = prefs.getBool(_autoRefreshKey) ?? false;
_debugInfoEnabled = prefs.getBool(_debugInfoKey) ?? false;
_globalTipsEnabled =
GlobalTipsManager().isEnabled; // 从 GlobalTipsManager 加载状态
_preloadEnabled = prefs.getBool('preload_enabled') ?? true;
_soundEnabled = prefs.getBool(_soundEnabledKey) ?? false; // 加载声音反馈状态
_hideSecondaryButtons =
prefs.getBool(_hideSecondaryButtonsKey) ?? false; // 加载隐藏次要按钮状态
});
// 同步到 AudioManager
AudioManager().setMuted(!_soundEnabled);
}
}
Future<void> _setAutoRefresh(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_autoRefreshKey, value);
await AutoRefreshManager().setEnabled(value);
if (mounted) {
setState(() {
_autoRefreshEnabled = value;
});
}
}
Future<void> _setDebugInfo(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_debugInfoKey, value);
await DebugInfoManager().setEnabled(value);
if (mounted) {
setState(() {
_debugInfoEnabled = value;
});
}
}
Future<void> _setPreload(bool value) async {
await LocalCacheManager().setPreloadEnabled(value);
if (mounted) {
setState(() {
_preloadEnabled = value;
});
}
}
// 设置声音反馈
Future<void> _setSoundEnabled(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_soundEnabledKey, value);
// 更新 AudioManager 的静音状态
await AudioManager().setMuted(!value);
if (mounted) {
setState(() {
_soundEnabled = value;
});
}
}
// 设置震动反馈
Future<void> _setVibrationEnabled(bool value) async {
if (value && !_vibrationEnabled) {
// 从关闭到开启,显示提示对话框
_showVibrationDialog();
} else {
// 从开启到关闭,直接设置
if (mounted) {
setState(() {
_vibrationEnabled = value;
});
}
}
}
// 显示震动提示对话框
void _showVibrationDialog() {
final primaryColor = _themeController.currentThemeColor;
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('震动反馈'),
content: const Text('默认场景调用震动,未对软件震动做出优化,待收集建议改进'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Navigator.of(context).pop();
if (mounted) {
setState(() {
_vibrationEnabled = true;
});
}
},
child: Text('确定', style: TextStyle(color: primaryColor)),
),
],
),
);
}
// 设置隐藏次要按钮
Future<void> _setHideSecondaryButtons(bool value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_hideSecondaryButtonsKey, value);
// 更新管理器状态
await SecondaryButtonsManager().setHidden(value);
if (mounted) {
setState(() {
_hideSecondaryButtons = value;
});
}
}
// 设置Tap沉浸光感导航栏
Future<void> _setTapLiquidGlass(bool value) async {
await _glassController.toggleEnabled(value);
}
@override
Widget build(BuildContext context) {
return Obx(() {
final isDark = _themeController.isDarkMode;
final primaryColor = _themeController.currentThemeColor;
return Scaffold(
backgroundColor: isDark
? const Color(0xFF1A1A1A)
: const Color(0xFFF5F5F5),
appBar: AppBar(
title: Text(
'功能设置',
style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),
),
backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white,
elevation: 0,
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: primaryColor),
onPressed: () => Navigator.of(context).pop(),
),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildSettingsGroup('基础功能', [
_buildSwitchItem(
'自动刷新',
'首页诗句自动刷新5s ',
Icons.refresh,
_autoRefreshEnabled,
_setAutoRefresh,
isDark,
),
_buildSwitchItem(
'调式信息',
'开启后可加载更多信息',
Icons.bug_report,
_debugInfoEnabled,
_setDebugInfo,
isDark,
),
_buildSwitchItem(
'预加载',
_preloadEnabled
? '开启后 部分数据优先使用本地缓存,减少与服务器的通信次数'
: '关闭后,优先使用云端数据,无延迟,但刷新缓慢',
Icons.storage,
_preloadEnabled,
_setPreload,
isDark,
),
], isDark),
const SizedBox(height: 16),
_buildSettingsGroup('主页显示设置', [
Obx(
() => _buildSwitchItem(
'Tap沉浸光感',
'开启后底栏显示类iOS26 风格',
Icons.dark_mode,
_glassController.isEnabled,
_setTapLiquidGlass,
isDark,
),
),
Obx(() {
if (!_glassController.isEnabled) return const SizedBox.shrink();
return _buildTransparencyLevelItem(isDark);
}),
_buildSwitchItem(
'隐藏次要按钮',
'开启后隐藏上一条和分享按钮',
Icons.share,
_hideSecondaryButtons,
_setHideSecondaryButtons,
isDark,
),
_buildFontSliderItem(isDark),
], isDark),
const SizedBox(height: 16),
_buildSettingsGroup('交互反馈', [
_buildSwitchItem(
'全局Tips开关',
'显示一些使用技巧',
Icons.volume_up,
_globalTipsEnabled,
(value) async {
await GlobalTipsManager().setEnabled(value);
if (mounted) {
setState(() {
_globalTipsEnabled = value;
});
}
},
isDark,
),
_buildSwitchItem(
'声音反馈',
'操作时播放提示音',
Icons.volume_up,
_soundEnabled,
_setSoundEnabled,
isDark,
),
_buildSwitchItem(
'震动反馈',
'操作时震动提示',
Icons.vibration,
_vibrationEnabled,
(value) => _setVibrationEnabled(value),
isDark,
),
], isDark),
const SizedBox(height: 16),
_buildSettingsGroup('高级设置', [
_buildActionItem(
'重置设置',
'恢复默认设置',
Icons.restore,
() => _showResetDialog(),
isDark,
),
], isDark),
const SizedBox(height: 32),
_buildVersionInfo(isDark),
],
),
);
});
}
Widget _buildSettingsGroup(String title, List<Widget> items, bool isDark) {
final primaryColor = _themeController.currentThemeColor;
return Container(
decoration: BoxDecoration(
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(isDark ? 30 : 5),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Text(
title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: primaryColor,
),
),
),
...items,
],
),
);
}
Widget _buildSwitchItem(
String title,
String subtitle,
IconData icon,
bool value,
ValueChanged<bool> onChanged,
bool isDark,
) {
final primaryColor = _themeController.currentThemeColor;
return ListTile(
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, color: primaryColor, size: 20),
),
title: Text(
title,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black,
),
),
subtitle: Text(
subtitle,
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
trailing: Switch(
value: value,
onChanged: onChanged,
activeThumbColor: primaryColor,
),
);
}
Widget _buildFontSliderItem(bool isDark) {
final primaryColor = _themeController.currentThemeColor;
return ListTile(
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(8),
),
child: Icon(Icons.widgets, color: primaryColor, size: 20),
),
title: Text(
'桌面卡片',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black,
),
),
subtitle: Text(
'使用帮助',
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
trailing: Icon(
Icons.chevron_right,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: isDark ? const Color(0xFF2A2A2A) : Colors.white,
title: Row(
children: [
Icon(Icons.info_outline, color: primaryColor),
const SizedBox(width: 8),
Text(
'桌面卡片设置',
style: TextStyle(
color: isDark ? Colors.white : Colors.black,
),
),
],
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'鸿蒙设备请在桌面端设置:',
style: TextStyle(
fontWeight: FontWeight.bold,
color: isDark ? Colors.white : Colors.black,
),
),
const SizedBox(height: 8),
Text(
'1. 长按桌面空白处',
style: TextStyle(
color: isDark ? Colors.grey[300] : Colors.black,
),
),
Text(
'2. 选择「情景诗词」卡片',
style: TextStyle(
color: isDark ? Colors.grey[300] : Colors.black,
),
),
Text(
'3. 添加后点击桌面卡片即可设置',
style: TextStyle(
color: isDark ? Colors.grey[300] : Colors.black,
),
),
Text(
'4. 后续版本支持在应用内设置卡片',
style: TextStyle(
color: isDark ? Colors.grey[300] : Colors.black,
),
),
const SizedBox(height: 12),
const Text(
'注意:该页面设置对鸿蒙设备不生效',
style: TextStyle(color: Colors.orange, fontSize: 12),
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
SystemNavigator.pop();
},
child: const Text('前往桌面'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const WidgetsPage(),
),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: primaryColor,
foregroundColor: Colors.white,
),
child: const Text('仍要进入'),
),
],
);
},
);
},
);
}
Widget _buildTransparencyLevelItem(bool isDark) {
final primaryColor = _themeController.currentThemeColor;
return Obx(() {
final currentIndex = _glassController.transparencyLevelIndex;
return Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 12),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(8),
),
child: Icon(Icons.opacity, color: primaryColor, size: 20),
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'高透级别',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black,
),
),
Text(
'当前: ${_glassController.transparencyLevelLabel}',
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
const SizedBox(width: 12),
Expanded(
child: Row(
children: [
_buildLevelButton('', 0, currentIndex == 0, isDark),
const SizedBox(width: 8),
_buildLevelButton('', 1, currentIndex == 1, isDark),
const SizedBox(width: 8),
_buildLevelButton('', 2, currentIndex == 2, isDark),
],
),
),
],
),
);
});
}
Widget _buildLevelButton(
String label,
int levelIndex,
bool isSelected,
bool isDark,
) {
final primaryColor = _themeController.currentThemeColor;
return Expanded(
child: GestureDetector(
onTap: () => _glassController.setTransparencyLevelByIndex(levelIndex),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: isSelected
? primaryColor
: (isDark ? Colors.grey[800] : Colors.grey[200]),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: isSelected
? primaryColor
: (isDark ? Colors.grey[700]! : Colors.grey[300]!),
width: 1.5,
),
),
child: Text(
label,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: isSelected
? Colors.white
: (isDark ? Colors.grey[300] : Colors.grey[700]),
),
),
),
),
);
}
Widget _buildActionItem(
String title,
String subtitle,
IconData icon,
VoidCallback onTap,
bool isDark,
) {
final primaryColor = _themeController.currentThemeColor;
return ListTile(
leading: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(8),
),
child: Icon(icon, color: primaryColor, size: 20),
),
title: Text(
title,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black,
),
),
subtitle: Text(
subtitle,
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
trailing: Icon(
Icons.chevron_right,
color: isDark ? Colors.grey[500] : Colors.grey[400],
),
onTap: onTap,
);
}
Widget _buildVersionInfo(bool isDark) {
return const SuggestionsCard();
}
Widget _buildActionButton(
String title,
String subtitle,
IconData icon,
Color color,
VoidCallback onTap,
) {
final isDark = _themeController.isDarkMode;
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: color.withValues(alpha: 0.2), width: 1),
),
child: Column(
children: [
Icon(icon, color: color, size: 24),
const SizedBox(height: 4),
Text(
title,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black87,
),
),
const SizedBox(height: 2),
Text(
subtitle,
style: TextStyle(
fontSize: 10,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
textAlign: TextAlign.center,
),
],
),
),
);
}
void _showSnackBar(String message) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(message)));
}
void _showResetDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('重置设置'),
content: const Text('确定要恢复默认设置吗?'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('取消'),
),
TextButton(
onPressed: () async {
Navigator.of(context).pop();
// 重置所有设置为默认值
await _setAutoRefresh(false); // 自动刷新:关闭
await _setDebugInfo(false); // 调试信息:关闭
await _setPreload(true); // 预加载:开启
await _setHideSecondaryButtons(false); // 隐藏次要按钮:关闭
await _setSoundEnabled(false); // 声音反馈:关闭
await _setTapLiquidGlass(true); // Tap沉浸光感开启
// 全局Tips开启
await GlobalTipsManager().setEnabled(true);
// 震动反馈开启不需要保存到SharedPreferences直接更新状态
setState(() {
_vibrationEnabled = true;
_globalTipsEnabled = true; // 全局Tips开启
});
_showSnackBar('已恢复默认设置');
},
child: Text('确定', style: TextStyle(color: Colors.red[400])),
),
],
),
);
}
}
// - 自动刷新:关闭
// - 调试信息:关闭
// - 预加载:开启
// - 隐藏次要按钮:关闭
// - 声音反馈:关闭
// - 震动反馈:开启
// - 全局Tips开启
// - tap