diff --git a/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/.openspec.yaml b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/.openspec.yaml new file mode 100644 index 000000000..a8821c74d --- /dev/null +++ b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-08-11 diff --git a/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/design.md b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/design.md new file mode 100644 index 000000000..06c756171 --- /dev/null +++ b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/design.md @@ -0,0 +1,116 @@ +## 上下文 + +参见 `proposal.md` 的“为什么”和 `specs/kindle-page-turn-animation/spec.md` 的行为契约。当前横向翻页模式由 `ReadView` 选择不同 `PageDelegate`,`HorizontalPageDelegate` 已提供当前页、前一页和后一页的 `CanvasRecorder` 快照以及统一的 `Scroller` 驱动。翻页模式整数同时进入全局阅读配置 JSON 和单本书 Room JSON;设置界面又直接把选项下标作为协议值,因此新增模式必须追加,不能插入或重排。 + +海信 Hi Reader Pro 实机只读调查确认系统存在 `com.hmct.epd.IEpdManager`,但相关 framework 类被标记为非 SDK `BLOCKED`,已提取接口中也没有方向、步数、区域或 swipe 波形能力。后续实机反馈还确认,普通 Android 绘制在清晰模式下基本没有动画,非清晰模式则存在不同程度的残影,因此普通 Canvas 路线已记为 `NO_GO_CLEAR_AND_ANIMATED`。 + +## 目标 / 非目标 + +**目标:** + +- 沿用现有阅读页和 Delegate 边界,以最小增量加入可独立选择的软件扫屏模式。 +- 将视觉进度、页面提交和连续输入拆成明确状态,保证每一页最多提交一次且失败可回退。 +- 在不新增依赖、不改变 Room 结构和最低 SDK 21 的前提下,提供可自动测试的状态逻辑和可人工复现的墨水屏验收流程。 +- 让调试包与设备正式版隔离,保持正式版应用和数据不受影响。 + +**非目标:** + +- 不抽象或实现无真实 SDK 支撑的厂商硬件刷新层。 +- 不尝试规避 Android 非 SDK 限制,不调用海信 Binder、系统签名能力或内核节点。 +- 不改变现有其他五种动画、滚动排版、图片书强制模式、自动阅读、朗读或非相邻跳转逻辑。 +- 不通过新的速度设置暴露调优参数;200ms 只作为极速模式观感较佳的软件候选,不作为核心门槛通过证据。 + +## 技术决策 + +### 1. 追加协议值并保持设置索引兼容 + +在 `PageAnim` 末尾追加值 `5`,并让 `ReadView` 为该值选择新的横向 Delegate。设置布局和单本书选择列表都把新选项追加在现有“无动画”之后,使物理下标继续与协议值一致;不重构其他模式的映射,避免扩大兼容面。普通模式的 `pageAnim`、墨水屏模式的 `pageAnimEInk` 和单本书 `ReadConfig.pageAnim` 沿用现有存储路径。“Kindle翻页动画”保留完整本地化文本,但设置按钮限制为单行并在宽度不足时尾部省略,避免第六个等宽按钮把整行撑高。 + +备选方案是在本次顺便把所有设置改成显式 ID 到协议值映射。它能降低未来重排风险,但会同时改动既有五种模式的读写路径,不符合聚焦变更原则;可在独立重构中处理。 + +### 2. 新 Delegate 复用现有页面录制结果 + +新增一个仅负责 Kindle 风格绘制和状态提交的 `HorizontalPageDelegate` 子类,复用现有 `curRecorder`、`prevRecorder`、`nextRecorder`,不再额外保存全屏 Bitmap。横屏双页天然作为同一个 `ReadView` 画布处理。 + +确认参考视频的 30fps 逐帧结果表明:纸张背景保持稳定,目标页内容停留在最终坐标并从翻页方向一侧逐步显现,起始页内容在同一区域逐步变浅,两页文字会在一段较宽区域内短暂叠印;不存在独立灰色竖条,也不存在整页平移。此前“硬裁剪目标页 + 约 10% 灰色渐变带”的模型已被实机观感否定,不得继续作为实现基础。 + +修订后的绘制单元使用宽幅空间交叉淡变遮罩。每帧先绘制完整起始页,再在隔离图层绘制目标页,并用带方向的透明度渐变限制目标图层:前沿之外一侧保持完整起始页,另一侧显示完整目标页,中间通过目标页透明度从 0 到 1 的连续变化自然产生旧墨迹变浅、新墨迹变深的叠印。遮罩只改变页面像素的混合比例,不额外绘制灰色、阴影或高亮颜色。首个验证值使用约 35% 视口宽度的交叉区,并在目标设备上依据参考观感调整;该比例不会作为用户设置暴露。 + +选择空间交叉淡变而不是逐像素 Bitmap 合成,是因为它可以通过 `Canvas` 隔离图层和透明度遮罩复用现有录制结果,同时保留内容驱动的灰阶叠印语义。实现需要验证 API 21 的 `saveLayer` 与 `DST_IN` 兼容路径;失败时直接显示正确目标页。 + +### 3. 分离扫动位置与内容灰阶缓动 + +首轮实机验证表明,120ms 基本不可辨,160ms 可辨但跳帧感明显,200ms 较完整而 250ms 偏慢;这些观察后来由用户复核为流畅模式结果,不是清晰模式证据。用户指出与参考视频最明显的剩余差异是当前线性扫动不够流畅。参考视频只有 30fps,且同时包含 E‑Ink 面板响应和相机采样,无法据此反推出 Kindle 控制器的精确曲线;逐帧只足以支持首尾变化较缓、中段变化更集中的视觉判断。 + +第二轮曾将归一化时间直接传入 `smoothstep`(`3t² - 2t³`),使扫动位置起步和收尾较慢、中段较快;在同一流畅模式下,120、160、200、220、250ms 五个候选均退化为“一闪而过”,肉眼无法辨认方向。该时间模型记为 `INVALID_EASING_MODEL`,不得作为生产参数;该结果只描述当轮流畅模式实测,不能据此归因清晰模式的面板调度或推断其行为。 + +修订后将两个维度分离:扫动位置恢复按真实经过时间线性跨越视口;仅对交叉区内的目标页透明度使用 `smoothstep`,让旧字变浅和新字变深的灰阶比例在两端更柔和,而不压缩边界穿越时间。Android `LinearGradient` 使用 0、0.25、0.5、0.75、1 五个采样点近似该曲线,遮罩颜色仍只有透明度,不绘制独立灰色。第三轮在流畅模式重点对比 200、220、250ms 后曾选择 220ms;最新四模式复核又确认极速模式动画最好且 200ms 主观更佳,因此软件时间线改为 200ms,但不得把这一选择描述为清晰模式通过。 + +第三轮与第一轮的主观观感没有明显区别,因此实机证据不能证明只对内容混合使用 `smoothstep` 带来了额外的可感知顺滑收益。保留该混合比例是因为它不压缩已验证的线性扫动位置,且仍符合参考视频首尾灰阶变化较缓的有限观察;不得据此声称还原 Kindle 的私有缓动或硬件波形。 + +KOReader 的公开实现也支持这一边界:在 Kindle PW5 等 MTK 设备上,它只向驱动提交方向和 12 个 swipe 步进,平滑波形由 Kindle 驱动生成;社区跨设备软件补丁采用线性硬分条刷新,在 Kobo 可用但已有 Android 墨水屏刷新不同步的公开反馈。两者都不能提供可直接移植的 Android 非线性时间曲线,因此本变更仍以目标设备实测为准,不复制硬分条模型,也不声称复刻私有波形。 + +不安排动画结束 500ms 后的额外 `invalidate`。Kindle 的补刷属于专有控制器行为,普通 Canvas 重绘无法指定同等波形,额外提交可能增加残影和耗电。 + +### 4. 手势只确认方向,不驱动可见进度 + +新 Delegate 单独处理触摸确认:移动阶段只判断是否越过现有触摸阈值、方向和目标页是否存在,不绘制新旧页混合状态;`ACTION_UP` 确认翻页后才准备录制结果并启动时间线。取消或未达到阈值的手势直接回到空闲态,不播放回弹动画。现有其他 Delegate 的跟手行为保持不变。 + +点击、音量键和键盘仍通过既有阅读入口发起上一页或下一页。目录、进度、恢复位置、自动阅读和朗读原本不依赖这一手动动画入口,本次不把它们接入新状态机。 + +### 5. 单动画状态机保证连续输入语义 + +将复杂的页面意图与 View 绘制分离成可单元测试的内部状态控制器,至少包含 `Idle`、`Animating`、`Returning` 和 `Committing`。每段记录起始页、方向、进度和递增的 generation;旧回调发现 generation 不匹配时立即退出,避免中断后的旧 `Scroller` 或 posted callback 再次提交页面。 + +- 空闲时的有效输入准备相邻页并进入 `Animating`。 +- 动画中的同向输入先把当前段推进到终点,只调用一次现有页面提交入口,再为下一页启动新 generation;不保存无界动画 FIFO。 +- 动画中的反向输入不提交目标页,而是从当前进度进入 `Returning` 并回到起始页,使净页面变化为零。 +- 页面边界、内容准备失败或录制失败清空待处理意图并稳定在最后成功页面。 +- 绘制时间超过预算或状态不一致时跳过视觉过程,只执行一次正确提交。 + +备选方案是完整排队每个动画,但连续输入会产生可见延迟;直接中断且不提交会丢页;只保存最终目标页又会让中间页提交与章节边界难以审计。单动画逐段快进在响应性、页数正确性和实现风险之间更平衡。 + +### 6. 新模式单独统一离散按键入口 + +现有实体键路径在长按翻页关闭时有 600ms leading-only 防抖,会丢弃窗口内的独立按键;`PageDelegate.keyTurnPage` 又在动画运行时直接返回。仅当当前 Delegate 是新模式时,活动层应把独立按键直接交给状态机,不使用该防抖;其他模式保留现状。 + +长按翻页关闭时忽略系统 repeat 事件,但每个新的物理按下都计入;开启时接受 repeat 事件并以单调时钟限制为最快约每最终动画时长一页。鼠标滚轮等未在规范中新增的入口沿用现有策略。 + +### 7. 主动选择和故障降级集中在动画入口 + +Hi Reader Pro 实机确认窗口动画、过渡动画和 Animator 时长比例均为 `0`,这是设备运行环境而不表示用户拒绝当前阅读模式。由于“Kindle翻页动画”是用户在应用内的明确主动选择,生产 Delegate 不读取这些全局比例,也不让 `ValueAnimator.areAnimatorsEnabled()` 阻断自身的 200ms 时间线;需要停止视觉效果时,用户可明确切换为“无动画”。页面录制异常、视口尺寸无效、绘制预算不足、生命周期结束或方向变化时,仍终止当前 generation 并稳定提交或回退,不能让视觉错误影响阅读位置。 + +### 8. 四种刷新模式复核推翻旧门槛 + +用户在生产路径复核后确认,前三轮候选和外部录像实际都来自流畅模式。最新四模式结果是:极速模式动画最好、200ms 主观更佳但有残影;流畅模式动画可见但卡顿且有残影;均衡模式很卡顿且仍有残影;清晰模式最终清晰但基本看不到动画。因此旧 `GO` 撤回,普通 Canvas 路线记录为 `NO_GO_CLEAR_AND_ANIMATED`。 + +通过条件仍是从清晰模式开始,肉眼能辨认方向、录像能看到移动中的新旧页边界,并在结束后恢复清晰且没有持续残影。当前证据不满足该条件,任务 5.2 保持未完成;不得用流畅或极速模式录像替代。 + +### 9. 海信自动组合刷新只适用于纵向滚动 + +Hi Reader Pro 的 `Activity` framework 确实包含自动组合刷新:真实纵向滚动越过阈值后设置动态刷新标志、临时切换较快模式,并在收到滚动结束回调后约一秒恢复原模式和清理残影。但横向触摸不会进入该分支,接口中也没有 Kindle 的方向与步数参数。 + +有界 `appDebug` 实验进一步验证:真实横向滑动保持动态标志为 `0`;纵向滚动可使标志发生 `0→1→0`。尝试仅使用标准 `MotionEvent` 和 View 滚动把该流程桥接到横向动画时,事件会递归进入应用手势处理并短暂改变刷新状态,不能可靠满足 `0→1→0`,记为 `NO_GO_UNSAFE_EVENT_BRIDGE`。实验代码已移除;2026-08-13 又通过真实系统列表滚动让 framework 将遗留动态标志恢复为 `0`,切回正式阅读页后当前应用刷新配置为清晰模式 `3`。不得将该桥接接入生产。 + +### 10. 实机测试隔离正式版 + +实机只构建、安装或更新 `appDebug`(`io.legado.app.debug`)。安装前再次只读确认包名;不得对 `io.legado.app.release` 执行安装覆盖、卸载、清数据或降级。调试数据独立创建,不从正式版复制书籍、配置或凭据;验收使用可公开或临时导入的测试文本。 + +### 11. 测试分层 + +把纯状态转换、协议值和设置映射作为 JVM 单元测试重点;Delegate 选择、裁剪方向、无效视口、录制失败和页面提交次数使用可行的 Android/Robolectric 或聚焦设备验证覆盖。实机还需确认系统动画时长比例为 `0` 时生产路径仍播放。物理 E‑Ink 是否显示扫动只能依赖外部观察,ADB 截图或录屏仅能证明应用生成了帧,不能代替面板验收。 + +## 风险 / 权衡 + +- [清晰模式实测基本看不到普通 Canvas 动画,非清晰模式保留动画却产生残影] → 记为 `NO_GO_CLEAR_AND_ANIMATED`;不推断厂商内部如何调度中间帧,停止把普通 Canvas 调参当作核心目标解决方案。 +- [利用纵向组合刷新桥接横向动画导致事件递归或刷新状态悬挂] → 记为 `NO_GO_UNSAFE_EVENT_BRIDGE`,移除实验代码,不进入生产。 +- [连续输入中旧回调二次提交页面] → 每段使用 generation,所有完成和中断路径集中到单一提交函数并测试提交计数。 +- [交叉淡变在深色主题出现背景明暗接缝] → 遮罩只混合完整页面录制结果,不绘制独立颜色;覆盖浅色、深色和 E‑Ink 人工验证,若背景仍出现接缝则调整交叉区宽度或降级为无动画。 +- [录制三页增加绘制成本] → 复用既有 CanvasRecorder,方向确定后只刷新当前页和一个目标页;预算不足直接无动画降级。 +- [新增整数值破坏历史配置] → 只在尾部追加 `5`,补充 `0..4` 稳定性、JSON 读取和旧值兜底测试;不新增 Room 列或迁移。 +- [“Kindle翻页动画”被理解为 Amazon 官方实现] → 本地化和维护说明只陈述视觉风格,不声称官方授权、专有波形或完全复刻。 +- [调试安装影响用户正式版] → 使用独立 applicationId,安装前核对目标包,禁止触碰正式版和其数据。 + +## 迁移与回滚 + +本变更不修改 Room schema、最低 SDK、规则格式、导入 URI 或备份结构。升级时仅增加可选值,默认行为不变。若回滚实现,已经保存值 `5` 的新版本配置在旧代码中会按现有未知值路径降级为无动画;值 `5` 不得在未来复用于其他语义。回滚不需要数据库迁移,也不得为了清理该值改写用户阅读配置。 diff --git a/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/proposal.md b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/proposal.md new file mode 100644 index 000000000..c2d4cd180 --- /dev/null +++ b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/proposal.md @@ -0,0 +1,34 @@ +## 为什么 + +Legado 现有横向翻页模式无法呈现 Kindle Paperwhite 5 那种快速、定向且最终清晰的电子墨水扫屏效果。实机复核确认,普通 Android 逐帧绘制在海信 Hi Reader Pro 上只能在“快速模式可见但有残影”和“清晰模式最终清晰但中间帧不可见”之间取舍,不能单独满足核心目标。系统自动组合刷新路线也已验证失败:它只响应纵向滚动,横向标准事件桥接会递归进入应用手势处理,无法安全用于翻页。本变更需要保留可复用的软件候选及完整失败证据,并明确在当前权限边界内不得把核心能力标记为实现完成。 + +## 变更内容 + +- 新增第六种独立翻页模式“Kindle翻页动画”,保持纸张背景稳定,通过宽幅空间交叉淡变让新页墨迹显现、旧页墨迹滞后消退,并按前后翻页方向形成短暂的文字叠印扫动。 +- 将该模式接入普通阅读设置、墨水屏阅读设置和单本书覆盖设置,并同步维护现有八套语言资源;现有默认值和用户配置保持不变。 +- 将动画限制在普通分页文字及少量插图的手动相邻翻页;目录跳转、进度跳转、自动阅读、朗读翻页、图片书、漫画和 RSS 保持现有行为。 +- 统一该模式下点击、滑动松手、音量键和键盘的连续翻页状态:同向输入逐页快进并继续,反向输入按净意图抵消,长按沿用现有开关并限速。 +- 用户主动选择该模式后,即使墨水屏设备把系统动画时长比例固定为 `0` 也播放翻页动画;视口无效、性能不足和渲染失败时仍无动画降级,保证最终页面、页数和章节边界正确。 +- 撤回此前基于错误刷新模式记录得到的“清晰模式 GO”和 220ms 最终参数;将普通 Canvas 路线记录为 `NO_GO_CLEAR_AND_ANIMATED`,200ms 仅作为极速模式下观感较好的软件候选,不作为核心目标完成证据。 +- 已在海信 Hi Reader Pro(`HLTE556N`、Android 11)上完成 framework 自动组合刷新审计与有界实验:纵向滚动能触发临时动态刷新并结束,横向滑动不会触发;标准事件桥接存在递归和刷新状态失控风险,记为 `NO_GO_UNSAFE_EVENT_BRIDGE`,不接入生产。 +- 当前结论为 `NO_GO_CLEAR_AND_ANIMATED`:生产代码中的 200ms 软件效果只适用于普通屏幕或设备快速模式候选,不能等同 Kindle 的专用硬件 swipe 波形,也不能作为“清晰且有动画”已经实现的证据。 +- **非目标**:不直接调用海信私有 Binder、隐藏 API 或 sysfs,不持久切换设备全局刷新模式,不实现 Kindle 专有硬件波形,不要求 root 或系统签名,不新增未经真实厂商行为验证的通用硬件适配抽象,不改变 RTL 排版、图片书、漫画、RSS 或网页端行为。 + +## 能力 + +### 新增能力 + +- `kindle-page-turn-animation`:规定 Kindle 风格软件扫屏动画的设置、适用范围、交互状态、兼容降级和实机验收要求。 + +### 修改能力 + +无。当前主规范中没有阅读翻页动画能力。 + +## 影响 + +- 受影响模块:仅 Android `app/`,主要涉及翻页模式常量、`ReadView`/`PageDelegate` 链路、阅读设置与单本书设置、字符串资源及聚焦测试;`modules/book/`、`modules/rhino/` 和 `modules/web/` 不受影响。 +- 用户可感知变化:用户可以主动选择“Kindle翻页动画”;默认翻页方式不变。前进和后退具有相反扫动方向,扫动区只由新旧页面内容的灰阶叠印构成,不显示独立灰色条;横屏双页作为一个完整阅读区域扫过。 +- 兼容性与持久化:新模式必须追加为整数值 `5`,既有 `0..4` 含义不得改变。全局 JSON 与单本书 Room JSON 可保存新值,无需新增数据库列或 Room 迁移;旧版本读取 `5` 时按现有兜底行为降级为无动画。 +- 安全与设备边界:实现不得包含从 Hi Reader Pro 提取的私有 framework 文件,不得直接调用 `com.hmct.epd` 服务或写入 EPD 控制节点;调试验证只安装独立包名 `io.legado.app.debug`,不得卸载、覆盖或清理设备上的 `io.legado.app.release` 及其数据。 +- 依赖:不新增第三方依赖,不升级现有依赖,不引入 Room 结构变化。 +- 可观察验收:目标设备初始保持清晰模式;翻页期间肉眼和外部录像均可辨认移动中的新旧墨迹叠印区,动画结束后文字恢复清晰且没有持续残影,纸张背景不得出现独立灰条。连续 20 次有效下一页最终尽量前进 20 页;正反输入可抵消;竖屏、横屏双页、浅色和深色主题显示正确;系统动画时长比例为 `0` 时主动选择的新模式仍播放,性能或设备能力不足时直接稳定显示正确目标页,且无崩溃、白屏或重复提交。当前该清晰且有动画的门槛尚未通过。 diff --git a/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/specs/kindle-page-turn-animation/spec.md b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/specs/kindle-page-turn-animation/spec.md new file mode 100644 index 000000000..3c0397b31 --- /dev/null +++ b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/specs/kindle-page-turn-animation/spec.md @@ -0,0 +1,130 @@ +## Purpose + +为分页文字阅读提供一种可主动选择、兼容既有阅读配置且不依赖厂商私有接口的 Kindle 风格定向扫屏动画,并规定连续翻页、无障碍降级、设备安全边界和墨水屏实机验收行为。 + +## ADDED Requirements + +### Requirement: 独立且向后兼容的动画选项 +系统 SHALL 将“Kindle翻页动画”作为新的独立翻页模式提供给普通阅读设置、墨水屏阅读设置和单本书覆盖设置,并 SHALL 保持现有翻页模式的默认值、持久化整数含义和已保存用户选择不变。该模式的持久化值 MUST 追加为 `5`,不得重排既有 `0..4`;所有现有语言资源 SHALL 提供本地化名称。 + +#### Scenario: 老用户升级后保持原动画 +- **WHEN** 用户升级前保存了任一既有 `0..4` 翻页模式 +- **THEN** 升级后系统 SHALL 继续解释为同一种模式,且不得自动切换为“Kindle翻页动画” + +#### Scenario: 用户在不同设置作用域选择新动画 +- **WHEN** 用户在普通阅读、墨水屏阅读或单本书覆盖设置中选择“Kindle翻页动画” +- **THEN** 系统 SHALL 在对应作用域保存值 `5`,且其他作用域的选择 SHALL 保持独立 + +#### Scenario: 设置面板宽度不足 +- **WHEN** “Kindle翻页动画”的本地化名称超过设置按钮的单行可用宽度 +- **THEN** 系统 SHALL 在按钮末尾显示省略号且不得把该按钮扩展为两行,并 SHALL 保留完整本地化名称作为控件文本 + +#### Scenario: 旧版本读取新配置 +- **WHEN** 不认识值 `5` 的旧版本读取包含该值的全局或单本书阅读配置 +- **THEN** 旧版本 SHALL 按既有未知值兜底行为使用无动画,不得破坏配置文件或书籍数据 + +### Requirement: 快速定向墨迹叠印视觉 +系统 SHALL 在已确认的手动相邻翻页后保持页面背景稳定,以宽幅空间交叉淡变让目标页墨迹逐步显现、起始页墨迹逐步消退。交叉区 SHALL 由两页内容自身的灰阶叠印形成,不得绘制独立灰色条、阴影幕布或整页位移。下一页 SHALL 从右向左扫过,上一页 SHALL 从左向右扫过;扫动位置 SHALL 按经过时间均匀跨越视口,交叉区内的新旧内容混合 SHALL 使用首尾较缓、中段较快的非线性灰阶比例。软件时间线 SHALL 使用实机反馈较佳的 200ms,但该参数本身不得作为清晰模式可行性证据。 + +#### Scenario: 翻到下一页 +- **WHEN** 用户触发有效的手动下一页操作 +- **THEN** 系统 SHALL 让新页墨迹从右侧按最终位置逐步显现、旧页墨迹滞后消退,使内容叠印区从右向左扫过,并在结束时稳定显示下一页 + +#### Scenario: 翻到上一页 +- **WHEN** 用户触发有效的手动上一页操作 +- **THEN** 系统 SHALL 让新页墨迹从左侧按最终位置逐步显现、旧页墨迹滞后消退,使内容叠印区从左向右扫过,并在结束时稳定显示上一页 + +#### Scenario: 过渡只来自页面内容 +- **WHEN** 动画处于新旧页面交叉淡变阶段 +- **THEN** 纸张或主题背景 SHALL 保持视觉稳定,新旧文字或插图 MAY 短暂以不同灰阶重叠,但系统 MUST 不得用独立纯色条带表示扫动边界 + +#### Scenario: 横屏双页翻页 +- **WHEN** 阅读界面以横屏双页显示且用户触发有效相邻翻页 +- **THEN** 系统 SHALL 将整个可见阅读内容区域作为一个连续画面一次扫过,不得按左右页分别播放两次动画 + +#### Scenario: 阅读界面元素参与动画 +- **WHEN** 动画覆盖的页面包含正文内页眉、页脚、章节名、页码或少量插图 +- **THEN** 这些阅读内容 SHALL 随页面共同扫过,而系统状态栏、导航栏、阅读菜单和弹窗 SHALL 保持不参与动画 + +### Requirement: 仅对手动相邻分页生效 +系统 SHALL 仅对分页文字阅读中的手动相邻翻页播放该动画,包含点击、滑动松手、音量键和键盘操作;动画 SHALL 在翻页已确认后开始,不得在拖动过程中跟随手指。自动产生的页面变化和非相邻跳转 MUST 保持现有行为。 + +#### Scenario: 滑动确认后翻页 +- **WHEN** 用户完成滑动手势且系统确认前进或后退一页 +- **THEN** 系统 SHALL 在手势松开后播放相应方向的动画 + +#### Scenario: 手势取消 +- **WHEN** 用户的滑动手势未达到翻页条件或被取消 +- **THEN** 系统 SHALL 保持原页且不得播放翻页动画 + +#### Scenario: 相邻翻页跨越章节 +- **WHEN** 用户通过下一页或上一页操作跨越章节边界且相邻页面内容已准备完成 +- **THEN** 系统 SHALL 为该相邻页面变化播放一次动画 + +#### Scenario: 非相邻或自动页面变化 +- **WHEN** 页面因目录跳转、进度跳转、恢复阅读位置、切换书籍、自动阅读或朗读而变化 +- **THEN** 系统 MUST 不播放“Kindle翻页动画”,并 SHALL 保持对应功能现有的页面切换行为 + +#### Scenario: 非目标内容类型 +- **WHEN** 用户阅读图片书、漫画或 RSS,或者内容继续使用既有非分页布局 +- **THEN** 系统 SHALL 保持该内容类型现有的翻页或滚动规则,不得强制应用新动画 + +### Requirement: 连续输入按净翻页意图处理 +系统 SHALL 让每次有效的手动翻页输入尽量对应一页变化,不得因动画正在运行而使用现有按键防抖静默丢弃输入。同向输入 SHALL 快速完成当前段并继续下一页;尚未完成的反向输入 SHALL 按净意图抵消。长按按键 SHALL 沿用现有长按翻页开关,并在启用时将连续翻页速率限制为最快约每最终动画时长一页。 + +#### Scenario: 连续同向翻页 +- **WHEN** 用户在当前动画结束前再次触发同方向的有效翻页 +- **THEN** 系统 SHALL 快速完成并只提交当前目标页一次,然后立即开始下一页,且停止输入后 SHALL 完整结束最后一段动画 + +#### Scenario: 动画中反向翻页 +- **WHEN** 用户在尚未完成的下一页动画中触发上一页,或在尚未完成的上一页动画中触发下一页 +- **THEN** 系统 SHALL 从当前视觉进度反向返回起始页,并使两次输入的净页面变化为零 + +#### Scenario: 音量键长按翻页 +- **WHEN** 用户启用了长按翻页并持续按住受支持的音量键 +- **THEN** 系统 SHALL 连续翻页但 MUST 将速率限制为最快约每最终动画时长一页 + +#### Scenario: 连续二十次有效下一页 +- **WHEN** 当前阅读位置之后至少还有二十页且用户连续触发二十次有效下一页 +- **THEN** 系统 SHALL 最终前进二十页,不得白屏、崩溃、重复提交或因动画防抖丢页 + +### Requirement: 主动选择与故障安全降级 +用户主动选择该模式后,系统 SHALL 不因 Android 全局动画时长比例为 `0` 而跳过翻页动画。动画准备、绘制或性能预算不足时,系统 MUST 将视觉效果降级为无动画,不得将动画失败转化为翻页失败。 + +#### Scenario: 墨水屏设备关闭系统动画 +- **WHEN** 用户主动选择“Kindle翻页动画”且设备把窗口、过渡或 Animator 动画时长比例设为 `0` +- **THEN** 系统 SHALL 仍播放该模式自身的 200ms 扫屏过程;用户可通过选择“无动画”关闭该效果 + +#### Scenario: 动画无法按预算完成 +- **WHEN** 页面快照、绘制或调度无法在允许的性能和时间预算内可靠完成 +- **THEN** 系统 SHALL 跳过或终止视觉动画并只提交正确目标页一次 + +#### Scenario: 页面加载失败或到达边界 +- **WHEN** 目标页面加载失败,或用户已到达书籍边界而没有有效目标页 +- **THEN** 系统 SHALL 停留在最后一个成功页面、清除待处理翻页意图,并不得显示空白目标页 + +### Requirement: 清晰模式可行性门槛与当前停止条件 +系统 MUST 在海信 Hi Reader Pro(设备标识 `HLTE556N`、Android 11)初始处于清晰刷新模式时,证明定向墨迹叠印扫动可感知且动画结束后文字恢复清晰、没有持续残影,才可将该能力标记为实现完成。普通 Canvas 逐帧方案已记录为 `NO_GO_CLEAR_AND_ANIMATED`;系统自动组合刷新也已确认只响应纵向滚动,横向标准事件桥接记为 `NO_GO_UNSAFE_EVENT_BRIDGE`。在不调用厂商私有接口、无 root 且无系统签名的当前范围内,系统 MUST 保持该能力未完成,不得继续把软件时长或缓动调参当作核心门槛验证。 + +#### Scenario: 清晰模式验证通过 +- **WHEN** 调试版本从目标设备清晰模式开始执行前后翻页测试 +- **THEN** 肉眼 SHALL 能辨认扫动方向,外部录像 SHALL 能捕获移动中的内容叠印区,系统 SHALL 在动画结束后恢复清晰显示,页面背景 SHALL 保持稳定且最终文字 SHALL 稳定正确、没有持续残影 + +#### Scenario: 清晰模式验证失败 +- **WHEN** 普通 Canvas 在清晰模式下无法辨认扫动方向,或系统自动组合刷新无法由横向翻页安全触发 +- **THEN** 该能力 MUST 不得标记为实现完成,组合刷新接入及后续完整功能开发 SHALL 记为 `NOT_RUN_PROTOCOL_STOP`,并返回实机证据供重新决策 + +### Requirement: 不越过设备私有接口边界 +系统 MUST 使用普通 Android 应用可用的绘制与事件分发能力实现首版动画,可以让海信 framework 自身响应标准触摸事件并自动选择临时刷新策略,但应用不得直接调用海信私有 Binder、隐藏 API、sysfs 控制节点、root 或系统签名能力,不得持久切换设备全局刷新模式,也不得自行在动画结束后调用私有清屏或补刷能力。 + +#### Scenario: 在 Hi Reader Pro 上运行 +- **WHEN** “Kindle翻页动画”在目标设备上播放 +- **THEN** 系统 SHALL 仅提交普通应用绘制结果和标准触摸事件,不得由应用调用 `com.hmct.epd`、写入 EPD 控制节点或持久更改全局刷新模式 + +#### Scenario: 动画结束后稳定显示 +- **WHEN** 动画已完成并提交最终页面 +- **THEN** 系统 SHALL 由 Android 和设备刷新策略自然稳定画面,不得调用私有强制清屏能力或安排 500ms 延迟补刷 + +#### Scenario: 安装实机调试版本 +- **WHEN** 在已安装 `io.legado.app.release` 的目标设备上执行实机验证 +- **THEN** 仅 SHALL 安装或更新独立包名 `io.legado.app.debug`,不得卸载、覆盖、清除或修改正式版及其数据 diff --git a/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/tasks.md b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/tasks.md new file mode 100644 index 000000000..f4aeebc62 --- /dev/null +++ b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/tasks.md @@ -0,0 +1,44 @@ +## 1. 清晰模式可行性门槛 + +- [x] 1.1 实现不依赖厂商接口的最小可复用宽幅空间交叉淡变绘制单元,使灰阶叠印只来自新旧页面内容且不绘制独立灰条;根据实机反馈保持扫动位置按时间线性跨越视口,仅将交叉区内容混合修订为首尾较缓、中段较快的非线性灰阶比例,并补充方向、交叉区位置、内容混合比例和时间进度的聚焦测试。 +- [x] 1.2 增加仅用于 `appDebug` 的最小实机验证入口,使用固定文字页面依次运行 120、160、200、220、250ms 的前进和后退动画,不接入海信 Binder、隐藏 API、sysfs 或全局刷新模式切换。 +- [x] 1.3 更正首轮至第三轮的刷新模式证据:用户复核确认相关可见动画实际来自流畅模式;补记极速、流畅、均衡和清晰模式的动画、卡顿、残影与最终清晰度结果,不再把既有录像标为清晰模式证据。 +- [x] 1.4 将普通 Canvas 路线记录为 `NO_GO_CLEAR_AND_ANIMATED`:清晰模式基本无动画,非清晰模式存在残影;撤回旧 `GO` 和 220ms 最终参数,200ms 仅保留为极速模式软件候选。 +- [x] 1.5 只读审计 Hi Reader Pro framework 的自动组合刷新流程,确认只有标准纵向滚动会进入动态刷新并在滚动结束后恢复模式;横向触摸不会触发,且该流程不提供 Kindle 的方向与步数波形接口。 +- [x] 1.6 在仅用于 `appDebug` 的固定文字页执行有界组合刷新实验:真实横向滑动未触发动态刷新;标准事件桥接发生递归并短暂改变刷新状态,记为 `NO_GO_UNSAFE_EVENT_BRIDGE`,代码已移除,设备动态标志已由 framework 正常恢复为 `0`。 + +## 2. 动画协议、设置与本地化 + +- [x] 2.1 在 `PageAnim` 尾部追加协议值 `5` 并更新注解范围,补充既有 `0..4` 含义不变和未知值仍降级为无动画的兼容测试。 +- [x] 2.2 将新值接入 `ReadView` 的 Delegate 选择,并确认图片书、滚动模式、自动阅读和非相邻跳转的既有选择逻辑不被改变。 +- [x] 2.3 在普通阅读、墨水屏阅读和单本书覆盖设置末尾追加“Kindle翻页动画”,保持列表下标与持久化值一致,为现有八套语言资源提供自然本地化名称,并让宽度不足的设置按钮保持单行尾部省略。 +- [x] 2.4 补充全局阅读配置 JSON 和单本书阅读配置 JSON 的读取、写入与旧配置回归测试,确认无需 Room 列、schema 快照或迁移变化。 + +## 3. 生产动画与连续输入状态 + +- [x] 3.1 以普通屏幕及快速刷新模式的软件候选参数实现生产 Delegate:移动阶段仅确认手势,松手后按方向播放;横屏双页作为完整视口绘制,阅读内容参与动画而系统栏和弹窗不参与;该实现不作为清晰模式门槛通过证据。 +- [x] 3.2 实现可独立测试的 `Idle`、`Animating`、`Returning`、`Committing` 状态及 generation 失效保护,保证同向输入逐页快进、反向输入净抵消、每页最多提交一次、边界与加载失败清空待处理意图。 +- [x] 3.3 仅为新动画统一点击、音量键和键盘的离散翻页入口:绕过现有 600ms 丢弃式防抖,长按关闭时忽略 repeat,长按开启时限制为最快约每最终动画时长一页;其他动画行为保持不变。 +- [x] 3.4 用户主动选择新模式后不受设备系统动画时长比例为 `0` 的影响;在动画入口处理视口无效、录制或绘制失败、生命周期销毁和方向变化,统一降级为正确最终页或原页,不安排 500ms 补刷。 +- [x] 3.5 移除清晰模式调试入口和候选参数切换代码,只保留选定的生产参数、可复用绘制代码及必要测试夹具。 +- [ ] 3.6 `NOT_RUN_PROTOCOL_STOP`:任务 1.6 未通过,不得把组合刷新桥接接入点击、滑动、音量键和键盘;如需继续,必须先明确批准海信私有接口或更高权限的范围扩张并重新设计。 + +## 4. 聚焦自动化与普通屏幕验证 + +- [x] 4.1 为状态控制器补充连续二十次同向输入、动画中反向抵消、章节或书籍边界、旧 generation 回调、失败降级和单次提交计数测试。 +- [x] 4.2 为手势补充未越阈值取消、松手后才启动、前后方向和目标页缺失场景;为按键补充独立快速按下不丢页及长按限速场景。 +- [ ] 4.3 在普通 Android 屏幕人工验证竖屏、横屏双页、浅色、深色、少量插图和跨章节;确认系统动画时长比例为 `0` 时主动选择的新模式仍播放,非相邻跳转不播放,并记录实际结果。 + +## 5. Hi Reader Pro 最终实机验收 + +- [x] 5.1 仅安装或更新 `io.legado.app.debug`,确认未对 `io.legado.app.release` 执行覆盖、卸载、清数据或降级;使用独立调试数据和可公开测试文本。 +- [ ] 5.2 `NO_GO_CLEAR_AND_ANIMATED`:清晰模式基本看不到动画,非清晰模式存在残影,尚未满足前进、后退、横屏双页、浅色和深色主题均“扫动可见且最终清晰”的物理屏幕门槛。 +- [ ] 5.3 `NOT_RUN_PROTOCOL_STOP`:任务 5.2 未通过,不继续用二十次翻页、反向抵消或按键验收包装未达成的核心硬件效果;状态机与限速语义仅保留自动化证据,设备验收等待重新批准硬件范围后执行。 +- [x] 5.4 审计 APK 和代码差异,确认不包含提取的海信 framework 文件、`com.hmct.epd` 调用、隐藏 API、sysfs、root、系统签名、全局刷新模式切换或 500ms 延迟补刷。 + +## 6. 最终项目检查 + +- [x] 6.1 运行 `./gradlew :app:testAppDebugUnitTest`,修复本变更引入的失败并记录真实结果。 +- [ ] 6.2 `BASELINE_LINT_BLOCKED`:`:app:assembleAppDebug` 成功且本变更新增文件没有 lint 错误,但 `:app:lintAppDebug` 仍因项目既有 14 个错误失败;未经独立授权不修改 lint 基线或顺手修复无关错误。 +- [x] 6.3 运行 `git diff --check`、检查 `git diff --stat`,确认没有 Room schema、依赖升级、生成物、设备私有文件或无关格式化差异。 +- [x] 6.4 运行 `openspec validate --all --strict`,核对提案、规范、设计、任务与实际 GO/NO-GO 及实机验证状态一致;未执行或协议停止的项目不得标记完成。 diff --git a/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/verification.md b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/verification.md new file mode 100644 index 000000000..85be930d5 --- /dev/null +++ b/openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/verification.md @@ -0,0 +1,200 @@ +# 验证记录 + +## 刷新模式证据更正与前置门槛 + +### 本地构建与隔离检查 + +- 日期:2026-08-11 +- 分支:`codex/add-kindle-page-turn-animation` +- 历史聚焦测试:旧版 `KindlePageTurnTimelineTest` 曾通过,但其“硬裁剪 + 独立灰条”视觉模型已被否定,不再作为当前任务 1.1 的完成证据。 +- 调试构建:`:app:assembleAppDebug` 成功。 +- 当前 APK:`app/build/outputs/apk/app/debug/legado_app_3.26.081200.apk` +- APK manifest 包名:`io.legado.app.debug`。 +- 历史调试入口:`io.legado.app.ui.debug.KindlePageTurnDebugActivity` 曾仅由 `app/src/debug` 提供;完成候选测试后已从当前源码和生产调试包删除。 +- 安装结果:旧视觉原型曾以 `io.legado.app.debug` 全新安装;第二轮非线性时间缓动版和第三轮非线性内容混合版均通过不带降级参数的 `adb install -r` 更新成功,专用验证 Activity 启动成功且系统状态为 `Resumed`,未发现启动崩溃。 +- 正式版保护:安装后 `io.legado.app.debug` 与 `io.legado.app.release` 同时存在;未对正式版执行安装覆盖、卸载、清数据或降级操作。 + +### 目标设备 + +- 设备:海信 Hi Reader Pro,ADB 型号实测为 `HLTE556N`,序列号为 `7a219732`。 +- 系统:实测为 Android 11,API 30。 +- 刷新模式更正:用户于 2026-08-12 复核确认,首轮、第二轮、第三轮和 `IMG_1005.MOV` 实际均在流畅模式下完成;此前“清晰模式”的记录无效。 +- ADB 状态:2026-08-12 已连接,第三轮调试入口已启动;设备显示为唤醒状态,Activity 为当前 `ResumedActivity`,等待用户观察物理屏幕。 + +### 第一轮候选时长观察:线性扫动与线性内容混合 + +以下项目只能由物理屏幕观察和外部录像判定,ADB 截图或录屏不能替代: + +| 时长 | 前进方向肉眼可辨 | 后退方向肉眼可辨 | 外部录像可见移动边界 | 最终文字稳定 | 备注 | +| --- | --- | --- | --- | --- | --- | +| 120ms | 基本不可辨 | 基本不可辨 | 待验证 | 是 | 肉眼基本看不出动画 | +| 160ms | 可辨 | 可辨 | 待验证 | 是 | 能看出动画,但肉眼感觉有掉帧 | +| 200ms | 完整可辨 | 完整可辨 | 待验证 | 是 | 动画较完整,但仍有轻微掉帧感;首轮优先候选 | +| 220ms | 待验证 | 待验证 | 待验证 | 待验证 | 新增非线性缓动精调候选,等待第二轮实机观察 | +| 250ms | 完整可辨 | 完整可辨 | 待验证 | 是 | 动画完整,但主观速度偏慢 | + +用户对修订视觉的当轮观察:不再出现独立灰条;下一页从右向左、上一页从左向右出现宽幅文字叠印;旧字逐渐变浅、新字逐渐变深;纸张背景基本稳定;动画结束后文字内容稳定。与 Kindle 参考视频最明显的剩余差异是当前线性速度带来的跳帧感,而参考视频呈现非线性节奏,主观观感更流畅。随后四模式复核确认流畅模式仍有面板残影,因此本段早期“没有异常残影”的主观记录不再作为最终清晰度证据。 + +### 第二轮候选时长观察:非线性时间扫动 + +第二轮把扫动位置改为对称 `smoothstep` 时间缓动。用户在同一目标设备的流畅模式下观察后确认,五个选项都只是一闪而过,已无法辨认动画: + +| 时长 | 前进方向肉眼可辨 | 后退方向肉眼可辨 | 最终文字稳定 | 备注 | +| --- | --- | --- | --- | --- | +| 120ms | 不可辨 | 不可辨 | 待确认 | 一闪而过 | +| 160ms | 不可辨 | 不可辨 | 待确认 | 一闪而过 | +| 200ms | 不可辨 | 不可辨 | 待确认 | 一闪而过 | +| 220ms | 不可辨 | 不可辨 | 待确认 | 一闪而过 | +| 250ms | 不可辨 | 不可辨 | 待确认 | 一闪而过 | + +结论:`INVALID_EASING_MODEL`。对扫动位置直接应用对称 `smoothstep` 后,当轮流畅模式的五个候选都失去首轮已经可见的方向感;现有证据不能说明清晰模式如何处理或调度中间帧。停止第二轮外部录像,不将其结果作为 GO 证据。 + +### 第三轮候选时长观察:线性扫动与非线性内容混合 + +第三轮恢复扫动位置的线性时间进度,仅在宽幅交叉区内部使用 `smoothstep` 灰阶混合,默认回到首轮最优的 200ms。用户在同一目标设备的流畅模式下重点对比 200、220、250ms,结果如下: + +| 时长 | 横向扫动肉眼可辨 | 无独立灰条 | 最终文字稳定 | 综合观感 | +| --- | --- | --- | --- | --- | +| 200ms | 是 | 是 | 是 | 可用,但综合效果不如 220ms | +| 220ms | 是 | 是 | 是 | 三个速度中综合效果最好 | +| 250ms | 是 | 是 | 是 | 可用,但综合效果不如 220ms | + +用户确认本轮询问的四项均达到要求,前进和后退方向仍符合既定模型,纸张背景保持基本稳定。120ms 与 160ms 本轮未作新的重点比较,继续沿用第一轮的肉眼结论,不据此新增证据。第三轮总体观感与第一轮没有明显区别,因此只能确认线性扫动位置恢复了可见方向,不能证明仅对内容混合使用 `smoothstep` 带来了可感知的额外顺滑收益。 + +### 门槛结论 + +旧结论 `GO` 已撤回。上述三轮只能证明流畅模式能够显示软件中间帧,不能证明清晰模式可行,也不能证明结束后无面板残影。当前门槛结论为 `NO_GO_CLEAR_AND_ANIMATED`;任务 5.2 保持未完成。 + +最新四模式复核如下: + +| 海信模式 | 动画表现 | 卡顿 | 残影/清晰度 | 结论 | +| --- | --- | --- | --- | --- | +| 极速 | 动画效果最好,200ms 主观优于 220ms | 较少 | 有残影 | 仅保留 200ms 软件候选 | +| 流畅 | 动画可见 | 有卡顿 | 有残影 | 不满足核心目标 | +| 均衡 | 动画可见性不足 | 很卡顿 | 有残影 | 不满足核心目标 | +| 清晰 | 基本看不到动画 | 不适用 | 最终清晰 | 不满足核心目标 | + +### 第三轮外部录像逐帧复核 + +- 录像:用户提供的 `IMG_1005.MOV`,HEVC、1080×1920、约 5.652 秒,视频轨名义帧率约 59.982fps;录像文件仅作本地验证证据,不纳入仓库。 +- 测试条件:画面显示 Hi Reader Pro 的独立调试入口、220ms 被选中,依次执行两次下一页和两次上一页;刷新模式现已更正为流畅模式。 +- 第一次下一页:约 1.67–1.90 秒的连续帧可见目标页文字先在右侧出现并向左扩展,新旧文字在移动区内重叠,随后稳定在固定测试页 2/3。 +- 第二次下一页:约 2.62–2.90 秒的连续帧再次捕获右侧先变化、随后向左覆盖的文字叠印,最终稳定在固定测试页 3/3。 +- 第一次上一页:约 3.72–3.98 秒的连续帧可见左侧内容先恢复并向右扩展,最终稳定在固定测试页 2/3。 +- 第二次上一页:约 4.65–4.98 秒的连续帧可见相反方向的内容恢复,最终稳定在固定测试页 1/3。 +- 独立灰条:四段过渡均未发现贯穿页面的纯色灰条、阴影幕布或整页平移;可见灰阶来自新旧文字的重叠与面板响应。 +- 背景与结束状态:纸张背景在相机曝光允许范围内保持基本稳定,每次过渡后页面均清晰稳定,没有白屏、崩溃或异常持续残影。 +- 与参考视频比较:两者都表现为固定坐标上的新旧文字灰阶叠印和定向扫过;当前录像能看到更明显的离散推进,而 Kindle 参考的变化更集中、更连贯,因此不能声称视觉完全一致或还原其专有波形。 + +### 海信自动组合刷新审计与有界实验 + +- 只读反汇编确认,Hi Reader Pro 的 `android.app.Activity.refreshEpdDisplayMode`、`setEnablePageScroll` 等方法属于非 SDK framework 能力;`IEpdManager` 没有 Kindle 那种方向、步数或 swipe 波形参数。 +- framework 的自动组合刷新只在纵向位移越过阈值且明显大于横向位移时进入;真实横向滑动没有触发,`sys.hmct.dynamic_refreshing_flag` 保持 `0`。 +- 纵向对照实验证明系统流程本身有效:动态标志可从 `0` 变为 `1`,framework 临时切换快速模式,并在真实 View 滚动结束后恢复原模式、执行清残影收尾并把标志恢复为 `0`。 +- 仅使用标准 `MotionEvent` 和 View 滚动把纵向流程桥接到横向 200ms 动画时,事件递归进入应用手势处理并反复触发刷新状态,不能可靠完成单次 `0→1→0`,结论为 `NO_GO_UNSAFE_EVENT_BRIDGE`。 +- 实验只安装 `io.legado.app.debug`,没有覆盖、卸载或清理 `io.legado.app.release`。实验代码随后已从工作区删除。2026-08-13 继续工作时先通过真实系统列表纵向滚动让 framework 将遗留动态标志恢复为 `0`;切回 `io.legado.app.release` 阅读页后只读确认当前应用刷新配置为清晰模式 `3`、`sys.hmct.epd_mode=515`。整个恢复过程未写系统属性、未调用私有 EPD 服务,正式版版本和安装时间未变化。 +- 因自动组合刷新仅适用于纵向滚动,且安全桥接失败,任务 3.6 记为 `NOT_RUN_PROTOCOL_STOP`。在当前不调用私有接口、无 root、无系统签名的范围内没有可继续实施的硬件路径。 + +### 参考视频复核与旧原型结论 + +- 参考:用户提供的 Kindle Paperwhite 5 实拍视频,H.264、1080×1920、30fps、约 7.47 秒。 +- 逐帧观察:前进翻页时目标页墨迹按最终位置从右向左显现,返回翻页时从左向右显现;起始页墨迹在扫过区域滞后变浅,新旧内容短暂以不同灰阶叠印,纸张背景基本稳定。 +- 逐帧观察:未见独立灰色条、阴影幕布、页面卷曲或整页平移;可见过渡约为 0.20–0.25 秒,但录像时间不直接作为内部固定时长。 +- 用户确认:2026-08-11,用户确认上述描述与参考视频观感一致。 +- 旧原型结论:`INVALID_VISUAL_MODEL`。此前调试包中的独立灰色条与 Kindle 参考不一致,任务 1.1 撤回完成状态,门槛继续保持 `PENDING`,不得开始第 2 节。 +- 修订实现:旧版硬裁剪和独立灰条已替换为约 35% 视口宽度的空间交叉淡变遮罩;新旧页面内容通过连续透明度混合产生叠印,不再绘制额外颜色。 +- 第一轮修订验证:`KindlePageTurnTimelineTest` 通过,覆盖前后方向、交叉区位置、区内 0.25/0.5/0.75 内容混合比例和线性时间进度;`appDebug` 源码编译成功,`openspec validate --all --strict` 通过。 +- 第二轮节奏修订:参考视频 30fps 关键帧与用户实机观感均支持线性速度是主要剩余差异,但受面板响应和相机采样影响,不能据此声称还原 Kindle 私有精确曲线。实现曾对扫动位置使用纯 Kotlin `smoothstep`(`3t² - 2t³`)非线性缓动并新增 220ms 候选,随后被实机结果判定为 `INVALID_EASING_MODEL`。 +- 第二轮本地与安装验证:聚焦 `KindlePageTurnTimelineTest` 通过,`:app:assembleAppDebug` 成功,`openspec validate --all --strict` 与 `git diff --check` 通过;APK manifest 确认为 `io.legado.app.debug`,设备上的调试版和正式版安装后仍同时存在。用户已完成第二轮物理屏幕观察;因全部候选不可辨,外部录像按门槛协议停止。 +- 第二轮实机结论:用户确认 120、160、200、220、250ms 均一闪而过、看不出动画;外部录像按协议停止,第二轮不得用于 GO。 +- 第三轮修订:扫动位置恢复线性时间进度,`smoothstep` 只用于交叉区内部的目标页透明度;2026-08-12 聚焦测试、`:app:assembleAppDebug`、`openspec validate --all --strict` 和 `git diff --check` 通过,APK 包名再次确认为 `io.legado.app.debug`,通过 `adb install -r` 更新并启动成功。 +- 第三轮实机结论:用户确认 200、220、250ms 的横向扫动、无独立灰条、背景与最终文字稳定等四项均达到要求,220ms 综合效果最好;但这些结果及随后提供的 59.98fps 外部录像现已更正为流畅模式证据,不能用于清晰模式门槛,旧 `GO` 已撤回。 + +## 生产实现聚焦验证 + +- 协议与设置:`PageAnim` 在既有 `0..4` 后追加值 `5`,未知值显式归一为无动画;普通阅读、墨水屏阅读和单本书覆盖设置均只在末尾追加新选项,八套现有语言资源已补齐名称。 +- 持久化:全局 `ReadBookConfig.Config` 的 `pageAnim`、`pageAnimEInk` 与单本书 `Book.ReadConfig.pageAnim` 继续沿用现有 JSON 字段;新旧 JSON 聚焦测试通过,未修改 Room 实体字段、数据库版本或 schema 快照。 +- 生产动画:新增 `KindlePageDelegate`,软件时间线根据最新极速模式反馈改为 200ms;手势移动阶段只确认方向,松手后才播放。渲染范围仍是 `ReadView` 的完整阅读内容画布,系统栏、菜单与弹窗不在录制范围内。200ms 不是清晰模式通过证据。 +- 连续输入:独立状态控制器覆盖 `Idle`、`Animating`、`Returning`、`Committing`,使用净待处理页数和 generation 保护;测试确认连续二十次同向输入提交二十页、反向输入净抵消、旧回调无效、目标缺失或提交失败清空意图。 +- 按键:仅新 Delegate 绕过既有 600ms 丢弃式防抖;独立按下直接进入状态机,关闭长按翻页时仍忽略 repeat,启用时以 200ms 为最短接受间隔。鼠标滚轮和其他动画路径保持既有逻辑。 +- 主动选择与降级:用户主动选择新模式后不受设备系统动画时长比例为 `0` 的影响;视口无效、录制器不可用或绘制异常时直接提交正确目标页,返回阶段失败稳定在原页,生命周期销毁清除未提交动画,尺寸变化时完成当前有效目标;没有 500ms 延迟补刷。 +- 调试清理:前置门槛使用的 `KindlePageTurnDebugActivity`、debug manifest 声明、候选时长控件和专用字符串已删除,未进入生产 APK。 +- 聚焦命令:`./gradlew :app:testAppDebugUnitTest --tests io.legado.app.constant.PageAnimTest --tests io.legado.app.help.config.PageAnimationConfigJsonTest --tests 'io.legado.app.ui.book.read.page.animation.*'`,2026-08-12 执行成功。 +- 基础检查:2026-08-12 `git diff --check` 与 `openspec validate --all --strict` 执行成功。普通 Android 人工验证、最终 Hi Reader Pro 生产路径验收和完整项目检查仍待执行。 + +## 生产 APK 与最终项目检查 + +### 完整单元测试 + +- 命令:`./gradlew :app:testAppDebugUnitTest`。 +- 结果:2026-08-12 执行成功,完整 `appDebug` JVM 单元测试没有失败;在最终复核中使用一次性 `ANDROID_HOME=/Users/back/Library/Android/sdk` 和 `ANDROID_SDK_ROOT=/Users/back/Library/Android/sdk` 再次执行,57 个任务均为最新状态且构建成功。 +- 环境说明:未设置 SDK 环境变量的一次调用在确定任务依赖前因找不到 SDK 位置而停止,不属于测试用例失败;没有创建或提交 `local.properties`。任务 6.1 完成。 + +### 静态检查与调试构建 + +- 命令:`./gradlew :app:testAppDebugUnitTest :app:lintAppDebug :app:assembleAppDebug`。 +- 单元测试与构建结果:`:app:testAppDebugUnitTest` 成功,`:app:assembleAppDebug` 成功。 +- lint 结果:`:app:lintAppDebug` 失败,报告为 14 个错误、880 个警告、18 个提示,因此不得描述为 lint 通过。 +- 错误归属:14 个错误位于既有 `AndroidManifest.xml`、`MainViewModel.kt`、`BookType.kt`、`LayoutManager.kt`、`ViewExtensions.kt`、`NavigationViewUtils.kt` 和既有缺失翻译项;没有错误指向本变更新增的 Delegate、时间线、状态控制器、渲染器或新增字符串。变更触及的既有文件只报告了原有 `dialog_read_book_style.xml` 根布局 overdraw 和 `BaseReadBookActivity.kt` 数字格式警告。 +- 处理边界:本变更没有顺手修改这些项目基线问题。由于 lint 命令本身失败,任务 6.2 保持未完成。 + +### 生产调试包审计 + +- APK:`app/build/outputs/apk/app/debug/legado_app_3.26.081201.apk`,大小约 29MB,SHA-256 为 `ea5769807377613c1b6c7d53a50a0717327d127c951cbb87707bc623a28a45cf`。 +- manifest:包名 `io.legado.app.debug`,`versionCode` 为 `16566`,`versionName` 为 `3.26.081201debug`,最低 API 21、目标 API 36。 +- 签名:`apksigner verify --verbose --print-certs` 验证 v1、v2 签名成功,签名者为 Android Debug 证书;这不是系统签名。 +- 源码差异审计:生产变更中没有 `com.hmct.epd`、`IEpdManager`、`EpdManager`、`ServiceManager`、`setEpdDisplayMode`、`detectBeginByDirection`、sysfs 路径、root 命令、全局刷新模式切换或 500ms 延迟补刷调用。 +- APK 审计:压缩包清单中没有提取的 `framework.jar`、`services.jar`、海信/HMCT 文件或已移除的 Kindle 调试入口;解压 `classes*.dex` 后也未匹配到上述海信 EPD 接口和 sysfs 字符串。 +- 工作区审计:变更列表中没有签名材料、设备私有文件、`local.properties` 或构建产物;任务 5.4 完成。 + +### 仍待实机覆盖 + +- `IMG_1005.MOV` 只覆盖前置专用调试入口的 220ms 前后翻页,不是生产阅读路径,不能替代任务 5.1–5.3。 +- 2026-08-12 最终检查时 `adb devices -l` 没有列出设备,因此尚未安装当前生产调试包,也没有执行横屏双页、浅色/深色主题、连续二十页、反向抵消和实体键验收。 +- 普通 Android 人工验证尚无可用普通设备;本机 `Pixel_5_API_30` AVD 的系统镜像缺少 `system.img` 和 `userdata.img`,未使用 `-wipe-data`,任务 4.3 保持未完成。 + +### Hi Reader Pro 生产调试包隔离安装 + +- 日期:2026-08-12;设备序列号 `7a219732`,型号/设备标识 `HLTE556N`,Android 11、API 30。 +- 安装前本地 APK 为 `io.legado.app.debug`、`versionCode=16566`、`versionName=3.26.081201debug`,签名为 Android Debug 证书,证书 SHA-256 为 `e5529aeb53e775e4f9647f73d1fad5d39f3b4ce8855cbe562d3eea9fc7265ce7`。 +- 安装前设备已有 `io.legado.app.debug` `3.26.081200debug`,使用相同 Android Debug 证书;正式版为独立包 `io.legado.app.release` `3.25`,使用 `CN=gedoor` 证书。 +- 更新命令仅对本地生产 debug APK 执行 `adb install -r`,返回 `Success`;没有使用 `-d`,没有执行卸载或清数据。更新后 debug 版本为 `3.26.081201debug`,设备回拉 APK 的 SHA-256 为 `ea5769807377613c1b6c7d53a50a0717327d127c951cbb87707bc623a28a45cf`,与本地 APK 完全一致。 +- 正式版保护复核:安装前后 `io.legado.app.release` 的 APK 路径相同,`versionCode=15604`、`versionName=3.25`、首次安装时间 `2024-05-10 11:59:42`、最后更新时间 `2025-01-03 11:37:11` 均未变化;安装前后 APK SHA-256 均为 `1e3a7aab498ffc4d7939c8be2f6ca1ff8c3c6e4847637e8080e4e4a463e0174e`。 +- 安装后只在 debug 应用自己的沙箱中导入仓库自带的公开 AGPL 许可证 `LICENSE`,共享测试文件为 `/sdcard/Download/codex_kindle_animation_test.txt`;安装前 debug 数据库为 0 本书,未从正式版复制书籍、配置、数据库或凭据。任务 5.1 完成。 + +### 生产阅读路径首次验收失败与修复 + +- 用户在生产阅读设置中确认“Kindle翻页动画”为选中状态,但前后翻页的视觉效果与“无翻页动画”一致,因此任务 5.2 本轮结论为 `PRODUCTION_PATH_NO_ANIMATION`,保持未完成。 +- 只读设备设置显示 `window_animation_scale=0.0`、`transition_animation_scale=0.0`、`animator_duration_scale=0.0`。生产 `KindlePageDelegate` 在启动前调用 `ValueAnimator.areAnimatorsEnabled()`,得到关闭状态后通过 `forceFinish` 直接提交目标页;前置专用调试入口没有读取该开关,所以此前 220ms 原型仍可见。 +- 修复移除生产 Delegate 对系统动画时长比例的依赖。用户主动选择该阅读模式视为明确要求播放;视口无效、页面录制未准备或绘制异常仍按原方案安全降级,且不修改设备全局动画设置。 +- 用户同时反馈第六个“Kindle翻页动画”按钮会把选项行撑高。布局已从最多两行改为单行尾部省略,完整本地化名称仍作为控件文本保留。 +- 修复后完整运行 `:app:testAppDebugUnitTest :app:assembleAppDebug`,82 个任务中 25 个执行、57 个为最新状态,构建成功且单元测试没有失败。新 APK 为 `legado_app_3.26.081210.apk`,包名 `io.legado.app.debug`、`versionCode=16566`、`versionName=3.26.081210debug`,SHA-256 为 `203d72a0b370122a818777cae29376188bfaf909d49d17bd8e3872485d8adfaf`,继续使用相同 Android Debug 证书。 +- 仅通过 `adb install -r` 更新上述 debug APK,返回 `Success`,没有降级、卸载或清数据。更新后正式版的包路径、版本、首次安装时间和最后更新时间均未变化,APK SHA-256 仍为 `1e3a7aab498ffc4d7939c8be2f6ca1ff8c3c6e4847637e8080e4e4a463e0174e`;设备三项系统动画比例继续保持 `0.0`,未为测试修改系统设置。 +- 修复后 `openspec validate --all --strict` 通过。`:app:lintAppDebug` 仍被项目既有的 14 个错误阻断,错误位置与修复前一致,没有错误指向本轮 Delegate、状态控制器、测试或按钮布局;本变更没有修改 lint 基线或顺手修复无关问题。 +- 修复后的生产阅读 Activity 已启动到锁屏后方,等待设备解锁和物理屏幕复验;以上自动化与安装结果不得作为任务 5.2 通过证据。 + +### 差异与 OpenSpec 校验 + +- `git diff --check` 通过;另对全部未跟踪的新文件逐一执行等价的 `git diff --no-index --check`,没有空白错误。 +- 已检查 `git diff --stat`、全部未跟踪文件和 `git status --short`。变更只涉及 Android 阅读动画实现、对应资源与测试以及本 OpenSpec 变更,没有 Room schema、Gradle 依赖、构建产物、设备私有文件、签名材料、`local.properties` 或无关格式化差异;任务 6.3 完成。 +- `openspec validate --all --strict` 通过,`change/add-kindle-page-turn-animation` 与既有 `spec/fork-build-security` 共 2 项通过、0 项失败;提案、规范、设计、任务和当前 `GO`/待验收状态一致,任务 6.4 完成。 + +## 2026-08-13 继续验证与停止边界 + +- 设备恢复:开始继续工作时只读发现 `sys.hmct.dynamic_refreshing_flag=1`。先唤醒设备并让系统设置中的真实可滚动列表完成纵向滚动,framework 将动态标志恢复为 `0`;随后切回正式版阅读页,只读确认 `current_epd_mode=3`、`sys.hmct.epd_mode=515`。整个过程未写系统属性、未调用私有 EPD 服务。 +- 正式版保护:恢复后正式版仍为 `io.legado.app.release` `3.25`,`versionCode=15604`,首次安装时间 `2024-05-10 11:59:42`、最后更新时间 `2025-01-03 11:37:11`,没有覆盖、卸载、清数据或降级。 +- 事实更正:提案、规范、设计和本记录不再把自动组合刷新描述为待验证可行路线,也不再用“清晰模式合并中间帧”解释现象。现有证据只证明清晰模式基本看不到普通 Canvas 动画,不能证明厂商内部如何调度中间帧。 +- 当前核心结论:普通 Canvas 路线保持 `NO_GO_CLEAR_AND_ANIMATED`,标准事件组合刷新桥接保持 `NO_GO_UNSAFE_EVENT_BRIDGE`。200ms 只保留为普通屏幕或极速模式软件候选;在当前权限边界内,任务 3.6、5.2 和 5.3 不得标记完成。 +- 聚焦测试与构建:使用一次性 `ANDROID_HOME=/Users/back/Library/Android/sdk` 和 `ANDROID_SDK_ROOT=/Users/back/Library/Android/sdk` 运行聚焦 JVM 测试及 `:app:assembleAppDebug`,82 个任务中 25 个执行、57 个为最新状态,构建成功。随后运行完整 `:app:testAppDebugUnitTest` 成功;将两处遗留的 220ms 测试名称和限速夹具更正为 200ms 后再次运行完整单测,57 个任务中 14 个执行、43 个为最新状态,构建成功。 +- lint:单独运行 `:app:lintAppDebug`,结果仍为 14 个错误、884 个警告、18 个提示并以失败退出。14 个错误全部位于既有 `AndroidManifest.xml`、`MainViewModel.kt`、`BookType.kt`、`LayoutManager.kt`、`ViewExtensions.kt`、`NavigationViewUtils.kt` 和既有缺失翻译;没有错误指向本变更新增的 Delegate、时间线、状态控制器、渲染器、测试或新字符串。任务 6.2 继续保持未完成。 +- 干净 APK:构建产物为 `app/build/outputs/apk/app/debug/legado_app_3.26.081316.apk`,SHA-256 为 `29d879aa13abf0299e1584d890c898e5f8d6cb062073e0b7701969067d6029a2`。`aapt` 确认为 `io.legado.app.debug`、`versionName=3.26.081316debug`、最低 API 21、目标 API 36;`apksigner` 验证 v1、v2 签名通过,签名者为 Android Debug 证书。 +- 私有接口审计:APK 的 `classes*.dex` 与压缩包清单均未匹配已删除的 `KindlePageTurnDebugActivity`、`com.hmct.epd`、`IEpdManager`、动态刷新属性、framework/services 提取物或海信 EPD 控制入口。 +- 安装:只对上述 `io.legado.app.debug` APK 执行 `adb install -r`,返回 `Success`。调试版更新为 `3.26.081316debug`;正式版路径、版本和安装时间前后不变,安装后设备仍为动态标志 `0`、清晰配置 `3`。 +- 最终基础检查:`openspec validate --all --strict` 通过,2 项通过、0 项失败;`git diff --check` 以及对全部未跟踪文件逐一执行的等价空白检查均通过。任务 6.4 完成;任务 3.6、4.3、5.2、5.3 和 6.2 保持未完成。 + +## NO-GO 归档收口 + +- 归档日期:2026-08-13;归档目录为 `openspec/changes/archive/2026-08-13-add-kindle-page-turn-animation/`,使用 `--skip-specs`,没有创建或修改 `openspec/specs/kindle-page-turn-animation/`。 +- 未推广实现快照:实验分支 `codex/add-kindle-page-turn-animation` 的提交 `5ef423314`;最终归档状态由远端不可变标签 `archive/kindle-page-turn-animation-no-go-20260813` 保留。该快照只用于保存软件候选、状态机、测试和复现上下文,不得整体合入主分支,不得作为功能完成或发布依据。 +- 主线允许回流范围仅为本归档目录中的事实记录;Android 实现、资源、测试、调试 APK 和增量能力规范均不推广。 +- 最终结论:Hi Reader Pro 普通应用权限下的 Canvas 路线为 `NO_GO_CLEAR_AND_ANIMATED`,标准事件组合刷新桥接为 `NO_GO_UNSAFE_EVENT_BRIDGE`。如需重启该方向,必须先明确批准海信私有接口、厂商 SDK、系统签名或 root 等新的权限边界,并建立新的 OpenSpec 变更。