diff --git a/lib/http/user.dart b/lib/http/user.dart index 166ab59b..5aff3e71 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -1,3 +1,4 @@ +import 'package:PiliPalaX/http/loading_state.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import '../common/constants.dart'; import '../models/model_hot_video_item.dart'; @@ -42,6 +43,27 @@ class UserHttp { } // 收藏夹 + static Future userfavFolderNew({ + required int pn, + required int ps, + required int mid, + }) async { + var res = await Request().get(Api.userFavFolder, data: { + 'pn': pn, + 'ps': ps, + 'up_mid': mid, + }); + if (res.data['code'] == 0) { + if (res.data['data'] != null) { + return LoadingState.success(FavFolderData.fromJson(res.data['data'])); + } else { + return LoadingState.empty(); + } + } else { + return LoadingState.error(res.data['message'] ?? '账号未登录'); + } + } + static Future userfavFolder({ required int pn, required int ps, diff --git a/lib/pages/fav/controller.dart b/lib/pages/fav/controller.dart index dd99fe27..7b4e6ed1 100644 --- a/lib/pages/fav/controller.dart +++ b/lib/pages/fav/controller.dart @@ -1,55 +1,50 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:get/get.dart'; +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:hive/hive.dart'; import 'package:PiliPalaX/http/user.dart'; -import 'package:PiliPalaX/models/user/fav_folder.dart'; import 'package:PiliPalaX/models/user/info.dart'; import 'package:PiliPalaX/utils/storage.dart'; -class FavController extends GetxController { - final ScrollController scrollController = ScrollController(); - Rx favFolderData = FavFolderData().obs; +class FavController extends CommonController { Box userInfoCache = GStorage.userInfo; - UserInfoData? userInfo; - int currentPage = 1; + late final UserInfoData? userInfo = userInfoCache.get('userInfoCache'); int pageSize = 10; - RxBool hasMore = true.obs; + bool hasMore = true; - Future queryFavFolder({type = 'init'}) async { - userInfo = userInfoCache.get('userInfoCache'); + @override + void onInit() { + super.onInit(); + queryData(); + } + + @override + Future queryData([bool isRefresh = true]) { if (userInfo == null) { - return {'status': false, 'msg': '账号未登录'}; + loadingState.value = LoadingState.error('账号未登录'); + return Future.value(); } - if (!hasMore.value) { - return; + if (!hasMore) { + return Future.value(); } - var res = await UserHttp.userfavFolder( - pn: currentPage, - ps: pageSize, - mid: userInfo!.mid!, - ); - if (res['status']) { - if (type == 'init') { - favFolderData.value = res['data']; - } else { - if (res['data'].list.isNotEmpty) { - favFolderData.value.list!.addAll(res['data'].list); - favFolderData.update((val) {}); - } - } - hasMore.value = res['data'].hasMore; - currentPage++; - if (hasMore.value && type == 'init') { - queryFavFolder(type: 'onload'); - } - } else { - SmartDialog.showToast(res['msg']); - } - return res; + return super.queryData(isRefresh); } - Future onLoad() async { - queryFavFolder(type: 'onload'); + @override + bool customHandleResponse(Success response) { + hasMore = response.response.hasMore; + List currentList = loadingState.value is Success + ? (loadingState.value as Success).response + : []; + loadingState.value = currentPage == 1 + ? LoadingState.success(response.response.list) + : LoadingState.success(currentList + response.response.list); + return true; } + + @override + Future customGetData() => UserHttp.userfavFolderNew( + pn: currentPage, + ps: pageSize, + mid: userInfo!.mid!, + ); } diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index 44b76a0a..bc92aa65 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -1,4 +1,5 @@ import 'package:PiliPalaX/common/skeleton/video_card_h.dart'; +import 'package:PiliPalaX/http/loading_state.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -18,20 +19,16 @@ class FavPage extends StatefulWidget { class _FavPageState extends State { final FavController _favController = Get.put(FavController()); - late Future _futureBuilderFuture; - late ScrollController scrollController; @override void initState() { super.initState(); - _futureBuilderFuture = _favController.queryFavFolder(); - scrollController = _favController.scrollController; - scrollController.addListener( + _favController.scrollController.addListener( () { - if (scrollController.position.pixels >= - scrollController.position.maxScrollExtent - 300) { + if (_favController.scrollController.position.pixels >= + _favController.scrollController.position.maxScrollExtent - 300) { EasyThrottle.throttle('history', const Duration(seconds: 1), () { - _favController.onLoad(); + _favController.onLoadMore(); }); } }, @@ -40,8 +37,7 @@ class _FavPageState extends State { @override void dispose() { - scrollController.removeListener(() {}); - scrollController.dispose(); + _favController.scrollController.removeListener(() {}); super.dispose(); } @@ -57,77 +53,64 @@ class _FavPageState extends State { ), actions: [ IconButton( - onPressed: () => Get.toNamed( - '/favSearch?searchType=1&mediaId=${_favController.favFolderData.value.list!.first.id}'), + onPressed: () { + if (_favController.loadingState.value is Success) { + Get.toNamed( + '/favSearch?searchType=1&mediaId=${(_favController.loadingState.value as Success).response.first.id}'); + } + }, icon: const Icon(Icons.search_outlined), tooltip: '搜索', ), const SizedBox(width: 6), ], ), - body: FutureBuilder( - future: _futureBuilderFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - Map data = snapshot.data as Map; - if (data['status']) { - return Obx(() => CustomScrollView( - controller: scrollController, - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0), - delegate: SliverChildBuilderDelegate( - childCount: - _favController.favFolderData.value.list!.length, - (BuildContext context, int index) { - return FavItem( - favFolderItem: _favController - .favFolderData.value.list![index]); - }, - ), - ) - ])); - } else { - return CustomScrollView( - physics: const NeverScrollableScrollPhysics(), - slivers: [ - HttpError( - errMsg: data['msg'], - fn: () => setState(() {}), - ), - ], - ); - } - } else { - // 骨架屏 - return CustomScrollView( - physics: const NeverScrollableScrollPhysics(), - slivers: [ - SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return const VideoCardHSkeleton(); - }, - childCount: 10, - ), - ), - ], - ); - } - }, + body: CustomScrollView( + controller: _favController.scrollController, + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + Obx( + () => _buildBody(_favController.loadingState.value), + ), + ], ), ); } + + Widget _buildBody(LoadingState loadingState) { + return loadingState is Success + ? SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0), + delegate: SliverChildBuilderDelegate( + childCount: loadingState.response.length, + (BuildContext context, int index) { + return FavItem(favFolderItem: loadingState.response[index]); + }, + ), + ) + : loadingState is Error + ? HttpError( + errMsg: loadingState.errMsg, + fn: _favController.onReload, + ) + : SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return const VideoCardHSkeleton(); + }, + childCount: 10, + ), + ); + } } diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 49a4d967..2f142c53 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -157,7 +157,7 @@ class VideoContent extends StatelessWidget { videoItem.title, textAlign: TextAlign.start, style: const TextStyle( - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w400, letterSpacing: 0.3, ), maxLines: 2,