diff --git a/lib/pages/bangumi/view.dart b/lib/pages/bangumi/view.dart index ca748b59..73fbc9a0 100644 --- a/lib/pages/bangumi/view.dart +++ b/lib/pages/bangumi/view.dart @@ -5,20 +5,18 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/tab_type.dart'; import 'package:PiliPlus/pages/bangumi/pgc_index/pgc_index_page.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/http_error.dart'; -import 'package:PiliPlus/pages/home/index.dart'; -import 'package:PiliPlus/pages/main/index.dart'; import '../../utils/grid.dart'; import 'controller.dart'; import 'widgets/bangumi_card_v.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart'; -class BangumiPage extends StatefulWidget { +class BangumiPage extends CommonPage { const BangumiPage({ super.key, required this.tabType, @@ -30,9 +28,10 @@ class BangumiPage extends StatefulWidget { State createState() => _BangumiPageState(); } -class _BangumiPageState extends State +class _BangumiPageState extends CommonPageState with AutomaticKeepAliveClientMixin { - late final BangumiController _bangumiController = Get.put( + @override + late BangumiController controller = Get.put( BangumiController(tabType: widget.tabType), tag: widget.tabType.name, ); @@ -40,51 +39,23 @@ class _BangumiPageState extends State @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - _bangumiController.scrollController.addListener(listener); - } - - void listener() { - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - final ScrollDirection direction = - _bangumiController.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - searchBarStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - searchBarStream.add(false); - } - } - - @override - void dispose() { - _bangumiController.scrollController.removeListener(listener); - super.dispose(); - } - @override Widget build(BuildContext context) { super.build(context); return refreshIndicator( onRefresh: () async { await Future.wait([ - _bangumiController.onRefresh(), - _bangumiController.queryBangumiFollow(), + controller.onRefresh(), + controller.queryBangumiFollow(), ]); }, child: CustomScrollView( - controller: _bangumiController.scrollController, + controller: controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverToBoxAdapter( child: Obx( - () => _bangumiController.isLogin.value + () => controller.isLogin.value ? Column( children: [ Padding( @@ -93,7 +64,7 @@ class _BangumiPageState extends State children: [ Obx( () => Text( - '最近${widget.tabType == TabType.bangumi ? '追番' : '追剧'}${_bangumiController.followCount.value == -1 ? '' : ' ${_bangumiController.followCount.value}'}', + '最近${widget.tabType == TabType.bangumi ? '追番' : '追剧'}${controller.followCount.value == -1 ? '' : ' ${controller.followCount.value}'}', style: Theme.of(context).textTheme.titleMedium, ), @@ -102,7 +73,7 @@ class _BangumiPageState extends State IconButton( tooltip: '刷新', onPressed: () { - _bangumiController + controller ..followPage = 1 ..followEnd = false ..queryBangumiFollow(); @@ -113,7 +84,7 @@ class _BangumiPageState extends State ), ), Obx( - () => _bangumiController.isLogin.value + () => controller.isLogin.value ? Padding( padding: const EdgeInsets.symmetric( horizontal: 10), @@ -165,8 +136,8 @@ class _BangumiPageState extends State height: Grid.smallCardWidth / 2 / 0.75 + MediaQuery.textScalerOf(context).scale(50), child: Obx( - () => _buildFollowBody( - _bangumiController.followState.value), + () => + _buildFollowBody(controller.followState.value), ), ), ], @@ -251,7 +222,7 @@ class _BangumiPageState extends State padding: const EdgeInsets.fromLTRB( StyleString.safeSpace, 0, StyleString.safeSpace, 0), sliver: Obx( - () => _buildBody(_bangumiController.loadingState.value), + () => _buildBody(controller.loadingState.value), ), ), ], @@ -277,7 +248,7 @@ class _BangumiPageState extends State delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { if (index == loadingState.response.length - 1) { - _bangumiController.onLoadMore(); + controller.onLoadMore(); } return BangumiCardV( bangumiItem: loadingState.response[index]); @@ -286,11 +257,11 @@ class _BangumiPageState extends State ), ) : HttpError( - callback: _bangumiController.onReload, + callback: controller.onReload, ), Error() => HttpError( errMsg: loadingState.errMsg, - callback: _bangumiController.onReload, + callback: controller.onReload, ), LoadingState() => throw UnimplementedError(), }; @@ -298,12 +269,12 @@ class _BangumiPageState extends State Widget _buildFollowList(Success loadingState) { return ListView.builder( - controller: _bangumiController.followController, + controller: controller.followController, scrollDirection: Axis.horizontal, itemCount: loadingState.response.length, itemBuilder: (context, index) { if (index == loadingState.response.length - 1) { - _bangumiController.queryBangumiFollow(false); + controller.queryBangumiFollow(false); } return Container( width: Grid.smallCardWidth / 2, diff --git a/lib/pages/common/common_page.dart b/lib/pages/common/common_page.dart new file mode 100644 index 00000000..46f5f012 --- /dev/null +++ b/lib/pages/common/common_page.dart @@ -0,0 +1,49 @@ +import 'dart:async'; + +import 'package:PiliPlus/pages/common/common_controller.dart'; +import 'package:PiliPlus/pages/home/controller.dart'; +import 'package:PiliPlus/pages/main/controller.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:get/get.dart'; + +abstract class CommonPage extends StatefulWidget { + const CommonPage({super.key}); +} + +abstract class CommonPageState + extends State { + R get controller; + StreamController? mainStream; + StreamController? searchBarStream; + + @override + void initState() { + super.initState(); + try { + mainStream = Get.find().bottomBarStream; + searchBarStream = Get.find().searchBarStream; + } catch (_) {} + if (mainStream != null || searchBarStream != null) { + controller.scrollController.addListener(listener); + } + } + + void listener() { + final ScrollDirection direction = + controller.scrollController.position.userScrollDirection; + if (direction == ScrollDirection.forward) { + mainStream?.add(true); + searchBarStream?.add(true); + } else if (direction == ScrollDirection.reverse) { + mainStream?.add(false); + searchBarStream?.add(false); + } + } + + @override + void dispose() { + controller.scrollController.removeListener(listener); + super.dispose(); + } +} diff --git a/lib/pages/dynamics/tab/view.dart b/lib/pages/dynamics/tab/view.dart index 41bccac2..dba38d65 100644 --- a/lib/pages/dynamics/tab/view.dart +++ b/lib/pages/dynamics/tab/view.dart @@ -2,11 +2,9 @@ import 'dart:async'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; -import 'package:PiliPlus/pages/home/controller.dart'; -import 'package:PiliPlus/pages/main/controller.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/http_error.dart'; @@ -19,7 +17,7 @@ import '../index.dart'; import '../widgets/dynamic_panel.dart'; import 'controller.dart'; -class DynamicsTabPage extends StatefulWidget { +class DynamicsTabPage extends CommonPage { const DynamicsTabPage({super.key, required this.dynamicsType}); final String dynamicsType; @@ -28,60 +26,40 @@ class DynamicsTabPage extends StatefulWidget { State createState() => _DynamicsTabPageState(); } -class _DynamicsTabPageState extends State +class _DynamicsTabPageState + extends CommonPageState with AutomaticKeepAliveClientMixin { - late DynamicsTabController _dynamicsTabController; late bool dynamicsWaterfallFlow; - late final DynamicsController dynamicsController; StreamSubscription? _listener; + DynamicsController dynamicsController = Get.put(DynamicsController()); + @override + late DynamicsTabController controller = Get.put( + DynamicsTabController(dynamicsType: widget.dynamicsType) + ..mid = dynamicsController.mid.value, + tag: widget.dynamicsType, + ); + @override bool get wantKeepAlive => true; @override void initState() { super.initState(); - dynamicsController = Get.put(DynamicsController()); - _dynamicsTabController = Get.put( - DynamicsTabController(dynamicsType: widget.dynamicsType) - ..mid = dynamicsController.mid.value, - tag: widget.dynamicsType, - ); - _dynamicsTabController.scrollController.addListener(listener); if (widget.dynamicsType == 'up') { _listener = dynamicsController.mid.listen((mid) { - // debugPrint('midListen: $mid'); - _dynamicsTabController.mid = mid; - _dynamicsTabController.scrollController.jumpTo(0); - _dynamicsTabController.onReload(); + controller.mid = mid; + controller.scrollController.jumpTo(0); + controller.onReload(); }); } dynamicsWaterfallFlow = GStorage.setting .get(SettingBoxKey.dynamicsWaterfallFlow, defaultValue: true); } - void listener() { - try { - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - final ScrollDirection direction = - _dynamicsTabController.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - searchBarStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - searchBarStream.add(false); - } - } catch (_) {} - } - @override void dispose() { _listener?.cancel(); - _dynamicsTabController.scrollController.removeListener(listener); dynamicsController.mid.close(); super.dispose(); } @@ -97,15 +75,15 @@ class _DynamicsTabPageState extends State dynamicsWaterfallFlow = GStorage.setting .get(SettingBoxKey.dynamicsWaterfallFlow, defaultValue: true); await Future.wait([ - _dynamicsTabController.onRefresh(), + controller.onRefresh(), dynamicsController.queryFollowUp(), ]); }, child: CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), - controller: _dynamicsTabController.scrollController, + controller: controller.scrollController, slivers: [ - Obx(() => _buildBody(_dynamicsTabController.loadingState.value)), + Obx(() => _buildBody(controller.loadingState.value)), ], ), ); @@ -161,7 +139,7 @@ class _DynamicsTabPageState extends State lastChildLayoutTypeBuilder: (index) { if (index == loadingState.response.length - 1) { - _dynamicsTabController.onLoadMore(); + controller.onLoadMore(); } return index == loadingState.response.length ? LastChildLayoutType.foot @@ -173,7 +151,7 @@ class _DynamicsTabPageState extends State for (var i in loadingState.response) DynamicPanel( item: i, - onRemove: _dynamicsTabController.onRemove, + onRemove: controller.onRemove, ), ] else ...[ for (var i in loadingState.response) @@ -181,7 +159,7 @@ class _DynamicsTabPageState extends State .contains(i.modules?.moduleAuthor?.mid)) DynamicPanel( item: i, - onRemove: _dynamicsTabController.onRemove, + onRemove: controller.onRemove, ), ] ], @@ -195,7 +173,7 @@ class _DynamicsTabPageState extends State delegate: SliverChildBuilderDelegate( (context, index) { if (index == loadingState.response.length - 1) { - _dynamicsTabController.onLoadMore(); + controller.onLoadMore(); } if ((dynamicsController.tabController.index == 4 && dynamicsController.mid.value != -1) || @@ -204,7 +182,7 @@ class _DynamicsTabPageState extends State ?.moduleAuthor?.mid)) { return DynamicPanel( item: loadingState.response[index], - onRemove: _dynamicsTabController.onRemove, + onRemove: controller.onRemove, ); } return const SizedBox.shrink(); @@ -217,11 +195,11 @@ class _DynamicsTabPageState extends State ], ) : HttpError( - callback: _dynamicsTabController.onReload, + callback: controller.onReload, ), Error() => HttpError( errMsg: loadingState.errMsg, - callback: _dynamicsTabController.onReload, + callback: controller.onReload, ), LoadingState() => throw UnimplementedError(), }; diff --git a/lib/pages/home/controller.dart b/lib/pages/home/controller.dart index 75045126..8ff05d10 100644 --- a/lib/pages/home/controller.dart +++ b/lib/pages/home/controller.dart @@ -19,8 +19,7 @@ class HomeController extends GetxController RxBool isLogin = false.obs; RxString userFace = ''.obs; dynamic userInfo; - late final StreamController searchBarStream = - StreamController.broadcast(); + StreamController? searchBarStream; late bool hideSearchBar; late List defaultTabs; late List tabbarSort; @@ -51,6 +50,9 @@ class HomeController extends GetxController userFace.value = userInfo != null ? userInfo.face : ''; hideSearchBar = GStorage.setting.get(SettingBoxKey.hideSearchBar, defaultValue: true); + if (hideSearchBar) { + searchBarStream = StreamController.broadcast(); + } enableSearchWord = GStorage.setting .get(SettingBoxKey.enableSearchWord, defaultValue: true); if (enableSearchWord) { @@ -117,7 +119,7 @@ class HomeController extends GetxController @override void onClose() { - searchBarStream.close(); + searchBarStream?.close(); super.onClose(); } } diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index 86daf704..7f9dc5a4 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -155,9 +155,9 @@ class _HomePageState extends State return StreamBuilder( stream: _homeController.hideSearchBar ? _mainController.navSearchStreamDebounce - ? _homeController.searchBarStream.stream + ? _homeController.searchBarStream?.stream .throttle(const Duration(milliseconds: 500)) - : _homeController.searchBarStream.stream + : _homeController.searchBarStream?.stream : null, initialData: true, builder: (BuildContext context, AsyncSnapshot snapshot) { diff --git a/lib/pages/hot/view.dart b/lib/pages/hot/view.dart index 76b1fe6a..b1c547e3 100644 --- a/lib/pages/hot/view.dart +++ b/lib/pages/hot/view.dart @@ -1,63 +1,34 @@ -import 'dart:async'; - import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/video_card_h.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/tab_type.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:PiliPlus/pages/rank/view.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/skeleton/video_card_h.dart'; import 'package:PiliPlus/common/widgets/http_error.dart'; import 'package:PiliPlus/pages/home/index.dart'; import 'package:PiliPlus/pages/hot/controller.dart'; -import 'package:PiliPlus/pages/main/index.dart'; import '../../utils/grid.dart'; -class HotPage extends StatefulWidget { +class HotPage extends CommonPage { const HotPage({super.key}); @override State createState() => _HotPageState(); } -class _HotPageState extends State with AutomaticKeepAliveClientMixin { - final HotController _hotController = Get.put(HotController()); +class _HotPageState extends CommonPageState + with AutomaticKeepAliveClientMixin { + @override + HotController controller = Get.put(HotController()); @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - _hotController.scrollController.addListener(listener); - } - - void listener() { - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - final ScrollDirection direction = - _hotController.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - searchBarStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - searchBarStream.add(false); - } - } - - @override - void dispose() { - _hotController.scrollController.removeListener(listener); - super.dispose(); - } - Widget _buildEntranceItem({ required String iconUrl, required String title, @@ -84,15 +55,15 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { super.build(context); return refreshIndicator( onRefresh: () async { - return await _hotController.onRefresh(); + await controller.onRefresh(); }, child: CustomScrollView( physics: const AlwaysScrollableScrollPhysics(), - controller: _hotController.scrollController, + controller: controller.scrollController, slivers: [ SliverToBoxAdapter( child: Obx( - () => _hotController.showHotRcmd.value + () => controller.showHotRcmd.value ? Padding( padding: const EdgeInsets.only(left: 12, top: 12, right: 12), @@ -165,7 +136,7 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { bottom: MediaQuery.of(context).padding.bottom + 80, ), sliver: Obx( - () => _buildBody(_hotController.loadingState.value), + () => _buildBody(controller.loadingState.value), ), ), ], @@ -202,7 +173,7 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { delegate: SliverChildBuilderDelegate( (context, index) { if (index == loadingState.response.length - 1) { - _hotController.onLoadMore(); + controller.onLoadMore(); } return VideoCardH( videoItem: loadingState.response[index], @@ -213,11 +184,11 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { ), ) : HttpError( - callback: _hotController.onReload, + callback: controller.onReload, ), Error() => HttpError( errMsg: loadingState.errMsg, - callback: _hotController.onReload, + callback: controller.onReload, ), LoadingState() => throw UnimplementedError(), }; diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart index b5a96fd7..2787811d 100644 --- a/lib/pages/live/view.dart +++ b/lib/pages/live/view.dart @@ -1,67 +1,36 @@ -import 'dart:async'; - import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:PiliPlus/pages/live/controller.dart'; import 'package:PiliPlus/pages/live/widgets/live_item.dart'; import 'package:PiliPlus/pages/live/widgets/live_item_follow.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/skeleton/video_card_v.dart'; import 'package:PiliPlus/common/widgets/http_error.dart'; -import 'package:PiliPlus/pages/home/index.dart'; -import 'package:PiliPlus/pages/main/index.dart'; import '../../utils/grid.dart'; -class LivePage extends StatefulWidget { +class LivePage extends CommonPage { const LivePage({super.key}); @override State createState() => _LivePageState(); } -class _LivePageState extends State +class _LivePageState extends CommonPageState with AutomaticKeepAliveClientMixin { - late final _controller = Get.put(LiveController()); + @override + LiveController controller = Get.put(LiveController()); @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - _controller.scrollController.addListener(listener); - } - - void listener() { - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - final ScrollDirection direction = - _controller.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - searchBarStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - searchBarStream.add(false); - } - } - - @override - void dispose() { - _controller.scrollController.removeListener(listener); - super.dispose(); - } - @override Widget build(BuildContext context) { super.build(context); @@ -74,14 +43,14 @@ class _LivePageState extends State ), child: refreshIndicator( onRefresh: () async { - await _controller.onRefresh(); + await controller.onRefresh(); }, child: CustomScrollView( - controller: _controller.scrollController, + controller: controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ Obx( - () => _controller.isLogin.value + () => controller.isLogin.value ? SliverPadding( padding: EdgeInsets.symmetric( vertical: StyleString.cardSpace, @@ -98,14 +67,14 @@ class _LivePageState extends State bottom: MediaQuery.paddingOf(context).bottom + 80, ), sliver: Obx( - () => _controller.loadingState.value is Loading || - _controller.loadingState.value is Success - ? contentGrid(_controller.loadingState.value) + () => controller.loadingState.value is Loading || + controller.loadingState.value is Success + ? contentGrid(controller.loadingState.value) : HttpError( - errMsg: _controller.loadingState.value is Error - ? (_controller.loadingState.value as Error).errMsg + errMsg: controller.loadingState.value is Error + ? (controller.loadingState.value as Error).errMsg : '没有相关数据', - callback: _controller.onReload, + callback: controller.onReload, ), ), ), @@ -131,7 +100,7 @@ class _LivePageState extends State (BuildContext context, int index) { if (loadingState is Success && index == loadingState.response.length - 1) { - _controller.onLoadMore(); + controller.onLoadMore(); } return loadingState is Success ? LiveCardV( @@ -157,7 +126,7 @@ class _LivePageState extends State children: [ TextSpan(text: '我的关注 '), TextSpan( - text: '${_controller.liveCount.value}', + text: '${controller.liveCount.value}', style: TextStyle( fontSize: 13, color: Theme.of(context).colorScheme.primary, @@ -198,7 +167,7 @@ class _LivePageState extends State ), ], ), - Obx(() => _buildFollowBody(_controller.followListState.value)), + Obx(() => _buildFollowBody(controller.followListState.value)), ], ); } @@ -214,7 +183,7 @@ class _LivePageState extends State gapSize: 5, childBuilder: (index) { if (index == loadingState.response.length - 1) { - _controller.fetchLiveFollowing(false); + controller.fetchLiveFollowing(false); } return SizedBox( width: 65, @@ -275,7 +244,7 @@ class _LivePageState extends State : const SizedBox.shrink(), Error() => GestureDetector( onTap: () { - _controller.fetchLiveFollowing(); + controller.fetchLiveFollowing(); }, child: Container( height: 80, @@ -294,13 +263,13 @@ class _LivePageState extends State Widget get _buildFollowListPage => Scaffold( appBar: AppBar( title: Obx( - () => Text('${_controller.liveCount.value}人正在直播'), + () => Text('${controller.liveCount.value}人正在直播'), ), ), body: CustomScrollView( slivers: [ Obx( - () => _buildFollowListBody(_controller.followListState.value), + () => _buildFollowListBody(controller.followListState.value), ), ], ), @@ -326,7 +295,7 @@ class _LivePageState extends State (BuildContext context, int index) { if (loadingState is Success && index == loadingState.response.length - 1) { - _controller.fetchLiveFollowing(false); + controller.fetchLiveFollowing(false); } return loadingState is Success ? LiveCardVFollow( @@ -342,7 +311,7 @@ class _LivePageState extends State Error() => HttpError( errMsg: loadingState.errMsg, callback: () { - _controller + controller ..followListState.value = LoadingState.loading() ..fetchLiveFollowing(); }, diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index 943b63fa..9b449c78 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -18,8 +18,7 @@ class MainController extends GetxController { List pages = []; RxList navigationBars = [].obs; - final StreamController bottomBarStream = - StreamController.broadcast(); + StreamController? bottomBarStream; late bool hideTabBar; late dynamic controller; RxInt selectedIndex = 0.obs; @@ -48,6 +47,9 @@ class MainController extends GetxController { } hideTabBar = GStorage.setting.get(SettingBoxKey.hideTabBar, defaultValue: true); + if (hideTabBar) { + bottomBarStream = StreamController.broadcast(); + } isLogin.value = Accounts.main.isLogin; dynamicBadgeMode = DynamicBadgeMode.values[GStorage.setting.get( SettingBoxKey.dynamicBadgeMode, @@ -217,7 +219,7 @@ class MainController extends GetxController { @override void onClose() { - bottomBarStream.close(); + bottomBarStream?.close(); super.onClose(); } } diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index d91de134..5fb61dc8 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -178,7 +178,8 @@ class _MainAppState extends State onPopInvokedWithResult: (bool didPop, Object? result) async { if (_mainController.selectedIndex.value != 0) { setIndex(0); - _mainController.bottomBarStream.add(true); + _mainController.bottomBarStream?.add(true); + _homeController.searchBarStream?.add(true); } else { if (Platform.isAndroid) { Utils.channel.invokeMethod('back'); @@ -265,9 +266,9 @@ class _MainAppState extends State : StreamBuilder( stream: _mainController.hideTabBar ? _mainController.navSearchStreamDebounce - ? _mainController.bottomBarStream.stream + ? _mainController.bottomBarStream?.stream .throttle(const Duration(milliseconds: 500)) - : _mainController.bottomBarStream.stream + : _mainController.bottomBarStream?.stream : null, initialData: true, builder: (context, AsyncSnapshot snapshot) { diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index 3ca45010..09ac7db0 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -1,54 +1,29 @@ import 'dart:async'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/models/user/fav_folder.dart'; -import 'package:PiliPlus/pages/main/index.dart'; import 'package:PiliPlus/pages/media/index.dart'; import 'package:PiliPlus/utils/utils.dart'; -class MediaPage extends StatefulWidget { +class MediaPage extends CommonPage { const MediaPage({super.key}); @override State createState() => _MediaPageState(); } -class _MediaPageState extends State +class _MediaPageState extends CommonPageState with AutomaticKeepAliveClientMixin { - late MediaController mediaController; + @override + MediaController controller = Get.put(MediaController()); @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - mediaController = Get.put(MediaController()); - mediaController.scrollController.addListener(listener); - } - - void listener() { - StreamController mainStream = - Get.find().bottomBarStream; - final ScrollDirection direction = - mediaController.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - } - } - - @override - void dispose() { - mediaController.scrollController.removeListener(listener); - super.dispose(); - } - @override Widget build(BuildContext context) { super.build(context); @@ -60,7 +35,7 @@ class _MediaPageState extends State ), body: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), - controller: mediaController.scrollController, + controller: controller.scrollController, child: Column( children: [ ListTile( @@ -86,7 +61,7 @@ class _MediaPageState extends State size: 20, ), )), - for (var i in mediaController.list) ...[ + for (var i in controller.list) ...[ ListTile( onTap: () => i['onTap'](), dense: true, @@ -107,7 +82,7 @@ class _MediaPageState extends State ), ], Obx( - () => mediaController.loadingState.value is Loading + () => controller.loadingState.value is Loading ? const SizedBox.shrink() : favFolder(), ) @@ -128,7 +103,7 @@ class _MediaPageState extends State onTap: () async { await Get.toNamed('/fav'); Future.delayed(const Duration(milliseconds: 150), () { - mediaController.onRefresh(); + controller.onRefresh(); }); }, leading: null, @@ -146,9 +121,9 @@ class _MediaPageState extends State Theme.of(context).textTheme.titleMedium!.fontSize, fontWeight: FontWeight.bold), ), - if (mediaController.count.value != -1) + if (controller.count.value != -1) TextSpan( - text: "${mediaController.count.value} ", + text: "${controller.count.value} ", style: TextStyle( fontSize: Theme.of(context).textTheme.titleSmall!.fontSize, @@ -168,7 +143,7 @@ class _MediaPageState extends State ), trailing: IconButton( tooltip: '刷新', - onPressed: mediaController.onRefresh, + onPressed: controller.onRefresh, icon: const Icon( Icons.refresh, size: 20, @@ -179,7 +154,7 @@ class _MediaPageState extends State SizedBox( width: double.infinity, height: MediaQuery.textScalerOf(context).scale(200), - child: Obx(() => _buildBody(mediaController.loadingState.value)), + child: Obx(() => _buildBody(controller.loadingState.value)), ), SizedBox( height: MediaQuery.paddingOf(context).bottom + 100, @@ -214,7 +189,7 @@ class _MediaPageState extends State onPressed: () async { await Get.toNamed('/fav'); Future.delayed(const Duration(milliseconds: 150), () { - mediaController.onRefresh(); + controller.onRefresh(); }); }, icon: Icon( @@ -242,7 +217,7 @@ class _MediaPageState extends State }, ); Future.delayed(const Duration(milliseconds: 150), () { - mediaController.onRefresh(); + controller.onRefresh(); }); }, ); diff --git a/lib/pages/rank/zone/view.dart b/lib/pages/rank/zone/view.dart index 5b52a200..f80fdf91 100644 --- a/lib/pages/rank/zone/view.dart +++ b/lib/pages/rank/zone/view.dart @@ -1,21 +1,17 @@ -import 'dart:async'; - import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/skeleton/video_card_h.dart'; import 'package:PiliPlus/common/widgets/http_error.dart'; import 'package:PiliPlus/common/widgets/video_card_h.dart'; -import 'package:PiliPlus/pages/home/index.dart'; -import 'package:PiliPlus/pages/main/index.dart'; import 'package:PiliPlus/pages/rank/zone/index.dart'; import '../../../utils/grid.dart'; -class ZonePage extends StatefulWidget { +class ZonePage extends CommonPage { const ZonePage({super.key, required this.rid}); final int rid; @@ -24,52 +20,26 @@ class ZonePage extends StatefulWidget { State createState() => _ZonePageState(); } -class _ZonePageState extends State +class _ZonePageState extends CommonPageState with AutomaticKeepAliveClientMixin { - late ZoneController _zoneController; + @override + late ZoneController controller = Get.put( + ZoneController(zoneID: widget.rid), + tag: widget.rid.toString(), + ); @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - _zoneController = - Get.put(ZoneController(zoneID: widget.rid), tag: widget.rid.toString()); - _zoneController.scrollController.addListener(listener); - } - - void listener() { - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - final ScrollDirection direction = - _zoneController.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - searchBarStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - searchBarStream.add(false); - } - } - - @override - void dispose() { - _zoneController.scrollController.removeListener(listener); - super.dispose(); - } - @override Widget build(BuildContext context) { super.build(context); return refreshIndicator( onRefresh: () async { - await _zoneController.onRefresh(); + await controller.onRefresh(); }, child: CustomScrollView( - controller: _zoneController.scrollController, + controller: controller.scrollController, slivers: [ SliverPadding( // 单列布局 EdgeInsets.zero @@ -78,17 +48,15 @@ class _ZonePageState extends State bottom: MediaQuery.of(context).padding.bottom + 80, ), sliver: Obx( - () => _zoneController.loadingState.value is Loading + () => controller.loadingState.value is Loading ? _buildSkeleton() - : _zoneController.loadingState.value is Success - ? _buildBody( - _zoneController.loadingState.value as Success) + : controller.loadingState.value is Success + ? _buildBody(controller.loadingState.value as Success) : HttpError( - errMsg: _zoneController.loadingState.value is Error - ? (_zoneController.loadingState.value as Error) - .errMsg + errMsg: controller.loadingState.value is Error + ? (controller.loadingState.value as Error).errMsg : '没有相关数据', - callback: _zoneController.onReload, + callback: controller.onReload, ), ), ), diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index 0eca275a..7b6c43d7 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -1,62 +1,31 @@ -import 'dart:async'; - import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/skeleton/video_card_v.dart'; import 'package:PiliPlus/common/widgets/http_error.dart'; import 'package:PiliPlus/common/widgets/video_card_v.dart'; -import 'package:PiliPlus/pages/home/index.dart'; -import 'package:PiliPlus/pages/main/index.dart'; import '../../utils/grid.dart'; import 'controller.dart'; -class RcmdPage extends StatefulWidget { +class RcmdPage extends CommonPage { const RcmdPage({super.key}); @override State createState() => _RcmdPageState(); } -class _RcmdPageState extends State +class _RcmdPageState extends CommonPageState with AutomaticKeepAliveClientMixin { - late final _controller = Get.put(RcmdController()); + @override + late RcmdController controller = Get.put(RcmdController()); @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - _controller.scrollController.addListener(listener); - } - - void listener() { - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - final ScrollDirection direction = - _controller.scrollController.position.userScrollDirection; - if (direction == ScrollDirection.forward) { - mainStream.add(true); - searchBarStream.add(true); - } else if (direction == ScrollDirection.reverse) { - mainStream.add(false); - searchBarStream.add(false); - } - } - - @override - void dispose() { - _controller.scrollController.removeListener(listener); - super.dispose(); - } - @override Widget build(BuildContext context) { super.build(context); @@ -69,10 +38,10 @@ class _RcmdPageState extends State ), child: refreshIndicator( onRefresh: () async { - await _controller.onRefresh(); + await controller.onRefresh(); }, child: CustomScrollView( - controller: _controller.scrollController, + controller: controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverPadding( @@ -81,14 +50,14 @@ class _RcmdPageState extends State bottom: MediaQuery.paddingOf(context).bottom, ), sliver: Obx( - () => _controller.loadingState.value is Loading || - _controller.loadingState.value is Success - ? contentGrid(_controller.loadingState.value) + () => controller.loadingState.value is Loading || + controller.loadingState.value is Success + ? contentGrid(controller.loadingState.value) : HttpError( - errMsg: _controller.loadingState.value is Error - ? (_controller.loadingState.value as Error).errMsg + errMsg: controller.loadingState.value is Error + ? (controller.loadingState.value as Error).errMsg : '没有相关数据', - callback: _controller.onReload, + callback: controller.onReload, ), ), ), @@ -114,15 +83,15 @@ class _RcmdPageState extends State (BuildContext context, int index) { if (loadingState is Success && index == loadingState.response.length - 1) { - _controller.onLoadMore(); + controller.onLoadMore(); } if (loadingState is Success) { - if (_controller.lastRefreshAt != null) { - if (_controller.lastRefreshAt == index) { + if (controller.lastRefreshAt != null) { + if (controller.lastRefreshAt == index) { return GestureDetector( onTap: () { - _controller.animateToTop(); - _controller.onRefresh(); + controller.animateToTop(); + controller.onRefresh(); }, child: Card( margin: EdgeInsets.zero, @@ -140,19 +109,19 @@ class _RcmdPageState extends State ), ); } - int actualIndex = _controller.lastRefreshAt == null + int actualIndex = controller.lastRefreshAt == null ? index - : index > _controller.lastRefreshAt! + : index > controller.lastRefreshAt! ? index - 1 : index; return VideoCardV( videoItem: loadingState.response[actualIndex], onRemove: () { - if (_controller.lastRefreshAt != null && - actualIndex < _controller.lastRefreshAt!) { - _controller.lastRefreshAt = _controller.lastRefreshAt! - 1; + if (controller.lastRefreshAt != null && + actualIndex < controller.lastRefreshAt!) { + controller.lastRefreshAt = controller.lastRefreshAt! - 1; } - _controller.loadingState.value = LoadingState.success( + controller.loadingState.value = LoadingState.success( (loadingState.response as List)..removeAt(actualIndex)); }, ); @@ -160,7 +129,7 @@ class _RcmdPageState extends State return VideoCardV( videoItem: loadingState.response[index], onRemove: () { - _controller.loadingState.value = LoadingState.success( + controller.loadingState.value = LoadingState.success( (loadingState.response as List)..removeAt(index)); }, ); @@ -169,7 +138,7 @@ class _RcmdPageState extends State return const VideoCardVSkeleton(); }, childCount: loadingState is Success - ? _controller.lastRefreshAt != null + ? controller.lastRefreshAt != null ? loadingState.response.length + 1 : loadingState.response.length : 10,