diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c52d8447..f119eb1e 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -45,7 +45,7 @@
android:fullBackupContent="false"
tools:replace="android:allowBackup">
NSPhotoLibraryAddUsageDescription
请允许APP保存图片到相册
+ NSPhotoLibraryUsageDescription
+ 请允许APP保存图片到相册
NSCameraUsageDescription
App需要您的同意,才能访问相册
NSAppleMusicUsageDescription
diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart
index bda8ee5c..d2772478 100644
--- a/lib/common/widgets/network_img_layer.dart
+++ b/lib/common/widgets/network_img_layer.dart
@@ -34,6 +34,9 @@ class NetworkImgLayer extends StatelessWidget {
@override
Widget build(BuildContext context) {
final int defaultImgQuality = GlobalData().imgQuality;
+ if (src == '' || src == null) {
+ return placeholder(context);
+ }
final String imageUrl =
'${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp';
int? memCacheWidth, memCacheHeight;
diff --git a/lib/common/widgets/overlay_pop.dart b/lib/common/widgets/overlay_pop.dart
deleted file mode 100644
index 4f0a3899..00000000
--- a/lib/common/widgets/overlay_pop.dart
+++ /dev/null
@@ -1,87 +0,0 @@
-import 'package:flutter/material.dart';
-import '../../utils/download.dart';
-import '../constants.dart';
-import 'network_img_layer.dart';
-
-class OverlayPop extends StatelessWidget {
- const OverlayPop({super.key, this.videoItem, this.closeFn});
-
- final dynamic videoItem;
- final Function? closeFn;
-
- @override
- Widget build(BuildContext context) {
- final double imgWidth = MediaQuery.sizeOf(context).width - 8 * 2;
- return Container(
- margin: const EdgeInsets.symmetric(horizontal: 8),
- decoration: BoxDecoration(
- color: Theme.of(context).colorScheme.background,
- borderRadius: BorderRadius.circular(10.0),
- ),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Stack(
- children: [
- NetworkImgLayer(
- width: imgWidth,
- height: imgWidth / StyleString.aspectRatio,
- src: videoItem.pic! as String,
- quality: 100,
- ),
- Positioned(
- right: 8,
- top: 8,
- child: Container(
- width: 30,
- height: 30,
- decoration: BoxDecoration(
- color: Colors.black.withOpacity(0.3),
- borderRadius:
- const BorderRadius.all(Radius.circular(20))),
- child: IconButton(
- style: ButtonStyle(
- padding: MaterialStateProperty.all(EdgeInsets.zero),
- ),
- onPressed: () => closeFn!(),
- icon: const Icon(
- Icons.close,
- size: 18,
- color: Colors.white,
- ),
- ),
- ),
- ),
- ],
- ),
- Padding(
- padding: const EdgeInsets.fromLTRB(12, 10, 8, 10),
- child: Row(
- children: [
- Expanded(
- child: Text(
- videoItem.title! as String,
- style: Theme.of(context).textTheme.titleSmall,
- ),
- ),
- const SizedBox(width: 4),
- IconButton(
- tooltip: '保存封面图',
- onPressed: () async {
- await DownloadUtils.downloadImg(
- videoItem.pic != null
- ? videoItem.pic as String
- : videoItem.cover as String,
- );
- // closeFn!();
- },
- icon: const Icon(Icons.download, size: 20),
- )
- ],
- )),
- ],
- ),
- );
- }
-}
diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart
index 25e701ac..1265477f 100644
--- a/lib/common/widgets/video_card_h.dart
+++ b/lib/common/widgets/video_card_h.dart
@@ -1,6 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
+import 'package:pilipala/http/constants.dart';
+import 'package:pilipala/utils/feed_back.dart';
+import 'package:pilipala/utils/image_save.dart';
+import 'package:pilipala/utils/route_push.dart';
+import 'package:pilipala/utils/url_utils.dart';
import '../../http/search.dart';
import '../../http/user.dart';
import '../../http/video.dart';
@@ -16,8 +21,7 @@ class VideoCardH extends StatelessWidget {
const VideoCardH({
super.key,
required this.videoItem,
- this.longPress,
- this.longPressEnd,
+ this.onPressedFn,
this.source = 'normal',
this.showOwner = true,
this.showView = true,
@@ -27,8 +31,8 @@ class VideoCardH extends StatelessWidget {
});
// ignore: prefer_typing_uninitialized_variables
final videoItem;
- final Function()? longPress;
- final Function()? longPressEnd;
+ final Function()? onPressedFn;
+ // normal 推荐, later 稍后再看, search 搜索
final String source;
final bool showOwner;
final bool showView;
@@ -45,109 +49,117 @@ class VideoCardH extends StatelessWidget {
type = videoItem.type;
} catch (_) {}
final String heroTag = Utils.makeHeroTag(aid);
- return GestureDetector(
- onLongPress: () {
- if (longPress != null) {
- longPress!();
+ return InkWell(
+ onTap: () async {
+ try {
+ if (type == 'ketang') {
+ SmartDialog.showToast('课堂视频暂不支持播放');
+ return;
+ }
+ if (showCharge && videoItem?.typeid == 33) {
+ final String redirectUrl = await UrlUtils.parseRedirectUrl(
+ '${HttpString.baseUrl}/video/$bvid/');
+ final String lastPathSegment = redirectUrl.split('/').last;
+ if (lastPathSegment.contains('ss')) {
+ RoutePush.bangumiPush(
+ Utils.matchNum(lastPathSegment).first, null);
+ }
+ if (lastPathSegment.contains('ep')) {
+ RoutePush.bangumiPush(
+ null, Utils.matchNum(lastPathSegment).first);
+ }
+ return;
+ }
+ final int cid =
+ videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
+ Get.toNamed('/video?bvid=$bvid&cid=$cid',
+ arguments: {'videoItem': videoItem, 'heroTag': heroTag});
+ } catch (err) {
+ SmartDialog.showToast(err.toString());
}
},
- // onLongPressEnd: (details) {
- // if (longPressEnd != null) {
- // longPressEnd!();
- // }
- // },
- child: InkWell(
- onTap: () async {
- try {
- if (type == 'ketang') {
- SmartDialog.showToast('课堂视频暂不支持播放');
- return;
- }
- final int cid =
- videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
- Get.toNamed('/video?bvid=$bvid&cid=$cid',
- arguments: {'videoItem': videoItem, 'heroTag': heroTag});
- } catch (err) {
- SmartDialog.showToast(err.toString());
- }
- },
- child: Padding(
- padding: const EdgeInsets.fromLTRB(
- StyleString.safeSpace, 5, StyleString.safeSpace, 5),
- child: LayoutBuilder(
- builder: (BuildContext context, BoxConstraints boxConstraints) {
- final double width = (boxConstraints.maxWidth -
- StyleString.cardSpace *
- 6 /
- MediaQuery.textScalerOf(context).scale(1.0)) /
- 2;
- return Container(
- constraints: const BoxConstraints(minHeight: 88),
- height: width / StyleString.aspectRatio,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- 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.pic as String,
- width: maxWidth,
- height: maxHeight,
- ),
+ onLongPress: () => imageSaveDialog(
+ context,
+ videoItem,
+ SmartDialog.dismiss,
+ ),
+ child: Padding(
+ padding: const EdgeInsets.fromLTRB(
+ StyleString.safeSpace, 5, StyleString.safeSpace, 5),
+ child: LayoutBuilder(
+ builder: (BuildContext context, BoxConstraints boxConstraints) {
+ final double width = (boxConstraints.maxWidth -
+ StyleString.cardSpace *
+ 6 /
+ MediaQuery.textScalerOf(context).scale(1.0)) /
+ 2;
+ return Container(
+ constraints: const BoxConstraints(minHeight: 88),
+ height: width / StyleString.aspectRatio,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ 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.pic as String,
+ width: maxWidth,
+ height: maxHeight,
),
- if (videoItem.duration != 0)
- PBadge(
- text: Utils.timeFormat(videoItem.duration!),
- right: 6.0,
- 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),
- if (showCharge && videoItem?.isChargingSrc)
- const PBadge(
- text: '充电专属',
- right: 6.0,
- top: 6.0,
- type: 'primary',
- ),
- ],
- );
- },
- ),
+ ),
+ if (videoItem.duration != 0)
+ PBadge(
+ text: Utils.timeFormat(videoItem.duration!),
+ right: 6.0,
+ 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),
+ if (showCharge && videoItem?.isChargingSrc)
+ const PBadge(
+ text: '充电专属',
+ right: 6.0,
+ top: 6.0,
+ type: 'primary',
+ ),
+ ],
+ );
+ },
),
- VideoContent(
- videoItem: videoItem,
- source: source,
- showOwner: showOwner,
- showView: showView,
- showDanmaku: showDanmaku,
- showPubdate: showPubdate,
- )
- ],
- ),
- );
- },
- ),
+ ),
+ VideoContent(
+ videoItem: videoItem,
+ source: source,
+ showOwner: showOwner,
+ showView: showView,
+ showDanmaku: showDanmaku,
+ showPubdate: showPubdate,
+ onPressedFn: onPressedFn,
+ )
+ ],
+ ),
+ );
+ },
),
),
);
@@ -162,6 +174,7 @@ class VideoContent extends StatelessWidget {
final bool showView;
final bool showDanmaku;
final bool showPubdate;
+ final Function()? onPressedFn;
const VideoContent({
super.key,
@@ -171,6 +184,7 @@ class VideoContent extends StatelessWidget {
this.showView = true,
this.showDanmaku = true,
this.showPubdate = false,
+ this.onPressedFn,
});
@override
@@ -181,7 +195,7 @@ class VideoContent extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- if (videoItem.title is String) ...[
+ if (source == 'normal' || source == 'later') ...[
Text(
videoItem.title as String,
textAlign: TextAlign.start,
@@ -196,7 +210,7 @@ class VideoContent extends StatelessWidget {
maxLines: 2,
text: TextSpan(
children: [
- for (final i in videoItem.title) ...[
+ for (final i in videoItem.titleList) ...[
TextSpan(
text: i['text'] as String,
style: TextStyle(
@@ -263,117 +277,44 @@ class VideoContent extends StatelessWidget {
theme: 'gray',
danmu: videoItem.stat.danmaku as int,
),
-
const Spacer(),
- // SizedBox(
- // width: 20,
- // height: 20,
- // child: IconButton(
- // tooltip: '稍后再看',
- // style: ButtonStyle(
- // padding: MaterialStateProperty.all(EdgeInsets.zero),
- // ),
- // onPressed: () async {
- // var res =
- // await UserHttp.toViewLater(bvid: videoItem.bvid);
- // SmartDialog.showToast(res['msg']);
- // },
- // icon: Icon(
- // Icons.more_vert_outlined,
- // color: Theme.of(context).colorScheme.outline,
- // size: 14,
- // ),
- // ),
- // ),
if (source == 'normal')
SizedBox(
width: 24,
height: 24,
- child: PopupMenuButton(
+ child: IconButton(
padding: EdgeInsets.zero,
+ onPressed: () {
+ feedBack();
+ showModalBottomSheet(
+ context: context,
+ useRootNavigator: true,
+ isScrollControlled: true,
+ builder: (context) {
+ return MorePanel(videoItem: videoItem);
+ },
+ );
+ },
icon: Icon(
Icons.more_vert_outlined,
color: Theme.of(context).colorScheme.outline,
size: 14,
),
- position: PopupMenuPosition.under,
- // constraints: const BoxConstraints(maxHeight: 35),
- onSelected: (String type) {},
- itemBuilder: (BuildContext context) =>
- >[
- PopupMenuItem(
- onTap: () async {
- var res = await UserHttp.toViewLater(
- bvid: videoItem.bvid as String);
- SmartDialog.showToast(res['msg']);
- },
- value: 'pause',
- height: 40,
- child: const Row(
- children: [
- Icon(Icons.watch_later_outlined, size: 16),
- SizedBox(width: 6),
- Text('稍后再看', style: TextStyle(fontSize: 13))
- ],
- ),
- ),
- const PopupMenuDivider(),
- PopupMenuItem(
- onTap: () async {
- SmartDialog.show(
- useSystem: true,
- animationType:
- SmartAnimationType.centerFade_otherSlide,
- builder: (BuildContext context) {
- return AlertDialog(
- title: const Text('提示'),
- content: Text(
- '确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
- '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'),
- actions: [
- TextButton(
- onPressed: () => SmartDialog.dismiss(),
- 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,
- );
- SmartDialog.dismiss();
- SmartDialog.showToast(res['code'] == 0
- ? '成功'
- : res['msg']);
- },
- child: const Text('确认'),
- )
- ],
- );
- },
- );
- },
- value: 'pause',
- height: 40,
- child: Row(
- children: [
- const Icon(Icons.block, size: 16),
- const SizedBox(width: 6),
- Text('拉黑:${videoItem.owner.name}',
- style: const TextStyle(fontSize: 13))
- ],
- ),
- ),
- ],
),
),
+ if (source == 'later') ...[
+ IconButton(
+ style: ButtonStyle(
+ padding: MaterialStateProperty.all(EdgeInsets.zero),
+ ),
+ onPressed: () => onPressedFn?.call(),
+ icon: Icon(
+ Icons.clear_outlined,
+ color: Theme.of(context).colorScheme.outline,
+ size: 18,
+ ),
+ )
+ ],
],
),
],
@@ -382,3 +323,110 @@ class VideoContent extends StatelessWidget {
);
}
}
+
+class MorePanel extends StatelessWidget {
+ final dynamic videoItem;
+ const MorePanel({super.key, required this.videoItem});
+
+ Future menuActionHandler(String type) async {
+ switch (type) {
+ case 'block':
+ blockUser();
+ break;
+ case 'watchLater':
+ var res = await UserHttp.toViewLater(bvid: videoItem.bvid as String);
+ SmartDialog.showToast(res['msg']);
+ Get.back();
+ break;
+ default:
+ }
+ }
+
+ void blockUser() async {
+ SmartDialog.show(
+ useSystem: true,
+ animationType: SmartAnimationType.centerFade_otherSlide,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ title: const Text('提示'),
+ content: Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
+ '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'),
+ actions: [
+ TextButton(
+ onPressed: () => SmartDialog.dismiss(),
+ 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,
+ );
+ SmartDialog.dismiss();
+ SmartDialog.showToast(res['msg'] ?? '成功');
+ },
+ child: const Text('确认'),
+ )
+ ],
+ );
+ },
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ InkWell(
+ onTap: () => Get.back(),
+ child: Container(
+ height: 35,
+ padding: const EdgeInsets.only(bottom: 2),
+ child: Center(
+ child: Container(
+ width: 32,
+ height: 3,
+ decoration: BoxDecoration(
+ color: Theme.of(context).colorScheme.outline,
+ borderRadius: const BorderRadius.all(Radius.circular(3))),
+ ),
+ ),
+ ),
+ ),
+ ListTile(
+ onTap: () async => await menuActionHandler('block'),
+ minLeadingWidth: 0,
+ leading: const Icon(Icons.block, size: 19),
+ title: Text(
+ '拉黑up主 「${videoItem.owner.name}」',
+ style: Theme.of(context).textTheme.titleSmall,
+ ),
+ ),
+ ListTile(
+ onTap: () async => await menuActionHandler('watchLater'),
+ minLeadingWidth: 0,
+ leading: const Icon(Icons.watch_later_outlined, size: 19),
+ title:
+ Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall),
+ ),
+ ListTile(
+ onTap: () =>
+ imageSaveDialog(context, videoItem, SmartDialog.dismiss),
+ minLeadingWidth: 0,
+ leading: const Icon(Icons.photo_outlined, size: 19),
+ title:
+ Text('查看视频封面', style: Theme.of(context).textTheme.titleSmall),
+ ),
+ const SizedBox(height: 20),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart
index 9916aa7a..7b56152f 100644
--- a/lib/common/widgets/video_card_v.dart
+++ b/lib/common/widgets/video_card_v.dart
@@ -2,15 +2,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/utils/feed_back.dart';
+import 'package:pilipala/utils/image_save.dart';
+import 'package:pilipala/utils/route_push.dart';
import '../../models/model_rec_video_item.dart';
-import 'overlay_pop.dart';
import 'stat/danmu.dart';
import 'stat/view.dart';
import '../../http/dynamics.dart';
-import '../../http/search.dart';
import '../../http/user.dart';
import '../../http/video.dart';
-import '../../models/common/search_type.dart';
import '../../utils/id_utils.dart';
import '../../utils/utils.dart';
import '../constants.dart';
@@ -42,23 +41,11 @@ class VideoCardV extends StatelessWidget {
return;
}
int epId = videoItem.param;
- SmartDialog.showLoading(msg: '资源获取中');
- var result = await SearchHttp.bangumiInfo(seasonId: null, epId: epId);
- if (result['status']) {
- var bangumiDetail = result['data'];
- int cid = bangumiDetail.episodes!.first.cid;
- String bvid = IdUtils.av2bv(bangumiDetail.episodes!.first.aid);
- SmartDialog.dismiss().then(
- (value) => Get.toNamed(
- '/video?bvid=$bvid&cid=$cid&epId=$epId',
- arguments: {
- 'pic': videoItem.pic,
- 'heroTag': heroTag,
- 'videoType': SearchType.media_bangumi,
- },
- ),
- );
- }
+ RoutePush.bangumiPush(
+ null,
+ epId,
+ heroTag: heroTag,
+ );
break;
case 'av':
String bvid = videoItem.bvid ?? IdUtils.av2bv(videoItem.aid);
@@ -127,14 +114,11 @@ class VideoCardV extends StatelessWidget {
String heroTag = Utils.makeHeroTag(videoItem.id);
return InkWell(
onTap: () async => onPushDetail(heroTag),
- onLongPress: () {
- SmartDialog.show(
- builder: (context) => OverlayPop(
- videoItem: videoItem,
- closeFn: () => SmartDialog.dismiss(),
- ),
- );
- },
+ onLongPress: () => imageSaveDialog(
+ context,
+ videoItem,
+ SmartDialog.dismiss,
+ ),
borderRadius: BorderRadius.circular(16),
child: Column(
children: [
@@ -249,6 +233,7 @@ class VideoContent extends StatelessWidget {
width: 24,
height: 24,
child: IconButton(
+ padding: EdgeInsets.zero,
onPressed: () {
feedBack();
showModalBottomSheet(
@@ -402,6 +387,15 @@ class MorePanel extends StatelessWidget {
title:
Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall),
),
+ ListTile(
+ onTap: () =>
+ imageSaveDialog(context, videoItem, SmartDialog.dismiss),
+ minLeadingWidth: 0,
+ leading: const Icon(Icons.photo_outlined, size: 19),
+ title:
+ Text('查看视频封面', style: Theme.of(context).textTheme.titleSmall),
+ ),
+ const SizedBox(height: 20),
],
),
);
diff --git a/lib/http/api.dart b/lib/http/api.dart
index 1735902c..42fc03b8 100644
--- a/lib/http/api.dart
+++ b/lib/http/api.dart
@@ -520,4 +520,7 @@ class Api {
/// 删除收藏夹
static const String delFavFolder = '/x/v3/fav/folder/del';
+
+ /// 搜索结果计数
+ static const String searchCount = '/x/web-interface/wbi/search/all/v2';
}
diff --git a/lib/http/dynamics.dart b/lib/http/dynamics.dart
index 63dea4ff..69619361 100644
--- a/lib/http/dynamics.dart
+++ b/lib/http/dynamics.dart
@@ -41,6 +41,7 @@ class DynamicsHttp {
'status': false,
'data': [],
'msg': res.data['message'],
+ 'code': res.data['code'],
};
}
}
diff --git a/lib/http/interceptor.dart b/lib/http/interceptor.dart
index a5359283..10b5aee5 100644
--- a/lib/http/interceptor.dart
+++ b/lib/http/interceptor.dart
@@ -46,7 +46,7 @@ class ApiInterceptor extends Interceptor {
// 处理网络请求错误
// handler.next(err);
String url = err.requestOptions.uri.toString();
- if (!url.contains('heartBeat')) {
+ if (!url.contains('heartbeat')) {
SmartDialog.showToast(
await dioError(err),
displayType: SmartToastType.onlyRefresh,
diff --git a/lib/http/search.dart b/lib/http/search.dart
index 18481ea8..9b493a84 100644
--- a/lib/http/search.dart
+++ b/lib/http/search.dart
@@ -1,5 +1,7 @@
import 'dart:convert';
import 'package:hive/hive.dart';
+import 'package:pilipala/models/search/all.dart';
+import 'package:pilipala/utils/wbi_sign.dart';
import '../models/bangumi/info.dart';
import '../models/common/search_type.dart';
import '../models/search/hot.dart';
@@ -163,4 +165,42 @@ class SearchHttp {
};
}
}
+
+ static Future