From b8affcef050ecc4529a06e390468d693e8247e10 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 18 Nov 2024 00:27:58 +0800 Subject: [PATCH 1/2] feat: view invalid fav video --- lib/http/api.dart | 4 ++ lib/http/common.dart | 29 ++++++++ lib/http/constants.dart | 2 + lib/models/common/invalid_video.dart | 70 +++++++++++++++++++ lib/pages/fav_detail/controller.dart | 21 ++++++ lib/pages/fav_detail/view.dart | 2 + .../fav_detail/widget/fav_video_card.dart | 22 ++++-- .../fav_detail/widget/invalid_video_card.dart | 51 ++++++++++++++ 8 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 lib/models/common/invalid_video.dart create mode 100644 lib/pages/fav_detail/widget/invalid_video_card.dart diff --git a/lib/http/api.dart b/lib/http/api.dart index 5b2cdf58..379540a5 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -622,4 +622,8 @@ class Api { /// 视频标签 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'; } diff --git a/lib/http/common.dart b/lib/http/common.dart index 2f5f0e84..87d5e2a2 100644 --- a/lib/http/common.dart +++ b/lib/http/common.dart @@ -1,3 +1,6 @@ +import 'dart:developer'; + +import 'package:pilipala/models/common/invalid_video.dart'; import 'package:pilipala/models/sponsor_block/segment.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': '没有相关信息', + }; + } + } } diff --git a/lib/http/constants.dart b/lib/http/constants.dart index 07d06958..e7e031bb 100644 --- a/lib/http/constants.dart +++ b/lib/http/constants.dart @@ -8,6 +8,8 @@ class HttpString { static const String messageBaseUrl = 'https://message.bilibili.com'; static const String bangumiBaseUrl = 'https://bili.meark.me'; static const String sponsorBlockBaseUrl = 'https://www.bsbsb.top'; + static const String biliplusBaseUrl = 'https://www.biliplus.com'; + static const List validateStatusCodes = [ 302, 304, diff --git a/lib/models/common/invalid_video.dart b/lib/models/common/invalid_video.dart new file mode 100644 index 00000000..c4813872 --- /dev/null +++ b/lib/models/common/invalid_video.dart @@ -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 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'], + ); + } +} diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 93efd3aa..022e0103 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/http/common.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/video.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/utils/utils.dart'; +import 'widget/invalid_video_card.dart'; + class FavDetailController extends GetxController { FavFolderItemData? item; 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']); + } + } } diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index 462c7df3..30a15bf4 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -226,6 +226,8 @@ class _FavDetailPageState extends State { isOwner: _favDetailController.isOwner, callFn: () => _favDetailController .onCancelFav(favList[index].id), + viewInvalidVideoCb: () => _favDetailController + .toViewInvalidVideo(favList[index]), ); }, childCount: favList.length), ), diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index ecb4dd4a..ec2a7755 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -19,6 +19,7 @@ class FavVideoCardH extends StatelessWidget { final Function? callFn; final int? searchType; final String isOwner; + final Function? viewInvalidVideoCb; const FavVideoCardH({ Key? key, @@ -26,6 +27,7 @@ class FavVideoCardH extends StatelessWidget { this.callFn, this.searchType, required this.isOwner, + this.viewInvalidVideoCb, }) : super(key: key); @override @@ -36,6 +38,10 @@ class FavVideoCardH extends StatelessWidget { return InkWell( onTap: () async { // int? seasonId; + if (videoItem.title == '已失效视频') { + viewInvalidVideoCb?.call(); + return; + } String? epId; if (videoItem.ogv != null && (videoItem.ogv['type_name'] == '番剧' || @@ -65,11 +71,17 @@ class FavVideoCardH extends StatelessWidget { epId != null ? SearchType.media_bangumi : SearchType.video, }); }, - onLongPress: () => imageSaveDialog( - context, - videoItem, - SmartDialog.dismiss, - ), + onLongPress: () { + if (videoItem.title == '已失效视频') { + SmartDialog.showToast('视频已失效'); + return; + } + imageSaveDialog( + context, + videoItem, + SmartDialog.dismiss, + ); + }, child: Column( children: [ Padding( diff --git a/lib/pages/fav_detail/widget/invalid_video_card.dart b/lib/pages/fav_detail/widget/invalid_video_card.dart new file mode 100644 index 00000000..e8e82d0e --- /dev/null +++ b/lib/pages/fav_detail/widget/invalid_video_card.dart @@ -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), + ], + ), + ); + }, + ), + ); + } +} From 85ace29282303ea5f52f1ee0887fa0e91e6fcfa5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 19 Nov 2024 23:22:33 +0800 Subject: [PATCH 2/2] mod: invalid video style --- lib/http/common.dart | 2 - lib/models/common/invalid_video.dart | 3 + .../fav_detail/widget/invalid_video_card.dart | 58 +++++++++++++++++-- 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/lib/http/common.dart b/lib/http/common.dart index 87d5e2a2..c6354900 100644 --- a/lib/http/common.dart +++ b/lib/http/common.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:pilipala/models/common/invalid_video.dart'; import 'package:pilipala/models/sponsor_block/segment.dart'; diff --git a/lib/models/common/invalid_video.dart b/lib/models/common/invalid_video.dart index c4813872..e1541f9c 100644 --- a/lib/models/common/invalid_video.dart +++ b/lib/models/common/invalid_video.dart @@ -19,6 +19,7 @@ class InvalidVideoModel { final String? videoReview; final String? favorites; final String? tag; + final List? tagList; InvalidVideoModel({ this.id, @@ -41,6 +42,7 @@ class InvalidVideoModel { this.videoReview, this.favorites, this.tag, + this.tagList, }); factory InvalidVideoModel.fromJson(Map json) { @@ -65,6 +67,7 @@ class InvalidVideoModel { videoReview: json['video_review'], favorites: json['favorites'], tag: json['tag'], + tagList: json['tag'].toString().split(',').toList(), ); } } diff --git a/lib/pages/fav_detail/widget/invalid_video_card.dart b/lib/pages/fav_detail/widget/invalid_video_card.dart index e8e82d0e..78e9ab0a 100644 --- a/lib/pages/fav_detail/widget/invalid_video_card.dart +++ b/lib/pages/fav_detail/widget/invalid_video_card.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/common/invalid_video.dart'; @@ -32,15 +33,28 @@ class InvalidVideoCard extends StatelessWidget { radius: 20, ), const SizedBox(height: 10), - SelectableText('标题:${videoInfo.title}', style: textStyle), - SelectableText('作者:${videoInfo.author}', style: textStyle), + SelectableText( + videoInfo.title!, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 2), + SelectableText(videoInfo.author!, style: textStyle), + const SizedBox(height: 2), SelectableText('创建时间:${videoInfo.createdAt}', style: textStyle), - SelectableText('上次更新时间:${videoInfo.lastupdate}', + 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), + SelectableText( + '投币:${videoInfo.coins} 收藏:${videoInfo.favorites}', + style: textStyle), + if (videoInfo.tagList != null && + videoInfo.tagList!.isNotEmpty) ...[ + const SizedBox(height: 6), + _buildTags(context, videoInfo.tagList), + ], ], ), ); @@ -48,4 +62,36 @@ class InvalidVideoCard extends StatelessWidget { ), ); } + + Widget _buildTags(BuildContext context, List? videoTags) { + final ColorScheme colorScheme = Theme.of(context).colorScheme; + return Wrap( + spacing: 6, + runSpacing: 6, + direction: Axis.horizontal, + textDirection: TextDirection.ltr, + children: videoTags!.map((tag) { + return InkWell( + onTap: () { + Get.toNamed('/searchResult', parameters: {'keyword': tag}); + }, + borderRadius: BorderRadius.circular(6), + child: Container( + decoration: BoxDecoration( + color: colorScheme.surfaceVariant.withOpacity(0.5), + borderRadius: BorderRadius.circular(6), + ), + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 10), + child: Text( + tag, + style: TextStyle( + fontSize: 12, + color: colorScheme.onSurfaceVariant, + ), + ), + ), + ); + }).toList(), + ); + } }