design: add dog park easter egg spec
This commit is contained in:
parent
bd4dad4794
commit
5714802c89
3
.gitignore
vendored
3
.gitignore
vendored
@ -22,5 +22,6 @@ node_modules/
|
|||||||
.omc/
|
.omc/
|
||||||
logs/
|
logs/
|
||||||
.claude/
|
.claude/
|
||||||
docs/superpowers/
|
docs/superpowers/*
|
||||||
|
!docs/superpowers/specs/
|
||||||
.worktrees/
|
.worktrees/
|
||||||
|
|||||||
175
docs/superpowers/specs/2026-06-16-dog-park-easter-egg-design.md
Normal file
175
docs/superpowers/specs/2026-06-16-dog-park-easter-egg-design.md
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
# 关于页面「小狗乐园」彩蛋设计
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
在「关于鸭鸭日历」页面中,版本号目前是一个无实际功能的 `TextButton`。本设计为其增加一个隐藏彩蛋:连续点击版本号 7 次后进入「小狗乐园」页面,全屏循环播放一段彩蛋视频。
|
||||||
|
|
||||||
|
## 目标
|
||||||
|
|
||||||
|
- 提升应用趣味性,给用户一个可发现的隐藏彩蛋。
|
||||||
|
- 保持现有架构:所有 UI 与业务逻辑留在 `:core`,`:app` 仅作为 Activity 壳。
|
||||||
|
- 不引入过度复杂的依赖或状态管理。
|
||||||
|
|
||||||
|
## 设计决策摘要
|
||||||
|
|
||||||
|
| 决策项 | 选择 | 说明 |
|
||||||
|
|--------|------|------|
|
||||||
|
| 总点击次数 | 7 次 | 足够隐藏,又不会太难触发 |
|
||||||
|
| 提示开始时机 | 第 4 次点击 | 前 3 次静默,避免普通用户误触时被打扰 |
|
||||||
|
| 提示文案 | 「再点击 N 下进入小狗乐园」 | N 为剩余次数,简洁明确 |
|
||||||
|
| 超时重置 | 1.5 秒 | 与 Android 开发者选项等经典彩蛋保持一致节奏 |
|
||||||
|
| 进度持久化 | 不持久化 | 离开页面或超时即重置 |
|
||||||
|
| 提示组件 | 系统 Toast | 最符合「小气泡」语义,轻量 |
|
||||||
|
| 视频播放 | Media3 ExoPlayer | 功能强、与 Compose 集成成熟 |
|
||||||
|
| 视频位置 | `core/src/main/assets/video/enter_screen_bg1.mp4` | 与现有 `app_icon.webp` 等资源保持一致 |
|
||||||
|
| 视频显示 | 等比裁剪铺满(`RESIZE_MODE_ZOOM`) | 填满屏幕,视觉沉浸 |
|
||||||
|
| 声音 | 静音 | 不打扰用户 |
|
||||||
|
| 屏幕方向 | 跟随系统 | 不强制横竖屏 |
|
||||||
|
| 退出方式 | 系统返回键 | 支持预测性返回手势,Activity 自然 finish |
|
||||||
|
| 进入过渡动画 | 淡入 400ms | 营造进入彩蛋的仪式感 |
|
||||||
|
| 退出过渡动画 | 默认 slide | 保持现有返回风格 |
|
||||||
|
|
||||||
|
## 触发机制(关于页面)
|
||||||
|
|
||||||
|
### 状态
|
||||||
|
|
||||||
|
- 在 `AboutScreen` 内使用 `remember { mutableIntStateOf(0) }` 保存当前连续点击次数。
|
||||||
|
- 计数为局部状态,不提升到 ViewModel,也不持久化。
|
||||||
|
- `AboutScreen` 离开 Composition 时计数自然消失。
|
||||||
|
|
||||||
|
### 点击行为
|
||||||
|
|
||||||
|
| 当前点击次数 | 行为 |
|
||||||
|
|--------------|------|
|
||||||
|
| 1 ~ 3 | 计数 +1,无 Toast |
|
||||||
|
| 4 | Toast「再点击 3 下进入小狗乐园」 |
|
||||||
|
| 5 | Toast「再点击 2 下进入小狗乐园」 |
|
||||||
|
| 6 | Toast「再点击 1 下进入小狗乐园」 |
|
||||||
|
| 7 | 调用 `onNavigateToDogPark()`,进入彩蛋页面 |
|
||||||
|
|
||||||
|
### 超时重置
|
||||||
|
|
||||||
|
每次点击启动/重启一个 `LaunchedEffect`:
|
||||||
|
|
||||||
|
- 在 1.5 秒内收到下一次点击:取消旧 Job,计数 +1。
|
||||||
|
- 1.5 秒内无新点击:Job 执行,计数重置为 0。
|
||||||
|
|
||||||
|
## 导航链路
|
||||||
|
|
||||||
|
```
|
||||||
|
MainActivity
|
||||||
|
└── startActivityWithSlide → AboutActivity
|
||||||
|
└── onNavigateToDogPark → startActivityWithSlide → DogParkActivity
|
||||||
|
```
|
||||||
|
|
||||||
|
- `AboutActivity` 给 `AboutScreen` 新增回调 `onNavigateToDogPark: () -> Unit`。
|
||||||
|
- `DogParkActivity` 继承 `BaseActivity`,自动获得 edge-to-edge 和 slide 转场支持。
|
||||||
|
|
||||||
|
## 小狗乐园页面
|
||||||
|
|
||||||
|
### 组件
|
||||||
|
|
||||||
|
- `DogParkScreen`:位于 `:core`,无业务参数,只负责全屏视频播放。
|
||||||
|
- `DogParkActivity`:位于 `:app`,继承 `BaseActivity`,壳逻辑。
|
||||||
|
|
||||||
|
### 视频播放
|
||||||
|
|
||||||
|
- 使用 Media3 ExoPlayer + `PlayerView`。
|
||||||
|
- 通过 Compose `AndroidView` 嵌入 `PlayerView`。
|
||||||
|
- 配置:
|
||||||
|
- `resizeMode = RESIZE_MODE_ZOOM`:等比裁剪铺满全屏。
|
||||||
|
- `useController = false`:不显示播放控件。
|
||||||
|
- `player.volume = 0f`:静音。
|
||||||
|
- `repeatMode = Player.REPEAT_MODE_ONE`:循环播放。
|
||||||
|
- 媒体源 URI:`asset:///video/enter_screen_bg1.mp4`。
|
||||||
|
|
||||||
|
### 生命周期
|
||||||
|
|
||||||
|
- `onStart` → `player.play()`
|
||||||
|
- `onStop` → `player.pause()`
|
||||||
|
- `onDestroy` → `player.release()`
|
||||||
|
- 使用 `DisposableEffect` 绑定释放逻辑。
|
||||||
|
|
||||||
|
### 退出
|
||||||
|
|
||||||
|
- 用户按系统返回键或执行返回手势时 Activity finish。
|
||||||
|
- 预测性返回手势由 Manifest 中的 `android:enableOnBackInvokedCallback="true"` 支持。
|
||||||
|
- 退出动画保留 `BaseActivity` 默认 slide。
|
||||||
|
|
||||||
|
## 过渡动画
|
||||||
|
|
||||||
|
### 进入动画(淡入)
|
||||||
|
|
||||||
|
- 新增 `app/src/main/res/anim/fade_in.xml`。
|
||||||
|
- `DogParkActivity.onCreate` 中:
|
||||||
|
- Android 14+:`overrideActivityTransition(OVERRIDE_TRANSITION_OPEN, R.anim.fade_in, R.anim.fade_out)`
|
||||||
|
- 低版本:`overridePendingTransition(R.anim.fade_in, R.anim.fade_out)`(在 `super.onCreate` 之后、`setContent` 之前调用)
|
||||||
|
- 淡入时长约 400ms。
|
||||||
|
|
||||||
|
### 退出动画
|
||||||
|
|
||||||
|
- 保留 `BaseActivity` 默认的 slide 返回动画,不覆盖。
|
||||||
|
|
||||||
|
## 资源
|
||||||
|
|
||||||
|
- 视频文件:
|
||||||
|
- 来源:`~/Pictures/enter_screen_bg1.mp4`
|
||||||
|
- 目标:`core/src/main/assets/video/enter_screen_bg1.mp4`
|
||||||
|
- 动画资源:
|
||||||
|
- 新增 `app/src/main/res/anim/fade_in.xml`
|
||||||
|
|
||||||
|
## 依赖变更
|
||||||
|
|
||||||
|
### `gradle/libs.versions.toml`
|
||||||
|
|
||||||
|
新增:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[versions]
|
||||||
|
androidx-media3 = "1.6.1"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
androidx-media3-exoplayer = { module = "androidx.media3:media3-exoplayer", version.ref = "androidx-media3" }
|
||||||
|
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "androidx-media3" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### `core/build.gradle.kts`
|
||||||
|
|
||||||
|
新增:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
implementation(libs.androidx.media3.exoplayer)
|
||||||
|
implementation(libs.androidx.media3.ui)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
- 视频加载/准备失败时,直接 `finishWithSlideBack()` 静默返回关于页面。
|
||||||
|
- 不显示弹窗或 Snackbar,避免破坏彩蛋体验。
|
||||||
|
|
||||||
|
## 测试计划
|
||||||
|
|
||||||
|
### 单元测试
|
||||||
|
|
||||||
|
- 抽离纯函数 `getToastMessage(clickCount: Int): String?` 并测试:
|
||||||
|
- 1 ~ 3 返回 `null`
|
||||||
|
- 4 返回「再点击 3 下进入小狗乐园」
|
||||||
|
- 5 返回「再点击 2 下进入小狗乐园」
|
||||||
|
- 6 返回「再点击 1 下进入小狗乐园」
|
||||||
|
- 7 返回 `null`(此时已跳转)
|
||||||
|
|
||||||
|
### 手动测试
|
||||||
|
|
||||||
|
- 连续点击版本号 7 次,确认进入 `DogParkActivity`。
|
||||||
|
- 点击过程中停顿 1.5 秒,确认计数重置。
|
||||||
|
- 确认进入动画为淡入。
|
||||||
|
- 确认视频全屏、静音、无控件、循环播放。
|
||||||
|
- 确认系统返回键正常退出,并回到关于页面。
|
||||||
|
- 确认低版本(< Android 14)和 Android 14+ 的淡入动画都生效。
|
||||||
|
|
||||||
|
## 未包含在本期
|
||||||
|
|
||||||
|
- 多次进入彩蛋后的不同内容。
|
||||||
|
- 视频下载/动态更新。
|
||||||
|
- 屏幕常亮保持。
|
||||||
|
- 分享彩蛋入口。
|
||||||
Loading…
x
Reference in New Issue
Block a user