Merge branch 'main' into fix

This commit is contained in:
guozhigq
2024-05-03 16:29:55 +08:00
11 changed files with 143 additions and 166 deletions

View File

@ -1,7 +1,10 @@
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/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';
@ -52,6 +55,20 @@ class VideoCardH extends StatelessWidget {
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',

View File

@ -3,14 +3,13 @@ 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 '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);

View File

@ -1,13 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/constants.dart';
import 'package:pilipala/common/widgets/badge.dart';
import 'package:pilipala/http/search.dart';
import 'package:pilipala/models/bangumi/info.dart';
import 'package:pilipala/models/bangumi/list.dart';
import 'package:pilipala/models/common/search_type.dart';
import 'package:pilipala/utils/image_save.dart';
import 'package:pilipala/utils/route_push.dart';
import 'package:pilipala/utils/utils.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
@ -24,32 +21,12 @@ class BangumiCardV extends StatelessWidget {
Widget build(BuildContext context) {
String heroTag = Utils.makeHeroTag(bangumiItem.mediaId);
return InkWell(
onTap: () async {
final int seasonId = bangumiItem.seasonId!;
SmartDialog.showLoading(msg: '获取中...');
final res = await SearchHttp.bangumiInfo(seasonId: seasonId);
SmartDialog.dismiss().then((value) {
if (res['status']) {
if (res['data'].episodes.isEmpty) {
SmartDialog.showToast('资源加载失败');
return;
}
EpisodeItem episode = res['data'].episodes.first;
String bvid = episode.bvid!;
int cid = episode.cid!;
String pic = episode.cover!;
String heroTag = Utils.makeHeroTag(cid);
Get.toNamed(
'/video?bvid=$bvid&cid=$cid&seasonId=$seasonId',
arguments: {
'pic': pic,
'heroTag': heroTag,
'videoType': SearchType.media_bangumi,
'bangumiItem': res['data'],
},
);
}
});
onTap: () {
RoutePush.bangumiPush(
bangumiItem.seasonId,
null,
heroTag: heroTag,
);
},
onLongPress: () =>
imageSaveDialog(context, bangumiItem, SmartDialog.dismiss),

View File

@ -14,6 +14,7 @@ import 'package:pilipala/models/dynamics/up.dart';
import 'package:pilipala/models/live/item.dart';
import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/id_utils.dart';
import 'package:pilipala/utils/route_push.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:pilipala/utils/utils.dart';
@ -220,25 +221,7 @@ class DynamicsController extends GetxController {
print('DYNAMIC_TYPE_PGC_UNION 番剧');
DynamicArchiveModel pgc = item.modules.moduleDynamic.major.pgc;
if (pgc.epid != null) {
SmartDialog.showLoading(msg: '获取中...');
var res = await SearchHttp.bangumiInfo(epId: pgc.epid);
SmartDialog.dismiss();
if (res['status']) {
EpisodeItem episode = res['data'].episodes.first;
String bvid = episode.bvid!;
int cid = episode.cid!;
String pic = episode.cover!;
String heroTag = Utils.makeHeroTag(cid);
Get.toNamed(
'/video?bvid=$bvid&cid=$cid&seasonId=${res['data'].seasonId}',
arguments: {
'pic': pic,
'heroTag': heroTag,
'videoType': SearchType.media_bangumi,
'bangumiItem': res['data'],
},
);
}
RoutePush.bangumiPush(null, pgc.epid);
}
break;
}

View File

@ -7,13 +7,13 @@ import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/http/search.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/http/video.dart';
import 'package:pilipala/models/bangumi/info.dart';
import 'package:pilipala/models/common/business_type.dart';
import 'package:pilipala/models/common/search_type.dart';
import 'package:pilipala/models/live/item.dart';
import 'package:pilipala/pages/history_search/index.dart';
import 'package:pilipala/utils/feed_back.dart';
import 'package:pilipala/utils/id_utils.dart';
import 'package:pilipala/utils/route_push.dart';
import 'package:pilipala/utils/utils.dart';
class HistoryItem extends StatelessWidget {
@ -101,26 +101,11 @@ class HistoryItem extends StatelessWidget {
}
} else {
if (videoItem.history.epid != '') {
SmartDialog.showLoading(msg: '获取中...');
var res =
await SearchHttp.bangumiInfo(epId: videoItem.history.epid);
SmartDialog.dismiss();
if (res['status']) {
EpisodeItem episode = res['data'].episodes.first;
String bvid = episode.bvid!;
int cid = episode.cid!;
String pic = episode.cover!;
String heroTag = Utils.makeHeroTag(cid);
Get.toNamed(
'/video?bvid=$bvid&cid=$cid&seasonId=${res['data'].seasonId}',
arguments: {
'pic': pic,
'heroTag': heroTag,
'videoType': SearchType.media_bangumi,
'bangumiItem': res['data'],
},
);
}
RoutePush.bangumiPush(
null,
videoItem.history.epid,
heroTag: heroTag,
);
}
}
} else {

View File

@ -7,6 +7,7 @@ import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/http/search.dart';
import 'package:pilipala/models/bangumi/info.dart';
import 'package:pilipala/models/common/search_type.dart';
import 'package:pilipala/utils/route_push.dart';
import 'package:pilipala/utils/utils.dart';
Widget searchMbangumiPanel(BuildContext context, ctr, list) {
@ -108,28 +109,8 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) {
SizedBox(
height: 32,
child: ElevatedButton(
onPressed: () async {
SmartDialog.showLoading(msg: '获取中...');
var res = await SearchHttp.bangumiInfo(
seasonId: i.seasonId);
SmartDialog.dismiss().then((value) {
if (res['status']) {
EpisodeItem episode = res['data'].episodes.first;
String bvid = episode.bvid!;
int cid = episode.cid!;
String pic = episode.cover!;
String heroTag = Utils.makeHeroTag(cid);
Get.toNamed(
'/video?bvid=$bvid&cid=$cid&seasonId=${i.seasonId}',
arguments: {
'pic': pic,
'heroTag': heroTag,
'videoType': SearchType.media_bangumi,
'bangumiItem': res['data'],
},
);
}
});
onPressed: () {
RoutePush.bangumiPush(i.seasonId, null);
},
child: const Text('观看'),
),

View File

@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/utils/route_push.dart';
import 'package:pilipala/utils/utils.dart';
import 'package:pilipala/utils/storage.dart';
@ -154,16 +155,33 @@ class ChatItem extends StatelessWidget {
GestureDetector(
onTap: () async {
SmartDialog.showLoading();
var bvid = content["bvid"];
final String bvid = content["bvid"];
// 16番剧 5投稿
final int source = content["source"];
final String? url = content["url"];
final int cid = await SearchHttp.ab2c(bvid: bvid);
final String heroTag = Utils.makeHeroTag(bvid);
SmartDialog.dismiss<dynamic>().then(
(e) => Get.toNamed<dynamic>('/video?bvid=$bvid&cid=$cid',
arguments: <String, String?>{
'pic': content['thumb'],
'heroTag': heroTag,
}),
);
await SmartDialog.dismiss();
if (source == 5) {
Get.toNamed<dynamic>(
'/video?bvid=$bvid&cid=$cid',
arguments: <String, String?>{
'pic': content['thumb'],
'heroTag': heroTag,
},
);
}
if (source == 16) {
if (url != null) {
final String area = url.split('/').last;
if (area.startsWith('ep')) {
RoutePush.bangumiPush(null, Utils.matchNum(area).first);
} else if (area.startsWith('ss')) {
RoutePush.bangumiPush(Utils.matchNum(area).first, null);
}
}
}
},
child: NetworkImgLayer(
width: 220,
@ -183,7 +201,7 @@ class ChatItem extends StatelessWidget {
),
const SizedBox(height: 1),
Text(
content['author'],
content['author'] ?? '',
style: TextStyle(
letterSpacing: 0.6,
height: 1.5,
@ -206,7 +224,7 @@ class ChatItem extends StatelessWidget {
SmartDialog.dismiss<dynamic>().then(
(e) => Get.toNamed<dynamic>('/video?bvid=$bvid&cid=$cid',
arguments: <String, String?>{
'pic': content['thumb'],
'pic': content['thumb'] ?? '',
'heroTag': heroTag,
}),
);

View File

@ -2,6 +2,7 @@ import 'package:appscheme/appscheme.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/utils/route_push.dart';
import '../http/search.dart';
import '../models/common/search_type.dart';
import 'id_utils.dart';
@ -68,7 +69,7 @@ class PiliSchame {
} else if (host == 'bangumi') {
if (path.startsWith('/season')) {
final String seasonId = path.split('/').last;
_bangumiPush(int.parse(seasonId), null);
RoutePush.bangumiPush(int.parse(seasonId), null);
}
} else if (host == 'opus') {
if (path.startsWith('/detail')) {
@ -126,35 +127,6 @@ class PiliSchame {
}
}
// 番剧跳转
static Future<void> _bangumiPush(int? seasonId, int? epId) async {
SmartDialog.showLoading<dynamic>(msg: '获取中...');
try {
var result = await SearchHttp.bangumiInfo(seasonId: seasonId, epId: epId);
if (result['status']) {
var bangumiDetail = result['data'];
final int cid = bangumiDetail.episodes!.first.cid;
final String bvid = IdUtils.av2bv(bangumiDetail.episodes!.first.aid);
final String heroTag = Utils.makeHeroTag(cid);
var epId = bangumiDetail.episodes!.first.id;
SmartDialog.dismiss().then(
(e) => Get.toNamed(
'/video?bvid=$bvid&cid=$cid&epId=$epId',
arguments: <String, dynamic>{
'pic': bangumiDetail.cover,
'heroTag': heroTag,
'videoType': SearchType.media_bangumi,
},
),
);
} else {
SmartDialog.showToast(result['msg']);
}
} catch (e) {
SmartDialog.showToast('番剧获取失败:$e');
}
}
static Future<void> _fullPathPush(SchemeEntity value) async {
// https://m.bilibili.com/bangumi/play/ss39708
// https | m.bilibili.com | /bangumi/play/ss39708
@ -167,8 +139,21 @@ class PiliSchame {
print('bilibili.com host: $host');
print('bilibili.com path: $path');
final String lastPathSegment = path!.split('/').last;
if (lastPathSegment.contains('BV')) {
_videoPush(null, lastPathSegment);
if (path.startsWith('/video')) {
if (lastPathSegment.contains('BV')) {
_videoPush(null, lastPathSegment);
}
if (lastPathSegment.contains('av')) {
_videoPush(Utils.matchNum(lastPathSegment)[0], null);
}
}
if (path.startsWith('/bangumi')) {
if (lastPathSegment.contains('ss')) {
RoutePush.bangumiPush(Utils.matchNum(lastPathSegment).first, null);
}
if (lastPathSegment.contains('ep')) {
RoutePush.bangumiPush(null, Utils.matchNum(lastPathSegment).first);
}
}
} else if (host.contains('live')) {
int roomId = int.parse(path!.split('/').last);
@ -220,9 +205,9 @@ class PiliSchame {
case 'bangumi':
print('番剧');
if (area.startsWith('ep')) {
_bangumiPush(null, matchNum(area).first);
RoutePush.bangumiPush(null, Utils.matchNum(area).first);
} else if (area.startsWith('ss')) {
_bangumiPush(matchNum(area).first, null);
RoutePush.bangumiPush(Utils.matchNum(area).first, null);
}
break;
case 'video':
@ -238,7 +223,7 @@ class PiliSchame {
break;
case 'read':
print('专栏');
String id = 'cv${matchNum(query!['id']!).first}';
String id = 'cv${Utils.matchNum(query!['id']!).first}';
Get.toNamed('/htmlRender', parameters: {
'url': value.dataString!,
'title': '',
@ -254,21 +239,14 @@ class PiliSchame {
}
}
static List<int> matchNum(String str) {
final RegExp regExp = RegExp(r'\d+');
final Iterable<Match> matches = regExp.allMatches(str);
return matches.map((Match match) => int.parse(match.group(0)!)).toList();
}
static void _handleEpisodePath(String lastPathSegment, String redirectUrl) {
final String seasonId = _extractIdFromPath(lastPathSegment);
_bangumiPush(null, matchNum(seasonId).first);
RoutePush.bangumiPush(null, Utils.matchNum(seasonId).first);
}
static void _handleSeasonPath(String lastPathSegment, String redirectUrl) {
final String seasonId = _extractIdFromPath(lastPathSegment);
_bangumiPush(matchNum(seasonId).first, null);
RoutePush.bangumiPush(Utils.matchNum(seasonId).first, null);
}
static String _extractIdFromPath(String lastPathSegment) {

44
lib/utils/route_push.dart Normal file
View File

@ -0,0 +1,44 @@
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/http/search.dart';
import 'package:pilipala/models/bangumi/info.dart';
import 'package:pilipala/models/common/search_type.dart';
import 'package:pilipala/utils/utils.dart';
class RoutePush {
// 番剧跳转
static Future<void> bangumiPush(int? seasonId, int? epId,
{String? heroTag}) async {
SmartDialog.showLoading<dynamic>(msg: '获取中...');
try {
var result = await SearchHttp.bangumiInfo(seasonId: seasonId, epId: epId);
await SmartDialog.dismiss();
if (result['status']) {
if (result['data'].episodes.isEmpty) {
SmartDialog.showToast('资源获取失败');
return;
}
final BangumiInfoModel bangumiDetail = result['data'];
final EpisodeItem episode = bangumiDetail.episodes!.first;
final int epId = episode.id!;
final int cid = episode.cid!;
final String bvid = episode.bvid!;
final String cover = episode.cover!;
final Map arguments = <String, dynamic>{
'pic': cover,
'videoType': SearchType.media_bangumi,
// 'bangumiItem': bangumiDetail,
};
arguments['heroTag'] = heroTag ?? Utils.makeHeroTag(cid);
Get.toNamed(
'/video?bvid=$bvid&cid=$cid&epId=$epId',
arguments: arguments,
);
} else {
SmartDialog.showToast(result['msg']);
}
} catch (e) {
SmartDialog.showToast('番剧获取失败:$e');
}
}
}

View File

@ -16,7 +16,7 @@ class UrlUtils {
};
try {
final response = await dio.get(url);
if (response.statusCode == 302) {
if (response.statusCode == 302 || response.statusCode == 301) {
redirectUrl = response.headers['location']?.first as String;
if (redirectUrl.endsWith('/')) {
redirectUrl = redirectUrl.substring(0, redirectUrl.length - 1);

View File

@ -383,4 +383,11 @@ class Utils {
List<int> randomBytes = generateRandomBytes(minLength, maxLength);
return base64.encode(randomBytes);
}
static List<int> matchNum(String str) {
final RegExp regExp = RegExp(r'\d+');
final Iterable<Match> matches = regExp.allMatches(str);
return matches.map((Match match) => int.parse(match.group(0)!)).toList();
}
}