# Card UI（任务清单）

> 说明：本清单根据 `plan.md` 拆解，要求“可执行、可验收、可标记”。  
> 标记规则：执行完成后将对应项从 `- [ ]` 改为 `- [x]`，并把“状态”改为 **已完成**；进行中改为 **进行中**；阻塞写明原因与解除条件。

## 0. UI 参考（本次实现对齐）

- **参考截图**：你提供的卡片页 + 主题弹窗 + 我的弹窗
- **弹窗内容区背景色**：`#FAF3EC`
- **右上角按钮资源**：`client/assets/images/home/theme.svg`、`client/assets/images/home/my.svg`
- **底部反应按钮资源**：`client/assets/images/home/like.svg`、`client/assets/images/home/hate.svg`
- **交互约束**：
  - 弹窗为**底部上拉（Sheet）**
  - 关闭方式：**点 X 关闭**（不要求点遮罩关闭）
  - 顶部按钮使用**系统导航栏**（`headerRight`）
  - 主题切换最少影响：**页面背景**
  - 个人主页弹窗中的列表项：本期允许 **仅做占位**
  - 喜欢动效为**强反馈：心形填满**（按压回弹 + 填充变化）

## 1. 依赖与基础设施（SVG 可 import）

- [x] **安装 `react-native-svg-transformer` 并新增 `client/metro.config.js`**  
  - **状态**：已完成  
  - **原因**：让 `assets/images/home/*.svg` 支持 `import XxxIcon from '...svg'` 作为组件使用  
  - **命令**：

```bash
cd client
pnpm add react-native-svg-transformer
```

  - **实现点**：
    - 新增 `client/metro.config.js`，基于 `expo/metro-config` 配置 `svg` transformer
  - **验收**：
    - 任一页面可成功渲染 `theme.svg`/`like.svg`（真机/模拟器均可）
    - `pnpm start` 正常启动，无 Metro 报错

## 2. 本地存储：主题模式持久化

- [x] **在 `src/storage/appStorage.ts` 新增主题 mode key 与读写方法**  
  - **状态**：已完成  
  - **Key**：`ui.theme.mode`  
  - **类型**：`'scenery' | 'color'`（默认 `scenery`）  
  - **新增 API（建议）**：
    - `getThemeMode(): Promise<'scenery' | 'color'>`
    - `setThemeMode(mode: 'scenery' | 'color'): Promise<void>`
  - **验收**：
    - 代码中不散落硬编码 key
    - 切换主题后重启 App 仍保持上次选择

## 3. 通用组件：底部上拉弹窗（Sheet）框架

- [x] **新增通用 `SheetModal` 组件（底部上拉 + 背景色 #FAF3EC + X 关闭）**  
  - **状态**：已完成  
  - **建议路径**：`client/components/ui/SheetModal.tsx`  
  - **要求**：
    - 遮罩存在（可拦截背景交互），但本期**不要求点遮罩关闭**
    - 内容区背景色固定为 `#FAF3EC`
    - 顶部提供右上/左上 **X 按钮**关闭（以设计稿为准）
    - 基础动效：上滑进入、下滑退出（或淡入淡出 + translateY）
  - **验收**：
    - 任意页面可打开/关闭该弹窗，不闪烁、不穿透点击
    - iOS 安全区适配正常（底部不被 Home Indicator 遮挡）

## 4. 主题弹窗：风景 / 颜色

- [x] **实现 `ThemeModal`（复用 `SheetModal`）**  
  - **状态**：已完成  
  - **建议路径**：`client/components/home/ThemeModal.tsx`  
  - **内容**：
    - 标题：主题
    - 选项：风景 / 颜色（含预览卡片）
    - 选中态：明显高亮（描边/阴影/勾选均可）
  - **交互**：
    - 点击选项：`setThemeMode(...)` 并立即生效（可关闭弹窗或保持打开，按设计稿）
    - 点 X：关闭
  - **验收**：
    - 两种主题可切换
    - 切换后 Home 页面背景立刻变化

## 5. 个人主页弹窗：占位入口

- [x] **实现 `ProfileModal`（复用 `SheetModal`）**  
  - **状态**：已完成  
  - **建议路径**：`client/components/home/ProfileModal.tsx`  
  - **内容（按设计最小闭环）**：
    - 顶部：插画/头像 + 昵称（来自 `getUserProfile().name`，无则占位）
    - 快捷卡片：我的喜欢 / 小组件（小组件可占位）
    - 通用列表：每日提醒 / 隐私政策 / 使用条款 / 语言（本期均允许占位）
  - **交互**：
    - 点 X：关闭
    - 列表项点击：占位反馈（例如 `Alert` 或轻提示），不崩溃即可
  - **验收**：
    - 弹窗 UI 与 ThemeModal 同一套视觉（背景色/圆角/间距一致）
    - 点击各入口有明确反馈

## 6. 卡片页头部：系统导航栏右上角两个 icon 按钮

- [x] **改造 `client/app/(app)/_layout.tsx`：`home` 的 `headerRight` 使用两个圆形 icon 按钮**  
  - **状态**：已完成  
  - **要求**：
    - 两按钮水平排列、圆形浅色底、`hitSlop>=10`
    - 左：主题（`theme.svg`），右：我的（`my.svg`）
  - **事件传递方案（需要落地）**：
    - 实际落地：在 `home.tsx` 内通过 `navigation.setOptions()` 设置 `headerRight`，直接使用页面 state 打开 Theme/Profile 弹窗（避免跨层事件传递）
  - **验收**：
    - 右上角两个按钮展示正确
    - 点击分别能打开对应弹窗

## 7. 卡片页内容：喜欢/讨厌改为 icon + 强反馈动效

- [x] **改造 `client/app/(app)/home.tsx`：底部按钮从文字改为 icon**  
  - **状态**：已完成  
  - **要求**：
    - 喜欢按钮使用 `like.svg`
    - 讨厌按钮使用 `hate.svg`（逻辑仍写入 reaction=`dislike`）
  - **验收**：两按钮 icon 显示清晰，点击逻辑仍正常推进下一张卡片

- [x] **实现“强反馈：心形填满”点击动效**  
  - **状态**：已完成  
  - **范围**：至少作用于“喜欢”按钮  
  - **建议实现**：
    - `pressIn/pressOut`：按钮缩放回弹
    - `onPress`：短促强调动效（scale 1 → 1.12 → 1）
    - “填满”效果：点击后切换到“填充版心形”（若当前资源仅描边，需要：
      - 新增一份 `like_filled.svg`（或在现有 SVG 上修改 fill/stroke），并保持风格一致
      - 或用 `react-native-svg` 动态改 `fill`（可行但实现复杂）
  - **验收**：
    - 点击喜欢按钮能看到明显的“变填充 + 弹一下”反馈
    - 动效结束后再推进下一张卡片（避免动画被切页吞掉）

## 8. 主题对 Home 背景的影响

- [x] **让主题 mode 影响 Home 页面背景**  
  - **状态**：已完成  
  - **规则**：
    - `scenery`：使用风景主题背景（可先用现有米色/图片占位）
    - `color`：使用颜色主题背景（可先用淡粉色/纯色占位）
  - **验收**：切换主题后背景立即变化；返回/重进页面仍正确

## 9. i18n（用于标题/无障碍/占位文案）

- [x] **补齐本需求相关 i18n key（至少 zh-CN/en）**  
  - **状态**：已完成  
  - **建议 key**：
    - `theme.title`、`theme.scenery`、`theme.color`
    - `profile.title`、`profile.favorites`、`profile.widget`
    - `profile.dailyReminder`、`profile.privacy`、`profile.terms`、`profile.language`
    - `home.theme`、`home.profile`（用于 `accessibilityLabel`）
  - **验收**：弹窗标题/选项/占位提示无硬编码长文案；切换语言可生效

## 10. 自测与验收

- [ ] **主题弹窗流程自测**  
  - **状态**：未开始  
  - **路径**：Home 右上角主题按钮 → 主题弹窗 → 切换风景/颜色 → 背景变化 → 重启后仍保持  
  - **验收**：符合 `spec.md` / `plan.md` / 本清单验收点

- [ ] **我的弹窗流程自测**  
  - **状态**：未开始  
  - **路径**：Home 右上角我的按钮 → 个人主页弹窗 → 点 X 关闭 → 列表项点击占位反馈  
  - **验收**：弹窗不穿透、关闭稳定、占位反馈明确

- [ ] **喜欢/讨厌动效与逻辑自测**  
  - **状态**：未开始  
  - **路径**：连续点击喜欢/讨厌 → 按钮动效可见 → 卡片索引推进 → 收藏/反应写入正常  
  - **验收**：无报错、不卡顿、动效不被切换吞掉

