From e5d3e84b612c03b70643b51140199bd7043589e6 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 14:05:04 +0800 Subject: [PATCH 01/18] opt: videoDetail appbar --- lib/pages/video/detail/view.dart | 48 +++++++++++++++------ lib/pages/video/detail/widgets/app_bar.dart | 21 ++++----- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 75f50b61..1585a6f3 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -123,14 +123,7 @@ class _VideoDetailPageState extends State // 流 appbarStreamListen() { appbarStream = StreamController.broadcast(); - _extendNestCtr.addListener( - () { - final double offset = _extendNestCtr.position.pixels; - vdCtr.sheetHeight.value = - Get.size.height - videoHeight - statusBarHeight + offset; - appbarStream.add(offset); - }, - ); + _extendNestCtr.addListener(_extendNestCtrListener); } // 播放器状态监听 @@ -225,6 +218,14 @@ class _VideoDetailPageState extends State statusHeight = await StatusBarControl.getHeight; } + // _extendNestCtr监听 + void _extendNestCtrListener() { + final double offset = _extendNestCtr.position.pixels; + vdCtr.sheetHeight.value = + Get.size.height - videoHeight - statusBarHeight + offset; + appbarStream.add(offset); + } + @override void dispose() { shutdownTimerService.handleWaitingFinished(); @@ -243,6 +244,7 @@ class _VideoDetailPageState extends State appbarStream.close(); WidgetsBinding.instance.removeObserver(this); _lifecycleListener.dispose(); + _extendNestCtr.removeListener(_extendNestCtrListener); super.dispose(); } @@ -594,6 +596,28 @@ class _VideoDetailPageState extends State ); } + Widget buildAppBar(BuildContext context, AsyncSnapshot snapshot) { + final double distance = + statusBarHeight + MediaQuery.of(context).padding.top; + return AppBar( + backgroundColor: Colors.black, + systemOverlayStyle: Platform.isAndroid + ? SystemUiOverlayStyle( + statusBarIconBrightness: + Theme.of(context).brightness == Brightness.dark + ? Brightness.light + : (snapshot.data! > distance + ? Brightness.dark + : Brightness.light), + ) + : Theme.of(context).brightness == Brightness.dark + ? SystemUiOverlayStyle.light + : (snapshot.data! > distance + ? SystemUiOverlayStyle.dark + : SystemUiOverlayStyle.light), + ); + } + Widget childWhenDisabled = SafeArea( top: MediaQuery.of(context).orientation == Orientation.portrait && plPlayerController?.isFullScreen.value == true, @@ -611,11 +635,7 @@ class _VideoDetailPageState extends State child: StreamBuilder( stream: appbarStream.stream.distinct(), initialData: 0, - builder: ((context, snapshot) { - return AppBar( - backgroundColor: Colors.black, - ); - }), + builder: buildAppBar, ), ), body: ExtendedNestedScrollView( @@ -773,7 +793,7 @@ class _VideoDetailPageState extends State builder: ((context, snapshot) { return ScrollAppBar( snapshot.data!.toDouble(), - () => continuePlay(), + continuePlay, playerStatus.value, null, ); diff --git a/lib/pages/video/detail/widgets/app_bar.dart b/lib/pages/video/detail/widgets/app_bar.dart index bf74ac13..6fdd72f6 100644 --- a/lib/pages/video/detail/widgets/app_bar.dart +++ b/lib/pages/video/detail/widgets/app_bar.dart @@ -34,21 +34,16 @@ class ScrollAppBar extends StatelessWidget { child: AppBar( primary: false, centerTitle: true, - title: TextButton( + title: TextButton.icon( onPressed: () => callback(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.play_arrow_rounded), - Text( - playerStatus == PlayerStatus.paused - ? '继续播放' - : playerStatus == PlayerStatus.completed - ? '重新播放' - : '播放中', - ) - ], + label: Text( + playerStatus == PlayerStatus.paused + ? '继续播放' + : playerStatus == PlayerStatus.completed + ? '重新播放' + : '播放中', ), + icon: const Icon(Icons.play_arrow_rounded), ), // actions: [ // IconButton( From 88d8027b60e40d8e38c2b56f07dbb687f83dd17e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 15:59:54 +0800 Subject: [PATCH 02/18] opt: vertical video layout --- lib/pages/video/detail/controller.dart | 12 +++++++----- lib/pages/video/detail/view.dart | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index e09dd20f..0f66ad02 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -125,6 +125,8 @@ class VideoDetailController extends GetxController RxInt watchLaterCount = 0.obs; List skipSegments = []; int? lastPosition; + // 默认屏幕方向 + RxString videoDirection = 'horizontal'.obs; @override void onInit() { @@ -283,6 +285,10 @@ class VideoDetailController extends GetxController } else { ScreenBrightness().resetScreenBrightness(); } + videoDirection.value = (firstVideo.width != null && + firstVideo.height != null) + ? (firstVideo.width! > firstVideo.height! ? 'horizontal' : 'vertical') + : 'horizontal'; await plPlayerController.setDataSource( DataSource( videoSource: video ?? videoUrl, @@ -299,11 +305,7 @@ class VideoDetailController extends GetxController seekTo: seekToTime ?? defaultST, duration: duration ?? Duration(milliseconds: data.timeLength ?? 0), // 宽>高 水平 否则 垂直 - direction: firstVideo.width != null && firstVideo.height != null - ? ((firstVideo.width! - firstVideo.height!) > 0 - ? 'horizontal' - : 'vertical') - : null, + direction: videoDirection.value, bvid: bvid, cid: cid.value, enableHeart: enableHeart, diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 1585a6f3..91f942d5 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -221,9 +221,15 @@ class _VideoDetailPageState extends State // _extendNestCtr监听 void _extendNestCtrListener() { final double offset = _extendNestCtr.position.pixels; - vdCtr.sheetHeight.value = - Get.size.height - videoHeight - statusBarHeight + offset; - appbarStream.add(offset); + if (vdCtr.videoDirection.value == 'horizontal') { + vdCtr.sheetHeight.value = + Get.size.height - videoHeight - statusBarHeight + offset; + appbarStream.add(offset); + } else { + if (offset > (Get.size.width * 22 / 16 - videoHeight)) { + appbarStream.add(offset - (Get.size.width * 22 / 16 - videoHeight)); + } + } } @override @@ -501,6 +507,12 @@ class _VideoDetailPageState extends State final double pinnedHeaderHeight = statusBarHeight + kToolbarHeight + videoHeight.value; // ignore: no_leading_underscores_for_local_identifiers + vdCtr.videoDirection.listen((p0) { + if (p0 == 'vertical') { + defaultVideoHeight = sizeContext.width * 22 / 16; + videoHeight.value = sizeContext.width * 22 / 16; + } + }); // 竖屏 final bool isPortrait = _context.orientation == Orientation.portrait; From c3ef35f150d1857ba2e85cb36043f229b6934949 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 19:45:06 +0800 Subject: [PATCH 03/18] mod: cancel player fullScreenCb --- lib/pages/video/detail/view.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 91f942d5..599ad07c 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -555,10 +555,6 @@ class _VideoDetailPageState extends State showEposideCb: () => vdCtr.videoType == SearchType.video ? videoIntroController.showEposideHandler() : bangumiIntroController.showEposideHandler(), - fullScreenCb: (bool status) { - videoHeight.value = - status ? Get.size.height : defaultVideoHeight; - }, )); } From 570a073963dcf7f8148823fe965cd967b089818c Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 19:56:14 +0800 Subject: [PATCH 04/18] mod: AppBarTheme --- lib/main.dart | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 930b8f4b..1ec86c8e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -224,12 +224,8 @@ class BuildMainApp extends StatelessWidget { AppBarTheme appBarTheme(ColorScheme colorScheme) { return AppBarTheme( - backgroundColor: currentThemeValue == ThemeType.dark - ? darkColorScheme.surface - : lightColorScheme.surface, - foregroundColor: currentThemeValue == ThemeType.dark - ? darkColorScheme.onSurface - : lightColorScheme.onSurface, + backgroundColor: colorScheme.surface, + foregroundColor: colorScheme.onSurface, elevation: 0, titleSpacing: 0, scrolledUnderElevation: 0, From 1252b609a9f0075fa1a046bb2c434b2b0eed1739 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 22:18:53 +0800 Subject: [PATCH 05/18] mod: userInfo data type --- lib/http/init.dart | 3 ++- lib/http/member.dart | 5 +++-- lib/pages/bangumi/controller.dart | 7 ++++--- lib/pages/bangumi/introduction/controller.dart | 5 +++-- lib/pages/bangumi/introduction/view.dart | 2 +- lib/pages/bangumi/widgets/bangumi_panel.dart | 5 +++-- lib/pages/dynamics/controller.dart | 5 +++-- lib/pages/dynamics/widgets/action_panel.dart | 2 +- lib/pages/fan/controller.dart | 9 +++++---- lib/pages/follow/controller.dart | 11 ++++++----- lib/pages/home/controller.dart | 7 ++++--- lib/pages/home/widgets/app_bar.dart | 3 ++- lib/pages/main/controller.dart | 5 +++-- lib/pages/member/controller.dart | 5 +++-- lib/pages/mine_edit/controller.dart | 3 ++- lib/pages/setting/controller.dart | 4 ++-- lib/pages/setting/privacy_setting.dart | 3 ++- lib/pages/setting/recommend_setting.dart | 3 ++- lib/pages/video/detail/controller.dart | 5 +++-- lib/pages/video/detail/introduction/controller.dart | 7 +++---- lib/pages/whisper_detail/controller.dart | 5 +++-- lib/pages/whisper_detail/view.dart | 3 --- 22 files changed, 60 insertions(+), 47 deletions(-) diff --git a/lib/http/init.dart b/lib/http/init.dart index db56fa70..8a11034c 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -9,6 +9,7 @@ import 'package:dio/dio.dart'; import 'package:dio/io.dart'; import 'package:dio_cookie_manager/dio_cookie_manager.dart'; import 'package:hive/hive.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/id_utils.dart'; import '../utils/storage.dart'; import '../utils/utils.dart'; @@ -43,7 +44,7 @@ class Request { dio.interceptors.add(cookieManager); final List cookie = await cookieManager.cookieJar .loadForRequest(Uri.parse(HttpString.baseUrl)); - final userInfo = userInfoCache.get('userInfoCache'); + final UserInfoData? userInfo = userInfoCache.get('userInfoCache'); if (userInfo != null && userInfo.mid != null) { final List cookie2 = await cookieManager.cookieJar .loadForRequest(Uri.parse(HttpString.tUrl)); diff --git a/lib/http/member.dart b/lib/http/member.dart index 53e14eae..66d0ff47 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -4,6 +4,7 @@ import 'package:hive/hive.dart'; import 'package:html/parser.dart'; import 'package:pilipala/models/member/article.dart'; import 'package:pilipala/models/member/like.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/global_data_cache.dart'; import '../common/constants.dart'; import '../models/dynamics/result.dart'; @@ -472,9 +473,9 @@ class MemberHttp { String accessKey = res.data['data']['access_token']; Box localCache = GStorage.localCache; Box userInfoCache = GStorage.userInfo; - var userInfo = userInfoCache.get('userInfoCache'); + final UserInfoData? userInfo = userInfoCache.get('userInfoCache'); localCache.put( - LocalCacheKey.accessKey, {'mid': userInfo.mid, 'value': accessKey}); + LocalCacheKey.accessKey, {'mid': userInfo!.mid, 'value': accessKey}); return {'status': true, 'data': [], 'msg': '操作成功'}; } else { return { diff --git a/lib/pages/bangumi/controller.dart b/lib/pages/bangumi/controller.dart index 746808bf..e7582cfc 100644 --- a/lib/pages/bangumi/controller.dart +++ b/lib/pages/bangumi/controller.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/bangumi.dart'; import 'package:pilipala/models/bangumi/list.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; class BangumiController extends GetxController { @@ -15,14 +16,14 @@ class BangumiController extends GetxController { Box userInfoCache = GStorage.userInfo; RxBool userLogin = false.obs; late int mid; - var userInfo; + UserInfoData? userInfo; @override void onInit() { super.onInit(); userInfo = userInfoCache.get('userInfoCache'); if (userInfo != null) { - mid = userInfo.mid; + mid = userInfo!.mid!; } userLogin.value = userInfo != null; } @@ -55,7 +56,7 @@ class BangumiController extends GetxController { if (userInfo == null) { return; } - var result = await BangumiHttp.getRecentBangumi(mid: userInfo.mid); + var result = await BangumiHttp.getRecentBangumi(mid: userInfo!.mid!); if (result['status']) { bangumiFollowList.value = result['data'].list; total.value = result['data'].total; diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 2e6cd392..f06e6ee8 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -8,6 +8,7 @@ import 'package:pilipala/http/search.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/bangumi/info.dart'; import 'package:pilipala/models/user/fav_folder.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/reply/index.dart'; import 'package:pilipala/plugin/pl_player/models/play_repeat.dart'; @@ -57,7 +58,7 @@ class BangumiIntroController extends GetxController { RxBool isFollowed = false.obs; RxInt followStatus = 1.obs; int _tempThemeValue = -1; - var userInfo; + UserInfoData? userInfo; PersistentBottomSheetController? bottomSheetController; List> followStatusList = [ {'title': '标记为 「想看」', 'status': 1}, @@ -259,7 +260,7 @@ class BangumiIntroController extends GetxController { Future queryVideoInFolder() async { var result = await VideoHttp.videoInFolder( - mid: userInfo.mid, rid: IdUtils.bv2av(bvid)); + mid: userInfo!.mid!, rid: IdUtils.bv2av(bvid)); if (result['status']) { favFolderData.value = result['data']; } diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index 3ad0625f..75e293c4 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -148,7 +148,7 @@ class _BangumiInfoState extends State { // 收藏 showFavBottomSheet() async { - if (bangumiIntroController.userInfo.mid == null) { + if (bangumiIntroController.userInfo?.mid == null) { SmartDialog.showToast('账号未登录'); return; } diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index f6f1ff22..63da14fd 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -5,6 +5,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/models/bangumi/info.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/utils/storage.dart'; import '../../../common/pages_bottom_sheet.dart'; @@ -37,7 +38,7 @@ class _BangumiPanelState extends State { late RxInt currentIndex = (-1).obs; final ScrollController listViewScrollCtr = ScrollController(); Box userInfoCache = GStorage.userInfo; - dynamic userInfo; + UserInfoData? userInfo; // 默认未开通 int vipStatus = 0; late int cid; @@ -63,7 +64,7 @@ class _BangumiPanelState extends State { /// 获取大会员状态 userInfo = userInfoCache.get('userInfoCache'); if (userInfo != null) { - vipStatus = userInfo.vipStatus; + vipStatus = userInfo!.vipStatus!; } } diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index ff5c959a..cdc08bdd 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -10,6 +10,7 @@ import 'package:pilipala/models/common/dynamics_type.dart'; import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/models/dynamics/up.dart'; import 'package:pilipala/models/live/item.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/route_push.dart'; @@ -52,7 +53,7 @@ class DynamicsController extends GetxController { RxInt initialValue = 0.obs; Box userInfoCache = GStorage.userInfo; RxBool userLogin = false.obs; - var userInfo; + UserInfoData? userInfo; RxBool isLoadingDynamic = false.obs; Box setting = GStorage.setting; @@ -246,7 +247,7 @@ class DynamicsController extends GetxController { } upData.value.upList!.insertAll(0, [ UpItem(face: '', uname: '全部动态', mid: -1), - UpItem(face: userInfo.face, uname: '我', mid: userInfo.mid), + UpItem(face: userInfo!.face, uname: '我', mid: userInfo!.mid), ]); } return res; diff --git a/lib/pages/dynamics/widgets/action_panel.dart b/lib/pages/dynamics/widgets/action_panel.dart index f403ee19..26c0d7a1 100644 --- a/lib/pages/dynamics/widgets/action_panel.dart +++ b/lib/pages/dynamics/widgets/action_panel.dart @@ -90,7 +90,7 @@ class _ActionPanelState extends State SmartDialog.showToast('请先登录'); return; } - int mid = userInfo.mid; + int mid = userInfo.mid!; showModalBottomSheet( context: context, enableDrag: true, diff --git a/lib/pages/fan/controller.dart b/lib/pages/fan/controller.dart index 1a82b538..f9a9388f 100644 --- a/lib/pages/fan/controller.dart +++ b/lib/pages/fan/controller.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/fan.dart'; import 'package:pilipala/models/fans/result.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; class FansController extends GetxController { @@ -13,7 +14,7 @@ class FansController extends GetxController { RxList fansList = [].obs; late int mid; late String name; - var userInfo; + UserInfoData? userInfo; RxString loadingText = '加载中...'.obs; RxBool isOwner = false.obs; @@ -23,9 +24,9 @@ class FansController extends GetxController { userInfo = userInfoCache.get('userInfoCache'); mid = Get.parameters['mid'] != null ? int.parse(Get.parameters['mid']!) - : userInfo.mid; - isOwner.value = mid == userInfo.mid; - name = Get.parameters['name'] ?? userInfo.uname; + : userInfo!.mid!; + isOwner.value = mid == userInfo?.mid; + name = Get.parameters['name'] ?? userInfo?.uname ?? ''; } Future queryFans(type) async { diff --git a/lib/pages/follow/controller.dart b/lib/pages/follow/controller.dart index e39eb3cd..04bba2f9 100644 --- a/lib/pages/follow/controller.dart +++ b/lib/pages/follow/controller.dart @@ -6,6 +6,7 @@ import 'package:pilipala/http/follow.dart'; import 'package:pilipala/http/member.dart'; import 'package:pilipala/models/follow/result.dart'; import 'package:pilipala/models/member/tags.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; /// 查看自己的关注时,可以查看分类 @@ -18,7 +19,7 @@ class FollowController extends GetxController with GetTickerProviderStateMixin { RxList followList = [].obs; late int mid; late String name; - var userInfo; + UserInfoData? userInfo; RxString loadingText = '加载中...'.obs; RxBool isOwner = false.obs; late List followTags; @@ -30,9 +31,9 @@ class FollowController extends GetxController with GetTickerProviderStateMixin { userInfo = userInfoCache.get('userInfoCache'); mid = Get.parameters['mid'] != null ? int.parse(Get.parameters['mid']!) - : userInfo.mid; - isOwner.value = mid == userInfo.mid; - name = Get.parameters['name'] ?? userInfo.uname; + : userInfo!.mid!; + isOwner.value = mid == userInfo?.mid; + name = Get.parameters['name'] ?? userInfo?.uname ?? ''; } Future queryFollowings(type) async { @@ -68,7 +69,7 @@ class FollowController extends GetxController with GetTickerProviderStateMixin { // 当查看当前用户的关注时,请求关注分组 Future followUpTags() async { - if (userInfo != null && mid == userInfo.mid) { + if (userInfo != null && mid == userInfo!.mid) { var res = await MemberHttp.followUpTags(); if (res['status']) { followTags = res['data']; diff --git a/lib/pages/home/controller.dart b/lib/pages/home/controller.dart index 91f16c9f..0797f499 100644 --- a/lib/pages/home/controller.dart +++ b/lib/pages/home/controller.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/models/common/tab_type.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; import '../../http/index.dart'; @@ -18,7 +19,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { Box settingStorage = GStorage.setting; RxBool userLogin = false.obs; RxString userFace = ''.obs; - var userInfo; + UserInfoData? userInfo; Box setting = GStorage.setting; late final StreamController searchBarStream = StreamController.broadcast(); @@ -33,7 +34,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { super.onInit(); userInfo = userInfoCache.get('userInfoCache'); userLogin.value = userInfo != null; - userFace.value = userInfo != null ? userInfo.face : ''; + userFace.value = userInfo != null ? userInfo!.face! : ''; hideSearchBar = setting.get(SettingBoxKey.hideSearchBar, defaultValue: false); if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) { @@ -62,7 +63,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin { userInfo = await userInfoCache.get('userInfoCache'); userLogin.value = val ?? false; if (val) return; - userFace.value = userInfo != null ? userInfo.face : ''; + userFace.value = userInfo != null ? userInfo!.face! : ''; } void setTabConfig() async { diff --git a/lib/pages/home/widgets/app_bar.dart b/lib/pages/home/widgets/app_bar.dart index 8715a513..4f15cb30 100644 --- a/lib/pages/home/widgets/app_bar.dart +++ b/lib/pages/home/widgets/app_bar.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; Box userInfoCache = GStorage.userInfo; @@ -12,7 +13,7 @@ class HomeAppBar extends StatelessWidget { @override Widget build(BuildContext context) { - var userInfo = userInfoCache.get('userInfoCache'); + final UserInfoData? userInfo = userInfoCache.get('userInfoCache'); return SliverAppBar( // forceElevated: true, scrolledUnderElevation: 0, diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index 3a3cc9eb..b89fe403 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/http/common.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; import '../../models/common/dynamic_badge_mode.dart'; @@ -26,7 +27,7 @@ class MainController extends GetxController { late PageController pageController; int selectedIndex = 0; Box userInfoCache = GStorage.userInfo; - dynamic userInfo; + UserInfoData? userInfo; RxBool userLogin = false.obs; late Rx dynamicBadgeType = DynamicBadgeMode.number.obs; late bool enableGradientBg; @@ -85,7 +86,7 @@ class MainController extends GetxController { } if (mineItemIndex != -1 && userInfo != null) { Widget avatar = NetworkImgLayer( - width: 28, height: 28, src: userInfo.face, type: 'avatar'); + width: 28, height: 28, src: userInfo!.face, type: 'avatar'); navigationBars[mineItemIndex]['icon'] = avatar; navigationBars[mineItemIndex]['selectIcon'] = avatar; } diff --git a/lib/pages/member/controller.dart b/lib/pages/member/controller.dart index 6e66b5ed..3c63d560 100644 --- a/lib/pages/member/controller.dart +++ b/lib/pages/member/controller.dart @@ -9,6 +9,7 @@ import 'package:pilipala/models/member/archive.dart'; import 'package:pilipala/models/member/coin.dart'; import 'package:pilipala/models/member/info.dart'; import 'package:pilipala/models/member/like.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:share_plus/share_plus.dart'; @@ -22,7 +23,7 @@ class MemberController extends GetxController { late int ownerMid; // 投稿列表 RxList? archiveList = [].obs; - dynamic userInfo; + UserInfoData? userInfo; RxInt attribute = (-1).obs; RxString attributeText = '关注'.obs; RxList recentCoinsList = [].obs; @@ -34,7 +35,7 @@ class MemberController extends GetxController { super.onInit(); mid = int.tryParse(Get.parameters['mid']!) ?? -2; userInfo = userInfoCache.get('userInfoCache'); - ownerMid = userInfo != null ? userInfo.mid : -1; + ownerMid = userInfo != null ? userInfo!.mid! : -1; isOwner.value = mid == ownerMid; face.value = Get.arguments['face'] ?? ''; heroTag = Get.arguments['heroTag'] ?? ''; diff --git a/lib/pages/mine_edit/controller.dart b/lib/pages/mine_edit/controller.dart index 148aaccc..79e1e32a 100644 --- a/lib/pages/mine_edit/controller.dart +++ b/lib/pages/mine_edit/controller.dart @@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/user.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; class MineEditController extends GetxController { @@ -13,7 +14,7 @@ class MineEditController extends GetxController { final TextEditingController signCtr = TextEditingController(); final TextEditingController birthdayCtr = TextEditingController(); String? sex; - dynamic userInfo; + UserInfoData? userInfo; @override void onInit() { diff --git a/lib/pages/setting/controller.dart b/lib/pages/setting/controller.dart index ca027832..459a36a2 100644 --- a/lib/pages/setting/controller.dart +++ b/lib/pages/setting/controller.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; -import 'package:pilipala/http/init.dart'; import 'package:pilipala/models/common/theme_type.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/login.dart'; import 'package:pilipala/utils/storage.dart'; @@ -22,7 +22,7 @@ class SettingController extends GetxController { RxDouble toastOpacity = (1.0).obs; RxInt picQuality = 10.obs; Rx themeType = ThemeType.system.obs; - var userInfo; + UserInfoData? userInfo; Rx dynamicBadgeType = DynamicBadgeMode.number.obs; RxInt defaultHomePage = 0.obs; diff --git a/lib/pages/setting/privacy_setting.dart b/lib/pages/setting/privacy_setting.dart index 9b7f5f6e..3b70e86c 100644 --- a/lib/pages/setting/privacy_setting.dart +++ b/lib/pages/setting/privacy_setting.dart @@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/member.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; class PrivacySetting extends StatefulWidget { @@ -15,7 +16,7 @@ class PrivacySetting extends StatefulWidget { class _PrivacySettingState extends State { bool userLogin = false; Box userInfoCache = GStorage.userInfo; - var userInfo; + UserInfoData? userInfo; @override void initState() { diff --git a/lib/pages/setting/recommend_setting.dart b/lib/pages/setting/recommend_setting.dart index 16d60d25..89e670c8 100644 --- a/lib/pages/setting/recommend_setting.dart +++ b/lib/pages/setting/recommend_setting.dart @@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/member.dart'; import 'package:pilipala/models/common/rcmd_type.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/pages/setting/widgets/select_dialog.dart'; import 'package:pilipala/utils/recommend_filter.dart'; import 'package:pilipala/utils/storage.dart'; @@ -21,7 +22,7 @@ class _RecommendSettingState extends State { static Box localCache = GStorage.localCache; late dynamic defaultRcmdType; Box userInfoCache = GStorage.userInfo; - late dynamic userInfo; + UserInfoData? userInfo; bool userLogin = false; late dynamic accessKeyInfo; // late int filterUnfollowedRatio; diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 0f66ad02..da3b0cbc 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -14,6 +14,7 @@ import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/models/sponsor_block/segment.dart'; import 'package:pilipala/models/sponsor_block/segment_type.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/video/later.dart'; import 'package:pilipala/models/video/play/quality.dart'; import 'package:pilipala/models/video/play/url.dart'; @@ -94,7 +95,7 @@ class VideoDetailController extends GetxController double? brightness; // 默认记录历史记录 bool enableHeart = true; - var userInfo; + UserInfoData? userInfo; late bool isFirstTime = true; Floating? floating; late PreferredSizeWidget headerControl; @@ -617,7 +618,7 @@ class VideoDetailController extends GetxController var count = argMap['count']; var res = await UserHttp.getMediaList( type: 2, - bizId: userInfo.mid, + bizId: userInfo!.mid!, ps: count, ); if (res['status']) { diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 5ddede96..24bd7db0 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -9,6 +9,7 @@ import 'package:pilipala/http/constants.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/user/fav_folder.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/video/ai.dart'; import 'package:pilipala/models/video/tags.dart'; import 'package:pilipala/models/video_detail_res.dart'; @@ -49,10 +50,8 @@ class VideoIntroController extends GetxController { List delMediaIdsNew = []; // 关注状态 默认未关注 RxMap followStatus = {}.obs; - int _tempThemeValue = -1; - RxInt lastPlayCid = 0.obs; - var userInfo; + UserInfoData? userInfo; RxList videoTags = [].obs; // 同时观看 @@ -301,7 +300,7 @@ class VideoIntroController extends GetxController { Future queryVideoInFolder() async { var result = await VideoHttp.videoInFolder( - mid: userInfo.mid, rid: IdUtils.bv2av(bvid)); + mid: userInfo!.mid!, rid: IdUtils.bv2av(bvid)); if (result['status']) { favFolderData.value = result['data']; } diff --git a/lib/pages/whisper_detail/controller.dart b/lib/pages/whisper_detail/controller.dart index 54d6a2c4..24a0f8c2 100644 --- a/lib/pages/whisper_detail/controller.dart +++ b/lib/pages/whisper_detail/controller.dart @@ -6,6 +6,7 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/msg.dart'; import 'package:pilipala/models/msg/session.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/pages/whisper/index.dart'; import '../../utils/feed_back.dart'; import '../../utils/storage.dart'; @@ -80,7 +81,7 @@ class WhisperDetailController extends GetxController { Future sendMsg() async { feedBack(); String message = replyContentController.text; - final userInfo = userInfoCache.get('userInfoCache'); + final UserInfoData? userInfo = userInfoCache.get('userInfoCache'); if (userInfo == null) { SmartDialog.showToast('请先登录'); return; @@ -90,7 +91,7 @@ class WhisperDetailController extends GetxController { return; } var result = await MsgHttp.sendMsg( - senderUid: userInfo.mid, + senderUid: userInfo.mid!, receiverId: int.parse(mid), content: {'content': message}, msgType: 1, diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index f79c241d..3c3d9f18 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -2,14 +2,12 @@ import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/models/video/reply/emote.dart'; import 'package:pilipala/pages/emote/index.dart'; import 'package:pilipala/pages/video/detail/reply_new/toolbar_icon_button.dart'; import 'package:pilipala/pages/whisper_detail/controller.dart'; import 'package:pilipala/utils/feed_back.dart'; -import '../../utils/storage.dart'; import 'widget/chat_item.dart'; class WhisperDetailPage extends StatefulWidget { @@ -30,7 +28,6 @@ class _WhisperDetailPageState extends State late double emoteHeight = 230.0; double keyboardHeight = 0.0; // 键盘高度 RxString toolbarType = ''.obs; - Box userInfoCache = GStorage.userInfo; @override void initState() { From 5c8a822c2fceff24af14a65fd5fe619b47c3db5a Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 22:33:53 +0800 Subject: [PATCH 06/18] opt: seasons layout --- lib/pages/member_seasons/controller.dart | 3 +- lib/pages/member_seasons/view.dart | 42 ++++++++++++++++++++---- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/lib/pages/member_seasons/controller.dart b/lib/pages/member_seasons/controller.dart index ef85398b..07532787 100644 --- a/lib/pages/member_seasons/controller.dart +++ b/lib/pages/member_seasons/controller.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/http/member.dart'; import 'package:pilipala/models/member/seasons.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; class MemberSeasonsController extends GetxController { final ScrollController scrollController = ScrollController(); @@ -58,7 +59,7 @@ class MemberSeasonsController extends GetxController { mid: mid, seriesId: seriesId!, pn: pn, - currentMid: 17340771, + currentMid: GlobalDataCache().userInfo?.mid ?? -1, ); if (res['status']) { seasonsList.addAll(res['data'].seriesList); diff --git a/lib/pages/member_seasons/view.dart b/lib/pages/member_seasons/view.dart index 689ddd34..6bda2278 100644 --- a/lib/pages/member_seasons/view.dart +++ b/lib/pages/member_seasons/view.dart @@ -2,6 +2,8 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; +import 'package:pilipala/common/skeleton/video_card_h.dart'; +import 'package:pilipala/common/widgets/http_error.dart'; import 'controller.dart'; import 'widgets/item.dart'; @@ -54,9 +56,9 @@ class _MemberSeasonsPageState extends State { builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.data != null) { - Map data = snapshot.data as Map; + Map? data = snapshot.data; List list = _memberSeasonsController.seasonsList; - if (data['status']) { + if (data?['status']) { return Obx( () => list.isNotEmpty ? LayoutBuilder( @@ -82,16 +84,44 @@ class _MemberSeasonsPageState extends State { ); }, ) - : const SizedBox(), + : const HttpError( + errMsg: '没有数据', + isInSliver: false, + isShowBtn: false, + ), ); } else { - return const SizedBox(); + return HttpError( + errMsg: snapshot.data['msg'], + isInSliver: false, + fn: () { + setState(() { + _futureBuilderFuture = + _memberSeasonsController.onRefresh(); + }); + }, + ); } } else { - return const SizedBox(); + return HttpError( + errMsg: snapshot.data['msg'] ?? '请求异常', + isInSliver: false, + fn: () { + setState(() { + _futureBuilderFuture = + _memberSeasonsController.onRefresh(); + }); + }, + ); } } else { - return const SizedBox(); + return ListView.builder( + itemCount: 10, + shrinkWrap: true, + itemBuilder: (context, index) { + return const VideoCardHSkeleton(); + }, + ); } }, ), From d6247fad98b4d743038fa164d2c1454f600a8880 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 17 Nov 2024 22:45:51 +0800 Subject: [PATCH 07/18] mod: verticalHeight calc --- lib/pages/video/detail/view.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 599ad07c..0fb97066 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -502,15 +502,16 @@ class _VideoDetailPageState extends State Widget build(BuildContext context) { final sizeContext = MediaQuery.sizeOf(context); final _context = MediaQuery.of(context); - late double defaultVideoHeight = sizeContext.width * 9 / 16; + late final double verticalHeight = sizeContext.width * 22 / 16; + late double defaultVideoHeight = vdCtr.videoDirection.value == 'vertical' + ? verticalHeight + : sizeContext.width * 9 / 16; late RxDouble videoHeight = defaultVideoHeight.obs; final double pinnedHeaderHeight = statusBarHeight + kToolbarHeight + videoHeight.value; - // ignore: no_leading_underscores_for_local_identifiers vdCtr.videoDirection.listen((p0) { if (p0 == 'vertical') { - defaultVideoHeight = sizeContext.width * 22 / 16; - videoHeight.value = sizeContext.width * 22 / 16; + videoHeight.value = defaultVideoHeight = verticalHeight; } }); From 16fa4677423b95dd829b087b6c0104c92afa6d87 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 19 Nov 2024 23:50:45 +0800 Subject: [PATCH 08/18] refactor: GlobalDataCache --- lib/common/widgets/network_img_layer.dart | 2 +- lib/http/member.dart | 8 +-- lib/main.dart | 2 +- lib/pages/dynamics/widgets/up_panel.dart | 2 +- lib/pages/main/view.dart | 2 +- lib/pages/member_archive/controller.dart | 5 +- lib/pages/member_article/controller.dart | 5 +- lib/pages/member_dynamics/controller.dart | 5 +- lib/pages/member_seasons/controller.dart | 2 +- lib/pages/search/controller.dart | 8 +-- lib/pages/setting/extra_setting.dart | 4 +- lib/pages/setting/pages/action_menu_set.dart | 2 +- lib/pages/setting/pages/play_gesture_set.dart | 4 +- lib/pages/setting/play_setting.dart | 2 +- lib/pages/setting/style_setting.dart | 2 +- lib/pages/video/detail/introduction/view.dart | 6 +-- .../detail/reply/widgets/reply_item.dart | 4 +- lib/pages/video/detail/widgets/ai_detail.dart | 2 +- lib/plugin/pl_player/controller.dart | 38 +++++++------- lib/plugin/pl_player/view.dart | 4 +- lib/utils/global_data_cache.dart | 52 +++++++++---------- lib/utils/login.dart | 2 +- 22 files changed, 79 insertions(+), 84 deletions(-) diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 4980e2fc..b7b5de7e 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -48,7 +48,7 @@ class NetworkImgLayer extends StatelessWidget { Widget build(BuildContext context) { int defaultImgQuality = 10; try { - defaultImgQuality = GlobalDataCache().imgQuality; + defaultImgQuality = GlobalDataCache.imgQuality; } catch (_) {} if (src == '' || src == null) { diff --git a/lib/http/member.dart b/lib/http/member.dart index 66d0ff47..107a9379 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -26,7 +26,7 @@ class MemberHttp { }) async { String? wWebid; if ((await getWWebid(mid: mid))['status']) { - wWebid = GlobalDataCache().wWebid; + wWebid = GlobalDataCache.wWebid; } Map params = await WbiSign().makSign({ @@ -574,7 +574,7 @@ class MemberHttp { } static Future getWWebid({required int mid}) async { - String? wWebid = GlobalDataCache().wWebid; + String? wWebid = GlobalDataCache.wWebid; if (wWebid != null) { return {'status': true, 'data': wWebid}; } @@ -588,7 +588,7 @@ class MemberHttp { final content = match.group(1); String decodedString = Uri.decodeComponent(content!); Map map = jsonDecode(decodedString); - GlobalDataCache().wWebid = map['access_id']; + GlobalDataCache.wWebid = map['access_id']; return {'status': true, 'data': map['access_id']}; } else { return {'status': false, 'data': '请检查登录状态'}; @@ -605,7 +605,7 @@ class MemberHttp { }) async { String? wWebid; if ((await getWWebid(mid: mid))['status']) { - wWebid = GlobalDataCache().wWebid; + wWebid = GlobalDataCache.wWebid; } Map params = await WbiSign().makSign({ 'host_mid': mid, diff --git a/lib/main.dart b/lib/main.dart index 1ec86c8e..5a163f49 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -65,7 +65,7 @@ void main() async { } PiliSchame.init(); - await GlobalDataCache().initialize(); + await GlobalDataCache.initialize(); } class MyApp extends StatelessWidget { diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index d5d7958e..607b6af7 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -173,7 +173,7 @@ class _UpPanelState extends State { if (data.type == 'up') { EasyThrottle.throttle('follow', const Duration(milliseconds: 300), () { - if (GlobalDataCache().enableDynamicSwitch) { + if (GlobalDataCache.enableDynamicSwitch) { onClickUp(data, i); } else { onClickUpAni(data, i); diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 01fae4bf..1c4dbf62 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -125,7 +125,7 @@ class _MainAppState extends State with SingleTickerProviderStateMixin { double sheetHeight = MediaQuery.sizeOf(context).height - MediaQuery.of(context).padding.top - MediaQuery.sizeOf(context).width * 9 / 16; - GlobalDataCache().sheetHeight = sheetHeight; + GlobalDataCache.sheetHeight = sheetHeight; localCache.put('sheetHeight', sheetHeight); localCache.put('statusBarHeight', statusBarHeight); diff --git a/lib/pages/member_archive/controller.dart b/lib/pages/member_archive/controller.dart index 61816ed5..3fdcbedc 100644 --- a/lib/pages/member_archive/controller.dart +++ b/lib/pages/member_archive/controller.dart @@ -28,9 +28,8 @@ class MemberArchiveController extends GetxController { super.onInit(); mid = int.parse(Get.parameters['mid']!); currentOrder.value = orderList.first; - ownerMid = GlobalDataCache().userInfo != null - ? GlobalDataCache().userInfo!.mid! - : -1; + ownerMid = + GlobalDataCache.userInfo != null ? GlobalDataCache.userInfo!.mid! : -1; isOwner.value = mid == -1 || mid == ownerMid; } diff --git a/lib/pages/member_article/controller.dart b/lib/pages/member_article/controller.dart index 9c67f679..542fbc4f 100644 --- a/lib/pages/member_article/controller.dart +++ b/lib/pages/member_article/controller.dart @@ -20,9 +20,8 @@ class MemberArticleController extends GetxController { void onInit() { super.onInit(); mid = int.parse(Get.parameters['mid']!); - ownerMid = GlobalDataCache().userInfo != null - ? GlobalDataCache().userInfo!.mid! - : -1; + ownerMid = + GlobalDataCache.userInfo != null ? GlobalDataCache.userInfo!.mid! : -1; isOwner.value = mid == -1 || mid == ownerMid; } diff --git a/lib/pages/member_dynamics/controller.dart b/lib/pages/member_dynamics/controller.dart index 8fdf55b7..be5b2454 100644 --- a/lib/pages/member_dynamics/controller.dart +++ b/lib/pages/member_dynamics/controller.dart @@ -18,9 +18,8 @@ class MemberDynamicsController extends GetxController { void onInit() { super.onInit(); mid = int.parse(Get.parameters['mid']!); - ownerMid = GlobalDataCache().userInfo != null - ? GlobalDataCache().userInfo!.mid! - : -1; + ownerMid = + GlobalDataCache.userInfo != null ? GlobalDataCache.userInfo!.mid! : -1; isOwner.value = mid == -1 || mid == ownerMid; } diff --git a/lib/pages/member_seasons/controller.dart b/lib/pages/member_seasons/controller.dart index 07532787..e3f2c409 100644 --- a/lib/pages/member_seasons/controller.dart +++ b/lib/pages/member_seasons/controller.dart @@ -59,7 +59,7 @@ class MemberSeasonsController extends GetxController { mid: mid, seriesId: seriesId!, pn: pn, - currentMid: GlobalDataCache().userInfo?.mid ?? -1, + currentMid: GlobalDataCache.userInfo?.mid ?? -1, ); if (res['status']) { seasonsList.addAll(res['data'].seriesList); diff --git a/lib/pages/search/controller.dart b/lib/pages/search/controller.dart index 2da2acff..8d24f167 100644 --- a/lib/pages/search/controller.dart +++ b/lib/pages/search/controller.dart @@ -43,10 +43,10 @@ class SSearchController extends GetxController { hintText = hint; } } - historyCacheList = GlobalDataCache().historyCacheList; + historyCacheList = GlobalDataCache.historyCacheList; historyList.value = historyCacheList; enableHotKey = setting.get(SettingBoxKey.enableHotKey, defaultValue: true); - enableSearchSuggest = GlobalDataCache().enableSearchSuggest; + enableSearchSuggest = GlobalDataCache.enableSearchSuggest; } void onChange(value) { @@ -128,7 +128,7 @@ class SSearchController extends GetxController { historyCacheList = []; historyList.refresh(); localCache.put('cacheList', []); - GlobalDataCache().historyCacheList = []; + GlobalDataCache.historyCacheList = []; SmartDialog.showToast('搜索历史已清空'); } @@ -139,7 +139,7 @@ class SSearchController extends GetxController { historyList.value = historyCacheList; historyList.refresh(); localCache.put('cacheList', historyCacheList); - GlobalDataCache().historyCacheList = historyCacheList; + GlobalDataCache.historyCacheList = historyCacheList; searchFocusNode.unfocus(); } } diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index 07cd585a..fdc62f13 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -146,7 +146,7 @@ class _ExtraSettingState extends State { setKey: SettingBoxKey.enableSearchSuggest, defaultVal: true, callFn: (val) { - GlobalDataCache().enableSearchSuggest = val; + GlobalDataCache.enableSearchSuggest = val; }, ), SetSwitchItem( @@ -181,7 +181,7 @@ class _ExtraSettingState extends State { setKey: SettingBoxKey.enableAutoExpand, defaultVal: false, callFn: (val) { - GlobalDataCache().enableAutoExpand = val; + GlobalDataCache.enableAutoExpand = val; }, ), const SetSwitchItem( diff --git a/lib/pages/setting/pages/action_menu_set.dart b/lib/pages/setting/pages/action_menu_set.dart index cbbd0e84..3b211bae 100644 --- a/lib/pages/setting/pages/action_menu_set.dart +++ b/lib/pages/setting/pages/action_menu_set.dart @@ -38,7 +38,7 @@ class _ActionMenuSetPageState extends State { .map((i) => (i['value'] as ActionType).value) .toList(); setting.put(SettingBoxKey.actionTypeSort, sortedTabbar); - GlobalDataCache().actionTypeSort = sortedTabbar; + GlobalDataCache.actionTypeSort = sortedTabbar; SmartDialog.showToast('操作成功'); } diff --git a/lib/pages/setting/pages/play_gesture_set.dart b/lib/pages/setting/pages/play_gesture_set.dart index bad115a5..dc11cd6f 100644 --- a/lib/pages/setting/pages/play_gesture_set.dart +++ b/lib/pages/setting/pages/play_gesture_set.dart @@ -58,11 +58,11 @@ class _PlayGesturePageState extends State { }, ); if (result != null) { - GlobalDataCache().fullScreenGestureMode = FullScreenGestureMode + GlobalDataCache.fullScreenGestureMode = FullScreenGestureMode .values .firstWhere((element) => element.values == result); fullScreenGestureMode = - GlobalDataCache().fullScreenGestureMode.index; + GlobalDataCache.fullScreenGestureMode.index; setting.put( SettingBoxKey.fullScreenGestureMode, fullScreenGestureMode); SmartDialog.showToast('设置成功'); diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index e191d8fd..7090bfaf 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -155,7 +155,7 @@ class _PlaySettingState extends State { setKey: SettingBoxKey.enablePlayerControlAnimation, defaultVal: true, callFn: (bool val) { - GlobalDataCache().enablePlayerControlAnimation = val; + GlobalDataCache.enablePlayerControlAnimation = val; }), SetSwitchItem( title: '港澳台模式', diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 5b59397e..54b97ea5 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -175,7 +175,7 @@ class _StyleSettingState extends State { SettingBoxKey.defaultPicQa, picQuality); Get.back(); settingController.picQuality.value = picQuality; - GlobalDataCache().imgQuality = picQuality; + GlobalDataCache.imgQuality = picQuality; SmartDialog.showToast('设置成功'); }, child: const Text('确定'), diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 451173dd..417548d5 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -169,8 +169,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { owner = widget.videoDetail!.owner; enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true); - _expandableCtr = ExpandableController( - initialExpanded: GlobalDataCache().enableAutoExpand); + _expandableCtr = + ExpandableController(initialExpanded: GlobalDataCache.enableAutoExpand); } // 收藏 @@ -556,7 +556,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { } Widget actionGrid(BuildContext context, videoIntroController) { - final actionTypeSort = GlobalDataCache().actionTypeSort; + final actionTypeSort = GlobalDataCache.actionTypeSort; Map menuListWidgets = { 'like': Obx( diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 5d31858f..e0a6d07f 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -52,7 +52,7 @@ class ReplyItem extends StatelessWidget { @override Widget build(BuildContext context) { final bool isOwner = int.parse(replyItem!.member!.mid!) == - (GlobalDataCache().userInfo?.mid ?? -1); + (GlobalDataCache.userInfo?.mid ?? -1); return Material( child: InkWell( // 点击整个评论区 评论详情/回复 @@ -415,7 +415,7 @@ class ReplyItemRow extends StatelessWidget { onLongPress: () { feedBack(); final bool isOwner = int.parse(replyItem!.member!.mid!) == - (GlobalDataCache().userInfo?.mid ?? -1); + (GlobalDataCache.userInfo?.mid ?? -1); showModalBottomSheet( context: context, useRootNavigator: true, diff --git a/lib/pages/video/detail/widgets/ai_detail.dart b/lib/pages/video/detail/widgets/ai_detail.dart index 64327553..c17591fb 100644 --- a/lib/pages/video/detail/widgets/ai_detail.dart +++ b/lib/pages/video/detail/widgets/ai_detail.dart @@ -18,7 +18,7 @@ class AiDetail extends StatelessWidget { Widget build(BuildContext context) { return Container( padding: const EdgeInsets.only(left: 16, right: 16), - height: GlobalDataCache().sheetHeight, + height: GlobalDataCache.sheetHeight, child: Column( children: [ _buildHeader(context), diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index de4cd9df..b69d96bb 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -278,19 +278,18 @@ class PlPlayerController { // 添加一个私有构造函数 PlPlayerController._internal(this.videoType) { - final cache = GlobalDataCache(); - isOpenDanmu.value = cache.isOpenDanmu; - blockTypes = cache.blockTypes; - showArea = cache.showArea; - opacityVal = cache.opacityVal; - fontSizeVal = cache.fontSizeVal; - danmakuDurationVal = cache.danmakuDurationVal; - strokeWidth = cache.strokeWidth; - playRepeat = cache.playRepeat; - _playbackSpeed.value = cache.playbackSpeed; - enableAutoLongPressSpeed = cache.enableAutoLongPressSpeed; - _longPressSpeed.value = cache.longPressSpeed; - speedsList = cache.speedsList; + isOpenDanmu.value = GlobalDataCache.isOpenDanmu; + blockTypes = GlobalDataCache.blockTypes; + showArea = GlobalDataCache.showArea; + opacityVal = GlobalDataCache.opacityVal; + fontSizeVal = GlobalDataCache.fontSizeVal; + danmakuDurationVal = GlobalDataCache.danmakuDurationVal; + strokeWidth = GlobalDataCache.strokeWidth; + playRepeat = GlobalDataCache.playRepeat; + _playbackSpeed.value = GlobalDataCache.playbackSpeed; + enableAutoLongPressSpeed = GlobalDataCache.enableAutoLongPressSpeed; + _longPressSpeed.value = GlobalDataCache.longPressSpeed; + speedsList = GlobalDataCache.speedsList; // _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) { // if (status == PlayerStatus.playing) { // WakelockPlus.enable(); @@ -1047,13 +1046,12 @@ class PlPlayerController { /// 缓存本次弹幕选项 cacheDanmakuOption() { - final cache = GlobalDataCache(); - cache.blockTypes = blockTypes; - cache.showArea = showArea; - cache.opacityVal = opacityVal; - cache.fontSizeVal = fontSizeVal; - cache.danmakuDurationVal = danmakuDurationVal; - cache.strokeWidth = strokeWidth; + GlobalDataCache.blockTypes = blockTypes; + GlobalDataCache.showArea = showArea; + GlobalDataCache.opacityVal = opacityVal; + GlobalDataCache.fontSizeVal = fontSizeVal; + GlobalDataCache.danmakuDurationVal = danmakuDurationVal; + GlobalDataCache.strokeWidth = strokeWidth; localCache.put(LocalCacheKey.danmakuBlockType, blockTypes); localCache.put(LocalCacheKey.danmakuShowArea, showArea); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 990661bc..c73bc55f 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -89,7 +89,7 @@ class _PLVideoPlayerState extends State late bool enableBackgroundPlay; late double screenWidth; final FullScreenGestureMode fullScreenGestureMode = - GlobalDataCache().fullScreenGestureMode; + GlobalDataCache.fullScreenGestureMode; // 用于记录上一次全屏切换手势触发时间,避免误触 DateTime? lastFullScreenToggleTime; @@ -136,7 +136,7 @@ class _PLVideoPlayerState extends State screenWidth = Get.size.width; animationController = AnimationController( vsync: this, - duration: GlobalDataCache().enablePlayerControlAnimation + duration: GlobalDataCache.enablePlayerControlAnimation ? const Duration(milliseconds: 150) : const Duration(milliseconds: 10), ); diff --git a/lib/utils/global_data_cache.dart b/lib/utils/global_data_cache.dart index 3321c660..ea673859 100644 --- a/lib/utils/global_data_cache.dart +++ b/lib/utils/global_data_cache.dart @@ -11,48 +11,48 @@ Box videoStorage = GStorage.video; Box userInfoCache = GStorage.userInfo; class GlobalDataCache { - late int imgQuality; - late FullScreenGestureMode fullScreenGestureMode; - late bool enablePlayerControlAnimation; - late List actionTypeSort; - late double sheetHeight; - String? wWebid; + static late int imgQuality; + static late FullScreenGestureMode fullScreenGestureMode; + static late bool enablePlayerControlAnimation; + static late List actionTypeSort; + static late double sheetHeight; + static String? wWebid; /// 播放器相关 // 弹幕开关 - late bool isOpenDanmu; + static late bool isOpenDanmu; // 弹幕屏蔽类型 - late List blockTypes; + static late List blockTypes; // 弹幕展示区域 - late double showArea; + static late double showArea; // 弹幕透明度 - late double opacityVal; + static late double opacityVal; // 弹幕字体大小 - late double fontSizeVal; + static late double fontSizeVal; // 弹幕显示时间 - late double danmakuDurationVal; + static late double danmakuDurationVal; // 弹幕描边宽度 - late double strokeWidth; + static late double strokeWidth; // 播放器循环模式 - late PlayRepeat playRepeat; + static late PlayRepeat playRepeat; // 播放器默认播放速度 - late double playbackSpeed; + static late double playbackSpeed; // 播放器自动长按速度 - late bool enableAutoLongPressSpeed; + static late bool enableAutoLongPressSpeed; // 播放器长按速度 - late double longPressSpeed; + static late double longPressSpeed; // 播放器速度列表 - late List speedsList; + static late List speedsList; // 用户信息 - UserInfoData? userInfo; + static UserInfoData? userInfo; // 搜索历史 - late List historyCacheList; - // - late bool enableSearchSuggest = true; + static late List historyCacheList; + // 搜索建议 + static late bool enableSearchSuggest; // 简介默认展开 - late bool enableAutoExpand = false; - // - late bool enableDynamicSwitch = true; + static late bool enableAutoExpand; + // 动态切换 + static late bool enableDynamicSwitch; // 私有构造函数 GlobalDataCache._(); @@ -64,7 +64,7 @@ class GlobalDataCache { factory GlobalDataCache() => _instance; // 异步初始化方法 - Future initialize() async { + static Future initialize() async { imgQuality = await setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10); // 设置全局变量 fullScreenGestureMode = FullScreenGestureMode.values[setting.get( diff --git a/lib/utils/login.dart b/lib/utils/login.dart index 9dde1cb1..159de81d 100644 --- a/lib/utils/login.dart +++ b/lib/utils/login.dart @@ -118,7 +118,7 @@ class LoginUtils { Request.dio.options.headers['cookie'] = ''; userInfoCache.put('userInfoCache', null); localCache.put(LocalCacheKey.accessKey, {'mid': -1, 'value': ''}); - GlobalDataCache().userInfo = null; + GlobalDataCache.userInfo = null; await refreshLoginStatus(false); } } From 65bb5d7e3d762f8700101e4546f6d3058ec66b34 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 20 Nov 2024 00:02:12 +0800 Subject: [PATCH 09/18] refactor: buvidActivate call --- lib/http/common.dart | 44 ++++++++++++++++++++++++++++++++++++++++++++ lib/http/init.dart | 34 ---------------------------------- lib/main.dart | 2 ++ 3 files changed, 46 insertions(+), 34 deletions(-) diff --git a/lib/http/common.dart b/lib/http/common.dart index 2f5f0e84..9644d142 100644 --- a/lib/http/common.dart +++ b/lib/http/common.dart @@ -1,8 +1,14 @@ +import 'dart:convert'; +import 'dart:math'; +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; import 'package:pilipala/models/sponsor_block/segment.dart'; import 'index.dart'; class CommonHttp { + static final RegExp spmPrefixExp = + RegExp(r''); static Future unReadDynamic() async { var res = await Request().get(Api.getUnreadDynamic, data: {'alltype_offset': 0, 'video_offset': '', 'article_offset': 0}); @@ -43,4 +49,42 @@ class CommonHttp { }; } } + + static Future buvidActivate() async { + try { + // 获取 HTML 数据 + var html = await Request().get(Api.dynamicSpmPrefix); + + // 提取 spmPrefix + String spmPrefix = spmPrefixExp.firstMatch(html.data)?.group(1) ?? ''; + + // 生成随机 PNG 结束部分 + Random rand = Random(); + String randPngEnd = base64.encode( + List.generate(32, (_) => rand.nextInt(256)) + ..addAll(List.filled(4, 0)) + ..addAll([73, 69, 78, 68]) + ..addAll(List.generate(4, (_) => rand.nextInt(256))), + ); + + // 构建 JSON 数据 + String jsonData = json.encode({ + '3064': 1, + '39c8': '$spmPrefix.fp.risk', + '3c43': { + 'adca': 'Linux', + 'bfe9': randPngEnd.substring(randPngEnd.length - 50), + }, + }); + + // 发送 POST 请求 + await Request().post( + Api.activateBuvidApi, + data: {'payload': jsonData}, + options: Options(contentType: 'application/json'), + ); + } catch (err) { + debugPrint('buvidActivate error: $err'); + } + } } diff --git a/lib/http/init.dart b/lib/http/init.dart index 8a11034c..03de43b7 100644 --- a/lib/http/init.dart +++ b/lib/http/init.dart @@ -1,9 +1,7 @@ // ignore_for_file: avoid_print import 'dart:async'; -import 'dart:convert'; import 'dart:developer'; import 'dart:io'; -import 'dart:math' show Random; import 'package:cookie_jar/cookie_jar.dart'; import 'package:dio/dio.dart'; import 'package:dio/io.dart'; @@ -13,7 +11,6 @@ import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/id_utils.dart'; import '../utils/storage.dart'; import '../utils/utils.dart'; -import 'api.dart'; import 'constants.dart'; import 'interceptor.dart'; @@ -27,8 +24,6 @@ class Request { late bool enableSystemProxy; late String systemProxyHost; late String systemProxyPort; - static final RegExp spmPrefixExp = - RegExp(r''); static String? buvid; /// 设置cookie @@ -62,11 +57,6 @@ class Request { baseUrlType = 'bangumi'; } setBaseUrl(type: baseUrlType); - try { - await buvidActivate(); - } catch (e) { - log("setCookie, ${e.toString()}"); - } final String cookieString = cookie .map((Cookie cookie) => '${cookie.name}=${cookie.value}') @@ -122,30 +112,6 @@ class Request { dio.options.headers['referer'] = 'https://www.bilibili.com/'; } - static Future buvidActivate() async { - var html = await Request().get(Api.dynamicSpmPrefix); - String spmPrefix = spmPrefixExp.firstMatch(html.data)!.group(1)!; - Random rand = Random(); - String rand_png_end = base64.encode( - List.generate(32, (_) => rand.nextInt(256)) + - List.filled(4, 0) + - [73, 69, 78, 68] + - List.generate(4, (_) => rand.nextInt(256))); - - String jsonData = json.encode({ - '3064': 1, - '39c8': '${spmPrefix}.fp.risk', - '3c43': { - 'adca': 'Linux', - 'bfe9': rand_png_end.substring(rand_png_end.length - 50), - }, - }); - - await Request().post(Api.activateBuvidApi, - data: {'payload': jsonData}, - options: Options(contentType: 'application/json')); - } - /* * config it and create */ diff --git a/lib/main.dart b/lib/main.dart index 1ec86c8e..fcb29fad 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/custom_toast.dart'; +import 'package:pilipala/http/common.dart'; import 'package:pilipala/http/init.dart'; import 'package:pilipala/models/common/color_type.dart'; import 'package:pilipala/models/common/theme_type.dart'; @@ -66,6 +67,7 @@ void main() async { PiliSchame.init(); await GlobalDataCache().initialize(); + CommonHttp.buvidActivate(); } class MyApp extends StatelessWidget { From 121d32e40324d2f178493c07d0213f68bb02f5b8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 20 Nov 2024 09:50:34 +0800 Subject: [PATCH 10/18] mod: reply appbar title spacing --- lib/pages/video/detail/reply_reply/view.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index c697349d..cf72c3a4 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -89,9 +89,12 @@ class _VideoReplyReplyPanelState extends State { return AppBar( toolbarHeight: 45, automaticallyImplyLeading: false, - title: Text( - '评论详情', - style: Theme.of(context).textTheme.titleSmall, + title: Padding( + padding: const EdgeInsets.only(left: 14), + child: Text( + '评论详情', + style: Theme.of(context).textTheme.titleSmall, + ), ), actions: [ IconButton( @@ -102,7 +105,7 @@ class _VideoReplyReplyPanelState extends State { Navigator.pop(context); }, ), - const SizedBox(width: 14), + const SizedBox(width: 12), ], ); } From 1ac152bb49ed159cd7366a20f23227accd882a75 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 20 Nov 2024 22:45:25 +0800 Subject: [PATCH 11/18] feat: dlna switch --- lib/pages/setting/extra_setting.dart | 6 ++++ .../video/detail/widgets/header_control.dart | 33 ++++++++++--------- lib/utils/global_data_cache.dart | 3 ++ lib/utils/storage.dart | 3 +- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index fdc62f13..3e82f2bd 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -190,6 +190,12 @@ class _ExtraSettingState extends State { setKey: SettingBoxKey.enableRelatedVideo, defaultVal: true, ), + const SetSwitchItem( + title: '视频投屏开关', + subTitle: '打开后将在播放器右上角显示投屏入口', + setKey: SettingBoxKey.enableDlna, + defaultVal: false, + ), ListTile( dense: false, title: Text('评论展示', style: titleStyle), diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index f22bf846..bc9167d5 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -16,6 +16,7 @@ import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/introduction/widgets/menu_row.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/plugin/pl_player/models/play_repeat.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/services/shutdown_timer_service.dart'; import '../../../../http/danmaku.dart'; @@ -1237,22 +1238,24 @@ class _HeaderControlState extends State { // ), // fuc: () => _.screenshot(), // ), - ComBtn( - icon: const Icon( - Icons.cast, - size: 19, - color: Colors.white, + if (GlobalDataCache.enableDlna) ...[ + ComBtn( + icon: const Icon( + Icons.cast, + size: 19, + color: Colors.white, + ), + fuc: () async { + showDialog( + context: context, + builder: (BuildContext context) { + return LiveDlnaPage( + datasource: widget.videoDetailCtr!.videoUrl); + }, + ); + }, ), - fuc: () async { - showDialog( - context: context, - builder: (BuildContext context) { - return LiveDlnaPage( - datasource: widget.videoDetailCtr!.videoUrl); - }, - ); - }, - ), + ], if (isFullScreen.value) ...[ SizedBox( width: 56, diff --git a/lib/utils/global_data_cache.dart b/lib/utils/global_data_cache.dart index ea673859..a421f829 100644 --- a/lib/utils/global_data_cache.dart +++ b/lib/utils/global_data_cache.dart @@ -53,6 +53,8 @@ class GlobalDataCache { static late bool enableAutoExpand; // 动态切换 static late bool enableDynamicSwitch; + // 投屏开关 + static bool enableDlna = false; // 私有构造函数 GlobalDataCache._(); @@ -120,5 +122,6 @@ class GlobalDataCache { setting.get(SettingBoxKey.enableAutoExpand, defaultValue: false); enableDynamicSwitch = setting.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true); + enableDlna = setting.get(SettingBoxKey.enableDlna, defaultValue: false); } } diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index a5b36768..49a5c734 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -115,7 +115,8 @@ class SettingBoxKey { enableAi = 'enableAi', enableAutoExpand = 'enableAutoExpand', defaultHomePage = 'defaultHomePage', - enableRelatedVideo = 'enableRelatedVideo'; + enableRelatedVideo = 'enableRelatedVideo', + enableDlna = 'enableDlna'; /// 外观 static const String themeMode = 'themeMode', From 14640f338ca4068f29214ea707c362083a775428 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 21 Nov 2024 23:43:55 +0800 Subject: [PATCH 12/18] opt: hide live users by default --- lib/pages/dynamics/widgets/up_panel.dart | 239 +++++++++++++++-------- 1 file changed, 156 insertions(+), 83 deletions(-) diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index d5d7958e..35dc5cd8 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -34,6 +34,7 @@ class _UpPanelState extends State { List liveList = []; static const itemPadding = EdgeInsets.symmetric(horizontal: 5, vertical: 0); late MyInfo userInfo; + RxBool showLiveUser = false.obs; void listFormat() { userInfo = widget.upData.myInfo!; @@ -131,21 +132,70 @@ class _UpPanelState extends State { children: [ const SizedBox(width: 10), if (liveList.isNotEmpty) ...[ - for (int i = 0; i < liveList.length; i++) ...[ - upItemBuild(liveList[i], i) - ], - VerticalDivider( - indent: 20, - endIndent: 40, - width: 26, - color: Theme.of(context) - .colorScheme - .primary - .withOpacity(0.5), + Obx( + () => AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: (Widget child, + Animation animation) { + return FadeTransition( + opacity: animation, child: child); + }, + child: showLiveUser.value + ? Row( + key: ValueKey(showLiveUser.value), + children: [ + for (int i = 0; + i < liveList.length; + i++) + UpItemWidget( + data: liveList[i], + index: i, + currentMid: currentMid, + onClickUp: onClickUp, + onClickUpAni: onClickUpAni, + itemPadding: itemPadding, + contentWidth: contentWidth, + ) + ], + ) + : SizedBox.shrink( + key: ValueKey(showLiveUser.value), + ), + ), + ), + Obx( + () => IconButton( + onPressed: () { + showLiveUser.value = !showLiveUser.value; + }, + icon: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: (Widget child, + Animation animation) { + return ScaleTransition( + scale: animation, child: child); + }, + child: Icon( + !showLiveUser.value + ? Icons.arrow_forward_ios_rounded + : Icons.arrow_back_ios_rounded, + key: ValueKey(showLiveUser.value), + size: 18, + ), + ), + ), ), ], for (int i = 0; i < upList.length; i++) ...[ - upItemBuild(upList[i], i) + UpItemWidget( + data: upList[i], + index: i, + currentMid: currentMid, + onClickUp: onClickUp, + onClickUpAni: onClickUpAni, + itemPadding: itemPadding, + contentWidth: contentWidth, + ) ], const SizedBox(width: 10), ], @@ -165,8 +215,93 @@ class _UpPanelState extends State { )), ); } +} - Widget upItemBuild(data, i) { +class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate { + _SliverHeaderDelegate({required this.height, required this.child}); + + final double height; + final Widget child; + + @override + Widget build( + BuildContext context, double shrinkOffset, bool overlapsContent) { + return child; + } + + @override + double get maxExtent => height; + + @override + double get minExtent => height; + + @override + bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => + true; +} + +class UpPanelSkeleton extends StatelessWidget { + const UpPanelSkeleton({super.key}); + + @override + Widget build(BuildContext context) { + return ListView.builder( + scrollDirection: Axis.horizontal, + physics: const NeverScrollableScrollPhysics(), + itemCount: 10, + itemBuilder: ((context, index) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.onInverseSurface, + borderRadius: BorderRadius.circular(50), + ), + ), + Container( + margin: const EdgeInsets.only(top: 6), + width: 45, + height: 12, + color: Theme.of(context).colorScheme.onInverseSurface, + ), + ], + ), + ); + }), + ); + } +} + +class UpItemWidget extends StatelessWidget { + final dynamic data; + final int index; + final RxInt currentMid; + final Function(dynamic, int) onClickUp; + final Function(dynamic, int) onClickUpAni; + // final Function() feedBack; + final EdgeInsets itemPadding; + final double contentWidth; + + const UpItemWidget({ + Key? key, + required this.data, + required this.index, + required this.currentMid, + required this.onClickUp, + required this.onClickUpAni, + // required this.feedBack, + required this.itemPadding, + required this.contentWidth, + }) : super(key: key); + + @override + Widget build(BuildContext context) { return InkWell( onTap: () { feedBack(); @@ -174,9 +309,9 @@ class _UpPanelState extends State { EasyThrottle.throttle('follow', const Duration(milliseconds: 300), () { if (GlobalDataCache().enableDynamicSwitch) { - onClickUp(data, i); + onClickUp(data, index); } else { - onClickUpAni(data, i); + onClickUpAni(data, index); } }); } else if (data.type == 'live') { @@ -251,13 +386,12 @@ class _UpPanelState extends State { softWrap: false, textAlign: TextAlign.center, style: TextStyle( - color: currentMid.value == data.mid - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context) - .textTheme - .labelMedium! - .fontSize), + color: currentMid.value == data.mid + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + ), ), ), ), @@ -269,64 +403,3 @@ class _UpPanelState extends State { ); } } - -class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate { - _SliverHeaderDelegate({required this.height, required this.child}); - - final double height; - final Widget child; - - @override - Widget build( - BuildContext context, double shrinkOffset, bool overlapsContent) { - return child; - } - - @override - double get maxExtent => height; - - @override - double get minExtent => height; - - @override - bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => - true; -} - -class UpPanelSkeleton extends StatelessWidget { - const UpPanelSkeleton({super.key}); - - @override - Widget build(BuildContext context) { - return ListView.builder( - scrollDirection: Axis.horizontal, - physics: const NeverScrollableScrollPhysics(), - itemCount: 10, - itemBuilder: ((context, index) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 0), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 50, - height: 50, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, - borderRadius: BorderRadius.circular(50), - ), - ), - Container( - margin: const EdgeInsets.only(top: 6), - width: 45, - height: 12, - color: Theme.of(context).colorScheme.onInverseSurface, - ), - ], - ), - ); - }), - ); - } -} From b824b75bc64f5b45a784965a99424282c3b69bc9 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 23 Nov 2024 00:01:16 +0800 Subject: [PATCH 13/18] opt: enableDlna switch callFn --- lib/pages/setting/extra_setting.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index 3e82f2bd..004f3e9c 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -190,11 +190,14 @@ class _ExtraSettingState extends State { setKey: SettingBoxKey.enableRelatedVideo, defaultVal: true, ), - const SetSwitchItem( + SetSwitchItem( title: '视频投屏开关', subTitle: '打开后将在播放器右上角显示投屏入口', setKey: SettingBoxKey.enableDlna, defaultVal: false, + callFn: (bool val) { + GlobalDataCache.enableDlna = val; + }, ), ListTile( dense: false, From e1c7a74e1be2226527f5b1eafd7ffec07a59ed88 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 23 Nov 2024 01:15:32 +0800 Subject: [PATCH 14/18] feat: SponsorBlock switch --- lib/pages/setting/extra_setting.dart | 9 +++++++++ lib/pages/video/detail/controller.dart | 3 ++- lib/utils/global_data_cache.dart | 4 ++++ lib/utils/storage.dart | 3 ++- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index 004f3e9c..f4b56508 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -199,6 +199,15 @@ class _ExtraSettingState extends State { GlobalDataCache.enableDlna = val; }, ), + SetSwitchItem( + title: 'Sponsor Block', + subTitle: '自动跳过视频中赞助片段', + setKey: SettingBoxKey.enableSponsorBlock, + defaultVal: false, + callFn: (bool val) { + GlobalDataCache.enableSponsorBlock = val; + }, + ), ListTile( dense: false, title: Text('评论展示', style: titleStyle), diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index da3b0cbc..cb2e324c 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -21,6 +21,7 @@ import 'package:pilipala/models/video/play/url.dart'; import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/video/detail/reply_reply/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/video_utils.dart'; @@ -198,7 +199,7 @@ class VideoDetailController extends GetxController }); /// 仅投稿视频skip - if (videoType == SearchType.video) { + if (videoType == SearchType.video && GlobalDataCache.enableSponsorBlock) { querySkipSegments(); } } diff --git a/lib/utils/global_data_cache.dart b/lib/utils/global_data_cache.dart index a421f829..90b42795 100644 --- a/lib/utils/global_data_cache.dart +++ b/lib/utils/global_data_cache.dart @@ -55,6 +55,8 @@ class GlobalDataCache { static late bool enableDynamicSwitch; // 投屏开关 static bool enableDlna = false; + // sponsorBlock开关 + static bool enableSponsorBlock = false; // 私有构造函数 GlobalDataCache._(); @@ -123,5 +125,7 @@ class GlobalDataCache { enableDynamicSwitch = setting.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true); enableDlna = setting.get(SettingBoxKey.enableDlna, defaultValue: false); + enableSponsorBlock = + setting.get(SettingBoxKey.enableSponsorBlock, defaultValue: false); } } diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 49a5c734..9133314c 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -116,7 +116,8 @@ class SettingBoxKey { enableAutoExpand = 'enableAutoExpand', defaultHomePage = 'defaultHomePage', enableRelatedVideo = 'enableRelatedVideo', - enableDlna = 'enableDlna'; + enableDlna = 'enableDlna', + enableSponsorBlock = 'enableSponsorBlock'; /// 外观 static const String themeMode = 'themeMode', From 2db409b44909f2ce06a485248846e8ba67f12071 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 23 Nov 2024 15:15:58 +0800 Subject: [PATCH 15/18] opt: video intro skeleton --- lib/common/skeleton/video_intro.dart | 126 ++++++++++++++++++ lib/pages/video/detail/introduction/view.dart | 25 +--- 2 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 lib/common/skeleton/video_intro.dart diff --git a/lib/common/skeleton/video_intro.dart b/lib/common/skeleton/video_intro.dart new file mode 100644 index 00000000..b7a5ec74 --- /dev/null +++ b/lib/common/skeleton/video_intro.dart @@ -0,0 +1,126 @@ +import 'package:flutter/material.dart'; +import '../constants.dart'; +import 'skeleton.dart'; + +class VideoIntroSkeleton extends StatelessWidget { + const VideoIntroSkeleton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + Color bgColor = Theme.of(context).colorScheme.onInverseSurface; + return Skeleton( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 18), + Container( + width: double.infinity, + height: 20, + margin: const EdgeInsets.only(bottom: 6), + color: bgColor, + ), + Container( + width: 220, + height: 20, + margin: const EdgeInsets.only(bottom: 12), + color: bgColor, + ), + Row( + children: [ + Container( + width: 45, + height: 14, + color: bgColor, + ), + const SizedBox(width: 8), + Container( + width: 45, + height: 14, + color: bgColor, + ), + const SizedBox(width: 8), + Container( + width: 45, + height: 14, + color: bgColor, + ), + const Spacer(), + Container( + width: 35, + height: 14, + color: bgColor, + ), + const SizedBox(width: 4), + ], + ), + const SizedBox(height: 30), + LayoutBuilder(builder: (context, constraints) { + // 并列5个正方形 + double width = (constraints.maxWidth - 30) / 5; + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: List.generate(5, (index) { + return Container( + width: width - 24, + height: width - 24, + decoration: BoxDecoration( + color: bgColor, + borderRadius: BorderRadius.circular(16), + ), + ); + }), + ); + }), + const SizedBox(height: 20), + Container( + width: double.infinity, + height: 30, + margin: const EdgeInsets.symmetric(horizontal: 6), + decoration: BoxDecoration( + color: bgColor, + borderRadius: BorderRadius.circular(8), + ), + ), + const SizedBox(height: 20), + Row( + children: [ + ClipOval( + child: Container( + width: 44, + height: 44, + color: bgColor, + ), + ), + const SizedBox(width: 12), + Container( + width: 50, + height: 14, + color: bgColor, + ), + const SizedBox(width: 8), + Container( + width: 35, + height: 14, + color: bgColor, + ), + const Spacer(), + Container( + width: 55, + height: 30, + decoration: BoxDecoration( + color: bgColor, + borderRadius: BorderRadius.circular(16), + ), + ), + const SizedBox(width: 2) + ], + ), + const SizedBox(height: 10), + ], + ), + ), + ); + } +} diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 451173dd..d283d086 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -6,8 +6,8 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; -import 'package:lottie/lottie.dart'; import 'package:pilipala/common/constants.dart'; +import 'package:pilipala/common/skeleton/video_intro.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; @@ -76,10 +76,8 @@ class _VideoIntroPanelState extends State future: _futureBuilderFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.data == null) { - return const SliverToBoxAdapter(child: SizedBox()); - } - if (snapshot.data['status']) { + Map? data = snapshot.data; + if (data != null && data['status']) { // 请求成功 return Obx( () => VideoInfo( @@ -91,25 +89,16 @@ class _VideoIntroPanelState extends State } else { // 请求错误 return HttpError( - errMsg: snapshot.data['msg'], - btnText: snapshot.data['code'] == -404 || - snapshot.data['code'] == 62002 + errMsg: data?['msg'] ?? '请求异常', + btnText: (data?['code'] == -404 || data?['code'] == 62002) ? '返回上一页' : null, fn: () => Get.back(), ); } } else { - return SliverToBoxAdapter( - child: SizedBox( - height: 100, - child: Center( - child: Lottie.asset( - 'assets/loading.json', - width: 200, - ), - ), - ), + return const SliverToBoxAdapter( + child: VideoIntroSkeleton(), ); } }, From 79cd211976e05bc027e1951e71af632e2cedc110 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 23 Nov 2024 15:28:26 +0800 Subject: [PATCH 16/18] feat: back home when autoplay is off --- lib/pages/video/detail/view.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 0fb97066..488ed14d 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -909,6 +909,21 @@ class _VideoDetailPageState extends State icon: const Icon(FontAwesomeIcons.arrowLeft, size: 15), fuc: () => Get.back(), ), + const SizedBox(width: 8), + ComBtn( + icon: const Icon( + FontAwesomeIcons.house, + size: 15, + color: Colors.white, + ), + fuc: () async { + await vdCtr.plPlayerController.dispose(type: 'all'); + if (mounted) { + Navigator.popUntil( + context, (Route route) => route.isFirst); + } + }, + ), const Spacer(), ComBtn( icon: const Icon(Icons.history_outlined, size: 22), From e8166c9f829e9887fef01680ebbea0f90eaf8f16 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 23 Nov 2024 22:48:09 +0800 Subject: [PATCH 17/18] opt: toggle showSubtitleBtn --- lib/pages/video/detail/controller.dart | 9 +++++++++ lib/pages/video/detail/widgets/header_control.dart | 6 +++--- lib/plugin/pl_player/controller.dart | 5 +++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index da3b0cbc..ca5a73be 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -480,6 +480,15 @@ class VideoDetailController extends GetxController getDanmaku(subtitles); } } + headerControl = HeaderControl( + controller: plPlayerController, + videoDetailCtr: this, + floating: floating, + bvid: bvid, + videoType: videoType, + showSubtitleBtn: result['status'] && result['data'].subtitles.isNotEmpty, + ); + plPlayerController.setHeaderControl(headerControl); } // 获取弹幕 diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index f22bf846..d563396d 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -30,7 +30,7 @@ class HeaderControl extends StatefulWidget implements PreferredSizeWidget { this.floating, this.bvid, this.videoType, - this.showSubtitleBtn, + this.showSubtitleBtn = true, super.key, }); final PlPlayerController? controller; @@ -38,7 +38,7 @@ class HeaderControl extends StatefulWidget implements PreferredSizeWidget { final Floating? floating; final String? bvid; final SearchType? videoType; - final bool? showSubtitleBtn; + final bool showSubtitleBtn; @override State createState() => _HeaderControlState(); @@ -1326,7 +1326,7 @@ class _HeaderControlState extends State { ], /// 字幕 - if (widget.showSubtitleBtn ?? true) + if (widget.showSubtitleBtn) ComBtn( icon: const Icon( Icons.closed_caption_off, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index de4cd9df..d1305aa7 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -929,6 +929,11 @@ class PlPlayerController { showControls.value = !val; } + /// 设置/更新顶部控制栏 + void setHeaderControl(PreferredSizeWidget? widget) { + headerControl = widget; + } + void toggleFullScreen(bool val) { _isFullScreen.value = val; } From e1948b159b0b6e129d993c1093f639d5a53cf7a4 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 24 Nov 2024 01:16:33 +0800 Subject: [PATCH 18/18] feat: comment can be closed --- lib/models/common/comment_range_type.dart | 18 ++++ lib/pages/setting/extra_setting.dart | 83 ++++++++++++++++++- lib/pages/video/detail/controller.dart | 13 ++- .../video/detail/introduction/controller.dart | 17 ++-- lib/pages/video/detail/view.dart | 22 +++-- lib/utils/global_data_cache.dart | 28 ++++--- lib/utils/storage.dart | 3 +- 7 files changed, 156 insertions(+), 28 deletions(-) create mode 100644 lib/models/common/comment_range_type.dart diff --git a/lib/models/common/comment_range_type.dart b/lib/models/common/comment_range_type.dart new file mode 100644 index 00000000..979c84d8 --- /dev/null +++ b/lib/models/common/comment_range_type.dart @@ -0,0 +1,18 @@ +enum CommentRangeType { + video, + bangumi, + // dynamic, +} + +extension ActionTypeExtension on CommentRangeType { + String get value => [ + 'video', + 'bangumi', + // 'dynamic', + ][index]; + String get label => [ + '视频', + '番剧', + // '动态', + ][index]; +} diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index 004f3e9c..299f9094 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; +import 'package:pilipala/models/common/comment_range_type.dart'; import 'package:pilipala/models/common/dynamics_type.dart'; import 'package:pilipala/models/common/reply_sort_type.dart'; import 'package:pilipala/pages/setting/widgets/select_dialog.dart'; @@ -27,6 +28,8 @@ class _ExtraSettingState extends State { late String defaultSystemProxyHost; late String defaultSystemProxyPort; bool userLogin = false; + // 记录每个选项是否被选中的状态 + late List enableComment; @override void initState() { @@ -47,6 +50,8 @@ class _ExtraSettingState extends State { localCache.get(LocalCacheKey.systemProxyHost, defaultValue: ''); defaultSystemProxyPort = localCache.get(LocalCacheKey.systemProxyPort, defaultValue: ''); + enableComment = setting + .get(SettingBoxKey.enableComment, defaultValue: ['video', 'bangumi']); } // 设置代理 @@ -202,6 +207,82 @@ class _ExtraSettingState extends State { ListTile( dense: false, title: Text('评论展示', style: titleStyle), + onTap: () async { + List tempEnableComment = List.from(enableComment); + int? result = await showDialog( + context: context, + builder: (context) { + // 带多选框的list + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return AlertDialog( + title: const Text('评论展示'), + contentPadding: const EdgeInsets.fromLTRB(0, 24, 0, 24), + content: SizedBox( + width: double.maxFinite, + child: ListView.builder( + itemCount: CommentRangeType.values.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return CheckboxListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 24, vertical: 0), + title: Text( + '${CommentRangeType.values[index].label}评论'), + value: tempEnableComment.contains( + CommentRangeType.values[index].value), + onChanged: (bool? value) { + setState(() { + if (value == true) { + tempEnableComment.add( + CommentRangeType.values[index].value); + } else { + tempEnableComment.remove( + CommentRangeType.values[index].value); + } + }); + }, + ); + }, + ), + ), + actions: [ + TextButton( + onPressed: Navigator.of(context).pop, + child: Text( + '取消', + style: TextStyle( + color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () async { + enableComment = tempEnableComment; + setting.put( + SettingBoxKey.enableComment, enableComment); + GlobalDataCache.enableComment = enableComment; + SmartDialog.showToast('操作成功'); + Navigator.of(context).pop(); + }, + child: const Text('确认'), + ) + ], + ); + }, + ); + }, + ); + if (result != null) { + defaultReplySort = result; + setting.put(SettingBoxKey.replySortType, result); + setState(() {}); + } + }, + ), + ListTile( + dense: false, + title: Text('评论排序', style: titleStyle), subtitle: Text( '当前优先展示「${ReplySortType.values[defaultReplySort].titles}」', style: subTitleStyle, @@ -211,7 +292,7 @@ class _ExtraSettingState extends State { context: context, builder: (context) { return SelectDialog( - title: '评论展示', + title: '评论排序', value: defaultReplySort, values: ReplySortType.values.map((e) { return {'title': e.titles, 'value': e.index}; diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index ca5a73be..3755233c 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -21,6 +21,7 @@ import 'package:pilipala/models/video/play/url.dart'; import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/video/detail/reply_reply/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/video_utils.dart'; @@ -140,8 +141,16 @@ class VideoDetailController extends GetxController } else if (argMap.containsKey('pic')) { updateCover(argMap['pic']); } - - tabCtr = TabController(length: 2, vsync: this); + tabs.value = [ + '简介', + if (videoType == SearchType.video && + GlobalDataCache.enableComment.contains('video')) + '评论', + if (videoType == SearchType.media_bangumi && + GlobalDataCache.enableComment.contains('bangumi')) + '评论' + ]; + tabCtr = TabController(length: tabs.length, vsync: this); autoPlay.value = setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true); enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: false); diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 24bd7db0..5af5d57a 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -17,6 +17,7 @@ import 'package:pilipala/pages/video/detail/controller.dart'; import 'package:pilipala/pages/video/detail/reply/index.dart'; import 'package:pilipala/plugin/pl_player/models/play_repeat.dart'; import 'package:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:share_plus/share_plus.dart'; @@ -99,7 +100,11 @@ class VideoIntroController extends GetxController { } final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); - videoDetailCtr.tabs.value = ['简介', '评论 ${result['data']?.stat?.reply}']; + videoDetailCtr.tabs.value = [ + '简介', + if (GlobalDataCache.enableComment.contains('video')) + '评论 ${result['data']?.stat?.reply}' + ]; videoDetailCtr.cover.value = cover ?? result['data'].pic ?? ''; // 获取到粉丝数再返回 await queryUserStat(); @@ -469,10 +474,12 @@ class VideoIntroController extends GetxController { // 重新请求评论 try { /// 未渲染回复组件时可能异常 - final VideoReplyController videoReplyCtr = - Get.find(tag: heroTag); - videoReplyCtr.aid = aid; - videoReplyCtr.queryReplyList(type: 'init'); + if (GlobalDataCache.enableComment.contains('video')) { + final VideoReplyController videoReplyCtr = + Get.find(tag: heroTag); + videoReplyCtr.aid = aid; + videoReplyCtr.queryReplyList(type: 'init'); + } } catch (_) {} this.bvid = bvid; await queryVideoIntro(cover: cover); diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 488ed14d..564ab65a 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -24,6 +24,7 @@ import 'package:pilipala/pages/video/detail/related/index.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/plugin/pl_player/models/play_repeat.dart'; import 'package:pilipala/services/service_locator.dart'; +import 'package:pilipala/utils/global_data_cache.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:status_bar_control/status_bar_control.dart'; @@ -779,13 +780,20 @@ class _VideoDetailPageState extends State ); }, ), - Obx( - () => VideoReplyPanel( - bvid: vdCtr.bvid, - oid: vdCtr.oid.value, - onControllerCreated: vdCtr.onControllerCreated, - ), - ) + if ((vdCtr.videoType == SearchType.media_bangumi && + GlobalDataCache.enableComment + .contains('bangumi')) || + (vdCtr.videoType == SearchType.video && + GlobalDataCache.enableComment + .contains('video'))) ...[ + Obx( + () => VideoReplyPanel( + bvid: vdCtr.bvid, + oid: vdCtr.oid.value, + onControllerCreated: vdCtr.onControllerCreated, + ), + ) + ], ], ), ), diff --git a/lib/utils/global_data_cache.dart b/lib/utils/global_data_cache.dart index a421f829..01b68dc6 100644 --- a/lib/utils/global_data_cache.dart +++ b/lib/utils/global_data_cache.dart @@ -5,7 +5,7 @@ import 'package:pilipala/plugin/pl_player/models/play_speed.dart'; import 'package:pilipala/utils/storage.dart'; import '../models/common/index.dart'; -Box setting = GStorage.setting; +Box settingBox = GStorage.setting; Box localCache = GStorage.localCache; Box videoStorage = GStorage.video; Box userInfoCache = GStorage.userInfo; @@ -55,6 +55,8 @@ class GlobalDataCache { static late bool enableDynamicSwitch; // 投屏开关 static bool enableDlna = false; + // 视频评论开关 + static List enableComment = ['video', 'bangumi']; // 私有构造函数 GlobalDataCache._(); @@ -67,18 +69,18 @@ class GlobalDataCache { // 异步初始化方法 static Future initialize() async { - imgQuality = await setting.get(SettingBoxKey.defaultPicQa, + imgQuality = await settingBox.get(SettingBoxKey.defaultPicQa, defaultValue: 10); // 设置全局变量 - fullScreenGestureMode = FullScreenGestureMode.values[setting.get( + fullScreenGestureMode = FullScreenGestureMode.values[settingBox.get( SettingBoxKey.fullScreenGestureMode, defaultValue: FullScreenGestureMode.fromBottomtoTop.index)]; - enablePlayerControlAnimation = setting + enablePlayerControlAnimation = settingBox .get(SettingBoxKey.enablePlayerControlAnimation, defaultValue: true); - actionTypeSort = await setting.get(SettingBoxKey.actionTypeSort, + actionTypeSort = await settingBox.get(SettingBoxKey.actionTypeSort, defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); - isOpenDanmu = - await setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: false); + isOpenDanmu = await settingBox.get(SettingBoxKey.enableShowDanmaku, + defaultValue: false); blockTypes = await localCache.get(LocalCacheKey.danmakuBlockType, defaultValue: []); showArea = @@ -99,7 +101,7 @@ class GlobalDataCache { .firstWhere((e) => e.value == defaultPlayRepeat); playbackSpeed = await videoStorage.get(VideoBoxKey.playSpeedDefault, defaultValue: 1.0); - enableAutoLongPressSpeed = await setting + enableAutoLongPressSpeed = await settingBox .get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false); if (!enableAutoLongPressSpeed) { longPressSpeed = await videoStorage.get(VideoBoxKey.longPressSpeedDefault, @@ -117,11 +119,13 @@ class GlobalDataCache { sheetHeight = localCache.get('sheetHeight', defaultValue: 0.0); historyCacheList = localCache.get('cacheList', defaultValue: []); enableSearchSuggest = - setting.get(SettingBoxKey.enableSearchSuggest, defaultValue: true); + settingBox.get(SettingBoxKey.enableSearchSuggest, defaultValue: true); enableAutoExpand = - setting.get(SettingBoxKey.enableAutoExpand, defaultValue: false); + settingBox.get(SettingBoxKey.enableAutoExpand, defaultValue: false); enableDynamicSwitch = - setting.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true); - enableDlna = setting.get(SettingBoxKey.enableDlna, defaultValue: false); + settingBox.get(SettingBoxKey.enableDynamicSwitch, defaultValue: true); + enableDlna = settingBox.get(SettingBoxKey.enableDlna, defaultValue: false); + enableComment = settingBox + .get(SettingBoxKey.enableComment, defaultValue: ['video', 'bangumi']); } } diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 49a5c734..8fb00cb5 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -116,7 +116,8 @@ class SettingBoxKey { enableAutoExpand = 'enableAutoExpand', defaultHomePage = 'defaultHomePage', enableRelatedVideo = 'enableRelatedVideo', - enableDlna = 'enableDlna'; + enableDlna = 'enableDlna', + enableComment = 'enableComment'; /// 外观 static const String themeMode = 'themeMode',