mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-13 22:28:08 +08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9223f40f6d | ||
|
|
34bceeea39 | ||
|
|
36ee59c7da | ||
|
|
c23f15b195 | ||
|
|
94c077a4fe | ||
|
|
23ba9ad8c1 | ||
|
|
f29e49dc4c | ||
|
|
7603a72101 | ||
|
|
569cf6b4a3 | ||
|
|
e2b30200bf | ||
|
|
07d8504f91 | ||
|
|
952f1429eb | ||
|
|
c79364cef2 | ||
|
|
3ee1c9fdcd | ||
|
|
385ebd01cc | ||
|
|
a8d40b4aea | ||
|
|
dffea51223 | ||
|
|
812170ce38 |
@@ -18,6 +18,7 @@ import 'api.dart';
|
||||
import 'constants.dart';
|
||||
import 'interceptor.dart';
|
||||
import 'interceptor_anonymity.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web;
|
||||
|
||||
class Request {
|
||||
static final Request _instance = Request._internal();
|
||||
@@ -43,8 +44,19 @@ class Request {
|
||||
cookieManager = CookieManager(cookieJar);
|
||||
dio.interceptors.add(cookieManager);
|
||||
dio.interceptors.add(AnonymityInterceptor());
|
||||
// final List<Cookie> cookie = await cookieManager.cookieJar
|
||||
// .loadForRequest(Uri.parse(HttpString.baseUrl));
|
||||
final List<Cookie> cookies = await cookieManager.cookieJar
|
||||
.loadForRequest(Uri.parse(HttpString.baseUrl));
|
||||
for (Cookie item in cookies) {
|
||||
await web.CookieManager().setCookie(
|
||||
url: web.WebUri(item.domain ?? ''),
|
||||
name: item.name,
|
||||
value: item.value,
|
||||
path: item.path ?? '',
|
||||
domain: item.domain,
|
||||
isSecure: item.secure,
|
||||
isHttpOnly: item.httpOnly,
|
||||
);
|
||||
}
|
||||
final userInfo = userInfoCache.get('userInfoCache');
|
||||
if (userInfo != null && userInfo.mid != null) {
|
||||
final List<Cookie> cookie2 = await cookieManager.cookieJar
|
||||
@@ -65,7 +77,7 @@ class Request {
|
||||
log("setCookie, ${e.toString()}");
|
||||
}
|
||||
|
||||
// final String cookieString = cookie
|
||||
// final String cookieString = cookies
|
||||
// .map((Cookie cookie) => '${cookie.name}=${cookie.value}')
|
||||
// .join('; ');
|
||||
// dio.options.headers['cookie'] = cookieString;
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:PiliPalaX/http/constants.dart';
|
||||
import 'package:PiliPalaX/services/loggeer.dart';
|
||||
import 'package:cookie_jar/cookie_jar.dart';
|
||||
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
@@ -167,6 +173,9 @@ class _AboutPageState extends State<AboutPage> {
|
||||
onTap: () {
|
||||
Get.toNamed('/logs');
|
||||
},
|
||||
onLongPress: () {
|
||||
clearLogs();
|
||||
},
|
||||
leading: const Icon(Icons.bug_report_outlined),
|
||||
title: const Text('错误日志'),
|
||||
trailing: Icon(Icons.arrow_forward, size: 16, color: outline),
|
||||
@@ -185,12 +194,112 @@ class _AboutPageState extends State<AboutPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('导入/导出登录信息'),
|
||||
leading: const Icon(Icons.import_export_outlined),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => SimpleDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
ListTile(
|
||||
title: const Text('导出'),
|
||||
onTap: () async {
|
||||
dynamic accessKey = GStorage.localCache
|
||||
.get(LocalCacheKey.accessKey, defaultValue: {});
|
||||
dynamic cookies = (await CookieManager(PersistCookieJar(
|
||||
ignoreExpires: true,
|
||||
storage: FileStorage(await Utils.getCookiePath()),
|
||||
))
|
||||
.cookieJar
|
||||
.loadForRequest(Uri.parse(HttpString.baseUrl)))
|
||||
.map(
|
||||
(Cookie cookie) => {
|
||||
'name': cookie.name,
|
||||
'value': cookie.value,
|
||||
},
|
||||
)
|
||||
.toList();
|
||||
dynamic res = jsonEncode({
|
||||
'accessKey': accessKey,
|
||||
'cookies': cookies,
|
||||
});
|
||||
Utils.copyText('$res');
|
||||
if (context.mounted) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
content: SelectableText('$res'),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('导入'),
|
||||
onTap: () async {
|
||||
Get.back();
|
||||
ClipboardData? data =
|
||||
await Clipboard.getData('text/plain');
|
||||
if (data == null ||
|
||||
data.text == null ||
|
||||
data.text!.isEmpty) {
|
||||
SmartDialog.showToast('剪贴板无数据');
|
||||
return;
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('是否导入以下登录信息?'),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(data.text!),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color:
|
||||
Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Get.back();
|
||||
try {
|
||||
dynamic res = jsonDecode(data.text!);
|
||||
Utils.afterLoginByApp(
|
||||
res['accessKey'],
|
||||
{'cookies': res['cookies']},
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('导入失败:$e');
|
||||
}
|
||||
},
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('导入/导出设置'),
|
||||
dense: false,
|
||||
leading: const Icon(Icons.import_export_outlined),
|
||||
onTap: () async {
|
||||
await showDialog(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SimpleDialog(
|
||||
@@ -224,13 +333,20 @@ class _AboutPageState extends State<AboutPage> {
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('是否导入如下设置?'),
|
||||
content: Text(data.text!),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(data.text!),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
child: const Text('取消'),
|
||||
onPressed: Get.back,
|
||||
child: Text(
|
||||
'取消',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
|
||||
@@ -387,14 +387,18 @@ class BangumiIntroController extends CommonController {
|
||||
if (cover is String && cover.isNotEmpty) {
|
||||
videoDetailCtr.videoItem['pic'] = cover;
|
||||
}
|
||||
|
||||
// 重新请求评论
|
||||
try {
|
||||
/// 未渲染回复组件时可能异常
|
||||
VideoReplyController videoReplyCtr =
|
||||
Get.find<VideoReplyController>(tag: Get.arguments['heroTag']);
|
||||
videoReplyCtr.aid = aid;
|
||||
videoReplyCtr.onRefresh();
|
||||
} catch (_) {}
|
||||
if (videoDetailCtr.showReply) {
|
||||
try {
|
||||
/// 未渲染回复组件时可能异常
|
||||
VideoReplyController videoReplyCtr =
|
||||
Get.find<VideoReplyController>(tag: Get.arguments['heroTag']);
|
||||
videoReplyCtr.aid = aid;
|
||||
videoReplyCtr.onRefresh();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
if (userLogin) {
|
||||
queryBangumiLikeCoinFav();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class _DynamicsPageState extends State<DynamicsPage>
|
||||
}),
|
||||
),
|
||||
onPressed: () {
|
||||
if (GStorage.userInfo.get('userInfoCache') != null) {
|
||||
if (GStorage.isLogin) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
useSafeArea: true,
|
||||
|
||||
@@ -97,9 +97,9 @@ class _UpPanelState extends State<UpPanel> {
|
||||
upItemBuild(UpItem(face: '', uname: '全部动态', mid: -1), 0),
|
||||
upItemBuild(
|
||||
UpItem(
|
||||
face: userInfo.face,
|
||||
face: userInfo?.face,
|
||||
uname: '我',
|
||||
mid: userInfo.mid,
|
||||
mid: userInfo?.mid,
|
||||
),
|
||||
1),
|
||||
for (int i = 0; i < upList.length; i++) ...[
|
||||
|
||||
@@ -59,7 +59,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
|
||||
}
|
||||
|
||||
// 更新登录状态
|
||||
void updateLoginStatus(val) async {
|
||||
Future updateLoginStatus(val) async {
|
||||
userInfo = await userInfoCache.get('userInfoCache');
|
||||
userLogin.value = val ?? false;
|
||||
if (val) return;
|
||||
|
||||
@@ -2,22 +2,13 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:PiliPalaX/common/constants.dart';
|
||||
import 'package:PiliPalaX/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:PiliPalaX/http/login.dart';
|
||||
import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart';
|
||||
import 'package:PiliPalaX/models/login/index.dart';
|
||||
import '../../utils/login.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:webview_cookie_manager/webview_cookie_manager.dart';
|
||||
|
||||
import '../../http/constants.dart';
|
||||
import '../../http/init.dart';
|
||||
import '../../http/user.dart';
|
||||
import '../../utils/storage.dart';
|
||||
import '../home/controller.dart';
|
||||
import '../media/controller.dart';
|
||||
|
||||
class LoginPageController extends GetxController
|
||||
with GetSingleTickerProviderStateMixin {
|
||||
@@ -86,7 +77,7 @@ class LoginPageController extends GetxController
|
||||
if (value['status']) {
|
||||
t.cancel();
|
||||
statusQRCode.value = '扫码成功';
|
||||
await afterLoginByApp(
|
||||
await Utils.afterLoginByApp(
|
||||
value['data'], value['data']['cookie_info']);
|
||||
Get.back();
|
||||
} else if (value['code'] == 86038) {
|
||||
@@ -111,58 +102,6 @@ class LoginPageController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
Future afterLoginByApp(Map<String, dynamic> token_info, cookie_info) async {
|
||||
try {
|
||||
Box localCache = GStorage.localCache;
|
||||
localCache.put(LocalCacheKey.accessKey, {
|
||||
'mid': token_info['mid'],
|
||||
'value': token_info['access_token'],
|
||||
'refresh': token_info['refresh_token']
|
||||
});
|
||||
List<dynamic> cookieInfo = cookie_info['cookies'];
|
||||
List<Cookie> cookies = [];
|
||||
String cookieStrings = cookieInfo.map((cookie) {
|
||||
String cstr =
|
||||
'${cookie['name']}=${cookie['value']};Domain=.bilibili.com;Path=/;';
|
||||
cookies.add(Cookie.fromSetCookieValue(cstr));
|
||||
return cstr;
|
||||
}).join('');
|
||||
List<String> Urls = [
|
||||
HttpString.baseUrl,
|
||||
HttpString.apiBaseUrl,
|
||||
HttpString.tUrl
|
||||
];
|
||||
for (var url in Urls) {
|
||||
await Request.cookieManager.cookieJar
|
||||
.saveFromResponse(Uri.parse(url), cookies);
|
||||
}
|
||||
Request.dio.options.headers['cookie'] = cookieStrings;
|
||||
await WebviewCookieManager().setCookies(cookies);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('设置登录态失败,$e');
|
||||
}
|
||||
final result = await UserHttp.userInfo();
|
||||
if (result['status'] && result['data'].isLogin) {
|
||||
SmartDialog.showToast('登录成功,当前采用「'
|
||||
'${GStorage.setting.get(SettingBoxKey.defaultRcmdType, defaultValue: 'web')}'
|
||||
'端」推荐');
|
||||
await GStorage.userInfo.put('userInfoCache', result['data']);
|
||||
try {
|
||||
final HomeController homeCtr = Get.find<HomeController>();
|
||||
homeCtr.updateLoginStatus(true);
|
||||
homeCtr.userFace.value = result['data'].face;
|
||||
final MediaController mediaCtr = Get.find<MediaController>();
|
||||
mediaCtr.mid = result['data'].mid;
|
||||
} catch (_) {}
|
||||
await LoginUtils.refreshLoginStatus(true);
|
||||
} else {
|
||||
// 获取用户信息失败
|
||||
SmartDialog.showNotify(
|
||||
msg: '登录失败,请检查cookie是否正确,${result['message']}',
|
||||
notifyType: NotifyType.warning);
|
||||
}
|
||||
}
|
||||
|
||||
// 申请极验验证码
|
||||
Future getCaptcha(geeGt, geeChallenge, onSuccess) async {
|
||||
var registerData = Gt3RegisterData(
|
||||
@@ -415,7 +354,8 @@ class LoginPageController extends GetxController
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast('正在保存身份信息');
|
||||
await afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||
await Utils.afterLoginByApp(
|
||||
data['token_info'], data['cookie_info']);
|
||||
Get.back();
|
||||
Get.back();
|
||||
},
|
||||
@@ -432,7 +372,7 @@ class LoginPageController extends GetxController
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast('正在保存身份信息');
|
||||
await afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||
await Utils.afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||
Get.back();
|
||||
} else {
|
||||
// handle login result
|
||||
@@ -495,7 +435,7 @@ class LoginPageController extends GetxController
|
||||
if (res['status']) {
|
||||
SmartDialog.showToast('登录成功');
|
||||
var data = res['data'];
|
||||
await afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||
await Utils.afterLoginByApp(data['token_info'], data['cookie_info']);
|
||||
Get.back();
|
||||
} else {
|
||||
SmartDialog.showToast(res['msg']);
|
||||
|
||||
@@ -64,6 +64,7 @@ class _MediaPageState extends State<MediaPage>
|
||||
toolbarHeight: 30,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
controller: mediaController.scrollController,
|
||||
child: Column(
|
||||
children: [
|
||||
@@ -183,6 +184,9 @@ class _MediaPageState extends State<MediaPage>
|
||||
height: MediaQuery.textScalerOf(context).scale(200),
|
||||
child: Obx(() => _buildBody(mediaController.loadingState.value)),
|
||||
),
|
||||
SizedBox(
|
||||
height: MediaQuery.paddingOf(context).bottom + 100,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,6 +223,36 @@ class _ExtraSettingState extends State<ExtraSetting> {
|
||||
setKey: SettingBoxKey.showViewPoints,
|
||||
defaultVal: true,
|
||||
),
|
||||
SetSwitchItem(
|
||||
title: '视频页显示相关视频',
|
||||
leading: Icon(Icons.recommend_outlined),
|
||||
setKey: SettingBoxKey.showRelatedVideo,
|
||||
defaultVal: true,
|
||||
),
|
||||
SetSwitchItem(
|
||||
title: '显示视频评论',
|
||||
leading: Icon(Icons.reply_all),
|
||||
setKey: SettingBoxKey.showVideoReply,
|
||||
defaultVal: true,
|
||||
),
|
||||
SetSwitchItem(
|
||||
title: '显示番剧评论',
|
||||
leading: Icon(Icons.reply_all),
|
||||
setKey: SettingBoxKey.showBangumiReply,
|
||||
defaultVal: true,
|
||||
),
|
||||
SetSwitchItem(
|
||||
title: '默认展开视频简介',
|
||||
leading: Icon(Icons.expand_more),
|
||||
setKey: SettingBoxKey.alwaysExapndIntroPanel,
|
||||
defaultVal: false,
|
||||
),
|
||||
SetSwitchItem(
|
||||
title: '横屏自动展开视频简介',
|
||||
leading: Icon(Icons.expand_more),
|
||||
setKey: SettingBoxKey.exapndIntroPanelH,
|
||||
defaultVal: false,
|
||||
),
|
||||
Obx(
|
||||
() => ListTile(
|
||||
enableFeedback: true,
|
||||
|
||||
@@ -216,6 +216,13 @@ class VideoDetailController extends GetxController
|
||||
late String cacheSecondDecode;
|
||||
late int cacheAudioQa;
|
||||
|
||||
late final showRelatedVideo = GStorage.showRelatedVideo;
|
||||
|
||||
late final _showVideoReply = GStorage.showVideoReply;
|
||||
late final _showBangumiReply = GStorage.showBangumiReply;
|
||||
bool get showReply =>
|
||||
videoType == SearchType.video ? _showVideoReply : _showBangumiReply;
|
||||
|
||||
late final bool enableSponsorBlock;
|
||||
PlayerStatus? playerStatus;
|
||||
StreamSubscription<Duration>? positionSubscription;
|
||||
@@ -236,6 +243,8 @@ class VideoDetailController extends GetxController
|
||||
RxString sourceType = 'normal'.obs;
|
||||
List<MediaVideoItemModel> mediaList = <MediaVideoItemModel>[];
|
||||
RxString watchLaterTitle = ''.obs;
|
||||
bool get isPlayAll =>
|
||||
sourceType.value == 'watchLater' || sourceType.value == 'fav';
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
@@ -357,18 +366,22 @@ class VideoDetailController extends GetxController
|
||||
videoItem['pic'] = cover;
|
||||
queryVideoUrl();
|
||||
|
||||
Get.find<VideoReplyController>(tag: heroTag)
|
||||
..aid = aid
|
||||
..onRefresh();
|
||||
if (showReply) {
|
||||
Get.find<VideoReplyController>(tag: heroTag)
|
||||
..aid = aid
|
||||
..onRefresh();
|
||||
}
|
||||
|
||||
Get.find<VideoIntroController>(tag: heroTag)
|
||||
..lastPlayCid.value = cid
|
||||
..bvid = bvid
|
||||
..queryVideoIntro();
|
||||
|
||||
Get.find<RelatedController>(tag: heroTag)
|
||||
..bvid = bvid
|
||||
..onRefresh();
|
||||
if (showRelatedVideo) {
|
||||
Get.find<RelatedController>(tag: heroTag)
|
||||
..bvid = bvid
|
||||
..onRefresh();
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:math';
|
||||
|
||||
import 'package:PiliPalaX/http/loading_state.dart';
|
||||
import 'package:PiliPalaX/utils/utils.dart';
|
||||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
@@ -79,6 +80,8 @@ class VideoIntroController extends GetxController
|
||||
Rx<Map<String, dynamic>> queryVideoIntroData =
|
||||
Rx<Map<String, dynamic>>({"status": true});
|
||||
|
||||
ExpandableController? expandableCtr;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
@@ -549,20 +552,25 @@ class VideoIntroController extends GetxController
|
||||
}
|
||||
videoDetailCtr.danmakuCid.value = cid;
|
||||
videoDetailCtr.queryVideoUrl();
|
||||
|
||||
// 重新请求相关视频
|
||||
try {
|
||||
final RelatedController relatedCtr =
|
||||
Get.find<RelatedController>(tag: heroTag);
|
||||
relatedCtr.bvid = bvid;
|
||||
relatedCtr.queryData();
|
||||
} catch (_) {}
|
||||
if (videoDetailCtr.showRelatedVideo) {
|
||||
try {
|
||||
Get.find<RelatedController>(tag: heroTag)
|
||||
..bvid = bvid
|
||||
..queryData();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
// 重新请求评论
|
||||
try {
|
||||
final VideoReplyController videoReplyCtr =
|
||||
Get.find<VideoReplyController>(tag: heroTag);
|
||||
videoReplyCtr.aid = aid;
|
||||
videoReplyCtr.onRefresh();
|
||||
} catch (_) {}
|
||||
if (videoDetailCtr.showReply) {
|
||||
try {
|
||||
Get.find<VideoReplyController>(tag: heroTag)
|
||||
..aid = aid
|
||||
..onRefresh();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
this.bvid = bvid;
|
||||
lastPlayCid.value = cid;
|
||||
queryVideoIntro();
|
||||
@@ -604,6 +612,8 @@ class VideoIntroController extends GetxController
|
||||
@override
|
||||
void onClose() {
|
||||
canelTimer();
|
||||
expandableCtr?.dispose();
|
||||
expandableCtr = null;
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -652,8 +662,7 @@ class VideoIntroController extends GetxController
|
||||
final VideoDetailController videoDetailCtr =
|
||||
Get.find<VideoDetailController>(tag: heroTag);
|
||||
|
||||
if (videoDetailController.sourceType.value == 'watchLater' ||
|
||||
videoDetailController.sourceType.value == 'fav') {
|
||||
if (videoDetailController.isPlayAll) {
|
||||
episodes.addAll(videoDetailCtr.mediaList);
|
||||
} else if ((videoDetail.value.pages?.length ?? 0) > 1) {
|
||||
isPages = true;
|
||||
@@ -671,7 +680,8 @@ class VideoIntroController extends GetxController
|
||||
final PlayRepeat platRepeat = videoDetailCtr.plPlayerController.playRepeat;
|
||||
|
||||
if (episodes.isEmpty) {
|
||||
if (platRepeat == PlayRepeat.autoPlayRelated) {
|
||||
if (platRepeat == PlayRepeat.autoPlayRelated &&
|
||||
videoDetailCtr.showRelatedVideo) {
|
||||
return playRelated();
|
||||
}
|
||||
return false;
|
||||
@@ -692,7 +702,8 @@ class VideoIntroController extends GetxController
|
||||
if (nextIndex >= episodes.length) {
|
||||
if (platRepeat == PlayRepeat.listCycle) {
|
||||
nextIndex = 0;
|
||||
} else if (platRepeat == PlayRepeat.autoPlayRelated) {
|
||||
} else if (platRepeat == PlayRepeat.autoPlayRelated &&
|
||||
videoDetailCtr.showRelatedVideo) {
|
||||
return playRelated();
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -73,12 +73,6 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
videoIntroController.onClose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
@@ -158,7 +152,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
|
||||
late final _coinKey = GlobalKey<ActionItemState>();
|
||||
late final _favKey = GlobalKey<ActionItemState>();
|
||||
final _expandableCtr = ExpandableController(initialExpanded: false);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -170,12 +163,23 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
|
||||
loadingStatus = widget.loadingStatus;
|
||||
enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_expandableCtr.dispose();
|
||||
super.dispose();
|
||||
if (videoIntroController.expandableCtr == null) {
|
||||
bool alwaysExapndIntroPanel = GStorage.alwaysExapndIntroPanel;
|
||||
|
||||
videoIntroController.expandableCtr = ExpandableController(
|
||||
initialExpanded: alwaysExapndIntroPanel,
|
||||
);
|
||||
|
||||
if (alwaysExapndIntroPanel.not && GStorage.exapndIntroPanelH) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (context.orientation == Orientation.landscape &&
|
||||
videoIntroController.expandableCtr?.expanded == false) {
|
||||
videoIntroController.expandableCtr?.toggle();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _showFavBottomSheet() => showModalBottomSheet(
|
||||
@@ -234,7 +238,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
}
|
||||
feedBack();
|
||||
// widget.showIntroDetail();
|
||||
_expandableCtr.toggle();
|
||||
videoIntroController.expandableCtr?.toggle();
|
||||
}
|
||||
|
||||
// 用户主页
|
||||
@@ -397,7 +401,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: showIntroDetail,
|
||||
child: ExpandablePanel(
|
||||
controller: _expandableCtr,
|
||||
controller: videoIntroController.expandableCtr,
|
||||
collapsed: GestureDetector(
|
||||
onLongPress: () {
|
||||
feedBack();
|
||||
@@ -525,7 +529,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: showIntroDetail,
|
||||
child: ExpandablePanel(
|
||||
controller: _expandableCtr,
|
||||
controller: videoIntroController.expandableCtr,
|
||||
collapsed: const SizedBox.shrink(),
|
||||
expanded: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@@ -538,7 +542,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
||||
'${videoIntroController.videoDetail.value.bvid}');
|
||||
},
|
||||
child: Text(
|
||||
'${videoIntroController.videoDetail.value.bvid}',
|
||||
videoIntroController.videoDetail.value.bvid ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
|
||||
@@ -62,6 +62,7 @@ class VideoReplyReplyController extends CommonController
|
||||
).then((res) {
|
||||
if (res['status'] && (res['data']?.mid ?? -1) > 0) {
|
||||
firstFloor = res['data'];
|
||||
hasRoot = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -85,7 +86,7 @@ class VideoReplyReplyController extends CommonController
|
||||
.map((item) => item.id.toInt())
|
||||
.toList()
|
||||
.indexOf(id!);
|
||||
if (index != -1) {
|
||||
if (index != null && index != -1) {
|
||||
controller = AnimationController(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
vsync: this,
|
||||
@@ -95,13 +96,15 @@ class VideoReplyReplyController extends CommonController
|
||||
end: Theme.of(Get.context!).colorScheme.surface,
|
||||
).animate(controller!);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
itemScrollCtr.jumpTo(
|
||||
index: hasRoot ? index! + 3 : index! + 1,
|
||||
alignment: 0.25,
|
||||
);
|
||||
await Future.delayed(const Duration(milliseconds: 800));
|
||||
await controller?.forward();
|
||||
index = null;
|
||||
if (index != null) {
|
||||
itemScrollCtr.jumpTo(
|
||||
index: hasRoot ? index! + 3 : index! + 1,
|
||||
alignment: 0.25,
|
||||
);
|
||||
await Future.delayed(const Duration(milliseconds: 800));
|
||||
await controller?.forward();
|
||||
index = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
id = null;
|
||||
@@ -146,6 +149,7 @@ class VideoReplyReplyController extends CommonController
|
||||
} else {
|
||||
if (response.response.root != null) {
|
||||
firstFloor = response.response.root;
|
||||
hasRoot = true;
|
||||
}
|
||||
List<ReplyItemModel> replies = response.response.replies;
|
||||
count.value = response.response.page.count;
|
||||
|
||||
@@ -100,9 +100,11 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
}
|
||||
videoDetailController = Get.put(VideoDetailController(), tag: heroTag);
|
||||
|
||||
_videoReplyController = Get.put(
|
||||
VideoReplyController(videoDetailController.oid.value, '0', '1'),
|
||||
tag: heroTag);
|
||||
if (videoDetailController.showReply) {
|
||||
_videoReplyController = Get.put(
|
||||
VideoReplyController(videoDetailController.oid.value, '0', '1'),
|
||||
tag: heroTag);
|
||||
}
|
||||
videoIntroController = Get.put(VideoIntroController(), tag: heroTag);
|
||||
videoIntroController.videoDetail.listen((value) {
|
||||
if (!context.mounted) return;
|
||||
@@ -179,7 +181,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
// 获取视频资源,初始化播放器
|
||||
Future<void> videoSourceInit() async {
|
||||
_futureBuilderFuture = videoDetailController.queryVideoUrl();
|
||||
_videoReplyController.queryData();
|
||||
if (videoDetailController.showReply) {
|
||||
_videoReplyController.queryData();
|
||||
}
|
||||
if (videoDetailController.autoPlay.value) {
|
||||
plPlayerController = videoDetailController.plPlayerController;
|
||||
plPlayerController!.addStatusLister(playerListener);
|
||||
@@ -222,7 +226,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
bool notExitFlag = false;
|
||||
|
||||
/// 顺序播放 列表循环
|
||||
if (plPlayerController!.playRepeat != PlayRepeat.pause &&
|
||||
if (videoDetailController.isPlayAll) {
|
||||
notExitFlag = videoIntroController.nextPlay();
|
||||
} else if (plPlayerController!.playRepeat != PlayRepeat.pause &&
|
||||
plPlayerController!.playRepeat != PlayRepeat.singleCycle) {
|
||||
if (videoDetailController.videoType == SearchType.video) {
|
||||
notExitFlag = videoIntroController.nextPlay();
|
||||
@@ -561,14 +567,17 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Column(
|
||||
children: [
|
||||
tabbarBuild(),
|
||||
buildTabbar(
|
||||
showReply: videoDetailController.showReply,
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: const ClampingScrollPhysics(),
|
||||
controller: videoDetailController.tabCtr,
|
||||
children: [
|
||||
videoIntro(),
|
||||
videoReplyPanel,
|
||||
if (videoDetailController.showReply)
|
||||
videoReplyPanel,
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -610,14 +619,15 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Column(
|
||||
children: [
|
||||
tabbarBuild(),
|
||||
buildTabbar(showReply: videoDetailController.showReply),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: const ClampingScrollPhysics(),
|
||||
controller: videoDetailController.tabCtr,
|
||||
children: [
|
||||
videoIntro(),
|
||||
videoReplyPanel,
|
||||
if (videoDetailController.showReply)
|
||||
videoReplyPanel,
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -653,14 +663,16 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Column(
|
||||
children: [
|
||||
tabbarBuild(false),
|
||||
buildTabbar(
|
||||
needIndicator: false,
|
||||
showReply: videoDetailController.showReply,
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: videoIntro()),
|
||||
Expanded(
|
||||
child: videoReplyPanel,
|
||||
)
|
||||
if (videoDetailController.showReply)
|
||||
Expanded(child: videoReplyPanel)
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -699,8 +711,12 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Column(
|
||||
children: [
|
||||
tabbarBuild(false, '', true),
|
||||
Expanded(child: videoReplyPanel),
|
||||
buildTabbar(
|
||||
showIntro: false,
|
||||
showReply: videoDetailController.showReply,
|
||||
),
|
||||
if (videoDetailController.showReply)
|
||||
Expanded(child: videoReplyPanel),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -790,12 +806,12 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Column(
|
||||
children: [
|
||||
tabbarBuild(
|
||||
videoDetailController.videoType !=
|
||||
SearchType.media_bangumi,
|
||||
'相关视频',
|
||||
videoDetailController.videoType ==
|
||||
SearchType.media_bangumi,
|
||||
buildTabbar(
|
||||
introText: '相关视频',
|
||||
showIntro: videoDetailController.videoType ==
|
||||
SearchType.video &&
|
||||
videoDetailController.showRelatedVideo,
|
||||
showReply: videoDetailController.showReply,
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
@@ -803,14 +819,16 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
controller: videoDetailController.tabCtr,
|
||||
children: <Widget>[
|
||||
if (videoDetailController.videoType ==
|
||||
SearchType.video)
|
||||
SearchType.video &&
|
||||
videoDetailController.showRelatedVideo)
|
||||
CustomScrollView(
|
||||
controller: _introController,
|
||||
slivers: [
|
||||
RelatedVideoPanel(heroTag: heroTag),
|
||||
],
|
||||
),
|
||||
videoReplyPanel,
|
||||
if (videoDetailController.showReply)
|
||||
videoReplyPanel,
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -1131,15 +1149,58 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget tabbarBuild([
|
||||
Widget buildTabbar({
|
||||
bool needIndicator = true,
|
||||
String introText = '简介',
|
||||
bool isSingle = false,
|
||||
]) {
|
||||
if (videoDetailController.tabCtr.length != (isSingle ? 1 : 2)) {
|
||||
videoDetailController.tabCtr =
|
||||
TabController(length: isSingle ? 1 : 2, vsync: this);
|
||||
bool showIntro = true,
|
||||
bool showReply = true,
|
||||
}) {
|
||||
int length = (showIntro ? 1 : 0) + (showReply ? 1 : 0);
|
||||
if (videoDetailController.tabCtr.length != length) {
|
||||
videoDetailController.tabCtr = TabController(length: length, vsync: this);
|
||||
}
|
||||
|
||||
Widget tabbar() => TabBar(
|
||||
labelColor: needIndicator.not || length == 1
|
||||
? Theme.of(context).colorScheme.onSurface
|
||||
: null,
|
||||
indicatorColor:
|
||||
needIndicator.not || length == 1 ? Colors.transparent : null,
|
||||
padding: EdgeInsets.zero,
|
||||
controller: videoDetailController.tabCtr,
|
||||
labelStyle: const TextStyle(fontSize: 13),
|
||||
labelPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 10.0), // 设置每个标签的宽度
|
||||
dividerColor: Colors.transparent,
|
||||
onTap: (value) {
|
||||
void animToTop() {
|
||||
if (value == 0) {
|
||||
if (showIntro) {
|
||||
_introController.animToTop();
|
||||
} else if (showReply) {
|
||||
_videoReplyController.animateToTop();
|
||||
}
|
||||
} else {
|
||||
_videoReplyController.animateToTop();
|
||||
}
|
||||
}
|
||||
|
||||
if (needIndicator.not || length == 1) {
|
||||
animToTop();
|
||||
} else if (videoDetailController.tabCtr.indexIsChanging.not) {
|
||||
animToTop();
|
||||
}
|
||||
},
|
||||
tabs: [
|
||||
if (showIntro) Tab(text: introText),
|
||||
if (showReply)
|
||||
Tab(
|
||||
text:
|
||||
'评论${_videoReplyController.count.value == -1 ? '' : ' ${_videoReplyController.count.value}'}',
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: 45,
|
||||
@@ -1154,42 +1215,13 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
child: Material(
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: Obx(
|
||||
() => TabBar(
|
||||
labelColor: needIndicator
|
||||
? null
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
indicatorColor: needIndicator ? null : Colors.transparent,
|
||||
padding: EdgeInsets.zero,
|
||||
controller: videoDetailController.tabCtr,
|
||||
labelStyle: const TextStyle(fontSize: 13),
|
||||
labelPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 10.0), // 设置每个标签的宽度
|
||||
dividerColor: Colors.transparent,
|
||||
onTap: (value) {
|
||||
if (isSingle) {
|
||||
_videoReplyController.animateToTop();
|
||||
} else if (!needIndicator ||
|
||||
!videoDetailController.tabCtr.indexIsChanging) {
|
||||
if (value == 0) {
|
||||
_introController.animToTop();
|
||||
} else {
|
||||
_videoReplyController.animateToTop();
|
||||
}
|
||||
}
|
||||
},
|
||||
tabs: [
|
||||
if (!isSingle) Tab(text: introText),
|
||||
Tab(
|
||||
text:
|
||||
'评论${_videoReplyController.count.value == -1 ? '' : ' ${_videoReplyController.count.value}'}',
|
||||
),
|
||||
],
|
||||
),
|
||||
if (length == 0)
|
||||
const Spacer()
|
||||
else
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: showReply ? Obx(() => tabbar()) : tabbar(),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: Center(
|
||||
@@ -1287,7 +1319,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
|
||||
Widget videoIntro([bool needRelated = true]) {
|
||||
Widget introPanel() => CustomScrollView(
|
||||
controller: _introController,
|
||||
controller: needRelated ? _introController : null,
|
||||
slivers: [
|
||||
if (videoDetailController.videoType == SearchType.video) ...[
|
||||
VideoIntroPanel(
|
||||
@@ -1296,7 +1328,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
showIntroDetail: showIntroDetail,
|
||||
showEpisodes: showEpisodes,
|
||||
),
|
||||
if (needRelated) ...[
|
||||
if (needRelated && videoDetailController.showRelatedVideo) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
@@ -1323,12 +1355,18 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(height: MediaQuery.paddingOf(context).bottom),
|
||||
child: SizedBox(
|
||||
height: MediaQuery.paddingOf(context).bottom +
|
||||
(videoDetailController.isPlayAll &&
|
||||
MediaQuery.orientationOf(context) ==
|
||||
Orientation.landscape
|
||||
? 75
|
||||
: 0),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
if (videoDetailController.sourceType.value == 'watchLater' ||
|
||||
videoDetailController.sourceType.value == 'fav') {
|
||||
if (videoDetailController.isPlayAll) {
|
||||
return Stack(
|
||||
children: [
|
||||
introPanel(),
|
||||
|
||||
@@ -189,22 +189,6 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
// ),
|
||||
// ),
|
||||
// if (widget.videoDetailCtr?.userInfo != null)
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
if (widget.videoDetailCtr?.userInfo == null) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
Get.toNamed('/webviewnew', parameters: {
|
||||
'url':
|
||||
'https://www.bilibili.com/appeal/?avid=${IdUtils.bv2av(widget.videoDetailCtr!.bvid)}&bvid=${widget.videoDetailCtr!.bvid}'
|
||||
});
|
||||
},
|
||||
leading: const Icon(Icons.error_outline, size: 20),
|
||||
title: const Text('举报', style: titleStyle),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
@@ -514,6 +498,22 @@ class _HeaderControlState extends State<HeaderControl> {
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
if (widget.videoDetailCtr?.userInfo == null) {
|
||||
SmartDialog.showToast('账号未登录');
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
Get.toNamed('/webviewnew', parameters: {
|
||||
'url':
|
||||
'https://www.bilibili.com/appeal/?avid=${IdUtils.bv2av(widget.videoDetailCtr!.bvid)}&bvid=${widget.videoDetailCtr!.bvid}'
|
||||
});
|
||||
},
|
||||
leading: const Icon(Icons.error_outline, size: 20),
|
||||
title: const Text('举报', style: titleStyle),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -249,10 +249,12 @@ class _WhisperPageState extends State<WhisperPage> {
|
||||
sessionList[i].accountInfo.name,
|
||||
'face':
|
||||
sessionList[i].accountInfo.face,
|
||||
'mid': sessionList[i]
|
||||
.accountInfo
|
||||
.mid
|
||||
.toString(),
|
||||
if (sessionList[i].accountInfo.mid !=
|
||||
null)
|
||||
'mid': sessionList[i]
|
||||
.accountInfo
|
||||
.mid
|
||||
.toString(),
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@ class WhisperDetailController extends GetxController {
|
||||
talkerId = int.parse(Get.parameters['talkerId']!);
|
||||
name = Get.parameters['name']!;
|
||||
face = Get.parameters['face']!;
|
||||
mid = Get.parameters['mid']!;
|
||||
mid = Get.parameters['mid'];
|
||||
|
||||
querySessionMsg();
|
||||
}
|
||||
|
||||
@@ -1351,6 +1351,10 @@ class PlPlayerController {
|
||||
}
|
||||
|
||||
static void updatePlayCount() {
|
||||
_instance?._playerCount.value -= 1;
|
||||
if (_instance?._playerCount.value == 1) {
|
||||
_instance?.dispose();
|
||||
} else {
|
||||
_instance?._playerCount.value -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:PiliPalaX/utils/extension.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -14,20 +15,18 @@ class LoginUtils {
|
||||
static Future refreshLoginStatus(bool status) async {
|
||||
try {
|
||||
// 更改我的页面登录状态
|
||||
await Get.find<MineController>().resetUserInfo();
|
||||
if (status.not) {
|
||||
await Get.find<MineController>().resetUserInfo();
|
||||
}
|
||||
|
||||
// 更改主页登录状态
|
||||
HomeController homeCtr = Get.find<HomeController>();
|
||||
homeCtr.updateLoginStatus(status);
|
||||
Get.find<HomeController>().updateLoginStatus(status);
|
||||
|
||||
MineController mineCtr = Get.find<MineController>();
|
||||
mineCtr.userLogin.value = status;
|
||||
Get.find<MineController>().userLogin.value = status;
|
||||
|
||||
DynamicsController dynamicsCtr = Get.find<DynamicsController>();
|
||||
dynamicsCtr.userLogin.value = status;
|
||||
Get.find<DynamicsController>().userLogin.value = status;
|
||||
|
||||
MediaController mediaCtr = Get.find<MediaController>();
|
||||
mediaCtr.userLogin.value = status;
|
||||
Get.find<MediaController>().userLogin.value = status;
|
||||
} catch (err) {
|
||||
// SmartDialog.showToast('refreshLoginStatus error: ${err.toString()}');
|
||||
debugPrint('refreshLoginStatus error: $err');
|
||||
|
||||
@@ -22,6 +22,8 @@ class GStorage {
|
||||
static late final Box<dynamic> setting;
|
||||
static late final Box<dynamic> video;
|
||||
|
||||
static bool get isLogin => userInfo.get('userInfoCache') != null;
|
||||
|
||||
static List<double> get speedList => List<double>.from(
|
||||
video.get(
|
||||
VideoBoxKey.speedsList,
|
||||
@@ -113,6 +115,21 @@ class GStorage {
|
||||
static bool get showViewPoints =>
|
||||
setting.get(SettingBoxKey.showViewPoints, defaultValue: true);
|
||||
|
||||
static bool get showRelatedVideo =>
|
||||
setting.get(SettingBoxKey.showRelatedVideo, defaultValue: true);
|
||||
|
||||
static bool get showVideoReply =>
|
||||
setting.get(SettingBoxKey.showVideoReply, defaultValue: true);
|
||||
|
||||
static bool get showBangumiReply =>
|
||||
setting.get(SettingBoxKey.showBangumiReply, defaultValue: true);
|
||||
|
||||
static bool get alwaysExapndIntroPanel =>
|
||||
setting.get(SettingBoxKey.alwaysExapndIntroPanel, defaultValue: false);
|
||||
|
||||
static bool get exapndIntroPanelH =>
|
||||
setting.get(SettingBoxKey.exapndIntroPanelH, defaultValue: false);
|
||||
|
||||
static List<double> get dynamicDetailRatio =>
|
||||
setting.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]);
|
||||
|
||||
@@ -306,6 +323,11 @@ class SettingBoxKey {
|
||||
schemeVariant = 'schemeVariant',
|
||||
grpcReply = 'grpcReply',
|
||||
showViewPoints = 'showViewPoints',
|
||||
showRelatedVideo = 'showRelatedVideo',
|
||||
showVideoReply = 'showVideoReply',
|
||||
showBangumiReply = 'showBangumiReply',
|
||||
alwaysExapndIntroPanel = 'alwaysExapndIntroPanel',
|
||||
exapndIntroPanelH = 'exapndIntroPanelH',
|
||||
|
||||
// Sponsor Block
|
||||
enableSponsorBlock = 'enableSponsorBlock',
|
||||
|
||||
@@ -3,13 +3,20 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart';
|
||||
import 'package:PiliPalaX/http/constants.dart';
|
||||
import 'package:PiliPalaX/http/init.dart';
|
||||
import 'package:PiliPalaX/http/member.dart';
|
||||
import 'package:PiliPalaX/http/search.dart';
|
||||
import 'package:PiliPalaX/http/user.dart';
|
||||
import 'package:PiliPalaX/http/video.dart';
|
||||
import 'package:PiliPalaX/models/bangumi/info.dart';
|
||||
import 'package:PiliPalaX/models/common/search_type.dart';
|
||||
import 'package:PiliPalaX/pages/home/controller.dart';
|
||||
import 'package:PiliPalaX/pages/media/controller.dart';
|
||||
import 'package:PiliPalaX/pages/video/detail/introduction/widgets/group_panel.dart';
|
||||
import 'package:PiliPalaX/utils/feed_back.dart';
|
||||
import 'package:PiliPalaX/utils/login.dart';
|
||||
import 'package:PiliPalaX/utils/storage.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -18,10 +25,76 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:webview_cookie_manager/webview_cookie_manager.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web;
|
||||
|
||||
class Utils {
|
||||
static final Random random = Random();
|
||||
|
||||
static Future afterLoginByApp(
|
||||
Map<String, dynamic> token_info, cookie_info) async {
|
||||
try {
|
||||
GStorage.localCache.put(LocalCacheKey.accessKey, {
|
||||
'mid': token_info['mid'],
|
||||
'value': token_info['access_token'] ?? token_info['value'],
|
||||
'refresh': token_info['refresh_token'] ?? token_info['refresh']
|
||||
});
|
||||
List<dynamic> cookieInfo = cookie_info['cookies'];
|
||||
List<Cookie> cookies = [];
|
||||
String cookieStrings = cookieInfo.map((cookie) {
|
||||
String cstr =
|
||||
'${cookie['name']}=${cookie['value']};Domain=.bilibili.com;Path=/;';
|
||||
cookies.add(Cookie.fromSetCookieValue(cstr));
|
||||
return cstr;
|
||||
}).join('');
|
||||
List<String> urls = [
|
||||
HttpString.baseUrl,
|
||||
HttpString.apiBaseUrl,
|
||||
HttpString.tUrl
|
||||
];
|
||||
for (var url in urls) {
|
||||
await Request.cookieManager.cookieJar
|
||||
.saveFromResponse(Uri.parse(url), cookies);
|
||||
}
|
||||
Request.dio.options.headers['cookie'] = cookieStrings;
|
||||
await WebviewCookieManager().setCookies(cookies);
|
||||
for (Cookie item in cookies) {
|
||||
await web.CookieManager().setCookie(
|
||||
url: web.WebUri(item.domain ?? ''),
|
||||
name: item.name,
|
||||
value: item.value,
|
||||
path: item.path ?? '',
|
||||
domain: item.domain,
|
||||
isSecure: item.secure,
|
||||
isHttpOnly: item.httpOnly,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
SmartDialog.showToast('设置登录态失败,$e');
|
||||
}
|
||||
final result = await UserHttp.userInfo();
|
||||
if (result['status'] && result['data'].isLogin) {
|
||||
SmartDialog.showToast('登录成功,当前采用「'
|
||||
'${GStorage.setting.get(SettingBoxKey.defaultRcmdType, defaultValue: 'web')}'
|
||||
'端」推荐');
|
||||
await GStorage.userInfo.put('userInfoCache', result['data']);
|
||||
|
||||
try {
|
||||
final HomeController homeCtr = Get.find<HomeController>();
|
||||
homeCtr.updateLoginStatus(true);
|
||||
homeCtr.userFace.value = result['data'].face;
|
||||
final MediaController mediaCtr = Get.find<MediaController>();
|
||||
mediaCtr.mid = result['data'].mid;
|
||||
} catch (_) {}
|
||||
await LoginUtils.refreshLoginStatus(true);
|
||||
} else {
|
||||
// 获取用户信息失败
|
||||
SmartDialog.showNotify(
|
||||
msg: '登录失败,请检查cookie是否正确,${result['message']}',
|
||||
notifyType: NotifyType.warning);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isStringNumeric(str) {
|
||||
RegExp numericRegex = RegExp(r'^[\d\.]+$');
|
||||
return numericRegex.hasMatch(str.toString());
|
||||
|
||||
@@ -252,7 +252,7 @@ packages:
|
||||
description:
|
||||
path: "."
|
||||
ref: main
|
||||
resolved-ref: "7861474d44739adcf494dd3881cc64cb1a36ed72"
|
||||
resolved-ref: "cfa1b7cc7fbd7276d58307ea515533af3807ac7d"
|
||||
url: "https://github.com/bggRGjQaUbCoE/canvas_danmaku.git"
|
||||
source: git
|
||||
version: "0.2.5"
|
||||
@@ -2078,4 +2078,4 @@ packages:
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.5.0 <4.0.0"
|
||||
flutter: ">=3.24.5"
|
||||
flutter: ">=3.24.5"
|
||||
|
||||
Reference in New Issue
Block a user