You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
5.5 KiB
Dart

2 years ago
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:isekai_wiki/api/mw/list.dart';
import 'package:isekai_wiki/api/mw/mw_api.dart';
import 'package:isekai_wiki/api/response/page_info.dart';
import 'package:isekai_wiki/components/page_card.dart';
import 'package:isekai_wiki/models/favorite_list.dart';
import 'package:isekai_wiki/models/user.dart';
2 years ago
import 'package:isekai_wiki/pages/home.dart';
class RecentPageListController extends GetxController {
Function? _handleReload;
ScrollController? scrollController;
UserController? uc;
FavoriteListController? flc;
double insetBottom = 0;
2 years ago
var shouldRefresh = true;
var pageList = RxList<PageInfo>();
var continueInfo = RxMap<String, String>();
var errorList = RxList<MWApiErrorException>();
2 years ago
var hasNextPage = true.obs;
var isLoading = false.obs;
RecentPageListController({this.scrollController});
@override
void onInit() {
scrollController?.addListener(() {
if (scrollController!.position.pixels >
scrollController!.position.maxScrollExtent - 10) {
2 years ago
// 滚动到底部
if (hasNextPage.value && !isLoading.value) {
loadNextPages();
}
}
});
super.onInit();
uc = Get.find<UserController>();
flc = Get.find<FavoriteListController>();
2 years ago
loadNextPages();
var homeController = Get.find<HomeController>();
homeController.onRefresh = refreshPages;
}
@override
void dispose() {
var homeController = Get.find<HomeController>();
homeController.onRefresh = refreshPages;
super.dispose();
}
Future<void> refreshPages() async {
continueInfo.clear();
errorList.clear();
hasNextPage.value = true;
shouldRefresh = true;
await loadNextPages();
}
Future<void> loadNextPages() async {
// 如果没有下一页,则阻止加载
if (!hasNextPage.value) return;
isLoading.value = true;
try {
var rcListRes = await MWApiList.getMixedRecentChanges(
limit: 10,
continueInfo: continueInfo.isNotEmpty ? continueInfo : null);
var pageIds = rcListRes.data.map((rcInfo) => rcInfo.pageid).toList();
var pageListRes = await MWApiList.getPageInfoList(
pageids: pageIds, extractChars: 515, getInWatchlist: uc!.isLoggedIn);
if (uc!.isLoggedIn) {
// 更新收藏列表信息
flc!.updateFromPageList(pageListRes.data);
2 years ago
}
// 加载完成,设置信息
if (shouldRefresh) {
// 初次加载,替换全部数据
pageList.value = pageListRes.data;
shouldRefresh = false;
} else {
pageList.addAll(pageListRes.data);
}
hasNextPage.value = rcListRes.continueInfo != null;
continueInfo.value = rcListRes.continueInfo ?? {};
} catch (err) {
2 years ago
hasNextPage.value = false;
if (shouldRefresh) {
pageList.clear();
}
} finally {
isLoading.value = false;
2 years ago
}
}
Future<void> reload() async {
if (_handleReload != null) {
await _handleReload!();
}
}
void setReloadHandler(Function? reloadHandler) {
_handleReload = reloadHandler;
}
}
class RecentPageList extends StatelessWidget {
final ScrollController? scrollController;
final double insetBottom;
2 years ago
const RecentPageList(
{super.key, this.scrollController, this.insetBottom = 0});
2 years ago
Widget _buildSkeletonList() {
return Column(
key: key,
children: [
for (var i = 0; i < 6; i++)
PageCard(key: ValueKey("rpl-card-$i"), isLoading: true),
2 years ago
],
);
}
Widget _buildPageCard(int index, PageInfo pageInfo,
RecentPageListController c, FavoriteListController flc) {
2 years ago
return PageCard(
key: ValueKey("rpl-card-$index"),
2 years ago
pageInfo: c.pageList[index],
isFavorite: flc.isFavorite(c.pageList[index]),
onSetFavorite: flc.setFavoriteImmediate,
2 years ago
);
}
SliverChildBuilderDelegate _buildPageListDelegate() {
var c = Get.find<RecentPageListController>();
var flc = Get.find<FavoriteListController>();
2 years ago
return SliverChildBuilderDelegate(
childCount: c.pageList.length + 1,
(context, index) {
if (index == 0) {
// 第一页数据,直接加载
return Obx(() {
if (c.pageList.isEmpty) {
return _buildSkeletonList();
} else {
return _buildPageCard(index, c.pageList[index], c, flc);
}
});
2 years ago
}
// 后续页数据
if (index < c.pageList.length) {
return Obx(() => _buildPageCard(index, c.pageList[index], c, flc));
2 years ago
} else if (index == c.pageList.length) {
// 显示加载动画
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Center(
child: Obx(
() => c.isLoading.value
? Padding(
padding: EdgeInsets.only(bottom: insetBottom),
child: const CupertinoActivityIndicator(
radius: 14,
),
)
: SizedBox(
width: 28,
height: 28 + insetBottom,
),
),
2 years ago
),
);
}
return null;
},
);
}
@override
Widget build(BuildContext context) {
Get.put(RecentPageListController(scrollController: scrollController));
return Obx(
() => SliverList(
delegate: _buildPageListDelegate(),
),
);
2 years ago
}
}