mod: bangumi: load more followlist

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-01-10 10:17:54 +08:00
parent 093b84ca3a
commit c9fe3c6485
4 changed files with 97 additions and 29 deletions

View File

@@ -390,9 +390,8 @@ class Api {
static const String bangumiList = static const String bangumiList =
'/pgc/season/index/result?st=1&order=3&season_version=-1&spoken_language_type=-1&area=-1&is_finish=-1&copyright=-1&season_status=-1&season_month=-1&year=-1&style_id=-1&sort=0&season_type=1&pagesize=20&type=1'; '/pgc/season/index/result?st=1&order=3&season_version=-1&spoken_language_type=-1&area=-1&is_finish=-1&copyright=-1&season_status=-1&season_month=-1&year=-1&style_id=-1&sort=0&season_type=1&pagesize=20&type=1';
// 我的订阅 // 我的追番/追剧 ?type=1&pn=1&ps=15
static const String bangumiFollow = static const String bangumiFollow = '/x/space/bangumi/follow/list';
'/x/space/bangumi/follow/list?type=1&follow_status=0&pn=1&ps=15&ts=1691544359969';
// 黑名单 // 黑名单
static const String blackLst = '/x/relation/blacks'; static const String blackLst = '/x/relation/blacks';

View File

@@ -16,13 +16,20 @@ class BangumiHttp {
} }
} }
static Future<LoadingState> bangumiFollow({int? mid}) async { static Future<LoadingState> bangumiFollow({
var res = dynamic mid,
await Request().get(Api.bangumiFollow, queryParameters: {'vmid': mid}); required int type,
required int pn,
}) async {
var res = await Request().get(Api.bangumiFollow, queryParameters: {
'vmid': mid,
'type': type,
'pn': pn,
});
if (res.data['code'] == 0) { if (res.data['code'] == 0) {
BangumiListDataModel data = BangumiListDataModel data =
BangumiListDataModel.fromJson(res.data['data']); BangumiListDataModel.fromJson(res.data['data']);
return LoadingState.success(data.list); return LoadingState.success(data);
} else { } else {
return LoadingState.error(res.data['message']); return LoadingState.error(res.data['message']);
} }

View File

@@ -1,5 +1,8 @@
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/bangumi/list.dart';
import 'package:PiliPlus/pages/common/common_controller.dart'; import 'package:PiliPlus/pages/common/common_controller.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:PiliPlus/http/bangumi.dart'; import 'package:PiliPlus/http/bangumi.dart';
import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage.dart';
@@ -7,33 +10,76 @@ import 'package:PiliPlus/utils/storage.dart';
class BangumiController extends CommonController { class BangumiController extends CommonController {
bool isLoadingMore = true; bool isLoadingMore = true;
RxBool isLogin = false.obs; RxBool isLogin = false.obs;
late int mid; int? mid;
dynamic userInfo; dynamic userInfo;
Rx<LoadingState> followState = LoadingState.loading().obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
userInfo = GStorage.userInfo.get('userInfoCache'); userInfo = GStorage.userInfo.get('userInfoCache');
if (userInfo != null) { mid = userInfo?.mid;
mid = userInfo.mid;
}
isLogin.value = userInfo != null; isLogin.value = userInfo != null;
queryData(); queryData();
queryBangumiFollow(); queryBangumiFollow();
} if (isLogin.value) {
followController = ScrollController();
// 我的订阅
Future queryBangumiFollow() async {
userInfo = userInfo ?? GStorage.userInfo.get('userInfoCache');
if (userInfo != null) {
followState.value = await BangumiHttp.bangumiFollow(mid: userInfo.mid);
} }
} }
@override @override
Future<LoadingState> customGetData() => Future onRefresh() {
BangumiHttp.bangumiList(page: currentPage); if (isLogin.value) {
followPage = 1;
followEnd = false;
}
return super.onRefresh();
}
late int followPage = 1;
late RxInt followCount = (-1).obs;
late bool followLoading = false;
late bool followEnd = false;
late Rx<LoadingState> followState = LoadingState.loading().obs;
ScrollController? followController;
// 我的订阅
Future queryBangumiFollow([bool isRefresh = true]) async {
if (isLogin.value.not || followLoading || (isRefresh.not && followEnd)) {
return;
}
followLoading = true;
dynamic res = await BangumiHttp.bangumiFollow(
mid: mid,
type: 1,
pn: followPage,
);
if (res is Success) {
BangumiListDataModel data = res.response;
followPage++;
followEnd = data.hasNext == 0 || data.list.isNullOrEmpty;
followCount.value = data.total ?? -1;
if (isRefresh.not && followState.value is Success) {
data.list?.insertAll(0, (followState.value as Success).response);
}
followState.value = LoadingState.success(data.list);
if (isRefresh) {
followController?.animToTop();
}
} else {
followState.value = res;
}
followLoading = false;
}
@override
Future<LoadingState> customGetData() => BangumiHttp.bangumiList(
page: currentPage,
);
@override
void onClose() {
followController?.dispose();
super.onClose();
}
} }

View File

@@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'package:PiliPlus/common/widgets/loading_widget.dart';
import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:nil/nil.dart';
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/http_error.dart'; import 'package:PiliPlus/common/widgets/http_error.dart';
import 'package:PiliPlus/pages/home/index.dart'; import 'package:PiliPlus/pages/home/index.dart';
@@ -82,14 +82,19 @@ class _BangumiPageState extends State<BangumiPage>
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Obx(
'最近追番', () => Text(
style: Theme.of(context).textTheme.titleMedium, '最近追番${_bangumiController.followCount.value == -1 ? '' : ' ${_bangumiController.followCount.value}'}',
style: Theme.of(context).textTheme.titleMedium,
),
), ),
IconButton( IconButton(
tooltip: '刷新', tooltip: '刷新',
onPressed: () { onPressed: () {
_bangumiController.queryBangumiFollow(); _bangumiController
..followPage = 1
..followEnd = false
..queryBangumiFollow();
}, },
icon: const Icon( icon: const Icon(
Icons.refresh, Icons.refresh,
@@ -177,9 +182,13 @@ class _BangumiPageState extends State<BangumiPage>
Widget _buildFollowList(Success loadingState) { Widget _buildFollowList(Success loadingState) {
return ListView.builder( return ListView.builder(
controller: _bangumiController.followController,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: loadingState.response.length, itemCount: loadingState.response.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
if (index == loadingState.response.length - 1) {
_bangumiController.queryBangumiFollow(false);
}
return Container( return Container(
width: Grid.maxRowWidth / 2, width: Grid.maxRowWidth / 2,
margin: EdgeInsets.only( margin: EdgeInsets.only(
@@ -198,11 +207,18 @@ class _BangumiPageState extends State<BangumiPage>
Widget _buildFollowBody(LoadingState loadingState) { Widget _buildFollowBody(LoadingState loadingState) {
return switch (loadingState) { return switch (loadingState) {
Loading() => nil, Loading() => loadingWidget,
Success() => (loadingState.response as List?)?.isNotEmpty == true Success() => (loadingState.response as List?)?.isNotEmpty == true
? _buildFollowList(loadingState) ? _buildFollowList(loadingState)
: const Center(child: Text('还没有追番')), : const Center(child: Text('还没有追番')),
Error() => Center(child: Text(loadingState.errMsg)), Error() => Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.center,
child: Text(
loadingState.errMsg,
textAlign: TextAlign.center,
),
),
LoadingState() => throw UnimplementedError(), LoadingState() => throw UnimplementedError(),
}; };
} }