refactor(feed): 合并首页与剧场频道控制器的重复分桶逻辑

两个控制器的缓存优先、请求序号防串台、分页去重、预取与 seed 完全同构,
此前各写一份。抽出 ChannelFeedController 后,子类只保留分桶 key 与取页
实现;顺带修掉刷新被翻页抢占时 loading 永久为 true 的问题。
This commit is contained in:
Zhou Weidong authored and trae-solo-agent committed 2026-10-29 10:44:36 +08:00
1 parent 1be8ebf1f9
commit 9c9a277217
4 files changed
+313 -372

No files matched your search

@@ -0,0 +1,50 @@
// Author: fruit.com.cn
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/data/models/drama.dart';
import 'package:fruitshorts/core/data/models/feed_page.dart';
import 'package:fruitshorts/core/data/services/channel_feed_controller.dart';
void main() {
test('should_clear_loading_when_load_more_supersedes_refresh', () async {
final pendingRefresh = Completer<FeedPage>();
final controller = _ScriptedFeedController([
() async => FeedPage(
dramas: [_drama('a')],
nextCursor: 'cursor-1',
hasMore: true,
),
() => pendingRefresh.future,
() async => FeedPage(dramas: [_drama('b')], hasMore: false),
]);
await controller.refreshCurrent();
expect(controller.hasMore, isTrue);
final refresh = controller.refreshCurrent();
final more = controller.loadMore();
pendingRefresh.complete(FeedPage(dramas: [_drama('late')], hasMore: false));
await Future.wait([refresh, more]);
// 刷新被翻页抢占后,加载态必须收掉,否则该分桶永远显示加载中且无法再刷新。
expect(controller.isLoading, isFalse);
expect(controller.loadingMore, isFalse);
expect(controller.dramas.map((drama) => drama.id), contains('b'));
expect(controller.dramas.map((drama) => drama.id), isNot(contains('late')));
controller.dispose();
});
}
class _ScriptedFeedController extends ChannelFeedController<String> {
_ScriptedFeedController(this._pages) : super('all');
final List<Future<FeedPage> Function()> _pages;
@override
Future<FeedPage> fetchPage(String key, {String? cursor}) =>
_pages.removeAt(0)();
}
Drama _drama(String id) =>
Drama(id: id, title: id, synopsis: id, posterUrl: '');