TV 端焦点更稳 —— 卡片开始「记住自己是谁」,列表被销毁重建或重排后,焦点回到原来那张卡。
变更
- 网格身份锚定(P11-202)。此前 TV 的焦点恢复靠页面级存一个「稳定 key」+ 侧栏/播放器一串显式计数器触发,卡片本身不参与身份记忆:网格一被销毁,网格内部那份记忆就没了;每接一个新页面还得再穿一条恢复管线。现在新增一份挂在 AppShell 的网格焦点记忆,所有用共用视频网格的页面(推荐/动态/搜索/直播/UP 主页/YouTube 频道)一起受益。
- 判据是「网格自己发起过跳转、且焦点再没回到任何卡片」,而不是「销毁前网格是否持有焦点」。后者在 Compose 里无法可靠判定:
hasFocus=false有三种成因(网格被销毁 / 焦点移到侧栏 / 覆盖层抢焦),后两者一个是「应该拒绝恢复」、一个是「应该恢复」,语义正好相反。 - 显式恢复管线仍然是主路径。新机制只在管线跑完仍没把焦点落到目标卡时接力补一刀(慢布局把重试预算耗尽、焦点被头像抢走、或页面初焦把焦点落到了第 0 张卡)。用户一按方向键立刻让位,绝不抢焦。
- 判据是「网格自己发起过跳转、且焦点再没回到任何卡片」,而不是「销毁前网格是否持有焦点」。后者在 Compose 里无法可靠判定:
- 修「动态页合并 YouTube 关注流后焦点落到别的卡」。动态页的列表 key 里编了行下标,一旦重排必然失配、只能退回旧下标 —— 而旧下标上很可能已经是另一条视频。现在先按不含下标的稳定身份找,找不到才退回下标。
- 统一三份重复的「卡片身份」实现,并补上原先算不出身份的类别:图文/纯文字动态(此前四个分支全落空、返回空串,等于永远锚不住)与本地 YouTube 历史(videoId 为空时用播放时刻作身份)。顺带修掉一个空列表时的下标越界异常。
已知
- 本条待真机验收。该恢复的场合应见
grid-memory relay→success且紧随GAINED [<网格名>],全程不出现头像被自动确认(avatar focused … openMyPage=true);不该恢复的场合(侧栏切走再切回、切子 tab、侧栏重点击手动刷新、重新搜索)应见grid-memory clear: id=… reason=…且整轮没有恢复动作。日志 tag 仍是BiliMT:Focus。 - IPTV 分区天然不适用:IPTV 卡片没有可用的稳定身份,行为与之前一致(从第 0 行开始),这是已知限制不是缺陷。
- alpha.5~alpha.8 里记的已知项(编码分组/缓冲地板/顶档闸/档位基准待复测;转发、专栏动态不渲染、话题/@ 不可点等)仍未变。