From c42ce2f1f96c797237b4fca38690d5fae2053810 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 21 Apr 2024 17:38:07 +0800 Subject: [PATCH 01/23] =?UTF-8?q?mod:=20=E7=95=AA=E5=89=A7=E4=BC=A0?= =?UTF-8?q?=E9=80=92aid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/bangumi/introduction/controller.dart | 1 + lib/pages/bangumi/widgets/bangumi_panel.dart | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 2098302d..b26028cf 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -236,6 +236,7 @@ class BangumiIntroController extends GetxController { videoDetailCtr.bvid = bvid; videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; + videoDetailCtr.oid.value = aid; videoDetailCtr.queryVideoUrl(); // 重新请求评论 try { diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index b01f3be7..3e965f34 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -85,7 +85,9 @@ class _BangumiPanelState extends State { item.cid, item.aid, ); - _bottomSheetController?.close(); + if (_bottomSheetController != null) { + _bottomSheetController?.close(); + } currentIndex = i; scrollToIndex(); } From 926c99001ebd47b860073029419f3d93338ab346 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 22 Apr 2024 23:58:36 +0800 Subject: [PATCH 02/23] =?UTF-8?q?mod:=20=E8=A7=86=E9=A2=91=E7=AE=80?= =?UTF-8?q?=E4=BB=8B=E5=A2=9E=E5=8A=A0aid=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../introduction/widgets/intro_detail.dart | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/pages/video/detail/introduction/widgets/intro_detail.dart b/lib/pages/video/detail/introduction/widgets/intro_detail.dart index 1e9bb842..3ec92023 100644 --- a/lib/pages/video/detail/introduction/widgets/intro_detail.dart +++ b/lib/pages/video/detail/introduction/widgets/intro_detail.dart @@ -23,16 +23,34 @@ class IntroDetail extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); - SmartDialog.showToast('已复制'); - }, - child: Text( - videoDetail!.bvid!, - style: TextStyle( - fontSize: 13, color: Theme.of(context).colorScheme.primary), - ), + Row( + children: [ + GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); + SmartDialog.showToast('已复制'); + }, + child: Text( + videoDetail!.bvid!, + style: TextStyle( + fontSize: 13, + color: Theme.of(context).colorScheme.primary), + ), + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); + SmartDialog.showToast('已复制'); + }, + child: Text( + videoDetail!.aid!.toString(), + style: TextStyle( + fontSize: 13, + color: Theme.of(context).colorScheme.primary), + ), + ) + ], ), const SizedBox(height: 4), Text.rich( From 31125435b11501e4236456e31541ab48aa996118 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 23 Apr 2024 23:40:40 +0800 Subject: [PATCH 03/23] =?UTF-8?q?opt:=20=E9=A6=96=E9=A1=B5=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E6=A0=8F=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/overlay_pop.dart | 1 + lib/common/widgets/video_card_v.dart | 283 +++++++++++---------------- lib/pages/home/view.dart | 87 ++++---- lib/pages/rcmd/view.dart | 20 -- 4 files changed, 160 insertions(+), 231 deletions(-) diff --git a/lib/common/widgets/overlay_pop.dart b/lib/common/widgets/overlay_pop.dart index fe9b9377..4f0a3899 100644 --- a/lib/common/widgets/overlay_pop.dart +++ b/lib/common/widgets/overlay_pop.dart @@ -62,6 +62,7 @@ class OverlayPop extends StatelessWidget { Expanded( child: Text( videoItem.title! as String, + style: Theme.of(context).textTheme.titleSmall, ), ), const SizedBox(width: 4), diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 0d96f7b7..0598f973 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import '../../models/model_rec_video_item.dart'; +import 'overlay_pop.dart'; import 'stat/danmu.dart'; import 'stat/view.dart'; import '../../http/dynamics.dart'; @@ -19,15 +20,15 @@ import 'network_img_layer.dart'; class VideoCardV extends StatelessWidget { final dynamic videoItem; final int crossAxisCount; - final Function()? longPress; - final Function()? longPressEnd; + // final Function()? longPress; + // final Function()? longPressEnd; const VideoCardV({ Key? key, required this.videoItem, required this.crossAxisCount, - this.longPress, - this.longPressEnd, + // this.longPress, + // this.longPressEnd, }) : super(key: key); bool isStringNumeric(String str) { @@ -131,59 +132,55 @@ class VideoCardV extends StatelessWidget { elevation: 0, clipBehavior: Clip.hardEdge, margin: EdgeInsets.zero, - child: GestureDetector( + child: InkWell( + onTap: () async => onPushDetail(heroTag), onLongPress: () { - if (longPress != null) { - longPress!(); - } + SmartDialog.show( + builder: (context) => OverlayPop( + videoItem: videoItem, + closeFn: () => SmartDialog.dismiss(), + ), + ); }, - // onLongPressEnd: (details) { - // if (longPressEnd != null) { - // longPressEnd!(); - // } - // }, - child: InkWell( - onTap: () async => onPushDetail(heroTag), - child: Column( - children: [ - 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: videoItem.pic, - width: maxWidth, - height: maxHeight, - ), + child: Column( + children: [ + 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: videoItem.pic, + width: maxWidth, + height: maxHeight, ), - if (videoItem.duration > 0) - if (crossAxisCount == 1) ...[ - PBadge( - bottom: 10, - right: 10, - text: Utils.timeFormat(videoItem.duration), - ) - ] else ...[ - PBadge( - bottom: 6, - right: 7, - size: 'small', - type: 'gray', - text: Utils.timeFormat(videoItem.duration), - ) - ], - ], - ); - }), - ), - VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) - ], - ), + ), + if (videoItem.duration > 0) + if (crossAxisCount == 1) ...[ + PBadge( + bottom: 10, + right: 10, + text: Utils.timeFormat(videoItem.duration), + ) + ] else ...[ + PBadge( + bottom: 6, + right: 7, + size: 'small', + type: 'gray', + text: Utils.timeFormat(videoItem.duration), + ) + ], + ], + ); + }), + ), + VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) + ], ), ), ); @@ -196,122 +193,73 @@ class VideoContent extends StatelessWidget { const VideoContent( {Key? key, required this.videoItem, required this.crossAxisCount}) : super(key: key); + + Widget _buildBadge(String text, String type, [double fs = 12]) { + return PBadge( + text: text, + stack: 'normal', + size: 'small', + type: type, + fs: fs, + ); + } + @override Widget build(BuildContext context) { - return Expanded( - flex: crossAxisCount == 1 ? 0 : 1, - child: Padding( - padding: crossAxisCount == 1 - ? const EdgeInsets.fromLTRB(9, 9, 9, 4) - : const EdgeInsets.fromLTRB(5, 8, 5, 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Expanded( - child: Text( - videoItem.title, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - if (videoItem.goto == 'av' && crossAxisCount == 1) ...[ - const SizedBox(width: 10), - VideoPopupMenu( - size: 32, - iconSize: 18, - videoItem: videoItem, - ), - ], - ], - ), - if (crossAxisCount > 1) ...[ - const SizedBox(height: 2), - VideoStat( - videoItem: videoItem, - crossAxisCount: crossAxisCount, - ), - ], - if (crossAxisCount == 1) const SizedBox(height: 4), - Row( - children: [ - if (videoItem.goto == 'bangumi') ...[ - PBadge( - text: videoItem.bangumiBadge, - stack: 'normal', - size: 'small', - type: 'line', - fs: 9, - ) - ], - if (videoItem.rcmdReason != null && - videoItem.rcmdReason.content != '') ...[ - PBadge( - text: videoItem.rcmdReason.content, - stack: 'normal', - size: 'small', - type: 'color', - ) - ], - if (videoItem.goto == 'picture') ...[ - const PBadge( - text: '动态', - stack: 'normal', - size: 'small', - type: 'line', - fs: 9, - ) - ], - if (videoItem.isFollowed == 1) ...[ - const PBadge( - text: '已关注', - stack: 'normal', - size: 'small', - type: 'color', - ) - ], - Expanded( - flex: crossAxisCount == 1 ? 0 : 1, - child: Text( - videoItem.owner.name, - maxLines: 1, - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - ), - if (crossAxisCount == 1) ...[ - Text( - ' • ', - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - VideoStat( - videoItem: videoItem, - crossAxisCount: crossAxisCount, - ), - const Spacer(), - ], - if (videoItem.goto == 'av' && crossAxisCount != 1) ...[ - VideoPopupMenu( - size: 24, - iconSize: 14, - videoItem: videoItem, - ), - ] else ...[ - const SizedBox(height: 24) - ] - ], - ), + return Padding( + padding: crossAxisCount == 1 + ? const EdgeInsets.fromLTRB(9, 9, 9, 4) + : const EdgeInsets.fromLTRB(5, 8, 5, 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + videoItem.title, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + if (crossAxisCount > 1) ...[ + const SizedBox(height: 2), + VideoStat(videoItem: videoItem, crossAxisCount: crossAxisCount), ], - ), + if (crossAxisCount == 1) const SizedBox(height: 4), + Row( + children: [ + if (videoItem.goto == 'bangumi') + _buildBadge(videoItem.bangumiBadge, 'line', 9), + if (videoItem.rcmdReason?.content != null && + videoItem.rcmdReason.content != '') + _buildBadge(videoItem.rcmdReason.content, 'color'), + if (videoItem.goto == 'picture') _buildBadge('动态', 'line', 9), + if (videoItem.isFollowed == 1) _buildBadge('已关注', 'color'), + Expanded( + flex: crossAxisCount == 1 ? 0 : 1, + child: Text( + videoItem.owner.name, + maxLines: 1, + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: Theme.of(context).colorScheme.outline, + ), + ), + ), + if (crossAxisCount == 1) ...[ + const SizedBox(width: 10), + VideoStat( + videoItem: videoItem, + crossAxisCount: crossAxisCount, + ), + const Spacer(), + ], + if (videoItem.goto == 'av') + VideoPopupMenu( + size: 24, + iconSize: 14, + videoItem: videoItem, + ), + ], + ), + ], ), ); } @@ -383,7 +331,6 @@ class VideoPopupMenu extends StatelessWidget { size: iconSize, ), position: PopupMenuPosition.under, - // constraints: const BoxConstraints(maxHeight: 35), onSelected: (String type) {}, itemBuilder: (BuildContext context) => >[ PopupMenuItem( diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index cc228f6b..a25389bd 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -214,6 +214,34 @@ class UserInfoWidget extends StatelessWidget { final VoidCallback? callback; final HomeController? ctr; + Widget buildLoggedInWidget(context) { + return Stack( + children: [ + NetworkImgLayer( + type: 'avatar', + width: 34, + height: 34, + src: userFace, + ), + Positioned.fill( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => callback?.call(), + splashColor: Theme.of(context) + .colorScheme + .primaryContainer + .withOpacity(0.3), + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + ), + ), + ) + ], + ); + } + @override Widget build(BuildContext context) { return Row( @@ -231,31 +259,7 @@ class UserInfoWidget extends StatelessWidget { const SizedBox(width: 8), Obx( () => userLogin.value - ? Stack( - children: [ - NetworkImgLayer( - type: 'avatar', - width: 34, - height: 34, - src: userFace, - ), - Positioned.fill( - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => callback?.call(), - splashColor: Theme.of(context) - .colorScheme - .primaryContainer - .withOpacity(0.3), - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - ), - ), - ) - ], - ) + ? buildLoggedInWidget(context) : DefaultUser(callback: () => callback!()), ), ], @@ -402,30 +406,27 @@ class SearchBar extends StatelessWidget { color: colorScheme.onSecondaryContainer.withOpacity(0.05), child: InkWell( splashColor: colorScheme.primaryContainer.withOpacity(0.3), - onTap: () => Get.toNamed( - '/search', - parameters: {'hintText': ctr!.defaultSearch.value}, - ), - child: Row( - children: [ - const SizedBox(width: 14), - Icon( - Icons.search_outlined, - color: colorScheme.onSecondaryContainer, - ), - const SizedBox(width: 10), - Obx( - () => Expanded( - child: Text( + onTap: () => Get.toNamed('/search', + parameters: {'hintText': ctr!.defaultSearch.value}), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: Row( + children: [ + Icon( + Icons.search_outlined, + color: colorScheme.onSecondaryContainer, + ), + const SizedBox(width: 10), + Obx( + () => Text( ctr!.defaultSearch.value, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: colorScheme.outline), ), ), - ), - const SizedBox(width: 15), - ], + ], + ), ), ), ), diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index acc1e654..67567870 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -5,9 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/skeleton/video_card_v.dart'; -import 'package:pilipala/common/widgets/animated_dialog.dart'; import 'package:pilipala/common/widgets/http_error.dart'; -import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/common/widgets/video_card_v.dart'; import 'package:pilipala/utils/main_stream.dart'; @@ -118,16 +116,6 @@ class _RcmdPageState extends State ); } - OverlayEntry _createPopupDialog(videoItem) { - return OverlayEntry( - builder: (context) => AnimatedDialog( - closeFn: _rcmdController.popupDialog?.remove, - child: OverlayPop( - videoItem: videoItem, closeFn: _rcmdController.popupDialog?.remove), - ), - ); - } - Widget contentGrid(ctr, videoList) { // double maxWidth = Get.size.width; // int baseWidth = 500; @@ -158,14 +146,6 @@ class _RcmdPageState extends State ? VideoCardV( videoItem: videoList[index], crossAxisCount: crossAxisCount, - longPress: () { - _rcmdController.popupDialog = - _createPopupDialog(videoList[index]); - Overlay.of(context).insert(_rcmdController.popupDialog!); - }, - longPressEnd: () { - _rcmdController.popupDialog?.remove(); - }, ) : const VideoCardVSkeleton(); }, From ab45d2e6a68a5000c82e038a3f1308ab88b4be0d Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 24 Apr 2024 23:56:07 +0800 Subject: [PATCH 04/23] =?UTF-8?q?opt:=20=E9=A6=96=E9=A1=B5=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E5=8D=A1=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_v.dart | 310 ++++++++++++++------------- 1 file changed, 157 insertions(+), 153 deletions(-) diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 0598f973..9916aa7a 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/utils/feed_back.dart'; import '../../models/model_rec_video_item.dart'; import 'overlay_pop.dart'; import 'stat/danmu.dart'; @@ -20,15 +21,11 @@ import 'network_img_layer.dart'; class VideoCardV extends StatelessWidget { final dynamic videoItem; final int crossAxisCount; - // final Function()? longPress; - // final Function()? longPressEnd; const VideoCardV({ Key? key, required this.videoItem, required this.crossAxisCount, - // this.longPress, - // this.longPressEnd, }) : super(key: key); bool isStringNumeric(String str) { @@ -128,60 +125,56 @@ class VideoCardV extends StatelessWidget { @override Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(videoItem.id); - return Card( - elevation: 0, - clipBehavior: Clip.hardEdge, - margin: EdgeInsets.zero, - child: InkWell( - onTap: () async => onPushDetail(heroTag), - onLongPress: () { - SmartDialog.show( - builder: (context) => OverlayPop( - videoItem: videoItem, - closeFn: () => SmartDialog.dismiss(), - ), - ); - }, - child: Column( - children: [ - 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: videoItem.pic, - width: maxWidth, - height: maxHeight, - ), + return InkWell( + onTap: () async => onPushDetail(heroTag), + onLongPress: () { + SmartDialog.show( + builder: (context) => OverlayPop( + videoItem: videoItem, + closeFn: () => SmartDialog.dismiss(), + ), + ); + }, + borderRadius: BorderRadius.circular(16), + child: Column( + children: [ + 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: videoItem.pic, + width: maxWidth, + height: maxHeight, ), - if (videoItem.duration > 0) - if (crossAxisCount == 1) ...[ - PBadge( - bottom: 10, - right: 10, - text: Utils.timeFormat(videoItem.duration), - ) - ] else ...[ - PBadge( - bottom: 6, - right: 7, - size: 'small', - type: 'gray', - text: Utils.timeFormat(videoItem.duration), - ) - ], - ], - ); - }), - ), - VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) - ], - ), + ), + if (videoItem.duration > 0) + if (crossAxisCount == 1) ...[ + PBadge( + bottom: 10, + right: 10, + text: Utils.timeFormat(videoItem.duration), + ) + ] else ...[ + PBadge( + bottom: 6, + right: 7, + size: 'small', + type: 'gray', + text: Utils.timeFormat(videoItem.duration), + ) + ], + ], + ); + }), + ), + VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) + ], ), ); } @@ -252,11 +245,28 @@ class VideoContent extends StatelessWidget { const Spacer(), ], if (videoItem.goto == 'av') - VideoPopupMenu( - size: 24, - iconSize: 14, - videoItem: videoItem, - ), + SizedBox( + width: 24, + height: 24, + child: IconButton( + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) { + return MorePanel(videoItem: videoItem); + }, + ); + }, + icon: Icon( + Icons.more_vert_outlined, + color: Theme.of(context).colorScheme.outline, + size: 14, + ), + ), + ) ], ), ], @@ -279,15 +289,9 @@ class VideoStat extends StatelessWidget { Widget build(BuildContext context) { return Row( children: [ - StatView( - theme: 'gray', - view: videoItem.stat.view, - ), + StatView(theme: 'gray', view: videoItem.stat.view), const SizedBox(width: 8), - StatDanMu( - theme: 'gray', - danmu: videoItem.stat.danmu, - ), + StatDanMu(theme: 'gray', danmu: videoItem.stat.danmu), if (videoItem is RecVideoItemModel) ...[ crossAxisCount > 1 ? const Spacer() : const SizedBox(width: 8), RichText( @@ -306,98 +310,98 @@ class VideoStat extends StatelessWidget { } } -class VideoPopupMenu extends StatelessWidget { - final double? size; - final double? iconSize; +class MorePanel extends StatelessWidget { final dynamic videoItem; + const MorePanel({super.key, required this.videoItem}); - const VideoPopupMenu({ - Key? key, - required this.size, - required this.iconSize, - required this.videoItem, - }) : super(key: key); + Future menuActionHandler(String type) async { + switch (type) { + case 'block': + blockUser(); + break; + case 'watchLater': + var res = await UserHttp.toViewLater(bvid: videoItem.bvid as String); + SmartDialog.showToast(res['msg']); + Get.back(); + break; + default: + } + } + + void blockUser() async { + SmartDialog.show( + useSystem: true, + animationType: SmartAnimationType.centerFade_otherSlide, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('提示'), + content: Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' + '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'), + actions: [ + TextButton( + onPressed: () => SmartDialog.dismiss(), + child: Text( + '点错了', + style: TextStyle(color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () async { + var res = await VideoHttp.relationMod( + mid: videoItem.owner.mid, + act: 5, + reSrc: 11, + ); + SmartDialog.dismiss(); + SmartDialog.showToast(res['msg'] ?? '成功'); + }, + child: const Text('确认'), + ) + ], + ); + }, + ); + } @override Widget build(BuildContext context) { - return SizedBox( - width: size, - height: size, - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: Icon( - Icons.more_vert_outlined, - color: Theme.of(context).colorScheme.outline, - size: iconSize, - ), - position: PopupMenuPosition.under, - onSelected: (String type) {}, - itemBuilder: (BuildContext context) => >[ - PopupMenuItem( - onTap: () async { - var res = - await UserHttp.toViewLater(bvid: videoItem.bvid as String); - SmartDialog.showToast(res['msg']); - }, - value: 'pause', - height: 40, - child: const Row( - children: [ - Icon(Icons.watch_later_outlined, size: 16), - SizedBox(width: 6), - Text('稍后再看', style: TextStyle(fontSize: 13)) - ], + return Container( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + onTap: () => Get.back(), + child: Container( + height: 35, + padding: const EdgeInsets.only(bottom: 2), + child: Center( + child: Container( + width: 32, + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.outline, + borderRadius: const BorderRadius.all(Radius.circular(3))), + ), + ), ), ), - const PopupMenuDivider(), - PopupMenuItem( - onTap: () async { - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: Text( - '确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' - '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'), - actions: [ - TextButton( - onPressed: () => SmartDialog.dismiss(), - child: Text( - '点错了', - style: TextStyle( - color: Theme.of(context).colorScheme.outline), - ), - ), - TextButton( - onPressed: () async { - var res = await VideoHttp.relationMod( - mid: videoItem.owner.mid, - act: 5, - reSrc: 11, - ); - SmartDialog.dismiss(); - SmartDialog.showToast(res['msg'] ?? '成功'); - }, - child: const Text('确认'), - ) - ], - ); - }, - ); - }, - value: 'pause', - height: 40, - child: Row( - children: [ - const Icon(Icons.block, size: 16), - const SizedBox(width: 6), - Text('拉黑:${videoItem.owner.name}', - style: const TextStyle(fontSize: 13)) - ], + ListTile( + onTap: () async => await menuActionHandler('block'), + minLeadingWidth: 0, + leading: const Icon(Icons.block, size: 19), + title: Text( + '拉黑up主 「${videoItem.owner.name}」', + style: Theme.of(context).textTheme.titleSmall, ), ), + ListTile( + onTap: () async => await menuActionHandler('watchLater'), + minLeadingWidth: 0, + leading: const Icon(Icons.watch_later_outlined, size: 19), + title: + Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall), + ), ], ), ); From 1f426881f2c4ae43f5f58695ff342d175460f2a8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 25 Apr 2024 22:42:42 +0800 Subject: [PATCH 05/23] =?UTF-8?q?mod:=20=E4=BD=BF=E7=94=A8feed=5Fversion?= =?UTF-8?q?=20V3=E6=8E=A8=E8=8D=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/video.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http/video.dart b/lib/http/video.dart index d43656b2..f8e19060 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -35,7 +35,7 @@ class VideoHttp { Api.recommendListWeb, data: { 'version': 1, - 'feed_version': 'V8', + 'feed_version': 'V3', 'homepage_ver': 1, 'ps': ps, 'fresh_idx': freshIdx, From c6f5bc561c5f4f5c275b569338132be9df41f6f8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 25 Apr 2024 23:18:21 +0800 Subject: [PATCH 06/23] =?UTF-8?q?feat:=20up=E6=8A=95=E7=A8=BF=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E5=85=85=E7=94=B5=E4=B8=93=E5=B1=9E=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_h.dart | 9 +++++++++ lib/pages/member_archive/view.dart | 1 + 2 files changed, 10 insertions(+) diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index 99059a9e..25e701ac 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -23,6 +23,7 @@ class VideoCardH extends StatelessWidget { this.showView = true, this.showDanmaku = true, this.showPubdate = false, + this.showCharge = false, }); // ignore: prefer_typing_uninitialized_variables final videoItem; @@ -33,6 +34,7 @@ class VideoCardH extends StatelessWidget { final bool showView; final bool showDanmaku; final bool showPubdate; + final bool showCharge; @override Widget build(BuildContext context) { @@ -121,6 +123,13 @@ class VideoCardH extends StatelessWidget { // videoItem.rcmdReason.content != '') // pBadge(videoItem.rcmdReason.content, context, // 6.0, 6.0, null, null), + if (showCharge && videoItem?.isChargingSrc) + const PBadge( + text: '充电专属', + right: 6.0, + top: 6.0, + type: 'primary', + ), ], ); }, diff --git a/lib/pages/member_archive/view.dart b/lib/pages/member_archive/view.dart index 3103683a..f38ca0cb 100644 --- a/lib/pages/member_archive/view.dart +++ b/lib/pages/member_archive/view.dart @@ -79,6 +79,7 @@ class _MemberArchivePageState extends State { videoItem: list[index], showOwner: false, showPubdate: true, + showCharge: true, ); }, childCount: list.length, From 4e66a3f9e7ab379a5501f40ea5fabd983e0a8480 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 26 Apr 2024 23:22:26 +0800 Subject: [PATCH 07/23] =?UTF-8?q?opt:=20=E8=AF=84=E8=AE=BA=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=98=E5=85=88=E5=B1=95=E7=A4=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/dynamics/detail/view.dart | 6 +- lib/pages/video/detail/controller.dart | 5 +- lib/pages/video/detail/reply/view.dart | 9 +- .../detail/reply/widgets/reply_item.dart | 133 +++++++++--------- .../video/detail/reply_reply/controller.dart | 10 +- lib/pages/video/detail/reply_reply/view.dart | 14 +- 6 files changed, 99 insertions(+), 78 deletions(-) diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index c6ec682a..757ba0ce 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -106,7 +106,7 @@ class _DynamicDetailPageState extends State } // 查看二级评论 - void replyReply(replyItem) { + void replyReply(replyItem, currentReply) { int oid = replyItem.oid; int rpid = replyItem.rpid!; Get.to( @@ -324,8 +324,8 @@ class _DynamicDetailPageState extends State replyItem: replyList[index], showReplyRow: true, replyLevel: '1', - replyReply: (replyItem) => - replyReply(replyItem), + replyReply: (replyItem, currentReply) => + replyReply(replyItem, currentReply), replyType: ReplyType.values[replyType], addReply: (replyItem) { replyList[index] diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4d40e535..4613c7ca 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -161,11 +161,11 @@ class VideoDetailController extends GetxController getSubtitle(); } - showReplyReplyPanel() { + showReplyReplyPanel(oid, fRpid, firstFloor, currentReply) { replyReplyBottomSheetCtr = scaffoldKey.currentState?.showBottomSheet((BuildContext context) { return VideoReplyReplyPanel( - oid: oid.value, + oid: oid, rpid: fRpid, closePanel: () => { fRpid = 0, @@ -174,6 +174,7 @@ class VideoDetailController extends GetxController replyType: ReplyType.video, source: 'videoDetail', sheetHeight: sheetHeight.value, + currentReply: currentReply, ); }); replyReplyBottomSheetCtr?.closed.then((value) { diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 2a167fe9..3b4891b8 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -110,14 +110,15 @@ class _VideoReplyPanelState extends State } // 展示二级回复 - void replyReply(replyItem) { + void replyReply(replyItem, currentReply) { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); if (replyItem != null) { videoDetailCtr.oid.value = replyItem.oid; videoDetailCtr.fRpid = replyItem.rpid!; videoDetailCtr.firstFloor = replyItem; - videoDetailCtr.showReplyReplyPanel(); + videoDetailCtr.showReplyReplyPanel( + replyItem.oid, replyItem.rpid!, replyItem, currentReply); } } @@ -228,8 +229,8 @@ class _VideoReplyPanelState extends State .replyList[index], showReplyRow: true, replyLevel: replyLevel, - replyReply: (replyItem) => - replyReply(replyItem), + replyReply: (replyItem, currentReply) => + replyReply(replyItem, currentReply), replyType: ReplyType.video, ); } diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 50fe20d4..8a8e4af7 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -12,7 +12,6 @@ import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/reply_new/index.dart'; import 'package:pilipala/utils/feed_back.dart'; -import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/url_utils.dart'; import 'package:pilipala/utils/utils.dart'; @@ -45,7 +44,7 @@ class ReplyItem extends StatelessWidget { onTap: () { feedBack(); if (replyReply != null) { - replyReply!(replyItem); + replyReply!(replyItem, null); } }, onLongPress: () { @@ -59,28 +58,23 @@ class ReplyItem extends StatelessWidget { }, ); }, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), - child: content(context), - ), - Divider( - indent: 55, - endIndent: 15, - height: 0.3, - color: Theme.of(context) - .colorScheme - .onInverseSurface - .withOpacity(0.5), - ) - ], + child: Container( + padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: + Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.5), + ))), + child: content(context), ), ), ); } Widget lfAvtar(BuildContext context, String heroTag) { + ColorScheme colorScheme = Theme.of(context).colorScheme; return Stack( children: [ Hero( @@ -100,11 +94,11 @@ class ReplyItem extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), - color: Theme.of(context).colorScheme.background, + color: colorScheme.background, ), child: Icon( Icons.offline_bolt, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, size: 16, ), ), @@ -117,7 +111,7 @@ class ReplyItem extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), - color: Theme.of(context).colorScheme.background, + color: colorScheme.background, ), child: Image.asset( 'assets/images/big-vip.png', @@ -131,6 +125,8 @@ class ReplyItem extends StatelessWidget { Widget content(BuildContext context) { final String heroTag = Utils.makeHeroTag(replyItem!.mid); + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -160,16 +156,17 @@ class ReplyItem extends StatelessWidget { style: TextStyle( color: replyItem!.member!.vip!['vipStatus'] > 0 ? const Color.fromARGB(255, 251, 100, 163) - : Theme.of(context).colorScheme.outline, + : colorScheme.outline, fontSize: 13, ), ), - const SizedBox(width: 6), - Image.asset( - 'assets/images/lv/lv${replyItem!.member!.level}.png', - height: 11, + Padding( + padding: const EdgeInsets.only(left: 6, right: 6), + child: Image.asset( + 'assets/images/lv/lv${replyItem!.member!.level}.png', + height: 11, + ), ), - const SizedBox(width: 6), if (replyItem!.isUp!) const PBadge( text: 'UP', @@ -184,9 +181,8 @@ class ReplyItem extends StatelessWidget { Text( Utils.dateFormat(replyItem!.ctime), style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: textTheme.labelSmall!.fontSize, + color: colorScheme.outline, ), ), if (replyItem!.replyControl != null && @@ -194,11 +190,8 @@ class ReplyItem extends StatelessWidget { Text( ' • ${replyItem!.replyControl!.location!}', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline), + fontSize: textTheme.labelSmall!.fontSize, + color: colorScheme.outline), ), ], ) @@ -256,6 +249,8 @@ class ReplyItem extends StatelessWidget { // 感谢、回复、复制 Widget bottonAction(BuildContext context, replyControl) { + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; return Row( children: [ const SizedBox(width: 32), @@ -287,15 +282,13 @@ class ReplyItem extends StatelessWidget { }, child: Row(children: [ Icon(Icons.reply, - size: 18, - color: - Theme.of(context).colorScheme.outline.withOpacity(0.8)), + size: 18, color: colorScheme.outline.withOpacity(0.8)), const SizedBox(width: 3), Text( '回复', style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: textTheme.labelMedium!.fontSize, + color: colorScheme.outline, ), ), ]), @@ -306,8 +299,8 @@ class ReplyItem extends StatelessWidget { Text( 'up主觉得很赞', style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + color: colorScheme.primary, + fontSize: textTheme.labelMedium!.fontSize), ), const SizedBox(width: 2), ], @@ -316,8 +309,8 @@ class ReplyItem extends StatelessWidget { Text( '热评', style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + color: colorScheme.primary, + fontSize: textTheme.labelMedium!.fontSize), ), const Spacer(), ZanButton(replyItem: replyItem, replyType: replyType), @@ -347,10 +340,13 @@ class ReplyItemRow extends StatelessWidget { Widget build(BuildContext context) { final bool isShow = replyControl!.isShow!; final int extraRow = replyControl != null && isShow ? 1 : 0; + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; + return Container( margin: const EdgeInsets.only(left: 42, right: 4, top: 0), child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, + color: colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), clipBehavior: Clip.hardEdge, animationDuration: Duration.zero, @@ -361,7 +357,9 @@ class ReplyItemRow extends StatelessWidget { for (int i = 0; i < replies!.length; i++) ...[ InkWell( // 一楼点击评论展开评论详情 - onTap: () => replyReply!(replyItem), + // onTap: () { + // replyReply?.call(replyItem, replies![i]); + // }, onLongPress: () { feedBack(); showModalBottomSheet( @@ -379,7 +377,7 @@ class ReplyItemRow extends StatelessWidget { 8, i == 0 && (extraRow == 1 || replies!.length > 1) ? 8 : 5, 8, - i == 0 && (extraRow == 1 || replies!.length > 1) ? 5 : 6, + 6, ), child: Text.rich( overflow: TextOverflow.ellipsis, @@ -393,7 +391,7 @@ class ReplyItemRow extends StatelessWidget { .textTheme .titleSmall! .fontSize, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -429,15 +427,14 @@ class ReplyItemRow extends StatelessWidget { if (extraRow == 1) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply!(replyItem), + onTap: () => replyReply!(replyItem, null), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), child: Text.rich( TextSpan( style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, + fontSize: textTheme.labelMedium!.fontSize, ), children: [ if (replyControl!.upReply!) @@ -445,7 +442,7 @@ class ReplyItemRow extends StatelessWidget { TextSpan( text: replyControl!.entryText!, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), ) ], @@ -464,6 +461,7 @@ InlineSpan buildContent( BuildContext context, replyItem, replyReply, fReplyItem) { final String routePath = Get.currentRoute; bool isVideoPage = routePath.startsWith('/video'); + ColorScheme colorScheme = Theme.of(context).colorScheme; // replyItem 当前回复内容 // replyReply 查看二楼回复(回复详情)回调 @@ -533,8 +531,10 @@ InlineSpan buildContent( TextSpan( text: str, recognizer: TapGestureRecognizer() - ..onTap = () => - replyReply?.call(replyItem.root == 0 ? replyItem : fReplyItem), + ..onTap = () => replyReply?.call( + replyItem.root == 0 ? replyItem : fReplyItem, + replyItem, + ), ), ); } @@ -564,7 +564,7 @@ InlineSpan buildContent( TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -584,7 +584,7 @@ InlineSpan buildContent( text: ' $matchStr ', style: isVideoPage ? TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ) : null, recognizer: TapGestureRecognizer() @@ -624,14 +624,14 @@ InlineSpan buildContent( child: Image.network( content.jumpUrl[matchStr]['prefix_icon'], height: 19, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), ) ], TextSpan( text: content.jumpUrl[matchStr]['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () async { @@ -721,7 +721,7 @@ InlineSpan buildContent( TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -747,7 +747,7 @@ InlineSpan buildContent( text: ' $matchStr ', style: isVideoPage ? TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ) : null, recognizer: TapGestureRecognizer() @@ -786,14 +786,14 @@ InlineSpan buildContent( child: Image.network( content.jumpUrl[patternStr]['prefix_icon'], height: 19, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), ) ], TextSpan( text: content.jumpUrl[patternStr]['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -997,7 +997,8 @@ class MorePanel extends StatelessWidget { @override Widget build(BuildContext context) { - Color errorColor = Theme.of(context).colorScheme.error; + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; return Container( padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), child: Column( @@ -1013,7 +1014,7 @@ class MorePanel extends StatelessWidget { width: 32, height: 3, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.outline, + color: colorScheme.outline, borderRadius: const BorderRadius.all(Radius.circular(3))), ), ), @@ -1023,13 +1024,13 @@ class MorePanel extends StatelessWidget { onTap: () async => await menuActionHandler('copyAll'), minLeadingWidth: 0, leading: const Icon(Icons.copy_all_outlined, size: 19), - title: Text('复制全部', style: Theme.of(context).textTheme.titleSmall), + title: Text('复制全部', style: textTheme.titleSmall), ), ListTile( onTap: () async => await menuActionHandler('copyFreedom'), minLeadingWidth: 0, leading: const Icon(Icons.copy_outlined, size: 19), - title: Text('自由复制', style: Theme.of(context).textTheme.titleSmall), + title: Text('自由复制', style: textTheme.titleSmall), ), // ListTile( // onTap: () async => await menuActionHandler('block'), diff --git a/lib/pages/video/detail/reply_reply/controller.dart b/lib/pages/video/detail/reply_reply/controller.dart index e94aaea5..4c553e29 100644 --- a/lib/pages/video/detail/reply_reply/controller.dart +++ b/lib/pages/video/detail/reply_reply/controller.dart @@ -26,7 +26,7 @@ class VideoReplyReplyController extends GetxController { currentPage = 0; } - Future queryReplyList({type = 'init'}) async { + Future queryReplyList({type = 'init', currentReply}) async { if (type == 'init') { currentPage = 0; } @@ -63,6 +63,14 @@ class VideoReplyReplyController extends GetxController { // res['data'].replies.addAll(replyList); } } + if (replyList.isNotEmpty && currentReply != null) { + int indexToRemove = + replyList.indexWhere((item) => currentReply.rpid == item.rpid); + // 如果找到了指定ID的项,则移除 + if (indexToRemove != -1) { + replyList.removeAt(indexToRemove); + } + } isLoadingMore = false; return res; } diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index 3fe84c71..6441c600 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -20,6 +20,7 @@ class VideoReplyReplyPanel extends StatefulWidget { this.source, this.replyType, this.sheetHeight, + this.currentReply, super.key, }); final int? oid; @@ -29,6 +30,7 @@ class VideoReplyReplyPanel extends StatefulWidget { final String? source; final ReplyType? replyType; final double? sheetHeight; + final dynamic currentReply; @override State createState() => _VideoReplyReplyPanelState(); @@ -63,7 +65,9 @@ class _VideoReplyReplyPanelState extends State { }, ); - _futureBuilderFuture = _videoReplyReplyController.queryReplyList(); + _futureBuilderFuture = _videoReplyReplyController.queryReplyList( + currentReply: widget.currentReply, + ); } void replyReply(replyItem) {} @@ -107,7 +111,9 @@ class _VideoReplyReplyPanelState extends State { onRefresh: () async { setState(() {}); _videoReplyReplyController.currentPage = 0; - return await _videoReplyReplyController.queryReplyList(); + return await _videoReplyReplyController.queryReplyList( + currentReply: widget.currentReply, + ); }, child: CustomScrollView( controller: _videoReplyReplyController.scrollController, @@ -140,6 +146,10 @@ class _VideoReplyReplyPanelState extends State { if (snapshot.connectionState == ConnectionState.done) { Map? data = snapshot.data; if (data != null && data['status']) { + if (widget.currentReply != null) { + _videoReplyReplyController.replyList + .insert(0, widget.currentReply); + } // 请求成功 return Obx( () => SliverList( From 8273ff2e02f3900425465485c31d99ef3e5b5b15 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 26 Apr 2024 23:46:54 +0800 Subject: [PATCH 08/23] =?UTF-8?q?opt:=20=E8=AF=84=E8=AE=BA=E6=A1=86?= =?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/http/reply.dart | 11 +--- lib/pages/dynamics/detail/controller.dart | 2 + lib/pages/dynamics/detail/view.dart | 63 +++++++++++--------- lib/pages/video/detail/reply/controller.dart | 2 + lib/pages/video/detail/reply/view.dart | 59 ++++++++++-------- lib/pages/video/detail/reply_new/view.dart | 22 ++++--- 6 files changed, 88 insertions(+), 71 deletions(-) diff --git a/lib/http/reply.dart b/lib/http/reply.dart index f080ed51..880f9072 100644 --- a/lib/http/reply.dart +++ b/lib/http/reply.dart @@ -22,19 +22,14 @@ class ReplyHttp { return { 'status': true, 'data': ReplyData.fromJson(res.data['data']), + 'code': 200, }; } else { - Map errMap = { - -400: '请求错误', - -404: '无此项', - 12002: '当前页面评论功能已关闭', - 12009: '评论主体的type不合法', - 12061: 'UP主已关闭评论区', - }; return { 'status': false, 'date': [], - 'msg': errMap[res.data['code']] ?? res.data['message'], + 'code': res.data['code'], + 'msg': res.data['message'], }; } } diff --git a/lib/pages/dynamics/detail/controller.dart b/lib/pages/dynamics/detail/controller.dart index 8e117383..f34de061 100644 --- a/lib/pages/dynamics/detail/controller.dart +++ b/lib/pages/dynamics/detail/controller.dart @@ -25,6 +25,7 @@ class DynamicDetailController extends GetxController { RxString sortTypeTitle = ReplySortType.time.titles.obs; RxString sortTypeLabel = ReplySortType.time.labels.obs; Box setting = GStrorage.setting; + RxInt replyReqCode = 200.obs; @override void onInit() { @@ -84,6 +85,7 @@ class DynamicDetailController extends GetxController { replyList.addAll(replies); } } + replyReqCode.value = res['code']; isLoadingMore = false; return res; } diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index 757ba0ce..11636b5b 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -369,35 +369,40 @@ class _DynamicDetailPageState extends State curve: Curves.easeInOut, ), ), - child: FloatingActionButton( - heroTag: null, - onPressed: () { - feedBack(); - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (BuildContext context) { - return VideoReplyNewDialog( - oid: _dynamicDetailController.oid ?? - IdUtils.bv2av(Get.parameters['bvid']!), - root: 0, - parent: 0, - replyType: ReplyType.values[replyType], - ); - }, - ).then( - (value) => { - // 完成评论,数据添加 - if (value != null && value['data'] != null) - { - _dynamicDetailController.replyList.add(value['data']), - _dynamicDetailController.acount.value++ - } - }, - ); - }, - tooltip: '评论动态', - child: const Icon(Icons.reply), + child: Obx( + () => _dynamicDetailController.replyReqCode.value == 12061 + ? const SizedBox() + : FloatingActionButton( + heroTag: null, + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (BuildContext context) { + return VideoReplyNewDialog( + oid: _dynamicDetailController.oid ?? + IdUtils.bv2av(Get.parameters['bvid']!), + root: 0, + parent: 0, + replyType: ReplyType.values[replyType], + ); + }, + ).then( + (value) => { + // 完成评论,数据添加 + if (value != null && value['data'] != null) + { + _dynamicDetailController.replyList + .add(value['data']), + _dynamicDetailController.acount.value++ + } + }, + ); + }, + tooltip: '评论动态', + child: const Icon(Icons.reply), + ), ), ), ); diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index 06ce26ff..b718c840 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -37,6 +37,7 @@ class VideoReplyController extends GetxController { RxString sortTypeLabel = ReplySortType.time.labels.obs; Box setting = GStrorage.setting; + RxInt replyReqCode = 200.obs; @override void onInit() { @@ -106,6 +107,7 @@ class VideoReplyController extends GetxController { replyList.addAll(replies); } } + replyReqCode.value = res['code']; isLoadingMore = false; return res; } diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 3b4891b8..420f349c 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -277,32 +277,39 @@ class _VideoReplyPanelState extends State parent: fabAnimationCtr, curve: Curves.easeInOut, )), - child: FloatingActionButton( - heroTag: null, - onPressed: () { - feedBack(); - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (BuildContext context) { - return VideoReplyNewDialog( - oid: _videoReplyController.aid ?? - IdUtils.bv2av(Get.parameters['bvid']!), - root: 0, - parent: 0, - replyType: ReplyType.video, - ); - }, - ).then( - (value) => { - // 完成评论,数据添加 - if (value != null && value['data'] != null) - {_videoReplyController.replyList.add(value['data'])} - }, - ); - }, - tooltip: '发表评论', - child: const Icon(Icons.reply), + child: Obx( + () => _videoReplyController.replyReqCode.value == 12061 + ? const SizedBox() + : FloatingActionButton( + heroTag: null, + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (BuildContext context) { + return VideoReplyNewDialog( + oid: _videoReplyController.aid ?? + IdUtils.bv2av(Get.parameters['bvid']!), + root: 0, + parent: 0, + replyType: ReplyType.video, + ); + }, + ).then( + (value) => { + // 完成评论,数据添加 + if (value != null && value['data'] != null) + { + _videoReplyController.replyList + .add(value['data']) + } + }, + ); + }, + tooltip: '发表评论', + child: const Icon(Icons.reply), + ), ), ), ), diff --git a/lib/pages/video/detail/reply_new/view.dart b/lib/pages/video/detail/reply_new/view.dart index 029e015a..3da15f64 100644 --- a/lib/pages/video/detail/reply_new/view.dart +++ b/lib/pages/video/detail/reply_new/view.dart @@ -43,6 +43,7 @@ class _VideoReplyNewDialogState extends State String toolbarType = 'input'; RxBool isForward = false.obs; RxBool showForward = false.obs; + RxString message = ''.obs; @override void initState() { @@ -80,15 +81,15 @@ class _VideoReplyNewDialogState extends State Future submitReplyAdd() async { feedBack(); - String message = _replyContentController.text; + // String message = _replyContentController.text; var result = await VideoHttp.replyAdd( type: widget.replyType ?? ReplyType.video, oid: widget.oid!, root: widget.root!, parent: widget.parent!, message: widget.replyItem != null && widget.replyItem!.root != 0 - ? ' 回复 @${widget.replyItem!.member!.uname!} : $message' - : message, + ? ' 回复 @${widget.replyItem!.member!.uname!} : ${message.value}' + : message.value, ); if (result['status']) { SmartDialog.showToast(result['data']['success_toast']); @@ -100,7 +101,7 @@ class _VideoReplyNewDialogState extends State if (isForward.value) { await DynamicsHttp.dynamicCreate( mid: 0, - rawText: message, + rawText: message.value, oid: widget.oid!, scene: 5, ); @@ -188,7 +189,7 @@ class _VideoReplyNewDialogState extends State autovalidateMode: AutovalidateMode.onUserInteraction, child: TextField( controller: _replyContentController, - minLines: 1, + minLines: 3, maxLines: null, autofocus: false, focusNode: replyContentFocusNode, @@ -199,6 +200,9 @@ class _VideoReplyNewDialogState extends State fontSize: 14, )), style: Theme.of(context).textTheme.bodyLarge, + onChanged: (text) { + message.value = text; + }, ), ), ), @@ -267,9 +271,11 @@ class _VideoReplyNewDialogState extends State const Spacer(), SizedBox( height: 36, - child: FilledButton( - onPressed: () => submitReplyAdd(), - child: const Text('发送'), + child: Obx( + () => FilledButton( + onPressed: message.isNotEmpty ? submitReplyAdd : null, + child: const Text('发送'), + ), ), ), ], From b752214af3c09f885e312bf23ed99567e07c4a68 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 01:04:11 +0800 Subject: [PATCH 09/23] =?UTF-8?q?fix:=20durl=E6=A0=BC=E5=BC=8F=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/video/play/quality.dart | 8 ++ lib/pages/video/detail/controller.dart | 84 ++++++++++++------- .../video/detail/widgets/header_control.dart | 43 ++++++---- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/lib/models/video/play/quality.dart b/lib/models/video/play/quality.dart index 6cae84cc..7bedf62a 100644 --- a/lib/models/video/play/quality.dart +++ b/lib/models/video/play/quality.dart @@ -39,6 +39,14 @@ extension VideoQualityCode on VideoQuality { } return null; } + + static int? toCode(VideoQuality quality) { + final index = VideoQuality.values.indexOf(quality); + if (index != -1 && index < _codeList.length) { + return _codeList[index]; + } + return null; + } } extension VideoQualityDesc on VideoQuality { diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4d40e535..3cc43005 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -51,7 +51,7 @@ class VideoDetailController extends GetxController /// 播放器配置 画质 音质 解码格式 late VideoQuality currentVideoQa; AudioQuality? currentAudioQa; - late VideoDecodeFormats currentDecodeFormats; + VideoDecodeFormats? currentDecodeFormats; // 是否开始自动播放 存在多p的情况下,第二p需要为true RxBool autoPlay = true.obs; // 视频资源是否有效 @@ -107,6 +107,7 @@ class VideoDetailController extends GetxController BottomControlType.fullscreen, ].obs; RxDouble sheetHeight = 0.0.obs; + RxString archiveSourceType = 'dash'.obs; @override void onInit() { @@ -189,37 +190,43 @@ class VideoDetailController extends GetxController plPlayerController.isBuffering.value = false; plPlayerController.buffered.value = Duration.zero; - /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl - List videoList = - data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); - try { - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); - } catch (_) { - if (currentVideoQa == VideoQuality.dolbyVision) { - firstVideo = videoList.first; - currentDecodeFormats = - VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!; - } else { - // 当前格式不可用 - currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( - SettingBoxKey.defaultDecode, - defaultValue: VideoDecodeFormats.values.last.code))!; - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); + if (archiveSourceType.value == 'dash') { + /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl + List videoList = + data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); + try { + firstVideo = videoList.firstWhere( + (i) => i.codecs!.startsWith(currentDecodeFormats?.code)); + } catch (_) { + if (currentVideoQa == VideoQuality.dolbyVision) { + firstVideo = videoList.first; + currentDecodeFormats = + VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!; + } else { + // 当前格式不可用 + currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( + SettingBoxKey.defaultDecode, + defaultValue: VideoDecodeFormats.values.last.code))!; + firstVideo = videoList.firstWhere( + (i) => i.codecs!.startsWith(currentDecodeFormats?.code)); + } + } + videoUrl = firstVideo.baseUrl!; + + /// 根据currentAudioQa 重新设置audioUrl + if (currentAudioQa != null) { + final AudioItem firstAudio = data.dash!.audio!.firstWhere( + (AudioItem i) => i.id == currentAudioQa!.code, + orElse: () => data.dash!.audio!.first, + ); + audioUrl = firstAudio.baseUrl ?? ''; } } - videoUrl = firstVideo.baseUrl!; - /// 根据currentAudioQa 重新设置audioUrl - if (currentAudioQa != null) { - final AudioItem firstAudio = data.dash!.audio!.firstWhere( - (AudioItem i) => i.id == currentAudioQa!.code, - orElse: () => data.dash!.audio!.first, - ); - audioUrl = firstAudio.baseUrl ?? ''; + if (archiveSourceType.value == 'durl') { + cacheVideoQa = VideoQualityCode.toCode(currentVideoQa); + queryVideoUrl(); } - playerInit(); } @@ -272,7 +279,8 @@ class VideoDetailController extends GetxController // 视频链接 Future queryVideoUrl() async { - var result = await VideoHttp.videoUrl(cid: cid.value, bvid: bvid); + var result = + await VideoHttp.videoUrl(cid: cid.value, bvid: bvid, qn: cacheVideoQa); if (result['status']) { data = result['data']; if (data.acceptDesc!.isNotEmpty && data.acceptDesc!.contains('试看')) { @@ -290,8 +298,22 @@ class VideoDetailController extends GetxController } return result; } + if (data.durl != null) { + archiveSourceType.value = 'durl'; + videoUrl = data.durl!.first.url!; + audioUrl = ''; + defaultST = Duration.zero; + firstVideo = VideoItem(); + currentVideoQa = VideoQualityCode.fromCode(data.quality!)!; + if (autoPlay.value) { + await playerInit(); + isShowCover.value = false; + } + return result; + } final List allVideosList = data.dash!.video!; try { + archiveSourceType.value = 'dash'; // 当前可播放的最高质量视频 int currentHighVideoQa = allVideosList.first.quality!.code; // 预设的画质为null,则当前可用的最高质量 @@ -321,7 +343,7 @@ class VideoDetailController extends GetxController // 当前视频没有对应格式返回第一个 bool flag = false; for (var i in supportDecodeFormats) { - if (i.startsWith(currentDecodeFormats.code)) { + if (i.startsWith(currentDecodeFormats?.code)) { flag = true; } } @@ -335,7 +357,7 @@ class VideoDetailController extends GetxController /// 取出符合当前解码格式的videoItem try { firstVideo = videosList.firstWhere( - (e) => e.codecs!.startsWith(currentDecodeFormats.code)); + (e) => e.codecs!.startsWith(currentDecodeFormats?.code)); } catch (_) { firstVideo = videosList.first; } diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index e00311c5..6acd20d7 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -180,15 +180,16 @@ class _HeaderControlState extends State { '当前音质 ${widget.videoDetailCtr!.currentAudioQa!.description}', style: subTitleStyle), ), - ListTile( - onTap: () => {Get.back(), showSetDecodeFormats()}, - dense: true, - leading: const Icon(Icons.av_timer_outlined, size: 20), - title: const Text('解码格式', style: titleStyle), - subtitle: Text( - '当前解码格式 ${widget.videoDetailCtr!.currentDecodeFormats.description}', - style: subTitleStyle), - ), + if (widget.videoDetailCtr!.currentDecodeFormats != null) + ListTile( + onTap: () => {Get.back(), showSetDecodeFormats()}, + dense: true, + leading: const Icon(Icons.av_timer_outlined, size: 20), + title: const Text('解码格式', style: titleStyle), + subtitle: Text( + '当前解码格式 ${widget.videoDetailCtr!.currentDecodeFormats!.description}', + style: subTitleStyle), + ), ListTile( onTap: () => {Get.back(), showSetRepeat()}, dense: true, @@ -541,16 +542,24 @@ class _HeaderControlState extends State { /// 可用的质量分类 int userfulQaSam = 0; - final List video = videoInfo.dash!.video!; - final Set idSet = {}; - for (final VideoItem item in video) { - final int id = item.id!; - if (!idSet.contains(id)) { - idSet.add(id); - userfulQaSam++; + if (videoInfo.dash != null) { + // dash格式视频一次请求会返回所有可播放的清晰度video + final List video = videoInfo.dash!.video!; + final Set idSet = {}; + for (final VideoItem item in video) { + final int id = item.id!; + if (!idSet.contains(id)) { + idSet.add(id); + userfulQaSam++; + } } } + if (videoInfo.durl != null) { + // durl格式视频一次请求返回对应清晰度video + userfulQaSam = videoFormat.length - 1; + } + showModalBottomSheet( context: context, elevation: 0, @@ -707,7 +716,7 @@ class _HeaderControlState extends State { void showSetDecodeFormats() { // 当前选中的解码格式 final VideoDecodeFormats currentDecodeFormats = - widget.videoDetailCtr!.currentDecodeFormats; + widget.videoDetailCtr!.currentDecodeFormats!; final VideoItem firstVideo = widget.videoDetailCtr!.firstVideo; // 当前视频可用的解码格式 final List videoFormat = videoInfo.supportFormats!; From 0312c8d01d6d8623de6f23c3fc9af8b58f2a81e3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 12:35:43 +0800 Subject: [PATCH 10/23] =?UTF-8?q?feat:=20=E6=98=BE=E7=A4=BA=E8=81=94?= =?UTF-8?q?=E5=90=88=E6=8A=95=E7=A8=BFup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/video.dart | 15 +-- lib/models/video_detail_res.dart | 45 +++++++ lib/pages/video/detail/introduction/view.dart | 111 +++++++++++++----- .../introduction/widgets/staff_up_item.dart | 74 ++++++++++++ 4 files changed, 206 insertions(+), 39 deletions(-) create mode 100644 lib/pages/video/detail/introduction/widgets/staff_up_item.dart diff --git a/lib/http/video.dart b/lib/http/video.dart index d43656b2..bdfaedf7 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -192,22 +192,15 @@ class VideoHttp { // 视频信息 标题、简介 static Future videoIntro({required String bvid}) async { var res = await Request().get(Api.videoIntro, data: {'bvid': bvid}); - VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); - if (result.code == 0) { + if (res.data['code'] == 0) { + VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); return {'status': true, 'data': result.data!}; } else { - Map errMap = { - -400: '请求错误', - -403: '权限不足', - -404: '视频资源失效', - 62002: '稿件不可见', - 62004: '稿件审核中', - }; return { 'status': false, 'data': null, - 'code': result.code, - 'msg': errMap[result.code] ?? '请求异常', + 'code': res.data['code'], + 'msg': res.data['message'], }; } } diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index 38e0b877..a82b6fbb 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -67,6 +67,7 @@ class VideoDetailData { String? likeIcon; bool? needJumpBv; String? epId; + List? staff; VideoDetailData({ this.bvid, @@ -103,6 +104,7 @@ class VideoDetailData { this.likeIcon, this.needJumpBv, this.epId, + this.staff, }); VideoDetailData.fromJson(Map json) { @@ -155,6 +157,9 @@ class VideoDetailData { if (json['redirect_url'] != null) { epId = resolveEpId(json['redirect_url']); } + staff = json["staff"] != null + ? List.from(json["staff"]!.map((e) => Staff.fromJson(e))) + : null; } String resolveEpId(url) { @@ -652,3 +657,43 @@ class EpisodeItem { bvid = json['bvid']; } } + +class Staff { + Staff({ + this.mid, + this.title, + this.name, + this.face, + this.vip, + }); + + int? mid; + String? title; + String? name; + String? face; + int? status; + Vip? vip; + + Staff.fromJson(Map json) { + mid = json['mid']; + title = json['title']; + name = json['name']; + face = json['face']; + vip = Vip.fromJson(json['vip']); + } +} + +class Vip { + Vip({ + this.type, + this.status, + }); + + int? type; + int? status; + + Vip.fromJson(Map json) { + type = json['type']; + status = json['status']; + } +} diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index a7eae6d2..597b6def 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -22,6 +22,7 @@ import 'widgets/fav_panel.dart'; import 'widgets/intro_detail.dart'; import 'widgets/page_panel.dart'; import 'widgets/season_panel.dart'; +import 'widgets/staff_up_item.dart'; class VideoIntroPanel extends StatefulWidget { final String bvid; @@ -409,32 +410,35 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ) ], - GestureDetector( - onTap: onPushMember, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 4), - child: Row( - children: [ - NetworkImgLayer( - type: 'avatar', - src: widget.videoDetail!.owner!.face, - width: 34, - height: 34, - fadeInDuration: Duration.zero, - fadeOutDuration: Duration.zero, - ), - const SizedBox(width: 10), - Text(owner.name, style: const TextStyle(fontSize: 13)), - const SizedBox(width: 6), - Text( - follower, - style: TextStyle( - fontSize: t.textTheme.labelSmall!.fontSize, - color: outline, + if (widget.videoDetail!.staff == null) + GestureDetector( + onTap: onPushMember, + child: Container( + padding: + const EdgeInsets.symmetric(vertical: 12, horizontal: 4), + child: Row( + children: [ + NetworkImgLayer( + type: 'avatar', + src: widget.videoDetail!.owner!.face, + width: 34, + height: 34, + fadeInDuration: Duration.zero, + fadeOutDuration: Duration.zero, ), - ), - const Spacer(), - Obx(() => AnimatedOpacity( + const SizedBox(width: 10), + Text(owner.name, style: const TextStyle(fontSize: 13)), + const SizedBox(width: 6), + Text( + follower, + style: TextStyle( + fontSize: t.textTheme.labelSmall!.fontSize, + color: outline, + ), + ), + const Spacer(), + Obx( + () => AnimatedOpacity( opacity: videoIntroController.followStatus.isEmpty ? 0 : 1, duration: const Duration(milliseconds: 50), @@ -474,11 +478,58 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ), ), - )), - ], + ), + ), + ], + ), ), ), - ), + if (widget.videoDetail!.staff != null) ...[ + const SizedBox(height: 15), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text.rich( + TextSpan( + style: TextStyle( + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + ), + children: [ + TextSpan( + text: '创作团队', + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(fontWeight: FontWeight.bold), + ), + const WidgetSpan(child: SizedBox(width: 6)), + TextSpan( + text: '${widget.videoDetail!.staff!.length}人', + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + ), + ) + ], + ), + ), + SizedBox( + height: 120, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + for (int i = 0; + i < widget.videoDetail!.staff!.length; + i++) ...[ + StaffUpItem(item: widget.videoDetail!.staff![i]) + ], + ], + ), + ), + ], + ), + ] ], )), ); @@ -545,4 +596,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ); }); } + + // Widget StaffPanel(BuildContext context, videoIntroController) { + // return + // } } diff --git a/lib/pages/video/detail/introduction/widgets/staff_up_item.dart b/lib/pages/video/detail/introduction/widgets/staff_up_item.dart new file mode 100644 index 00000000..7b18d95d --- /dev/null +++ b/lib/pages/video/detail/introduction/widgets/staff_up_item.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/models/video_detail_res.dart'; +import 'package:pilipala/utils/utils.dart'; + +class StaffUpItem extends StatelessWidget { + final Staff item; + + const StaffUpItem({ + super.key, + required this.item, + }); + + @override + Widget build(BuildContext context) { + final String heroTag = Utils.makeHeroTag(item.mid); + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 15), + GestureDetector( + onTap: () => Get.toNamed( + '/member?mid=${item.mid}', + arguments: {'face': item.face, 'heroTag': heroTag}, + ), + child: Hero( + tag: heroTag, + child: NetworkImgLayer( + width: 45, + height: 45, + src: item.face, + type: 'avatar', + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 4), + child: SizedBox( + width: 85, + child: Text( + item.name!, + overflow: TextOverflow.ellipsis, + softWrap: false, + textAlign: TextAlign.center, + style: TextStyle( + color: item.vip!.status == 1 + ? const Color.fromARGB(255, 251, 100, 163) + : null, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 4), + child: SizedBox( + width: 85, + child: Text( + item.title!, + overflow: TextOverflow.ellipsis, + softWrap: false, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + fontSize: 12, + ), + ), + ), + ), + ], + ); + } +} From 29bdbbfe18d86fe3c5ee1755bb25902247525b89 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 15:32:05 +0800 Subject: [PATCH 11/23] mod: playCount calc --- lib/plugin/pl_player/controller.dart | 12 +++++------- lib/services/audio_handler.dart | 2 +- lib/services/audio_session.dart | 4 ++-- lib/services/shutdown_timer_service.dart | 18 +++++++++++------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index be72eccb..ca147fd1 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -101,7 +101,7 @@ class PlPlayerController { bool _isFirstTime = true; Timer? _timer; - late Timer? _timerForSeek; + Timer? _timerForSeek; Timer? _timerForVolume; Timer? _timerForShowingVolume; Timer? _timerForGettingVolume; @@ -335,8 +335,10 @@ class PlPlayerController { }) { // 如果实例尚未创建,则创建一个新实例 _instance ??= PlPlayerController._(); - _instance!._playerCount.value += 1; - _videoType.value = videoType; + if (videoType != 'none') { + _instance!._playerCount.value += 1; + _videoType.value = videoType; + } return _instance!; } @@ -1120,9 +1122,6 @@ class PlPlayerController { } Future dispose({String type = 'single'}) async { - print('dispose'); - print('dispose: ${playerCount.value}'); - // 每次减1,最后销毁 if (type == 'single' && playerCount.value > 1) { _playerCount.value -= 1; @@ -1132,7 +1131,6 @@ class PlPlayerController { } _playerCount.value = 0; try { - print('dispose dispose ---------'); _timer?.cancel(); _timerForVolume?.cancel(); _timerForGettingVolume?.cancel(); diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index bf98298b..b0ca8cd7 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -26,7 +26,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { static final List _item = []; Box setting = GStrorage.setting; bool enableBackgroundPlay = false; - PlPlayerController player = PlPlayerController.getInstance(); + PlPlayerController player = PlPlayerController.getInstance(videoType: 'none'); VideoPlayerServiceHandler() { revalidateSetting(); diff --git a/lib/services/audio_session.dart b/lib/services/audio_session.dart index ea83a30a..53b497ae 100644 --- a/lib/services/audio_session.dart +++ b/lib/services/audio_session.dart @@ -18,7 +18,7 @@ class AudioSessionHandler { session.configure(const AudioSessionConfiguration.music()); session.interruptionEventStream.listen((event) { - final player = PlPlayerController.getInstance(); + final player = PlPlayerController.getInstance(videoType: 'none'); if (event.begin) { if (!player.playerStatus.playing) return; switch (event.type) { @@ -51,7 +51,7 @@ class AudioSessionHandler { // 耳机拔出暂停 session.becomingNoisyEventStream.listen((_) { - final player = PlPlayerController.getInstance(); + final player = PlPlayerController.getInstance(videoType: 'none'); if (player.playerStatus.playing) { player.pause(); } diff --git a/lib/services/shutdown_timer_service.dart b/lib/services/shutdown_timer_service.dart index aa9c5ceb..156b63c8 100644 --- a/lib/services/shutdown_timer_service.dart +++ b/lib/services/shutdown_timer_service.dart @@ -29,8 +29,8 @@ class ShutdownTimerService { return; } SmartDialog.showToast("设置 $scheduledExitInMinutes 分钟后定时关闭"); - _shutdownTimer = Timer(Duration(minutes: scheduledExitInMinutes), - () => _shutdownDecider()); + _shutdownTimer = Timer( + Duration(minutes: scheduledExitInMinutes), () => _shutdownDecider()); } void _showTimeUpButPauseDialog() { @@ -59,7 +59,7 @@ class ShutdownTimerService { // Start the 10-second timer to auto close the dialog _autoCloseDialogTimer?.cancel(); _autoCloseDialogTimer = Timer(const Duration(seconds: 10), () { - SmartDialog.dismiss();// Close the dialog + SmartDialog.dismiss(); // Close the dialog _executeShutdown(); }); return AlertDialog( @@ -88,7 +88,8 @@ class ShutdownTimerService { _showShutdownDialog(); return; } - PlPlayerController plPlayerController = PlPlayerController.getInstance(); + PlPlayerController plPlayerController = + PlPlayerController.getInstance(videoType: 'none'); if (!exitApp && !waitForPlayingCompleted) { if (!plPlayerController.playerStatus.playing) { //仅提示用户 @@ -108,19 +109,22 @@ class ShutdownTimerService { //该方法依赖耦合实现,不够优雅 isWaiting = true; } - void handleWaitingFinished(){ - if(isWaiting){ + + void handleWaitingFinished() { + if (isWaiting) { _showShutdownDialog(); isWaiting = false; } } + void _executeShutdown() { if (exitApp) { //退出app exit(0); } else { //暂停播放 - PlPlayerController plPlayerController = PlPlayerController.getInstance(); + PlPlayerController plPlayerController = + PlPlayerController.getInstance(videoType: 'none'); if (plPlayerController.playerStatus.playing) { plPlayerController.pause(); waitForPlayingCompleted = true; From 0e52e0288c0d9772df5615bf0121788a201cc7b7 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 16:08:10 +0800 Subject: [PATCH 12/23] =?UTF-8?q?opt:=20=E4=BC=98=E5=8C=96=E6=8A=95?= =?UTF-8?q?=E5=B8=81Dialog=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bangumi/introduction/controller.dart | 66 ++++++++----------- lib/pages/setting/widgets/select_dialog.dart | 2 +- .../video/detail/introduction/controller.dart | 64 +++++++----------- 3 files changed, 52 insertions(+), 80 deletions(-) diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index b26028cf..575a77de 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -131,51 +131,37 @@ class BangumiIntroController extends GetxController { builder: (context) { return AlertDialog( title: const Text('选择投币个数'), - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 24), content: StatefulBuilder(builder: (context, StateSetter setState) { return Column( mainAxisSize: MainAxisSize.min, - children: [ - RadioListTile( - value: 1, - title: const Text('1枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - RadioListTile( - value: 2, - title: const Text('2枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - ], + children: [1, 2] + .map( + (e) => RadioListTile( + value: e, + title: Text('$e枚'), + groupValue: _tempThemeValue, + onChanged: (value) async { + _tempThemeValue = value!; + setState(() {}); + var res = await VideoHttp.coinVideo( + bvid: bvid, multiply: _tempThemeValue); + if (res['status']) { + SmartDialog.showToast('投币成功 👏'); + hasCoin.value = true; + bangumiDetail.value.stat!['coins'] = + bangumiDetail.value.stat!['coins'] + + _tempThemeValue; + } else { + SmartDialog.showToast(res['msg']); + } + Get.back(); + }, + ), + ) + .toList(), ); }), - actions: [ - TextButton(onPressed: () => Get.back(), child: const Text('取消')), - TextButton( - onPressed: () async { - var res = await VideoHttp.coinVideo( - bvid: bvid, multiply: _tempThemeValue); - if (res['status']) { - SmartDialog.showToast('投币成功 👏'); - hasCoin.value = true; - bangumiDetail.value.stat!['coins'] = - bangumiDetail.value.stat!['coins'] + _tempThemeValue; - } else { - SmartDialog.showToast(res['msg']); - } - Get.back(); - }, - child: const Text('确定'), - ) - ], ); }); } diff --git a/lib/pages/setting/widgets/select_dialog.dart b/lib/pages/setting/widgets/select_dialog.dart index 50229f9e..ab5f2ce4 100644 --- a/lib/pages/setting/widgets/select_dialog.dart +++ b/lib/pages/setting/widgets/select_dialog.dart @@ -29,7 +29,7 @@ class _SelectDialogState extends State> { return AlertDialog( title: Text(widget.title), - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 24), content: StatefulBuilder(builder: (context, StateSetter setState) { return SingleChildScrollView( child: Column( diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 6469b5c5..8d602b83 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -219,50 +219,36 @@ class VideoIntroController extends GetxController { builder: (context) { return AlertDialog( title: const Text('选择投币个数'), - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 24), content: StatefulBuilder(builder: (context, StateSetter setState) { return Column( mainAxisSize: MainAxisSize.min, - children: [ - RadioListTile( - value: 1, - title: const Text('1枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - RadioListTile( - value: 2, - title: const Text('2枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - ], + children: [1, 2] + .map( + (e) => RadioListTile( + value: e, + title: Text('$e枚'), + groupValue: _tempThemeValue, + onChanged: (value) async { + _tempThemeValue = value!; + setState(() {}); + var res = await VideoHttp.coinVideo( + bvid: bvid, multiply: _tempThemeValue); + if (res['status']) { + SmartDialog.showToast('投币成功 👏'); + hasCoin.value = true; + videoDetail.value.stat!.coin = + videoDetail.value.stat!.coin! + _tempThemeValue; + } else { + SmartDialog.showToast(res['msg']); + } + Get.back(); + }, + ), + ) + .toList(), ); }), - actions: [ - TextButton(onPressed: () => Get.back(), child: const Text('取消')), - TextButton( - onPressed: () async { - var res = await VideoHttp.coinVideo( - bvid: bvid, multiply: _tempThemeValue); - if (res['status']) { - SmartDialog.showToast('投币成功 👏'); - hasCoin.value = true; - videoDetail.value.stat!.coin = - videoDetail.value.stat!.coin! + _tempThemeValue; - } else { - SmartDialog.showToast(res['msg']); - } - Get.back(); - }, - child: const Text('确定')) - ], ); }); } From f24291134c84c864b5047ed90f1d7a628c30722b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 17:44:19 +0800 Subject: [PATCH 13/23] =?UTF-8?q?feat:=20=E5=90=88=E9=9B=86=E5=B0=81?= =?UTF-8?q?=E9=9D=A2=E5=B1=95=E7=A4=BA=E3=80=81=E5=B0=81=E9=9D=A2=E5=88=87?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/pages_bottom_sheet.dart | 44 ++++++++++++------- lib/models/model_hot_video_item.dart | 3 ++ lib/models/video_detail_res.dart | 6 +++ .../bangumi/introduction/controller.dart | 8 ++-- lib/pages/bangumi/introduction/view.dart | 4 +- lib/pages/bangumi/widgets/bangumi_panel.dart | 3 +- lib/pages/video/detail/controller.dart | 3 ++ .../video/detail/introduction/controller.dart | 12 +++-- lib/pages/video/detail/introduction/view.dart | 7 ++- .../introduction/widgets/page_panel.dart | 6 +-- .../introduction/widgets/season_panel.dart | 1 + lib/pages/video/detail/view.dart | 16 ++++--- 12 files changed, 78 insertions(+), 35 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index c64b58b6..54f14654 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../models/common/video_episode_type.dart'; @@ -44,25 +45,38 @@ class EpisodeBottomSheet { title = '第${episode.title}话 ${episode.longTitle!}'; break; } - return ListTile( + return InkWell( onTap: () { SmartDialog.showToast('切换至「$title」'); changeFucCall.call(episode, index); }, - dense: false, - leading: isCurrentIndex - ? Image.asset( - 'assets/images/live.gif', - color: primary, - height: 12, - ) - : null, - title: Text( - title, - style: TextStyle( - fontSize: 14, - color: isCurrentIndex ? primary : onSurface, - ), + child: Padding( + padding: const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8), + child: isFullScreen + ? Text( + title, + maxLines: 1, + style: TextStyle( + fontSize: 14, + color: isCurrentIndex ? primary : onSurface, + ), + ) + : Row( + children: [ + NetworkImgLayer(width: 130, height: 75, src: episode.cover), + const SizedBox(width: 10), + Expanded( + child: Text( + title, + maxLines: 2, + style: TextStyle( + fontSize: 14, + color: isCurrentIndex ? primary : onSurface, + ), + ), + ), + ], + ), ), ); } diff --git a/lib/models/model_hot_video_item.dart b/lib/models/model_hot_video_item.dart index db331a4c..ab7e6e04 100644 --- a/lib/models/model_hot_video_item.dart +++ b/lib/models/model_hot_video_item.dart @@ -23,6 +23,7 @@ class HotVideoItemModel { this.dimension, this.shortLinkV2, this.firstFrame, + this.cover, this.pubLocation, this.seasontype, this.isOgv, @@ -50,6 +51,7 @@ class HotVideoItemModel { Dimension? dimension; String? shortLinkV2; String? firstFrame; + String? cover; String? pubLocation; int? seasontype; bool? isOgv; @@ -77,6 +79,7 @@ class HotVideoItemModel { dimension = Dimension.fromMap(json['dimension']); shortLinkV2 = json["short_link_v2"]; firstFrame = json["first_frame"]; + cover = json["first_frame"]; pubLocation = json["pub_location"]; seasontype = json["seasontype"]; isOgv = json["isOgv"]; diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index a82b6fbb..b7b1b481 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -382,6 +382,7 @@ class Part { String? weblink; Dimension? dimension; String? firstFrame; + String? cover; Part({ this.cid, @@ -393,6 +394,7 @@ class Part { this.weblink, this.dimension, this.firstFrame, + this.cover, }); fromRawJson(String str) => Part.fromJson(json.decode(str)); @@ -411,6 +413,7 @@ class Part { ? null : Dimension.fromJson(json["dimension"]); firstFrame = json["first_frame"]; + cover = json["first_frame"]; } Map toJson() { @@ -634,6 +637,7 @@ class EpisodeItem { this.attribute, this.page, this.bvid, + this.cover, }); int? seasonId; int? sectionId; @@ -644,6 +648,7 @@ class EpisodeItem { int? attribute; Part? page; String? bvid; + String? cover; EpisodeItem.fromJson(Map json) { seasonId = json['season_id']; @@ -655,6 +660,7 @@ class EpisodeItem { attribute = json['attribute']; page = Part.fromJson(json['page']); bvid = json['bvid']; + cover = json['arc']['pic']; } } diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 575a77de..65cd5dd8 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -215,7 +215,7 @@ class BangumiIntroController extends GetxController { } // 修改分P或番剧分集 - Future changeSeasonOrbangu(bvid, cid, aid) async { + Future changeSeasonOrbangu(bvid, cid, aid, cover) async { // 重新获取视频资源 VideoDetailController videoDetailCtr = Get.find(tag: Get.arguments['heroTag']); @@ -223,6 +223,7 @@ class BangumiIntroController extends GetxController { videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; videoDetailCtr.oid.value = aid; + videoDetailCtr.cover.value = cover; videoDetailCtr.queryVideoUrl(); // 重新请求评论 try { @@ -281,7 +282,8 @@ class BangumiIntroController extends GetxController { int cid = episodes[nextIndex].cid!; String bvid = episodes[nextIndex].bvid!; int aid = episodes[nextIndex].aid!; - changeSeasonOrbangu(bvid, cid, aid); + String cover = episodes[nextIndex].cover!; + changeSeasonOrbangu(bvid, cid, aid, cover); } // 播放器底栏 选集 回调 @@ -302,7 +304,7 @@ class BangumiIntroController extends GetxController { sheetHeight: Get.size.height, isFullScreen: true, changeFucCall: (item, index) { - changeSeasonOrbangu(item.bvid, item.cid, item.aid); + changeSeasonOrbangu(item.bvid, item.cid, item.aid, item.cover); SmartDialog.dismiss(); }, ).buildShowContent(Get.context!), diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index e47db480..6876da79 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -322,8 +322,8 @@ class _BangumiInfoState extends State { pages: widget.bangumiDetail!.episodes!, cid: cid! ?? widget.bangumiDetail!.episodes!.first.cid!, sheetHeight: sheetHeight, - changeFuc: (bvid, cid, aid) => - bangumiIntroController.changeSeasonOrbangu(bvid, cid, aid), + changeFuc: (bvid, cid, aid, cover) => bangumiIntroController + .changeSeasonOrbangu(bvid, cid, aid, cover), bangumiDetail: bangumiIntroController.bangumiDetail.value, bangumiIntroController: bangumiIntroController, ) diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index 3e965f34..3df7ce25 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -84,11 +84,12 @@ class _BangumiPanelState extends State { item.bvid, item.cid, item.aid, + item.cover, ); if (_bottomSheetController != null) { _bottomSheetController?.close(); } - currentIndex = i; + currentIndex.value = i; scrollToIndex(); } diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 3cc43005..5fecde8d 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -73,6 +73,7 @@ class VideoDetailController extends GetxController ReplyItemModel? firstFloor; final scaffoldKey = GlobalKey(); RxString bgCover = ''.obs; + RxString cover = ''.obs; PlPlayerController plPlayerController = PlPlayerController.getInstance(); late VideoItem firstVideo; @@ -120,10 +121,12 @@ class VideoDetailController extends GetxController var args = argMap['videoItem']; if (args.pic != null && args.pic != '') { videoItem['pic'] = args.pic; + cover.value = args.pic; } } if (keys.contains('pic')) { videoItem['pic'] = argMap['pic']; + cover.value = argMap['pic']; } } tabCtr = TabController(length: 2, vsync: this); diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 8d602b83..b9a3ef93 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -432,7 +432,7 @@ class VideoIntroController extends GetxController { } // 修改分P或番剧分集 - Future changeSeasonOrbangu(bvid, cid, aid) async { + Future changeSeasonOrbangu(bvid, cid, aid, cover) async { // 重新获取视频资源 final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); @@ -447,6 +447,7 @@ class VideoIntroController extends GetxController { videoDetailCtr.oid.value = aid ?? IdUtils.bv2av(bvid); videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; + videoDetailCtr.cover.value = cover; videoDetailCtr.queryVideoUrl(); // 重新请求评论 try { @@ -494,6 +495,7 @@ class VideoIntroController extends GetxController { void nextPlay() { final List episodes = []; bool isPages = false; + late String cover; if (videoDetail.value.ugcSeason != null) { final UgcSeason ugcSeason = videoDetail.value.ugcSeason!; final List sections = ugcSeason.sections!; @@ -510,6 +512,7 @@ class VideoIntroController extends GetxController { final int currentIndex = episodes.indexWhere((e) => e.cid == lastPlayCid.value); int nextIndex = currentIndex + 1; + cover = episodes[nextIndex].cover; final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); final PlayRepeat platRepeat = videoDetailCtr.plPlayerController.playRepeat; @@ -526,7 +529,7 @@ class VideoIntroController extends GetxController { final int cid = episodes[nextIndex].cid!; final String rBvid = isPages ? bvid : episodes[nextIndex].bvid; final int rAid = isPages ? IdUtils.bv2av(bvid) : episodes[nextIndex].aid!; - changeSeasonOrbangu(rBvid, cid, rAid); + changeSeasonOrbangu(rBvid, cid, rAid, cover); } // 设置关注分组 @@ -591,10 +594,11 @@ class VideoIntroController extends GetxController { isFullScreen: true, changeFucCall: (item, index) { if (dataType == VideoEpidoesType.videoEpisode) { - changeSeasonOrbangu(IdUtils.av2bv(item.aid), item.cid, item.aid); + changeSeasonOrbangu( + IdUtils.av2bv(item.aid), item.cid, item.aid, item.cover); } if (dataType == VideoEpidoesType.videoPart) { - changeSeasonOrbangu(bvid, item.cid, null); + changeSeasonOrbangu(bvid, item.cid, null, item.cover); } SmartDialog.dismiss(); }, diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 597b6def..47404658 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -383,11 +383,12 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ? videoIntroController.lastPlayCid.value : widget.videoDetail!.pages!.first.cid, sheetHeight: videoDetailCtr.sheetHeight.value, - changeFuc: (bvid, cid, aid) => + changeFuc: (bvid, cid, aid, cover) => videoIntroController.changeSeasonOrbangu( bvid, cid, aid, + cover, ), videoIntroCtr: videoIntroController, ), @@ -401,10 +402,12 @@ class _VideoInfoState extends State with TickerProviderStateMixin { pages: widget.videoDetail!.pages!, cid: videoIntroController.lastPlayCid.value, sheetHeight: videoDetailCtr.sheetHeight.value, - changeFuc: (cid) => videoIntroController.changeSeasonOrbangu( + changeFuc: (cid, cover) => + videoIntroController.changeSeasonOrbangu( videoIntroController.bvid, cid, null, + cover, ), videoIntroCtr: videoIntroController, ), diff --git a/lib/pages/video/detail/introduction/widgets/page_panel.dart b/lib/pages/video/detail/introduction/widgets/page_panel.dart index 83db2d52..266f5566 100644 --- a/lib/pages/video/detail/introduction/widgets/page_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/page_panel.dart @@ -58,7 +58,7 @@ class _PagesPanelState extends State { } void changeFucCall(item, i) async { - widget.changeFuc?.call(item.cid); + widget.changeFuc?.call(item.cid, item.cover); currentIndex.value = i; _bottomSheetController?.close(); scrollToIndex(); @@ -129,7 +129,7 @@ class _PagesPanelState extends State { ), ), Container( - height: 35, + height: 55, margin: const EdgeInsets.only(bottom: 8), child: ListView.builder( scrollDirection: Axis.horizontal, @@ -163,7 +163,7 @@ class _PagesPanelState extends State { Expanded( child: Text( widget.pages[i].pagePart!, - maxLines: 1, + maxLines: 2, style: TextStyle( fontSize: 13, color: isCurrentIndex diff --git a/lib/pages/video/detail/introduction/widgets/season_panel.dart b/lib/pages/video/detail/introduction/widgets/season_panel.dart index 2afefcb4..fdfec6f9 100644 --- a/lib/pages/video/detail/introduction/widgets/season_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/season_panel.dart @@ -67,6 +67,7 @@ class _SeasonPanelState extends State { IdUtils.av2bv(item.aid), item.cid, item.aid, + item.cover, ); currentIndex.value = i; _bottomSheetController?.close(); diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 0152a2cb..7f1d6039 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -458,11 +458,17 @@ class _VideoDetailPageState extends State onTap: () { handlePlay(); }, - child: NetworkImgLayer( - type: 'emote', - src: vdCtr.videoItem['pic'], - width: Get.width, - height: videoHeight.value, + child: Obx( + () => AnimatedOpacity( + duration: const Duration(milliseconds: 100), // 渐变动画的持续时间 + opacity: 1, // 设置不透明度 + child: NetworkImgLayer( + type: 'emote', + src: vdCtr.cover.value, + width: Get.width, + height: videoHeight.value, + ), + ), ), ), Positioned( From 257596cb9eb025ccc674c413c575e59fe4c0cf7e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 20:40:23 +0800 Subject: [PATCH 14/23] =?UTF-8?q?mod:=20=E9=BB=98=E8=AE=A4=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E7=A1=AC=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/setting/play_setting.dart | 2 +- lib/pages/video/detail/controller.dart | 4 ++-- lib/plugin/pl_player/controller.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index 07d736e3..4a8495e5 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -131,7 +131,7 @@ class _PlaySettingState extends State { title: '开启硬解', subTitle: '以较低功耗播放视频', setKey: SettingBoxKey.enableHA, - defaultVal: true, + defaultVal: false, ), const SetSwitchItem( title: '观看人数', diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4613c7ca..127e81a7 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -59,7 +59,7 @@ class VideoDetailController extends GetxController // 封面图的展示 RxBool isShowCover = true.obs; // 硬解 - RxBool enableHA = true.obs; + RxBool enableHA = false.obs; /// 本地存储 Box userInfoCache = GStrorage.userInfo; @@ -128,7 +128,7 @@ class VideoDetailController extends GetxController tabCtr = TabController(length: 2, vsync: this); autoPlay.value = setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true); - enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: true); + enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: false); enableRelatedVideo = setting.get(SettingBoxKey.enableRelatedVideo, defaultValue: true); if (userInfo == null || diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index be72eccb..a31ce0b8 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -351,7 +351,7 @@ class PlPlayerController { // 初始化播放速度 double speed = 1.0, // 硬件加速 - bool enableHA = true, + bool enableHA = false, double? width, double? height, Duration? duration, From cbb7b90bf9ce8678fc2a9f585a5b4f8a3a21a016 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 22:11:56 +0800 Subject: [PATCH 15/23] mod --- lib/common/widgets/network_img_layer.dart | 1 - lib/pages/video/detail/widgets/header_control.dart | 2 +- lib/utils/utils.dart | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 173db853..bda8ee5c 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -36,7 +36,6 @@ class NetworkImgLayer extends StatelessWidget { final int defaultImgQuality = GlobalData().imgQuality; final String imageUrl = '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp'; - // print(imageUrl); int? memCacheWidth, memCacheHeight; double aspectRatio = (width / height).toDouble(); diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 6acd20d7..544d93e0 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -446,7 +446,7 @@ class _HeaderControlState extends State { children: [ RadioListTile( value: -1, - title: const Text('关闭弹幕'), + title: const Text('关闭字幕'), groupValue: tempThemeValue, onChanged: (value) { tempThemeValue = value!; diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 987f57c1..b40e9bfe 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -109,7 +109,6 @@ class Utils { toInt: false, formatType: formatType); } - print('distance: $distance'); if (distance <= 60) { return '刚刚'; } else if (distance <= 3600) { From aff39c291dc669158277301541cb98c9ed8ec0b0 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 22:17:10 +0800 Subject: [PATCH 16/23] =?UTF-8?q?fix:=20=E5=90=88=E9=9B=86cover=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/pages_bottom_sheet.dart | 46 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index 54f14654..00233a07 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -45,25 +45,37 @@ class EpisodeBottomSheet { title = '第${episode.title}话 ${episode.longTitle!}'; break; } - return InkWell( - onTap: () { - SmartDialog.showToast('切换至「$title」'); - changeFucCall.call(episode, index); - }, - child: Padding( - padding: const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8), - child: isFullScreen - ? Text( - title, - maxLines: 1, + return isFullScreen || episode?.cover == null + ? ListTile( + onTap: () { + SmartDialog.showToast('切换至「$title」'); + changeFucCall.call(episode, index); + }, + dense: false, + leading: isCurrentIndex + ? Image.asset( + 'assets/images/live.gif', + color: primary, + height: 12, + ) + : null, + title: Text(title, style: TextStyle( fontSize: 14, color: isCurrentIndex ? primary : onSurface, - ), - ) - : Row( + ))) + : InkWell( + onTap: () { + SmartDialog.showToast('切换至「$title」'); + changeFucCall.call(episode, index); + }, + child: Padding( + padding: + const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8), + child: Row( children: [ - NetworkImgLayer(width: 130, height: 75, src: episode.cover), + NetworkImgLayer( + width: 130, height: 75, src: episode?.cover ?? ''), const SizedBox(width: 10), Expanded( child: Text( @@ -77,8 +89,8 @@ class EpisodeBottomSheet { ), ], ), - ), - ); + ), + ); } Widget buildTitle() { From c653a60f05501f983bb0d98c529fb240409bba6e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 00:06:08 +0800 Subject: [PATCH 17/23] =?UTF-8?q?feat:=20=E6=B4=BB=E5=8A=A8=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=8A=A8=E6=80=81=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/dynamics/result.dart | 3 + lib/pages/dynamics/widgets/forward_panel.dart | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index 2f7c2d40..bc7105d1 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -414,6 +414,7 @@ class DynamicMajorModel { this.none, this.type, this.courses, + this.common, }); DynamicArchiveModel? archive; @@ -429,6 +430,7 @@ class DynamicMajorModel { // MAJOR_TYPE_OPUS 图文/文章 String? type; Map? courses; + Map? common; DynamicMajorModel.fromJson(Map json) { archive = json['archive'] != null @@ -452,6 +454,7 @@ class DynamicMajorModel { json['none'] != null ? DynamicNoneModel.fromJson(json['none']) : null; type = json['type']; courses = json['courses'] ?? {}; + common = json['common'] ?? {}; } } diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index 5a8d9f17..76c7b24e 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/utils/utils.dart'; import 'additional_panel.dart'; @@ -182,6 +183,61 @@ Widget forWard(item, context, ctr, source, {floor = 1}) { ) ], ); + // 活动 + case 'DYNAMIC_TYPE_COMMON_SQUARE': + return Padding( + padding: const EdgeInsets.only(top: 8), + child: InkWell( + onTap: () { + Get.toNamed('/webview', parameters: { + 'url': item.modules.moduleDynamic.major.common['jump_url'], + 'type': 'url', + 'pageTitle': item.modules.moduleDynamic.major.common['title'] + }); + }, + child: Container( + width: double.infinity, + padding: + const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10), + color: Theme.of(context).dividerColor.withOpacity(0.08), + child: Row( + children: [ + NetworkImgLayer( + width: 45, + height: 45, + src: item.modules.moduleDynamic.major.common['cover'], + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.modules.moduleDynamic.major.common['title'], + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Text( + item.modules.moduleDynamic.major.common['desc'], + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ) + ], + ), + // TextButton(onPressed: () {}, child: Text('123')) + ), + ), + ); default: return const SizedBox( width: double.infinity, From 750e9d2b58635d70c0627d64adaf1ea5dd7621db Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 07:39:55 +0800 Subject: [PATCH 18/23] =?UTF-8?q?revert:=20=E8=AF=84=E8=AE=BA=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=98=E5=85=88=E5=B1=95=E7=A4=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/dynamics/detail/view.dart | 6 +++--- lib/pages/video/detail/controller.dart | 3 +-- lib/pages/video/detail/reply/view.dart | 8 ++++---- .../video/detail/reply/widgets/reply_item.dart | 6 ++---- lib/pages/video/detail/reply_reply/controller.dart | 10 +--------- lib/pages/video/detail/reply_reply/view.dart | 14 ++------------ 6 files changed, 13 insertions(+), 34 deletions(-) diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index 11636b5b..bd07921b 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -106,7 +106,7 @@ class _DynamicDetailPageState extends State } // 查看二级评论 - void replyReply(replyItem, currentReply) { + void replyReply(replyItem) { int oid = replyItem.oid; int rpid = replyItem.rpid!; Get.to( @@ -324,8 +324,8 @@ class _DynamicDetailPageState extends State replyItem: replyList[index], showReplyRow: true, replyLevel: '1', - replyReply: (replyItem, currentReply) => - replyReply(replyItem, currentReply), + replyReply: (replyItem) => + replyReply(replyItem), replyType: ReplyType.values[replyType], addReply: (replyItem) { replyList[index] diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index c6c4bef6..8efc8ea1 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -165,7 +165,7 @@ class VideoDetailController extends GetxController getSubtitle(); } - showReplyReplyPanel(oid, fRpid, firstFloor, currentReply) { + showReplyReplyPanel(oid, fRpid, firstFloor) { replyReplyBottomSheetCtr = scaffoldKey.currentState?.showBottomSheet((BuildContext context) { return VideoReplyReplyPanel( @@ -178,7 +178,6 @@ class VideoDetailController extends GetxController replyType: ReplyType.video, source: 'videoDetail', sheetHeight: sheetHeight.value, - currentReply: currentReply, ); }); replyReplyBottomSheetCtr?.closed.then((value) { diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 420f349c..4c533647 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -110,7 +110,7 @@ class _VideoReplyPanelState extends State } // 展示二级回复 - void replyReply(replyItem, currentReply) { + void replyReply(replyItem) { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); if (replyItem != null) { @@ -118,7 +118,7 @@ class _VideoReplyPanelState extends State videoDetailCtr.fRpid = replyItem.rpid!; videoDetailCtr.firstFloor = replyItem; videoDetailCtr.showReplyReplyPanel( - replyItem.oid, replyItem.rpid!, replyItem, currentReply); + replyItem.oid, replyItem.rpid!, replyItem); } } @@ -229,8 +229,8 @@ class _VideoReplyPanelState extends State .replyList[index], showReplyRow: true, replyLevel: replyLevel, - replyReply: (replyItem, currentReply) => - replyReply(replyItem, currentReply), + replyReply: (replyItem) => + replyReply(replyItem), replyType: ReplyType.video, ); } diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 8a8e4af7..ecc2dd02 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -531,10 +531,8 @@ InlineSpan buildContent( TextSpan( text: str, recognizer: TapGestureRecognizer() - ..onTap = () => replyReply?.call( - replyItem.root == 0 ? replyItem : fReplyItem, - replyItem, - ), + ..onTap = () => + replyReply?.call(replyItem.root == 0 ? replyItem : fReplyItem), ), ); } diff --git a/lib/pages/video/detail/reply_reply/controller.dart b/lib/pages/video/detail/reply_reply/controller.dart index 4c553e29..e94aaea5 100644 --- a/lib/pages/video/detail/reply_reply/controller.dart +++ b/lib/pages/video/detail/reply_reply/controller.dart @@ -26,7 +26,7 @@ class VideoReplyReplyController extends GetxController { currentPage = 0; } - Future queryReplyList({type = 'init', currentReply}) async { + Future queryReplyList({type = 'init'}) async { if (type == 'init') { currentPage = 0; } @@ -63,14 +63,6 @@ class VideoReplyReplyController extends GetxController { // res['data'].replies.addAll(replyList); } } - if (replyList.isNotEmpty && currentReply != null) { - int indexToRemove = - replyList.indexWhere((item) => currentReply.rpid == item.rpid); - // 如果找到了指定ID的项,则移除 - if (indexToRemove != -1) { - replyList.removeAt(indexToRemove); - } - } isLoadingMore = false; return res; } diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index 6441c600..3fe84c71 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -20,7 +20,6 @@ class VideoReplyReplyPanel extends StatefulWidget { this.source, this.replyType, this.sheetHeight, - this.currentReply, super.key, }); final int? oid; @@ -30,7 +29,6 @@ class VideoReplyReplyPanel extends StatefulWidget { final String? source; final ReplyType? replyType; final double? sheetHeight; - final dynamic currentReply; @override State createState() => _VideoReplyReplyPanelState(); @@ -65,9 +63,7 @@ class _VideoReplyReplyPanelState extends State { }, ); - _futureBuilderFuture = _videoReplyReplyController.queryReplyList( - currentReply: widget.currentReply, - ); + _futureBuilderFuture = _videoReplyReplyController.queryReplyList(); } void replyReply(replyItem) {} @@ -111,9 +107,7 @@ class _VideoReplyReplyPanelState extends State { onRefresh: () async { setState(() {}); _videoReplyReplyController.currentPage = 0; - return await _videoReplyReplyController.queryReplyList( - currentReply: widget.currentReply, - ); + return await _videoReplyReplyController.queryReplyList(); }, child: CustomScrollView( controller: _videoReplyReplyController.scrollController, @@ -146,10 +140,6 @@ class _VideoReplyReplyPanelState extends State { if (snapshot.connectionState == ConnectionState.done) { Map? data = snapshot.data; if (data != null && data['status']) { - if (widget.currentReply != null) { - _videoReplyReplyController.replyList - .insert(0, widget.currentReply); - } // 请求成功 return Obx( () => SliverList( From 8a6b4f987f4aeabe91c0d2d98adc898be044521f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 22:03:19 +0800 Subject: [PATCH 19/23] revert: NavigationBar Color --- lib/main.dart | 59 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3877685c..43bcf930 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -65,6 +65,20 @@ void main() async { }, ); + // 小白条、导航栏沉浸 + if (Platform.isAndroid) { + List versionParts = Platform.version.split('.'); + int androidVersion = int.parse(versionParts[0]); + if (androidVersion >= 29) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + } + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + systemNavigationBarDividerColor: Colors.transparent, + statusBarColor: Colors.transparent, + )); + } + Data.init(); GlobalData(); PiliSchame.init(); @@ -130,26 +144,33 @@ class MyApp extends StatelessWidget { ); } - ThemeData themeData = ThemeData( - colorScheme: currentThemeValue == ThemeType.dark - ? darkColorScheme - : lightColorScheme, - ); + // ThemeData themeData = ThemeData( + // colorScheme: currentThemeValue == ThemeType.dark + // ? darkColorScheme + // : lightColorScheme, + // ); - // 小白条、导航栏沉浸 - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( - systemNavigationBarColor: GlobalData().enableMYBar - ? const Color(0x00010000) - : themeData.canvasColor, - systemNavigationBarDividerColor: GlobalData().enableMYBar - ? const Color(0x00010000) - : themeData.canvasColor, - systemNavigationBarIconBrightness: currentThemeValue == ThemeType.dark - ? Brightness.light - : Brightness.dark, - statusBarColor: Colors.transparent, - )); + // // 小白条、导航栏沉浸 + // if (Platform.isAndroid) { + // List versionParts = Platform.version.split('.'); + // int androidVersion = int.parse(versionParts[0]); + // if (androidVersion >= 29) { + // SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + // } + // SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( + // systemNavigationBarColor: GlobalData().enableMYBar + // ? const Color(0x00010000) + // : themeData.canvasColor, + // systemNavigationBarDividerColor: GlobalData().enableMYBar + // ? const Color(0x00010000) + // : themeData.canvasColor, + // systemNavigationBarIconBrightness: + // currentThemeValue == ThemeType.dark + // ? Brightness.light + // : Brightness.dark, + // statusBarColor: Colors.transparent, + // )); + // } // 图片缓存 // PaintingBinding.instance.imageCache.maximumSizeBytes = 1000 << 20; From bc4fb0e0ae40cb9a77ebe18893f8a4cbd34071c5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 22:27:14 +0800 Subject: [PATCH 20/23] fix: videoDetail cover null --- lib/pages/video/detail/controller.dart | 27 ++++++++++--------- .../video/detail/introduction/controller.dart | 1 + lib/utils/app_scheme.dart | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index c6c4bef6..bb099255 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -115,20 +115,15 @@ class VideoDetailController extends GetxController super.onInit(); final Map argMap = Get.arguments; userInfo = userInfoCache.get('userInfoCache'); - var keys = argMap.keys.toList(); - if (keys.isNotEmpty) { - if (keys.contains('videoItem')) { - var args = argMap['videoItem']; - if (args.pic != null && args.pic != '') { - videoItem['pic'] = args.pic; - cover.value = args.pic; - } - } - if (keys.contains('pic')) { - videoItem['pic'] = argMap['pic']; - cover.value = argMap['pic']; - } + if (argMap.containsKey('videoItem')) { + var args = argMap['videoItem']; + updateCover(args.pic); } + + if (argMap.containsKey('pic')) { + updateCover(argMap['pic']); + } + tabCtr = TabController(length: 2, vsync: this); autoPlay.value = setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true); @@ -551,4 +546,10 @@ class VideoDetailController extends GetxController }, ); } + + void updateCover(String? pic) { + if (pic != null && pic != '') { + cover.value = videoItem['pic'] = pic; + } + } } diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index b9a3ef93..2ced79f0 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -90,6 +90,7 @@ class VideoIntroController extends GetxController { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); videoDetailCtr.tabs.value = ['简介', '评论 ${result['data']?.stat?.reply}']; + videoDetailCtr.cover.value = result['data'].pic ?? ''; // 获取到粉丝数再返回 await queryUserStat(); } diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 9009df6f..69fa717d 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -117,7 +117,7 @@ class PiliSchame { // ignore: always_specify_types (e) => Get.toNamed('/video?bvid=$bvid&cid=$cid', arguments: { - 'pic': null, + 'pic': '', 'heroTag': heroTag, }), ); From 811487bdd42f696b7ee56c4dd8c43fed2c787217 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 23:03:33 +0800 Subject: [PATCH 21/23] =?UTF-8?q?fix:=20=E9=87=8D=E5=9B=9E=E5=89=8D?= =?UTF-8?q?=E5=8F=B0=E5=BC=B9=E5=B9=95=E5=A0=86=E7=A7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/view.dart | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 7f1d6039..199e6b88 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -38,7 +38,7 @@ class VideoDetailPage extends StatefulWidget { } class _VideoDetailPageState extends State - with TickerProviderStateMixin, RouteAware { + with TickerProviderStateMixin, RouteAware, WidgetsBindingObserver { late VideoDetailController vdCtr; PlPlayerController? plPlayerController; final ScrollController _extendNestCtr = ScrollController(); @@ -61,6 +61,8 @@ class _VideoDetailPageState extends State late bool autoPiP; late Floating floating; bool isShowing = true; + // 生命周期监听 + late final AppLifecycleListener _lifecycleListener; @override void initState() { @@ -96,6 +98,8 @@ class _VideoDetailPageState extends State floating = vdCtr.floating!; autoEnterPip(); } + WidgetsBinding.instance.addObserver(this); + lifecycleListener(); } // 获取视频资源,初始化播放器 @@ -219,6 +223,8 @@ class _VideoDetailPageState extends State floating.dispose(); } appbarStream.close(); + WidgetsBinding.instance.removeObserver(this); + _lifecycleListener.dispose(); super.dispose(); } @@ -281,6 +287,29 @@ class _VideoDetailPageState extends State } } + // 生命周期监听 + void lifecycleListener() { + _lifecycleListener = AppLifecycleListener( + // onResume: () => _handleTransition('resume'), + // 后台 + // onInactive: () => _handleTransition('inactive'), + // 在Android和iOS端不生效 + // onHide: () => _handleTransition('hide'), + onShow: () => _handleTransition('show'), + onPause: () => _handleTransition('pause'), + onRestart: () => _handleTransition('restart'), + onDetach: () => _handleTransition('detach'), + ); + } + + void _handleTransition(String name) { + switch (name) { + case 'show' || 'restart': + plPlayerController?.danmakuController?.clear(); + break; + } + } + @override Widget build(BuildContext context) { final sizeContext = MediaQuery.sizeOf(context); From 0bb26aa46757eec6b3e5855e2e90e5f0fe4d167b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 29 Apr 2024 13:16:25 +0800 Subject: [PATCH 22/23] fix: videoDetail cover null --- lib/common/pages_bottom_sheet.dart | 2 +- lib/models/video_detail_res.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index 00233a07..2a56eb41 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -45,7 +45,7 @@ class EpisodeBottomSheet { title = '第${episode.title}话 ${episode.longTitle!}'; break; } - return isFullScreen || episode?.cover == null + return isFullScreen || episode?.cover == null || episode?.cover == '' ? ListTile( onTap: () { SmartDialog.showToast('切换至「$title」'); diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index b7b1b481..ae272375 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -412,8 +412,8 @@ class Part { dimension = json["dimension"] == null ? null : Dimension.fromJson(json["dimension"]); - firstFrame = json["first_frame"]; - cover = json["first_frame"]; + firstFrame = json["first_frame"] ?? ''; + cover = json["first_frame"] ?? ''; } Map toJson() { From 3c8a92209fa5b1725df883b9b9cc62a369708e76 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 29 Apr 2024 13:41:25 +0800 Subject: [PATCH 23/23] =?UTF-8?q?revert:=20=E8=AF=84=E8=AE=BA=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=98=E5=85=88=E5=B1=95=E7=A4=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/widgets/reply_item.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index ecc2dd02..468d2541 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -427,7 +427,7 @@ class ReplyItemRow extends StatelessWidget { if (extraRow == 1) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply!(replyItem, null), + onTap: () => replyReply!(replyItem), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8),