从 im-client-ios-swift-demo 搬运 Settings 逻辑,对齐 Gitea issue #5–#13 ## 基础设施 - AuthNotifier 新增 currentUid 字段,login() 接受 uid 参数 (#5) - LoginViewModel 登录成功后传入 user.uid - ApiPaths 补充 account/block/store 系列路径 - Tab 重命名"设置"→"我的",icon 改为 person_outline (#5) - AppRouteName 新增5条子路由 (edit-profile/blocklist/language/network-diagnostics/about) - app_router + auth_guard 同步注册新路由 ## Settings Feature - SettingsViewModel 重写为 NotifierProvider(去除 @riverpod 依赖) - build() 自动触发 loadProfile() - logout() 完整流程:API → WS 断开 → DB 关闭 → AuthNotifier - 6 个 navigateTo* 方法 - SettingsPage 完整 UI:资料卡 / 偏好设置 / 工具 / 关于 / 退出登录按钮 (#5 #7) - FetchProfileUseCase: GET /app/api/user/profile (#5) - LogoutUseCase: logout + disconnect + closeDatabase (#7) - UpdateProfileUseCase + UpdateProfileRequest: POST /app/api/user/update-profile (#6) - EditProfilePage + EditProfileViewModel: 昵称/bio 编辑 (#6) - LanguagePage: 语言选择 UI 框架,l10n_sdk 待接入 (#9) - BlocklistPage: 黑名单框架,API 待实现 (#10) - NetworkDiagnosticsPage + ViewModel: 四步诊断(连通/TCP/DNS/HTTPS)(#12) - AboutPage: 版本号 + 服务条款/隐私政策入口 (#13) - settings_providers.dart: 扩展 DI 装配 ## 文档 - Doc/mine_tab_architecture.md: 架构说明、数据流、路由、待完成事项 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
65 lines
2.0 KiB
Dart
65 lines
2.0 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
/// 语言设置页
|
||
///
|
||
/// 对应 Gitea issue #9
|
||
/// TODO: 接入 l10n_sdk,实现语言切换持久化
|
||
class LanguagePage extends StatefulWidget {
|
||
const LanguagePage({super.key});
|
||
|
||
@override
|
||
State<LanguagePage> createState() => _LanguagePageState();
|
||
}
|
||
|
||
class _LanguagePageState extends State<LanguagePage> {
|
||
/// TODO: 从 l10n_sdk / Locale 读取当前语言
|
||
String _selected = 'zh';
|
||
|
||
static const _languages = [
|
||
_LangOption(code: 'zh', label: '简体中文', nativeLabel: '简体中文'),
|
||
_LangOption(code: 'en', label: '英文', nativeLabel: 'English'),
|
||
_LangOption(code: 'zh-TW', label: '繁体中文', nativeLabel: '繁體中文'),
|
||
];
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: AppBar(title: const Text('语言')),
|
||
body: ListView.separated(
|
||
itemCount: _languages.length,
|
||
separatorBuilder: (_, __) => const Divider(height: 1, indent: 16),
|
||
itemBuilder: (context, index) {
|
||
final lang = _languages[index];
|
||
final isSelected = _selected == lang.code;
|
||
return ListTile(
|
||
title: Text(lang.nativeLabel),
|
||
subtitle: lang.label != lang.nativeLabel ? Text(lang.label) : null,
|
||
trailing: isSelected
|
||
? Icon(Icons.check, color: Theme.of(context).colorScheme.primary)
|
||
: null,
|
||
onTap: () {
|
||
setState(() => _selected = lang.code);
|
||
// TODO: ref.read(localeProvider.notifier).setLocale(lang.code)
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(content: Text('语言已切换为 ${lang.nativeLabel}(持久化待接入)')),
|
||
);
|
||
},
|
||
);
|
||
},
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
class _LangOption {
|
||
const _LangOption({
|
||
required this.code,
|
||
required this.label,
|
||
required this.nativeLabel,
|
||
});
|
||
|
||
final String code;
|
||
final String label;
|
||
final String nativeLabel;
|
||
}
|