Files
social-app/docs/plans/2026-03-12-home-composer-redesign-implementation-plan.md
T
qzl 01c36eb32e refactor: 移除前端 Mock API,新增共享组件,优化认证流程
- 删除 mock_api_client、mock_calendar_service、mock_history_service
- 新增 fixed_length_code_input、link_button、message_composer 共享组件
- 优化登录/注册/密码重置页面使用新组件
- 简化 injection.dart 移除 mock 分支
- 更新 env.dart 配置(BACKEND_URL 替换 API_URL)
- 后端 agentscope 工具和测试更新
- 重构 AGENTS.md 文档结构
- 新增 deploy/ 目录和 protocol 文档
2026-03-12 16:41:45 +08:00

276 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Home Composer Redesign Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 重做 Home 输入组件,统一为单胶囊容器并稳定语音长按交互,消除布局漂移,同时保持 `+` 与发送等既有业务逻辑不变。
**Architecture:** 采用“单容器双模式”方案:`HomeScreen` 继续持有业务状态与动作,新增 `HomeComposer` 专注 UI 与手势分发;中间区域用受控状态在文本/按住说话/录音中/识别中之间切换,外层高度固定。录音提示与声波动画都内聚在主容器内部渲染,避免额外布局占位。
**Tech Stack:** Flutter, flutter_bloc, lucide_icons, design tokens (`AppColors`/`AppSpacing`/`AppRadius`), widget test
---
### Task 1: 建立 HomeComposer 组件骨架与参数契约
**Files:**
- Create: `apps/lib/features/home/ui/widgets/home_composer.dart`
- Modify: `apps/lib/features/home/ui/screens/home_screen.dart`
- Test: `apps/test/features/home/ui/widgets/home_composer_test.dart`
**Step 1: 写失败测试(渲染结构)**
```dart
testWidgets('renders one unified rounded composer container', (tester) async {
// pump HomeComposer with minimum required callbacks/states
// expect: one root container, plus button, center content slot, right action slot
});
```
**Step 2: 运行测试确认失败**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "renders one unified rounded composer container"`
Expected: FAIL`HomeComposer` 未定义或结构不匹配)
**Step 3: 写最小实现**
```dart
class HomeComposer extends StatelessWidget {
const HomeComposer({
super.key,
required this.isHoldToSpeakMode,
required this.isRecording,
required this.isTranscribing,
required this.hasMessage,
required this.isWaitingAgent,
required this.onTapPlus,
required this.onTapRightAction,
required this.centerChild,
});
// unified capsule container with left/center/right slots
}
```
**Step 4: 再跑测试确认通过**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "renders one unified rounded composer container"`
Expected: PASS
**Step 5: 小步提交(仅用户明确要求时)**
```bash
git add apps/lib/features/home/ui/widgets/home_composer.dart apps/lib/features/home/ui/screens/home_screen.dart apps/test/features/home/ui/widgets/home_composer_test.dart
git commit -m "refactor: extract unified home composer container"
```
### Task 2: 完成右侧图标状态映射(activity/keyboard/send/stop
**Files:**
- Modify: `apps/lib/features/home/ui/widgets/home_composer.dart`
- Modify: `apps/lib/features/home/ui/screens/home_screen.dart`
- Test: `apps/test/features/home/ui/widgets/home_composer_test.dart`
**Step 1: 写失败测试(图标状态机)**
```dart
testWidgets('right action icon follows state priority', (tester) async {
// waiting > hasMessage > holdToSpeakMode > textMode
// expect LucideIcons.square/send/keyboard/activity respectively
});
```
**Step 2: 运行测试确认失败**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "right action icon follows state priority"`
Expected: FAIL(图标选择逻辑尚未完整实现)
**Step 3: 最小实现图标决策**
```dart
IconData resolveRightIcon(...) {
if (isWaitingAgent) return LucideIcons.square;
if (hasMessage) return LucideIcons.send;
return isHoldToSpeakMode ? LucideIcons.keyboard : LucideIcons.activity;
}
```
**Step 4: 再跑测试确认通过**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "right action icon follows state priority"`
Expected: PASS
**Step 5: 小步提交(仅用户明确要求时)**
```bash
git add apps/lib/features/home/ui/widgets/home_composer.dart apps/lib/features/home/ui/screens/home_screen.dart apps/test/features/home/ui/widgets/home_composer_test.dart
git commit -m "refactor: stabilize composer right action icon mapping"
```
### Task 3: 实现中间区域双模式替换并固定高度
**Files:**
- Modify: `apps/lib/features/home/ui/widgets/home_composer.dart`
- Modify: `apps/lib/features/home/ui/screens/home_screen.dart`
- Test: `apps/test/features/home/ui/widgets/home_composer_test.dart`
**Step 1: 写失败测试(模式切换不改变高度)**
```dart
testWidgets('composer height remains stable across mode switches', (tester) async {
// measure size in text mode and hold-to-speak mode
// expect equal heights
});
```
**Step 2: 运行测试确认失败**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "composer height remains stable across mode switches"`
Expected: FAIL(当前结构切换时高度波动)
**Step 3: 最小实现(AnimatedSwitcher + fixed constraints**
```dart
SizedBox(
height: composerHeight,
child: AnimatedSwitcher(
duration: switchDuration,
child: isHoldToSpeakMode ? holdToSpeakChild : textInputChild,
),
)
```
**Step 4: 再跑测试确认通过**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "composer height remains stable across mode switches"`
Expected: PASS
**Step 5: 小步提交(仅用户明确要求时)**
```bash
git add apps/lib/features/home/ui/widgets/home_composer.dart apps/lib/features/home/ui/screens/home_screen.dart apps/test/features/home/ui/widgets/home_composer_test.dart
git commit -m "refactor: keep composer layout stable during mode switch"
```
### Task 4: 实现长按录音交互(开始/上滑取消/松开发送)
**Files:**
- Modify: `apps/lib/features/home/ui/screens/home_screen.dart`
- Modify: `apps/lib/features/home/ui/widgets/home_composer.dart`
- Test: `apps/test/features/home/ui/widgets/home_composer_test.dart`
**Step 1: 写失败测试(录音提示只在 recording)**
```dart
testWidgets('recording hint appears only while recording', (tester) async {
// idle hold-to-speak: no hint
// recording: show "松开发送,上滑取消"
});
```
**Step 2: 运行测试确认失败**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "recording hint appears only while recording"`
Expected: FAIL
**Step 3: 最小实现录音流程映射**
```dart
onLongPressStart => HapticFeedback.lightImpact() + onHoldStart();
onLongPressMoveUpdate => if (dy < threshold) onHoldCancel();
onLongPressEnd => onHoldEnd(autoSend: true);
```
**Step 4: 再跑测试确认通过**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "recording hint appears only while recording"`
Expected: PASS
**Step 5: 小步提交(仅用户明确要求时)**
```bash
git add apps/lib/features/home/ui/widgets/home_composer.dart apps/lib/features/home/ui/screens/home_screen.dart apps/test/features/home/ui/widgets/home_composer_test.dart
git commit -m "feat: rework hold-to-speak interaction with stable recording state"
```
### Task 5: 视觉重构为轻拟物胶囊(仅 tokens)
**Files:**
- Modify: `apps/lib/features/home/ui/widgets/home_composer.dart`
- Modify: `apps/lib/core/theme/design_tokens.dart`(仅当现有 token 不足时新增)
- Test: `apps/test/features/home/ui/widgets/home_composer_test.dart`
**Step 1: 写失败测试(主容器统一性)**
```dart
testWidgets('plus, center and right action are inside same capsule', (tester) async {
// find one capsule host and verify children are descendants
});
```
**Step 2: 运行测试确认失败**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "plus, center and right action are inside same capsule"`
Expected: FAIL
**Step 3: 最小视觉实现(不硬编码)**
```dart
// use AppColors/AppSpacing/AppRadius and existing shadow tokens
// no hardcoded color/spacing/radius/size
```
**Step 4: 再跑测试确认通过**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart --plain-name "plus, center and right action are inside same capsule"`
Expected: PASS
**Step 5: 小步提交(仅用户明确要求时)**
```bash
git add apps/lib/features/home/ui/widgets/home_composer.dart apps/lib/core/theme/design_tokens.dart apps/test/features/home/ui/widgets/home_composer_test.dart
git commit -m "refactor: redesign home composer with neumorphic capsule style"
```
### Task 6: 集成回归与文档同步
**Files:**
- Modify: `apps/lib/features/home/ui/screens/home_screen.dart`
- Modify: `docs/runtime/runtime-route.md`(若交互说明有变化)
**Step 1: 运行目标测试文件**
Run: `flutter test test/features/home/ui/widgets/home_composer_test.dart`
Expected: PASS
**Step 2: 运行 Home 相关回归测试(若新增)**
Run: `flutter test test/features/home`
Expected: PASS(若目录存在)
**Step 3: 运行应用侧基础回归**
Run: `flutter test`
Expected: PASS 或仅存在与本改动无关的已知失败
**Step 4: 记录验证结论**
```text
- 输入组件统一容器:通过
- 模式切换稳定:通过
- 录音提示条件:通过
- + 按钮/发送逻辑:通过
```
**Step 5: 小步提交(仅用户明确要求时)**
```bash
git add apps/lib/features/home/ui/screens/home_screen.dart apps/lib/features/home/ui/widgets/home_composer.dart apps/test/features/home/ui/widgets/home_composer_test.dart docs/runtime/runtime-route.md
git commit -m "test: add regression coverage for home composer redesign"
```
## 实施注意事项
- 保持 `HomeScreen` 作为业务状态单一来源,避免在 `HomeComposer` 内部复制业务状态。
- 录音中 (`recording`) 禁止触发模式切换,防止并发手势引发错位。
- 严格遵守 `apps/AGENTS.md`:不硬编码视觉值,必须使用 design tokens。
- 用户反馈统一使用 `Toast.show(...)`,不得引入 `SnackBar`