mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-19 01:56:53 +08:00
@@ -35,8 +35,8 @@ class PgcIntroController extends CommonIntroController {
|
||||
|
||||
late dynamic type =
|
||||
Get.parameters['type'] == '1' || Get.parameters['type'] == '4'
|
||||
? '追番'
|
||||
: '追剧';
|
||||
? '追番'
|
||||
: '追剧';
|
||||
|
||||
final PgcInfoModel pgcItem = Get.arguments['pgcItem'];
|
||||
|
||||
@@ -190,65 +190,66 @@ class PgcIntroController extends CommonIntroController {
|
||||
// 分享视频
|
||||
void actionShareVideo(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
String videoUrl = '${HttpString.baseUrl}/bangumi/play/ep$epId';
|
||||
return AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'复制链接',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.copyText(videoUrl);
|
||||
},
|
||||
context: context,
|
||||
builder: (_) {
|
||||
String videoUrl = '${HttpString.baseUrl}/bangumi/play/ep$epId';
|
||||
return AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'复制链接',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'其它app打开',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
PageUtils.launchURL(videoUrl);
|
||||
},
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.copyText(videoUrl);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'其它app打开',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享视频',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.shareText(videoUrl);
|
||||
},
|
||||
onTap: () {
|
||||
Get.back();
|
||||
PageUtils.launchURL(videoUrl);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享视频',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至动态',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
EpisodeItem? item = pgcItem.episodes
|
||||
?.firstWhereOrNull((item) => item.epId == epId);
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (context) => RepostPanel(
|
||||
rid: epId,
|
||||
/**
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.shareText(videoUrl);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至动态',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
EpisodeItem? item = pgcItem.episodes?.firstWhereOrNull(
|
||||
(item) => item.epId == epId,
|
||||
);
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (context) => RepostPanel(
|
||||
rid: epId,
|
||||
/**
|
||||
* 1:番剧 // 4097
|
||||
2:电影 // 4098
|
||||
3:纪录片 // 4101
|
||||
@@ -257,64 +258,66 @@ class PgcIntroController extends CommonIntroController {
|
||||
6:漫画
|
||||
7:综艺 // 4099
|
||||
*/
|
||||
dynType: switch (Get.parameters['type']) {
|
||||
'1' => 4097,
|
||||
'2' => 4098,
|
||||
'3' => 4101,
|
||||
'4' => 4100,
|
||||
'5' || '7' => 4099,
|
||||
_ => -1,
|
||||
},
|
||||
pic: pgcItem.cover,
|
||||
title:
|
||||
'${pgcItem.title}${item != null ? '\n${item.showTitle}' : ''}',
|
||||
uname: '',
|
||||
),
|
||||
dynType: switch (Get.parameters['type']) {
|
||||
'1' => 4097,
|
||||
'2' => 4098,
|
||||
'3' => 4101,
|
||||
'4' => 4100,
|
||||
'5' || '7' => 4099,
|
||||
_ => -1,
|
||||
},
|
||||
pic: pgcItem.cover,
|
||||
title:
|
||||
'${pgcItem.title}${item != null ? '\n${item.showTitle}' : ''}',
|
||||
uname: '',
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至消息',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
try {
|
||||
EpisodeItem item = pgcItem.episodes!.firstWhere(
|
||||
(item) => item.epId == epId,
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至消息',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
try {
|
||||
EpisodeItem item = pgcItem.episodes!
|
||||
.firstWhere((item) => item.epId == epId);
|
||||
final title = '${item.title!} ${item.showTitle}';
|
||||
PageUtils.pmShare(
|
||||
context,
|
||||
content: {
|
||||
"id": epId!.toString(),
|
||||
"title": title,
|
||||
"url": item.shareUrl,
|
||||
"headline": title,
|
||||
"source": 16,
|
||||
"thumb": item.cover,
|
||||
"source_desc": switch (pgcItem.type) {
|
||||
1 => '番剧',
|
||||
2 => '电影',
|
||||
3 => '纪录片',
|
||||
4 => '国创',
|
||||
5 => '电视剧',
|
||||
6 => '漫画',
|
||||
7 => '综艺',
|
||||
_ => null,
|
||||
}
|
||||
final title = '${item.title!} ${item.showTitle}';
|
||||
PageUtils.pmShare(
|
||||
context,
|
||||
content: {
|
||||
"id": epId!.toString(),
|
||||
"title": title,
|
||||
"url": item.shareUrl,
|
||||
"headline": title,
|
||||
"source": 16,
|
||||
"thumb": item.cover,
|
||||
"source_desc": switch (pgcItem.type) {
|
||||
1 => '番剧',
|
||||
2 => '电影',
|
||||
3 => '纪录片',
|
||||
4 => '国创',
|
||||
5 => '电视剧',
|
||||
6 => '漫画',
|
||||
7 => '综艺',
|
||||
_ => null,
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast(e.toString());
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast(e.toString());
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 修改分P或番剧分集
|
||||
@@ -409,10 +412,12 @@ class PgcIntroController extends CommonIntroController {
|
||||
|
||||
bool prevPlay() {
|
||||
List episodes = pgcItem.episodes!;
|
||||
VideoDetailController videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||
int currentIndex =
|
||||
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value);
|
||||
VideoDetailController videoDetailCtr = Get.find<VideoDetailController>(
|
||||
tag: Get.arguments['heroTag'],
|
||||
);
|
||||
int currentIndex = episodes.indexWhere(
|
||||
(e) => e.cid == videoDetailCtr.cid.value,
|
||||
);
|
||||
int prevIndex = currentIndex - 1;
|
||||
PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
if (prevIndex < 0) {
|
||||
@@ -435,12 +440,14 @@ class PgcIntroController extends CommonIntroController {
|
||||
bool nextPlay() {
|
||||
try {
|
||||
List episodes = pgcItem.episodes!;
|
||||
VideoDetailController videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: Get.arguments['heroTag']);
|
||||
VideoDetailController videoDetailCtr = Get.find<VideoDetailController>(
|
||||
tag: Get.arguments['heroTag'],
|
||||
);
|
||||
PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
|
||||
int currentIndex =
|
||||
episodes.indexWhere((e) => e.cid == videoDetailCtr.cid.value);
|
||||
int currentIndex = episodes.indexWhere(
|
||||
(e) => e.cid == videoDetailCtr.cid.value,
|
||||
);
|
||||
int nextIndex = currentIndex + 1;
|
||||
// 列表循环
|
||||
if (nextIndex >= episodes.length) {
|
||||
|
||||
@@ -96,7 +96,7 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
imgList: [
|
||||
SourceModel(
|
||||
url: item.cover!,
|
||||
)
|
||||
),
|
||||
],
|
||||
onDismissed: videoDetailCtr.onDismissed,
|
||||
);
|
||||
@@ -124,7 +124,9 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => widget.showIntroDetail(
|
||||
item, pgcIntroController.videoTags.value),
|
||||
item,
|
||||
pgcIntroController.videoTags.value,
|
||||
),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: SizedBox(
|
||||
height: isLandscape ? 115 : 115 / 0.75,
|
||||
@@ -182,7 +184,8 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
} else {
|
||||
pgcIntroController
|
||||
.pgcUpdate(
|
||||
followStatus);
|
||||
followStatus,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -214,7 +217,7 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
if (isLandscape) ...[
|
||||
areasAndPubTime(theme, item),
|
||||
newEpDesc(theme, item),
|
||||
]
|
||||
],
|
||||
],
|
||||
),
|
||||
SizedBox(height: isLandscape ? 2 : 6),
|
||||
@@ -251,7 +254,7 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
changeFuc: pgcIntroController.changeSeasonOrbangu,
|
||||
showEpisodes: widget.showEpisodes,
|
||||
newEp: item.newEp,
|
||||
)
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
@@ -259,8 +262,11 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget actionGrid(ThemeData theme, PgcInfoModel item,
|
||||
PgcIntroController pgcIntroController) {
|
||||
Widget actionGrid(
|
||||
ThemeData theme,
|
||||
PgcInfoModel item,
|
||||
PgcIntroController pgcIntroController,
|
||||
) {
|
||||
return SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
@@ -275,7 +281,8 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
semanticsLabel: '点赞',
|
||||
text: NumUtil.numFormat(item.stat!.likes),
|
||||
needAnim: true,
|
||||
hasTriple: pgcIntroController.hasLike.value &&
|
||||
hasTriple:
|
||||
pgcIntroController.hasLike.value &&
|
||||
pgcIntroController.hasCoin &&
|
||||
pgcIntroController.hasFav.value,
|
||||
callBack: (start) {
|
||||
@@ -308,8 +315,10 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
onTap: () => pgcIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => pgcIntroController.showFavBottomSheet(context,
|
||||
type: 'longPress'),
|
||||
onLongPress: () => pgcIntroController.showFavBottomSheet(
|
||||
context,
|
||||
type: 'longPress',
|
||||
),
|
||||
selectStatus: pgcIntroController.hasFav.value,
|
||||
semanticsLabel: '收藏',
|
||||
text: NumUtil.numFormat(item.stat!.favorite),
|
||||
|
||||
@@ -55,7 +55,10 @@ class _IntroDetailState extends CommonCollapseSlidePageState<PgcIntroPanel> {
|
||||
isScrollable: true,
|
||||
tabAlignment: TabAlignment.start,
|
||||
dividerColor: Colors.transparent,
|
||||
tabs: const [Tab(text: '详情'), Tab(text: '点评')],
|
||||
tabs: const [
|
||||
Tab(text: '详情'),
|
||||
Tab(text: '点评'),
|
||||
],
|
||||
onTap: (index) {
|
||||
if (!_tabController.indexIsChanging) {
|
||||
if (index == 0) {
|
||||
@@ -176,7 +179,7 @@ class _IntroDetailState extends CommonCollapseSlidePageState<PgcIntroPanel> {
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
)
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
|
||||
@@ -72,8 +72,10 @@ class _PgcPanelState extends State<PgcPanel> {
|
||||
void scrollToIndex() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
listViewScrollCtr.animateTo(
|
||||
(currentIndex * 150.0).clamp(listViewScrollCtr.position.minScrollExtent,
|
||||
listViewScrollCtr.position.maxScrollExtent),
|
||||
(currentIndex * 150.0).clamp(
|
||||
listViewScrollCtr.position.minScrollExtent,
|
||||
listViewScrollCtr.position.maxScrollExtent,
|
||||
),
|
||||
duration: const Duration(milliseconds: 500),
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
@@ -162,7 +164,9 @@ class _PgcPanelState extends State<PgcPanel> {
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 10),
|
||||
vertical: 8,
|
||||
horizontal: 10,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@@ -175,21 +179,24 @@ class _PgcPanelState extends State<PgcPanel> {
|
||||
height: 12,
|
||||
semanticLabel: "正在播放:",
|
||||
),
|
||||
const SizedBox(width: 6)
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
Expanded(
|
||||
child: Text(
|
||||
item.title ?? '第${index + 1}话',
|
||||
maxLines: (item.longTitle != null &&
|
||||
item.longTitle != '')
|
||||
? 1
|
||||
: 2,
|
||||
style: TextStyle(
|
||||
child: Text(
|
||||
item.title ?? '第${index + 1}话',
|
||||
maxLines:
|
||||
(item.longTitle != null &&
|
||||
item.longTitle != '')
|
||||
? 1
|
||||
: 2,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: index == currentIndex
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface),
|
||||
)),
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
if (item.badge != null) ...[
|
||||
const Spacer(),
|
||||
@@ -207,7 +214,7 @@ class _PgcPanelState extends State<PgcPanel> {
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
],
|
||||
),
|
||||
if (item.longTitle != null &&
|
||||
@@ -217,13 +224,14 @@ class _PgcPanelState extends State<PgcPanel> {
|
||||
item.longTitle!,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: index == currentIndex
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface),
|
||||
fontSize: 13,
|
||||
color: index == currentIndex
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
)
|
||||
]
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -81,8 +81,9 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
bool alwaysExapndIntroPanel = Pref.alwaysExapndIntroPanel;
|
||||
expandableCtr =
|
||||
ExpandableController(initialExpanded: alwaysExapndIntroPanel);
|
||||
expandableCtr = ExpandableController(
|
||||
initialExpanded: alwaysExapndIntroPanel,
|
||||
);
|
||||
if (!alwaysExapndIntroPanel && Pref.exapndIntroPanelH) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (Get.context!.orientation == Orientation.landscape &&
|
||||
@@ -103,8 +104,10 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
if (videoItem.title case String e) {
|
||||
videoDetail.value.title = e;
|
||||
} else if (videoItem.title case List list) {
|
||||
videoDetail.value.title =
|
||||
list.fold<String>('', (prev, val) => prev + val['text']);
|
||||
videoDetail.value.title = list.fold<String>(
|
||||
'',
|
||||
(prev, val) => prev + val['text'],
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
@@ -132,8 +135,9 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
}
|
||||
videoDetail.value = data;
|
||||
try {
|
||||
final videoDetailController =
|
||||
Get.find<VideoDetailController>(tag: heroTag);
|
||||
final videoDetailController = Get.find<VideoDetailController>(
|
||||
tag: heroTag,
|
||||
);
|
||||
if (videoDetailController.cover.value.isEmpty ||
|
||||
(videoDetailController.videoUrl.isNullOrEmpty &&
|
||||
!videoDetailController.isQuerying)) {
|
||||
@@ -141,8 +145,9 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
}
|
||||
if (videoDetailController.showReply) {
|
||||
try {
|
||||
final videoReplyController =
|
||||
Get.find<VideoReplyController>(tag: heroTag);
|
||||
final videoReplyController = Get.find<VideoReplyController>(
|
||||
tag: heroTag,
|
||||
);
|
||||
videoReplyController.count.value = data.stat?.reply ?? 0;
|
||||
} catch (_) {}
|
||||
}
|
||||
@@ -166,17 +171,19 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
// 获取up主粉丝数
|
||||
Future<void> queryUserStat(List<Staff>? staff) async {
|
||||
if (staff?.isNotEmpty == true) {
|
||||
Request().get(
|
||||
Api.relations,
|
||||
queryParameters: {'fids': staff!.map((item) => item.mid).join(',')},
|
||||
).then((res) {
|
||||
if (res.data['code'] == 0) {
|
||||
staffRelations.addAll({
|
||||
'status': true,
|
||||
if (res.data['data'] != null) ...res.data['data'],
|
||||
Request()
|
||||
.get(
|
||||
Api.relations,
|
||||
queryParameters: {'fids': staff!.map((item) => item.mid).join(',')},
|
||||
)
|
||||
.then((res) {
|
||||
if (res.data['code'] == 0) {
|
||||
staffRelations.addAll({
|
||||
'status': true,
|
||||
if (res.data['data'] != null) ...res.data['data'],
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
final mid = videoDetail.value.owner?.mid;
|
||||
if (mid == null) {
|
||||
@@ -258,8 +265,10 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
var result =
|
||||
await VideoHttp.dislikeVideo(bvid: bvid, type: !hasDislike.value);
|
||||
var result = await VideoHttp.dislikeVideo(
|
||||
bvid: bvid,
|
||||
type: !hasDislike.value,
|
||||
);
|
||||
if (result['status']) {
|
||||
if (!hasDislike.value) {
|
||||
SmartDialog.showToast('点踩成功');
|
||||
@@ -401,103 +410,106 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
// 分享视频
|
||||
void actionShareVideo(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
final videoDetail = this.videoDetail.value;
|
||||
String videoUrl = '${HttpString.baseUrl}/video/$bvid';
|
||||
return AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'复制链接',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.copyText(videoUrl);
|
||||
},
|
||||
context: context,
|
||||
builder: (_) {
|
||||
final videoDetail = this.videoDetail.value;
|
||||
String videoUrl = '${HttpString.baseUrl}/video/$bvid';
|
||||
return AlertDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'复制链接',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'其它app打开',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
PageUtils.launchURL(videoUrl);
|
||||
},
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.copyText(videoUrl);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'其它app打开',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享视频',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.shareText('${videoDetail.title} '
|
||||
'UP主: ${videoDetail.owner!.name!}'
|
||||
' - $videoUrl');
|
||||
},
|
||||
onTap: () {
|
||||
Get.back();
|
||||
PageUtils.launchURL(videoUrl);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享视频',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至动态',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (context) => RepostPanel(
|
||||
rid: videoDetail.aid,
|
||||
dynType: 8,
|
||||
pic: videoDetail.pic,
|
||||
title: videoDetail.title,
|
||||
uname: videoDetail.owner?.name,
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Utils.shareText(
|
||||
'${videoDetail.title} '
|
||||
'UP主: ${videoDetail.owner!.name!}'
|
||||
' - $videoUrl',
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至动态',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (context) => RepostPanel(
|
||||
rid: videoDetail.aid,
|
||||
dynType: 8,
|
||||
pic: videoDetail.pic,
|
||||
title: videoDetail.title,
|
||||
uname: videoDetail.owner?.name,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至消息',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
try {
|
||||
PageUtils.pmShare(
|
||||
context,
|
||||
content: {
|
||||
"id": videoDetail.aid!.toString(),
|
||||
"title": videoDetail.title!,
|
||||
"headline": videoDetail.title!,
|
||||
"source": 5,
|
||||
"thumb": videoDetail.pic!,
|
||||
"author": videoDetail.owner!.name!,
|
||||
"author_id": videoDetail.owner!.mid!.toString(),
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text(
|
||||
'分享至消息',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
try {
|
||||
PageUtils.pmShare(
|
||||
context,
|
||||
content: {
|
||||
"id": videoDetail.aid!.toString(),
|
||||
"title": videoDetail.title!,
|
||||
"headline": videoDetail.title!,
|
||||
"source": 5,
|
||||
"thumb": videoDetail.pic!,
|
||||
"author": videoDetail.owner!.name!,
|
||||
"author_id": videoDetail.owner!.mid!.toString(),
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast(e.toString());
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
} catch (e) {
|
||||
SmartDialog.showToast(e.toString());
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -695,13 +707,15 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
}
|
||||
}
|
||||
|
||||
final int currentIndex = episodes.indexWhere((e) =>
|
||||
e.cid ==
|
||||
(skipPages
|
||||
? videoDetail.isPageReversed == true
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid
|
||||
: lastPlayCid.value));
|
||||
final int currentIndex = episodes.indexWhere(
|
||||
(e) =>
|
||||
e.cid ==
|
||||
(skipPages
|
||||
? videoDetail.isPageReversed == true
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid
|
||||
: lastPlayCid.value),
|
||||
);
|
||||
int prevIndex = currentIndex - 1;
|
||||
final PlayRepeat playRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
|
||||
@@ -759,13 +773,15 @@ class VideoIntroController extends CommonIntroController with ReloadMixin {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int currentIndex = episodes.indexWhere((e) =>
|
||||
e.cid ==
|
||||
(skipPages
|
||||
? videoDetail.isPageReversed == true
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid
|
||||
: videoDetailCtr.cid.value));
|
||||
final int currentIndex = episodes.indexWhere(
|
||||
(e) =>
|
||||
e.cid ==
|
||||
(skipPages
|
||||
? videoDetail.isPageReversed == true
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid
|
||||
: videoDetailCtr.cid.value),
|
||||
);
|
||||
|
||||
int nextIndex = currentIndex + 1;
|
||||
|
||||
|
||||
@@ -83,7 +83,8 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
);
|
||||
return SliverLayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
bool isHorizontal = context.orientation == Orientation.landscape &&
|
||||
bool isHorizontal =
|
||||
context.orientation == Orientation.landscape &&
|
||||
constraints.crossAxisExtent >
|
||||
constraints.viewportMainAxisExtent * 1.25;
|
||||
return SliverPadding(
|
||||
@@ -145,7 +146,8 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
physics: ReloadScrollPhysics(
|
||||
controller: introController),
|
||||
controller: introController,
|
||||
),
|
||||
child: Row(
|
||||
spacing: 25,
|
||||
children: videoDetail.staff!
|
||||
@@ -157,9 +159,14 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
if (isHorizontal) ...[
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: actionGrid(context, isLoading,
|
||||
videoDetail, introController)),
|
||||
]
|
||||
child: actionGrid(
|
||||
context,
|
||||
isLoading,
|
||||
videoDetail,
|
||||
introController,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -181,8 +188,11 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
Feedback.forLongPress(context);
|
||||
Utils.copyText(videoDetail.title ?? '');
|
||||
},
|
||||
child: _buildVideoTitle(theme, videoDetail,
|
||||
isExpand: true),
|
||||
child: _buildVideoTitle(
|
||||
theme,
|
||||
videoDetail,
|
||||
isExpand: true,
|
||||
),
|
||||
),
|
||||
theme: expandTheme,
|
||||
),
|
||||
@@ -211,7 +221,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
const WidgetSpan(child: SizedBox(width: 2)),
|
||||
TextSpan(
|
||||
text: '${videoDetail.argueInfo!.argueMsg}',
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
style: TextStyle(
|
||||
@@ -258,7 +268,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return _buildTags(videoTags!);
|
||||
})
|
||||
}),
|
||||
],
|
||||
),
|
||||
theme: expandTheme,
|
||||
@@ -285,14 +295,19 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
if (!isHorizontal) ...[
|
||||
const SizedBox(height: 8),
|
||||
actionGrid(
|
||||
context, isLoading, videoDetail, introController),
|
||||
context,
|
||||
isLoading,
|
||||
videoDetail,
|
||||
introController,
|
||||
),
|
||||
],
|
||||
// 合集
|
||||
if (!isLoading &&
|
||||
videoDetail.ugcSeason != null &&
|
||||
(context.orientation != Orientation.landscape ||
|
||||
(context.orientation == Orientation.landscape &&
|
||||
!videoDetailCtr.plPlayerController
|
||||
!videoDetailCtr
|
||||
.plPlayerController
|
||||
.horizontalSeasonPanel)))
|
||||
SeasonPanel(
|
||||
heroTag: widget.heroTag,
|
||||
@@ -305,7 +320,8 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
videoDetail.pages!.length > 1 &&
|
||||
(context.orientation != Orientation.landscape ||
|
||||
(context.orientation == Orientation.landscape &&
|
||||
!videoDetailCtr.plPlayerController
|
||||
!videoDetailCtr
|
||||
.plPlayerController
|
||||
.horizontalSeasonPanel))) ...[
|
||||
PagesPanel(
|
||||
heroTag: widget.heroTag,
|
||||
@@ -356,8 +372,11 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVideoTitle(ThemeData theme, VideoDetailData videoDetail,
|
||||
{bool isExpand = false}) {
|
||||
Widget _buildVideoTitle(
|
||||
ThemeData theme,
|
||||
VideoDetailData videoDetail, {
|
||||
bool isExpand = false,
|
||||
}) {
|
||||
late final isDark = theme.brightness == Brightness.dark;
|
||||
Widget child() {
|
||||
final videoLabel = videoDetailCtr.videoLabel.value;
|
||||
@@ -480,7 +499,7 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
4 || 6 => '已互关',
|
||||
128 => '已拉黑',
|
||||
-10 => '特别关注',
|
||||
_ => ' 关注 '
|
||||
_ => ' 关注 ',
|
||||
},
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
@@ -512,7 +531,8 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
? NumUtil.numFormat(videoDetail.stat!.like!)
|
||||
: null,
|
||||
needAnim: true,
|
||||
hasTriple: videoIntroController.hasLike.value &&
|
||||
hasTriple:
|
||||
videoIntroController.hasLike.value &&
|
||||
videoIntroController.hasCoin &&
|
||||
videoIntroController.hasFav.value,
|
||||
callBack: (start) {
|
||||
@@ -557,8 +577,10 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
onTap: () => videoIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => videoIntroController
|
||||
.showFavBottomSheet(context, type: 'longPress'),
|
||||
onLongPress: () => videoIntroController.showFavBottomSheet(
|
||||
context,
|
||||
type: 'longPress',
|
||||
),
|
||||
selectStatus: videoIntroController.hasFav.value,
|
||||
semanticsLabel: '收藏',
|
||||
text: !isLoading
|
||||
@@ -582,8 +604,9 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
onTap: () => videoIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
semanticsLabel: '分享',
|
||||
text:
|
||||
!isLoading ? NumUtil.numFormat(videoDetail.stat!.share!) : null,
|
||||
text: !isLoading
|
||||
? NumUtil.numFormat(videoDetail.stat!.share!)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -726,38 +749,40 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: -6,
|
||||
child: Obx(() => introController.staffRelations['status'] ==
|
||||
true &&
|
||||
introController.staffRelations['${item.mid}'] == null
|
||||
? Material(
|
||||
type: MaterialType.transparency,
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
customBorder: const CircleBorder(),
|
||||
onTap: () => RequestUtils.actionRelationMod(
|
||||
context: context,
|
||||
mid: item.mid,
|
||||
isFollow: false,
|
||||
callback: (val) {
|
||||
introController.staffRelations['${item.mid}'] =
|
||||
true;
|
||||
},
|
||||
),
|
||||
child: Ink(
|
||||
padding: const EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
shape: BoxShape.circle,
|
||||
child: Obx(
|
||||
() =>
|
||||
introController.staffRelations['status'] == true &&
|
||||
introController.staffRelations['${item.mid}'] == null
|
||||
? Material(
|
||||
type: MaterialType.transparency,
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
customBorder: const CircleBorder(),
|
||||
onTap: () => RequestUtils.actionRelationMod(
|
||||
context: context,
|
||||
mid: item.mid,
|
||||
isFollow: false,
|
||||
callback: (val) {
|
||||
introController.staffRelations['${item.mid}'] =
|
||||
true;
|
||||
},
|
||||
),
|
||||
child: Icon(
|
||||
MdiIcons.plus,
|
||||
size: 16,
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
child: Ink(
|
||||
padding: const EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.secondaryContainer,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
MdiIcons.plus,
|
||||
size: 16,
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink()),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -791,124 +816,126 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAvatar(ThemeData theme, VoidCallback onPushMember) =>
|
||||
GestureDetector(
|
||||
onTap: onPushMember,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Obx(
|
||||
() {
|
||||
final userStat = introController.userStat.value;
|
||||
final isVip = (userStat.card?.vip?.status ?? 0) > 0;
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
Widget _buildAvatar(
|
||||
ThemeData theme,
|
||||
VoidCallback onPushMember,
|
||||
) => GestureDetector(
|
||||
onTap: onPushMember,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Obx(
|
||||
() {
|
||||
final userStat = introController.userStat.value;
|
||||
final isVip = (userStat.card?.vip?.status ?? 0) > 0;
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
PendantAvatar(
|
||||
avatar: userStat.card?.face,
|
||||
size: 35,
|
||||
badgeSize: 14,
|
||||
isVip: isVip,
|
||||
officialType: userStat.card?.officialVerify?.type,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
PendantAvatar(
|
||||
avatar: userStat.card?.face,
|
||||
size: 35,
|
||||
badgeSize: 14,
|
||||
isVip: isVip,
|
||||
officialType: userStat.card?.officialVerify?.type,
|
||||
Text(
|
||||
userStat.card?.name ?? "",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: isVip && userStat.card?.vip?.type == 2
|
||||
? context.vipColor
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
userStat.card?.name ?? "",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: isVip && userStat.card?.vip?.type == 2
|
||||
? context.vipColor
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 0),
|
||||
Text(
|
||||
'${NumUtil.numFormat(userStat.follower)}粉丝 ${'${NumUtil.numFormat(userStat.archiveCount)}视频'}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 0),
|
||||
Text(
|
||||
'${NumUtil.numFormat(userStat.follower)}粉丝 ${'${NumUtil.numFormat(userStat.archiveCount)}视频'}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildInfo(ThemeData theme, VideoDetailData videoDetail) => Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
StatWidget(
|
||||
type: StatType.play,
|
||||
value: videoDetail.stat?.view,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
StatWidget(
|
||||
type: StatType.danmaku,
|
||||
value: videoDetail.stat?.danmaku,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
Text(
|
||||
DateUtil.format(videoDetail.pubdate),
|
||||
spacing: 10,
|
||||
children: [
|
||||
StatWidget(
|
||||
type: StatType.play,
|
||||
value: videoDetail.stat?.view,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
StatWidget(
|
||||
type: StatType.danmaku,
|
||||
value: videoDetail.stat?.danmaku,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
Text(
|
||||
DateUtil.format(videoDetail.pubdate),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
if (MineController.anonymity.value)
|
||||
Icon(
|
||||
MdiIcons.incognito,
|
||||
size: 15,
|
||||
color: theme.colorScheme.outline,
|
||||
semanticLabel: '无痕',
|
||||
),
|
||||
if (introController.isShowOnlineTotal)
|
||||
Obx(
|
||||
() => Text(
|
||||
'${introController.total.value}人在看',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
if (MineController.anonymity.value)
|
||||
Icon(
|
||||
MdiIcons.incognito,
|
||||
size: 15,
|
||||
color: theme.colorScheme.outline,
|
||||
semanticLabel: '无痕',
|
||||
),
|
||||
if (introController.isShowOnlineTotal)
|
||||
Obx(
|
||||
() => Text(
|
||||
'${introController.total.value}人在看',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Widget get _aiBtn => Positioned(
|
||||
right: 10,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Center(
|
||||
child: Semantics(
|
||||
label: 'AI总结',
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
if (introController.aiConclusionResult == null) {
|
||||
await introController.aiConclusion();
|
||||
}
|
||||
if (introController.aiConclusionResult == null) {
|
||||
return;
|
||||
}
|
||||
if (introController.aiConclusionResult!.summary?.isNotEmpty ==
|
||||
true ||
|
||||
introController.aiConclusionResult!.outline?.isNotEmpty ==
|
||||
true) {
|
||||
widget.showAiBottomSheet();
|
||||
} else {
|
||||
SmartDialog.showToast("当前视频不支持AI视频总结");
|
||||
}
|
||||
},
|
||||
child: Image.asset('assets/images/ai.png', height: 22),
|
||||
),
|
||||
),
|
||||
right: 10,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
child: Center(
|
||||
child: Semantics(
|
||||
label: 'AI总结',
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
if (introController.aiConclusionResult == null) {
|
||||
await introController.aiConclusion();
|
||||
}
|
||||
if (introController.aiConclusionResult == null) {
|
||||
return;
|
||||
}
|
||||
if (introController.aiConclusionResult!.summary?.isNotEmpty ==
|
||||
true ||
|
||||
introController.aiConclusionResult!.outline?.isNotEmpty ==
|
||||
true) {
|
||||
widget.showAiBottomSheet();
|
||||
} else {
|
||||
SmartDialog.showToast("当前视频不支持AI视频总结");
|
||||
}
|
||||
},
|
||||
child: Image.asset('assets/images/ai.png', height: 22),
|
||||
),
|
||||
);
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _buildTags(List<VideoTagItem> tags) {
|
||||
return GestureDetector(
|
||||
|
||||
@@ -60,10 +60,11 @@ class ActionRowLineItem extends StatelessWidget {
|
||||
child: Text(
|
||||
text!,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: selectStatus
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.outline),
|
||||
fontSize: 13,
|
||||
color: selectStatus
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -44,8 +44,9 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_videoDetailController =
|
||||
Get.find<VideoDetailController>(tag: widget.heroTag);
|
||||
_videoDetailController = Get.find<VideoDetailController>(
|
||||
tag: widget.heroTag,
|
||||
);
|
||||
if (widget.list == null) {
|
||||
cid = widget.videoIntroController.lastPlayCid.value;
|
||||
pageIndex = pages.indexWhere((Part e) => e.cid == cid);
|
||||
@@ -68,8 +69,9 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
}
|
||||
const double itemWidth = 150;
|
||||
final double targetOffset = (pageIndex * itemWidth - itemWidth / 2).clamp(
|
||||
_scrollController.position.minScrollExtent,
|
||||
_scrollController.position.maxScrollExtent);
|
||||
_scrollController.position.minScrollExtent,
|
||||
_scrollController.position.maxScrollExtent,
|
||||
);
|
||||
_scrollController.animateTo(
|
||||
targetOffset,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
@@ -162,7 +164,10 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
widget.cover,
|
||||
);
|
||||
if (widget.list != null &&
|
||||
widget.videoIntroController.videoDetail.value
|
||||
widget
|
||||
.videoIntroController
|
||||
.videoDetail
|
||||
.value
|
||||
.ugcSeason !=
|
||||
null) {
|
||||
_videoDetailController.seasonCid = pages.first.cid;
|
||||
@@ -179,7 +184,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
height: 12,
|
||||
semanticLabel: "正在播放:",
|
||||
),
|
||||
const SizedBox(width: 6)
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
Expanded(
|
||||
child: Text(
|
||||
@@ -202,7 +207,7 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,19 +40,20 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_videoDetailController =
|
||||
Get.find<VideoDetailController>(tag: widget.heroTag);
|
||||
_videoDetailController = Get.find<VideoDetailController>(
|
||||
tag: widget.heroTag,
|
||||
);
|
||||
|
||||
_videoDetailController.seasonCid =
|
||||
videoIntroController.lastPlayCid.value != 0
|
||||
? (videoDetail.pages?.isNotEmpty == true
|
||||
? videoDetail.isPageReversed
|
||||
? (videoDetail.pages?.isNotEmpty == true
|
||||
? videoDetail.isPageReversed
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid
|
||||
: videoIntroController.lastPlayCid.value)
|
||||
: videoDetail.isPageReversed
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid;
|
||||
: videoIntroController.lastPlayCid.value)
|
||||
: videoDetail.isPageReversed
|
||||
? videoDetail.pages!.last.cid
|
||||
: videoDetail.pages!.first.cid;
|
||||
|
||||
/// 根据 cid 找到对应集,找到对应 episodes
|
||||
/// 有多个episodes时,只显示其中一个
|
||||
@@ -63,7 +64,8 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
|
||||
/// 取对应 season_id 的 episodes
|
||||
currentIndex.value = episodes.indexWhere(
|
||||
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
|
||||
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid,
|
||||
);
|
||||
_listener = _videoDetailController.cid.listen((int cid) {
|
||||
if (_videoDetailController.seasonCid != cid) {
|
||||
bool isPart =
|
||||
@@ -74,7 +76,8 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
}
|
||||
_findEpisode();
|
||||
currentIndex.value = episodes.indexWhere(
|
||||
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid);
|
||||
(EpisodeItem e) => e.cid == _videoDetailController.seasonCid,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -104,13 +107,13 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
onTap: widget.onTap == false
|
||||
? null
|
||||
: () => widget.showEpisodes(
|
||||
_videoDetailController.seasonIndex.value,
|
||||
videoDetail.ugcSeason,
|
||||
null,
|
||||
_videoDetailController.bvid,
|
||||
null,
|
||||
_videoDetailController.seasonCid,
|
||||
),
|
||||
_videoDetailController.seasonIndex.value,
|
||||
videoDetail.ugcSeason,
|
||||
null,
|
||||
_videoDetailController.bvid,
|
||||
null,
|
||||
_videoDetailController.seasonCid,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
|
||||
child: Row(
|
||||
@@ -143,7 +146,7 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
Icons.arrow_forward_ios_outlined,
|
||||
size: 13,
|
||||
semanticLabel: '查看',
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user