mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: resCode, post panel
fix: bangumi panel Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -158,7 +158,9 @@ class _ListSheetContentState extends State<ListSheetContent>
|
|||||||
late String title;
|
late String title;
|
||||||
if (episode.runtimeType.toString() == "EpisodeItem") {
|
if (episode.runtimeType.toString() == "EpisodeItem") {
|
||||||
if (episode.longTitle != null && episode.longTitle != "") {
|
if (episode.longTitle != null && episode.longTitle != "") {
|
||||||
title = "第${(episode.title ?? '${index + 1}')}话 ${episode.longTitle!}";
|
dynamic leading = episode.title ?? index + 1;
|
||||||
|
title =
|
||||||
|
"${Utils.isStringNumeric(leading) ? '第$leading话' : leading} ${episode.longTitle!}";
|
||||||
} else {
|
} else {
|
||||||
title = episode.title!;
|
title = episode.title!;
|
||||||
}
|
}
|
||||||
@@ -255,13 +257,12 @@ class _ListSheetContentState extends State<ListSheetContent>
|
|||||||
'assets/images/big-vip.png',
|
'assets/images/big-vip.png',
|
||||||
height: 20,
|
height: 20,
|
||||||
semanticLabel: "大会员",
|
semanticLabel: "大会员",
|
||||||
),
|
)
|
||||||
if (episode.badge != '会员') Text(episode.badge),
|
else
|
||||||
|
Text(episode.badge),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
],
|
],
|
||||||
if (!(episode.runtimeType.toString() == 'EpisodeItem' &&
|
if (episode is! bangumi.EpisodeItem) Text('${index + 1}/$length'),
|
||||||
(episode.longTitle != null && episode.longTitle != '')))
|
|
||||||
Text('${index + 1}/$length'),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'package:PiliPalaX/common/widgets/stat/danmu.dart';
|
||||||
|
import 'package:PiliPalaX/common/widgets/stat/view.dart';
|
||||||
|
import 'package:PiliPalaX/common/widgets/video_popup_menu.dart';
|
||||||
import 'package:PiliPalaX/models/space_archive/item.dart';
|
import 'package:PiliPalaX/models/space_archive/item.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
@@ -14,163 +17,98 @@ class VideoCardHMemberVideo extends StatelessWidget {
|
|||||||
required this.videoItem,
|
required this.videoItem,
|
||||||
this.longPress,
|
this.longPress,
|
||||||
this.longPressEnd,
|
this.longPressEnd,
|
||||||
this.source = 'normal',
|
|
||||||
this.showOwner = true,
|
|
||||||
this.showView = true,
|
|
||||||
this.showDanmaku = true,
|
|
||||||
this.showPubdate = false,
|
|
||||||
});
|
});
|
||||||
final Item videoItem;
|
final Item videoItem;
|
||||||
final Function()? longPress;
|
final Function()? longPress;
|
||||||
final Function()? longPressEnd;
|
final Function()? longPressEnd;
|
||||||
final String source;
|
|
||||||
final bool showOwner;
|
|
||||||
final bool showView;
|
|
||||||
final bool showDanmaku;
|
|
||||||
final bool showPubdate;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final int aid = int.tryParse(videoItem.param ?? '') ?? -1;
|
final int aid = int.tryParse(videoItem.param ?? '') ?? -1;
|
||||||
final String bvid = videoItem.bvid ?? '';
|
final String bvid = videoItem.bvid ?? '';
|
||||||
String type = 'video';
|
|
||||||
// try {
|
|
||||||
// type = videoItem.type;
|
|
||||||
// } catch (_) {}
|
|
||||||
// List<VideoCustomAction> actions =
|
|
||||||
// VideoCustomActions(videoItem, context).actions;
|
|
||||||
final String heroTag = Utils.makeHeroTag(aid);
|
final String heroTag = Utils.makeHeroTag(aid);
|
||||||
return Stack(children: [
|
return Stack(children: [
|
||||||
Semantics(
|
InkWell(
|
||||||
// label: Utils.videoItemSemantics(videoItem),
|
borderRadius: BorderRadius.circular(12),
|
||||||
excludeSemantics: true,
|
onLongPress: () {
|
||||||
// customSemanticsActions: <CustomSemanticsAction, void Function()>{
|
if (longPress != null) {
|
||||||
// for (var item in actions)
|
longPress!();
|
||||||
// CustomSemanticsAction(label: item.title): item.onTap!,
|
}
|
||||||
// },
|
},
|
||||||
child: InkWell(
|
onTap: () async {
|
||||||
borderRadius: BorderRadius.circular(12),
|
try {
|
||||||
onLongPress: () {
|
Get.toNamed('/video?bvid=$bvid&cid=${videoItem.firstCid}',
|
||||||
if (longPress != null) {
|
arguments: {'heroTag': heroTag});
|
||||||
longPress!();
|
} catch (err) {
|
||||||
}
|
SmartDialog.showToast(err.toString());
|
||||||
},
|
}
|
||||||
onTap: () async {
|
},
|
||||||
if (type == 'ketang') {
|
child: LayoutBuilder(
|
||||||
SmartDialog.showToast('课堂视频暂不支持播放');
|
builder: (BuildContext context, BoxConstraints boxConstraints) {
|
||||||
return;
|
return Row(
|
||||||
}
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
try {
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
// PiliScheme.routePush(Uri.parse(videoItem.smallCoverV5.base.uri));
|
children: <Widget>[
|
||||||
// final int cid =
|
AspectRatio(
|
||||||
// videoItem.smallCoverV5.base.playerArgs.cid.toInt() ??
|
aspectRatio: StyleString.aspectRatio,
|
||||||
// await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
child: LayoutBuilder(
|
||||||
Get.toNamed('/video?bvid=$bvid&cid=${videoItem.firstCid}',
|
builder:
|
||||||
arguments: {'heroTag': heroTag});
|
(BuildContext context, BoxConstraints boxConstraints) {
|
||||||
// Get.toNamed('/video?bvid=$bvid&cid=$cid',
|
final double maxWidth = boxConstraints.maxWidth;
|
||||||
// arguments: {'videoItem': videoItem, 'heroTag': heroTag});
|
final double maxHeight = boxConstraints.maxHeight;
|
||||||
} catch (err) {
|
return Stack(
|
||||||
SmartDialog.showToast(err.toString());
|
children: [
|
||||||
}
|
Hero(
|
||||||
},
|
tag: heroTag,
|
||||||
child: LayoutBuilder(
|
child: NetworkImgLayer(
|
||||||
builder: (BuildContext context, BoxConstraints boxConstraints) {
|
src: videoItem.cover,
|
||||||
return Row(
|
width: maxWidth,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
height: maxHeight,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
AspectRatio(
|
|
||||||
aspectRatio: StyleString.aspectRatio,
|
|
||||||
child: LayoutBuilder(
|
|
||||||
builder: (BuildContext context,
|
|
||||||
BoxConstraints boxConstraints) {
|
|
||||||
final double maxWidth = boxConstraints.maxWidth;
|
|
||||||
final double maxHeight = boxConstraints.maxHeight;
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
Hero(
|
|
||||||
tag: heroTag,
|
|
||||||
child: NetworkImgLayer(
|
|
||||||
src: videoItem.cover,
|
|
||||||
width: maxWidth,
|
|
||||||
height: maxHeight,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (videoItem.duration != null)
|
),
|
||||||
PBadge(
|
if (videoItem.duration != null)
|
||||||
text: Utils.timeFormat(videoItem.duration),
|
PBadge(
|
||||||
right: 6.0,
|
text: Utils.timeFormat(videoItem.duration),
|
||||||
bottom: 6.0,
|
right: 6.0,
|
||||||
type: 'gray',
|
bottom: 6.0,
|
||||||
),
|
type: 'gray',
|
||||||
if (type != 'video')
|
),
|
||||||
PBadge(
|
],
|
||||||
text: type,
|
);
|
||||||
left: 6.0,
|
},
|
||||||
bottom: 6.0,
|
|
||||||
type: 'primary',
|
|
||||||
),
|
|
||||||
// if (videoItem.rcmdReason != null &&
|
|
||||||
// videoItem.rcmdReason.content != '')
|
|
||||||
// pBadge(videoItem.rcmdReason.content, context,
|
|
||||||
// 6.0, 6.0, null, null),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
VideoContent(
|
),
|
||||||
videoItem: videoItem,
|
VideoContent(
|
||||||
source: source,
|
videoItem: videoItem,
|
||||||
showOwner: showOwner,
|
)
|
||||||
showView: showView,
|
],
|
||||||
showDanmaku: showDanmaku,
|
);
|
||||||
showPubdate: showPubdate,
|
},
|
||||||
)
|
),
|
||||||
],
|
),
|
||||||
);
|
Positioned(
|
||||||
},
|
bottom: 0,
|
||||||
),
|
right: 0,
|
||||||
|
child: VideoPopupMenu(
|
||||||
|
size: 29,
|
||||||
|
iconSize: 17,
|
||||||
|
actions: VideoCustomActions(videoItem, context).actions,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// if (source == 'normal')
|
|
||||||
// Positioned(
|
|
||||||
// bottom: 0,
|
|
||||||
// right: 0,
|
|
||||||
// child: VideoPopupMenu(
|
|
||||||
// size: 29,
|
|
||||||
// iconSize: 17,
|
|
||||||
// actions: actions,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class VideoContent extends StatelessWidget {
|
class VideoContent extends StatelessWidget {
|
||||||
final Item videoItem;
|
final Item videoItem;
|
||||||
final String source;
|
|
||||||
final bool showOwner;
|
|
||||||
final bool showView;
|
|
||||||
final bool showDanmaku;
|
|
||||||
final bool showPubdate;
|
|
||||||
|
|
||||||
const VideoContent({
|
const VideoContent({
|
||||||
super.key,
|
super.key,
|
||||||
required this.videoItem,
|
required this.videoItem,
|
||||||
this.source = 'normal',
|
|
||||||
this.showOwner = true,
|
|
||||||
this.showView = true,
|
|
||||||
this.showDanmaku = true,
|
|
||||||
this.showPubdate = false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// String pubdate = showPubdate
|
|
||||||
// ? Utils.dateFormat(videoItem.pubdate!, formatType: 'day')
|
|
||||||
// : '';
|
|
||||||
// if (pubdate != '') pubdate += ' ';
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(10, 0, 6, 0),
|
padding: const EdgeInsets.fromLTRB(10, 0, 6, 0),
|
||||||
@@ -193,39 +131,8 @@ class VideoContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
// const Spacer(),
|
|
||||||
// if (videoItem.rcmdReason != null &&
|
|
||||||
// videoItem.rcmdReason.content != '')
|
|
||||||
// Container(
|
|
||||||
// padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 5),
|
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// borderRadius: BorderRadius.circular(4),
|
|
||||||
// border: Border.all(
|
|
||||||
// color: Theme.of(context).colorScheme.surfaceTint),
|
|
||||||
// ),
|
|
||||||
// child: Text(
|
|
||||||
// videoItem.rcmdReason.content,
|
|
||||||
// style: TextStyle(
|
|
||||||
// fontSize: 9,
|
|
||||||
// color: Theme.of(context).colorScheme.surfaceTint),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(height: 4),
|
|
||||||
if (showOwner || showPubdate)
|
|
||||||
Text(
|
|
||||||
videoItem.publishTimeText ?? '',
|
|
||||||
maxLines: 1,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
|
||||||
height: 1,
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
overflow: TextOverflow.clip,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 3),
|
|
||||||
Text(
|
Text(
|
||||||
'${videoItem.viewContent} · ${videoItem.danmaku}',
|
videoItem.publishTimeText ?? '',
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
@@ -235,24 +142,20 @@ class VideoContent extends StatelessWidget {
|
|||||||
overflow: TextOverflow.clip,
|
overflow: TextOverflow.clip,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Row(
|
const SizedBox(height: 3),
|
||||||
// children: [
|
Row(
|
||||||
// if (showView) ...[
|
children: [
|
||||||
// StatView(
|
StatView(
|
||||||
// theme: 'gray',
|
theme: 'gray',
|
||||||
// view: videoItem.stat.view as int,
|
view: videoItem.viewContent,
|
||||||
// ),
|
),
|
||||||
// const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
// ],
|
StatDanMu(
|
||||||
// if (showDanmaku)
|
theme: 'gray',
|
||||||
// StatDanMu(
|
danmu: videoItem.danmaku,
|
||||||
// theme: 'gray',
|
),
|
||||||
// danmu: videoItem.stat.danmu as int,
|
],
|
||||||
// ),
|
),
|
||||||
// const Spacer(),
|
|
||||||
// if (source == 'normal') const SizedBox(width: 24),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -20,11 +20,6 @@ class VideoCardVMemberHome extends StatelessWidget {
|
|||||||
this.longPressEnd,
|
this.longPressEnd,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool isStringNumeric(String str) {
|
|
||||||
RegExp numericRegex = RegExp(r'^\d+$');
|
|
||||||
return numericRegex.hasMatch(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onPushDetail(heroTag) async {
|
void onPushDetail(heroTag) async {
|
||||||
String goto = videoItem.goto ?? '';
|
String goto = videoItem.goto ?? '';
|
||||||
switch (goto) {
|
switch (goto) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import '../../http/video.dart';
|
|||||||
import '../../models/home/rcmd/result.dart';
|
import '../../models/home/rcmd/result.dart';
|
||||||
import '../../pages/mine/controller.dart';
|
import '../../pages/mine/controller.dart';
|
||||||
import '../../utils/storage.dart';
|
import '../../utils/storage.dart';
|
||||||
|
import 'package:PiliPalaX/models/space_archive/item.dart';
|
||||||
|
|
||||||
class VideoCustomAction {
|
class VideoCustomAction {
|
||||||
String title;
|
String title;
|
||||||
@@ -47,211 +48,215 @@ class VideoCustomActions {
|
|||||||
SmartDialog.showToast(res['msg']);
|
SmartDialog.showToast(res['msg']);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
VideoCustomAction(
|
if (videoItem is! Item)
|
||||||
'访问:${videoItem.owner.name}',
|
VideoCustomAction(
|
||||||
'visit',
|
'访问:${videoItem.owner.name}',
|
||||||
Icon(MdiIcons.accountCircleOutline, size: 16),
|
'visit',
|
||||||
() async {
|
Icon(MdiIcons.accountCircleOutline, size: 16),
|
||||||
Get.toNamed('/member?mid=${videoItem.owner.mid}', arguments: {
|
|
||||||
// 'face': videoItem.owner.face,
|
|
||||||
'heroTag': '${videoItem.owner.mid}',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
VideoCustomAction(
|
|
||||||
'不感兴趣', 'dislike', Icon(MdiIcons.thumbDownOutline, size: 16),
|
|
||||||
() async {
|
() async {
|
||||||
String? accessKey = GStorage.localCache
|
Get.toNamed('/member?mid=${videoItem.owner.mid}', arguments: {
|
||||||
.get(LocalCacheKey.accessKey, defaultValue: {})['value'];
|
// 'face': videoItem.owner.face,
|
||||||
if (accessKey == null || accessKey == "") {
|
'heroTag': '${videoItem.owner.mid}',
|
||||||
SmartDialog.showToast("请退出账号后重新登录");
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (videoItem is RecVideoItemAppModel) {
|
|
||||||
RecVideoItemAppModel v = videoItem as RecVideoItemAppModel;
|
|
||||||
ThreePoint? tp = v.threePoint;
|
|
||||||
if (tp == null) {
|
|
||||||
SmartDialog.showToast("未能获取threePoint");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (tp.dislikeReasons == null && tp.feedbacks == null) {
|
|
||||||
SmartDialog.showToast("未能获取dislikeReasons或feedbacks");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Widget actionButton(DislikeReason? r, FeedbackReason? f) {
|
|
||||||
return ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 0.0),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
SmartDialog.showLoading(msg: '正在提交');
|
|
||||||
var res = await VideoHttp.feedDislike(
|
|
||||||
reasonId: r?.id,
|
|
||||||
feedbackId: f?.id,
|
|
||||||
id: v.param!,
|
|
||||||
goto: v.goto!,
|
|
||||||
);
|
|
||||||
SmartDialog.dismiss();
|
|
||||||
SmartDialog.showToast(
|
|
||||||
res['status'] ? (r?.toast ?? f?.toast) : res['msg']);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: Text(r?.name ?? f?.name ?? '未知'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text('请选择'),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
if (tp.dislikeReasons != null)
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: Text('我不想看'),
|
|
||||||
),
|
|
||||||
if (tp.dislikeReasons != null)
|
|
||||||
Wrap(
|
|
||||||
spacing: 5.0,
|
|
||||||
runSpacing: 2.0,
|
|
||||||
children: tp.dislikeReasons!.map((item) {
|
|
||||||
return actionButton(item, null);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
if (tp.feedbacks != null)
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 8.0),
|
|
||||||
child: Text('反馈'),
|
|
||||||
),
|
|
||||||
if (tp.feedbacks != null)
|
|
||||||
Wrap(
|
|
||||||
spacing: 5.0,
|
|
||||||
runSpacing: 2.0,
|
|
||||||
children: tp.feedbacks!.map((item) {
|
|
||||||
return actionButton(null, item);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
//分割线
|
|
||||||
const Divider(),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
SmartDialog.showLoading(msg: '正在提交');
|
|
||||||
var res = await VideoHttp.feedDislikeCancel(
|
|
||||||
// reasonId: r?.id,
|
|
||||||
// feedbackId: f?.id,
|
|
||||||
id: v.param!,
|
|
||||||
goto: v.goto!,
|
|
||||||
);
|
|
||||||
SmartDialog.dismiss();
|
|
||||||
SmartDialog.showToast(
|
|
||||||
res['status'] ? "成功" : res['msg']);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: const Text("撤销"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text('点踩该视频?'),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
const Text("web端暂不支持精细选择"),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
Wrap(
|
|
||||||
spacing: 5.0,
|
|
||||||
runSpacing: 2.0,
|
|
||||||
children: [
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
SmartDialog.showLoading(msg: '正在提交');
|
|
||||||
var res = await VideoHttp.dislikeVideo(
|
|
||||||
bvid: videoItem.bvid as String, type: true);
|
|
||||||
SmartDialog.dismiss();
|
|
||||||
SmartDialog.showToast(
|
|
||||||
res['status'] ? "点踩成功" : res['msg']);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: const Text("点踩"),
|
|
||||||
),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
SmartDialog.showLoading(msg: '正在提交');
|
|
||||||
var res = await VideoHttp.dislikeVideo(
|
|
||||||
bvid: videoItem.bvid as String, type: false);
|
|
||||||
SmartDialog.dismiss();
|
|
||||||
SmartDialog.showToast(
|
|
||||||
res['status'] ? "取消踩" : res['msg']);
|
|
||||||
Get.back();
|
|
||||||
},
|
|
||||||
child: const Text("撤销"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
VideoCustomAction('拉黑:${videoItem.owner.name}', 'block',
|
|
||||||
Icon(MdiIcons.cancel, size: 16), () async {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: const Text('提示'),
|
|
||||||
content:
|
|
||||||
Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
|
|
||||||
'\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Get.back(),
|
|
||||||
child: Text(
|
|
||||||
'点错了',
|
|
||||||
style:
|
|
||||||
TextStyle(color: Theme.of(context).colorScheme.outline),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
var res = await VideoHttp.relationMod(
|
|
||||||
mid: videoItem.owner.mid,
|
|
||||||
act: 5,
|
|
||||||
reSrc: 11,
|
|
||||||
);
|
|
||||||
List<int> blackMidsList = GStorage.localCache
|
|
||||||
.get(LocalCacheKey.blackMidsList, defaultValue: [-1])
|
|
||||||
.map<int>((i) => i as int)
|
|
||||||
.toList();
|
|
||||||
blackMidsList.insert(0, videoItem.owner.mid);
|
|
||||||
GStorage.localCache
|
|
||||||
.put(LocalCacheKey.blackMidsList, blackMidsList);
|
|
||||||
Get.back();
|
|
||||||
SmartDialog.showToast(res['msg'] ?? '成功');
|
|
||||||
},
|
|
||||||
child: const Text('确认'),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
),
|
||||||
}),
|
if (videoItem is! Item)
|
||||||
|
VideoCustomAction(
|
||||||
|
'不感兴趣', 'dislike', Icon(MdiIcons.thumbDownOutline, size: 16),
|
||||||
|
() async {
|
||||||
|
String? accessKey = GStorage.localCache
|
||||||
|
.get(LocalCacheKey.accessKey, defaultValue: {})['value'];
|
||||||
|
if (accessKey == null || accessKey == "") {
|
||||||
|
SmartDialog.showToast("请退出账号后重新登录");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (videoItem is RecVideoItemAppModel) {
|
||||||
|
RecVideoItemAppModel v = videoItem as RecVideoItemAppModel;
|
||||||
|
ThreePoint? tp = v.threePoint;
|
||||||
|
if (tp == null) {
|
||||||
|
SmartDialog.showToast("未能获取threePoint");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tp.dislikeReasons == null && tp.feedbacks == null) {
|
||||||
|
SmartDialog.showToast("未能获取dislikeReasons或feedbacks");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Widget actionButton(DislikeReason? r, FeedbackReason? f) {
|
||||||
|
return ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12.0, vertical: 0.0),
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
SmartDialog.showLoading(msg: '正在提交');
|
||||||
|
var res = await VideoHttp.feedDislike(
|
||||||
|
reasonId: r?.id,
|
||||||
|
feedbackId: f?.id,
|
||||||
|
id: v.param!,
|
||||||
|
goto: v.goto!,
|
||||||
|
);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
SmartDialog.showToast(
|
||||||
|
res['status'] ? (r?.toast ?? f?.toast) : res['msg']);
|
||||||
|
Get.back();
|
||||||
|
},
|
||||||
|
child: Text(r?.name ?? f?.name ?? '未知'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('请选择'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (tp.dislikeReasons != null)
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Text('我不想看'),
|
||||||
|
),
|
||||||
|
if (tp.dislikeReasons != null)
|
||||||
|
Wrap(
|
||||||
|
spacing: 5.0,
|
||||||
|
runSpacing: 2.0,
|
||||||
|
children: tp.dislikeReasons!.map((item) {
|
||||||
|
return actionButton(item, null);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
if (tp.feedbacks != null)
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Text('反馈'),
|
||||||
|
),
|
||||||
|
if (tp.feedbacks != null)
|
||||||
|
Wrap(
|
||||||
|
spacing: 5.0,
|
||||||
|
runSpacing: 2.0,
|
||||||
|
children: tp.feedbacks!.map((item) {
|
||||||
|
return actionButton(null, item);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
//分割线
|
||||||
|
const Divider(),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
SmartDialog.showLoading(msg: '正在提交');
|
||||||
|
var res = await VideoHttp.feedDislikeCancel(
|
||||||
|
// reasonId: r?.id,
|
||||||
|
// feedbackId: f?.id,
|
||||||
|
id: v.param!,
|
||||||
|
goto: v.goto!,
|
||||||
|
);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
SmartDialog.showToast(
|
||||||
|
res['status'] ? "成功" : res['msg']);
|
||||||
|
Get.back();
|
||||||
|
},
|
||||||
|
child: const Text("撤销"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('点踩该视频?'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
const Text("web端暂不支持精细选择"),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
Wrap(
|
||||||
|
spacing: 5.0,
|
||||||
|
runSpacing: 2.0,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
SmartDialog.showLoading(msg: '正在提交');
|
||||||
|
var res = await VideoHttp.dislikeVideo(
|
||||||
|
bvid: videoItem.bvid as String, type: true);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
SmartDialog.showToast(
|
||||||
|
res['status'] ? "点踩成功" : res['msg']);
|
||||||
|
Get.back();
|
||||||
|
},
|
||||||
|
child: const Text("点踩"),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
SmartDialog.showLoading(msg: '正在提交');
|
||||||
|
var res = await VideoHttp.dislikeVideo(
|
||||||
|
bvid: videoItem.bvid as String,
|
||||||
|
type: false);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
SmartDialog.showToast(
|
||||||
|
res['status'] ? "取消踩" : res['msg']);
|
||||||
|
Get.back();
|
||||||
|
},
|
||||||
|
child: const Text("撤销"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
if (videoItem is! Item)
|
||||||
|
VideoCustomAction('拉黑:${videoItem.owner.name}', 'block',
|
||||||
|
Icon(MdiIcons.cancel, size: 16), () async {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('提示'),
|
||||||
|
content:
|
||||||
|
Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
|
||||||
|
'\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
child: Text(
|
||||||
|
'点错了',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.outline),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
var res = await VideoHttp.relationMod(
|
||||||
|
mid: videoItem.owner.mid,
|
||||||
|
act: 5,
|
||||||
|
reSrc: 11,
|
||||||
|
);
|
||||||
|
List<int> blackMidsList = GStorage.localCache
|
||||||
|
.get(LocalCacheKey.blackMidsList, defaultValue: [-1])
|
||||||
|
.map<int>((i) => i as int)
|
||||||
|
.toList();
|
||||||
|
blackMidsList.insert(0, videoItem.owner.mid);
|
||||||
|
GStorage.localCache
|
||||||
|
.put(LocalCacheKey.blackMidsList, blackMidsList);
|
||||||
|
Get.back();
|
||||||
|
SmartDialog.showToast(res['msg'] ?? '成功');
|
||||||
|
},
|
||||||
|
child: const Text('确认'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
VideoCustomAction(
|
VideoCustomAction(
|
||||||
"${MineController.anonymity ? '退出' : '进入'}无痕模式",
|
"${MineController.anonymity ? '退出' : '进入'}无痕模式",
|
||||||
'anonymity',
|
'anonymity',
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class Request {
|
|||||||
data: {
|
data: {
|
||||||
'message': await ApiInterceptor.dioError(e)
|
'message': await ApiInterceptor.dioError(e)
|
||||||
}, // 将自定义 Map 数据赋值给 Response 的 data 属性
|
}, // 将自定义 Map 数据赋值给 Response 的 data 属性
|
||||||
statusCode: 200,
|
statusCode: -1,
|
||||||
requestOptions: RequestOptions(),
|
requestOptions: RequestOptions(),
|
||||||
);
|
);
|
||||||
return errResponse;
|
return errResponse;
|
||||||
@@ -241,7 +241,7 @@ class Request {
|
|||||||
data: {
|
data: {
|
||||||
'message': await ApiInterceptor.dioError(e)
|
'message': await ApiInterceptor.dioError(e)
|
||||||
}, // 将自定义 Map 数据赋值给 Response 的 data 属性
|
}, // 将自定义 Map 数据赋值给 Response 的 data 属性
|
||||||
statusCode: 200,
|
statusCode: -1,
|
||||||
requestOptions: RequestOptions(),
|
requestOptions: RequestOptions(),
|
||||||
);
|
);
|
||||||
return errResponse;
|
return errResponse;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class _BangumiIntroPanelState extends State<BangumiIntroPanel>
|
|||||||
bangumiDetail: null,
|
bangumiDetail: null,
|
||||||
cid: cid,
|
cid: cid,
|
||||||
showEpisodes: widget.showEpisodes,
|
showEpisodes: widget.showEpisodes,
|
||||||
showIntroDetail: widget.showIntroDetail,
|
showIntroDetail: () {},
|
||||||
),
|
),
|
||||||
Success() => BangumiInfo(
|
Success() => BangumiInfo(
|
||||||
heroTag: widget.heroTag,
|
heroTag: widget.heroTag,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class IntroDetail extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
SelectableText(
|
||||||
bangumiDetail!.title,
|
bangumiDetail!.title,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@@ -97,7 +97,7 @@ class IntroDetail extends StatelessWidget {
|
|||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
SelectableText(
|
||||||
'${bangumiDetail!.evaluate!}',
|
'${bangumiDetail!.evaluate!}',
|
||||||
style: smallTitle.copyWith(fontSize: 13),
|
style: smallTitle.copyWith(fontSize: 13),
|
||||||
),
|
),
|
||||||
@@ -107,7 +107,7 @@ class IntroDetail extends StatelessWidget {
|
|||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
SelectableText(
|
||||||
bangumiDetail.actors,
|
bangumiDetail.actors,
|
||||||
style: smallTitle.copyWith(fontSize: 13),
|
style: smallTitle.copyWith(fontSize: 13),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:PiliPalaX/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -129,8 +130,8 @@ class _BangumiPanelState extends State<BangumiPanel> {
|
|||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.newEp?['desc']?.contains('连载') == true
|
widget.newEp?['desc']?.contains('连载') == true
|
||||||
? '连载中,更新至第${widget.newEp?['title']}话'
|
? '连载中,更新至${Utils.isStringNumeric(widget.newEp['title']) ? '第${widget.newEp?['title']}话' : '${widget.newEp?['title']}'}'
|
||||||
: '全${widget.newEp?['title']}话',
|
: '全${widget.pages.length}话',
|
||||||
style: const TextStyle(fontSize: 13),
|
style: const TextStyle(fontSize: 13),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -130,7 +130,6 @@ class _MemberVideoState extends State<MemberVideo>
|
|||||||
}
|
}
|
||||||
return VideoCardHMemberVideo(
|
return VideoCardHMemberVideo(
|
||||||
videoItem: loadingState.response[index],
|
videoItem: loadingState.response[index],
|
||||||
showPubdate: true,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
childCount: loadingState.response.length,
|
childCount: loadingState.response.length,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:PiliPalaX/pages/video/detail/controller.dart'
|
|||||||
show SegmentType, SegmentTypeExt, SkipType, SkipTypeExt;
|
show SegmentType, SegmentTypeExt, SkipType, SkipTypeExt;
|
||||||
import 'package:PiliPalaX/utils/storage.dart';
|
import 'package:PiliPalaX/utils/storage.dart';
|
||||||
import 'package:PiliPalaX/utils/utils.dart';
|
import 'package:PiliPalaX/utils/utils.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -57,7 +58,20 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
_checkServerStatus() {
|
_checkServerStatus() {
|
||||||
Request().get('$_blockServer/api/status').then((res) {
|
Request()
|
||||||
|
.get(
|
||||||
|
'$_blockServer/api/status',
|
||||||
|
options: Options(
|
||||||
|
headers: {
|
||||||
|
'env': '',
|
||||||
|
'app-key': '',
|
||||||
|
'x-bili-mid': '',
|
||||||
|
'x-bili-aurora-eid': '',
|
||||||
|
'x-bili-aurora-zone': '',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.then((res) {
|
||||||
if (res.data is Map) {
|
if (res.data is Map) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_serverStatus = res.data['uptime'] != null;
|
_serverStatus = res.data['uptime'] != null;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:PiliPalaX/common/constants.dart';
|
import 'package:PiliPalaX/common/constants.dart';
|
||||||
import 'package:PiliPalaX/common/widgets/icon_button.dart';
|
import 'package:PiliPalaX/common/widgets/icon_button.dart';
|
||||||
|
import 'package:PiliPalaX/common/widgets/loading_widget.dart';
|
||||||
import 'package:PiliPalaX/common/widgets/pair.dart';
|
import 'package:PiliPalaX/common/widgets/pair.dart';
|
||||||
import 'package:PiliPalaX/common/widgets/segment_progress_bar.dart';
|
import 'package:PiliPalaX/common/widgets/segment_progress_bar.dart';
|
||||||
import 'package:PiliPalaX/http/danmaku.dart';
|
import 'package:PiliPalaX/http/danmaku.dart';
|
||||||
@@ -1045,7 +1046,7 @@ class VideoDetailController extends GetxController
|
|||||||
iconButton(
|
iconButton(
|
||||||
context: context,
|
context: context,
|
||||||
size: 26,
|
size: 26,
|
||||||
tooltip: '使用当前位置',
|
tooltip: '使用当前位置时间',
|
||||||
icon: Icons.my_location,
|
icon: Icons.my_location,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -1204,6 +1205,7 @@ class VideoDetailController extends GetxController
|
|||||||
iconButton(
|
iconButton(
|
||||||
context: context,
|
context: context,
|
||||||
size: 26,
|
size: 26,
|
||||||
|
tooltip: '移除',
|
||||||
icon: Icons.clear,
|
icon: Icons.clear,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -1365,7 +1367,7 @@ class VideoDetailController extends GetxController
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: null,
|
: errorWidget(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ import 'package:url_launcher/url_launcher.dart';
|
|||||||
class Utils {
|
class Utils {
|
||||||
static final Random random = Random();
|
static final Random random = Random();
|
||||||
|
|
||||||
|
static bool isStringNumeric(str) {
|
||||||
|
RegExp numericRegex = RegExp(r'^\d+$');
|
||||||
|
return numericRegex.hasMatch(str.toString());
|
||||||
|
}
|
||||||
|
|
||||||
static ReplyInfo replyCast(res) {
|
static ReplyInfo replyCast(res) {
|
||||||
Map? emote = res['content']['emote'];
|
Map? emote = res['content']['emote'];
|
||||||
emote?.forEach((key, value) {
|
emote?.forEach((key, value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user