From 3cb595e76e93369af5914e5ad4b97637c2f6e0fe Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 1 Nov 2024 21:20:36 +0800 Subject: [PATCH 1/5] opt: login status processing --- lib/http/interceptor.dart | 4 ++++ lib/pages/setting/controller.dart | 11 +---------- lib/utils/login.dart | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/http/interceptor.dart b/lib/http/interceptor.dart index 9f9bc1c1..e2ca5012 100644 --- a/lib/http/interceptor.dart +++ b/lib/http/interceptor.dart @@ -3,6 +3,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:dio/dio.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:pilipala/utils/login.dart'; class ApiInterceptor extends Interceptor { @override @@ -18,6 +19,9 @@ class ApiInterceptor extends Interceptor { void onResponse(Response response, ResponseInterceptorHandler handler) { try { // 在响应之后处理数据 + if (response.data['code'] == -101) { + LoginUtils.loginOut(); + } } catch (err) { print('ApiInterceptor: $err'); } diff --git a/lib/pages/setting/controller.dart b/lib/pages/setting/controller.dart index 1fbd7efb..49c4d1b7 100644 --- a/lib/pages/setting/controller.dart +++ b/lib/pages/setting/controller.dart @@ -61,16 +61,7 @@ class SettingController extends GetxController { ), TextButton( onPressed: () async { - // 清空cookie - await Request.cookieManager.cookieJar.deleteAll(); - Request.dio.options.headers['cookie'] = ''; - - // 清空本地存储的用户标识 - userInfoCache.put('userInfoCache', null); - localCache - .put(LocalCacheKey.accessKey, {'mid': -1, 'value': ''}); - - await LoginUtils.refreshLoginStatus(false); + await LoginUtils.loginOut(); SmartDialog.dismiss().then((value) => Get.back()); }, child: const Text('确认'), diff --git a/lib/utils/login.dart b/lib/utils/login.dart index 07afd2dc..841251b8 100644 --- a/lib/utils/login.dart +++ b/lib/utils/login.dart @@ -7,15 +7,20 @@ import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; +import 'package:pilipala/http/index.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/pages/dynamics/index.dart'; import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/mine/index.dart'; import 'package:pilipala/utils/cookie.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:uuid/uuid.dart'; class LoginUtils { + static Box userInfoCache = GStrorage.userInfo; + static Box localCache = GStrorage.localCache; + static Future refreshLoginStatus(bool status) async { try { // 更改我的页面登录状态 @@ -109,4 +114,14 @@ class LoginUtils { Clipboard.setData(ClipboardData(text: content)); } } + + // 退出登录 + static loginOut() async { + await Request.cookieManager.cookieJar.deleteAll(); + Request.dio.options.headers['cookie'] = ''; + userInfoCache.put('userInfoCache', null); + localCache.put(LocalCacheKey.accessKey, {'mid': -1, 'value': ''}); + GlobalDataCache().userInfo = null; + await refreshLoginStatus(false); + } } From 6dccaa87ae842239fd043c6015f33eda8c5be6d8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 1 Nov 2024 22:21:12 +0800 Subject: [PATCH 2/5] mod: fav isPublic logic --- lib/common/constants.dart | 1 - lib/pages/fav/widgets/item.dart | 5 ++--- .../video/detail/introduction/widgets/fav_panel.dart | 11 +++++------ lib/utils/logic_utils.dart | 6 ++++++ 4 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 lib/utils/logic_utils.dart diff --git a/lib/common/constants.dart b/lib/common/constants.dart index dda54361..0607206c 100644 --- a/lib/common/constants.dart +++ b/lib/common/constants.dart @@ -15,5 +15,4 @@ class Constants { // 59b43e04ad6965f34319062b478f83dd TV端 static const String appSec = '59b43e04ad6965f34319062b478f83dd'; static const String thirdSign = '04224646d1fea004e79606d3b038c84a'; - static const List publicFavFolder = [0, 2, 22]; } diff --git a/lib/pages/fav/widgets/item.dart b/lib/pages/fav/widgets/item.dart index 412b498f..5269d579 100644 --- a/lib/pages/fav/widgets/item.dart +++ b/lib/pages/fav/widgets/item.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/logic_utils.dart'; import 'package:pilipala/utils/utils.dart'; class FavItem extends StatelessWidget { @@ -96,9 +97,7 @@ class VideoContent extends StatelessWidget { ), const Spacer(), Text( - Constants.publicFavFolder.contains(favFolderItem.attr) - ? '公开' - : '私密', + LogicUtils.isPublic(favFolderItem.attr) ? '公开' : '私密', textAlign: TextAlign.start, style: TextStyle( fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, diff --git a/lib/pages/video/detail/introduction/widgets/fav_panel.dart b/lib/pages/video/detail/introduction/widgets/fav_panel.dart index fa043cb6..acccf862 100644 --- a/lib/pages/video/detail/introduction/widgets/fav_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/fav_panel.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; -import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/logic_utils.dart'; import 'package:pilipala/utils/storage.dart'; class FavPanel extends StatefulWidget { @@ -67,14 +67,13 @@ class _FavPanelState extends State { onTap: () => widget.ctr!.onChoose(item.favState != 1, index), dense: true, - leading: Icon( - Constants.publicFavFolder.contains(item.attr) - ? Icons.folder_outlined - : Icons.lock_outline), + leading: Icon(LogicUtils.isPublic(item.attr) + ? Icons.folder_outlined + : Icons.lock_outline), minLeadingWidth: 0, title: Text(item.title!), subtitle: Text( - '${item.mediaCount}个内容 - ${Constants.publicFavFolder.contains(item.attr) ? '公开' : '私密'}', + '${item.mediaCount}个内容 - ${LogicUtils.isPublic(item.attr) ? '公开' : '私密'}', ), trailing: Transform.scale( scale: 0.9, diff --git a/lib/utils/logic_utils.dart b/lib/utils/logic_utils.dart new file mode 100644 index 00000000..3994c222 --- /dev/null +++ b/lib/utils/logic_utils.dart @@ -0,0 +1,6 @@ +class LogicUtils { + // 收藏夹是否公开 + static bool isPublic(int attr) { + return (attr & 1) == 0; + } +} From 3209bde29094d9afa9704e674a611221d36d5dee Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 1 Nov 2024 22:22:19 +0800 Subject: [PATCH 3/5] opt: block rec ad --- lib/http/video.dart | 2 ++ lib/pages/bangumi/introduction/controller.dart | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/http/video.dart b/lib/http/video.dart index b3970a14..712b1363 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -97,6 +97,8 @@ class VideoHttp { for (var i in res.data['data']['items']) { // 屏蔽推广和拉黑用户 if (i['card_goto'] != 'ad_av' && + i['card_goto'] != 'ad_web_s' && + i['card_goto'] != 'ad_web' && (!enableRcmdDynamic ? i['card_goto'] != 'picture' : true) && (i['args'] != null && !blackMidsList.contains(i['args']['up_mid']))) { diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index dc173a57..d79eef79 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -24,7 +24,7 @@ class BangumiIntroController extends GetxController { // 视频bvid String bvid = Get.parameters['bvid']!; var seasonId = Get.parameters['seasonId'] != null - ? int.parse(Get.parameters['seasonId']!) + ? int.tryParse(Get.parameters['seasonId']!) : null; var epId = Get.parameters['epId'] != null ? int.tryParse(Get.parameters['epId']!) @@ -69,6 +69,7 @@ class BangumiIntroController extends GetxController { @override void onInit() { super.onInit(); + print('bangumi: ${Get.parameters.toString()}'); userInfo = userInfoCache.get('userInfoCache'); userLogin = userInfo != null; if (userLogin && seasonId != null) { From a69a27cdc43629761af187dd269bedd73690afcb Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 2 Nov 2024 01:51:26 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20up=E6=8A=95=E7=A8=BF=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=85=A8=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/user.dart | 30 ++++++++++++++ lib/pages/member_archive/controller.dart | 31 +++++++++++++- lib/pages/member_archive/view.dart | 9 +++++ lib/pages/video/detail/controller.dart | 40 +++++++++++++++++-- lib/pages/video/detail/view.dart | 25 +++++++----- .../detail/widgets/watch_later_list.dart | 10 +++-- 6 files changed, 126 insertions(+), 19 deletions(-) diff --git a/lib/http/user.dart b/lib/http/user.dart index 63f6bf66..99888aea 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -516,4 +516,34 @@ class UserHttp { }; } } + + // 解析up投稿 + static Future parseUpArchiveVideo({ + required int mid, + required int oid, + required String bvid, + String sortField = 'pubtime', + }) async { + var res = await Request().get( + 'https://www.bilibili.com/list/$mid', + data: { + 'oid': oid, + 'bvid': bvid, + 'sort_field': sortField, + }, + ); + String scriptContent = + extractScriptContents(parse(res.data).body!.outerHtml)[0]; + int startIndex = scriptContent.indexOf('{'); + int endIndex = scriptContent.lastIndexOf('};'); + String jsonContent = scriptContent.substring(startIndex, endIndex + 1); + // 解析JSON字符串为Map + Map jsonData = json.decode(jsonContent); + return { + 'status': true, + 'data': jsonData['resourceList'] + .map((e) => MediaVideoItemModel.fromJson(e)) + .toList() + }; + } } diff --git a/lib/pages/member_archive/controller.dart b/lib/pages/member_archive/controller.dart index 92f95da6..61816ed5 100644 --- a/lib/pages/member_archive/controller.dart +++ b/lib/pages/member_archive/controller.dart @@ -1,14 +1,16 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/http/member.dart'; +import 'package:pilipala/http/search.dart'; import 'package:pilipala/models/member/archive.dart'; import 'package:pilipala/utils/global_data_cache.dart'; +import 'package:pilipala/utils/utils.dart'; class MemberArchiveController extends GetxController { final ScrollController scrollController = ScrollController(); late int mid; int pn = 1; - int count = 0; + RxInt count = 0.obs; RxMap currentOrder = {}.obs; RxList> orderList = [ {'type': 'pubdate', 'label': '最新发布'}, @@ -50,11 +52,11 @@ class MemberArchiveController extends GetxController { if (res['status']) { if (type == 'init') { archivesList.value = res['data'].list.vlist; + count.value = res['data'].page['count']; } if (type == 'onLoad') { archivesList.addAll(res['data'].list.vlist); } - count = res['data'].page['count']; pn += 1; } isLoading.value = false; @@ -76,4 +78,29 @@ class MemberArchiveController extends GetxController { Future onLoad() async { getMemberArchive('onLoad'); } + + Future toViewPlayAll() async { + final VListItemModel firstItem = archivesList.first; + final String bvid = firstItem.bvid!; + final int cid = await SearchHttp.ab2c(bvid: bvid); + final String heroTag = Utils.makeHeroTag(bvid); + late Map sortFieldMap = { + 'pubdate': 'pubtime', + 'click': 'play', + 'fav': 'fav', + }; + Get.toNamed( + '/video?bvid=${firstItem.bvid}&cid=$cid', + arguments: { + 'videoItem': firstItem, + 'heroTag': heroTag, + 'sourceType': 'up_archive', + 'oid': firstItem.aid, + 'favTitle': '${firstItem.owner!.name!} - ${currentOrder['label']!}', + 'favInfo': firstItem, + 'count': count.value, + 'sortField': sortFieldMap[currentOrder['type']], + }, + ); + } } diff --git a/lib/pages/member_archive/view.dart b/lib/pages/member_archive/view.dart index 86ff9940..6963dad6 100644 --- a/lib/pages/member_archive/view.dart +++ b/lib/pages/member_archive/view.dart @@ -135,6 +135,15 @@ class _MemberArchivePageState extends State { ), ], ), + floatingActionButton: Obx( + () => _memberArchivesController.count > 0 + ? FloatingActionButton.extended( + onPressed: _memberArchivesController.toViewPlayAll, + label: const Text('播放全部'), + icon: const Icon(Icons.playlist_play), + ) + : const SizedBox(), + ), ); } } diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 3fead9c7..925f770b 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -119,6 +119,7 @@ class VideoDetailController extends GetxController List mediaList = []; RxBool isWatchLaterVisible = false.obs; RxString watchLaterTitle = ''.obs; + RxInt watchLaterCount = 0.obs; @override void onInit() { @@ -170,7 +171,7 @@ class VideoDetailController extends GetxController sourceType.value = argMap['sourceType'] ?? 'normal'; isWatchLaterVisible.value = - sourceType.value == 'watchLater' || sourceType.value == 'fav'; + ['watchLater', 'fav', 'up_archive'].contains(sourceType.value); if (sourceType.value == 'watchLater') { watchLaterTitle.value = '稍后再看'; fetchMediaList(); @@ -179,6 +180,11 @@ class VideoDetailController extends GetxController watchLaterTitle.value = argMap['favTitle']; queryFavVideoList(); } + if (sourceType.value == 'up_archive') { + watchLaterTitle.value = argMap['favTitle']; + watchLaterCount.value = argMap['count']; + queryArchiveVideoList(); + } tabCtr.addListener(() { onTabChanged(); }); @@ -585,7 +591,9 @@ class VideoDetailController extends GetxController } void toggeleWatchLaterVisible(bool val) { - if (sourceType.value == 'watchLater' || sourceType.value == 'fav') { + if (sourceType.value == 'watchLater' || + sourceType.value == 'fav' || + sourceType.value == 'up_archive') { isWatchLaterVisible.value = !isWatchLaterVisible.value; } } @@ -616,8 +624,19 @@ class VideoDetailController extends GetxController changeMediaList: changeMediaList, panelTitle: watchLaterTitle.value, bvid: bvid, - mediaId: Get.arguments['mediaId'], + mediaId: [ + 'watchLater', + 'fav', + ].contains(sourceType.value) + ? Get.arguments['mediaId'] + : Get.arguments['favInfo'].owner.mid, hasMore: mediaList.length != Get.arguments['count'], + type: [ + 'watchLater', + 'fav', + ].contains(sourceType.value) + ? 3 + : 1, ); }); replyReplyBottomSheetCtr?.closed.then((value) { @@ -667,6 +686,21 @@ class VideoDetailController extends GetxController } } + Future queryArchiveVideoList() async { + final Map argMap = Get.arguments; + var favInfo = argMap['favInfo']; + var sortField = argMap['sortField']; + var res = await UserHttp.parseUpArchiveVideo( + mid: favInfo.owner.mid, + oid: oid.value, + bvid: bvid, + sortField: sortField, + ); + if (res['status']) { + mediaList = res['data']; + } + } + // 监听tabBarView切换 void onTabChanged() { isWatchLaterVisible.value = tabCtr.index == 0; diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 7fe76745..57523dd0 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -783,7 +783,8 @@ class _VideoDetailPageState extends State Obx( () => Visibility( visible: vdCtr.sourceType.value == 'watchLater' || - vdCtr.sourceType.value == 'fav', + vdCtr.sourceType.value == 'fav' || + vdCtr.sourceType.value == 'up_archive', child: AnimatedPositioned( duration: const Duration(milliseconds: 400), curve: Curves.easeInOut, @@ -815,17 +816,21 @@ class _VideoDetailPageState extends State child: Row(children: [ const Icon(Icons.playlist_play, size: 24), const SizedBox(width: 10), - Text( - vdCtr.watchLaterTitle.value, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, - fontWeight: FontWeight.bold, - letterSpacing: 0.2, + Expanded( + child: Text( + vdCtr.watchLaterTitle.value, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + fontWeight: FontWeight.bold, + letterSpacing: 0.2, + ), ), ), - const Spacer(), + const SizedBox(width: 50), const Icon(Icons.keyboard_arrow_up_rounded, size: 26), ]), ), diff --git a/lib/pages/video/detail/widgets/watch_later_list.dart b/lib/pages/video/detail/widgets/watch_later_list.dart index 8e83af4e..eda6cf3e 100644 --- a/lib/pages/video/detail/widgets/watch_later_list.dart +++ b/lib/pages/video/detail/widgets/watch_later_list.dart @@ -19,8 +19,9 @@ class MediaListPanel extends StatefulWidget { this.changeMediaList, this.panelTitle, this.bvid, - this.mediaId, + required this.mediaId, this.hasMore = false, + required this.type, super.key, }); @@ -29,8 +30,9 @@ class MediaListPanel extends StatefulWidget { final Function? changeMediaList; final String? panelTitle; final String? bvid; - final int? mediaId; + final int mediaId; final bool hasMore; + final int type; @override State createState() => _MediaListPanelState(); @@ -59,8 +61,8 @@ class _MediaListPanelState extends State { void loadMore() async { var res = await UserHttp.getMediaList( - type: 3, - bizId: widget.mediaId!, + type: widget.type, + bizId: widget.mediaId, ps: 20, oid: mediaList.last.id, ); From fef0cf9546df5cd568fa0dc1dc777d2a2dac0be5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 2 Nov 2024 13:17:55 +0800 Subject: [PATCH 5/5] mod --- lib/http/interceptor.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http/interceptor.dart b/lib/http/interceptor.dart index e2ca5012..b33d18df 100644 --- a/lib/http/interceptor.dart +++ b/lib/http/interceptor.dart @@ -19,7 +19,7 @@ class ApiInterceptor extends Interceptor { void onResponse(Response response, ResponseInterceptorHandler handler) { try { // 在响应之后处理数据 - if (response.data['code'] == -101) { + if (response.data is Map && response.data['code'] == -101) { LoginUtils.loginOut(); } } catch (err) {