release
This commit is contained in:
@@ -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),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user