This commit is contained in:
Developer
2026-04-03 03:26:06 +08:00
parent 3063deb34c
commit cba04235c8
49 changed files with 3955 additions and 1421 deletions

View File

@@ -51,6 +51,7 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
Future<void> _loadSettings() async {
final prefs = await SharedPreferences.getInstance();
await GlobalTipsManager().init();
await AudioManager().init(); // 确保 AudioManager 已初始化
if (mounted) {
setState(() {
_autoRefreshEnabled = prefs.getBool(_autoRefreshKey) ?? false;
@@ -62,6 +63,8 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
_hideSecondaryButtons =
prefs.getBool(_hideSecondaryButtonsKey) ?? false; // 加载隐藏次要按钮状态
});
// 同步到 AudioManager
AudioManager().setMuted(!_soundEnabled);
}
}
@@ -101,7 +104,7 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_soundEnabledKey, value);
// 更新 AudioManager 的静音状态
AudioManager().setMuted(!value);
await AudioManager().setMuted(!value);
if (mounted) {
setState(() {
_soundEnabled = value;
@@ -506,60 +509,53 @@ class _AppFunSettingsPageState extends State<AppFunSettingsPage> {
final primaryColor = _themeController.currentThemeColor;
return Obx(() {
final currentIndex = _glassController.transparencyLevelIndex;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Row(
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: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(8),
Text(
'高透级别',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white : Colors.black,
),
child: Icon(Icons.opacity, color: primaryColor, size: 20),
),
const SizedBox(width: 12),
Expanded(
child: 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],
),
),
],
Text(
'当前: ${_glassController.transparencyLevelLabel}',
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey[600],
),
),
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 12),
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),
],
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),
],
),
),
),
],
],
),
);
});
}

View File

@@ -212,30 +212,18 @@ class LearnUsPage extends StatelessWidget {
),
),
const SizedBox(height: 12),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[50],
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: isDark
? Colors.grey[700]!.withAlpha(20)
: Colors.grey.withAlpha(20),
),
),
child: Row(
children: [
Icon(Icons.link, size: 16, color: primaryColor),
const SizedBox(width: 8),
Expanded(
child: Text(
'https://poe.vogov.cn/app.html',
style: TextStyle(fontSize: 14, color: primaryColor),
),
),
],
),
_buildWebsiteItem(
'https://poe.vogov.cn/app.html',
'官方APP页',
isDark,
primaryColor,
),
const SizedBox(height: 12),
_buildWebsiteItem(
'https://poe.vogov.cn/',
'情景诗词在线版',
isDark,
primaryColor,
),
],
),
@@ -245,6 +233,71 @@ class LearnUsPage extends StatelessWidget {
);
}
Widget _buildWebsiteItem(
String url,
String label,
bool isDark,
Color primaryColor,
) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: isDark ? const Color(0xFF3A3A3A) : Colors.grey[50],
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: isDark
? Colors.grey[700]!.withAlpha(20)
: Colors.grey.withAlpha(20),
),
),
child: Row(
children: [
Icon(Icons.link, size: 16, color: primaryColor),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.grey[400] : Colors.grey,
),
),
Text(url, style: TextStyle(fontSize: 14, color: primaryColor)),
],
),
),
const SizedBox(width: 8),
GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(text: url));
Get.snackbar(
'复制成功',
'链接已复制到剪贴板',
duration: const Duration(seconds: 2),
colorText: primaryColor,
snackPosition: SnackPosition.BOTTOM,
borderRadius: 8,
margin: const EdgeInsets.all(16),
);
},
child: Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
color: primaryColor.withAlpha(10),
borderRadius: BorderRadius.circular(4),
),
child: Icon(Icons.content_copy, size: 16, color: primaryColor),
),
),
],
),
);
}
Widget _buildQQGroupCard(BuildContext context, bool isDark) {
final themeController = Get.find<ThemeController>();
final primaryColor = themeController.currentThemeColor;
@@ -352,20 +405,15 @@ class LearnUsPage extends StatelessWidget {
final primaryColor = themeController.currentThemeColor;
Clipboard.setData(const ClipboardData(text: '271129018'));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(
children: [
Icon(Icons.check_circle, color: Colors.white, size: 20),
SizedBox(width: 8),
Text('QQ群号已复制到剪贴板'),
],
),
backgroundColor: primaryColor,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
duration: const Duration(seconds: 2),
),
Get.snackbar(
'复制成功',
'QQ群号已复制到剪贴板',
duration: const Duration(seconds: 2),
colorText: primaryColor,
snackPosition: SnackPosition.BOTTOM,
borderRadius: 8,
margin: const EdgeInsets.all(16),
icon: Icon(Icons.check_circle, color: primaryColor, size: 20),
);
}
@@ -572,14 +620,21 @@ class LearnUsPage extends StatelessWidget {
const SizedBox(width: 8),
GestureDetector(
onTap: () {
final themeController =
Get.find<ThemeController>();
final primaryColor =
themeController.currentThemeColor;
Clipboard.setData(
const ClipboardData(text: '微风暴'),
);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('已复制到剪贴板'),
duration: Duration(seconds: 2),
),
Get.snackbar(
'复制成功',
'已复制到剪贴板',
duration: const Duration(seconds: 2),
colorText: primaryColor,
snackPosition: SnackPosition.BOTTOM,
borderRadius: 8,
margin: const EdgeInsets.all(16),
);
},
child: Icon(
@@ -734,6 +789,8 @@ class LearnUsPage extends StatelessWidget {
}
Widget _buildIcpCard(BuildContext context, bool isDark) {
final themeController = Get.find<ThemeController>();
final primaryColor = themeController.currentThemeColor;
return Container(
decoration: BoxDecoration(
color: isDark ? const Color(0xFF2A2A2A) : Colors.white,
@@ -794,6 +851,7 @@ class LearnUsPage extends StatelessWidget {
'复制成功',
'备案号已复制到剪贴板',
duration: const Duration(seconds: 1),
colorText: primaryColor,
);
},
child: Row(

View File

@@ -85,14 +85,12 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
) ??
[];
if (existingData.length >= 500) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('缓存已达上限500条请先清空缓存'),
backgroundColor: Colors.red,
),
);
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'提示',
'缓存已达上限500条请先清空缓存',
colorText: themeController.currentThemeColor,
);
return;
}
@@ -100,23 +98,24 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
if (_selectedCount == 100) {
final isUserPlanJoined = await _checkUserPlanStatus();
if (!isUserPlanJoined) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('100条下载需要加入用户体验计划'),
backgroundColor: Colors.orange,
action: SnackBarAction(
label: '去加入',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const UserPlanPage()),
);
},
),
final themeController = Get.find<ThemeController>();
Get.snackbar(
'提示',
'100条下载需要加入用户体验计划',
colorText: themeController.currentThemeColor,
mainButton: TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => const UserPlanPage()),
);
},
child: Text(
'去加入',
style: TextStyle(color: themeController.currentThemeColor),
),
);
}
),
);
return;
}
}
@@ -149,14 +148,12 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
// 取消时保存已下载的数据
if (_downloadedCount > 0) {
await prefs.setStringList(dataKey, currentData);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('已保存 $_downloadedCount 条数据'),
backgroundColor: _themeController.currentThemeColor,
),
);
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'提示',
'已保存 $_downloadedCount 条数据',
colorText: themeController.currentThemeColor,
);
}
return;
}
@@ -240,17 +237,15 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
// 检查总缓存数量
if (currentData.length > 500) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('缓存将超过500条上限请先清空缓存'),
backgroundColor: Colors.red,
),
);
setState(() {
_isLoading = false;
});
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'提示',
'缓存将超过500条上限请先清空缓存',
colorText: themeController.currentThemeColor,
);
setState(() {
_isLoading = false;
});
return;
}
@@ -260,13 +255,12 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
_cachedCount = currentData.length;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'成功缓存 ${_selectedType == DownloadType.poetry ? '诗词' : '答题'} $_cachedCount 条数据',
),
backgroundColor: _themeController.currentThemeColor,
),
final themeController = Get.find<ThemeController>();
final themeController2 = Get.find<ThemeController>();
Get.snackbar(
'成功',
'成功缓存 ${_selectedType == DownloadType.poetry ? '诗词' : '答题'} $_cachedCount 条数据',
colorText: themeController2.currentThemeColor,
);
}
} catch (e) {
@@ -275,8 +269,11 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
_status = '下载失败: $e';
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('下载失败: $e'), backgroundColor: Colors.red),
final themeController = Get.find<ThemeController>();
Get.snackbar(
'错误',
'下载失败: $e',
colorText: themeController.currentThemeColor,
);
}
} finally {
@@ -297,14 +294,12 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
final quizCount = (prefs.getStringList('offline_quiz_data') ?? []).length;
if (poetryCount == 0 && quizCount == 0) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('暂无缓存数据'),
backgroundColor: Colors.orange,
),
);
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'提示',
'暂无缓存数据',
colorText: themeController.currentThemeColor,
);
return;
}
@@ -367,14 +362,12 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
final prefs = await SharedPreferences.getInstance();
await prefs.remove(key);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('已清空$typeName离线数据'),
backgroundColor: _themeController.currentThemeColor,
),
);
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'成功',
'已清空$typeName离线数据',
colorText: themeController.currentThemeColor,
);
// 更新对应的计数
if (key == 'offline_poetry_data') {
@@ -399,14 +392,12 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
await prefs.remove('offline_poetry_data');
await prefs.remove('offline_quiz_data');
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('已清空所有离线数据'),
backgroundColor: _themeController.currentThemeColor,
),
);
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'成功',
'已清空所有离线数据',
colorText: themeController.currentThemeColor,
);
setState(() {
_poetryCount = 0;
@@ -455,55 +446,47 @@ class _OfflineDataPageState extends State<OfflineDataPage> {
if (data['status'] == 'success') {
_displayServerInfoDialog(data);
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('服务器返回错误状态: ${data['status']}'),
backgroundColor: Colors.red,
duration: const Duration(seconds: 3),
),
);
}
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('解析服务器数据失败: $e'),
backgroundColor: Colors.red,
duration: const Duration(seconds: 3),
),
final themeController = Get.find<ThemeController>();
Get.snackbar(
'错误',
'服务器返回错误状态: ${data['status']}',
colorText: themeController.currentThemeColor,
duration: const Duration(seconds: 3),
);
}
}
} else {
if (mounted) {
final errorMsg =
'获取服务器信息失败\n'
'状态码: ${response.statusCode}\n'
'消息: ${response.message}';
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(errorMsg),
backgroundColor: Colors.red,
duration: const Duration(seconds: 5),
),
} catch (e) {
final themeController = Get.find<ThemeController>();
Get.snackbar(
'错误',
'解析服务器数据失败: $e',
colorText: themeController.currentThemeColor,
duration: const Duration(seconds: 3),
);
}
} else {
final errorMsg =
'获取服务器信息失败\n'
'状态码: ${response.statusCode}\n'
'消息: ${response.message}';
final themeController = Get.find<ThemeController>();
Get.snackbar(
'错误',
errorMsg,
colorText: themeController.currentThemeColor,
duration: const Duration(seconds: 5),
);
}
} catch (e) {
if (!mounted) return;
Navigator.of(context).pop();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('获取服务器信息异常: $e'),
backgroundColor: Colors.red,
duration: const Duration(seconds: 5),
),
);
}
final themeController = Get.find<ThemeController>();
Get.snackbar(
'错误',
'获取服务器信息异常: $e',
colorText: themeController.currentThemeColor,
duration: const Duration(seconds: 5),
);
}
}