diff --git a/lib/http/fan.dart b/lib/http/fan.dart index a69f58c8..d0c1b44b 100644 --- a/lib/http/fan.dart +++ b/lib/http/fan.dart @@ -1,8 +1,11 @@ +import 'package:PiliPalaX/http/loading_state.dart'; + import '../models/fans/result.dart'; import 'index.dart'; class FanHttp { - static Future fans({int? vmid, int? pn, int? ps, String? orderType}) async { + static Future fans( + {int? vmid, int? pn, int? ps, String? orderType}) async { var res = await Request().get(Api.fans, data: { 'vmid': vmid, 'pn': pn, @@ -11,13 +14,9 @@ class FanHttp { 'order_type': orderType, }); if (res.data['code'] == 0) { - return {'status': true, 'data': FansDataModel.fromJson(res.data['data'])}; + return LoadingState.success(FansDataModel.fromJson(res.data['data'])); } else { - return { - 'status': false, - 'data': [], - 'msg': res.data['message'], - }; + return LoadingState.error(res.data['message']); } } } diff --git a/lib/pages/fan/controller.dart b/lib/pages/fan/controller.dart index 4563d2d0..dde01cc7 100644 --- a/lib/pages/fan/controller.dart +++ b/lib/pages/fan/controller.dart @@ -1,21 +1,19 @@ -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:PiliPalaX/http/fan.dart'; +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; -import 'package:PiliPalaX/http/fan.dart'; -import 'package:PiliPalaX/models/fans/result.dart'; import 'package:PiliPalaX/utils/storage.dart'; -class FansController extends GetxController { +class FansController extends CommonController { Box userInfoCache = GStorage.userInfo; - int pn = 1; int ps = 20; int total = 0; - RxList fansList = [].obs; late int? mid; late String? name; dynamic userInfo; - RxString loadingText = '加载中...'.obs; RxBool isOwner = false.obs; + bool isEnd = false; @override void onInit() { @@ -26,40 +24,44 @@ class FansController extends GetxController { : userInfo?.mid; isOwner.value = mid == userInfo?.mid; name = Get.parameters['name'] ?? userInfo?.uname; + + queryData(); } - Future queryFans(type) async { - if (type == 'init' || type == 'refresh') { - pn = 1; - loadingText.value == '加载中...'; - } - if (loadingText.value == '没有更多了') { - return; - } - var res = await FanHttp.fans( - vmid: mid, - pn: pn, - ps: ps, - orderType: 'attention', - ); - if (res['status']) { - if (type == 'init') { - fansList.value = res['data'].list; - total = res['data'].total; - } else if (type == 'onLoad') { - fansList.addAll(res['data'].list); - } - print('fansList: ${fansList.length}, total: $total'); - if ((pn == 1 && total < ps) || res['data'].list.isEmpty) { - loadingText.value = '没有更多了'; - } - pn += 1; - if (total > ps && pn == 2) { - queryFans('onLoad'); - } - } else { - SmartDialog.showToast(res['msg']); - } - return res; + @override + Future onRefresh() { + isEnd = false; + return super.onRefresh(); } + + @override + Future queryData([bool isRefresh = true]) { + if (isEnd) { + return Future.value(); + } + return super.queryData(isRefresh); + } + + @override + bool customHandleResponse(Success response) { + if ((currentPage == 1 && response.response.total < ps) || + response.response.list.isEmpty) { + isEnd = true; + } + 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() => FanHttp.fans( + vmid: mid, + pn: currentPage, + ps: ps, + orderType: 'attention', + ); } diff --git a/lib/pages/fan/view.dart b/lib/pages/fan/view.dart index 8bf03482..1c32a071 100644 --- a/lib/pages/fan/view.dart +++ b/lib/pages/fan/view.dart @@ -1,9 +1,9 @@ +import 'package:PiliPalaX/http/loading_state.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/common/widgets/http_error.dart'; import 'package:PiliPalaX/common/widgets/no_data.dart'; -import 'package:PiliPalaX/models/fans/result.dart'; import '../../common/constants.dart'; import '../../utils/grid.dart'; @@ -20,21 +20,18 @@ class FansPage extends StatefulWidget { class _FansPageState extends State { late String mid; late FansController _fansController; - final ScrollController scrollController = ScrollController(); - Future? _futureBuilderFuture; @override void initState() { super.initState(); mid = Get.parameters['mid']!; _fansController = Get.put(FansController(), tag: mid); - _futureBuilderFuture = _fansController.queryFans('init'); - scrollController.addListener( + _fansController.scrollController.addListener( () async { - if (scrollController.position.pixels >= - scrollController.position.maxScrollExtent - 200) { + if (_fansController.scrollController.position.pixels >= + _fansController.scrollController.position.maxScrollExtent - 200) { EasyThrottle.throttle('follow', const Duration(seconds: 1), () { - _fansController.queryFans('onLoad'); + _fansController.onLoadMore(); }); } }, @@ -43,8 +40,7 @@ class _FansPageState extends State { @override void dispose() { - scrollController.removeListener(() {}); - scrollController.dispose(); + _fansController.scrollController.removeListener(() {}); super.dispose(); } @@ -62,58 +58,46 @@ class _FansPageState extends State { ), ), body: RefreshIndicator( - onRefresh: () async => await _fansController.queryFans('init'), + onRefresh: () async => await _fansController.onRefresh(), child: CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: scrollController, - slivers: [ - FutureBuilder( - future: _futureBuilderFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.data != null) { - var data = snapshot.data; - if (data['status']) { - return Obx(() { - List list = _fansController.fansList; - return list.isNotEmpty - ? SliverGrid( - gridDelegate: - SliverGridDelegateWithMaxCrossAxisExtent( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: - Grid.maxRowWidth * 2, - mainAxisExtent: 56), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return fanItem(item: list[index]); - }, - childCount: list.length, - )) - : const NoData(); - }); - } else { - return HttpError( - errMsg: data['msg'], - fn: () => _fansController.queryFans('init'), - ); - } - } else { - // 骨架屏 - return const SliverToBoxAdapter( - child: SizedBox( - height: 200, - child: Center( - child: CircularProgressIndicator(), - ), - ), - ); - } - }, - ), - ]), + physics: const AlwaysScrollableScrollPhysics(), + controller: _fansController.scrollController, + slivers: [ + Obx(() => _buildBody(_fansController.loadingState.value)), + ], + ), ), ); } + + Widget _buildBody(LoadingState loadingState) { + return loadingState is Success + ? loadingState.response.isNotEmpty + ? SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: StyleString.cardSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + mainAxisExtent: 56), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + return fanItem(item: loadingState.response[index]); + }, + childCount: loadingState.response.length, + )) + : const NoData() + : loadingState is Error + ? HttpError( + errMsg: loadingState.errMsg, + fn: _fansController.onReload, + ) + : const SliverToBoxAdapter( + child: SizedBox( + height: 200, + child: Center( + child: CircularProgressIndicator(), + ), + ), + ); + } }