4.6 KiB
4.6 KiB
K94 首页内容类型 Feed 与无感切换
目标
- 首页顶栏「漫剧 / 真人剧 / 推荐」接入既有
/app/feed。 - 每频道独立缓存与分页,切换时先同步展示缓存,再后台静默刷新。
- 推荐首屏复用
/app/home/feed打平数据,首次进入不额外转圈。 - 无缓存频道只在黑色内容区显示小转圈,顶栏和底栏保持。
- 滑动接近末尾自动加载下一页,并在播放器队列中原地追加。
分支
- ReelShort:
feat/k94-home-type-feed,从origin/develop创建。 - FruitServer 仅文档留痕,不改功能代码。
A. 数据层
A1 FeedPage
新增 lib/core/data/models/feed_page.dart:
dramas使用Drama.fromCardJson。nextCursor兼容数字/字符串,空值或字符串"null"转为 null。hasMore读取布尔值。
A2 CatalogApi / Repository
CatalogApi.feed({types, cursor, size})请求/app/feed。- types 为空不传;非空用逗号拼接。
- cursor 为空不传。
- 返回结构异常抛
ApiException(-1, '返回数据格式异常')。 CatalogRepository与 HTTP 实现增加fetchFeed。- 所有测试 CatalogRepository 实现同步补齐方法。
B. 频道控制器
新增:
lib/pages/home/home_feed_channel.dartlib/core/data/services/home_feed_controller.dart
HomeFeedController 使用每个频道独立状态:
- dramas / cursor / hasMore / loaded / loadingMore / requestSeq
- 当前 channel,默认 recommend
seedRecommend:同步写入推荐首屏,不发请求selectChannel:同步切频道并 notify;无缓存加载第一页,有缓存静默刷新refreshCurrent:失败保留旧列表loadMore:cursor 追加,按 drama.id 去重- 所有响应必须同时满足“仍为当前频道 + requestSeq 最新”才应用
- dispose 后停止 notify
C. 首页接入
C1 顶栏受控
HomeFeedHeader:
- 删除内部 tab 状态、comingSoon 和 SnackBar。
- 新增
channel与onChannelSelected。 - 三个 Key 保持不变。
- refresh 内部 loading 状态保留。
C2 HomePage
_HomePageState用CatalogController.repository创建 HomeFeedController。- Catalog 首次有数据时同步 seed recommend,随后在 post-frame 静默刷新 recommend。
_HomeTabs使用稳定 Key,删除ValueKey(catalog.dramas.first.id)。- 当前频道无数据时,保留
_HomeTabs顶栏/底栏,body 用黑色背景 + 居中home-feed-channel-loading。 - 当前频道有数据时把频道列表传给 PlayerPage。
- 刷新回调改
refreshCurrent;分页回调改loadMore。
C3 PlayerPage / PlayerLogic
- PlayerPage 增加
feedChannel和onLoadMore。 - 同频道 feed 列表变化:
updateFeed(..., keepDramaId: currentDramaId)。 - channel 变化:
updateFeed(..., keepDramaId: null),回到新频道第 1 个。 - PlayerLogic 保存 factory/coordinator,支持需要换内容时替换 PlaybackSession。
- 空列表清空 queue/visibleIndices 并停止旧播放。
- 当前剧仍在新列表且索引不变时,只扩展队列与 episode 列表,不重新 select。
- PageView 在
position >= visibleIndices.length - 3时调用 onLoadMore。
D. 测试
新增 test/core/data/services/home_feed_controller_test.dart:
- recommendation seed 不发请求
- 三频道请求 types 分别为
[] / [ANIME] / [LIVE] - 缓存频道切换不清空并后台刷新
- loadMore 追加去重、无更多后不再请求
- 串包只接受最新频道请求
- refresh 失败保留旧数据
新增顶栏 widget 测试:
- 三个 Key 存在
- 点击分别回调 anime/live/recommend
- 当前 channel 决定选中样式
PlayerLogic 测试补充:
- updateFeed 空列表安全
- 追加列表保持当前剧
- 切频道列表回到第 1 个
门禁:
dart analyze lib testflutter test --no-pubflutter build apk --debug
风险与控制
- PlaybackSession 的 episodes 是构造时绑定的列表;分页原地追加时会同步扩展该列表, 避免仅换 queue 而 session 仍指向旧列表。
- 换频道可能释放并重建播放器 session,这是内容源变化;静默刷新/分页在顺序不变时 不重新 select 当前剧,避免视频重启。
- 推荐 seed 只保证首帧立即有内容;后台
/app/feed刷新失败时保留 seed。 - 首页仍在
/app/home/feed首次加载期间使用既有启动页;频道切换不再触发整页 splash。
Git
- 提交:
feat(home): 首页按内容类型分频道 Feed 并支持分页 --no-ff合回 ReelShortdevelop并 push。- 作者:
Zhou Weidong <502333560@qq.com>;禁止git add -A。