mod: 视频简介与相关视频实现方式微调

This commit is contained in:
orz12
2024-07-11 17:48:15 +08:00
parent 815716c402
commit 17e9f00eca
2 changed files with 252 additions and 255 deletions

View File

@@ -1,4 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
@@ -17,6 +18,7 @@ import 'package:PiliPalaX/pages/video/detail/widgets/ai_detail.dart';
import 'package:PiliPalaX/utils/feed_back.dart';
import 'package:PiliPalaX/utils/storage.dart';
import 'package:PiliPalaX/utils/utils.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'widgets/action_item.dart';
import 'widgets/action_row_item.dart';
@@ -93,7 +95,18 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
snapshot.data['code'] == 62002
? '上一页'
: null,
fn: () => Get.back(),
fn: () {
if (snapshot.data['code'] == -404 ||
snapshot.data['code'] == 62002) {
Get.back();
return;
}
_futureBuilderFuture = videoIntroController.queryVideoIntro();
_futureBuilderFuture!.then((value) {
videoIntroController.videoDetail.refresh();
setState(() {});
});
},
);
}
} else {
@@ -245,273 +258,253 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
final ThemeData t = Theme.of(context);
final Color outline = t.colorScheme.outline;
bool isHorizontal = context.width > context.height * 1.25;
return SliverPadding(
padding: const EdgeInsets.only(
left: StyleString.safeSpace, right: StyleString.safeSpace, top: 10),
sliver: SliverToBoxAdapter(
child: !loadingStatus
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(children: [
Expanded(
child: GestureDetector(
onTap: onPushMember,
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 1, horizontal: 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
NetworkImgLayer(
type: 'avatar',
src: loadingStatus
? owner.face
: widget.videoDetail!.owner!.face,
width: 30,
height: 30,
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
),
const SizedBox(width: 10),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
owner.name,
style: TextStyle(
fontSize: 12,
color: t.colorScheme.primary),
// semanticsLabel: "Up主${owner.name}",
),
const SizedBox(height: 0),
Text(
follower,
semanticsLabel: "$follower粉丝",
style: TextStyle(
fontSize: 12,
color: outline,
),
),
]),
const Spacer(),
Obx(() => AnimatedOpacity(
opacity: loadingStatus ||
videoIntroController
.followStatus.isEmpty
? 0
: 1,
duration: const Duration(milliseconds: 50),
child: SizedBox(
height: 32,
child: Obx(
() => videoIntroController
.followStatus.isNotEmpty
? TextButton(
onPressed: () =>
videoIntroController
.actionRelationMod(
context),
style: TextButton.styleFrom(
padding: const EdgeInsets.only(
left: 8, right: 8),
foregroundColor:
followStatus['attribute'] !=
0
? outline
: t.colorScheme
.onPrimary,
backgroundColor:
followStatus['attribute'] !=
0
? t.colorScheme
.onInverseSurface
: t.colorScheme
.primary, // 设置按钮背景色
),
child: Text(
followStatus['attribute'] != 0
? '已关注'
: '关注',
style: TextStyle(
fontSize: t.textTheme
.labelMedium!.fontSize),
),
)
: ElevatedButton(
onPressed: () =>
videoIntroController
.actionRelationMod(
context),
child: const Text('关注'),
),
),
),
)),
],
),
),
)),
if (isHorizontal)
Expanded(
child: actionGrid(context, videoIntroController)),
]),
const SizedBox(height: 8),
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => showIntroDetail(),
child: Row(children: [
Expanded(
child: Text(
!loadingStatus
? widget.videoDetail!.title
: videoItem['title'],
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
)),
Icon(
Icons.arrow_forward_ios,
size: 16,
color: t.colorScheme.outline,
),
]),
),
Stack(
return SliverLayoutBuilder(
builder: (BuildContext context, SliverConstraints constraints) {
bool isHorizontal = constraints.crossAxisExtent >
constraints.viewportMainAxisExtent * 1.25;
return SliverPadding(
padding: const EdgeInsets.only(
left: StyleString.safeSpace,
right: StyleString.safeSpace,
top: 10),
sliver: SliverToBoxAdapter(
child: !loadingStatus
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(children: [
Expanded(
child: GestureDetector(
onTap: onPushMember,
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 1, horizontal: 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
NetworkImgLayer(
type: 'avatar',
src: loadingStatus
? owner.face
: widget.videoDetail!.owner!.face,
width: 30,
height: 30,
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
owner.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12,
color: t.colorScheme.primary),
// semanticsLabel: "Up主${owner.name}",
),
const SizedBox(height: 0),
Text(
follower,
semanticsLabel: "$follower粉丝",
style: TextStyle(
fontSize: 12,
color: t.colorScheme.outline,
),
),
],
)),
followButton(context, t),
],
),
),
)),
if (isHorizontal) ...[
const SizedBox(width: 10),
Expanded(
child: actionGrid(context, videoIntroController)),
]
]),
const SizedBox(height: 8),
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => showIntroDetail(),
child: Padding(
padding: const EdgeInsets.only(top: 7, bottom: 6),
child: Row(
children: <Widget>[
StatView(
theme: 'gray',
view: !loadingStatus
? widget.videoDetail!.stat!.view
: videoItem['stat'].view,
size: 'medium',
),
const SizedBox(width: 10),
StatDanMu(
theme: 'gray',
danmu: !loadingStatus
? widget.videoDetail!.stat!.danmu
: videoItem['stat'].danmu,
size: 'medium',
),
const SizedBox(width: 10),
Text(
Utils.dateFormat(
!loadingStatus
? widget.videoDetail!.pubdate
: videoItem['pubdate'],
formatType: 'detail'),
style: TextStyle(
fontSize: 12,
color: t.colorScheme.outline,
),
),
if (MineController.anonymity) ...<Widget>[
const SizedBox(width: 10),
Icon(
CupertinoIcons.checkmark_shield,
size: 15,
color: t.colorScheme.outline,
),
Text(
'无痕',
style: TextStyle(
fontSize: 12,
color: t.colorScheme.outline),
),
],
const SizedBox(width: 10),
if (videoIntroController.isShowOnlineTotal)
Obx(
() => Text(
'${videoIntroController.total.value}人在看',
child: Row(children: [
Expanded(
child: Text(
!loadingStatus
? widget.videoDetail!.title
: videoItem['title'],
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
)),
Icon(
Icons.arrow_forward_ios,
size: 16,
color: t.colorScheme.outline,
),
]),
),
Stack(
children: [
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => showIntroDetail(),
child: Padding(
padding: const EdgeInsets.only(top: 7, bottom: 6),
child: Row(
children: <Widget>[
StatView(
theme: 'gray',
view: !loadingStatus
? widget.videoDetail!.stat!.view
: videoItem['stat'].view,
size: 'medium',
),
const SizedBox(width: 10),
StatDanMu(
theme: 'gray',
danmu: !loadingStatus
? widget.videoDetail!.stat!.danmu
: videoItem['stat'].danmu,
size: 'medium',
),
const SizedBox(width: 10),
Text(
Utils.dateFormat(
!loadingStatus
? widget.videoDetail!.pubdate
: videoItem['pubdate'],
formatType: 'detail'),
style: TextStyle(
fontSize: 12,
color: t.colorScheme.outline,
),
),
),
],
if (MineController.anonymity) ...<Widget>[
const SizedBox(width: 10),
Icon(
MdiIcons.incognito,
size: 15,
color: t.colorScheme.outline,
semanticLabel: '无痕',
),
],
const SizedBox(width: 10),
if (videoIntroController.isShowOnlineTotal)
Obx(
() => Text(
'${videoIntroController.total.value}人在看',
style: TextStyle(
fontSize: 12,
color: t.colorScheme.outline,
),
),
),
],
),
),
),
),
if (enableAi)
Positioned(
right: 10,
top: 6,
child: Semantics(
label: 'AI总结',
child: GestureDetector(
onTap: () async {
final res = await videoIntroController
.aiConclusion();
if (res['status']) {
showAiBottomSheet();
}
},
child: Image.asset('assets/images/ai.png',
height: 22),
)),
)
],
),
if (enableAi)
Positioned(
right: 10,
top: 6,
child: Semantics(
label: 'AI总结',
child: GestureDetector(
onTap: () async {
final res =
await videoIntroController.aiConclusion();
if (res['status']) {
showAiBottomSheet();
}
},
child: Image.asset('assets/images/ai.png',
height: 22),
)),
// 点赞收藏转发 布局样式1
// SingleChildScrollView(
// padding: const EdgeInsets.only(top: 7, bottom: 7),
// scrollDirection: Axis.horizontal,
// child: actionRow(
// context,
// videoIntroController,
// videoDetailCtr,
// ),
// ),
// 点赞收藏转发 布局样式2
if (!isHorizontal)
actionGrid(context, videoIntroController),
// 合集
if (!loadingStatus &&
widget.videoDetail!.ugcSeason != null) ...[
Obx(
() => SeasonPanel(
heroTag: heroTag,
ugcSeason: widget.videoDetail!.ugcSeason!,
cid: videoIntroController.lastPlayCid.value != 0
? videoIntroController.lastPlayCid.value
: widget.videoDetail!.pages!.first.cid,
changeFuc: videoIntroController.changeSeasonOrbangu,
),
)
],
if (!loadingStatus &&
widget.videoDetail!.pages != null &&
widget.videoDetail!.pages!.length > 1) ...[
Obx(() => PagesPanel(
heroTag: heroTag,
pages: widget.videoDetail!.pages!,
cid: videoIntroController.lastPlayCid.value,
bvid: videoIntroController.bvid,
changeFuc:
videoIntroController.changeSeasonOrbangu,
))
],
],
)
: const SizedBox(
height: 130,
child: Center(
child: CircularProgressIndicator(),
),
),
// 点赞收藏转发 布局样式1
// SingleChildScrollView(
// padding: const EdgeInsets.only(top: 7, bottom: 7),
// scrollDirection: Axis.horizontal,
// child: actionRow(
// context,
// videoIntroController,
// videoDetailCtr,
// ),
// ),
// 点赞收藏转发 布局样式2
if (!isHorizontal) actionGrid(context, videoIntroController),
// 合集
if (!loadingStatus &&
widget.videoDetail!.ugcSeason != null) ...[
Obx(
() => SeasonPanel(
heroTag: heroTag,
ugcSeason: widget.videoDetail!.ugcSeason!,
cid: videoIntroController.lastPlayCid.value != 0
? videoIntroController.lastPlayCid.value
: widget.videoDetail!.pages!.first.cid,
changeFuc: videoIntroController.changeSeasonOrbangu,
),
)
],
if (!loadingStatus &&
widget.videoDetail!.pages != null &&
widget.videoDetail!.pages!.length > 1) ...[
Obx(() => PagesPanel(
heroTag: heroTag,
pages: widget.videoDetail!.pages!,
cid: videoIntroController.lastPlayCid.value,
bvid: videoIntroController.bvid,
changeFuc: videoIntroController.changeSeasonOrbangu,
))
],
],
)
: const SizedBox(
height: 130,
child: Center(
child: CircularProgressIndicator(),
),
),
),
);
},
);
}
Obx followButton(BuildContext context, ThemeData t) {
return Obx(
() => TextButton(
onPressed: () => videoIntroController.actionRelationMod(context),
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
padding: const EdgeInsets.only(left: 6, right: 6),
foregroundColor: (followStatus?['attribute'] ?? 0) != 0
? t.colorScheme.outline
: t.colorScheme.onPrimary,
backgroundColor: (followStatus?['attribute'] ?? 0) != 0
? t.colorScheme.onInverseSurface
: t.colorScheme.primary, // 设置按钮背景色
),
child: Text(
((followStatus?['attribute'] ?? 0) != 0) ? '已关注' : '关注',
style: TextStyle(fontSize: t.textTheme.labelMedium!.fontSize),
),
),
);
}
@@ -530,6 +523,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
icon: const Icon(FontAwesomeIcons.thumbsUp),
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
onTap: handleState(videoIntroController.actionLikeVideo),
onLongPress: handleState(videoIntroController.actionOneThree),
selectStatus: videoIntroController.hasLike.value,
loadingStatus: loadingStatus,
semanticsLabel: '点赞',

View File

@@ -85,7 +85,10 @@ class _RelatedVideoPanelState extends State<RelatedVideoPanel>
);
} else {
// 请求错误
return HttpError(errMsg: '出错了', fn: () {});
return HttpError(errMsg: '出错了', fn: () {
_futureBuilder = _relatedController.queryRelatedVideo();
_futureBuilder.then((value) => setState(() {}));
});
}
} else {
// 骨架屏