基本功能
This commit is contained in:
50
spec_kit/iOS Widget/plan.md
Normal file
50
spec_kit/iOS Widget/plan.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# iOS Widget(技术计划,V1 写死文案)
|
||||
|
||||
## 1. 计划目标
|
||||
|
||||
在 iOS 上实现真正可添加到桌面的小组件(WidgetKit Extension),V1 先展示**写死的美观文案**,不做 App->Widget 数据同步与更新。
|
||||
|
||||
- **构建方式**:方案 A(`expo prebuild` + Xcode)
|
||||
- **点击跳转**:跳转到 App 的 Home
|
||||
- **尺寸**:Small / Medium / Large 都支持
|
||||
|
||||
## 2. 默认技术决策
|
||||
|
||||
- **小组件实现**:iOS 原生 WidgetKit Extension(SwiftUI)
|
||||
- **数据来源**:V1 写死在 Widget 代码内
|
||||
- **跳转**:使用 Widget 的 `widgetURL` 打开 App(深链)
|
||||
- **App 侧路由**:使用现有 `expo-router`
|
||||
|
||||
## 3. Deep Link 约定(点击小组件打开 Home)
|
||||
|
||||
### 3.1 Scheme
|
||||
|
||||
当前 `client/app.json` 中已存在:
|
||||
|
||||
- `expo.scheme = "client"`
|
||||
|
||||
因此小组件点击跳转使用:
|
||||
|
||||
- `client:///(app)/home`
|
||||
|
||||
> 说明:这是 expo-router 的路径形态;若你后续调整路由结构,需要同步更新此 URL。
|
||||
|
||||
## 4. 实施步骤(高层)
|
||||
|
||||
1. **预构建 iOS 原生工程**:生成 `client/ios/`
|
||||
2. **在 Xcode 创建 WidgetKit Extension**:命名例如 `MindfulnessWidget`
|
||||
3. **实现 3 种尺寸 UI**:Small/Medium/Large 都展示写死文案,但排版适配不同尺寸
|
||||
4. **设置点击跳转**:为 Widget 配置 `widgetURL` 指向 `client:///(app)/home`
|
||||
5. **本地运行验证**:在模拟器安装 App,添加桌面小组件并验证显示与跳转
|
||||
|
||||
## 5. 验收标准
|
||||
|
||||
- 可以在 iOS 桌面添加小组件(Small/Medium/Large)
|
||||
- 小组件展示写死文案,排版美观
|
||||
- 点击小组件能打开 App 并进入 Home
|
||||
|
||||
## 6. 风险与注意事项
|
||||
|
||||
- **Expo Go 不支持**:必须用 Xcode 运行预构建后的 App(或后续 EAS Build)
|
||||
- **Bundle Identifier**:当前 `client/app.json` 使用 `com.anonymous.client`,仅适合本地验证;上线前需替换为真实 bundle id,并同步证书/签名
|
||||
|
||||
84
spec_kit/iOS Widget/spec.md
Normal file
84
spec_kit/iOS Widget/spec.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# iOS Widget(高层规范)
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
当前客户端仅在设置页展示了“小组件说明文案”,并未实现真正的 iOS 桌面小组件。
|
||||
|
||||
本需求用于实现**真正的 iOS 小组件**(WidgetKit Extension),使用户可以在 iOS 桌面添加小组件并看到“情绪文字/正念短句”等内容。
|
||||
|
||||
### 目标
|
||||
|
||||
- **可添加到桌面**:支持在 iOS 桌面添加小组件(WidgetKit)
|
||||
- **V1(本期)写死内容**:小组件展示一段美观文案(先写死,不做数据同步/更新)
|
||||
- **可点击跳转**:点击小组件可跳转回 App 指定页面(默认 Home)
|
||||
|
||||
### 非目标(本阶段不做)
|
||||
|
||||
- 不承诺严格准点刷新(受 iOS 系统调度限制)
|
||||
- 不做复杂的小组件交互配置(如需可后续拆分)
|
||||
- 不要求 Android Widget(仅 iOS)
|
||||
- **V1 不做数据更新**:不做 App -> Widget 数据共享与更新触发(App Group 留到后续版本)
|
||||
|
||||
## 2. 关键结论与约束(必须接受)
|
||||
|
||||
- **Expo Go 不支持 WidgetKit**:必须使用 **Development Build / 预构建后的原生工程 / EAS Build** 才能安装带小组件扩展的 App
|
||||
- **需要原生扩展**:iOS 小组件必须创建 **WidgetKit Extension(SwiftUI)**
|
||||
- **V1 不需要 App Group**:因为内容写死在 Widget 内部;后续做数据共享时再引入 App Group
|
||||
|
||||
## 3. 小组件功能需求(高层)
|
||||
|
||||
### 3.1 展示内容
|
||||
|
||||
- 展示一段“情绪文字/正念短句”
|
||||
- 背景支持:
|
||||
- 纯色或渐变(优先)
|
||||
- 图片(可选,后续)
|
||||
- 文案需“美观可读”,适配暗色模式(可选)
|
||||
|
||||
### 3.2 尺寸支持
|
||||
|
||||
- 支持 iOS 常见尺寸:
|
||||
- Small
|
||||
- Medium
|
||||
- Large
|
||||
|
||||
### 3.3 更新策略
|
||||
|
||||
V1:不做更新策略(内容写死)。后续版本可扩展:
|
||||
|
||||
- 固定间隔更新(例如每天/每小时)
|
||||
- App 驱动更新:App 写入新内容,Widget 触发 reload(系统仍可能延迟)
|
||||
|
||||
### 3.4 点击跳转
|
||||
|
||||
- 点击小组件可打开 App 并跳转到指定页面:
|
||||
- 默认:Home
|
||||
- 可选:Favorites
|
||||
|
||||
## 4. 数据共享与持久化(高层)
|
||||
|
||||
V1:不做数据共享与持久化(写死文案)。
|
||||
|
||||
后续版本(V2)再引入 App Group(共享 UserDefaults)与数据来源策略:
|
||||
|
||||
- `widget.text`、`widget.updatedAt`、`widget.lang`、`widget.theme` 等
|
||||
- 数据来源可选:Home 当前/最近 Like/随机 mock
|
||||
|
||||
## 5. 多语言(与 App 一致)
|
||||
|
||||
- 语言码沿用客户端:`zh-CN/en/es/pt/zh-TW`
|
||||
- V1:Widget 内可先写死单语(例如中文)或做最小的本地化(可选)
|
||||
- V2:建议由 App 端选择语言并写入共享数据,降低 Widget 端 i18n 复杂度
|
||||
|
||||
## 6. 验收标准
|
||||
|
||||
- 可以在 iOS 桌面搜索并添加小组件
|
||||
- 小组件能显示一段美观文案(至少支持 Small)
|
||||
- 点击小组件能打开 App 并进入预期页面
|
||||
|
||||
## 7. 风险与注意事项
|
||||
|
||||
- iOS 刷新频率限制:不可承诺“每分钟刷新”等高频
|
||||
- App Group / Bundle ID 配置错误会导致 Widget 读不到数据
|
||||
- Dev Build / EAS 证书配置成本较高,需要在计划阶段明确落地路径
|
||||
|
||||
79
spec_kit/iOS Widget/tasks.md
Normal file
79
spec_kit/iOS Widget/tasks.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# iOS Widget(任务清单,V1 写死文案)
|
||||
|
||||
> 说明:本清单根据 `plan.md` 拆解,要求“可执行、可验收、可标记”。
|
||||
> 标记规则:执行完成后将对应项从 `- [ ]` 改为 `- [x]`,并把“状态”改为 **已完成**;进行中改为 **进行中**;阻塞写明原因与解除条件。
|
||||
|
||||
## 0. 清单状态说明
|
||||
|
||||
- **状态**:未开始 / 进行中 / 已完成 / 阻塞
|
||||
- **阻塞**:必须写明阻塞点与解除条件
|
||||
|
||||
## 1. 预构建 iOS 原生工程(必须)
|
||||
|
||||
- [x] **执行 prebuild 生成 `ios/` 目录**
|
||||
- **状态**:已完成(已执行 `npx expo prebuild -p ios --no-install`,已生成 `client/ios/`)
|
||||
- **命令**:
|
||||
|
||||
```bash
|
||||
cd client
|
||||
npx expo prebuild -p ios
|
||||
```
|
||||
|
||||
- **产出**:`client/ios/`(包含 Xcode 工程)
|
||||
- **验收**:`client/ios/` 目录存在,并能在 Xcode 打开
|
||||
|
||||
## 2. 创建 WidgetKit Extension(Xcode 操作)
|
||||
|
||||
- [x] **在 Xcode 新建 Widget Extension(WidgetKit)**
|
||||
- **状态**:已完成(已创建 Target:情绪小组件;下一步把 Swift 文件加入该 Target 并跑模拟器验证)
|
||||
- **操作**:
|
||||
- 打开 `client/ios/*.xcworkspace`(优先 workspace)
|
||||
- `File -> New -> Target... -> Widget Extension`
|
||||
- 名称建议:`MindfulnessWidget`(或你喜欢的命名)
|
||||
- **验收**:工程里新增 Widget target,能编译通过
|
||||
- **下一步(必须做)**:
|
||||
- 把 `client/ios/MindfulnessWidget/MindfulnessWidget.swift` 加入 Target Membership:`情绪小组件`
|
||||
- 如果 Xcode 自动生成了同类的 Widget 主文件(例如 `情绪小组件.swift` / `*_Bundle.swift`),请确保最终只有一个 `@main struct ...: Widget` 入口(避免重复入口导致编译失败)
|
||||
|
||||
## 3. 实现写死文案(3 个尺寸都要)
|
||||
|
||||
- [x] **实现 Small/Medium/Large 三种尺寸布局**
|
||||
- **状态**:已完成(已提供 `client/ios/MindfulnessWidget/MindfulnessWidget.swift` 写死文案 + 三尺寸布局代码骨架)
|
||||
- **文案(写死)**:可先用一条默认文案,例如:`你已经很努力了,今天也值得被温柔对待。`
|
||||
- **要求**:
|
||||
- Small:一行标题 + 主文案(可截断)
|
||||
- Medium:主文案更完整(可多行)
|
||||
- Large:增加留白与排版层次(例如标题 + 文案 + 小注脚)
|
||||
- **验收**:三种尺寸均显示美观,无溢出/遮挡
|
||||
|
||||
## 4. 点击跳转到 Home(Deep Link)
|
||||
|
||||
- [x] **为 Widget 配置点击跳转 URL**
|
||||
- **状态**:已完成(代码骨架已使用 `.widgetURL(URL(string: \"client:///(app)/home\")!)`)
|
||||
- **URL**:`client:///(app)/home`
|
||||
- **实现**:在 Widget 中设置 `.widgetURL(URL(string: \"client:///(app)/home\")!)`
|
||||
- **验收**:点击小组件能打开 App 并进入 Home
|
||||
|
||||
## 5. 本地验证
|
||||
|
||||
- [ ] **在 iOS 模拟器运行并添加桌面小组件**
|
||||
- **状态**:阻塞(需要本机 Xcode Run 安装后在模拟器桌面添加 Widget 验证)
|
||||
- **步骤**:
|
||||
- Xcode Scheme 选择主 App(一般是 `client`),选择模拟器,点击 Run 安装 App
|
||||
- 回到桌面长按 -> “+” -> 搜索小组件 -> 添加 Small/Medium/Large
|
||||
- **验收**:小组件显示正确,点击跳转正确
|
||||
- **排查**:
|
||||
- 桌面搜索不到:通常是没有 Run 安装过主 App,或 Widget target 未加入编译
|
||||
- 点击不跳转:确认 Widget 里 `widgetURL` 为 `client:///(app)/home`,且 `app.json` 的 `scheme` 为 `client`
|
||||
|
||||
## 6. 文档补充(可选但建议)
|
||||
|
||||
- [x] **在 `client/README.md` 增加“小组件开发(V1 写死文案)”说明**
|
||||
- **状态**:已完成
|
||||
- **内容**:
|
||||
- Expo Go 不支持
|
||||
- prebuild 命令
|
||||
- Xcode 创建 Widget Extension 的步骤
|
||||
- deep link:`client:///(app)/home`
|
||||
- **验收**:新同学照 README 可复现
|
||||
|
||||
Reference in New Issue
Block a user