feat: view invalid fav video
This commit is contained in:
@ -622,4 +622,8 @@ class Api {
|
|||||||
|
|
||||||
/// 视频标签
|
/// 视频标签
|
||||||
static const String videoTag = '/x/tag/archive/tags';
|
static const String videoTag = '/x/tag/archive/tags';
|
||||||
|
|
||||||
|
/// 修复标题和海报
|
||||||
|
// /api/view?id=${aid} /all/video/av${aid} /video/av${aid}/
|
||||||
|
static const String fixTitleAndPic = '${HttpString.biliplusBaseUrl}/api/view';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:pilipala/models/common/invalid_video.dart';
|
||||||
import 'package:pilipala/models/sponsor_block/segment.dart';
|
import 'package:pilipala/models/sponsor_block/segment.dart';
|
||||||
|
|
||||||
import 'index.dart';
|
import 'index.dart';
|
||||||
@ -43,4 +46,30 @@ class CommonHttp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future fixVideoPicAndTitle({required int aid}) async {
|
||||||
|
var res = await Request().getWithoutCookie(Api.fixTitleAndPic, data: {
|
||||||
|
'id': aid,
|
||||||
|
});
|
||||||
|
if (res != null) {
|
||||||
|
if (res.data['code'] == -404) {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': null,
|
||||||
|
'msg': '没有相关信息',
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': true,
|
||||||
|
'data': InvalidVideoModel.fromJson(res.data),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
'status': false,
|
||||||
|
'data': null,
|
||||||
|
'msg': '没有相关信息',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ class HttpString {
|
|||||||
static const String messageBaseUrl = 'https://message.bilibili.com';
|
static const String messageBaseUrl = 'https://message.bilibili.com';
|
||||||
static const String bangumiBaseUrl = 'https://bili.meark.me';
|
static const String bangumiBaseUrl = 'https://bili.meark.me';
|
||||||
static const String sponsorBlockBaseUrl = 'https://www.bsbsb.top';
|
static const String sponsorBlockBaseUrl = 'https://www.bsbsb.top';
|
||||||
|
static const String biliplusBaseUrl = 'https://www.biliplus.com';
|
||||||
|
|
||||||
static const List<int> validateStatusCodes = [
|
static const List<int> validateStatusCodes = [
|
||||||
302,
|
302,
|
||||||
304,
|
304,
|
||||||
|
|||||||
70
lib/models/common/invalid_video.dart
Normal file
70
lib/models/common/invalid_video.dart
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
class InvalidVideoModel {
|
||||||
|
final int? id;
|
||||||
|
final int? ver;
|
||||||
|
final int? aid;
|
||||||
|
final String? lastupdate;
|
||||||
|
final int? lastupdatets;
|
||||||
|
final String? title;
|
||||||
|
final String? description;
|
||||||
|
final String? pic;
|
||||||
|
final int? tid;
|
||||||
|
final String? typename;
|
||||||
|
final int? created;
|
||||||
|
final String? createdAt;
|
||||||
|
final String? author;
|
||||||
|
final int? mid;
|
||||||
|
final String? play;
|
||||||
|
final String? coins;
|
||||||
|
final String? review;
|
||||||
|
final String? videoReview;
|
||||||
|
final String? favorites;
|
||||||
|
final String? tag;
|
||||||
|
|
||||||
|
InvalidVideoModel({
|
||||||
|
this.id,
|
||||||
|
this.ver,
|
||||||
|
this.aid,
|
||||||
|
this.lastupdate,
|
||||||
|
this.lastupdatets,
|
||||||
|
this.title,
|
||||||
|
this.description,
|
||||||
|
this.pic,
|
||||||
|
this.tid,
|
||||||
|
this.typename,
|
||||||
|
this.created,
|
||||||
|
this.createdAt,
|
||||||
|
this.author,
|
||||||
|
this.mid,
|
||||||
|
this.play,
|
||||||
|
this.coins,
|
||||||
|
this.review,
|
||||||
|
this.videoReview,
|
||||||
|
this.favorites,
|
||||||
|
this.tag,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory InvalidVideoModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return InvalidVideoModel(
|
||||||
|
id: json['id'],
|
||||||
|
ver: json['ver'],
|
||||||
|
aid: json['aid'],
|
||||||
|
lastupdate: json['lastupdate'],
|
||||||
|
lastupdatets: json['lastupdatets'],
|
||||||
|
title: json['title'],
|
||||||
|
description: json['description'],
|
||||||
|
pic: json['pic'],
|
||||||
|
tid: json['tid'],
|
||||||
|
typename: json['typename'],
|
||||||
|
created: json['created'],
|
||||||
|
createdAt: json['created_at'],
|
||||||
|
author: json['author'],
|
||||||
|
mid: json['mid'],
|
||||||
|
play: json['play'],
|
||||||
|
coins: json['coins'],
|
||||||
|
review: json['review'],
|
||||||
|
videoReview: json['video_review'],
|
||||||
|
favorites: json['favorites'],
|
||||||
|
tag: json['tag'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
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';
|
||||||
|
import 'package:pilipala/http/common.dart';
|
||||||
import 'package:pilipala/http/user.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
import 'package:pilipala/http/video.dart';
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/user/fav_detail.dart';
|
import 'package:pilipala/models/user/fav_detail.dart';
|
||||||
@ -8,6 +9,8 @@ import 'package:pilipala/models/user/fav_folder.dart';
|
|||||||
import 'package:pilipala/pages/fav/index.dart';
|
import 'package:pilipala/pages/fav/index.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
|
import 'widget/invalid_video_card.dart';
|
||||||
|
|
||||||
class FavDetailController extends GetxController {
|
class FavDetailController extends GetxController {
|
||||||
FavFolderItemData? item;
|
FavFolderItemData? item;
|
||||||
RxString title = ''.obs;
|
RxString title = ''.obs;
|
||||||
@ -152,4 +155,22 @@ class FavDetailController extends GetxController {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查看无效视频信息
|
||||||
|
Future toViewInvalidVideo(FavDetailItemData item) async {
|
||||||
|
SmartDialog.showLoading(msg: '加载中...');
|
||||||
|
var res = await CommonHttp.fixVideoPicAndTitle(aid: item.id!);
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
if (res['status']) {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: Get.context!,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) {
|
||||||
|
return InvalidVideoCard(videoInfo: res['data']);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
SmartDialog.showToast(res['msg']);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -226,6 +226,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
isOwner: _favDetailController.isOwner,
|
isOwner: _favDetailController.isOwner,
|
||||||
callFn: () => _favDetailController
|
callFn: () => _favDetailController
|
||||||
.onCancelFav(favList[index].id),
|
.onCancelFav(favList[index].id),
|
||||||
|
viewInvalidVideoCb: () => _favDetailController
|
||||||
|
.toViewInvalidVideo(favList[index]),
|
||||||
);
|
);
|
||||||
}, childCount: favList.length),
|
}, childCount: favList.length),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -19,6 +19,7 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
final Function? callFn;
|
final Function? callFn;
|
||||||
final int? searchType;
|
final int? searchType;
|
||||||
final String isOwner;
|
final String isOwner;
|
||||||
|
final Function? viewInvalidVideoCb;
|
||||||
|
|
||||||
const FavVideoCardH({
|
const FavVideoCardH({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -26,6 +27,7 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
this.callFn,
|
this.callFn,
|
||||||
this.searchType,
|
this.searchType,
|
||||||
required this.isOwner,
|
required this.isOwner,
|
||||||
|
this.viewInvalidVideoCb,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -36,6 +38,10 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// int? seasonId;
|
// int? seasonId;
|
||||||
|
if (videoItem.title == '已失效视频') {
|
||||||
|
viewInvalidVideoCb?.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
String? epId;
|
String? epId;
|
||||||
if (videoItem.ogv != null &&
|
if (videoItem.ogv != null &&
|
||||||
(videoItem.ogv['type_name'] == '番剧' ||
|
(videoItem.ogv['type_name'] == '番剧' ||
|
||||||
@ -65,11 +71,17 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
epId != null ? SearchType.media_bangumi : SearchType.video,
|
epId != null ? SearchType.media_bangumi : SearchType.video,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onLongPress: () => imageSaveDialog(
|
onLongPress: () {
|
||||||
context,
|
if (videoItem.title == '已失效视频') {
|
||||||
videoItem,
|
SmartDialog.showToast('视频已失效');
|
||||||
SmartDialog.dismiss,
|
return;
|
||||||
),
|
}
|
||||||
|
imageSaveDialog(
|
||||||
|
context,
|
||||||
|
videoItem,
|
||||||
|
SmartDialog.dismiss,
|
||||||
|
);
|
||||||
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
51
lib/pages/fav_detail/widget/invalid_video_card.dart
Normal file
51
lib/pages/fav_detail/widget/invalid_video_card.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
import 'package:pilipala/models/common/invalid_video.dart';
|
||||||
|
|
||||||
|
class InvalidVideoCard extends StatelessWidget {
|
||||||
|
const InvalidVideoCard({required this.videoInfo, Key? key}) : super(key: key);
|
||||||
|
final InvalidVideoModel videoInfo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const TextStyle textStyle = TextStyle(fontSize: 14.0);
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(
|
||||||
|
12,
|
||||||
|
14,
|
||||||
|
12,
|
||||||
|
MediaQuery.of(context).padding.bottom + 20,
|
||||||
|
),
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
double maxWidth = constraints.maxWidth;
|
||||||
|
double maxHeight = maxWidth * 9 / 16;
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
NetworkImgLayer(
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
src: videoInfo.pic,
|
||||||
|
radius: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
SelectableText('标题:${videoInfo.title}', style: textStyle),
|
||||||
|
SelectableText('作者:${videoInfo.author}', style: textStyle),
|
||||||
|
SelectableText('创建时间:${videoInfo.createdAt}', style: textStyle),
|
||||||
|
SelectableText('上次更新时间:${videoInfo.lastupdate}',
|
||||||
|
style: textStyle),
|
||||||
|
SelectableText('分类:${videoInfo.typename}', style: textStyle),
|
||||||
|
SelectableText('投币:${videoInfo.coins}', style: textStyle),
|
||||||
|
SelectableText('收藏:${videoInfo.favorites}', style: textStyle),
|
||||||
|
SelectableText('标签:${videoInfo.tag}', style: textStyle),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user