828 lines
27 KiB
Dart
828 lines
27 KiB
Dart
/// ============================================================
|
||
/// 闲言APP — 其他设置页面
|
||
/// 创建时间: 2026-05-23
|
||
/// 更新时间: 2026-05-26
|
||
/// 作用: 承载从通用设置和更多设置中拆出的低频/高级设置项
|
||
/// 上次更新: 完善导出/导入设置交互,支持文件选择和确认对话框
|
||
/// ============================================================
|
||
|
||
import 'dart:io';
|
||
|
||
import 'package:flutter/cupertino.dart';
|
||
import 'package:flutter/material.dart' show Divider;
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:file_picker/file_picker.dart';
|
||
|
||
import '../../../../core/router/app_routes.dart';
|
||
import '../../../../core/router/app_nav_extension.dart';
|
||
import '../../../../core/services/data/data_export_service.dart';
|
||
import '../../../../core/services/data/settings_export_service.dart';
|
||
import '../../../../core/services/device/haptic_service.dart';
|
||
import '../../../../core/services/accessibility/accessibility_service.dart';
|
||
import '../../../../core/theme/app_theme.dart';
|
||
import '../../../../core/theme/app_spacing.dart';
|
||
import '../../../../core/theme/app_typography.dart';
|
||
import '../../../../core/theme/app_radius.dart';
|
||
import '../../../../core/utils/logger.dart';
|
||
import '../../../../shared/widgets/adaptive/adaptive_back_button.dart';
|
||
import '../providers/general_settings_provider.dart';
|
||
import '../services/settings_change_logger.dart';
|
||
import 'shared/settings_tiles.dart';
|
||
|
||
class OtherSettingsPage extends ConsumerStatefulWidget {
|
||
const OtherSettingsPage({super.key});
|
||
|
||
@override
|
||
ConsumerState<OtherSettingsPage> createState() => _OtherSettingsPageState();
|
||
}
|
||
|
||
class _OtherSettingsPageState extends ConsumerState<OtherSettingsPage> {
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final ext = AppTheme.ext(context);
|
||
final settings = ref.watch(generalSettingsProvider);
|
||
|
||
return CupertinoPageScaffold(
|
||
backgroundColor: ext.bgPrimary,
|
||
navigationBar: CupertinoNavigationBar(
|
||
leading: const AdaptiveBackButton(),
|
||
middle: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(CupertinoIcons.gear_solid, size: 18, color: ext.accent),
|
||
const SizedBox(width: 6),
|
||
Text(
|
||
'其他设置',
|
||
style: AppTypography.title3.copyWith(color: ext.textPrimary),
|
||
),
|
||
],
|
||
),
|
||
backgroundColor: ext.bgElevated.withValues(alpha: 0.85),
|
||
border: null,
|
||
),
|
||
child: SafeArea(
|
||
child: ListView(
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: AppSpacing.md,
|
||
vertical: AppSpacing.sm,
|
||
),
|
||
children: [
|
||
_buildAdvancedSection(ext, settings),
|
||
const SizedBox(height: AppSpacing.md),
|
||
_buildAccessibilitySection(ext, settings),
|
||
const SizedBox(height: AppSpacing.md),
|
||
_buildBatteryStorageSection(ext, settings),
|
||
const SizedBox(height: AppSpacing.xl),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
// ── 分组1: 高级设置 ──
|
||
|
||
Widget _buildAdvancedSection(
|
||
AppThemeExtension ext,
|
||
GeneralSettingsState settings,
|
||
) {
|
||
return SettingsSectionCard(
|
||
header: '高级设置',
|
||
icon: CupertinoIcons.wrench_fill,
|
||
children: [
|
||
SettingsNavigationTile(
|
||
icon: CupertinoIcons.ellipsis_circle,
|
||
iconColor: const Color(0xFF8E8E93),
|
||
title: '更多设置',
|
||
subtitle: '内容搜索、存储管理等',
|
||
onTap: () {
|
||
HapticService.light();
|
||
context.appPush(AppRoutes.moreSettings);
|
||
},
|
||
),
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.arrow_clockwise,
|
||
iconColor: const Color(0xFF8E8E93),
|
||
title: '自动检查更新',
|
||
subtitle: '启动时自动检查新版本',
|
||
value: settings.autoCheckUpdate,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref.read(generalSettingsProvider.notifier).setAutoCheckUpdate(v);
|
||
},
|
||
),
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.arrow_up_arrow_down_circle_fill,
|
||
iconColor: const Color(0xFF8E8E93),
|
||
title: '同步设置',
|
||
subtitle: '跨设备同步设置数据',
|
||
value: settings.syncEnabled,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref.read(generalSettingsProvider.notifier).setSyncEnabled(v);
|
||
},
|
||
),
|
||
SettingsNavigationTile(
|
||
icon: CupertinoIcons.list_bullet,
|
||
iconColor: const Color(0xFFFF9500),
|
||
title: '日志管理',
|
||
subtitle: '查看和管理应用日志',
|
||
trailing: '${Log.entryCount} 条',
|
||
onTap: () {
|
||
HapticService.light();
|
||
context.appPush(AppRoutes.logViewer);
|
||
},
|
||
),
|
||
SettingsNavigationTile(
|
||
icon: CupertinoIcons.doc_text_search,
|
||
iconColor: const Color(0xFF5856D6),
|
||
title: '设置变更日志',
|
||
subtitle: '查看设置修改记录',
|
||
trailing: '${SettingsChangeLogger.entries.length} 条',
|
||
onTap: () {
|
||
HapticService.light();
|
||
_showSettingsChangeLog(ext);
|
||
},
|
||
),
|
||
SettingsActionTile(
|
||
icon: CupertinoIcons.arrow_up_arrow_down_circle_fill,
|
||
iconColor: const Color(0xFF5AC8FA),
|
||
title: '导出/导入设置',
|
||
subtitle: '备份或恢复设置数据',
|
||
onTap: () => _showExportImportSheet(ext),
|
||
),
|
||
SettingsActionTile(
|
||
icon: CupertinoIcons.square_arrow_up_fill,
|
||
iconColor: const Color(0xFF30D158),
|
||
title: '数据导出',
|
||
subtitle: '导出应用数据为文件',
|
||
onTap: () => _showDataExportDialog(ext),
|
||
),
|
||
SettingsActionTile(
|
||
icon: CupertinoIcons.trash_fill,
|
||
iconColor: const Color(0xFFFF9500),
|
||
title: '清理缓存',
|
||
subtitle: '清理临时缓存数据 (${settings.cacheSizeText})',
|
||
onTap: () => _showClearCacheDialog(ext),
|
||
),
|
||
SettingsActionTile(
|
||
icon: CupertinoIcons.exclamationmark_triangle_fill,
|
||
iconColor: const Color(0xFFFF3B30),
|
||
title: '重置设置',
|
||
subtitle: '恢复所有设置为默认值',
|
||
isDestructive: true,
|
||
onTap: () => _showResetDialog(ext),
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// ── 分组2: 辅助功能 ──
|
||
|
||
Widget _buildAccessibilitySection(
|
||
AppThemeExtension ext,
|
||
GeneralSettingsState settings,
|
||
) {
|
||
return SettingsSectionCard(
|
||
header: '辅助功能',
|
||
icon: CupertinoIcons.hand_raised_fill,
|
||
children: [
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.circle_lefthalf_fill,
|
||
iconColor: const Color(0xFF8E8E93),
|
||
title: '高对比度',
|
||
subtitle: '增强界面元素对比度',
|
||
value: settings.highContrastEnabled,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref
|
||
.read(generalSettingsProvider.notifier)
|
||
.setHighContrastEnabled(v);
|
||
},
|
||
),
|
||
SettingsSelectionTile(
|
||
icon: CupertinoIcons.eye_fill,
|
||
iconColor: const Color(0xFF30D158),
|
||
title: '色弱适配',
|
||
subtitle: '调整色彩以适配色弱用户',
|
||
value: settings.colorWeakType.label,
|
||
onTap: () => _showColorWeakPicker(settings),
|
||
),
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.textformat_abc,
|
||
iconColor: const Color(0xFF5856D6),
|
||
title: '文字加粗',
|
||
subtitle: '增强文字显示粗细',
|
||
value: settings.boldTextEnabled,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref.read(generalSettingsProvider.notifier).setBoldTextEnabled(v);
|
||
},
|
||
),
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.eye_fill,
|
||
iconColor: const Color(0xFFAF52DE),
|
||
title: '语义调试',
|
||
subtitle: '显示语义标注覆盖层,辅助开发无障碍适配',
|
||
value: settings.semanticsDebugEnabled,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref
|
||
.read(generalSettingsProvider.notifier)
|
||
.setSemanticsDebugEnabled(v);
|
||
AccessibilityService.instance.setSemanticsDebug(v);
|
||
},
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// ── 分组3: 电池与存储 ──
|
||
|
||
Widget _buildBatteryStorageSection(
|
||
AppThemeExtension ext,
|
||
GeneralSettingsState settings,
|
||
) {
|
||
return SettingsSectionCard(
|
||
header: '电池与存储',
|
||
icon: CupertinoIcons.battery_25,
|
||
children: [
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.battery_25,
|
||
iconColor: const Color(0xFF34C759),
|
||
title: '电池优化',
|
||
subtitle: '低电量自动开启省流模式',
|
||
value: settings.batteryOptimizationEnabled,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref
|
||
.read(generalSettingsProvider.notifier)
|
||
.setBatteryOptimizationEnabled(v);
|
||
},
|
||
),
|
||
SettingsSwitchTile(
|
||
icon: CupertinoIcons.arrow_clockwise,
|
||
iconColor: ext.accent,
|
||
title: '后台刷新',
|
||
subtitle: '后台获取新内容',
|
||
value: settings.backgroundRefreshEnabled,
|
||
onChanged: (v) {
|
||
HapticService.toggleSwitch();
|
||
ref
|
||
.read(generalSettingsProvider.notifier)
|
||
.setBackgroundRefreshEnabled(v);
|
||
},
|
||
),
|
||
SettingsNavigationTile(
|
||
icon: CupertinoIcons.folder_fill,
|
||
iconColor: const Color(0xFFFF9500),
|
||
title: '存储管理',
|
||
subtitle: '管理缓存和数据存储',
|
||
onTap: () {
|
||
HapticService.light();
|
||
context.appPush(AppRoutes.dataManagement);
|
||
},
|
||
),
|
||
],
|
||
);
|
||
}
|
||
|
||
// ============================================================
|
||
// 选择器弹窗
|
||
// ============================================================
|
||
|
||
void _showColorWeakPicker(GeneralSettingsState settings) {
|
||
final ext = AppTheme.ext(context);
|
||
HapticService.selection();
|
||
|
||
showCupertinoModalPopup<void>(
|
||
context: context,
|
||
builder: (ctx) => Container(
|
||
height: 260,
|
||
decoration: BoxDecoration(
|
||
color: ext.bgElevated,
|
||
borderRadius: const BorderRadius.vertical(top: Radius.circular(14)),
|
||
),
|
||
child: Column(
|
||
children: [
|
||
Padding(
|
||
padding: const EdgeInsets.all(AppSpacing.md),
|
||
child: Text(
|
||
'色弱适配',
|
||
style: AppTypography.subhead.copyWith(
|
||
color: ext.textPrimary,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
),
|
||
const Divider(height: 1),
|
||
Expanded(
|
||
child: CupertinoPicker(
|
||
itemExtent: 40,
|
||
scrollController: FixedExtentScrollController(
|
||
initialItem: ColorWeakType.values
|
||
.indexWhere((e) => e.id == settings.colorWeakTypeId)
|
||
.clamp(0, ColorWeakType.values.length - 1),
|
||
),
|
||
onSelectedItemChanged: (i) {
|
||
ref
|
||
.read(generalSettingsProvider.notifier)
|
||
.setColorWeakType(ColorWeakType.values[i].id);
|
||
},
|
||
children: ColorWeakType.values
|
||
.map(
|
||
(e) => Center(
|
||
child: Text(
|
||
e.label,
|
||
style: AppTypography.body.copyWith(
|
||
color: ext.textPrimary,
|
||
),
|
||
),
|
||
),
|
||
)
|
||
.toList(),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
// ============================================================
|
||
// 操作对话框
|
||
// ============================================================
|
||
|
||
void _showClearCacheDialog(AppThemeExtension ext) {
|
||
HapticService.impact();
|
||
showCupertinoDialog<void>(
|
||
context: context,
|
||
builder: (ctx) => CupertinoAlertDialog(
|
||
title: const Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(CupertinoIcons.trash_fill, size: 18, color: Color(0xFFFF9500)),
|
||
SizedBox(width: 8),
|
||
Text('清理缓存'),
|
||
],
|
||
),
|
||
content: const Text('确定要清理所有临时缓存数据吗?'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
child: const Text('取消'),
|
||
onPressed: () => Navigator.pop(ctx),
|
||
),
|
||
CupertinoDialogAction(
|
||
isDestructiveAction: true,
|
||
child: const Text('清理'),
|
||
onPressed: () {
|
||
ref.read(generalSettingsProvider.notifier).clearCache();
|
||
Navigator.pop(ctx);
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showResetDialog(AppThemeExtension ext) {
|
||
HapticService.heavy();
|
||
showCupertinoDialog<void>(
|
||
context: context,
|
||
builder: (ctx) => CupertinoAlertDialog(
|
||
title: const Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(
|
||
CupertinoIcons.exclamationmark_triangle_fill,
|
||
size: 18,
|
||
color: Color(0xFFFF3B30),
|
||
),
|
||
SizedBox(width: 8),
|
||
Text('重置设置'),
|
||
],
|
||
),
|
||
content: const Text('确定要将所有设置恢复为默认值吗?此操作不可撤销。'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
child: const Text('取消'),
|
||
onPressed: () => Navigator.pop(ctx),
|
||
),
|
||
CupertinoDialogAction(
|
||
isDestructiveAction: true,
|
||
child: const Text('重置'),
|
||
onPressed: () {
|
||
ref.read(generalSettingsProvider.notifier).resetAll();
|
||
Navigator.pop(ctx);
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showExportImportSheet(AppThemeExtension ext) {
|
||
HapticService.light();
|
||
showCupertinoModalPopup<void>(
|
||
context: context,
|
||
builder: (ctx) => Container(
|
||
padding: const EdgeInsets.all(AppSpacing.lg),
|
||
decoration: BoxDecoration(
|
||
color: ext.bgElevated,
|
||
borderRadius: const BorderRadius.vertical(top: Radius.circular(14)),
|
||
),
|
||
child: SafeArea(
|
||
top: false,
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Text(
|
||
'📤 导出/导入设置',
|
||
style: AppTypography.headline.copyWith(
|
||
color: ext.textPrimary,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
const SizedBox(height: AppSpacing.sm),
|
||
Text(
|
||
'导出当前设置到JSON文件,或从文件恢复设置',
|
||
style: AppTypography.caption1.copyWith(
|
||
color: ext.textSecondary,
|
||
),
|
||
textAlign: TextAlign.center,
|
||
),
|
||
const SizedBox(height: AppSpacing.lg),
|
||
SizedBox(
|
||
width: double.infinity,
|
||
child: CupertinoButton(
|
||
color: ext.accent,
|
||
borderRadius: AppRadius.mdBorder,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
const Icon(
|
||
CupertinoIcons.square_arrow_up,
|
||
size: 18,
|
||
color: CupertinoColors.white,
|
||
),
|
||
const SizedBox(width: AppSpacing.sm),
|
||
Text(
|
||
'导出设置',
|
||
style: AppTypography.body.copyWith(
|
||
color: CupertinoColors.white,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
onPressed: () async {
|
||
Navigator.pop(ctx);
|
||
try {
|
||
await SettingsExportService.shareSettings();
|
||
} catch (e) {
|
||
if (mounted) {
|
||
_showMessage('导出失败: $e');
|
||
}
|
||
}
|
||
},
|
||
),
|
||
),
|
||
const SizedBox(height: AppSpacing.md),
|
||
SizedBox(
|
||
width: double.infinity,
|
||
child: CupertinoButton(
|
||
color: ext.bgSecondary,
|
||
borderRadius: AppRadius.mdBorder,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Icon(
|
||
CupertinoIcons.square_arrow_down,
|
||
size: 18,
|
||
color: ext.textPrimary,
|
||
),
|
||
const SizedBox(width: AppSpacing.sm),
|
||
Text(
|
||
'从文件导入',
|
||
style: AppTypography.body.copyWith(
|
||
color: ext.textPrimary,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
onPressed: () {
|
||
Navigator.pop(ctx);
|
||
_importFromFile(ext);
|
||
},
|
||
),
|
||
),
|
||
const SizedBox(height: AppSpacing.sm),
|
||
SizedBox(
|
||
width: double.infinity,
|
||
child: CupertinoButton(
|
||
color: ext.bgSecondary,
|
||
borderRadius: AppRadius.mdBorder,
|
||
child: Row(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: [
|
||
Icon(
|
||
CupertinoIcons.doc_on_clipboard,
|
||
size: 18,
|
||
color: ext.textPrimary,
|
||
),
|
||
const SizedBox(width: AppSpacing.sm),
|
||
Text(
|
||
'从剪贴板导入',
|
||
style: AppTypography.body.copyWith(
|
||
color: ext.textPrimary,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
onPressed: () {
|
||
Navigator.pop(ctx);
|
||
_showImportFromClipboardDialog(ext);
|
||
},
|
||
),
|
||
),
|
||
const SizedBox(height: AppSpacing.md),
|
||
CupertinoButton(
|
||
child: Text(
|
||
'取消',
|
||
style: AppTypography.body.copyWith(color: ext.textHint),
|
||
),
|
||
onPressed: () => Navigator.pop(ctx),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
void _importFromFile(AppThemeExtension ext) async {
|
||
HapticService.light();
|
||
try {
|
||
FilePickerResult? result;
|
||
try {
|
||
result = await FilePicker.pickFiles(
|
||
type: FileType.custom,
|
||
allowedExtensions: ['json'],
|
||
);
|
||
} catch (_) {
|
||
result = await FilePicker.pickFiles();
|
||
}
|
||
|
||
if (result == null || result.files.isEmpty) return;
|
||
|
||
final filePath = result.files.single.path;
|
||
if (filePath == null || filePath.isEmpty) {
|
||
if (mounted) _showMessage('文件路径无效');
|
||
return;
|
||
}
|
||
|
||
final file = File(filePath);
|
||
if (!await file.exists()) {
|
||
if (mounted) _showMessage('文件不存在');
|
||
return;
|
||
}
|
||
|
||
final jsonStr = await file.readAsString();
|
||
if (jsonStr.isEmpty) {
|
||
if (mounted) _showMessage('文件内容为空');
|
||
return;
|
||
}
|
||
|
||
if (!mounted) return;
|
||
_showImportConfirmDialog(ext, jsonStr);
|
||
} catch (e) {
|
||
Log.e('文件选择失败', e);
|
||
if (mounted) _showMessage('文件选择失败: $e');
|
||
}
|
||
}
|
||
|
||
void _showImportFromClipboardDialog(AppThemeExtension ext) {
|
||
final controller = TextEditingController();
|
||
showCupertinoDialog<void>(
|
||
context: context,
|
||
builder: (ctx) => CupertinoAlertDialog(
|
||
title: const Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(CupertinoIcons.doc_on_clipboard, size: 18),
|
||
SizedBox(width: 8),
|
||
Text('从剪贴板导入'),
|
||
],
|
||
),
|
||
content: Padding(
|
||
padding: const EdgeInsets.only(top: AppSpacing.sm),
|
||
child: CupertinoTextField(
|
||
controller: controller,
|
||
maxLines: 6,
|
||
placeholder: '粘贴导出的 JSON 数据',
|
||
style: AppTypography.caption1.copyWith(
|
||
color: ext.textPrimary,
|
||
fontFamily: 'monospace',
|
||
),
|
||
),
|
||
),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
child: const Text('取消'),
|
||
onPressed: () {
|
||
controller.dispose();
|
||
Navigator.pop(ctx);
|
||
},
|
||
),
|
||
CupertinoDialogAction(
|
||
isDefaultAction: true,
|
||
child: const Text('确认导入'),
|
||
onPressed: () {
|
||
final json = controller.text;
|
||
controller.dispose();
|
||
Navigator.pop(ctx);
|
||
if (json.isNotEmpty) {
|
||
_showImportConfirmDialog(ext, json);
|
||
}
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showImportConfirmDialog(AppThemeExtension ext, String jsonStr) {
|
||
HapticService.impact();
|
||
showCupertinoDialog<void>(
|
||
context: context,
|
||
builder: (ctx) => CupertinoAlertDialog(
|
||
title: const Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(
|
||
CupertinoIcons.exclamationmark_triangle_fill,
|
||
size: 18,
|
||
color: Color(0xFFFF9500),
|
||
),
|
||
SizedBox(width: 8),
|
||
Text('确认导入'),
|
||
],
|
||
),
|
||
content: const Text('导入设置将覆盖当前设置,此操作不可撤销。确定要继续吗?'),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
child: const Text('取消'),
|
||
onPressed: () => Navigator.pop(ctx),
|
||
),
|
||
CupertinoDialogAction(
|
||
isDestructiveAction: true,
|
||
child: const Text('导入'),
|
||
onPressed: () async {
|
||
Navigator.pop(ctx);
|
||
final success = await SettingsExportService.importFromJson(
|
||
jsonStr,
|
||
);
|
||
if (mounted) {
|
||
_showMessage(success ? '✅ 导入成功,设置已更新' : '❌ 导入失败,请检查文件格式');
|
||
if (success) {
|
||
ref.read(generalSettingsProvider.notifier).reload();
|
||
}
|
||
}
|
||
},
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showDataExportDialog(AppThemeExtension ext) {
|
||
HapticService.light();
|
||
try {
|
||
DataExportService.shareData();
|
||
} catch (e) {
|
||
if (mounted) {
|
||
_showMessage('数据导出失败: $e');
|
||
}
|
||
}
|
||
}
|
||
|
||
void _showSettingsChangeLog(AppThemeExtension ext) {
|
||
final entries = SettingsChangeLogger.entries;
|
||
showCupertinoDialog<void>(
|
||
context: context,
|
||
builder: (ctx) => CupertinoAlertDialog(
|
||
title: Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(CupertinoIcons.doc_text_search, size: 18, color: ext.accent),
|
||
const SizedBox(width: 8),
|
||
const Text('设置变更日志'),
|
||
],
|
||
),
|
||
content: SizedBox(
|
||
width: double.maxFinite,
|
||
height: 320,
|
||
child: entries.isEmpty
|
||
? Center(
|
||
child: Column(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: [
|
||
Icon(
|
||
CupertinoIcons.doc_text,
|
||
size: 36,
|
||
color: ext.textHint,
|
||
),
|
||
const SizedBox(height: AppSpacing.sm),
|
||
Text(
|
||
'暂无变更记录',
|
||
style: AppTypography.subhead.copyWith(
|
||
color: ext.textHint,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
)
|
||
: ListView.separated(
|
||
padding: EdgeInsets.zero,
|
||
shrinkWrap: true,
|
||
itemCount: entries.length,
|
||
separatorBuilder: (_, __) => const Divider(height: 1),
|
||
itemBuilder: (_, index) {
|
||
final entry = entries[index];
|
||
final time =
|
||
'${entry.changedAt.month}/${entry.changedAt.day} '
|
||
'${entry.changedAt.hour.toString().padLeft(2, '0')}:'
|
||
'${entry.changedAt.minute.toString().padLeft(2, '0')}';
|
||
return Padding(
|
||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
Row(
|
||
children: [
|
||
Text(
|
||
entry.key,
|
||
style: AppTypography.caption1.copyWith(
|
||
color: ext.accent,
|
||
fontWeight: FontWeight.w600,
|
||
),
|
||
),
|
||
const Spacer(),
|
||
Text(
|
||
time,
|
||
style: AppTypography.caption2.copyWith(
|
||
color: ext.textHint,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
const SizedBox(height: 2),
|
||
Text(
|
||
'${entry.oldValue} → ${entry.newValue}',
|
||
style: AppTypography.caption1.copyWith(
|
||
color: ext.textSecondary,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
},
|
||
),
|
||
),
|
||
actions: [
|
||
if (entries.isNotEmpty)
|
||
CupertinoDialogAction(
|
||
isDestructiveAction: true,
|
||
child: const Text('清空日志'),
|
||
onPressed: () async {
|
||
await SettingsChangeLogger.clear();
|
||
if (!context.mounted) return;
|
||
Navigator.pop(ctx);
|
||
setState(() {});
|
||
},
|
||
),
|
||
CupertinoDialogAction(
|
||
isDefaultAction: true,
|
||
child: const Text('关闭'),
|
||
onPressed: () => Navigator.pop(ctx),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
|
||
void _showMessage(String message) {
|
||
showCupertinoDialog<void>(
|
||
context: context,
|
||
builder: (ctx) => CupertinoAlertDialog(
|
||
content: Text(message),
|
||
actions: [
|
||
CupertinoDialogAction(
|
||
isDefaultAction: true,
|
||
child: const Text('好的'),
|
||
onPressed: () => Navigator.pop(ctx),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|