# 我的（Mine）Tab — 架构文档

> 对应 Gitea issues #5–#13，#39–#41（UI 重设计）
> 参考实现：`im-client-ios-swift-demo` Features/Settings + Features/Profile

---

## 1. 功能范围

| Issue | 功能 | 状态 |
|-------|------|------|
| #5 | Tab 重命名 & 个人资料卡片 | ✅ 已实现 |
| #6 | 编辑个人资料（昵称/bio/头像） | ✅ 框架已建（CDN 上传待 #6 后续） |
| #7 | 退出登录 | ✅ 已实现 |
| #8 | 主题持久化 | ⏳ TODO（解开 ThemeModeNotifier 注释） |
| #9 | 语言设置 | ✅ UI 框架（l10n_sdk 待接入） |
| #10 | 黑名单管理 | ✅ 页面框架（API 待实现） |
| #11 | 聊天文件夹 | ⏳ TODO stub |
| #12 | 网络诊断 | ✅ 已实现（4步诊断） |
| #13 | 关于 / 版本 | ✅ 已实现 |

---

## 2. 目录结构

```
features/settings/
├── di/
│   └── settings_providers.dart      # UseCase DI 装配
├── presentation/
│   ├── settings_view_model.dart      # 我的页 ViewModel (NotifierProvider)
│   ├── edit_profile_view_model.dart  # 编辑资料 ViewModel
│   ├── network_diagnostics_view_model.dart  # 网络诊断 ViewModel
│   └── theme_view_model.dart         # 主题 ViewModel (@riverpod)
├── usecases/
│   ├── fetch_profile_usecase.dart    # GET /app/api/user/profile
│   ├── update_profile_usecase.dart   # POST /app/api/user/update-profile
│   ├── logout_usecase.dart           # POST /app/api/auth/logout + WS + DB
│   └── set_theme_usecase.dart        # 幂等主题切换
└── view/
    ├── settings_page.dart            # 我的主页
    ├── edit_profile_page.dart        # 编辑资料页
    ├── language_page.dart            # 语言选择页
    ├── blocklist_page.dart           # 黑名单页（框架）
    ├── network_diagnostics_page.dart # 网络诊断页
    ├── about_page.dart               # 关于页
    ├── theme_view.dart               # 主题选择页
    └── widgets/
        ├── settings_section_header.dart
        └── theme_option_tile.dart

data/remote/
├── get_profile_request.dart          # GET /app/api/user/profile（已有）
└── update_profile_request.dart       # POST /app/api/user/update-profile（新增）
```

---

## 3. 数据流

### 3.1 资料加载

```
SettingsPage (build)
  └─ ref.watch(settingsViewModelProvider)
       └─ SettingsViewModel.build()
            └─ Future.microtask(loadProfile)
                 └─ FetchProfileUseCase.execute()
                      └─ NetworksSdkApi.executeRequest(GetProfileRequest())
                           └─ GET /app/api/user/profile  (JWT token in header)
                           └─ ProfileResponse → SettingsState {nickname, avatarUrl, maskedContact, uid}
```

### 3.2 退出登录

```
SettingsPage._confirmLogout()
  └─ AlertDialog confirm
       └─ SettingsViewModel.logout()
            ├─ LogoutUseCase.execute()
            │    ├─ AuthRepository.logout()      → POST /app/api/auth/logout
            │    ├─ SocketManager.disconnect()   → 断开 WebSocket
            │    └─ StorageSdkLifecycle.closeDatabase()
            └─ AuthNotifier.logout()             → go_router 重定向 /login
```

### 3.3 编辑资料保存

```
EditProfilePage → 保存按钮
  └─ EditProfileViewModel.save()
       └─ UpdateProfileUseCase.execute(nickname, bio, profilePicUrl)
            └─ NetworksSdkApi.executeRequest(UpdateProfileRequest)
                 └─ POST /app/api/user/update-profile
  └─ SettingsViewModel.loadProfile()  (刷新资料卡)
```

---

## 4. API 端点

| 操作 | Method | Path |
|------|--------|------|
| 获取当前用户资料 | GET | `/app/api/user/profile` |
| 更新用户资料 | POST | `/app/api/user/update-profile` |
| 退出登录 | POST | `/app/api/auth/logout` |
| 黑名单列表（待实现） | GET | `/app/api/account/block/list` |
| 解除拉黑（待实现） | POST | `/app/api/account/block/remove` |
| 聊天文件夹（待实现） | POST | `/app/api/account/store/get-store` |

---

## 5. Provider 设计

所有 Settings ViewModel 使用 `Notifier<T>` + 手动 `NotifierProvider`，**不使用 `@riverpod` 代码生成**，避免额外 build_runner 依赖：

```dart
class SettingsViewModel extends Notifier<SettingsState> { ... }

final settingsViewModelProvider = NotifierProvider<SettingsViewModel, SettingsState>(
  SettingsViewModel.new,
);
```

DI 链路：

```
settingsViewModelProvider
  └─ fetchProfileUseCaseProvider   → networkSdkApiProvider
  └─ logoutUseCaseProvider
       ├─ authRepositoryProvider   → networkSdkApiProvider
       ├─ socketManagerProvider
       └─ storageSdkProvider
```

---

## 6. 路由

新增 Shell 外全屏路由（`parentNavigatorKey: _rootKey`），TabBar 在子页面隐藏：

```
/settings/edit-profile        EditProfilePage
/settings/blocklist           BlocklistPage
/settings/language            LanguagePage
/settings/network-diagnostics NetworkDiagnosticsPage
/settings/about               AboutPage
/settings/theme               ThemeView（原有）
```

认证守卫 `auth_guard.dart` switch 已补全上述路由。

---

## 7. UI 重设计（#39 / #40 / #41）

### 7.1 ProfileHeroCard (#39 / #41)

| 元素 | 规格 |
|------|------|
| 头像 | 72pt 圆形；无头像时 8 色渐变占位（uid%8） |
| 昵称 | fontWeight w700，titleMedium |
| Handle | `@J{uid}`，bodySmall onSurfaceVariant |
| 手机号 | 掩码 `+CC ***XXXX`，bodySmall |
| Bio | 非空显示，为空显示「添加一句话简介」（斜体，半透明） |
| AppBar | compact，右侧：QR 图标 + 编辑铅笔 |

渐变色方案（`_ProfileHeroCard._gradients[uid.abs() % 8]`）：
```
0: [#4776E6, #8E54E9]  1: [#11998E, #38EF7D]
2: [#FC466B, #3F5EFB]  3: [#F7971E, #FFD200]
4: [#56CCF2, #2F80ED]  5: [#EB3349, #F45C43]
6: [#1FA2FF, #12D8FA]  7: [#9D50BB, #6E48AA]
```

### 7.2 彩色图标行与分组卡片 (#40)

`_IconBox`：36pt 圆角正方形（8pt）白色图标，iOS Settings 风格。

| 卡片组 | 菜单项 | 颜色 |
|--------|--------|------|
| 账户 | 我的钱包 | #FFAA5B |
| | 账户安全 | #8A5CF6 |
| 工具 | 收藏 | #FFAF45 |
| | 最近呼叫 | #4CB050 |
| | 链接设备 | #5667FF |
| | 聊天文件夹 | #F2994A |
| 偏好设置 | 通知和声音 | #FF8B5E |
| | 隐私设置 | #0BB8A9 |
| | 黑名单 | #FF4B4B |
| | 语言 | #5667FF |
| | 主题 | #8A5CF6 |
| 关于 | 用户协议 | gray |
| | 隐私政策 | gray |
| | 版本号（静态）| gray，无 chevron |

### 7.3 SettingsState bio 字段 (#41)

- `SettingsState.bio: String`（默认 `''`）
- `SettingsViewModel.loadProfile()` 赋值 `bio: profile.bio`
- 数据来源：`ProfileResponse.bio` → `GET /app/api/user/profile`

---

## 8. 待完成事项

- **#6 头像上传**：接入 CDN upload（参考 iOS CDN 流程）
- **#8 主题持久化**：解开 `ThemeModeNotifier.build()` 和 `setMode()` 中的 TODO
- **#10 黑名单 API**：实现 `FetchBlocklistUseCase` + `UnblockUseCase`
- **#11 聊天文件夹**：`ChatCategoryViewModel` + `account/store` API
- **build_runner**：`UpdateProfileRequest` 使用 `@ApiRequest`，需执行：
  ```bash
  cd apps/im_app && dart run build_runner build --delete-conflicting-outputs
  ```
