diff --git a/lib/http/video.dart b/lib/http/video.dart index a3a3ce2e..9af4ec08 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -275,7 +275,7 @@ class VideoHttp { } // 相关视频 - static Future relatedVideoList({required String bvid}) async { + static Future relatedVideoList({required String bvid}) async { var res = await Request().get(Api.relatedList, data: {'bvid': bvid}); if (res.data['code'] == 0) { List list = []; @@ -285,9 +285,13 @@ class VideoHttp { list.add(videoItem); } } - return {'status': true, 'data': list}; + if (list.isNotEmpty) { + return LoadingState.success(list); + } else { + return LoadingState.empty(); + } } else { - return {'status': false, 'data': [], 'msg': res.data['message']}; + return LoadingState.error(res.data['message']); } } diff --git a/lib/pages/common/popup_controller.dart b/lib/pages/common/popup_controller.dart index 60b51b2e..1aa75cda 100644 --- a/lib/pages/common/popup_controller.dart +++ b/lib/pages/common/popup_controller.dart @@ -3,4 +3,9 @@ import 'package:flutter/material.dart'; abstract class PopupController extends CommonController { List popupDialog = []; + + void removePopupDialog() { + popupDialog.last?.remove(); + popupDialog.removeLast(); + } } diff --git a/lib/pages/hot/view.dart b/lib/pages/hot/view.dart index e42dcefc..6502980f 100644 --- a/lib/pages/hot/view.dart +++ b/lib/pages/hot/view.dart @@ -102,15 +102,10 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { ); } - void _removePopupDialog() { - _hotController.popupDialog.last?.remove(); - _hotController.popupDialog.removeLast(); - } - OverlayEntry _createPopupDialog(videoItem) { return OverlayEntry( builder: (context) => AnimatedDialog( - closeFn: _removePopupDialog, + closeFn: _hotController.removePopupDialog, videoItem: videoItem, ), ); @@ -152,7 +147,7 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { .add(_createPopupDialog(loadingState.response[index])); Overlay.of(context).insert(_hotController.popupDialog.last!); }, - longPressEnd: _removePopupDialog, + longPressEnd: _hotController.removePopupDialog, ); }, childCount: loadingState.response.length, diff --git a/lib/pages/rank/zone/view.dart b/lib/pages/rank/zone/view.dart index 30b0b1f6..0a644cd9 100644 --- a/lib/pages/rank/zone/view.dart +++ b/lib/pages/rank/zone/view.dart @@ -102,15 +102,10 @@ class _ZonePageState extends State ); } - void _removePopupDialog() { - _zoneController.popupDialog.last?.remove(); - _zoneController.popupDialog.removeLast(); - } - OverlayEntry _createPopupDialog(videoItem) { return OverlayEntry( builder: (context) => AnimatedDialog( - closeFn: _removePopupDialog, + closeFn: _zoneController.removePopupDialog, videoItem: videoItem, ), ); @@ -153,7 +148,7 @@ class _ZonePageState extends State .add(_createPopupDialog(loadingState.response[index])); Overlay.of(context).insert(_zoneController.popupDialog.last!); }, - longPressEnd: _removePopupDialog, + longPressEnd: _zoneController.removePopupDialog, ); }, childCount: loadingState.response.length, diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index a3db704c..ffa71c57 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -114,15 +114,10 @@ class _RcmdPageState extends State ); } - void _removePopupDialog() { - _controller.popupDialog.last?.remove(); - _controller.popupDialog.removeLast(); - } - OverlayEntry _createPopupDialog(videoItem) { return OverlayEntry( builder: (context) => AnimatedDialog( - closeFn: _removePopupDialog, + closeFn: _controller.removePopupDialog, videoItem: videoItem, ), ); @@ -152,7 +147,7 @@ class _RcmdPageState extends State Overlay.of(context) .insert(_controller.popupDialog.last!); }, - longPressEnd: _removePopupDialog, + longPressEnd: _controller.removePopupDialog, ) : LiveCardV( liveItem: loadingState.response[index], @@ -162,7 +157,7 @@ class _RcmdPageState extends State Overlay.of(context) .insert(_controller.popupDialog.last!); }, - longPressEnd: _removePopupDialog, + longPressEnd: _controller.removePopupDialog, ) : const VideoCardVSkeleton(); }, diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 3afcc39e..c29993be 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:PiliPalaX/http/loading_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -480,7 +481,7 @@ class VideoIntroController extends GetxController { final RelatedController relatedCtr = Get.find(tag: heroTag); relatedCtr.bvid = bvid; - relatedCtr.queryRelatedVideo(); + relatedCtr.queryData(); } catch (_) {} // 重新请求评论 try { @@ -614,13 +615,13 @@ class VideoIntroController extends GetxController { late RelatedController relatedCtr; try { relatedCtr = Get.find(tag: heroTag); - if (relatedCtr.relatedVideoList.isEmpty) { + if (relatedCtr.loadingState.value is Empty) { SmartDialog.showToast('暂无相关视频,停止连播'); return false; } } catch (_) { relatedCtr = Get.put(RelatedController(), tag: heroTag); - relatedCtr.queryRelatedVideo().then((value) { + relatedCtr.queryData().then((value) { if (value['status']) { playRelated(); } @@ -628,7 +629,8 @@ class VideoIntroController extends GetxController { return false; } - final HotVideoItemModel videoItem = relatedCtr.relatedVideoList[0]; + final HotVideoItemModel videoItem = + (relatedCtr.loadingState.value as Success).response[0]; try { if (videoItem.cid != null) { Get.offNamed('/video?bvid=${videoItem.bvid}&cid=${videoItem.cid}', diff --git a/lib/pages/video/detail/related/controller.dart b/lib/pages/video/detail/related/controller.dart index 3487fc6e..0e8dde0c 100644 --- a/lib/pages/video/detail/related/controller.dart +++ b/lib/pages/video/detail/related/controller.dart @@ -1,25 +1,19 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/common/popup_controller.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/http/video.dart'; -import '../../../../models/model_hot_video_item.dart'; -class RelatedController extends GetxController { +class RelatedController extends PopupController { // 视频aid String bvid = Get.parameters['bvid'] ?? ""; - // 推荐视频列表 - RxList relatedVideoList = [].obs; - List popupDialog = []; - - Future queryRelatedVideo() async { - return VideoHttp.relatedVideoList(bvid: bvid).then((value) { - if (value['status']) { - relatedVideoList.value = value['data']; - } else { - SmartDialog.showToast(value['msg']); - } - return value; - }); + @override + void onInit() { + super.onInit(); + queryData(); } + + @override + Future customGetData() => + VideoHttp.relatedVideoList(bvid: bvid); } diff --git a/lib/pages/video/detail/related/view.dart b/lib/pages/video/detail/related/view.dart index 9208ae78..2b444751 100644 --- a/lib/pages/video/detail/related/view.dart +++ b/lib/pages/video/detail/related/view.dart @@ -1,3 +1,4 @@ +import 'package:PiliPalaX/http/loading_state.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/common/skeleton/video_card_h.dart'; @@ -17,107 +18,80 @@ class RelatedVideoPanel extends StatefulWidget { class _RelatedVideoPanelState extends State with AutomaticKeepAliveClientMixin { - late RelatedController _relatedController; - late Future _futureBuilder; + late final RelatedController _relatedController = + Get.put(RelatedController(), tag: widget.heroTag); @override bool get wantKeepAlive => true; - @override - void initState() { - super.initState(); - _relatedController = Get.put(RelatedController(), tag: widget.heroTag); - _futureBuilder = _relatedController.queryRelatedVideo(); - } - @override Widget build(BuildContext context) { super.build(context); return SliverPadding( - padding: const EdgeInsets.all(StyleString.safeSpace), - sliver: FutureBuilder( - future: _futureBuilder, - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.data == null) { - return const SliverToBoxAdapter(child: SizedBox()); - } - if (snapshot.data!['status'] && snapshot.hasData) { - RxList relatedVideoList = _relatedController.relatedVideoList; - // 请求成功 - return Obx( - () => SliverGrid( - gridDelegate: SliverGridDelegateWithExtentAndRatio( - mainAxisSpacing: StyleString.safeSpace, - crossAxisSpacing: StyleString.safeSpace, - maxCrossAxisExtent: Grid.maxRowWidth * 2, - childAspectRatio: StyleString.aspectRatio * 2.4, - mainAxisExtent: 0), - delegate: SliverChildBuilderDelegate((context, index) { - if (index == relatedVideoList.length) { - return SizedBox( - height: MediaQuery.of(context).padding.bottom); - } else { - return Material( - child: VideoCardH( - videoItem: relatedVideoList[index], - showPubdate: true, - longPress: () { - try { - _relatedController.popupDialog.add( - _createPopupDialog(_relatedController - .relatedVideoList[index])); - Overlay.of(context).insert( - _relatedController.popupDialog.last!); - } catch (err) { - return {}; - } - }, - longPressEnd: _removePopupDialog, - ), - ); - } - }, childCount: relatedVideoList.length + 1), + padding: const EdgeInsets.all(StyleString.safeSpace), + sliver: Obx(() => _buildBody(_relatedController.loadingState.value)), + ); + } + + OverlayEntry _createPopupDialog(videoItem) { + return OverlayEntry( + builder: (BuildContext context) => AnimatedDialog( + closeFn: _relatedController.removePopupDialog, + videoItem: videoItem, + ), + ); + } + + Widget _buildBody(LoadingState loadingState) { + return loadingState is Success + ? SliverGrid( + gridDelegate: SliverGridDelegateWithExtentAndRatio( + mainAxisSpacing: StyleString.safeSpace, + crossAxisSpacing: StyleString.safeSpace, + maxCrossAxisExtent: Grid.maxRowWidth * 2, + childAspectRatio: StyleString.aspectRatio * 2.4, + mainAxisExtent: 0), + delegate: SliverChildBuilderDelegate((context, index) { + if (index == loadingState.response.length) { + return SizedBox(height: MediaQuery.of(context).padding.bottom); + } else { + return Material( + child: VideoCardH( + videoItem: loadingState.response[index], + showPubdate: true, + longPress: () { + _relatedController.popupDialog.add( + _createPopupDialog(loadingState.response[index])); + Overlay.of(context) + .insert(_relatedController.popupDialog.last!); + }, + longPressEnd: _relatedController.removePopupDialog, ), ); - } else { - // 请求错误 - return HttpError( - errMsg: '出错了', - fn: () { - _futureBuilder = _relatedController.queryRelatedVideo(); - _futureBuilder.then((value) => setState(() {})); - }); } - } else { - // 骨架屏 - return SliverGrid( + }, childCount: loadingState.response.length + 1), + ) + : loadingState is Error + ? HttpError( + errMsg: '出错了', + fn: () { + _relatedController.loadingState.value = + LoadingState.loading(); + _relatedController.queryData(); + }) + : SliverGrid( gridDelegate: SliverGridDelegateWithExtentAndRatio( mainAxisSpacing: StyleString.safeSpace, crossAxisSpacing: StyleString.safeSpace, maxCrossAxisExtent: Grid.maxRowWidth * 2, childAspectRatio: StyleString.aspectRatio * 2.4, mainAxisExtent: 0), - delegate: SliverChildBuilderDelegate((context, index) { - return const VideoCardHSkeleton(); - }, childCount: 5), + delegate: SliverChildBuilderDelegate( + (context, index) { + return const VideoCardHSkeleton(); + }, + childCount: 5, + ), ); - } - }, - )); - } - - void _removePopupDialog() { - _relatedController.popupDialog.last?.remove(); - _relatedController.popupDialog.removeLast(); - } - - OverlayEntry _createPopupDialog(videoItem) { - return OverlayEntry( - builder: (BuildContext context) => AnimatedDialog( - closeFn: _removePopupDialog, - videoItem: videoItem, - ), - ); } }