diff --git a/lib/pages/common/common_intro_controller.dart b/lib/pages/common/common_intro_controller.dart index 2feb768b..58ad2f29 100644 --- a/lib/pages/common/common_intro_controller.dart +++ b/lib/pages/common/common_intro_controller.dart @@ -54,6 +54,11 @@ abstract class CommonIntroController extends GetxController { bool prevPlay(); bool nextPlay(); + void actionLikeVideo(); + void actionCoinVideo(); + void actionTriple(); + void actionShareVideo(BuildContext context); + // 同时观看 final bool isShowOnlineTotal = Pref.enableOnlineTotal; late final RxString total = '1'.obs; diff --git a/lib/pages/video/introduction/pgc/controller.dart b/lib/pages/video/introduction/pgc/controller.dart index 0e9f9bfe..1cb77944 100644 --- a/lib/pages/video/introduction/pgc/controller.dart +++ b/lib/pages/video/introduction/pgc/controller.dart @@ -98,6 +98,7 @@ class PgcIntroController extends CommonIntroController { } // (取消)点赞 + @override Future actionLikeVideo() async { if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); @@ -115,6 +116,7 @@ class PgcIntroController extends CommonIntroController { } // 投币 + @override void actionCoinVideo() { if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); @@ -138,6 +140,7 @@ class PgcIntroController extends CommonIntroController { } // 分享视频 + @override void actionShareVideo(BuildContext context) { showDialog( context: context, @@ -408,7 +411,8 @@ class PgcIntroController extends CommonIntroController { } // 一键三连 - Future actionOneThree() async { + @override + Future actionTriple() async { feedBack(); if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); diff --git a/lib/pages/video/introduction/pgc/view.dart b/lib/pages/video/introduction/pgc/view.dart index e71e9fab..42b3d629 100644 --- a/lib/pages/video/introduction/pgc/view.dart +++ b/lib/pages/video/introduction/pgc/view.dart @@ -18,7 +18,6 @@ import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart'; import 'package:PiliPlus/utils/num_util.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart' show HapticFeedback; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; @@ -41,13 +40,13 @@ class PgcIntroPage extends StatefulWidget { } class _PgcIntroPageState extends State - with AutomaticKeepAliveClientMixin { + with + AutomaticKeepAliveClientMixin, + SingleTickerProviderStateMixin, + TripleAnimMixin { late PgcIntroController pgcIntroController; late VideoDetailController videoDetailCtr; - late final _coinKey = GlobalKey(); - late final _favKey = GlobalKey(); - bool isProcessing = false; Future handleState(FutureOr Function() action) async { if (!isProcessing) { @@ -65,6 +64,13 @@ class _PgcIntroPageState extends State super.initState(); pgcIntroController = Get.put(PgcIntroController(), tag: widget.heroTag); videoDetailCtr = Get.find(tag: widget.heroTag); + initTriple(); + } + + @override + void dispose() { + disposeTriple(); + super.dispose(); } @override @@ -425,42 +431,30 @@ class _PgcIntroPageState extends State icon: const Icon(FontAwesomeIcons.thumbsUp), selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), onTap: () => handleState(pgcIntroController.actionLikeVideo), - onLongPress: pgcIntroController.actionOneThree, + onLongPress: () => handleState(pgcIntroController.actionTriple), selectStatus: pgcIntroController.hasLike.value, semanticsLabel: '点赞', text: NumUtil.numFormat(item.stat!.like), - needAnim: true, - hasTriple: - pgcIntroController.hasLike.value && - pgcIntroController.hasCoin && - pgcIntroController.hasFav.value, - callBack: (start) { - if (start) { - HapticFeedback.lightImpact(); - _coinKey.currentState?.controller?.forward(); - _favKey.currentState?.controller?.forward(); - } else { - _coinKey.currentState?.controller?.reverse(); - _favKey.currentState?.controller?.reverse(); - } - }, + controller: animController, + animation: animation, + onStartTriple: onStartTriple, + onCancelTriple: onCancelTriple, ), ), Obx( () => ActionItem( - key: _coinKey, icon: const Icon(FontAwesomeIcons.b), selectIcon: const Icon(FontAwesomeIcons.b), onTap: () => handleState(pgcIntroController.actionCoinVideo), selectStatus: pgcIntroController.hasCoin, semanticsLabel: '投币', text: NumUtil.numFormat(item.stat!.coin), - needAnim: true, + controller: animController, + animation: animation, ), ), Obx( () => ActionItem( - key: _favKey, icon: const Icon(FontAwesomeIcons.star), selectIcon: const Icon(FontAwesomeIcons.solidStar), onTap: () => pgcIntroController.showFavBottomSheet(context), @@ -471,7 +465,8 @@ class _PgcIntroPageState extends State selectStatus: pgcIntroController.hasFav.value, semanticsLabel: '收藏', text: NumUtil.numFormat(item.stat!.favorite), - needAnim: true, + controller: animController, + animation: animation, ), ), Obx( @@ -495,4 +490,16 @@ class _PgcIntroPageState extends State ), ); } + + @override + bool get hasTriple => + pgcIntroController.hasLike.value && + pgcIntroController.hasCoin && + pgcIntroController.hasFav.value; + + @override + void onLike() => handleState(pgcIntroController.actionLikeVideo); + + @override + void onTriple() => handleState(pgcIntroController.actionTriple); } diff --git a/lib/pages/video/introduction/ugc/controller.dart b/lib/pages/video/introduction/ugc/controller.dart index ba981a26..c66114d1 100644 --- a/lib/pages/video/introduction/ugc/controller.dart +++ b/lib/pages/video/introduction/ugc/controller.dart @@ -181,7 +181,8 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { } // 一键三连 - Future actionOneThree() async { + @override + Future actionTriple() async { feedBack(); if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); @@ -217,6 +218,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { } // (取消)点赞 + @override Future actionLikeVideo() async { if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); @@ -266,7 +268,8 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { } // 投币 - Future actionCoinVideo() async { + @override + void actionCoinVideo() { if (!accountService.isLogin.value) { SmartDialog.showToast('账号未登录'); return; @@ -297,6 +300,7 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { StatDetail? getStat() => videoDetail.value.stat; // 分享视频 + @override void actionShareVideo(BuildContext context) { showDialog( context: context, diff --git a/lib/pages/video/introduction/ugc/view.dart b/lib/pages/video/introduction/ugc/view.dart index d57a225c..1eda4564 100644 --- a/lib/pages/video/introduction/ugc/view.dart +++ b/lib/pages/video/introduction/ugc/view.dart @@ -30,7 +30,6 @@ import 'package:PiliPlus/utils/utils.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart' show HapticFeedback; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart' hide ContextExtensionss; @@ -54,20 +53,27 @@ class UgcIntroPanel extends StatefulWidget { } class _UgcIntroPanelState extends State - with AutomaticKeepAliveClientMixin { + with + AutomaticKeepAliveClientMixin, + SingleTickerProviderStateMixin, + TripleAnimMixin { late UgcIntroController ugcIntroController; late final VideoDetailController videoDetailCtr = Get.find(tag: widget.heroTag); - late final _coinKey = GlobalKey(); - late final _favKey = GlobalKey(); - bool isProcessing = false; @override void initState() { super.initState(); ugcIntroController = Get.put(UgcIntroController(), tag: widget.heroTag); + initTriple(); + } + + @override + void dispose() { + disposeTriple(); + super.dispose(); } @override @@ -530,27 +536,16 @@ class _UgcIntroPanelState extends State icon: const Icon(FontAwesomeIcons.thumbsUp), selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), onTap: () => handleState(ugcIntroController.actionLikeVideo), - onLongPress: () => handleState(ugcIntroController.actionOneThree), + onLongPress: () => handleState(ugcIntroController.actionTriple), selectStatus: ugcIntroController.hasLike.value, semanticsLabel: '点赞', text: !isLoading ? NumUtil.numFormat(videoDetail.stat!.like) : null, - needAnim: true, - hasTriple: - ugcIntroController.hasLike.value && - ugcIntroController.hasCoin && - ugcIntroController.hasFav.value, - callBack: (start) { - if (start) { - HapticFeedback.lightImpact(); - _coinKey.currentState?.controller?.forward(); - _favKey.currentState?.controller?.forward(); - } else { - _coinKey.currentState?.controller?.reverse(); - _favKey.currentState?.controller?.reverse(); - } - }, + controller: animController, + animation: animation, + onStartTriple: onStartTriple, + onCancelTriple: onCancelTriple, ), ), Obx( @@ -565,7 +560,6 @@ class _UgcIntroPanelState extends State ), Obx( () => ActionItem( - key: _coinKey, icon: const Icon(FontAwesomeIcons.b), selectIcon: const Icon(FontAwesomeIcons.b), onTap: () => handleState(ugcIntroController.actionCoinVideo), @@ -574,12 +568,12 @@ class _UgcIntroPanelState extends State text: !isLoading ? NumUtil.numFormat(videoDetail.stat!.coin) : null, - needAnim: true, + controller: animController, + animation: animation, ), ), Obx( () => ActionItem( - key: _favKey, icon: const Icon(FontAwesomeIcons.star), selectIcon: const Icon(FontAwesomeIcons.solidStar), onTap: () => ugcIntroController.showFavBottomSheet(context), @@ -592,7 +586,8 @@ class _UgcIntroPanelState extends State text: !isLoading ? NumUtil.numFormat(videoDetail.stat!.favorite) : null, - needAnim: true, + controller: animController, + animation: animation, ), ), Obx( @@ -980,4 +975,16 @@ class _UgcIntroPanelState extends State @override bool get wantKeepAlive => true; + + @override + bool get hasTriple => + ugcIntroController.hasLike.value && + ugcIntroController.hasCoin && + ugcIntroController.hasFav.value; + + @override + void onLike() => handleState(ugcIntroController.actionLikeVideo); + + @override + void onTriple() => handleState(ugcIntroController.actionTriple); } diff --git a/lib/pages/video/introduction/ugc/widgets/action_item.dart b/lib/pages/video/introduction/ugc/widgets/action_item.dart index 80e485a7..6b00e33c 100644 --- a/lib/pages/video/introduction/ugc/widgets/action_item.dart +++ b/lib/pages/video/introduction/ugc/widgets/action_item.dart @@ -1,106 +1,65 @@ -import 'dart:async'; -import 'dart:math'; +import 'dart:async' show Timer; +import 'dart:math' show pi; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show HapticFeedback; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -class ActionItem extends StatefulWidget { - final Icon icon; - final Icon? selectIcon; - final VoidCallback? onTap; - final VoidCallback? onLongPress; - final String? text; - final bool selectStatus; - final String semanticsLabel; - final bool needAnim; - final bool hasTriple; - final ValueChanged? callBack; - final bool expand; +mixin TripleAnimMixin + on SingleTickerProviderStateMixin { + late AnimationController animController; + late Animation animation; - const ActionItem({ - super.key, - required this.icon, - this.selectIcon, - this.onTap, - this.onLongPress, - this.text, - this.selectStatus = false, - this.needAnim = false, - this.hasTriple = false, - this.callBack, - required this.semanticsLabel, - this.expand = true, - }); - - @override - State createState() => ActionItemState(); -} - -class ActionItemState extends State - with SingleTickerProviderStateMixin { - AnimationController? controller; - Animation? _animation; - - late final _isThumbsUp = widget.semanticsLabel == '点赞'; late int _lastTime; Timer? _timer; - void _startLongPress() { + bool get hasTriple; + void onTriple(); + void onLike(); + + void initTriple() { + animController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 1500), + reverseDuration: const Duration(milliseconds: 400), + ); + + animation = Tween(begin: 0, end: -2 * pi).animate( + CurvedAnimation( + parent: animController, + curve: Curves.easeInOut, + ), + ); + } + + void onStartTriple() { _lastTime = DateTime.now().millisecondsSinceEpoch; _timer ??= Timer(const Duration(milliseconds: 200), () { - if (widget.hasTriple) { + if (hasTriple) { HapticFeedback.lightImpact(); SmartDialog.showToast('已经完成三连'); } else { - controller?.forward(); - widget.callBack?.call(true); + animController.forward().whenComplete(() { + animController.reset(); + onTriple(); + }); } cancelTimer(); }); } - void _cancelLongPress([bool isCancel = false]) { + void onCancelTriple(bool isCancel) { int duration = DateTime.now().millisecondsSinceEpoch - _lastTime; if (duration >= 200 && duration < 1500) { - if (!widget.hasTriple) { - controller?.reverse(); - widget.callBack?.call(false); + if (!hasTriple) { + animController.reverse(); } } else if (duration < 200) { cancelTimer(); if (!isCancel) { feedBack(); - widget.onTap?.call(); - } - } - } - - @override - void initState() { - super.initState(); - if (widget.needAnim) { - controller = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 1500), - reverseDuration: const Duration(milliseconds: 400), - )..addListener(listener); - - _animation = Tween(begin: 0, end: -2 * pi).animate( - CurvedAnimation( - parent: controller!, - curve: Curves.easeInOut, - ), - ); - } - } - - void listener() { - if (controller!.value == 1) { - controller!.reset(); - if (_isThumbsUp) { - widget.onLongPress?.call(); + onLike(); } } } @@ -110,13 +69,49 @@ class ActionItemState extends State _timer = null; } - @override - void dispose() { + void disposeTriple() { cancelTimer(); - controller?.removeListener(listener); - controller?.dispose(); - super.dispose(); + animController.dispose(); } +} + +class ActionItem extends StatefulWidget { + const ActionItem({ + super.key, + required this.icon, + this.selectIcon, + this.onTap, + this.onLongPress, + this.text, + this.selectStatus = false, + required this.semanticsLabel, + this.expand = true, + this.controller, + this.animation, + this.onStartTriple, + this.onCancelTriple, + }); + + final Icon icon; + final Icon? selectIcon; + final VoidCallback? onTap; + final VoidCallback? onLongPress; + final String? text; + final bool selectStatus; + final String semanticsLabel; + final bool expand; + final AnimationController? controller; + final Animation? animation; + final VoidCallback? onStartTriple; + final ValueChanged? onCancelTriple; + + @override + State createState() => ActionItemState(); +} + +class ActionItemState extends State + with SingleTickerProviderStateMixin { + late final _isThumbsUp = widget.onStartTriple != null; @override Widget build(BuildContext context) { @@ -155,9 +150,11 @@ class ActionItemState extends State widget.onTap?.call(); }, onLongPress: _isThumbsUp ? null : widget.onLongPress, - onTapDown: _isThumbsUp ? (details) => _startLongPress() : null, - onTapUp: _isThumbsUp ? (details) => _cancelLongPress() : null, - onTapCancel: _isThumbsUp ? () => _cancelLongPress(true) : null, + onTapDown: _isThumbsUp ? (details) => widget.onStartTriple!() : null, + onTapUp: _isThumbsUp + ? (details) => widget.onCancelTriple!(false) + : null, + onTapCancel: _isThumbsUp ? () => widget.onCancelTriple!(true) : null, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -165,14 +162,14 @@ class ActionItemState extends State clipBehavior: Clip.none, alignment: Alignment.center, children: [ - if (widget.needAnim) + if (widget.animation != null) AnimatedBuilder( - animation: _animation!, + animation: widget.animation!, builder: (context, child) => CustomPaint( size: const Size(28, 28), painter: _ArcPainter( color: theme.colorScheme.primary, - sweepAngle: _animation!.value, + sweepAngle: widget.animation!.value, ), ), ) diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 408de901..1737a4f1 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -37,7 +37,6 @@ import 'package:dio/dio.dart'; import 'package:document_file_save_plus/document_file_save_plus_platform_interface.dart'; import 'package:floating/floating.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart' show HapticFeedback; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; @@ -63,7 +62,8 @@ class HeaderControl extends StatefulWidget { State createState() => HeaderControlState(); } -class HeaderControlState extends State { +class HeaderControlState extends State + with SingleTickerProviderStateMixin, TripleAnimMixin { late final PlPlayerController plPlayerController = widget.controller; late final VideoDetailController videoDetailCtr = widget.videoDetailCtr; late final PlayUrlModel videoInfo = videoDetailCtr.data; @@ -80,8 +80,6 @@ class HeaderControlState extends State { Timer? clock; bool get isFullScreen => widget.controller.isFullScreen.value; Box setting = GStorage.setting; - late final _coinKey = GlobalKey(); - late final _favKey = GlobalKey(); @override void initState() { @@ -91,11 +89,13 @@ class HeaderControlState extends State { } else { pgcIntroController = Get.find(tag: heroTag); } + initTriple(); } @override void dispose() { clock?.cancel(); + disposeTriple(); super.dispose(); } @@ -2224,51 +2224,38 @@ class HeaderControlState extends State { ? Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - if (videoDetailCtr.isUgc) ...[ - SizedBox( - width: 42, - height: 34, - child: Obx( - () => ActionItem( - expand: false, - icon: const Icon( - FontAwesomeIcons.thumbsUp, - color: Colors.white, - ), - selectIcon: const Icon( - FontAwesomeIcons.solidThumbsUp, - ), - onTap: ugcIntroController.actionLikeVideo, - onLongPress: () { - ugcIntroController.actionOneThree(); - plPlayerController - ..isTriple = null - ..hideTaskControls(); - }, - selectStatus: ugcIntroController.hasLike.value, - semanticsLabel: '点赞', - needAnim: true, - hasTriple: - ugcIntroController.hasLike.value && - ugcIntroController.hasCoin && - ugcIntroController.hasFav.value, - callBack: (start) { - if (start) { - HapticFeedback.lightImpact(); - plPlayerController.isTriple = true; - _coinKey.currentState?.controller?.forward(); - _favKey.currentState?.controller?.forward(); - } else { - _coinKey.currentState?.controller?.reverse(); - _favKey.currentState?.controller?.reverse(); - plPlayerController - ..isTriple = null - ..hideTaskControls(); - } - }, + SizedBox( + width: 42, + height: 34, + child: Obx( + () => ActionItem( + expand: false, + icon: const Icon( + FontAwesomeIcons.thumbsUp, + color: Colors.white, ), + selectIcon: const Icon( + FontAwesomeIcons.solidThumbsUp, + ), + onTap: introController.actionLikeVideo, + selectStatus: introController.hasLike.value, + semanticsLabel: '点赞', + controller: animController, + animation: animation, + onStartTriple: () { + plPlayerController.isTriple = true; + onStartTriple(); + }, + onCancelTriple: (value) { + plPlayerController + ..isTriple = null + ..hideTaskControls(); + onCancelTriple(value); + }, ), ), + ), + if (videoDetailCtr.isUgc) SizedBox( width: 42, height: 34, @@ -2288,162 +2275,62 @@ class HeaderControlState extends State { ), ), ), - SizedBox( - width: 42, - height: 34, - child: Obx( - () => ActionItem( - key: _coinKey, - expand: false, - icon: const Icon( - FontAwesomeIcons.b, - color: Colors.white, - ), - selectIcon: const Icon(FontAwesomeIcons.b), - onTap: ugcIntroController.actionCoinVideo, - selectStatus: ugcIntroController.hasCoin, - semanticsLabel: '投币', - needAnim: true, - ), - ), - ), - SizedBox( - width: 42, - height: 34, - child: Obx( - () => ActionItem( - key: _favKey, - expand: false, - icon: const Icon( - FontAwesomeIcons.star, - color: Colors.white, - ), - selectIcon: const Icon(FontAwesomeIcons.solidStar), - onTap: () => - ugcIntroController.showFavBottomSheet(context), - onLongPress: () => ugcIntroController - .showFavBottomSheet(context, isLongPress: true), - selectStatus: ugcIntroController.hasFav.value, - semanticsLabel: '收藏', - needAnim: true, - ), - ), - ), - SizedBox( - width: 42, - height: 34, - child: ActionItem( + SizedBox( + width: 42, + height: 34, + child: Obx( + () => ActionItem( expand: false, icon: const Icon( - FontAwesomeIcons.shareFromSquare, + FontAwesomeIcons.b, color: Colors.white, ), - onTap: () => - ugcIntroController.actionShareVideo(context), - semanticsLabel: '分享', + selectIcon: const Icon(FontAwesomeIcons.b), + onTap: introController.actionCoinVideo, + selectStatus: introController.hasCoin, + semanticsLabel: '投币', + controller: animController, + animation: animation, ), ), - ] else ...[ - SizedBox( - width: 42, - height: 34, - child: Obx( - () => ActionItem( - expand: false, - icon: const Icon( - FontAwesomeIcons.thumbsUp, - color: Colors.white, - ), - selectIcon: const Icon( - FontAwesomeIcons.solidThumbsUp, - ), - onTap: pgcIntroController.actionLikeVideo, - onLongPress: () { - pgcIntroController.actionOneThree(); - plPlayerController - ..isTriple = null - ..hideTaskControls(); - }, - selectStatus: pgcIntroController.hasLike.value, - semanticsLabel: '点赞', - needAnim: true, - hasTriple: - pgcIntroController.hasLike.value && - pgcIntroController.hasCoin && - pgcIntroController.hasFav.value, - callBack: (start) { - if (start) { - HapticFeedback.lightImpact(); - plPlayerController.isTriple = true; - _coinKey.currentState?.controller?.forward(); - _favKey.currentState?.controller?.forward(); - } else { - _coinKey.currentState?.controller?.reverse(); - _favKey.currentState?.controller?.reverse(); - plPlayerController - ..isTriple = null - ..hideTaskControls(); - } - }, - ), - ), - ), - SizedBox( - width: 42, - height: 34, - child: Obx( - () => ActionItem( - expand: false, - key: _coinKey, - icon: const Icon( - FontAwesomeIcons.b, - color: Colors.white, - ), - selectIcon: const Icon(FontAwesomeIcons.b), - onTap: pgcIntroController.actionCoinVideo, - selectStatus: pgcIntroController.hasCoin, - semanticsLabel: '投币', - needAnim: true, - ), - ), - ), - SizedBox( - width: 42, - height: 34, - child: Obx( - () => ActionItem( - key: _favKey, - expand: false, - icon: const Icon( - FontAwesomeIcons.star, - color: Colors.white, - ), - selectIcon: const Icon(FontAwesomeIcons.solidStar), - onTap: () => - pgcIntroController.showFavBottomSheet(context), - onLongPress: () => pgcIntroController - .showFavBottomSheet(context, isLongPress: true), - selectStatus: pgcIntroController.hasFav.value, - semanticsLabel: '收藏', - needAnim: true, - ), - ), - ), - SizedBox( - width: 42, - height: 34, - child: ActionItem( + ), + SizedBox( + width: 42, + height: 34, + child: Obx( + () => ActionItem( expand: false, icon: const Icon( - FontAwesomeIcons.shareFromSquare, + FontAwesomeIcons.star, color: Colors.white, ), + selectIcon: const Icon(FontAwesomeIcons.solidStar), onTap: () => - pgcIntroController.actionShareVideo(context), - semanticsLabel: '转发', + introController.showFavBottomSheet(context), + onLongPress: () => introController.showFavBottomSheet( + context, + isLongPress: true, + ), + selectStatus: introController.hasFav.value, + semanticsLabel: '收藏', + controller: animController, + animation: animation, ), ), - ], + ), + SizedBox( + width: 42, + height: 34, + child: ActionItem( + expand: false, + icon: const Icon( + FontAwesomeIcons.shareFromSquare, + color: Colors.white, + ), + onTap: () => introController.actionShareVideo(context), + semanticsLabel: '分享', + ), + ), ], ) : const SizedBox.shrink(), @@ -2457,6 +2344,18 @@ class HeaderControlState extends State { ? Obx(() => _buildHeader(true)) : _buildHeader(false); } + + @override + bool get hasTriple => + introController.hasLike.value && + introController.hasCoin && + introController.hasFav.value; + + @override + void onLike() => introController.actionLikeVideo(); + + @override + void onTriple() => introController.actionTriple(); } class MSliderTrackShape extends RoundedRectSliderTrackShape {