From 01df8622e03e1f21105a69b44eebf942b710b7cb Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 31 Aug 2023 21:42:59 +0800 Subject: [PATCH 1/2] =?UTF-8?q?mod:=20=E5=85=B3=E6=B3=A8=E3=80=81=E7=B2=89?= =?UTF-8?q?=E4=B8=9D=E9=A1=B5=E9=9D=A2=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/fan/controller.dart | 17 ++++++++++-- lib/pages/fan/view.dart | 45 ++++++++++++++++++++++-------- lib/pages/follow/controller.dart | 16 +++++++++-- lib/pages/follow/view.dart | 47 ++++++++++++++++++++++++-------- 4 files changed, 97 insertions(+), 28 deletions(-) diff --git a/lib/pages/fan/controller.dart b/lib/pages/fan/controller.dart index 4f389b92..4f1d2ae8 100644 --- a/lib/pages/fan/controller.dart +++ b/lib/pages/fan/controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/fan.dart'; @@ -7,11 +8,13 @@ import 'package:pilipala/utils/storage.dart'; class FansController extends GetxController { Box userInfoCache = GStrorage.userInfo; int pn = 1; + int ps = 20; int total = 0; RxList fansList = [FansItemModel()].obs; late int mid; late String name; var userInfo; + RxString loadingText = '加载中...'.obs; @override void onInit() { @@ -26,23 +29,31 @@ class FansController extends GetxController { Future queryFans(type) async { if (type == 'init') { pn = 1; + loadingText.value == '加载中...'; + } + if (loadingText.value == '没有更多了') { + return; } var res = await FanHttp.fans( vmid: mid, pn: pn, - ps: 20, + ps: ps, orderType: 'attention', ); if (res['status']) { if (type == 'init') { fansList.value = res['data'].list; total = res['data'].total; - } else if (type == 'onRefresh') { - fansList.insertAll(0, res['data'].list); } else if (type == 'onLoad') { fansList.addAll(res['data'].list); } + print(total); + if ((pn == 1 && total < ps) || res['data'].list.isEmpty) { + loadingText.value = '没有更多了'; + } pn += 1; + } else { + SmartDialog.showToast(res['msg']); } return res; } diff --git a/lib/pages/fan/view.dart b/lib/pages/fan/view.dart index a0b42528..6a0af3c6 100644 --- a/lib/pages/fan/view.dart +++ b/lib/pages/fan/view.dart @@ -1,6 +1,8 @@ +import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/models/fans/result.dart'; import 'controller.dart'; @@ -17,7 +19,6 @@ class _FansPageState extends State { final FansController _fansController = Get.put(FansController()); final ScrollController scrollController = ScrollController(); Future? _futureBuilderFuture; - bool _isLoadingMore = false; @override void initState() { @@ -27,11 +28,9 @@ class _FansPageState extends State { () async { if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 200) { - if (!_isLoadingMore) { - _isLoadingMore = true; - await _fansController.queryFans('onLoad'); - _isLoadingMore = false; - } + EasyThrottle.throttle('follow', const Duration(seconds: 1), () { + _fansController.queryFans('onLoad'); + }); } }, ); @@ -66,14 +65,38 @@ class _FansPageState extends State { if (data['status']) { List list = _fansController.fansList; return Obx( - () => list.length == 1 - ? const SizedBox() - : ListView.builder( + () => list.isNotEmpty + ? ListView.builder( controller: scrollController, - itemCount: list.length, + itemCount: list.length + 1, itemBuilder: (BuildContext context, int index) { - return fanItem(item: list[index]); + if (index == list.length) { + return Container( + height: + MediaQuery.of(context).padding.bottom + 60, + padding: EdgeInsets.only( + bottom: + MediaQuery.of(context).padding.bottom), + child: Center( + child: Obx( + () => Text( + _fansController.loadingText.value, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .outline, + fontSize: 13), + ), + ), + ), + ); + } else { + return fanItem(item: list[index]); + } }, + ) + : const CustomScrollView( + slivers: [NoData()], ), ); } else { diff --git a/lib/pages/follow/controller.dart b/lib/pages/follow/controller.dart index a64e20f6..fe1bfabc 100644 --- a/lib/pages/follow/controller.dart +++ b/lib/pages/follow/controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/follow.dart'; @@ -7,11 +8,13 @@ import 'package:pilipala/utils/storage.dart'; class FollowController extends GetxController { Box userInfoCache = GStrorage.userInfo; int pn = 1; + int ps = 20; int total = 0; RxList followList = [FollowItemModel()].obs; late int mid; late String name; var userInfo; + RxString loadingText = '加载中...'.obs; @override void onInit() { @@ -26,23 +29,30 @@ class FollowController extends GetxController { Future queryFollowings(type) async { if (type == 'init') { pn = 1; + loadingText.value == '加载中...'; + } + if (loadingText.value == '没有更多了') { + return; } var res = await FollowHttp.followings( vmid: mid, pn: pn, - ps: 20, + ps: ps, orderType: 'attention', ); if (res['status']) { if (type == 'init') { followList.value = res['data'].list; total = res['data'].total; - } else if (type == 'onRefresh') { - followList.insertAll(0, res['data'].list); } else if (type == 'onLoad') { followList.addAll(res['data'].list); } + if ((pn == 1 && total < ps) || res['data'].list.isEmpty) { + loadingText.value = '没有更多了'; + } pn += 1; + } else { + SmartDialog.showToast(res['msg']); } return res; } diff --git a/lib/pages/follow/view.dart b/lib/pages/follow/view.dart index d2a4b423..9e290f0f 100644 --- a/lib/pages/follow/view.dart +++ b/lib/pages/follow/view.dart @@ -1,6 +1,8 @@ +import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/models/follow/result.dart'; import 'controller.dart'; @@ -17,7 +19,6 @@ class _FollowPageState extends State { final FollowController _followController = Get.put(FollowController()); final ScrollController scrollController = ScrollController(); Future? _futureBuilderFuture; - bool _isLoadingMore = false; @override void initState() { @@ -27,11 +28,9 @@ class _FollowPageState extends State { () async { if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 200) { - if (!_isLoadingMore) { - _isLoadingMore = true; - await _followController.queryFollowings('onLoad'); - _isLoadingMore = false; - } + EasyThrottle.throttle('follow', const Duration(seconds: 1), () { + _followController.queryFollowings('onLoad'); + }); } }, ); @@ -67,14 +66,40 @@ class _FollowPageState extends State { if (data['status']) { List list = _followController.followList; return Obx( - () => list.length == 1 - ? const SizedBox() - : ListView.builder( + () => list.isNotEmpty + ? ListView.builder( controller: scrollController, - itemCount: list.length, + itemCount: list.length + 1, itemBuilder: (BuildContext context, int index) { - return followItem(item: list[index]); + if (index == list.length) { + return Container( + height: + MediaQuery.of(context).padding.bottom + + 60, + padding: EdgeInsets.only( + bottom: MediaQuery.of(context) + .padding + .bottom), + child: Center( + child: Obx( + () => Text( + _followController.loadingText.value, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .outline, + fontSize: 13), + ), + ), + ), + ); + } else { + return followItem(item: list[index]); + } }, + ) + : const CustomScrollView( + slivers: [NoData()], ), ); } else { From 9b1bb8c566517dea0d04b36abf6ea6f3eef44dd5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 31 Aug 2023 22:41:19 +0800 Subject: [PATCH 2/2] =?UTF-8?q?mod:=20=E7=99=BB=E5=BD=95=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/network_img_layer.dart | 10 ++++++- lib/pages/dynamics/view.dart | 15 +++++----- lib/pages/home/controller.dart | 5 ++-- lib/pages/home/view.dart | 12 ++++---- lib/pages/media/controller.dart | 5 ++-- lib/pages/media/view.dart | 6 ++-- lib/pages/mine/view.dart | 36 ++--------------------- lib/pages/setting/controller.dart | 17 ++--------- lib/pages/webview/controller.dart | 9 ++++-- lib/utils/login.dart | 30 +++++++++++++++++++ 10 files changed, 71 insertions(+), 74 deletions(-) create mode 100644 lib/utils/login.dart diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 46683e96..c44bd0e7 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -70,9 +70,17 @@ class NetworkImgLayer extends StatelessWidget { Widget placeholder(context) { return Container( - color: Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.4), width: width ?? double.infinity, height: height ?? double.infinity, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.4), + borderRadius: BorderRadius.circular(type == 'avatar' + ? 50 + : type == 'emote' + ? 0 + : StyleString.imgRadius.x), + ), child: Center( child: Image.asset( type == 'avatar' diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index 20a14e6a..d7d40021 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -11,7 +11,6 @@ import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/pages/main/index.dart'; -import 'package:pilipala/utils/event_bus.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/storage.dart'; @@ -32,7 +31,6 @@ class _DynamicsPageState extends State late Future _futureBuilderFuture; late Future _futureBuilderFutureUp; Box userInfoCache = GStrorage.userInfo; - EventBus eventBus = EventBus(); late ScrollController scrollController; @override @@ -66,12 +64,13 @@ class _DynamicsPageState extends State }, ); - eventBus.on(EventName.loginEvent, (args) { - _dynamicsController.userLogin.value = args['status']; - setState(() { - _futureBuilderFuture = _dynamicsController.queryFollowDynamic(); - _futureBuilderFutureUp = _dynamicsController.queryFollowUp(); - }); + _dynamicsController.userLogin.listen((status) { + if (mounted) { + setState(() { + _futureBuilderFuture = _dynamicsController.queryFollowDynamic(); + _futureBuilderFutureUp = _dynamicsController.queryFollowUp(); + }); + } }); } diff --git a/lib/pages/home/controller.dart b/lib/pages/home/controller.dart index 727cdce3..4239096c 100644 --- a/lib/pages/home/controller.dart +++ b/lib/pages/home/controller.dart @@ -48,9 +48,10 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { } // 更新登录状态 - void updateLoginStatus(val) { - userInfo = userInfoCache.get('userInfoCache'); + void updateLoginStatus(val) async { + userInfo = await userInfoCache.get('userInfoCache'); userLogin.value = val ?? false; + if (val) return; userFace.value = userInfo != null ? userInfo.face : ''; } } diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index 9ad8a25f..3cdf81c7 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -134,11 +134,13 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { () => ctr!.userLogin.value ? Stack( children: [ - NetworkImgLayer( - type: 'avatar', - width: 34, - height: 34, - src: ctr!.userFace.value, + Obx( + () => NetworkImgLayer( + type: 'avatar', + width: 34, + height: 34, + src: ctr!.userFace.value, + ), ), Positioned.fill( child: Material( diff --git a/lib/pages/media/controller.dart b/lib/pages/media/controller.dart index 688b555c..06522eeb 100644 --- a/lib/pages/media/controller.dart +++ b/lib/pages/media/controller.dart @@ -35,6 +35,7 @@ class MediaController extends GetxController { }, ]; var userInfo; + int? mid; @override void onInit() { @@ -44,13 +45,13 @@ class MediaController extends GetxController { } Future queryFavFolder() async { - if (!userLogin.value || GStrorage.userInfo.get('userInfoCache') == null) { + if (!userLogin.value) { return {'status': false, 'data': [], 'msg': '未登录'}; } var res = await await UserHttp.userfavFolder( pn: 1, ps: 5, - mid: GStrorage.userInfo.get('userInfoCache').mid, + mid: mid ?? GStrorage.userInfo.get('userInfoCache').mid, ); favFolderData.value = res['data']; return res; diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index 42ade71c..8ce33597 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -3,7 +3,6 @@ import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/user/fav_folder.dart'; import 'package:pilipala/pages/media/index.dart'; -import 'package:pilipala/utils/event_bus.dart'; import 'package:pilipala/utils/utils.dart'; class MediaPage extends StatefulWidget { @@ -17,7 +16,6 @@ class _MediaPageState extends State with AutomaticKeepAliveClientMixin { late MediaController mediaController; late Future _futureBuilderFuture; - EventBus eventBus = EventBus(); @override bool get wantKeepAlive => true; @@ -27,8 +25,8 @@ class _MediaPageState extends State super.initState(); mediaController = Get.put(MediaController()); _futureBuilderFuture = mediaController.queryFavFolder(); - eventBus.on(EventName.loginEvent, (args) { - mediaController.userLogin.value = args['status']; + + mediaController.userLogin.listen((status) { setState(() { _futureBuilderFuture = mediaController.queryFavFolder(); }); diff --git a/lib/pages/mine/view.dart b/lib/pages/mine/view.dart index 4c71869d..3698984c 100644 --- a/lib/pages/mine/view.dart +++ b/lib/pages/mine/view.dart @@ -7,7 +7,6 @@ import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/models/user/info.dart'; -import 'package:pilipala/utils/event_bus.dart'; import 'controller.dart'; class MinePage extends StatefulWidget { @@ -20,14 +19,13 @@ class MinePage extends StatefulWidget { class _MinePageState extends State { final MineController mineController = Get.put(MineController()); late Future _futureBuilderFuture; - EventBus eventBus = EventBus(); @override void initState() { super.initState(); _futureBuilderFuture = mineController.queryUserInfo(); - eventBus.on(EventName.loginEvent, (args) { - mineController.userLogin.value = args['status']; + + mineController.userLogin.listen((status) { if (mounted) { setState(() { _futureBuilderFuture = mineController.queryUserInfo(); @@ -214,36 +212,6 @@ class _MinePageState extends State { ); }, ), - // LayoutBuilder( - // builder: (context, BoxConstraints box) { - // return Container( - // width: box.maxWidth, - // height: 1, - // color: Theme.of(context).colorScheme.onInverseSurface, - // child: Stack( - // children: [ - // Positioned( - // top: 0, - // left: 0, - // bottom: 0, - // child: Container( - // width: box.maxWidth * - // (_mineController - // .userInfo.value.levelInfo!.currentExp! / - // _mineController - // .userInfo.value.levelInfo!.nextExp!), - // height: 1, - // decoration: BoxDecoration( - // borderRadius: BorderRadius.circular(4), - // color: Theme.of(context).colorScheme.primary, - // ), - // ), - // ), - // ], - // ), - // ); - // }, - // ), ], const SizedBox(height: 30), Padding( diff --git a/lib/pages/setting/controller.dart b/lib/pages/setting/controller.dart index 2cf50ebf..0e1505a5 100644 --- a/lib/pages/setting/controller.dart +++ b/lib/pages/setting/controller.dart @@ -4,16 +4,13 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/init.dart'; import 'package:pilipala/models/common/theme_type.dart'; -import 'package:pilipala/pages/home/index.dart'; -import 'package:pilipala/pages/mine/controller.dart'; -import 'package:pilipala/utils/event_bus.dart'; import 'package:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/login.dart'; import 'package:pilipala/utils/storage.dart'; class SettingController extends GetxController { Box userInfoCache = GStrorage.userInfo; Box setting = GStrorage.setting; - // Box userInfoCache = GStrorage.userInfo; Box localCache = GStrorage.localCache; RxBool userLogin = false.obs; @@ -59,17 +56,7 @@ class SettingController extends GetxController { localCache .put(LocalCacheKey.accessKey, {'mid': -1, 'value': ''}); - // 更改我的页面登录状态 - await Get.find().resetUserInfo(); - - // 更改主页登录状态 - HomeController homeCtr = Get.find(); - homeCtr.updateLoginStatus(false); - - // 事件通知 - EventBus eventBus = EventBus(); - eventBus.emit(EventName.loginEvent, {'status': false}); - + await LoginUtils.refreshLoginStatus(false); SmartDialog.dismiss().then((value) => Get.back()); }, child: const Text('确认'), diff --git a/lib/pages/webview/controller.dart b/lib/pages/webview/controller.dart index 67d60d6a..492bf19e 100644 --- a/lib/pages/webview/controller.dart +++ b/lib/pages/webview/controller.dart @@ -8,8 +8,10 @@ import 'package:hive/hive.dart'; import 'package:pilipala/http/init.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/pages/home/index.dart'; +import 'package:pilipala/pages/media/index.dart'; import 'package:pilipala/utils/cookie.dart'; import 'package:pilipala/utils/event_bus.dart'; +import 'package:pilipala/utils/login.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -94,11 +96,12 @@ class WebviewController extends GetxController { Box userInfoCache = GStrorage.userInfo; await userInfoCache.put('userInfoCache', result['data']); - // 通知更新 - eventBus.emit(EventName.loginEvent, {'status': true}); - HomeController homeCtr = Get.find(); homeCtr.updateLoginStatus(true); + homeCtr.userFace.value = result['data'].face; + MediaController mediaCtr = Get.find(); + mediaCtr.mid = result['data'].mid; + await LoginUtils.refreshLoginStatus(true); } catch (err) { SmartDialog.show(builder: (context) { return AlertDialog( diff --git a/lib/utils/login.dart b/lib/utils/login.dart new file mode 100644 index 00000000..54c03775 --- /dev/null +++ b/lib/utils/login.dart @@ -0,0 +1,30 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/pages/dynamics/index.dart'; +import 'package:pilipala/pages/home/index.dart'; +import 'package:pilipala/pages/media/index.dart'; +import 'package:pilipala/pages/mine/index.dart'; + +class LoginUtils { + static Future refreshLoginStatus(bool status) async { + try { + // 更改我的页面登录状态 + await Get.find().resetUserInfo(); + + // 更改主页登录状态 + HomeController homeCtr = Get.find(); + homeCtr.updateLoginStatus(status); + + MineController mineCtr = Get.find(); + mineCtr.userLogin.value = status; + + DynamicsController dynamicsCtr = Get.find(); + dynamicsCtr.userLogin.value = status; + + MediaController mediaCtr = Get.find(); + mediaCtr.userLogin.value = status; + } catch (err) { + SmartDialog.showToast('refreshLoginStatus error: ${err.toString()}'); + } + } +}