diff --git a/lib/grpc/grpc_req.dart b/lib/grpc/grpc_req.dart index 3600939f1..e221f0a1d 100644 --- a/lib/grpc/grpc_req.dart +++ b/lib/grpc/grpc_req.dart @@ -12,6 +12,7 @@ import 'package:protobuf/protobuf.dart' show GeneratedMessage; abstract final class GrpcReq { static const _isolateSize = 256 * 1024; + static const _gzipMinLength = 64; static final options = Options( contentType: 'application/grpc', @@ -19,9 +20,12 @@ abstract final class GrpcReq { ); static Uint8List compressProtobuf(Uint8List proto) { - proto = const GZipEncoder().encodeBytes(proto); + final compress = proto.length > _gzipMinLength; + if (compress) { + proto = const GZipEncoder().encodeBytes(proto); + } return Uint8List(5 + proto.length) - ..[0] = 1 + ..[0] = compress ? 1 : 0 ..buffer.asByteData(1, 4).setInt32(0, proto.length, Endian.big) ..setAll(5, proto); } @@ -48,7 +52,7 @@ abstract final class GrpcReq { } } - static Future> request( + static Future> request( String url, GeneratedMessage request, T Function(Uint8List) grpcParser, { diff --git a/lib/http/live.dart b/lib/http/live.dart index 3a84c9073..87c39dc7f 100644 --- a/lib/http/live.dart +++ b/lib/http/live.dart @@ -173,7 +173,6 @@ abstract final class LiveHttp { }) async { final params = { 'access_key': ?recommend.accessKey, - 'appkey': Constants.appKey, 'channel': 'master', 'actionKey': 'appkey', 'build': 8430300, @@ -194,7 +193,6 @@ abstract final class LiveHttp { 's_locale': 'zh_CN', 'scale': 2, 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); var res = await Request().get( @@ -250,7 +248,6 @@ abstract final class LiveHttp { }) async { final params = { 'access_key': ?recommend.accessKey, - 'appkey': Constants.appKey, 'actionKey': 'appkey', 'channel': 'master', 'area_id': ?areaId, @@ -276,7 +273,6 @@ abstract final class LiveHttp { 's_locale': 'zh_CN', 'scale': 2, 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); var res = await Request().get( @@ -310,7 +306,6 @@ abstract final class LiveHttp { static Future?>> liveAreaList() async { final params = { 'access_key': ?recommend.accessKey, - 'appkey': Constants.appKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', @@ -322,7 +317,6 @@ abstract final class LiveHttp { 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); var res = await Request().get( @@ -343,7 +337,6 @@ abstract final class LiveHttp { static Future>> getLiveFavTag() async { final params = { 'access_key': ?Accounts.main.accessKey, - 'appkey': Constants.appKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', @@ -355,7 +348,6 @@ abstract final class LiveHttp { 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); var res = await Request().get( @@ -381,7 +373,6 @@ abstract final class LiveHttp { final data = { 'tags': ids, 'access_key': Accounts.main.accessKey, - 'appkey': Constants.appKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', @@ -393,7 +384,6 @@ abstract final class LiveHttp { 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(data); var res = await Request().post( @@ -414,7 +404,6 @@ abstract final class LiveHttp { }) async { final params = { 'access_key': ?recommend.accessKey, - 'appkey': Constants.appKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', @@ -429,7 +418,6 @@ abstract final class LiveHttp { 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); var res = await Request().get( @@ -452,7 +440,6 @@ abstract final class LiveHttp { }) async { final params = { 'access_key': ?recommend.accessKey, - 'appkey': Constants.appKey, 'actionKey': 'appkey', 'build': 8430300, 'channel': 'master', @@ -467,7 +454,6 @@ abstract final class LiveHttp { 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statisticsApp, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, 'type': type.name, }; AppSign.appSign(params); diff --git a/lib/http/login.dart b/lib/http/login.dart index 542af8d57..587822ea5 100644 --- a/lib/http/login.dart +++ b/lib/http/login.dart @@ -36,7 +36,6 @@ abstract final class LoginHttp { var params = { // 'local_id': 'Y952A395BB157D305D8A8340FC2AAECECE17', 'local_id': '0', - 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), 'platform': 'android', 'mobi_app': 'android_hd', }; @@ -59,7 +58,6 @@ abstract final class LoginHttp { var params = { 'auth_code': authCode, 'local_id': '0', - 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), }; AppSign.appSign(params); var res = await Request().post(Api.qrcodePoll, queryParameters: params); @@ -118,7 +116,7 @@ abstract final class LoginHttp { 'local_id': buvid, // https://chinggg.github.io/post/appre/ 'login_session_id': md5 - .convert(utf8.encode(buvid + timestamp.toString())) + .convert(ascii.encode(buvid + timestamp.toString())) .toString(), 'mobi_app': 'android_hd', 'platform': 'android', @@ -236,7 +234,6 @@ abstract final class LoginHttp { 'recaptcha_token': ?recaptchaToken, 's_locale': 'zh_CN', 'statistics': Constants.statistics, - 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), 'username': username, }; AppSign.appSign(data); @@ -304,7 +301,6 @@ abstract final class LoginHttp { 's_locale': 'zh_CN', 'statistics': Constants.statistics, 'tel': tel, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(data); var res = await Request().post( @@ -456,8 +452,7 @@ abstract final class LoginHttp { static Future oauth2AccessToken({ required String code, }) async { - Map data = { - 'appkey': Constants.appKey, + final Map data = { 'build': '2001100', 'buvid': buvid, // 'c_locale': 'zh_CN', @@ -474,7 +469,6 @@ abstract final class LoginHttp { 'platform': 'android', // 's_locale': 'zh_CN', // 'statistics': Constants.statistics, - 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), }; AppSign.appSign(data); var res = await Request().post( @@ -523,7 +517,6 @@ abstract final class LoginHttp { 'platform': 'android', 'access_key': account.accessKey, 'statistics': Constants.statistics, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); var res = await Request().get( diff --git a/lib/http/member.dart b/lib/http/member.dart index 0c778689e..b88949f51 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -356,7 +356,7 @@ abstract final class MemberHttp { 'mid': mid, 'ps': ps, 'tid': tid, - 'pn': pn, + 'pn': ?pn, 'keyword': ?keyword, 'order': order, 'platform': 'web', @@ -392,7 +392,7 @@ abstract final class MemberHttp { @pragma('vm:notify-debugger-on-exception') static Future> memberDynamic({ String? offset, - int? mid, + required int mid, }) async { String dmImgStr = Utils.base64EncodeRandomString(16, 64); String dmCoverImgStr = Utils.base64EncodeRandomString(32, 128); @@ -648,7 +648,7 @@ abstract final class MemberHttp { required int pn, required String name, }) async { - Map data = { + final data = { 'vmid': mid, 'pn': pn, 'ps': ps, diff --git a/lib/http/msg.dart b/lib/http/msg.dart index 32981ea04..b2e2b01b9 100644 --- a/lib/http/msg.dart +++ b/lib/http/msg.dart @@ -383,7 +383,7 @@ abstract final class MsgHttp { }) async { String csrf = Accounts.main.csrf; final devId = getDevId(); - Map data = { + final data = { 'msg': { 'sender_uid': senderUid, 'receiver_id': receiverId, diff --git a/lib/http/sponsor_block.dart b/lib/http/sponsor_block.dart index 47cf0eaa5..647a68cd2 100644 --- a/lib/http/sponsor_block.dart +++ b/lib/http/sponsor_block.dart @@ -73,7 +73,7 @@ abstract final class SponsorBlock { assert((type == null) == (category == null)); final res = await Request().post( _api(SponsorBlockApi.voteOnSponsorTime), - data: { + queryParameters: { 'UUID': uuid, 'type': ?type, 'category': ?category?.name, diff --git a/lib/http/video.dart b/lib/http/video.dart index 7c8c6df96..3fbe441ac 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -801,7 +801,7 @@ abstract final class VideoHttp { final params = await WbiSign.makSign({ 'bvid': bvid, 'cid': cid, - 'up_mid': upMid, + 'up_mid': ?upMid, }); var res = await Request().get(Api.aiConclusion, queryParameters: params); final int? code = res.data['code']; @@ -1067,7 +1067,6 @@ abstract final class VideoHttp { 'playurl_type': playurlType, 'protocol': 0, 'qn': qn ?? 80, - 'ts': DateTime.now().millisecondsSinceEpoch ~/ 1000, }; AppSign.appSign(params); final res = await Request().get( diff --git a/lib/models/common/enum_with_label.dart b/lib/models/common/enum_with_label.dart index 3067a209a..ccf0f12ae 100644 --- a/lib/models/common/enum_with_label.dart +++ b/lib/models/common/enum_with_label.dart @@ -1,4 +1,3 @@ -abstract class EnumWithLabel { +mixin EnumWithLabel on Enum { String get label; - int get index; } diff --git a/lib/models_new/live/live_feed_index/data.dart b/lib/models_new/live/live_feed_index/data.dart index 50432e90b..c7c455359 100644 --- a/lib/models_new/live/live_feed_index/data.dart +++ b/lib/models_new/live/live_feed_index/data.dart @@ -26,8 +26,7 @@ class LiveIndexData { areaItem = LiveCardList.fromJson(json); break; case 'small_card_v1': - cardList ??= []; - cardList!.add(LiveCardList.fromJson(json)); + (cardList ??= []).add(LiveCardList.fromJson(json)); break; } } diff --git a/lib/models_new/live/live_follow/data.dart b/lib/models_new/live/live_follow/data.dart index f41c8cdf7..54ac481db 100644 --- a/lib/models_new/live/live_follow/data.dart +++ b/lib/models_new/live/live_follow/data.dart @@ -21,14 +21,11 @@ class LiveFollowData { title = json['title'] as String?; pageSize = json['pageSize'] as int?; totalPage = json['totalPage'] as int?; - if ((json['list'] as List?)?.isNotEmpty == true) { - list = []; - for (var json in json['list']) { - if (json['live_status'] == 1) { - list!.add(LiveFollowItem.fromJson(json)); - } - } - } + list = (json['list'] as List?) + ?.cast>() + .where((i) => i['live_status'] == 1) + .map(LiveFollowItem.fromJson) + .toList(); count = json['count'] as int?; liveCount = json['live_count'] as int?; } diff --git a/lib/pages/article_list/view.dart b/lib/pages/article_list/view.dart index 039e662c8..80c4bdff7 100644 --- a/lib/pages/article_list/view.dart +++ b/lib/pages/article_list/view.dart @@ -12,7 +12,6 @@ import 'package:PiliPlus/utils/date_utils.dart'; import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/num_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart'; -import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -26,7 +25,7 @@ class ArticleListPage extends StatefulWidget { class _ArticleListPageState extends State with GridMixin { final _controller = Get.put( ArticleListController(), - tag: Utils.generateRandomString(8), + tag: Get.parameters['id']!, ); late EdgeInsets padding; diff --git a/lib/pages/common/common_page.dart b/lib/pages/common/common_page.dart index 1873ac426..35f5b9a1c 100644 --- a/lib/pages/common/common_page.dart +++ b/lib/pages/common/common_page.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:PiliPlus/pages/common/common_controller.dart'; import 'package:PiliPlus/pages/home/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; @@ -14,8 +12,8 @@ abstract class CommonPageState< > extends State { R get controller; - StreamController? mainStream; - StreamController? searchBarStream; + RxBool? showBottomBar; + RxBool? showSearchBar; // late double _downScrollCount = 0.0; // 向下滚动计数器 late double _upScrollCount = 0.0; // 向上滚动计数器 double? _lastScrollPosition; // 记录上次滚动位置 @@ -27,18 +25,18 @@ abstract class CommonPageState< void initState() { super.initState(); try { - mainStream = Get.find().bottomBarStream; - searchBarStream = Get.find().searchBarStream; + showBottomBar = Get.find().bottomBar; + showSearchBar = Get.find().searchBar; } catch (_) {} if (_enableScrollThreshold && - (mainStream != null || searchBarStream != null)) { + (showBottomBar != null || showSearchBar != null)) { controller.scrollController.addListener(listener); } } Widget onBuild(Widget child) { if (!_enableScrollThreshold && - (mainStream != null || searchBarStream != null)) { + (showBottomBar != null || showSearchBar != null)) { return NotificationListener( onNotification: onNotification, child: child, @@ -51,11 +49,11 @@ abstract class CommonPageState< if (notification.metrics.axis == Axis.horizontal) return false; final direction = notification.direction; if (direction == ScrollDirection.forward) { - mainStream?.add(true); - searchBarStream?.add(true); + showBottomBar?.value = true; + showSearchBar?.value = true; } else if (direction == ScrollDirection.reverse) { - mainStream?.add(false); - searchBarStream?.add(false); + showBottomBar?.value = false; + showSearchBar?.value = false; } return false; } @@ -72,8 +70,8 @@ abstract class CommonPageState< final double scrollDelta = currentPosition - _lastScrollPosition!; if (direction == ScrollDirection.reverse) { - mainStream?.add(false); - searchBarStream?.add(false); // // 向下滚动,累加向下滚动距离,重置向上滚动计数器 + showBottomBar?.value = false; + showSearchBar?.value = false; // // 向下滚动,累加向下滚动距离,重置向上滚动计数器 _upScrollCount = 0.0; // 重置向上滚动计数器 // if (scrollDelta > 0) { // _downScrollCount += scrollDelta; @@ -93,8 +91,8 @@ abstract class CommonPageState< // 当累计向上滚动距离超过阈值时,显示顶底栏 if (_upScrollCount >= _scrollThreshold) { - mainStream?.add(true); - searchBarStream?.add(true); + showBottomBar?.value = true; + showSearchBar?.value = true; } } } @@ -105,6 +103,8 @@ abstract class CommonPageState< @override void dispose() { + showSearchBar = null; + showBottomBar = null; controller.scrollController.removeListener(listener); super.dispose(); } diff --git a/lib/pages/common/dyn/common_dyn_page.dart b/lib/pages/common/dyn/common_dyn_page.dart index f5c184a4e..7448cd2f2 100644 --- a/lib/pages/common/dyn/common_dyn_page.dart +++ b/lib/pages/common/dyn/common_dyn_page.dart @@ -17,7 +17,6 @@ import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; import 'package:get/get.dart' hide ContextExtensionss; abstract class CommonDynPageState extends State @@ -51,14 +50,9 @@ abstract class CommonDynPageState extends State void listener() { final pos = scrollController.positions; controller.showTitle.value = pos.first.pixels > 55; - - final direction1 = pos.first.userScrollDirection; - late final direction2 = pos.last.userScrollDirection; - if (direction1 == ScrollDirection.forward || - direction2 == ScrollDirection.forward) { + if (pos.any((e) => e.userScrollDirection == .forward)) { showFab(); - } else if (direction1 == ScrollDirection.reverse || - direction2 == ScrollDirection.reverse) { + } else if (pos.any((e) => e.userScrollDirection == .reverse)) { hideFab(); } } diff --git a/lib/pages/danmaku_block/controller.dart b/lib/pages/danmaku_block/controller.dart index 85ec1cf11..db1ee33d8 100644 --- a/lib/pages/danmaku_block/controller.dart +++ b/lib/pages/danmaku_block/controller.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:PiliPlus/http/danmaku_block.dart'; import 'package:PiliPlus/models/common/dm_block_type.dart'; import 'package:PiliPlus/models/user/danmaku_block.dart'; -import 'package:crclib/catalog.dart'; +import 'package:archive/archive.dart' show getCrc32; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -64,7 +64,7 @@ class DanmakuBlockController extends GetxController required int type, }) async { if (type == 2) { - filter = Crc32Xz().convert(utf8.encode(filter)).toRadixString(16); + filter = getCrc32(ascii.encode(filter), 0).toRadixString(16); } SmartDialog.showLoading(msg: '正在添加弹幕屏蔽规则……'); final result = await DanmakuFilterHttp.danmakuFilterAdd( diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index 0a693e338..a069a1f62 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -7,6 +7,7 @@ import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/pages/dynamics/widgets/up_panel.dart'; import 'package:PiliPlus/pages/dynamics_create/view.dart'; import 'package:PiliPlus/pages/dynamics_tab/view.dart'; +import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:flutter/material.dart' hide DraggableScrollableSheet; import 'package:get/get.dart'; @@ -19,7 +20,7 @@ class DynamicsPage extends StatefulWidget { class _DynamicsPageState extends State with AutomaticKeepAliveClientMixin { - final DynamicsController _dynamicsController = Get.put(DynamicsController()); + final _dynamicsController = Get.putOrFind(DynamicsController.new); UpPanelPosition get upPanelPosition => _dynamicsController.upPanelPosition; @override diff --git a/lib/pages/dynamics_tab/view.dart b/lib/pages/dynamics_tab/view.dart index 68717c88c..23bec6ba1 100644 --- a/lib/pages/dynamics_tab/view.dart +++ b/lib/pages/dynamics_tab/view.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/pages/dynamics/widgets/dynamic_panel.dart'; import 'package:PiliPlus/pages/dynamics_tab/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; +import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:PiliPlus/utils/global_data.dart'; import 'package:PiliPlus/utils/waterfall.dart'; import 'package:flutter/material.dart'; @@ -33,11 +34,12 @@ class _DynamicsTabPageState StreamSubscription? _listener; late final MainController _mainController = Get.find(); - DynamicsController dynamicsController = Get.put(DynamicsController()); + DynamicsController dynamicsController = Get.putOrFind(DynamicsController.new); @override - late DynamicsTabController controller = Get.put( - DynamicsTabController(dynamicsType: widget.dynamicsType) - ..mid = dynamicsController.mid.value, + late final DynamicsTabController controller = Get.putOrFind( + () => + DynamicsTabController(dynamicsType: widget.dynamicsType) + ..mid = dynamicsController.mid.value, tag: widget.dynamicsType.name, ); diff --git a/lib/pages/home/controller.dart b/lib/pages/home/controller.dart index 711c13287..9913184ea 100644 --- a/lib/pages/home/controller.dart +++ b/lib/pages/home/controller.dart @@ -19,8 +19,7 @@ class HomeController extends GetxController late List tabs; late TabController tabController; - StreamController? searchBarStream; - final bool hideSearchBar = Pref.hideSearchBar; + RxBool? searchBar; final bool useSideBar = Pref.useSideBar; bool enableSearchWord = Pref.enableSearchWord; @@ -38,8 +37,8 @@ class HomeController extends GetxController void onInit() { super.onInit(); - if (hideSearchBar) { - searchBarStream = StreamController.broadcast(); + if (Pref.hideSearchBar) { + searchBar = true.obs; } if (enableSearchWord) { @@ -90,10 +89,4 @@ class HomeController extends GetxController } } catch (_) {} } - - @override - void onClose() { - searchBarStream?.close(); - super.onClose(); - } } diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index fce6856da..da8ca4dac 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/pages/home/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; +import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:PiliPlus/utils/extension/size_ext.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:flutter/material.dart'; @@ -21,8 +22,8 @@ class HomePage extends StatefulWidget { class _HomePageState extends State with AutomaticKeepAliveClientMixin { - final HomeController _homeController = Get.put(HomeController()); - final MainController _mainController = Get.put(MainController()); + final _homeController = Get.putOrFind(HomeController.new); + final _mainController = Get.find(); @override bool get wantKeepAlive => true; @@ -149,30 +150,28 @@ class _HomePageState extends State } Widget customAppBar(ThemeData theme) { - if (!_homeController.hideSearchBar) { + if (_homeController.searchBar case final searchBar?) { + return Obx(() { + final showSearchBar = searchBar.value; + return AnimatedOpacity( + opacity: showSearchBar ? 1 : 0, + duration: const Duration(milliseconds: 300), + child: AnimatedContainer( + curve: Curves.easeInOutCubicEmphasized, + duration: const Duration(milliseconds: 500), + height: showSearchBar ? 52 : 0, + padding: const EdgeInsets.fromLTRB(14, 6, 14, 0), + child: searchBarAndUser(theme), + ), + ); + }); + } else { return Container( height: 52, padding: const EdgeInsets.fromLTRB(14, 6, 14, 0), child: searchBarAndUser(theme), ); } - return StreamBuilder( - stream: _homeController.searchBarStream?.stream.distinct(), - initialData: true, - builder: (BuildContext context, AsyncSnapshot snapshot) { - return AnimatedOpacity( - opacity: snapshot.data ? 1 : 0, - duration: const Duration(milliseconds: 300), - child: AnimatedContainer( - curve: Curves.easeInOutCubicEmphasized, - duration: const Duration(milliseconds: 500), - height: snapshot.data ? 52 : 0, - padding: const EdgeInsets.fromLTRB(14, 6, 14, 0), - child: searchBarAndUser(theme), - ), - ); - }, - ); } Widget searchBar(ThemeData theme) { diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index 0b8160513..c7c816577 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -12,6 +12,7 @@ import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/pages/home/controller.dart'; import 'package:PiliPlus/pages/mine/view.dart'; import 'package:PiliPlus/services/account_service.dart'; +import 'package:PiliPlus/utils/extension/get_ext.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:PiliPlus/utils/storage.dart'; @@ -30,8 +31,7 @@ class MainController extends GetxController List navigationBars = []; - StreamController? bottomBarStream; - late bool hideTabBar = Pref.hideTabBar; + RxBool? bottomBar; late dynamic controller; final RxInt selectedIndex = 0.obs; @@ -41,12 +41,10 @@ class MainController extends GetxController late int dynamicPeriod = Pref.dynamicPeriod * 60 * 1000; late int _lastCheckDynamicAt = 0; late bool hasDyn = false; - late final DynamicsController dynamicController = Get.put( - DynamicsController(), - ); + late final dynamicController = Get.putOrFind(DynamicsController.new); late bool hasHome = false; - late final HomeController homeController = Get.put(HomeController()); + late final homeController = Get.putOrFind(HomeController.new); late DynamicBadgeMode msgBadgeMode = Pref.msgBadgeMode; late Set msgUnReadTypes = Pref.msgUnReadTypeV2; @@ -84,8 +82,8 @@ class MainController extends GetxController ) : PageController(initialPage: selectedIndex.value); - if (navigationBars.length > 1 && hideTabBar) { - bottomBarStream = StreamController.broadcast(); + if (navigationBars.length > 1 && Pref.hideTabBar) { + bottomBar = true.obs; } dynamicBadgeMode = DynamicBadgeMode.values[Pref.dynamicBadgeMode]; @@ -321,13 +319,13 @@ class MainController extends GetxController void setSearchBar() { if (hasHome) { - homeController.searchBarStream?.add(true); + homeController.searchBar?.value = true; } } @override void onClose() { - bottomBarStream?.close(); + bottomBar?.close(); controller.dispose(); super.onClose(); } diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 762d25c6c..96b5ef634 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -36,7 +36,7 @@ class MainApp extends StatefulWidget { class _MainAppState extends State with RouteAware, WidgetsBindingObserver, WindowListener, TrayListener { - final MainController _mainController = Get.put(MainController()); + final _mainController = Get.put(MainController()); late final _setting = GStorage.setting; @override @@ -294,7 +294,7 @@ class _MainAppState extends State .toList(), ), ) - : const SizedBox.shrink() + : null : null; return PopScope( canPop: false, @@ -305,7 +305,7 @@ class _MainAppState extends State if (_mainController.selectedIndex.value != 0) { _mainController ..setIndex(0) - ..bottomBarStream?.add(true) + ..bottomBar?.value = true ..setSearchBar(); } else { onBack(); @@ -439,28 +439,28 @@ class _MainAppState extends State ], ), ), - bottomNavigationBar: useBottomNav - ? _mainController.hideTabBar - ? StreamBuilder( - stream: _mainController.bottomBarStream?.stream - .distinct(), - initialData: true, - builder: (context, AsyncSnapshot snapshot) { - return AnimatedSlide( - curve: Curves.easeInOutCubicEmphasized, - duration: const Duration(milliseconds: 500), - offset: Offset(0, snapshot.data ? 0 : 1), - child: bottomNav, - ); - }, - ) - : bottomNav - : null, + bottomNavigationBar: _buildBottom(bottomNav), ), ), ); } + Widget? _buildBottom(Widget? bottomNav) { + if (bottomNav != null) { + if (_mainController.bottomBar case final bottomBar?) { + return Obx( + () => AnimatedSlide( + curve: Curves.easeInOutCubicEmphasized, + duration: const Duration(milliseconds: 500), + offset: Offset(0, bottomBar.value ? 0 : 1), + child: bottomNav, + ), + ); + } + } + return bottomNav; + } + Widget _buildIcon({ required NavigationBarType type, bool selected = false, diff --git a/lib/pages/member_profile/view.dart b/lib/pages/member_profile/view.dart index e35a55bf3..8174722b1 100644 --- a/lib/pages/member_profile/view.dart +++ b/lib/pages/member_profile/view.dart @@ -363,7 +363,6 @@ class _EditProfilePageState extends State { 'platform': 'android', 's_locale': 'zh_CN', 'statistics': Constants.statistics, - 'ts': (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(), if (type == ProfileType.uname) 'uname': _textController.text else if (type == ProfileType.sign) @@ -500,15 +499,15 @@ class _EditProfilePageState extends State { toolbarColor: theme.colorScheme.secondaryContainer, toolbarWidgetColor: theme.colorScheme.onSecondaryContainer, statusBarLight: theme.colorScheme.isLight, - aspectRatioPresets: [CropAspectRatioPresetCustom()], + aspectRatioPresets: const [CropAspectRatioPresetCustom()], lockAspectRatio: true, hideBottomControls: true, cropStyle: CropStyle.circle, - initAspectRatio: CropAspectRatioPresetCustom(), + initAspectRatio: const CropAspectRatioPresetCustom(), ), IOSUiSettings( title: '裁剪', - aspectRatioPresets: [CropAspectRatioPresetCustom()], + aspectRatioPresets: const [CropAspectRatioPresetCustom()], cropStyle: CropStyle.circle, aspectRatioLockEnabled: true, resetAspectRatioEnabled: false, @@ -556,8 +555,10 @@ class _EditProfilePageState extends State { } class CropAspectRatioPresetCustom implements CropAspectRatioPresetData { + const CropAspectRatioPresetCustom(); + @override - (int, int)? get data => (1, 1); + (int, int) get data => const (1, 1); @override String get name => '1x1 (customized)'; diff --git a/lib/pages/setting/models/style_settings.dart b/lib/pages/setting/models/style_settings.dart index b3d61195f..ca132a938 100644 --- a/lib/pages/setting/models/style_settings.dart +++ b/lib/pages/setting/models/style_settings.dart @@ -245,7 +245,7 @@ List get styleSettings => [ }, ); if (result != null) { - MainController mainController = Get.put(MainController()) + final mainController = Get.find() ..dynamicBadgeMode = DynamicBadgeMode.values[result.index]; if (mainController.dynamicBadgeMode != DynamicBadgeMode.hidden) { mainController.getUnreadDynamic(); @@ -275,7 +275,7 @@ List get styleSettings => [ }, ); if (result != null) { - MainController mainController = Get.put(MainController()) + final mainController = Get.find() ..msgBadgeMode = DynamicBadgeMode.values[result.index]; if (mainController.msgBadgeMode != DynamicBadgeMode.hidden) { mainController.queryUnreadMsg(true); @@ -304,7 +304,7 @@ List get styleSettings => [ }, ); if (result != null) { - MainController mainController = Get.put(MainController()) + final mainController = Get.find() ..msgUnReadTypes = result; if (mainController.msgBadgeMode != DynamicBadgeMode.hidden) { mainController.queryUnreadMsg(); diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index d168872b5..5945e5f8a 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -42,8 +42,8 @@ import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; +import 'package:archive/archive.dart' show getCrc32; import 'package:canvas_danmaku/canvas_danmaku.dart'; -import 'package:crclib/catalog.dart'; import 'package:dio/dio.dart' show Options; import 'package:easy_debounce/easy_throttle.dart'; import 'package:floating/floating.dart'; @@ -329,9 +329,10 @@ class PlPlayerController { bool showDanmaku = true; Set dmState = {}; late final mergeDanmaku = Pref.mergeDanmaku; - late final String midHash = Crc32Xz() - .convert(utf8.encode(Accounts.main.mid.toString())) - .toRadixString(16); + late final String midHash = getCrc32( + ascii.encode(Accounts.main.mid.toString()), + 0, + ).toRadixString(16); // 弹幕相关配置 late Set blockTypes = Pref.danmakuBlockType; late bool blockColorful = blockTypes.contains(6); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index a1715626b..116496ef6 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -538,8 +538,8 @@ class _PLVideoPlayerState extends State final List sections = videoDetail.ugcSeason!.sections!; for (int i = 0; i < sections.length; i++) { final List episodesList = sections[i].episodes!; - for (int j = 0; j < episodesList.length; j++) { - if (episodesList[j].cid == plPlayerController.cid) { + for (var item in episodesList) { + if (item.cid == currentCid) { index = i; episodes = episodesList; break; @@ -2102,7 +2102,6 @@ class _PLVideoPlayerState extends State return Transform.flip( flipX: plPlayerController.flipX.value, flipY: plPlayerController.flipY.value, - filterQuality: FilterQuality.low, child: FittedBox( fit: videoFit.boxFit, alignment: widget.alignment, diff --git a/lib/services/download/download_service.dart b/lib/services/download/download_service.dart index 831c0a013..b37ee8aad 100644 --- a/lib/services/download/download_service.dart +++ b/lib/services/download/download_service.dart @@ -440,9 +440,9 @@ class DownloadService extends GetxService { } } - Future _updateBiliDownloadEntryJson(BiliDownloadEntryInfo entry) async { + Future _updateBiliDownloadEntryJson(BiliDownloadEntryInfo entry) { final entryJsonFile = File(path.join(entry.entryDirPath, _entryFile)); - await entryJsonFile.writeAsString(jsonEncode(entry.toJson())); + return entryJsonFile.writeAsString(jsonEncode(entry.toJson())); } void _onReceive(int progress, int total) { diff --git a/lib/utils/accounts/account_manager/account_mgr.dart b/lib/utils/accounts/account_manager/account_mgr.dart index dbc76c00e..1a1eb818e 100644 --- a/lib/utils/accounts/account_manager/account_mgr.dart +++ b/lib/utils/accounts/account_manager/account_mgr.dart @@ -77,8 +77,6 @@ class AccountManager extends Interceptor { if (!account.accessKey.isNullOrEmpty) { dataPtr['access_key'] = account.accessKey!; } - dataPtr['ts'] ??= (DateTime.now().millisecondsSinceEpoch ~/ 1000) - .toString(); AppSign.appSign(dataPtr); // if (kDebugMode) debugPrint(dataPtr.toString()); } diff --git a/lib/utils/app_sign.dart b/lib/utils/app_sign.dart index 8e8106324..38c616e42 100644 --- a/lib/utils/app_sign.dart +++ b/lib/utils/app_sign.dart @@ -9,10 +9,14 @@ abstract final class AppSign { String appkey = Constants.appKey, String appsec = Constants.appSec, }) { - params['appkey'] = appkey; - final sorted = Map.fromEntries( - params.entries.toList()..sort((a, b) => a.key.compareTo(b.key)), + assert( + params['appkey'] == null, + 'appkey-appsec should be provided in appSign', ); + params['appkey'] = appkey; + params['ts'] ??= (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString(); + final sorted = params.entries.toList() + ..sort((a, b) => a.key.compareTo(b.key)); params['sign'] = md5 .convert(utf8.encode(_makeQueryFromParametersDefault(sorted) + appsec)) .toString(); // 获取MD5哈希值 @@ -20,12 +24,14 @@ abstract final class AppSign { /// from [Uri] static String _makeQueryFromParametersDefault( - Map*/> queryParameters, + List*/>> + queryParameters, ) { var result = StringBuffer(); var separator = ''; void writeParameter(String key, String? value) { + assert(value != null, 'remove null value'); result.write(separator); separator = '&'; result.write(Uri.encodeQueryComponent(key)); @@ -36,15 +42,15 @@ abstract final class AppSign { } } - queryParameters.forEach((key, value) { - if (value case Iterable values) { + for (var i in queryParameters) { + if (i.value case Iterable values) { for (final String value in values) { - writeParameter(key, value); + writeParameter(i.key, value); } } else { - writeParameter(key, value?.toString()); + writeParameter(i.key, i.value?.toString()); } - }); + } return result.toString(); } } diff --git a/lib/utils/id_utils.dart b/lib/utils/id_utils.dart index e33220221..83c6ce52a 100644 --- a/lib/utils/id_utils.dart +++ b/lib/utils/id_utils.dart @@ -84,7 +84,7 @@ abstract final class IdUtils { return ''; } - var midByte = utf8.encode(uid.toString()); + var midByte = ascii.encode(uid.toString()); const key = 'ad1va46a7lza'; for (int i = 0; i < midByte.length; i++) { diff --git a/lib/utils/wbi_sign.dart b/lib/utils/wbi_sign.dart index bd6e76d09..57bf60c9d 100644 --- a/lib/utils/wbi_sign.dart +++ b/lib/utils/wbi_sign.dart @@ -11,13 +11,11 @@ import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:crypto/crypto.dart'; import 'package:hive/hive.dart'; -import 'package:synchronized/synchronized.dart'; abstract final class WbiSign { - static Box localCache = GStorage.localCache; - static final Lock lock = Lock(); - static final RegExp chrFilter = RegExp(r"[!\'\(\)\*]"); - static const mixinKeyEncTab = [ + static Box get _localCache => GStorage.localCache; + static final RegExp _chrFilter = RegExp(r"[!\'\(\)\*]"); + static const _mixinKeyEncTab = [ 46, 47, 18, @@ -52,20 +50,23 @@ abstract final class WbiSign { 13, ]; + static Future? _future; + // 对 imgKey 和 subKey 进行字符顺序打乱编码 static String getMixinKey(String orig) { - return mixinKeyEncTab.map((i) => orig[i]).join(); + final codeUnits = orig.codeUnits; + return String.fromCharCodes(_mixinKeyEncTab.map((i) => codeUnits[i])); } // 为请求参数进行 wbi 签名 - static void encWbi(Map params, String mixinKey) { + static void encWbi(Map params, String mixinKey) { params['wts'] = DateTime.now().millisecondsSinceEpoch ~/ 1000; // 按照 key 重排参数 final List keys = params.keys.toList()..sort(); final queryStr = keys .map( (i) => - '${Uri.encodeComponent(i)}=${Uri.encodeComponent(params[i].toString().replaceAll(chrFilter, ''))}', + '${Uri.encodeComponent(i)}=${Uri.encodeComponent(params[i].toString().replaceAll(_chrFilter, ''))}', ) .join('&'); params['w_rid'] = md5 @@ -73,30 +74,19 @@ abstract final class WbiSign { .toString(); // 计算 w_rid } - // 获取最新的 img_key 和 sub_key 可以从缓存中获取 - static Future getWbiKeys() async { - final DateTime nowDate = DateTime.now(); - String? mixinKey = localCache.get(LocalCacheKey.mixinKey); - if (mixinKey != null && - DateTime.fromMillisecondsSinceEpoch( - localCache.get(LocalCacheKey.timeStamp) as int, - ).day == - nowDate.day) { - return mixinKey; - } + static Future _getWbiKeys(DateTime nowDate) async { final resp = await Request().get(Api.userInfo); - try { final wbiUrls = resp.data['data']['wbi_img']; - mixinKey = getMixinKey( + final mixinKey = getMixinKey( Utils.getFileName(wbiUrls['img_url'], fileExt: false) + Utils.getFileName(wbiUrls['sub_url'], fileExt: false), ); - localCache + _localCache ..put(LocalCacheKey.mixinKey, mixinKey) - ..put(LocalCacheKey.timeStamp, nowDate.millisecondsSinceEpoch); + ..put(LocalCacheKey.timeStamp, DateTime.now().millisecondsSinceEpoch); return mixinKey; } catch (_) { @@ -104,11 +94,25 @@ abstract final class WbiSign { } } - static Future> makSign( - Map params, + static Future getWbiKeys() async { + final DateTime nowDate = DateTime.now(); + if (DateTime.fromMillisecondsSinceEpoch( + _localCache.get(LocalCacheKey.timeStamp, defaultValue: 0) as int, + ).day == + nowDate.day) { + final String? mixinKey = _localCache.get(LocalCacheKey.mixinKey); + if (mixinKey != null) return mixinKey; + return _future ??= _getWbiKeys(nowDate); + } else { + return _future = _getWbiKeys(nowDate); + } + } + + static Future> makSign( + Map params, ) async { // params 为需要加密的请求参数 - final String mixinKey = await lock.synchronized(getWbiKeys); + final String mixinKey = await getWbiKeys(); encWbi(params, mixinKey); return params; } diff --git a/pubspec.lock b/pubspec.lock index 9e5c4d766..7226edddf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -340,14 +340,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.8" - crclib: - dependency: "direct main" - description: - name: crclib - sha256: "800f2226cd90c900ddcaaccb79449eabe690627ee8c7046737458f1a2509043d" - url: "https://pub.dev" - source: hosted - version: "3.0.0" cross_file: dependency: transitive description: @@ -1762,14 +1754,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.5.2" - tuple: - dependency: transitive - description: - name: tuple - sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 - url: "https://pub.dev" - source: hosted - version: "2.0.2" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c0f09b7bc..9e9771c83 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -205,7 +205,6 @@ dependencies: git: url: https://github.com/bggRGjQaUbCoE/flutter_sortable_wrap.git ref: master - crclib: ^3.0.0 web_socket_channel: ^3.0.3 # image: ^4.7.1 # window_manager: ^0.5.1