opt action item

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-09 21:10:58 +08:00
parent 11c6745fd7
commit fac37e59aa
4 changed files with 104 additions and 151 deletions

View File

@@ -1,4 +1,3 @@
import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
@@ -44,25 +43,17 @@ class _PgcIntroPageState extends State<PgcIntroPage>
AutomaticKeepAliveClientMixin, AutomaticKeepAliveClientMixin,
SingleTickerProviderStateMixin, SingleTickerProviderStateMixin,
TripleAnimMixin { TripleAnimMixin {
late PgcIntroController pgcIntroController; @override
late PgcIntroController introController;
late VideoDetailController videoDetailCtr; late VideoDetailController videoDetailCtr;
bool isProcessing = false;
Future<void> handleState(FutureOr Function() action) async {
if (!isProcessing) {
isProcessing = true;
await action();
isProcessing = false;
}
}
@override @override
bool get wantKeepAlive => true; bool get wantKeepAlive => true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
pgcIntroController = Get.put(PgcIntroController(), tag: widget.heroTag); introController = Get.put(PgcIntroController(), tag: widget.heroTag);
videoDetailCtr = Get.find<VideoDetailController>(tag: widget.heroTag); videoDetailCtr = Get.find<VideoDetailController>(tag: widget.heroTag);
} }
@@ -70,7 +61,7 @@ class _PgcIntroPageState extends State<PgcIntroPage>
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final item = pgcIntroController.pgcItem; final item = introController.pgcItem;
final isLandscape = context.isLandscape; final isLandscape = context.isLandscape;
Widget sliver = SliverToBoxAdapter( Widget sliver = SliverToBoxAdapter(
child: Column( child: Column(
@@ -86,22 +77,21 @@ class _PgcIntroPageState extends State<PgcIntroPage>
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
// 点赞收藏转发 布局样式2 // 点赞收藏转发 布局样式2
if (pgcIntroController.isPgc) if (introController.isPgc) actionGrid(theme, item, introController),
actionGrid(theme, item, pgcIntroController),
// 番剧分集 // 番剧分集
if (item.episodes?.isNotEmpty == true) if (item.episodes?.isNotEmpty == true)
PgcPanel( PgcPanel(
heroTag: widget.heroTag, heroTag: widget.heroTag,
pages: item.episodes!, pages: item.episodes!,
cid: videoDetailCtr.cid.value, cid: videoDetailCtr.cid.value,
onChangeEpisode: pgcIntroController.onChangeEpisode, onChangeEpisode: introController.onChangeEpisode,
showEpisodes: widget.showEpisodes, showEpisodes: widget.showEpisodes,
newEp: item.newEp, newEp: item.newEp,
), ),
], ],
), ),
); );
if (!pgcIntroController.isPgc) { if (!introController.isPgc) {
sliver = SliverMainAxisGroup( sliver = SliverMainAxisGroup(
slivers: [ slivers: [
sliver, sliver,
@@ -181,18 +171,18 @@ class _PgcIntroPageState extends State<PgcIntroPage>
bottom: 6, bottom: 6,
left: null, left: null,
), ),
if (!pgcIntroController.isPgc) if (!introController.isPgc)
Positioned( Positioned(
right: 6, right: 6,
bottom: 6, bottom: 6,
child: Obx(() { child: Obx(() {
final isFav = pgcIntroController.isFav.value; final isFav = introController.isFav.value;
return iconButton( return iconButton(
context: context, context: context,
size: 28, size: 28,
iconSize: 26, iconSize: 26,
tooltip: '${isFav ? '取消' : ''}收藏', tooltip: '${isFav ? '取消' : ''}收藏',
onPressed: () => pgcIntroController.onFavPugv(isFav), onPressed: () => introController.onFavPugv(isFav),
icon: isFav ? Icons.star_rounded : Icons.star_border_rounded, icon: isFav ? Icons.star_rounded : Icons.star_border_rounded,
bgColor: isFav ? null : theme.colorScheme.onInverseSurface, bgColor: isFav ? null : theme.colorScheme.onInverseSurface,
iconColor: isFav ? null : theme.colorScheme.onSurfaceVariant, iconColor: isFav ? null : theme.colorScheme.onSurfaceVariant,
@@ -204,11 +194,11 @@ class _PgcIntroPageState extends State<PgcIntroPage>
} }
Widget _buildInfoPanel(bool isLandscape, ThemeData theme, PgcInfoModel item) { Widget _buildInfoPanel(bool isLandscape, ThemeData theme, PgcInfoModel item) {
if (pgcIntroController.isPgc) { if (introController.isPgc) {
Widget subBtn() => Obx( Widget subBtn() => Obx(
() { () {
final isFollowed = pgcIntroController.isFollowed.value; final isFollowed = introController.isFollowed.value;
final followStatus = pgcIntroController.followStatus.value; final followStatus = introController.followStatus.value;
return FilledButton.tonal( return FilledButton.tonal(
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
@@ -228,26 +218,26 @@ class _PgcIntroPageState extends State<PgcIntroPage>
if (isFollowed) { if (isFollowed) {
showPgcFollowDialog( showPgcFollowDialog(
context: context, context: context,
type: pgcIntroController.pgcType, type: introController.pgcType,
followStatus: followStatus, followStatus: followStatus,
onUpdateStatus: (followStatus) { onUpdateStatus: (followStatus) {
if (followStatus == -1) { if (followStatus == -1) {
pgcIntroController.pgcDel(); introController.pgcDel();
} else { } else {
pgcIntroController.pgcUpdate( introController.pgcUpdate(
followStatus, followStatus,
); );
} }
}, },
); );
} else { } else {
pgcIntroController.pgcAdd(); introController.pgcAdd();
} }
}, },
child: Text( child: Text(
isFollowed isFollowed
? '${pgcIntroController.pgcType}' ? '${introController.pgcType}'
: pgcIntroController.pgcType, : introController.pgcType,
), ),
); );
}, },
@@ -309,7 +299,7 @@ class _PgcIntroPageState extends State<PgcIntroPage>
return GestureDetector( return GestureDetector(
onTap: () => widget.showIntroDetail( onTap: () => widget.showIntroDetail(
item, item,
pgcIntroController.videoTags.value, introController.videoTags.value,
), ),
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: SizedBox( child: SizedBox(
@@ -413,7 +403,7 @@ class _PgcIntroPageState extends State<PgcIntroPage>
Widget actionGrid( Widget actionGrid(
ThemeData theme, ThemeData theme,
PgcInfoModel item, PgcInfoModel item,
PgcIntroController pgcIntroController, PgcIntroController introController,
) { ) {
return SizedBox( return SizedBox(
height: 48, height: 48,
@@ -423,9 +413,8 @@ class _PgcIntroPageState extends State<PgcIntroPage>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.thumbsUp), icon: const Icon(FontAwesomeIcons.thumbsUp),
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
onTap: () => handleState(pgcIntroController.actionLikeVideo), onTap: () => handleAction(introController.actionLikeVideo),
onLongPress: () => handleState(pgcIntroController.actionTriple), selectStatus: introController.hasLike.value,
selectStatus: pgcIntroController.hasLike.value,
semanticsLabel: '点赞', semanticsLabel: '点赞',
text: NumUtil.numFormat(item.stat!.like), text: NumUtil.numFormat(item.stat!.like),
controller: animController, controller: animController,
@@ -438,8 +427,8 @@ class _PgcIntroPageState extends State<PgcIntroPage>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.b), icon: const Icon(FontAwesomeIcons.b),
selectIcon: const Icon(FontAwesomeIcons.b), selectIcon: const Icon(FontAwesomeIcons.b),
onTap: () => handleState(pgcIntroController.actionCoinVideo), onTap: introController.actionCoinVideo,
selectStatus: pgcIntroController.hasCoin, selectStatus: introController.hasCoin,
semanticsLabel: '投币', semanticsLabel: '投币',
text: NumUtil.numFormat(item.stat!.coin), text: NumUtil.numFormat(item.stat!.coin),
controller: animController, controller: animController,
@@ -450,12 +439,12 @@ class _PgcIntroPageState extends State<PgcIntroPage>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.star), icon: const Icon(FontAwesomeIcons.star),
selectIcon: const Icon(FontAwesomeIcons.solidStar), selectIcon: const Icon(FontAwesomeIcons.solidStar),
onTap: () => pgcIntroController.showFavBottomSheet(context), onTap: () => introController.showFavBottomSheet(context),
onLongPress: () => pgcIntroController.showFavBottomSheet( onLongPress: () => introController.showFavBottomSheet(
context, context,
isLongPress: true, isLongPress: true,
), ),
selectStatus: pgcIntroController.hasFav.value, selectStatus: introController.hasFav.value,
semanticsLabel: '收藏', semanticsLabel: '收藏',
text: NumUtil.numFormat(item.stat!.favorite), text: NumUtil.numFormat(item.stat!.favorite),
controller: animController, controller: animController,
@@ -466,15 +455,15 @@ class _PgcIntroPageState extends State<PgcIntroPage>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.clock), icon: const Icon(FontAwesomeIcons.clock),
selectIcon: const Icon(FontAwesomeIcons.solidClock), selectIcon: const Icon(FontAwesomeIcons.solidClock),
onTap: () => handleState(pgcIntroController.viewLater), onTap: () => handleAction(introController.viewLater),
selectStatus: pgcIntroController.hasLater.value, selectStatus: introController.hasLater.value,
semanticsLabel: '再看', semanticsLabel: '再看',
text: '再看', text: '再看',
), ),
), ),
ActionItem( ActionItem(
icon: const Icon(FontAwesomeIcons.shareFromSquare), icon: const Icon(FontAwesomeIcons.shareFromSquare),
onTap: () => pgcIntroController.actionShareVideo(context), onTap: () => introController.actionShareVideo(context),
selectStatus: false, selectStatus: false,
semanticsLabel: '转发', semanticsLabel: '转发',
text: NumUtil.numFormat(item.stat!.share), text: NumUtil.numFormat(item.stat!.share),
@@ -483,16 +472,4 @@ class _PgcIntroPageState extends State<PgcIntroPage>
), ),
); );
} }
@override
bool get hasTriple =>
pgcIntroController.hasLike.value &&
pgcIntroController.hasCoin &&
pgcIntroController.hasFav.value;
@override
void onLike() => handleState(pgcIntroController.actionLikeVideo);
@override
void onTriple() => handleState(pgcIntroController.actionTriple);
} }

View File

@@ -1,5 +1,3 @@
import 'dart:async';
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/pendant_avatar.dart'; import 'package:PiliPlus/common/widgets/pendant_avatar.dart';
@@ -57,16 +55,15 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
AutomaticKeepAliveClientMixin, AutomaticKeepAliveClientMixin,
SingleTickerProviderStateMixin, SingleTickerProviderStateMixin,
TripleAnimMixin { TripleAnimMixin {
late UgcIntroController ugcIntroController; @override
late UgcIntroController introController;
late final VideoDetailController videoDetailCtr = late final VideoDetailController videoDetailCtr =
Get.find<VideoDetailController>(tag: widget.heroTag); Get.find<VideoDetailController>(tag: widget.heroTag);
bool isProcessing = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
ugcIntroController = Get.put(UgcIntroController(), tag: widget.heroTag); introController = Get.put(UgcIntroController(), tag: widget.heroTag);
} }
@override @override
@@ -95,8 +92,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
), ),
sliver: Obx( sliver: Obx(
() { () {
VideoDetailData videoDetail = VideoDetailData videoDetail = introController.videoDetail.value;
ugcIntroController.videoDetail.value;
bool isLoading = videoDetail.bvid == null; bool isLoading = videoDetail.bvid == null;
int? mid = videoDetail.owner?.mid; int? mid = videoDetail.owner?.mid;
return SliverToBoxAdapter( return SliverToBoxAdapter(
@@ -107,7 +103,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
return; return;
} }
feedBack(); feedBack();
ugcIntroController.expandableCtr.toggle(); introController.expandableCtr.toggle();
}, },
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -127,7 +123,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
if (mid != null) { if (mid != null) {
feedBack(); feedBack();
if (!isPortrait && if (!isPortrait &&
ugcIntroController introController
.horizontalMemberPage) { .horizontalMemberPage) {
widget.onShowMemberPage(mid); widget.onShowMemberPage(mid);
} else { } else {
@@ -146,7 +142,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
physics: ReloadScrollPhysics( physics: ReloadScrollPhysics(
controller: ugcIntroController, controller: introController,
), ),
child: Row( child: Row(
spacing: 25, spacing: 25,
@@ -170,7 +166,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
context, context,
isLoading, isLoading,
videoDetail, videoDetail,
ugcIntroController, introController,
), ),
), ),
], ],
@@ -182,7 +178,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
_buildVideoTitle(theme, videoDetail) _buildVideoTitle(theme, videoDetail)
else else
ExpandablePanel( ExpandablePanel(
controller: ugcIntroController.expandableCtr, controller: introController.expandableCtr,
collapsed: GestureDetector( collapsed: GestureDetector(
onLongPress: () { onLongPress: () {
Feedback.forLongPress(context); Feedback.forLongPress(context);
@@ -208,11 +204,11 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
_buildInfo(theme, videoDetail), _buildInfo(theme, videoDetail),
if (ugcIntroController.enableAi) _aiBtn, if (introController.enableAi) _aiBtn,
], ],
), ),
if (videoDetail.argueInfo?.argueMsg?.isNotEmpty == true && if (videoDetail.argueInfo?.argueMsg?.isNotEmpty == true &&
ugcIntroController.showArgueMsg) ...[ introController.showArgueMsg) ...[
const SizedBox(height: 2), const SizedBox(height: 2),
Text.rich( Text.rich(
TextSpan( TextSpan(
@@ -238,7 +234,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
), ),
], ],
ExpandablePanel( ExpandablePanel(
controller: ugcIntroController.expandableCtr, controller: introController.expandableCtr,
collapsed: const SizedBox.shrink(), collapsed: const SizedBox.shrink(),
expanded: Column( expanded: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -270,8 +266,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
), ),
], ],
Obx(() { Obx(() {
final videoTags = final videoTags = introController.videoTags.value;
ugcIntroController.videoTags.value;
if (videoTags.isNullOrEmpty) { if (videoTags.isNullOrEmpty) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
@@ -282,13 +277,13 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
theme: expandTheme, theme: expandTheme,
), ),
Obx( Obx(
() => ugcIntroController.status.value () => introController.status.value
? const SizedBox.shrink() ? const SizedBox.shrink()
: Center( : Center(
child: TextButton.icon( child: TextButton.icon(
icon: const Icon(Icons.refresh), icon: const Icon(Icons.refresh),
onPressed: () { onPressed: () {
ugcIntroController introController
..status.value = true ..status.value = true
..queryVideoIntro(); ..queryVideoIntro();
if (videoDetailCtr.videoUrl.isNullOrEmpty && if (videoDetailCtr.videoUrl.isNullOrEmpty &&
@@ -307,7 +302,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
context, context,
isLoading, isLoading,
videoDetail, videoDetail,
ugcIntroController, introController,
), ),
], ],
// 合集 // 合集
@@ -320,7 +315,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
SeasonPanel( SeasonPanel(
heroTag: widget.heroTag, heroTag: widget.heroTag,
showEpisodes: widget.showEpisodes, showEpisodes: widget.showEpisodes,
ugcIntroController: ugcIntroController, ugcIntroController: introController,
), ),
if (!isLoading && if (!isLoading &&
videoDetail.pages != null && videoDetail.pages != null &&
@@ -331,8 +326,8 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
.horizontalSeasonPanel)) ...[ .horizontalSeasonPanel)) ...[
PagesPanel( PagesPanel(
heroTag: widget.heroTag, heroTag: widget.heroTag,
ugcIntroController: ugcIntroController, ugcIntroController: introController,
bvid: ugcIntroController.bvid, bvid: introController.bvid,
showEpisodes: widget.showEpisodes, showEpisodes: widget.showEpisodes,
), ),
], ],
@@ -474,20 +469,12 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
return child(); return child();
} }
Future<void> handleState(FutureOr Function() action) async {
if (!isProcessing) {
isProcessing = true;
await action();
isProcessing = false;
}
}
Widget followButton(BuildContext context, ThemeData t) { Widget followButton(BuildContext context, ThemeData t) {
return Obx( return Obx(
() { () {
int attr = ugcIntroController.followStatus['attribute'] ?? 0; int attr = introController.followStatus['attribute'] ?? 0;
return TextButton( return TextButton(
onPressed: () => ugcIntroController.actionRelationMod(context), onPressed: () => introController.actionRelationMod(context),
style: TextButton.styleFrom( style: TextButton.styleFrom(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(vertical: -2.8), visualDensity: const VisualDensity(vertical: -2.8),
@@ -518,7 +505,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
BuildContext context, BuildContext context,
bool isLoading, bool isLoading,
VideoDetailData videoDetail, VideoDetailData videoDetail,
UgcIntroController ugcIntroController, UgcIntroController introController,
) { ) {
return SizedBox( return SizedBox(
height: 48, height: 48,
@@ -528,9 +515,8 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.thumbsUp), icon: const Icon(FontAwesomeIcons.thumbsUp),
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
onTap: () => handleState(ugcIntroController.actionLikeVideo), onTap: () => handleAction(introController.actionLikeVideo),
onLongPress: () => handleState(ugcIntroController.actionTriple), selectStatus: introController.hasLike.value,
selectStatus: ugcIntroController.hasLike.value,
semanticsLabel: '点赞', semanticsLabel: '点赞',
text: !isLoading text: !isLoading
? NumUtil.numFormat(videoDetail.stat!.like) ? NumUtil.numFormat(videoDetail.stat!.like)
@@ -545,8 +531,8 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.thumbsDown), icon: const Icon(FontAwesomeIcons.thumbsDown),
selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown), selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown),
onTap: () => handleState(ugcIntroController.actionDislikeVideo), onTap: () => handleAction(introController.actionDislikeVideo),
selectStatus: ugcIntroController.hasDislike.value, selectStatus: introController.hasDislike.value,
semanticsLabel: '点踩', semanticsLabel: '点踩',
text: "点踩", text: "点踩",
), ),
@@ -555,8 +541,8 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.b), icon: const Icon(FontAwesomeIcons.b),
selectIcon: const Icon(FontAwesomeIcons.b), selectIcon: const Icon(FontAwesomeIcons.b),
onTap: () => handleState(ugcIntroController.actionCoinVideo), onTap: introController.actionCoinVideo,
selectStatus: ugcIntroController.hasCoin, selectStatus: introController.hasCoin,
semanticsLabel: '投币', semanticsLabel: '投币',
text: !isLoading text: !isLoading
? NumUtil.numFormat(videoDetail.stat!.coin) ? NumUtil.numFormat(videoDetail.stat!.coin)
@@ -569,12 +555,12 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.star), icon: const Icon(FontAwesomeIcons.star),
selectIcon: const Icon(FontAwesomeIcons.solidStar), selectIcon: const Icon(FontAwesomeIcons.solidStar),
onTap: () => ugcIntroController.showFavBottomSheet(context), onTap: () => introController.showFavBottomSheet(context),
onLongPress: () => ugcIntroController.showFavBottomSheet( onLongPress: () => introController.showFavBottomSheet(
context, context,
isLongPress: true, isLongPress: true,
), ),
selectStatus: ugcIntroController.hasFav.value, selectStatus: introController.hasFav.value,
semanticsLabel: '收藏', semanticsLabel: '收藏',
text: !isLoading text: !isLoading
? NumUtil.numFormat(videoDetail.stat!.favorite) ? NumUtil.numFormat(videoDetail.stat!.favorite)
@@ -587,15 +573,15 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
() => ActionItem( () => ActionItem(
icon: const Icon(FontAwesomeIcons.clock), icon: const Icon(FontAwesomeIcons.clock),
selectIcon: const Icon(FontAwesomeIcons.solidClock), selectIcon: const Icon(FontAwesomeIcons.solidClock),
onTap: () => handleState(ugcIntroController.viewLater), onTap: () => handleAction(introController.viewLater),
selectStatus: ugcIntroController.hasLater.value, selectStatus: introController.hasLater.value,
semanticsLabel: '再看', semanticsLabel: '再看',
text: '再看', text: '再看',
), ),
), ),
ActionItem( ActionItem(
icon: const Icon(FontAwesomeIcons.shareFromSquare), icon: const Icon(FontAwesomeIcons.shareFromSquare),
onTap: () => ugcIntroController.actionShareVideo(context), onTap: () => introController.actionShareVideo(context),
selectStatus: false, selectStatus: false,
semanticsLabel: '分享', semanticsLabel: '分享',
text: !isLoading text: !isLoading
@@ -706,7 +692,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
onTap: () { onTap: () {
if (item.mid == ownerMid && if (item.mid == ownerMid &&
!isPortrait && !isPortrait &&
ugcIntroController.horizontalMemberPage) { introController.horizontalMemberPage) {
widget.onShowMemberPage(ownerMid); widget.onShowMemberPage(ownerMid);
} else { } else {
Get.toNamed( Get.toNamed(
@@ -750,9 +736,8 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
right: -6, right: -6,
child: Obx( child: Obx(
() => () =>
ugcIntroController.staffRelations['status'] == true && introController.staffRelations['status'] == true &&
ugcIntroController.staffRelations['${item.mid}'] == introController.staffRelations['${item.mid}'] == null
null
? Material( ? Material(
type: MaterialType.transparency, type: MaterialType.transparency,
shape: const CircleBorder(), shape: const CircleBorder(),
@@ -763,8 +748,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
mid: item.mid, mid: item.mid,
isFollow: false, isFollow: false,
callback: (val) { callback: (val) {
ugcIntroController introController.staffRelations['${item.mid}'] =
.staffRelations['${item.mid}'] =
true; true;
}, },
), ),
@@ -825,7 +809,7 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: Obx( child: Obx(
() { () {
final userStat = ugcIntroController.userStat.value; final userStat = introController.userStat.value;
final isVip = (userStat.card?.vip?.status ?? 0) > 0; final isVip = (userStat.card?.vip?.status ?? 0) > 0;
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@@ -895,10 +879,10 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
color: theme.colorScheme.outline, color: theme.colorScheme.outline,
semanticLabel: '无痕', semanticLabel: '无痕',
), ),
if (ugcIntroController.isShowOnlineTotal) if (introController.isShowOnlineTotal)
Obx( Obx(
() => Text( () => Text(
'${ugcIntroController.total.value}人在看', '${introController.total.value}人在看',
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: theme.colorScheme.outline, color: theme.colorScheme.outline,
@@ -917,15 +901,15 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
label: 'AI总结', label: 'AI总结',
child: GestureDetector( child: GestureDetector(
onTap: () async { onTap: () async {
if (ugcIntroController.aiConclusionResult == null) { if (introController.aiConclusionResult == null) {
await ugcIntroController.aiConclusion(); await introController.aiConclusion();
} }
if (ugcIntroController.aiConclusionResult == null) { if (introController.aiConclusionResult == null) {
return; return;
} }
if (ugcIntroController.aiConclusionResult!.summary?.isNotEmpty == if (introController.aiConclusionResult!.summary?.isNotEmpty ==
true || true ||
ugcIntroController.aiConclusionResult!.outline?.isNotEmpty == introController.aiConclusionResult!.outline?.isNotEmpty ==
true) { true) {
widget.showAiBottomSheet(); widget.showAiBottomSheet();
} else { } else {
@@ -968,16 +952,4 @@ class _UgcIntroPanelState extends State<UgcIntroPanel>
@override @override
bool get wantKeepAlive => true; 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);
} }

View File

@@ -1,6 +1,7 @@
import 'dart:async' show Timer; import 'dart:async' show Timer, FutureOr;
import 'dart:math' show pi; import 'dart:math' show pi;
import 'package:PiliPlus/pages/common/common_intro_controller.dart';
import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/feed_back.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show HapticFeedback; import 'package:flutter/services.dart' show HapticFeedback;
@@ -8,15 +9,26 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
mixin TripleAnimMixin<T extends StatefulWidget> mixin TripleAnimMixin<T extends StatefulWidget>
on SingleTickerProviderStateMixin<T> { on SingleTickerProviderStateMixin<T> {
CommonIntroController get introController;
late AnimationController animController; late AnimationController animController;
late Animation<double> animation; late Animation<double> animation;
late int _lastTime; late int _lastTime;
Timer? _timer; Timer? _timer;
bool get hasTriple; bool get _hasTriple =>
void onTriple(); introController.hasLike.value &&
void onLike(); introController.hasCoin &&
introController.hasFav.value;
bool isProcessing = false;
Future<void> handleAction(FutureOr Function() action) async {
if (!isProcessing) {
isProcessing = true;
await action();
isProcessing = false;
}
}
@override @override
void initState() { void initState() {
@@ -38,13 +50,13 @@ mixin TripleAnimMixin<T extends StatefulWidget>
void onStartTriple() { void onStartTriple() {
_lastTime = DateTime.now().millisecondsSinceEpoch; _lastTime = DateTime.now().millisecondsSinceEpoch;
_timer ??= Timer(const Duration(milliseconds: 200), () { _timer ??= Timer(const Duration(milliseconds: 200), () {
if (hasTriple) {
HapticFeedback.lightImpact(); HapticFeedback.lightImpact();
if (_hasTriple) {
SmartDialog.showToast('已经完成三连'); SmartDialog.showToast('已经完成三连');
} else { } else {
animController.forward().whenComplete(() { animController.forward().whenComplete(() {
animController.reset(); animController.reset();
onTriple(); handleAction(introController.actionTriple);
}); });
} }
cancelTimer(); cancelTimer();
@@ -54,14 +66,14 @@ mixin TripleAnimMixin<T extends StatefulWidget>
void onCancelTriple(bool isCancel) { void onCancelTriple(bool isCancel) {
int duration = DateTime.now().millisecondsSinceEpoch - _lastTime; int duration = DateTime.now().millisecondsSinceEpoch - _lastTime;
if (duration >= 200 && duration < 1500) { if (duration >= 200 && duration < 1500) {
if (!hasTriple) { if (!_hasTriple) {
animController.reverse(); animController.reverse();
} }
} else if (duration < 200) { } else if (duration < 200) {
cancelTimer(); cancelTimer();
if (!isCancel) { if (!isCancel) {
feedBack(); feedBack();
onLike(); handleAction(introController.actionLikeVideo);
} }
} }
} }

View File

@@ -72,6 +72,7 @@ class HeaderControlState extends State<HeaderControl>
String get heroTag => widget.heroTag; String get heroTag => widget.heroTag;
late final UgcIntroController ugcIntroController; late final UgcIntroController ugcIntroController;
late final PgcIntroController pgcIntroController; late final PgcIntroController pgcIntroController;
@override
late final CommonIntroController introController = videoDetailCtr.isUgc late final CommonIntroController introController = videoDetailCtr.isUgc
? ugcIntroController ? ugcIntroController
: pgcIntroController; : pgcIntroController;
@@ -2235,7 +2236,8 @@ class HeaderControlState extends State<HeaderControl>
selectIcon: const Icon( selectIcon: const Icon(
FontAwesomeIcons.solidThumbsUp, FontAwesomeIcons.solidThumbsUp,
), ),
onTap: introController.actionLikeVideo, onTap: () =>
handleAction(introController.actionLikeVideo),
selectStatus: introController.hasLike.value, selectStatus: introController.hasLike.value,
semanticsLabel: '点赞', semanticsLabel: '点赞',
controller: animController, controller: animController,
@@ -2267,7 +2269,9 @@ class HeaderControlState extends State<HeaderControl>
selectIcon: const Icon( selectIcon: const Icon(
FontAwesomeIcons.solidThumbsDown, FontAwesomeIcons.solidThumbsDown,
), ),
onTap: ugcIntroController.actionDislikeVideo, onTap: () => handleAction(
ugcIntroController.actionDislikeVideo,
),
selectStatus: ugcIntroController.hasDislike.value, selectStatus: ugcIntroController.hasDislike.value,
semanticsLabel: '点踩', semanticsLabel: '点踩',
), ),
@@ -2342,18 +2346,6 @@ class HeaderControlState extends State<HeaderControl>
? Obx(() => _buildHeader(true)) ? Obx(() => _buildHeader(true))
: _buildHeader(false); : _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 { class MSliderTrackShape extends RoundedRectSliderTrackShape {