mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: webview to video
Closes #209 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -9,11 +9,11 @@ import 'package:PiliPlus/utils/utils.dart';
|
|||||||
|
|
||||||
class SearchPanelController extends CommonController {
|
class SearchPanelController extends CommonController {
|
||||||
SearchPanelController({
|
SearchPanelController({
|
||||||
this.keyword,
|
required this.keyword,
|
||||||
required this.searchType,
|
required this.searchType,
|
||||||
required this.tag,
|
required this.tag,
|
||||||
});
|
});
|
||||||
String? keyword;
|
String keyword;
|
||||||
SearchType searchType;
|
SearchType searchType;
|
||||||
// 结果排序方式 搜索类型为视频、专栏及相簿时
|
// 结果排序方式 搜索类型为视频、专栏及相簿时
|
||||||
RxString order = ''.obs;
|
RxString order = ''.obs;
|
||||||
@@ -99,7 +99,7 @@ class SearchPanelController extends CommonController {
|
|||||||
@override
|
@override
|
||||||
Future<LoadingState> customGetData() => SearchHttp.searchByType(
|
Future<LoadingState> customGetData() => SearchHttp.searchByType(
|
||||||
searchType: searchType,
|
searchType: searchType,
|
||||||
keyword: keyword!,
|
keyword: keyword,
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
order: order.value,
|
order: order.value,
|
||||||
duration: searchType.name != 'video' ? null : duration.value,
|
duration: searchType.name != 'video' ? null : duration.value,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import 'widgets/media_bangumi_panel.dart';
|
|||||||
import 'widgets/user_panel.dart';
|
import 'widgets/user_panel.dart';
|
||||||
|
|
||||||
class SearchPanel extends StatefulWidget {
|
class SearchPanel extends StatefulWidget {
|
||||||
final String? keyword;
|
final String keyword;
|
||||||
final SearchType searchType;
|
final SearchType searchType;
|
||||||
final String tag;
|
final String tag;
|
||||||
const SearchPanel({
|
const SearchPanel({
|
||||||
@@ -46,7 +46,7 @@ class _SearchPanelState extends State<SearchPanel>
|
|||||||
searchType: widget.searchType,
|
searchType: widget.searchType,
|
||||||
tag: widget.tag,
|
tag: widget.tag,
|
||||||
),
|
),
|
||||||
tag: widget.searchType.name + widget.keyword!,
|
tag: widget.searchType.name + widget.keyword,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ class ArticlePanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'article${searchPanelCtr.keyword!}');
|
tag: 'article${searchPanelCtr.keyword}');
|
||||||
ctr.order.value = item['order'];
|
ctr.order.value = item['order'];
|
||||||
SmartDialog.showLoading(msg: 'loading');
|
SmartDialog.showLoading(msg: 'loading');
|
||||||
await ctr.onRefresh();
|
await ctr.onRefresh();
|
||||||
@@ -321,7 +321,7 @@ class ArticlePanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'article${searchPanelCtr.keyword!}');
|
tag: 'article${searchPanelCtr.keyword}');
|
||||||
ctr.categoryId = item['categoryId'];
|
ctr.categoryId = item['categoryId'];
|
||||||
SmartDialog.showLoading(msg: 'loading');
|
SmartDialog.showLoading(msg: 'loading');
|
||||||
await ctr.onRefresh();
|
await ctr.onRefresh();
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ class UserPanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'bili_user${searchPanelCtr.keyword!}');
|
tag: 'bili_user${searchPanelCtr.keyword}');
|
||||||
ctr.orderSort = item['orderSort'];
|
ctr.orderSort = item['orderSort'];
|
||||||
ctr.order.value = item['order'];
|
ctr.order.value = item['order'];
|
||||||
SmartDialog.showLoading(msg: 'loading');
|
SmartDialog.showLoading(msg: 'loading');
|
||||||
@@ -249,7 +249,7 @@ class UserPanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'bili_user${searchPanelCtr.keyword!}');
|
tag: 'bili_user${searchPanelCtr.keyword}');
|
||||||
ctr.userType = item['userType'];
|
ctr.userType = item['userType'];
|
||||||
SmartDialog.showLoading(msg: 'loading');
|
SmartDialog.showLoading(msg: 'loading');
|
||||||
await ctr.onRefresh();
|
await ctr.onRefresh();
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ class VideoPanelController extends GetxController {
|
|||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
// SmartDialog.showToast("「${item['label']}」的筛选结果");
|
// SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr = Get.find<SearchPanelController>(
|
SearchPanelController ctr = Get.find<SearchPanelController>(
|
||||||
tag: 'video${searchPanelCtr.keyword!}');
|
tag: 'video${searchPanelCtr.keyword}');
|
||||||
ctr.pubBegin = DateTime(
|
ctr.pubBegin = DateTime(
|
||||||
pubBegin.year,
|
pubBegin.year,
|
||||||
pubBegin.month,
|
pubBegin.month,
|
||||||
@@ -345,7 +345,7 @@ class VideoPanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'video${searchPanelCtr.keyword!}');
|
tag: 'video${searchPanelCtr.keyword}');
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
if (item['value'] == 0) {
|
if (item['value'] == 0) {
|
||||||
ctr.pubBegin = null;
|
ctr.pubBegin = null;
|
||||||
@@ -424,7 +424,7 @@ class VideoPanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'video${searchPanelCtr.keyword!}');
|
tag: 'video${searchPanelCtr.keyword}');
|
||||||
ctr.duration.value = item['value'];
|
ctr.duration.value = item['value'];
|
||||||
SmartDialog.showLoading(msg: 'loading');
|
SmartDialog.showLoading(msg: 'loading');
|
||||||
await ctr.onRefresh();
|
await ctr.onRefresh();
|
||||||
@@ -462,7 +462,7 @@ class VideoPanelController extends GetxController {
|
|||||||
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
SmartDialog.showToast("「${item['label']}」的筛选结果");
|
||||||
SearchPanelController ctr =
|
SearchPanelController ctr =
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: 'video${searchPanelCtr.keyword!}');
|
tag: 'video${searchPanelCtr.keyword}');
|
||||||
ctr.tids = item['tids'];
|
ctr.tids = item['tids'];
|
||||||
SmartDialog.showLoading(msg: 'loading');
|
SmartDialog.showLoading(msg: 'loading');
|
||||||
await ctr.onRefresh();
|
await ctr.onRefresh();
|
||||||
|
|||||||
@@ -2,16 +2,8 @@ import 'package:PiliPlus/models/common/search_type.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class SearchResultController extends GetxController {
|
class SearchResultController extends GetxController {
|
||||||
String? keyword;
|
String keyword = Get.parameters['keyword'] ?? '';
|
||||||
|
|
||||||
RxList<int> count =
|
RxList<int> count =
|
||||||
List.generate(SearchType.values.length, (_) => -1).toList().obs;
|
List.generate(SearchType.values.length, (_) => -1).toList().obs;
|
||||||
|
|
||||||
@override
|
|
||||||
void onInit() {
|
|
||||||
super.onInit();
|
|
||||||
if (Get.parameters.keys.isNotEmpty) {
|
|
||||||
keyword = Get.parameters['keyword'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class _SearchResultPageState extends State<SearchResultPage>
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Text(
|
child: Text(
|
||||||
'${_searchResultController.keyword}',
|
_searchResultController.keyword,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -110,7 +110,7 @@ class _SearchResultPageState extends State<SearchResultPage>
|
|||||||
if (_tabController.indexIsChanging.not) {
|
if (_tabController.indexIsChanging.not) {
|
||||||
Get.find<SearchPanelController>(
|
Get.find<SearchPanelController>(
|
||||||
tag: SearchType.values[index].name +
|
tag: SearchType.values[index].name +
|
||||||
_searchResultController.keyword!)
|
_searchResultController.keyword)
|
||||||
.animateToTop();
|
.animateToTop();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -198,35 +198,38 @@ class _WebviewPageNewState extends State<WebviewPageNew> {
|
|||||||
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
shouldOverrideUrlLoading: (controller, navigationAction) async {
|
||||||
final String? str =
|
final String? str =
|
||||||
navigationAction.request.url!.pathSegments.getOrNull(0);
|
navigationAction.request.url!.pathSegments.getOrNull(0);
|
||||||
final Map matchRes = IdUtils.matchAvorBv(input: str);
|
if (str != null) {
|
||||||
final List matchKeys = matchRes.keys.toList();
|
final Map matchRes = IdUtils.matchAvorBv(input: str);
|
||||||
if (matchKeys.isNotEmpty) {
|
if (matchRes.isNotEmpty) {
|
||||||
if (matchKeys.first == 'BV') {
|
Get.back();
|
||||||
Get.offAndToNamed(
|
PiliScheme.videoPush(matchRes['AV'], matchRes['BV']);
|
||||||
'/searchResult',
|
|
||||||
parameters: {'keyword': matchRes['BV']},
|
|
||||||
);
|
|
||||||
return NavigationActionPolicy.CANCEL;
|
return NavigationActionPolicy.CANCEL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = navigationAction.request.url!.toString();
|
var url = navigationAction.request.url!.toString();
|
||||||
|
|
||||||
if (url.startsWith('http')) {
|
if (RegExp(
|
||||||
if (RegExp(r'https://www.bilibili.com/video/BV[a-zA-Z\d]+')
|
r'^(https?://)?((www|m).)?(bilibili|b23).(com|tv)/video/BV[a-zA-Z\d]+')
|
||||||
.hasMatch(url)) {
|
.hasMatch(url)) {
|
||||||
PiliScheme.routePush(Uri.parse(url));
|
try {
|
||||||
return NavigationActionPolicy.CANCEL;
|
String? bvid =
|
||||||
} else if (url.startsWith('http://m.bilibili.com/playlist/')) {
|
RegExp(r'BV[a-zA-Z\d]+').firstMatch(url)?.group(0);
|
||||||
try {
|
if (bvid != null) {
|
||||||
String? bvid =
|
Get.back();
|
||||||
RegExp(r'bvid=(BV[a-zA-Z\d]+)').firstMatch(url)?.group(1);
|
PiliScheme.videoPush(null, bvid);
|
||||||
if (bvid != null) {
|
return NavigationActionPolicy.CANCEL;
|
||||||
PiliScheme.videoPush(null, bvid);
|
}
|
||||||
return NavigationActionPolicy.CANCEL;
|
} catch (_) {}
|
||||||
}
|
} else if (url.startsWith('http://m.bilibili.com/playlist/')) {
|
||||||
} catch (_) {}
|
try {
|
||||||
}
|
String? bvid =
|
||||||
|
RegExp(r'bvid=(BV[a-zA-Z\d]+)').firstMatch(url)?.group(1);
|
||||||
|
if (bvid != null) {
|
||||||
|
PiliScheme.videoPush(null, bvid);
|
||||||
|
return NavigationActionPolicy.CANCEL;
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
} else {
|
} else {
|
||||||
if (url.startsWith('bilibili://video/')) {
|
if (url.startsWith('bilibili://video/')) {
|
||||||
String? str = Uri.parse(url).pathSegments.getOrNull(0);
|
String? str = Uri.parse(url).pathSegments.getOrNull(0);
|
||||||
|
|||||||
@@ -225,18 +225,12 @@ class PiliScheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 投稿跳转
|
// 投稿跳转
|
||||||
static Future<void> videoPush(int? aidVal, String? bvidVal) async {
|
static Future<void> videoPush(int? aid, String? bvid) async {
|
||||||
try {
|
try {
|
||||||
int? aid = aidVal;
|
aid ??= IdUtils.bv2av(bvid!);
|
||||||
String? bvid = bvidVal;
|
bvid ??= IdUtils.av2bv(aid);
|
||||||
if (aidVal == null) {
|
|
||||||
aid = IdUtils.bv2av(bvidVal!);
|
|
||||||
}
|
|
||||||
if (bvidVal == null) {
|
|
||||||
bvid = IdUtils.av2bv(aidVal!);
|
|
||||||
}
|
|
||||||
SmartDialog.showLoading<dynamic>(msg: '获取中...');
|
SmartDialog.showLoading<dynamic>(msg: '获取中...');
|
||||||
final int cid = await SearchHttp.ab2c(bvid: bvidVal, aid: aidVal);
|
final int cid = await SearchHttp.ab2c(bvid: bvid, aid: aid);
|
||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
Utils.toDupNamed(
|
Utils.toDupNamed(
|
||||||
'/video?bvid=$bvid&cid=$cid',
|
'/video?bvid=$bvid&cid=$cid',
|
||||||
|
|||||||
@@ -68,23 +68,16 @@ class IdUtils {
|
|||||||
if (input == null || input.isEmpty) {
|
if (input == null || input.isEmpty) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
final RegExp bvRegex =
|
final RegExp bvRegex = RegExp(r'bv([0-9A-Za-z]+)', caseSensitive: false);
|
||||||
RegExp(r'[bB][vV][0-9A-Za-z]{10}', caseSensitive: false);
|
String? bvid = bvRegex.firstMatch(input)?.group(1);
|
||||||
final RegExp avRegex = RegExp(r'[aA][vV]\d+', caseSensitive: false);
|
|
||||||
|
|
||||||
final Iterable<Match> bvMatches = bvRegex.allMatches(input);
|
late final RegExp avRegex = RegExp(r'av(\d+)', caseSensitive: false);
|
||||||
final Iterable<Match> avMatches = avRegex.allMatches(input);
|
late String? aid = avRegex.firstMatch(input)?.group(1);
|
||||||
|
|
||||||
final List<String> bvs =
|
if (bvid != null) {
|
||||||
bvMatches.map((Match match) => match.group(0)!).toList();
|
result['BV'] = 'BV$bvid';
|
||||||
final List<String> avs =
|
} else if (aid != null) {
|
||||||
avMatches.map((Match match) => match.group(0)!).toList();
|
result['AV'] = int.parse(aid);
|
||||||
|
|
||||||
if (bvs.isNotEmpty) {
|
|
||||||
result['BV'] = bvs[0].substring(0, 2).toUpperCase() + bvs[0].substring(2);
|
|
||||||
}
|
|
||||||
if (avs.isNotEmpty) {
|
|
||||||
result['AV'] = int.parse(avs[0].substring(2));
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user