import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:social_app/core/constants/app_constants.dart'; import 'package:social_app/core/di/injection.dart'; import 'package:social_app/core/theme/design_tokens.dart'; import 'package:social_app/shared/widgets/app_loading_indicator.dart'; import 'package:social_app/shared/widgets/toast/toast.dart'; import 'package:social_app/shared/widgets/toast/toast_type.dart'; import 'package:social_app/shared/utils/phone_display_formatter.dart'; import 'package:social_app/features/friends/data/friends_api.dart'; import 'package:social_app/features/settings/data/settings_api.dart'; import 'package:social_app/features/users/data/models/user_response.dart'; import 'package:social_app/features/users/data/users_api.dart'; import '../widgets/settings_page_scaffold.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { UserResponse? _user; bool _isLoading = true; int _friendsCount = 0; String? _firstFriendName; @override void initState() { super.initState(); _loadData(); } Future _loadData() async { try { final usersApi = sl(); final friendsApi = sl(); final results = await Future.wait([ usersApi.getMe(), friendsApi.getFriends(), ]); final user = results[0] as UserResponse; final friends = results[1] as List; if (mounted) { setState(() { _user = user; _friendsCount = friends.length; _firstFriendName = friends.isNotEmpty ? friends.first.friend.username : null; _isLoading = false; }); } } catch (e) { if (mounted) { setState(() { _isLoading = false; }); } } } @override Widget build(BuildContext context) { return SettingsPageScaffold( title: '设置', onBack: () => context.pop(), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildProfileHero(), const SizedBox(height: 16), _buildQuickActions(context), const SizedBox(height: 16), _buildSubscriptionCard(), const SizedBox(height: 16), _buildMenuCard(context), ], ), ); } Widget _buildProfileHero() { if (_isLoading) { return Container( width: double.infinity, height: 120, padding: const EdgeInsets.all(AppSpacing.xl), decoration: BoxDecoration( color: AppColors.white, borderRadius: BorderRadius.circular(24), ), child: const Center(child: AppLoadingIndicator(size: 22)), ); } final username = _user?.username ?? '未设置'; final phone = _user?.phone == null ? '未设置' : formatPhoneForDisplay(_user?.phone); return Container( width: double.infinity, padding: const EdgeInsets.all(AppSpacing.xl), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.white, Color(0xF8F9FCFF)], ), borderRadius: BorderRadius.circular(24), border: Border.all(color: AppColors.borderSecondary), boxShadow: const [ BoxShadow( color: Color(0x05000000), blurRadius: 12, offset: Offset(0, 3), ), ], ), child: Row( children: [ Container( width: 64, height: 64, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.blue100, AppColors.blue50], ), borderRadius: BorderRadius.circular(32), boxShadow: [ BoxShadow( color: Color.fromRGBO( AppColors.blue400.r.toInt(), AppColors.blue400.g.toInt(), AppColors.blue400.b.toInt(), 0.2, ), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: const Icon(Icons.person, size: 28, color: AppColors.blue600), ), const SizedBox(width: AppSpacing.lg), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( child: Text( username, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: AppColors.slate900, ), overflow: TextOverflow.ellipsis, ), ), Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 5, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.blue50, AppColors.surfaceInfoLight, ], ), borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.borderQuaternary), ), child: const Text( 'Free', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: AppColors.blue600, ), ), ), ], ), const SizedBox(height: 6), Text( phone, style: TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: AppColors.slate500, ), ), ], ), ), ], ), ); } String _buildFriendsSubtitle() { if (_friendsCount == 0) { return '暂无联系人'; } if (_friendsCount == 1) { return '已添加 1 位:$_firstFriendName'; } return '已添加 $_friendsCount 位联系人'; } Widget _buildQuickActions(BuildContext context) { return Row( children: [ Expanded( child: _buildActionCard( icon: Icons.people, iconColor: AppColors.blue500, title: '联系人', subtitle: _buildFriendsSubtitle(), onTap: () => context.push('/contacts'), ), ), const SizedBox(width: AppSpacing.md), Expanded( child: _buildActionCard( icon: Icons.auto_awesome, iconColor: const Color(0xFF8B5CF6), title: '周期计划', subtitle: '已启用:会议提醒', onTap: () => context.push('/settings/features'), ), ), ], ); } Widget _buildActionCard({ required IconData icon, required Color iconColor, required String title, required String subtitle, required VoidCallback onTap, }) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(AppSpacing.lg), decoration: BoxDecoration( color: AppColors.white, borderRadius: BorderRadius.circular(20), border: Border.all(color: AppColors.borderSecondary), boxShadow: const [ BoxShadow( color: Color(0x04000000), blurRadius: 6, offset: Offset(0, 1), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 36, height: 36, decoration: BoxDecoration( color: AppColors.surfaceTertiary, borderRadius: BorderRadius.circular(10), ), child: Icon(icon, size: 18, color: iconColor), ), const Spacer(), Icon(Icons.chevron_right, size: 16, color: AppColors.slate300), ], ), const SizedBox(height: AppSpacing.md), Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.slate900, ), ), const SizedBox(height: 2), Text( subtitle, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: AppColors.slate500, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), ); } Widget _buildSubscriptionCard() { return Container( padding: const EdgeInsets.all(AppSpacing.lg), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.white, const Color(0xFFFAFBFF)], ), borderRadius: BorderRadius.circular(20), border: Border.all(color: AppColors.borderSecondary), boxShadow: const [ BoxShadow( color: Color(0x03000000), blurRadius: 6, offset: Offset(0, 1), ), ], ), child: Row( children: [ Container( width: 44, height: 44, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.blue100, AppColors.blue50], ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppColors.blue200.withValues(alpha: 0.45), blurRadius: 6, offset: const Offset(0, 1), ), ], ), child: const Icon( Icons.workspace_premium, size: 22, color: AppColors.blue600, ), ), const SizedBox(width: AppSpacing.md), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '升级到 Pro', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.slate900, ), ), const SizedBox(height: 2), Text( '解锁更多高级功能', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: AppColors.slate500, ), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( gradient: const LinearGradient( colors: [AppColors.blue500, AppColors.blue600], ), borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: const Color(0x4D60A5FA), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: const Text( '升级', style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: AppColors.white, ), ), ), ], ), ); } Widget _buildMenuCard(BuildContext context) { return Container( decoration: BoxDecoration( color: AppColors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.borderSecondary), ), child: Column( children: [ _buildMenuItem( icon: Icons.notifications, title: '提醒设置', onTap: () {}, ), _buildDivider(), _buildMenuItem( icon: Icons.bookmark, title: '我的记忆', onTap: () => context.push('/settings/memory'), ), _buildDivider(), _buildMenuItem( icon: Icons.person, title: '我的账户', onTap: () => context.push('/settings/account'), ), _buildDivider(), _buildMenuItem( icon: Icons.system_update, title: '检查更新', trailing: 'v${AppConstants.version}', onTap: _checkForUpdates, ), ], ), ); } Widget _buildMenuItem({ required IconData icon, required String title, String? trailing, required VoidCallback onTap, }) { return GestureDetector( onTap: onTap, behavior: HitTestBehavior.opaque, child: Container( height: 56, padding: const EdgeInsets.symmetric(horizontal: 14), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon(icon, size: 20, color: AppColors.slate500), const SizedBox(width: 10), Text( title, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.slate900, ), ), ], ), Row( children: [ if (trailing != null) ...[ Text( trailing, style: const TextStyle( fontSize: 14, color: AppColors.slate400, ), ), const SizedBox(width: 6), ], const Icon( Icons.chevron_right, size: 18, color: AppColors.slate400, ), ], ), ], ), ), ); } Widget _buildDivider() { return Container( height: 1, margin: const EdgeInsets.symmetric(horizontal: 14), color: AppColors.slate100, ); } Future _checkForUpdates() async { try { final settingsApi = sl(); final result = await settingsApi.checkUpdates( currentVersionCode: AppConstants.build, currentVersionName: AppConstants.version, platform: 'android', ); if (!mounted) return; if (!result.hasUpdate) { Toast.show(context, '当前已是最新版本', type: ToastType.success); return; } final message = result.updateType == 'required' ? '有新版本可用 (${result.latestVersionName}),请立即更新' : '发现新版本 (${result.latestVersionName}),是否更新?'; final shouldUpdate = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('检查更新'), content: Text(message), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), if (result.downloadUrl != null) TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('更新'), ), ], ), ); if (shouldUpdate == true && result.downloadUrl != null && mounted) { Toast.show( context, '下载链接: ${result.downloadUrl}', type: ToastType.info, ); } } catch (e) { if (!mounted) return; Toast.show(context, '检查更新失败', type: ToastType.error); } } }