diff --git a/lib/models/common/tab_type.dart b/lib/models/common/tab_type.dart index b4d1c73f..15705d30 100644 --- a/lib/models/common/tab_type.dart +++ b/lib/models/common/tab_type.dart @@ -22,7 +22,7 @@ List tabsConfig = [ 'label': '直播', 'type': TabType.live, 'ctr': Get.find, - 'page': const LivePage(), + 'page': const RcmdPage(tabType: TabType.live), }, { 'icon': const Icon( @@ -32,7 +32,7 @@ List tabsConfig = [ 'label': '推荐', 'type': TabType.rcmd, 'ctr': Get.find, - 'page': const RcmdPage(), + 'page': const RcmdPage(tabType: TabType.rcmd), }, { 'icon': const Icon( diff --git a/lib/pages/common/popup_controller.dart b/lib/pages/common/popup_controller.dart new file mode 100644 index 00000000..60b51b2e --- /dev/null +++ b/lib/pages/common/popup_controller.dart @@ -0,0 +1,6 @@ +import 'package:PiliPalaX/pages/common/common_controller.dart'; +import 'package:flutter/material.dart'; + +abstract class PopupController extends CommonController { + List popupDialog = []; +} diff --git a/lib/pages/home/controller.dart b/lib/pages/home/controller.dart index 35697cd6..dcefd823 100644 --- a/lib/pages/home/controller.dart +++ b/lib/pages/home/controller.dart @@ -67,7 +67,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { } void setTabConfig() async { - defaultTabs = [...tabsConfig]; + defaultTabs = tabsConfig; tabbarSort = settingStorage .get(SettingBoxKey.tabbarSort, defaultValue: ['live', 'rcmd', 'hot', 'rank', 'bangumi']) diff --git a/lib/pages/hot/controller.dart b/lib/pages/hot/controller.dart index f82dece0..096a641a 100644 --- a/lib/pages/hot/controller.dart +++ b/lib/pages/hot/controller.dart @@ -1,11 +1,9 @@ import 'package:PiliPalaX/http/loading_state.dart'; -import 'package:PiliPalaX/pages/common/common_controller.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPalaX/pages/common/popup_controller.dart'; import 'package:PiliPalaX/http/video.dart'; -class HotController extends CommonController { +class HotController extends PopupController { final int _count = 20; - List popupDialog = []; @override void onInit() { diff --git a/lib/pages/live/controller.dart b/lib/pages/live/controller.dart index b7bdb9e5..5da03be0 100644 --- a/lib/pages/live/controller.dart +++ b/lib/pages/live/controller.dart @@ -1,12 +1,8 @@ import 'package:PiliPalaX/http/loading_state.dart'; -import 'package:PiliPalaX/pages/common/common_controller.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPalaX/pages/common/popup_controller.dart'; import 'package:PiliPalaX/http/live.dart'; -class LiveController extends CommonController { - int count = 12; - List popupDialog = []; - +class LiveController extends PopupController { @override void onInit() { super.onInit(); @@ -14,7 +10,5 @@ class LiveController extends CommonController { } @override - Future customGetData() => LiveHttp.liveList( - pn: currentPage, - ); + Future customGetData() => LiveHttp.liveList(pn: currentPage); } diff --git a/lib/pages/live/index.dart b/lib/pages/live/index.dart index a847f497..2e560f11 100644 --- a/lib/pages/live/index.dart +++ b/lib/pages/live/index.dart @@ -1,4 +1,3 @@ library live; export './controller.dart'; -export './view.dart'; diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart deleted file mode 100644 index 82440f2d..00000000 --- a/lib/pages/live/view.dart +++ /dev/null @@ -1,155 +0,0 @@ -import 'dart:async'; - -import 'package:PiliPalaX/http/loading_state.dart'; -import 'package:easy_debounce/easy_throttle.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; -import 'package:get/get.dart'; -import 'package:PiliPalaX/common/constants.dart'; -import 'package:PiliPalaX/common/skeleton/video_card_v.dart'; -import 'package:PiliPalaX/common/widgets/animated_dialog.dart'; -import 'package:PiliPalaX/common/widgets/http_error.dart'; -import 'package:PiliPalaX/pages/home/index.dart'; -import 'package:PiliPalaX/pages/main/index.dart'; - -import '../../utils/grid.dart'; -import 'controller.dart'; -import 'widgets/live_item.dart'; - -class LivePage extends StatefulWidget { - const LivePage({super.key}); - - @override - State createState() => _LivePageState(); -} - -class _LivePageState extends State - with AutomaticKeepAliveClientMixin { - final LiveController _liveController = Get.put(LiveController()); - - @override - bool get wantKeepAlive => true; - - @override - void initState() { - super.initState(); - StreamController mainStream = - Get.find().bottomBarStream; - StreamController searchBarStream = - Get.find().searchBarStream; - _liveController.scrollController.addListener( - () { - if (_liveController.scrollController.position.pixels >= - _liveController.scrollController.position.maxScrollExtent - 200) { - EasyThrottle.throttle('liveList', const Duration(milliseconds: 200), - () { - _liveController.onLoadMore(); - }); - } - - final ScrollDirection direction = - _liveController.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() { - _liveController.scrollController.removeListener(() {}); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - super.build(context); - return Container( - clipBehavior: Clip.hardEdge, - margin: const EdgeInsets.only( - left: StyleString.cardSpace, right: StyleString.cardSpace), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(StyleString.imgRadius), - ), - child: RefreshIndicator( - onRefresh: () async { - return await _liveController.onRefresh(); - }, - child: CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), - controller: _liveController.scrollController, - slivers: [ - SliverPadding( - // 单列布局 EdgeInsets.zero - padding: - const EdgeInsets.fromLTRB(0, StyleString.cardSpace, 0, 0), - sliver: Obx( - () => _liveController.loadingState.value is Loading || - _liveController.loadingState.value is Success - ? contentGrid(_liveController.loadingState.value) - : HttpError( - errMsg: _liveController.loadingState.value is Error - ? (_liveController.loadingState.value as Error) - .errMsg - : '没有相关数据', - fn: () { - _liveController.loadingState.value = - LoadingState.loading(); - _liveController.onRefresh(); - }), - ), - ), - ], - ), - ), - ); - } - - void _removePopupDialog() { - _liveController.popupDialog.last?.remove(); - _liveController.popupDialog.removeLast(); - } - - OverlayEntry _createPopupDialog(liveItem) { - return OverlayEntry( - builder: (context) => AnimatedDialog( - closeFn: _removePopupDialog, - videoItem: liveItem, - ), - ); - } - - Widget contentGrid(LoadingState loadingState) { - return SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.cardSpace, - crossAxisSpacing: StyleString.cardSpace, - maxCrossAxisExtent: Grid.maxRowWidth, - childAspectRatio: StyleString.aspectRatio, - mainAxisExtent: MediaQuery.textScalerOf(context).scale(80), - ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return loadingState is Success - ? LiveCardV( - liveItem: loadingState.response[index], - longPress: () { - _liveController.popupDialog - .add(_createPopupDialog(loadingState.response[index])); - Overlay.of(context) - .insert(_liveController.popupDialog.last!); - }, - longPressEnd: _removePopupDialog, - ) - : const VideoCardVSkeleton(); - }, - childCount: loadingState is Success ? loadingState.response.length : 10, - ), - ); - } -} diff --git a/lib/pages/live/widgets/live_item.dart b/lib/pages/live/widgets/live_item.dart index 9ad23895..03ae3c85 100644 --- a/lib/pages/live/widgets/live_item.dart +++ b/lib/pages/live/widgets/live_item.dart @@ -24,61 +24,54 @@ class LiveCardV extends StatelessWidget { return Card( clipBehavior: Clip.hardEdge, margin: EdgeInsets.zero, - child: GestureDetector( + child: InkWell( + onTap: () async { + Get.toNamed('/liveRoom?roomid=${liveItem.roomId}', + arguments: {'liveItem': liveItem, 'heroTag': heroTag}); + }, onLongPress: () { if (longPress != null) { longPress!(); } }, - // onLongPressEnd: (details) { - // if (longPressEnd != null) { - // longPressEnd!(); - // } - // }, - child: InkWell( - onTap: () async { - Get.toNamed('/liveRoom?roomid=${liveItem.roomId}', - arguments: {'liveItem': liveItem, 'heroTag': heroTag}); - }, - child: Column( - children: [ - ClipRRect( - borderRadius: const BorderRadius.all(StyleString.imgRadius), - child: AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder(builder: (context, boxConstraints) { - double maxWidth = boxConstraints.maxWidth; - double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: liveItem.cover!, - width: maxWidth, - height: maxHeight, + child: Column( + children: [ + ClipRRect( + borderRadius: const BorderRadius.all(StyleString.imgRadius), + child: AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder(builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: liveItem.cover!, + width: maxWidth, + height: maxHeight, + ), + ), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: AnimatedOpacity( + opacity: 1, + duration: const Duration(milliseconds: 200), + child: VideoStat( + liveItem: liveItem, ), ), - Positioned( - left: 0, - right: 0, - bottom: 0, - child: AnimatedOpacity( - opacity: 1, - duration: const Duration(milliseconds: 200), - child: VideoStat( - liveItem: liveItem, - ), - ), - ), - ], - ); - }), - ), + ), + ], + ); + }), ), - LiveContent(liveItem: liveItem) - ], - ), + ), + LiveContent(liveItem: liveItem) + ], ), ), ); diff --git a/lib/pages/rank/zone/controller.dart b/lib/pages/rank/zone/controller.dart index 559a2a57..19489f5e 100644 --- a/lib/pages/rank/zone/controller.dart +++ b/lib/pages/rank/zone/controller.dart @@ -1,11 +1,9 @@ import 'package:PiliPalaX/http/loading_state.dart'; -import 'package:PiliPalaX/pages/common/common_controller.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPalaX/pages/common/popup_controller.dart'; import 'package:PiliPalaX/http/video.dart'; -class ZoneController extends CommonController { +class ZoneController extends PopupController { ZoneController({required this.zoneID}); - List popupDialog = []; int zoneID; @override diff --git a/lib/pages/rcmd/controller.dart b/lib/pages/rcmd/controller.dart index 2eff050b..fc783d10 100644 --- a/lib/pages/rcmd/controller.dart +++ b/lib/pages/rcmd/controller.dart @@ -1,14 +1,12 @@ import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/models/home/rcmd/result.dart'; -import 'package:PiliPalaX/pages/common/common_controller.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:PiliPalaX/pages/common/popup_controller.dart'; import 'package:PiliPalaX/http/video.dart'; import 'package:PiliPalaX/utils/storage.dart'; -class RcmdController extends CommonController { +class RcmdController extends PopupController { late bool enableSaveLastData; late String defaultRcmdType = 'web'; - List popupDialog = []; @override void onInit() { diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index 66c252a1..040c85c1 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -1,6 +1,10 @@ import 'dart:async'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/models/common/tab_type.dart'; +import 'package:PiliPalaX/pages/common/popup_controller.dart'; +import 'package:PiliPalaX/pages/live/controller.dart'; +import 'package:PiliPalaX/pages/live/widgets/live_item.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -17,7 +21,9 @@ import '../../utils/grid.dart'; import 'controller.dart'; class RcmdPage extends StatefulWidget { - const RcmdPage({super.key}); + const RcmdPage({super.key, required this.tabType}); + + final TabType tabType; @override State createState() => _RcmdPageState(); @@ -25,7 +31,10 @@ class RcmdPage extends StatefulWidget { class _RcmdPageState extends State with AutomaticKeepAliveClientMixin { - final RcmdController _rcmdController = Get.put(RcmdController()); + late final PopupController _controller = Get.put( + widget.tabType == TabType.rcmd ? RcmdController() : LiveController(), + tag: widget.tabType.name, + ); @override bool get wantKeepAlive => true; @@ -37,17 +46,17 @@ class _RcmdPageState extends State Get.find().bottomBarStream; StreamController searchBarStream = Get.find().searchBarStream; - _rcmdController.scrollController.addListener( + _controller.scrollController.addListener( () { - if (_rcmdController.scrollController.position.pixels >= - _rcmdController.scrollController.position.maxScrollExtent - 200) { + if (_controller.scrollController.position.pixels >= + _controller.scrollController.position.maxScrollExtent - 200) { EasyThrottle.throttle( 'my-throttler', const Duration(milliseconds: 200), () { - _rcmdController.onLoadMore(); + _controller.onLoadMore(); }); } final ScrollDirection direction = - _rcmdController.scrollController.position.userScrollDirection; + _controller.scrollController.position.userScrollDirection; if (direction == ScrollDirection.forward) { mainStream.add(true); searchBarStream.add(true); @@ -61,7 +70,7 @@ class _RcmdPageState extends State @override void dispose() { - _rcmdController.scrollController.removeListener(() {}); + _controller.scrollController.removeListener(() {}); super.dispose(); } @@ -77,27 +86,26 @@ class _RcmdPageState extends State ), child: RefreshIndicator( onRefresh: () async { - await _rcmdController.onRefresh(); + await _controller.onRefresh(); }, child: CustomScrollView( - controller: _rcmdController.scrollController, + controller: _controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ SliverPadding( padding: const EdgeInsets.only(top: StyleString.cardSpace), sliver: Obx( - () => _rcmdController.loadingState.value is Loading || - _rcmdController.loadingState.value is Success - ? contentGrid(_rcmdController.loadingState.value) + () => _controller.loadingState.value is Loading || + _controller.loadingState.value is Success + ? contentGrid(_controller.loadingState.value) : HttpError( - errMsg: _rcmdController.loadingState.value is Error - ? (_rcmdController.loadingState.value as Error) - .errMsg + errMsg: _controller.loadingState.value is Error + ? (_controller.loadingState.value as Error).errMsg : '没有相关数据', fn: () { - _rcmdController.loadingState.value = + _controller.loadingState.value = LoadingState.loading(); - _rcmdController.onRefresh(); + _controller.onRefresh(); }), ), ), @@ -108,8 +116,8 @@ class _RcmdPageState extends State } void _removePopupDialog() { - _rcmdController.popupDialog.last?.remove(); - _rcmdController.popupDialog.removeLast(); + _controller.popupDialog.last?.remove(); + _controller.popupDialog.removeLast(); } OverlayEntry _createPopupDialog(videoItem) { @@ -136,16 +144,27 @@ class _RcmdPageState extends State delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return loadingState is Success - ? VideoCardV( - videoItem: loadingState.response[index], - longPress: () { - _rcmdController.popupDialog - .add(_createPopupDialog(loadingState.response[index])); - Overlay.of(context) - .insert(_rcmdController.popupDialog.last!); - }, - longPressEnd: _removePopupDialog, - ) + ? widget.tabType == TabType.rcmd + ? VideoCardV( + videoItem: loadingState.response[index], + longPress: () { + _controller.popupDialog.add( + _createPopupDialog(loadingState.response[index])); + Overlay.of(context) + .insert(_controller.popupDialog.last!); + }, + longPressEnd: _removePopupDialog, + ) + : LiveCardV( + liveItem: loadingState.response[index], + longPress: () { + _controller.popupDialog.add( + _createPopupDialog(loadingState.response[index])); + Overlay.of(context) + .insert(_controller.popupDialog.last!); + }, + longPressEnd: _removePopupDialog, + ) : const VideoCardVSkeleton(); }, childCount: loadingState is Success ? loadingState.response.length : 10,