feat(home): 首页按内容类型分频道 Feed 并支持分页

This commit is contained in:
Zhou Weidong committed 2026-10-21 17:33:52 +08:00
1 parent 4d0be47ee3
commit ae61d9ec4c
22 files changed
+1001 -71

No files matched your search

+114
View File
@@ -412,6 +412,120 @@ void main() {
});
});
group('updateFeed', () {
test('should_append_feed_without_restarting_current_drama', () async {
final factory = _RecordingFactory();
final feed = [_drama('signal'), _drama('city')];
final logic = _logic(FakeWatchHistory());
logic.attach(
PlayerPage(
drama: feed.first,
initialIndex: 0,
homeMode: true,
feedDramas: feed,
),
isMounted: () => true,
);
logic.start(factory: factory.create, coordinator: PlaybackCoordinator());
await _drain(logic);
final activeBefore = logic.session.active;
logic.updateFeed([...feed, _drama('third')], keepDramaId: 'signal');
await pumpEventQueue();
expect(logic.currentDramaId, 'signal');
expect(logic.visibleIndices, [0, 1, 2]);
expect(logic.sessionEpisodes, hasLength(3));
expect(logic.session.active, same(activeBefore));
logic.dispose();
await _drain(logic);
});
test('should_remap_current_drama_without_restarting_when_order_changes',
() async {
final factory = _RecordingFactory();
final feed = [_drama('signal'), _drama('city')];
final logic = _logic(FakeWatchHistory());
logic.attach(
PlayerPage(
drama: feed.first,
initialIndex: 1,
homeMode: true,
feedDramas: feed,
),
isMounted: () => true,
);
logic.start(factory: factory.create, coordinator: PlaybackCoordinator());
await _drain(logic);
final activeBefore = logic.session.active;
logic.updateFeed(
[_drama('city'), _drama('signal'), _drama('third')],
keepDramaId: 'city',
);
await pumpEventQueue();
expect(logic.currentDramaId, 'city');
expect(logic.session.currentIndex, 0);
expect(logic.session.active, same(activeBefore));
logic.dispose();
await _drain(logic);
});
test('should_return_to_first_drama_when_feed_channel_changes', () async {
final factory = _RecordingFactory();
final feed = [_drama('signal'), _drama('city')];
final logic = _logic(FakeWatchHistory());
logic.attach(
PlayerPage(
drama: feed.first,
initialIndex: 0,
homeMode: true,
feedDramas: feed,
),
isMounted: () => true,
);
logic.start(factory: factory.create, coordinator: PlaybackCoordinator());
await _drain(logic);
logic.updateFeed([_drama('anime-a'), _drama('anime-b')]);
await _drain(logic);
expect(logic.queue.entryAt(0).drama.id, 'anime-a');
expect(logic.currentDramaId, 'anime-a');
expect(logic.session.currentIndex, 0);
logic.dispose();
await _drain(logic);
});
test('should_clear_queue_safely_when_feed_becomes_empty', () async {
final feed = [_drama('signal')];
final logic = _logic(FakeWatchHistory());
logic.attach(
PlayerPage(
drama: feed.first,
initialIndex: 0,
homeMode: true,
feedDramas: feed,
),
isMounted: () => true,
);
logic.start(
factory: _RecordingFactory().create,
coordinator: PlaybackCoordinator(),
);
await _drain(logic);
logic.updateFeed(const []);
expect(logic.queue.length, 0);
expect(logic.visibleIndices, isEmpty);
expect(logic.currentDramaId, isNull);
logic.dispose();
await _drain(logic);
});
});
group('lifecycle', () {
test('should_pause_active_player_when_backgrounded_and_play_it_when_resumed', () async {
final factory = _RecordingFactory();