import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../data/providers.dart'; import '../../data/state/app_interaction_state.dart'; import '../../routing/app_routes.dart'; import '../../theme/app_icons.dart'; import '../../theme/theme_controller.dart'; import '../../theme/yanting_text.dart'; import '../../theme/yanting_tokens.dart'; import '../../widgets/app_card.dart'; import '../../widgets/page_header.dart'; import '../../widgets/sheets.dart'; class SettingsPage extends ConsumerWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final themeMode = ref.watch(themeModeProvider); final scheme = ShadTheme.of(context).colorScheme; return Scaffold( appBar: AppBar( leading: IconButton( icon: const Icon(AppIcons.arrowLeft), onPressed: () { if (context.canPop()) { context.pop(); } else { context.go(AppRoutes.home); } }, ), title: const Text('设置 · Settings'), ), body: ListView( padding: const EdgeInsets.fromLTRB( YantingSpacing.screenX, 4, YantingSpacing.screenX, 20, ), children: [ const PageHeader(title: '设置', subtitle: '统一外观、主题和常用入口'), Text('外观', style: YantingText.sectionTitle), const SizedBox(height: 12), AppCard( padding: EdgeInsets.zero, child: Column( children: [ _ThemeModeTile( label: '跟随系统', description: '按系统深浅色自动切换', selected: themeMode == ThemeMode.system, onTap: () => ref .read(themeModeProvider.notifier) .setMode(ThemeMode.system), ), const Divider(height: 1, thickness: 1), _ThemeModeTile( label: '浅色', description: '稳定的浅色展示模式', selected: themeMode == ThemeMode.light, onTap: () => ref .read(themeModeProvider.notifier) .setMode(ThemeMode.light), ), const Divider(height: 1, thickness: 1), _ThemeModeTile( label: '深色', description: '适合低光环境阅读', selected: themeMode == ThemeMode.dark, onTap: () => ref .read(themeModeProvider.notifier) .setMode(ThemeMode.dark), ), ], ), ), const SizedBox(height: YantingSpacing.x3), Text('入口', style: YantingText.sectionTitle), const SizedBox(height: 12), AppCard( padding: EdgeInsets.zero, child: Column( children: [ _LinkTile( icon: Icons.description_outlined, title: '用户协议', onTap: () => _showOutbound( context, ref, 'settings_user_agreement', '用户协议', ), ), const Divider(height: 1, thickness: 1), _LinkTile( icon: Icons.privacy_tip_outlined, title: '隐私政策', onTap: () => _showOutbound( context, ref, 'settings_privacy_policy', '隐私政策', ), ), ], ), ), const SizedBox(height: YantingSpacing.x3), Text('关于', style: YantingText.sectionTitle), const SizedBox(height: 12), AppCard( color: scheme.secondary, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('研听', style: YantingText.cardTitle), const SizedBox(height: 6), Text( '全球机构研报中文解读', style: YantingText.meta.copyWith(fontSize: 12.5), ), const SizedBox(height: 12), Text( '主题、按钮、卡片和间距统一到 demo 的展示层基线。', style: YantingText.body.copyWith(fontSize: 14), ), const SizedBox(height: 14), Text( '当前版本以本地构建信息为准,发布时再注入正式版本号。', style: YantingText.meta.copyWith(fontSize: 12), ), ], ), ), ], ), ); } void _showOutbound( BuildContext context, WidgetRef ref, String scene, String title, ) { showOutboundSheet( context, title: title, onConfirm: () => ref .read(outboundRepositoryProvider) .recordOutbound(OutboundEvent(scene: scene)), ); } } class _ThemeModeTile extends StatelessWidget { const _ThemeModeTile({ required this.label, required this.description, required this.selected, required this.onTap, }); final String label; final String description; final bool selected; final VoidCallback onTap; @override Widget build(BuildContext context) { final scheme = ShadTheme.of(context).colorScheme; final foreground = selected ? scheme.background : scheme.foreground; final muted = scheme.mutedForeground; return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: YantingText.body.copyWith( color: scheme.foreground, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 4), Text( description, style: YantingText.meta.copyWith( color: muted, fontSize: 12.5, ), ), ], ), ), const SizedBox(width: 12), DecoratedBox( decoration: BoxDecoration( color: selected ? scheme.foreground : scheme.secondary, borderRadius: BorderRadius.circular(YantingRadius.pill), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 5), child: Icon( selected ? Icons.check : Icons.radio_button_unchecked, size: 16, color: foreground, ), ), ), ], ), ), ); } } class _LinkTile extends StatelessWidget { const _LinkTile({ required this.icon, required this.title, required this.onTap, }); final IconData icon; final String title; final VoidCallback onTap; @override Widget build(BuildContext context) { return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15), child: Row( children: [ Icon( icon, size: 20, color: ShadTheme.of(context).colorScheme.foreground, ), const SizedBox(width: 13), Expanded( child: Text( title, style: YantingText.body.copyWith( color: ShadTheme.of(context).colorScheme.foreground, ), ), ), const Icon(AppIcons.arrowRight, size: 18), ], ), ), ); } }