a57692353c
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
9.6 KiB
9.6 KiB
02 — 交互流程与导航设计
核心原则:间接启动(语音/手势)不进入全屏 APP,而是以悬浮覆盖层呈现
关联文档:01-voice-assistant-system.md
1. 启动来源 → 界面模式 映射表
┌──────────────────────────────────────────────────────────┐
│ 启动来源 │
├───────────────────────┬──────────────────────────────────┤
│ 直接启动 (Explicit) │ 间接启动 (Implicit) │
├───────────────────────┼──────────────────────────────────┤
│ · 桌面图标 │ · 语音唤醒 ("昔涟") │
│ · 最近任务列表 │ · 长按 Home 键 │
│ · 通知栏点击 │ · 底部两角向内滑动 │
│ · Deep Link │ · 长按电源键 (配置后) │
│ │ · 耳机按键 (单击/长按) │
│ │ · 锁屏右滑助手 │
├───────────────────────┼──────────────────────────────────┤
│ ▼ │ ▼ │
│ 全屏 Activity │ VoiceInteractionSession │
│ (MainActivity) │ (全屏悬浮覆盖层) │
│ · 完整导航栏 │ · 无导航栏 │
│ · Tab 切换 │ · 仅对话卡片 │
│ · 设置/IoT 面板 │ · 半透明遮罩透出底层 │
│ · 压入返回栈 │ · 不压入返回栈 │
└───────────────────────┴──────────────────────────────────┘
2. 全屏 Activity 模式
2.1 导航结构
MainActivity
├── BottomNavigation
│ ├── Tab 1: 对话 (ChatScreen) ← 默认页
│ ├── Tab 2: IoT 面板 (IoTScreen)
│ └── Tab 3: 我的 (ProfileScreen)
├── TopAppBar
│ ├── 昔涟状态指示器 (在线/思考中/离线)
│ └── 快捷操作 (设置、通知)
└── 子页面 (通过 NavHost 导航)
├── SettingsScreen
├── MemoryScreen (记忆查看)
├── KnowledgeScreen (知识库)
├── AutomationScreen (自动化规则)
├── ReminderScreen (提醒列表)
└── LoginScreen
2.2 导航图 (NavGraph)
LoginScreen ──(登录成功)──► MainScreen (带 BottomNav)
│
┌────────────┼────────────┐
▼ ▼ ▼
ChatScreen IoTScreen ProfileScreen
│ │
▼ ▼
MemoryScreen SettingsScreen
KnowledgeScreen ├─ Account
AutomationScreen ├─ Appearance (主题)
ReminderScreen ├─ Voice (唤醒词/语音)
├─ IoT Config
└─ About
2.3 登录流程
APP 首次启动
→ 检查本地 Token
├─ 有效 → 直接进入 MainScreen
└─ 无效 → LoginScreen
├─ 输入 Gateway 地址 + 账号密码
├─ POST /api/v1/auth/login
├─ 保存 Token 到 DataStore
└─ 进入 MainScreen
3. 悬浮覆盖层模式 (VoiceInteractionSession)
3.1 视觉层级
┌──────────────────────────────────────┐
│ 底层 APP (半透明可见) │
│ ┌──────────────────────────────┐ │
│ │ 半透明黑色遮罩 (80% 不透明度) │ │
│ │ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ 对话卡片区域 │ │ │
│ │ │ (圆角顶部 28dp) │ │ │
│ │ │ │ │ │
│ │ │ · 昔涟状态条 │ │ │
│ │ │ · 对话消息流 │ │ │
│ │ │ · 文本输入框 │ │ │
│ │ │ · 语音输入按钮 │ │ │
│ │ │ │ │ │
│ │ └──────────────────────┘ │ │
│ │ │ │
│ └──────────────────────────────┘ │
└──────────────────────────────────────┘
3.2 覆盖层生命周期
Trigger (唤醒词/手势/按键)
│
▼
VoiceInteractionSession.onCreateContentView()
│
▼
onShow() → 设置窗口属性 → 播放出现动画(底部滑入)
│
▼
OverlayScreen Compose 渲染
│
├→ 用户说话 → STT → 显示识别文本 → 发送到 AI-Core
│ │
│ ▼
│ SSE 流式响应
│ │
├← TTS 语音播放 ←── 流式合成 ←────────────┘
│
├→ 用户打字输入 → WebSocket 发送 → 显示回复气泡
│
▼
对话结束
├→ 用户主动关闭 (说"再见"/点击遮罩/下滑)
└→ 超时自动关闭 (静默 10 秒)
│
▼
onHide() → 播放消失动画(底部滑出)
│
▼
finish() → 返回触发前界面
3.3 覆盖层状态机
┌──────────┐
│ IDLE │ (覆盖层不可见)
└────┬─────┘
│ 触发
▼
┌──────────┐
│LISTENING │ (等待语音输入,波形动画)
└────┬─────┘
│ 检测到语音 / 用户开始打字
▼
┌──────────┐
│PROCESSING│ (STT 识别中 / LLM 思考中)
└────┬─────┘
│ 收到回复
▼
┌──────────┐
│SPEAKING │ (TTS 播放中)
└────┬─────┘
│ 播放完毕,等待下一轮
▼
┌──────────┐
│ WAITING │ (等待用户继续或关闭)
└────┬─────┘
│
┌───────┼───────┐
│ │
用户继续说话 10s 静默
│ │
▼ ▼
LISTENING IDLE
(覆盖层关闭)
3.4 与全屏 Activity 的切换
悬浮窗中用户点击 "打开完整 APP"
→ finish() 关闭悬浮窗
→ startActivity(MainActivity)
→ 用户在全屏模式下继续操作
全屏 APP 中用户按 Home 返回桌面
→ onStop() → 进入后台
→ WebSocket 保持连接
→ 推送/FCM 通知到达时,点击通知 → 恢复 MainActivity
4. 锁屏交互
4.1 锁屏唤醒
设备锁屏 + 息屏
│
├→ 说出唤醒词 "昔涟"
│ └→ onLaunchVoiceAssistFromKeyguard()
│ └→ 简化版覆盖层 (仅对话,无 IoT / 敏感操作)
│
└→ 长按电源键
└→ 同理
4.2 锁屏安全策略
| 操作 | 锁屏状态 | 行为 |
|---|---|---|
| 查询天气/时间 | 允许 | 直接回复 |
| 简单闲聊 | 允许 | 直接回复 |
| IoT 查询(状态) | 允许 | 回复设备状态 |
| IoT 控制(开关) | 禁止 | 提示"请先解锁设备" |
| 查看记忆 | 禁止 | 提示"请先解锁设备" |
| 修改设置 | 禁止 | 提示"请先解锁设备" |
| 宿主命令 | 禁止 | 提示"请先解锁设备" |
5. 多窗口与分屏
- 分屏模式:悬浮窗模式下不支持(本身已是覆盖层);全屏 Activity 支持分屏
- 画中画:语音通话场景支持画中画(PIP),显示昔涟头像 + 波形动画
6. 手势交互
| 手势 | 悬浮窗模式 | 全屏 Activity |
|---|---|---|
| 下滑覆盖层 | 关闭悬浮窗 | — |
| 点击遮罩区域 | 关闭悬浮窗 | — |
| 长按消息 | 复制/分享菜单 | 复制/分享/删除 |
| 左滑消息 | — | 查看消息详情/时间戳 |
| 双击昔涟头像 | 切换输入模式(语音↔文字) | 同左 |