From 6f628374953ff9d032e6f980f6497ca343b86026 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 2 Feb 2024 23:12:04 +0800 Subject: [PATCH 001/106] =?UTF-8?q?mod:=20media=5Fkit=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.lock | 27 +++++++++++++++------------ pubspec.yaml | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index d9b6a01d..e98d7443 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -848,10 +848,11 @@ packages: media_kit: dependency: "direct main" description: - name: media_kit - sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a" - url: "https://pub.flutter-io.cn" - source: hosted + path: media_kit + ref: main + resolved-ref: "63c6ebe8366db7ecfbd13ab9ce76b11dd86dae48" + url: "https://github.com/media-kit/media-kit.git" + source: git version: "1.1.10+1" media_kit_libs_android_video: dependency: transitive @@ -888,10 +889,11 @@ packages: media_kit_libs_video: dependency: "direct main" description: - name: media_kit_libs_video - sha256: "3688e0c31482074578652bf038ce6301a5d21e1eda6b54fc3117ffeb4bdba067" - url: "https://pub.flutter-io.cn" - source: hosted + path: "libs/universal/media_kit_libs_video" + ref: main + resolved-ref: "63c6ebe8366db7ecfbd13ab9ce76b11dd86dae48" + url: "https://github.com/media-kit/media-kit.git" + source: git version: "1.0.4" media_kit_libs_windows_video: dependency: transitive @@ -912,10 +914,11 @@ packages: media_kit_video: dependency: "direct main" description: - name: media_kit_video - sha256: c048d11a19e379aebbe810647636e3fc6d18374637e2ae12def4ff8a4b99a882 - url: "https://pub.flutter-io.cn" - source: hosted + path: media_kit_video + ref: main + resolved-ref: "63c6ebe8366db7ecfbd13ab9ce76b11dd86dae48" + url: "https://github.com/media-kit/media-kit.git" + source: git version: "1.2.4" meta: dependency: transitive diff --git a/pubspec.yaml b/pubspec.yaml index f4b8fe61..41cc829d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -85,9 +85,21 @@ dependencies: encrypt: ^5.0.3 # 视频播放器 - media_kit: ^1.1.10 # Primary package. - media_kit_video: ^1.2.4 # For video rendering. - media_kit_libs_video: ^1.0.4 + media_kit: + git: + url: https://github.com/media-kit/media-kit.git + ref: main + path: ./media_kit + media_kit_video: + git: + url: https://github.com/media-kit/media-kit.git + ref: main + path: ./media_kit_video + media_kit_libs_video: + git: + url: https://github.com/media-kit/media-kit.git + ref: main + path: ./libs/universal/media_kit_libs_video # 媒体通知 audio_service: ^0.18.12 @@ -156,6 +168,23 @@ dev_dependencies: hive_generator: ^2.0.0 build_runner: ^2.3.3 +dependency_overrides: + media_kit: + git: + url: https://github.com/media-kit/media-kit.git + ref: main + path: ./media_kit + media_kit_video: + git: + url: https://github.com/media-kit/media-kit.git + ref: main + path: ./media_kit_video + media_kit_libs_video: + git: + url: https://github.com/media-kit/media-kit.git + ref: main + path: ./libs/universal/media_kit_libs_video + flutter_launcher_icons: android: true ios: true From 2dbef3fee24ff5e9320b2c28f4e2e1835aa38416 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 19 Mar 2024 23:23:14 +0800 Subject: [PATCH 002/106] =?UTF-8?q?mod:=20media=5Fkit=E5=BC=95=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.lock | 12 ++++++------ pubspec.yaml | 27 ++++++--------------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a42bd421..fc479e1a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -858,8 +858,8 @@ packages: dependency: "direct main" description: path: media_kit - ref: main - resolved-ref: "63c6ebe8366db7ecfbd13ab9ce76b11dd86dae48" + ref: HEAD + resolved-ref: "77a130b1d7ce733b47d2133b57563716090450d0" url: "https://github.com/media-kit/media-kit.git" source: git version: "1.1.10+1" @@ -899,8 +899,8 @@ packages: dependency: "direct main" description: path: "libs/universal/media_kit_libs_video" - ref: main - resolved-ref: "63c6ebe8366db7ecfbd13ab9ce76b11dd86dae48" + ref: HEAD + resolved-ref: "77a130b1d7ce733b47d2133b57563716090450d0" url: "https://github.com/media-kit/media-kit.git" source: git version: "1.0.4" @@ -924,8 +924,8 @@ packages: dependency: "direct main" description: path: media_kit_video - ref: main - resolved-ref: "63c6ebe8366db7ecfbd13ab9ce76b11dd86dae48" + ref: HEAD + resolved-ref: "77a130b1d7ce733b47d2133b57563716090450d0" url: "https://github.com/media-kit/media-kit.git" source: git version: "1.2.4" diff --git a/pubspec.yaml b/pubspec.yaml index 23cc509f..e6690a37 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -85,21 +85,9 @@ dependencies: encrypt: ^5.0.3 # 视频播放器 - media_kit: - git: - url: https://github.com/media-kit/media-kit.git - ref: main - path: ./media_kit - media_kit_video: - git: - url: https://github.com/media-kit/media-kit.git - ref: main - path: ./media_kit_video - media_kit_libs_video: - git: - url: https://github.com/media-kit/media-kit.git - ref: main - path: ./libs/universal/media_kit_libs_video + media_kit: ^1.1.10 # Primary package. + media_kit_video: ^1.2.4 # For video rendering. + media_kit_libs_video: ^1.0.4 # 媒体通知 audio_service: ^0.18.12 @@ -177,18 +165,15 @@ dependency_overrides: media_kit: git: url: https://github.com/media-kit/media-kit.git - ref: main - path: ./media_kit + path: media_kit media_kit_video: git: url: https://github.com/media-kit/media-kit.git - ref: main - path: ./media_kit_video + path: media_kit_video media_kit_libs_video: git: url: https://github.com/media-kit/media-kit.git - ref: main - path: ./libs/universal/media_kit_libs_video + path: libs/universal/media_kit_libs_video flutter_launcher_icons: android: true From 76784ee6647893098512226f39e41c57c22b2dc9 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 19 Mar 2024 23:33:32 +0800 Subject: [PATCH 003/106] mod: seekTo --- lib/plugin/pl_player/controller.dart | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index aaded67d..465b3003 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -375,7 +375,13 @@ class PlPlayerController { } // 配置Player 音轨、字幕等等 _videoPlayerController = await _createVideoController( - dataSource, _looping, enableHA, width, height); + dataSource, + _looping, + enableHA, + width, + height, + seekTo, + ); // 获取视频时长 00:00 _duration.value = duration ?? _videoPlayerController!.state.duration; updateDurationSecond(); @@ -386,7 +392,7 @@ class PlPlayerController { if (!_listenersInitialized) { startListeners(); } - await _initializePlayer(seekTo: seekTo, duration: _duration.value); + await _initializePlayer(duration: _duration.value); bool autoEnterFullcreen = setting.get(SettingBoxKey.enableAutoEnter, defaultValue: false); if (autoEnterFullcreen && _isFirstTime) { @@ -406,6 +412,7 @@ class PlPlayerController { bool enableHA, double? width, double? height, + Duration? seekTo, ) async { // 每次配置时先移除监听 removeListeners(); @@ -488,7 +495,11 @@ class PlPlayerController { ); } player.open( - Media(dataSource.videoSource!, httpHeaders: dataSource.httpHeaders), + Media( + dataSource.videoSource!, + httpHeaders: dataSource.httpHeaders, + start: seekTo ?? Duration.zero, + ), play: false, ); // 音轨 @@ -501,7 +512,6 @@ class PlPlayerController { // 开始播放 Future _initializePlayer({ - Duration seekTo = Duration.zero, Duration? duration, }) async { // 设置倍速 @@ -519,11 +529,6 @@ class PlPlayerController { // await setLooping(_looping); // } - // 跳转播放 - if (seekTo != Duration.zero) { - await this.seekTo(seekTo); - } - // 自动播放 if (_autoPlay) { await play(duration: duration); @@ -637,21 +642,14 @@ class PlPlayerController { await _videoPlayerController?.stream.buffer.first; } await _videoPlayerController?.seek(position); - // if (playerStatus.stopped) { - // play(); - // } } else { print('seek duration else'); _timerForSeek?.cancel(); _timerForSeek = Timer.periodic(const Duration(milliseconds: 200), (Timer t) async { - //_timerForSeek = null; if (duration.value.inSeconds != 0) { await _videoPlayerController!.stream.buffer.first; await _videoPlayerController?.seek(position); - // if (playerStatus.status.value == PlayerStatus.paused) { - // play(); - // } t.cancel(); _timerForSeek = null; } From 53b72bec2543218e638bb62447ec9502c1311765 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 24 Mar 2024 13:16:13 +0800 Subject: [PATCH 004/106] =?UTF-8?q?mod:=20read=20schame=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Podfile.lock | 13 +++++++------ lib/common/widgets/network_img_layer.dart | 2 +- lib/utils/app_scheme.dart | 18 ++++++++++++++++-- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8db59815..2c1a635b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -9,6 +9,7 @@ PODS: - Flutter - connectivity_plus (0.0.1): - Flutter + - FlutterMacOS - ReachabilitySwift - device_info_plus (0.0.1): - Flutter @@ -38,7 +39,7 @@ PODS: - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - - permission_handler_apple (9.1.1): + - permission_handler_apple (9.3.0): - Flutter - ReachabilitySwift (5.0.0) - saver_gallery (0.0.1): @@ -71,7 +72,7 @@ DEPENDENCIES: - audio_service (from `.symlinks/plugins/audio_service/ios`) - audio_session (from `.symlinks/plugins/audio_session/ios`) - auto_orientation (from `.symlinks/plugins/auto_orientation/ios`) - - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`) + - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`) - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - Flutter (from `Flutter`) - flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`) @@ -113,7 +114,7 @@ EXTERNAL SOURCES: auto_orientation: :path: ".symlinks/plugins/auto_orientation/ios" connectivity_plus: - :path: ".symlinks/plugins/connectivity_plus/ios" + :path: ".symlinks/plugins/connectivity_plus/darwin" device_info_plus: :path: ".symlinks/plugins/device_info_plus/ios" Flutter: @@ -166,7 +167,7 @@ SPEC CHECKSUMS: audio_service: f509d65da41b9521a61f1c404dd58651f265a567 audio_session: 4f3e461722055d21515cf3261b64c973c062f345 auto_orientation: 102ed811a5938d52c86520ddd7ecd3a126b5d39d - connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a + connectivity_plus: e2dad488011aeb593e219360e804c43cc1af5770 device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 @@ -180,7 +181,7 @@ SPEC CHECKSUMS: media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 + permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 saver_gallery: 2b4e584106fde2407ab51560f3851564963e6b78 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 @@ -193,7 +194,7 @@ SPEC CHECKSUMS: volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9 wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 webview_cookie_manager: eaf920722b493bd0f7611b5484771ca53fed03f7 - webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a + webview_flutter_wkwebview: 4f3e50f7273d31e5500066ed267e3ae4309c5ae4 PODFILE CHECKSUM: 637cd290bed23275b5f5ffcc7eb1e73d0a5fb2be diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 06c35974..173db853 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -36,7 +36,7 @@ class NetworkImgLayer extends StatelessWidget { final int defaultImgQuality = GlobalData().imgQuality; final String imageUrl = '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp'; - print(imageUrl); + // print(imageUrl); int? memCacheWidth, memCacheHeight; double aspectRatio = (width / height).toDouble(); diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index bb9d556f..ffe90e35 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -20,7 +20,7 @@ class PiliSchame { /// 完整链接进入 b23.无效 appScheme.getLatestScheme().then((SchemeEntity? value) { if (value != null) { - _fullPathPush(value); + _routePush(value); } }); @@ -37,7 +37,6 @@ class PiliSchame { final String scheme = value.scheme; final String host = value.host; final String path = value.path; - if (scheme == 'bilibili') { if (host == 'root') { Navigator.popUntil( @@ -85,6 +84,14 @@ class PiliSchame { } } else if (host == 'search') { Get.toNamed('/searchResult', parameters: {'keyword': ''}); + } else if (host == 'article') { + final String id = path.split('/').last.split('?').first; + Get.toNamed('/htmlRender', parameters: { + 'url': 'https://www.bilibili.com/read/cv$id', + 'title': 'cv$id', + 'id': 'cv$id', + 'dynamicType': 'read' + }); } } if (scheme == 'https') { @@ -226,6 +233,13 @@ class PiliSchame { break; case 'read': print('专栏'); + String id = 'cv${matchNum(query!['id']!).first}'; + Get.toNamed('/htmlRender', parameters: { + 'url': value.dataString!, + 'title': '', + 'id': id, + 'dynamicType': 'read' + }); break; case 'space': print('个人空间'); From fcd7781789a1f53fc7ab7f80af85c60675103a68 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 20 Apr 2024 00:55:18 +0800 Subject: [PATCH 005/106] =?UTF-8?q?feat:=20=E6=94=B6=E8=97=8F=E5=A4=B9?= =?UTF-8?q?=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 3 +++ lib/http/user.dart | 17 ++++++++++++ lib/pages/fav/controller.dart | 13 +++++++++- lib/pages/fav/view.dart | 5 ++-- lib/pages/fav/widgets/item.dart | 18 +++++++------ lib/pages/fav_detail/controller.dart | 39 ++++++++++++++++++++++++++++ lib/pages/fav_detail/view.dart | 18 +++++++++---- 7 files changed, 96 insertions(+), 17 deletions(-) diff --git a/lib/http/api.dart b/lib/http/api.dart index b6975c4b..ad314acf 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -511,4 +511,7 @@ class Api { /// 取消订阅 static const String cancelSub = '/x/v3/fav/season/unfav'; + + /// 删除收藏夹 + static const String delFavFolder = '/x/v3/fav/folder/del'; } diff --git a/lib/http/user.dart b/lib/http/user.dart index fea0a22e..dfdf187e 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -395,4 +395,21 @@ class UserHttp { return {'status': false, 'msg': res.data['message']}; } } + + // 删除文件夹 + static Future delFavFolder({required int mediaIds}) async { + var res = await Request().post( + Api.delFavFolder, + queryParameters: { + 'media_ids': mediaIds, + 'platform': 'web', + 'csrf': await Request.getCsrf(), + }, + ); + if (res.data['code'] == 0) { + return {'status': true}; + } else { + return {'status': false, 'msg': res.data['message']}; + } + } } diff --git a/lib/pages/fav/controller.dart b/lib/pages/fav/controller.dart index 6ff0afc8..2307d303 100644 --- a/lib/pages/fav/controller.dart +++ b/lib/pages/fav/controller.dart @@ -10,6 +10,7 @@ import 'package:pilipala/utils/storage.dart'; class FavController extends GetxController { final ScrollController scrollController = ScrollController(); Rx favFolderData = FavFolderData().obs; + RxList favFolderList = [].obs; Box userInfoCache = GStrorage.userInfo; UserInfoData? userInfo; int currentPage = 1; @@ -32,9 +33,10 @@ class FavController extends GetxController { if (res['status']) { if (type == 'init') { favFolderData.value = res['data']; + favFolderList.value = res['data'].list; } else { if (res['data'].list.isNotEmpty) { - favFolderData.value.list!.addAll(res['data'].list); + favFolderList.addAll(res['data'].list); favFolderData.update((val) {}); } } @@ -49,4 +51,13 @@ class FavController extends GetxController { Future onLoad() async { queryFavFolder(type: 'onload'); } + + removeFavFolder({required int mediaIds}) async { + for (var i in favFolderList) { + if (i.id == mediaIds) { + favFolderList.remove(i); + break; + } + } + } } diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index b980914a..424a885d 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -62,11 +62,10 @@ class _FavPageState extends State { return Obx( () => ListView.builder( controller: scrollController, - itemCount: _favController.favFolderData.value.list!.length, + itemCount: _favController.favFolderList.length, itemBuilder: (context, index) { return FavItem( - favFolderItem: - _favController.favFolderData.value.list![index]); + favFolderItem: _favController.favFolderList[index]); }, ), ); diff --git a/lib/pages/fav/widgets/item.dart b/lib/pages/fav/widgets/item.dart index 08730d7b..3c44ec9d 100644 --- a/lib/pages/fav/widgets/item.dart +++ b/lib/pages/fav/widgets/item.dart @@ -13,14 +13,16 @@ class FavItem extends StatelessWidget { Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(favFolderItem.fid); return InkWell( - onTap: () => Get.toNamed( - '/favDetail', - arguments: favFolderItem, - parameters: { - 'heroTag': heroTag, - 'mediaId': favFolderItem.id.toString(), - }, - ), + onTap: () async { + Get.toNamed( + '/favDetail', + arguments: favFolderItem, + parameters: { + 'heroTag': heroTag, + 'mediaId': favFolderItem.id.toString(), + }, + ); + }, child: Padding( padding: const EdgeInsets.fromLTRB(12, 7, 12, 7), child: LayoutBuilder( diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 55d5b884..7af398e8 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -1,9 +1,11 @@ +import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/user/fav_detail.dart'; import 'package:pilipala/models/user/fav_folder.dart'; +import 'package:pilipala/pages/fav/index.dart'; class FavDetailController extends GetxController { FavFolderItemData? item; @@ -74,4 +76,41 @@ class FavDetailController extends GetxController { onLoad() { queryUserFavFolderDetail(type: 'onLoad'); } + + onDelFavFolder() async { + SmartDialog.show( + useSystem: true, + animationType: SmartAnimationType.centerFade_otherSlide, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('提示'), + content: const Text('确定删除这个收藏夹吗?'), + actions: [ + TextButton( + onPressed: () async { + SmartDialog.dismiss(); + }, + child: Text( + '点错了', + style: TextStyle(color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () async { + var res = await UserHttp.delFavFolder(mediaIds: mediaId!); + SmartDialog.dismiss(); + SmartDialog.showToast(res['status'] ? '操作成功' : res['msg']); + if (res['status']) { + FavController favController = Get.find(); + await favController.removeFavFolder(mediaIds: mediaId!); + Get.back(); + } + }, + child: const Text('确认'), + ) + ], + ); + }, + ); + } } diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index 74faa829..5f2d92af 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -100,11 +100,19 @@ class _FavDetailPageState extends State { Get.toNamed('/favSearch?searchType=0&mediaId=$mediaId'), icon: const Icon(Icons.search_outlined), ), - // IconButton( - // onPressed: () {}, - // icon: const Icon(Icons.more_vert), - // ), - const SizedBox(width: 6), + PopupMenuButton( + icon: const Icon(Icons.more_vert_outlined), + position: PopupMenuPosition.under, + onSelected: (String type) {}, + itemBuilder: (BuildContext context) => >[ + PopupMenuItem( + onTap: () => _favDetailController.onDelFavFolder(), + value: 'pause', + child: const Text('删除收藏夹'), + ), + ], + ), + const SizedBox(width: 14), ], flexibleSpace: FlexibleSpaceBar( background: Container( From 22d8cf12a0db7d7002abbddbdffe18d7e5d28e5f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 21 Apr 2024 15:52:16 +0800 Subject: [PATCH 006/106] opt: forward panel --- lib/pages/dynamics/widgets/action_panel.dart | 264 ++++++++++++------ lib/pages/dynamics/widgets/dynamic_panel.dart | 9 +- lib/pages/member_dynamics/view.dart | 4 +- 3 files changed, 181 insertions(+), 96 deletions(-) diff --git a/lib/pages/dynamics/widgets/action_panel.dart b/lib/pages/dynamics/widgets/action_panel.dart index 0e67b0a7..e94757ab 100644 --- a/lib/pages/dynamics/widgets/action_panel.dart +++ b/lib/pages/dynamics/widgets/action_panel.dart @@ -14,10 +14,10 @@ import 'rich_node_panel.dart'; class ActionPanel extends StatefulWidget { const ActionPanel({ super.key, - this.item, + required this.item, }); // ignore: prefer_typing_uninitialized_variables - final item; + final DynamicItemModel item; @override State createState() => _ActionPanelState(); @@ -28,7 +28,8 @@ class _ActionPanelState extends State final DynamicsController _dynamicsController = Get.put(DynamicsController()); late ModuleStatModel stat; bool isProcessing = false; - RxDouble height = (310.0).obs; + double defaultHeight = 260; + RxDouble height = 0.0.obs; RxBool isExpand = false.obs; late double statusHeight; TextEditingController _inputController = TextEditingController(); @@ -48,7 +49,7 @@ class _ActionPanelState extends State @override void initState() { super.initState(); - stat = widget.item!.modules.moduleStat; + stat = widget.item.modules!.moduleStat!; onInit(); } @@ -62,7 +63,7 @@ class _ActionPanelState extends State var item = widget.item!; String dynamicId = item.idStr!; // 1 已点赞 2 不喜欢 0 未操作 - Like like = item.modules.moduleStat.like; + Like like = item.modules!.moduleStat!.like!; int count = like.count == '点赞' ? 0 : int.parse(like.count ?? '0'); bool status = like.status!; int up = status ? 2 : 1; @@ -70,15 +71,15 @@ class _ActionPanelState extends State if (res['status']) { SmartDialog.showToast(!status ? '点赞成功' : '取消赞'); if (up == 1) { - item.modules.moduleStat.like.count = (count + 1).toString(); - item.modules.moduleStat.like.status = true; + item.modules!.moduleStat!.like!.count = (count + 1).toString(); + item.modules!.moduleStat!.like!.status = true; } else { if (count == 1) { - item.modules.moduleStat.like.count = '点赞'; + item.modules!.moduleStat!.like!.count = '点赞'; } else { - item.modules.moduleStat.like.count = (count - 1).toString(); + item.modules!.moduleStat!.like!.count = (count - 1).toString(); } - item.modules.moduleStat.like.status = false; + item.modules!.moduleStat!.like!.status = false; } setState(() {}); } else { @@ -88,50 +89,134 @@ class _ActionPanelState extends State // 转发动态预览 Widget dynamicPreview() { - return Padding( - padding: const EdgeInsets.fromLTRB(12, 0, 14, 12), - child: Container( - width: double.infinity, - decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.secondaryContainer.withOpacity(0.4), - borderRadius: BorderRadius.circular(12), + ItemModulesModel? modules = widget.item.modules; + final String type = widget.item.type!; + String? cover = modules?.moduleAuthor?.face; + switch (type) { + /// 图文动态 + case 'DYNAMIC_TYPE_DRAW': + cover = modules?.moduleDynamic?.major?.opus?.pics?.first.url; + + /// 投稿 + case 'DYNAMIC_TYPE_AV': + cover = modules?.moduleDynamic?.major?.archive?.cover; + + /// 转发的动态 + case 'DYNAMIC_TYPE_FORWARD': + String forwardType = widget.item.orig!.type!; + switch (forwardType) { + /// 图文动态 + case 'DYNAMIC_TYPE_DRAW': + cover = modules?.moduleDynamic?.major?.opus?.pics?.first.url; + + /// 投稿 + case 'DYNAMIC_TYPE_AV': + cover = modules?.moduleDynamic?.major?.archive?.cover; + + /// 专栏文章 + case 'DYNAMIC_TYPE_ARTICLE': + cover = ''; + + /// 番剧 + case 'DYNAMIC_TYPE_PGC': + cover = ''; + + /// 纯文字动态 + case 'DYNAMIC_TYPE_WORD': + cover = ''; + + /// 直播 + case 'DYNAMIC_TYPE_LIVE_RCMD': + cover = ''; + + /// 合集查看 + case 'DYNAMIC_TYPE_UGC_SEASON': + cover = ''; + + /// 番剧 + case 'DYNAMIC_TYPE_PGC_UNION': + cover = modules?.moduleDynamic?.major?.pgc?.cover; + + default: + cover = ''; + } + + /// 专栏文章 + case 'DYNAMIC_TYPE_ARTICLE': + cover = ''; + + /// 番剧 + case 'DYNAMIC_TYPE_PGC': + cover = ''; + + /// 纯文字动态 + case 'DYNAMIC_TYPE_WORD': + cover = ''; + + /// 直播 + case 'DYNAMIC_TYPE_LIVE_RCMD': + cover = ''; + + /// 合集查看 + case 'DYNAMIC_TYPE_UGC_SEASON': + cover = ''; + + /// 番剧查看 + case 'DYNAMIC_TYPE_PGC_UNION': + cover = ''; + + default: + cover = ''; + } + return Container( + width: double.infinity, + height: 95, + margin: const EdgeInsets.fromLTRB(12, 0, 12, 14), + decoration: BoxDecoration( + color: + Theme.of(context).colorScheme.secondaryContainer.withOpacity(0.4), + borderRadius: BorderRadius.circular(6), + border: Border( + left: BorderSide( + width: 4, + color: Theme.of(context).colorScheme.primary.withOpacity(0.8)), ), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + ), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '@${widget.item.modules!.moduleAuthor!.name}', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + ), + const SizedBox(height: 8), + Row( children: [ - Text( - '@${widget.item.modules.moduleAuthor.name}', - style: TextStyle( - color: Theme.of(context).colorScheme.primary, + NetworkImgLayer( + src: cover ?? '', + width: 34, + height: 34, + type: 'emote', + ), + const SizedBox(width: 10), + Expanded( + child: Text.rich( + style: const TextStyle(height: 0), + richNode(widget.item, context), + maxLines: 2, + overflow: TextOverflow.ellipsis, ), ), - const SizedBox(height: 6), - Row( - children: [ - NetworkImgLayer( - src: widget.item.modules.moduleAuthor.face, - width: 34, - height: 34, - type: 'emote', - ), - const SizedBox(width: 10), - Expanded( - child: Text.rich( - style: const TextStyle(height: 0), - richNode(widget.item, context), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - // Text(data) - ], - ) + // Text(data) ], - )), + ) + ], + ), ), ); } @@ -149,56 +234,54 @@ class _ActionPanelState extends State duration: Durations.medium1, onEnd: () async { if (isExpand.value) { - await Future.delayed(const Duration(milliseconds: 120)); + await Future.delayed(const Duration(milliseconds: 80)); myFocusNode.requestFocus(); } }, - height: height.value, + height: height.value + MediaQuery.of(context).padding.bottom, child: Column( - mainAxisSize: MainAxisSize.min, children: [ AnimatedContainer( duration: Durations.medium1, height: isExpand.value ? statusHeight : 0, ), Padding( - padding: const EdgeInsets.fromLTRB(16, 10, 12, 0), + padding: EdgeInsets.fromLTRB( + isExpand.value ? 10 : 16, + 10, + isExpand.value ? 14 : 12, + 0, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - AnimatedSwitcher( - duration: Durations.medium1, - transitionBuilder: - (Widget child, Animation animation) { - return ScaleTransition( - scale: animation, child: child); - }, - child: isExpand.value - ? IconButton( - onPressed: () => togglePanelState(false), - icon: const Icon(Icons.close)) - : const Text( - '转发动态', - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - AnimatedSwitcher( - duration: Durations.medium1, - transitionBuilder: - (Widget child, Animation animation) { - return ScaleTransition( - scale: animation, child: child); - }, - child: isExpand.value - ? FilledButton( - onPressed: () => dynamicForward('forward'), - child: const Text('转发'), - ) - : TextButton( - onPressed: () {}, - child: const Text('立即转发'), - ), - ), + if (isExpand.value) ...[ + IconButton( + onPressed: () => togglePanelState(false), + icon: const Icon(Icons.close), + ), + Text( + '转发动态', + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith(fontWeight: FontWeight.bold), + ) + ] else ...[ + const Text( + '转发动态', + style: TextStyle(fontWeight: FontWeight.bold), + ) + ], + isExpand.value + ? FilledButton( + onPressed: () => dynamicForward('forward'), + child: const Text('转发'), + ) + : TextButton( + onPressed: () {}, + child: const Text('立即转发'), + ) ], ), ), @@ -209,7 +292,7 @@ class _ActionPanelState extends State child: Container( width: double.infinity, alignment: Alignment.centerLeft, - padding: const EdgeInsets.fromLTRB(16, 0, 10, 15), + padding: const EdgeInsets.fromLTRB(16, 0, 10, 14), child: Text( '说点什么吧', textAlign: TextAlign.start, @@ -251,9 +334,6 @@ class _ActionPanelState extends State textAlign: TextAlign.center, ), ), - SizedBox( - height: MediaQuery.of(context).padding.bottom + 20, - ) ] ], ), @@ -266,7 +346,7 @@ class _ActionPanelState extends State togglePanelState(status) { if (!status) { Get.back(); - height.value = 310; + height.value = defaultHeight; _inputText = ''; _inputController.clear(); } else { @@ -298,6 +378,8 @@ class _ActionPanelState extends State Widget build(BuildContext context) { var color = Theme.of(context).colorScheme.outline; var primary = Theme.of(context).colorScheme.primary; + height.value = defaultHeight; + print('height.value: ${height.value}'); return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart index c85cad45..d273a1a6 100644 --- a/lib/pages/dynamics/widgets/dynamic_panel.dart +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/pages/dynamics/index.dart'; +import '../../../models/dynamics/result.dart'; import 'action_panel.dart'; import 'author_panel.dart'; import 'content_panel.dart'; import 'forward_panel.dart'; class DynamicPanel extends StatelessWidget { - final dynamic item; + final DynamicItemModel item; final String? source; - DynamicPanel({this.item, this.source, Key? key}) : super(key: key); + DynamicPanel({required this.item, this.source, Key? key}) : super(key: key); final DynamicsController _dynamicsController = Get.put(DynamicsController()); @override @@ -41,8 +42,8 @@ class DynamicPanel extends StatelessWidget { padding: const EdgeInsets.fromLTRB(12, 12, 12, 8), child: AuthorPanel(item: item), ), - if (item!.modules!.moduleDynamic!.desc != null || - item!.modules!.moduleDynamic!.major != null) + if (item.modules!.moduleDynamic!.desc != null || + item.modules!.moduleDynamic!.major != null) Content(item: item, source: source), forWard(item, context, _dynamicsController, source), const SizedBox(height: 2), diff --git a/lib/pages/member_dynamics/view.dart b/lib/pages/member_dynamics/view.dart index 68aa72d7..2e093bcc 100644 --- a/lib/pages/member_dynamics/view.dart +++ b/lib/pages/member_dynamics/view.dart @@ -5,6 +5,7 @@ import 'package:pilipala/pages/member_dynamics/index.dart'; import 'package:pilipala/utils/utils.dart'; import '../../common/widgets/http_error.dart'; +import '../../models/dynamics/result.dart'; import '../dynamics/widgets/dynamic_panel.dart'; class MemberDynamicsPage extends StatefulWidget { @@ -66,7 +67,8 @@ class _MemberDynamicsPageState extends State { if (snapshot.connectionState == ConnectionState.done) { if (snapshot.data != null) { Map data = snapshot.data as Map; - List list = _memberDynamicController.dynamicsList; + RxList list = + _memberDynamicController.dynamicsList; if (data['status']) { return Obx( () => list.isNotEmpty From 9dc7256a005247cb24b112d4850bc70b19ec9734 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 21 Apr 2024 16:47:38 +0800 Subject: [PATCH 007/106] =?UTF-8?q?feat:=20=E6=8A=95=E7=A8=BF=E7=95=AA?= =?UTF-8?q?=E5=89=A7=E8=AF=84=E8=AE=BA=E6=97=B6=E8=BD=AC=E5=8F=91=E5=88=B0?= =?UTF-8?q?=E5=8A=A8=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/dynamics.dart | 22 +++++++-- lib/pages/dynamics/widgets/action_panel.dart | 1 + lib/pages/video/detail/reply_new/view.dart | 50 ++++++++++++++++++-- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/lib/http/dynamics.dart b/lib/http/dynamics.dart index f0740d36..63dea4ff 100644 --- a/lib/http/dynamics.dart +++ b/lib/http/dynamics.dart @@ -152,16 +152,28 @@ class DynamicsHttp { } static Future dynamicCreate({ - required String dynIdStr, required int mid, + required int scene, + int? oid, + String? dynIdStr, String? rawText, }) async { DateTime now = DateTime.now(); int timestamp = now.millisecondsSinceEpoch ~/ 1000; Random random = Random(); int randomNumber = random.nextInt(9000) + 1000; - String uploadId = - mid.toString() + timestamp.toString() + randomNumber.toString(); + String uploadId = '${mid}_${timestamp}_$randomNumber'; + + Map webRepostSrc = { + 'dyn_id_str': dynIdStr ?? '', + }; + + /// 投稿转发 + if (scene == 5) { + webRepostSrc = { + 'revs_id': {'dyn_type': 8, 'rid': oid} + }; + } var res = await Request().post(Api.dynamicCreate, queryParameters: { 'platform': 'web', 'csrf': await Request.getCsrf(), @@ -174,14 +186,14 @@ class DynamicsHttp { {'raw_text': rawText ?? '', 'type': 1, 'biz_id': ''} ] }, - 'scene': 4, + 'scene': scene, 'attach_card': null, 'upload_id': uploadId, 'meta': { 'app_meta': {'from': 'create.dynamic.web', 'mobi_app': 'web'} } }, - 'web_repost_src': {'dyn_id_str': dynIdStr} + 'web_repost_src': webRepostSrc }); if (res.data['code'] == 0) { return { diff --git a/lib/pages/dynamics/widgets/action_panel.dart b/lib/pages/dynamics/widgets/action_panel.dart index e94757ab..51ef3952 100644 --- a/lib/pages/dynamics/widgets/action_panel.dart +++ b/lib/pages/dynamics/widgets/action_panel.dart @@ -361,6 +361,7 @@ class _ActionPanelState extends State dynIdStr: dynamicId, mid: _dynamicsController.userInfo.mid, rawText: _inputText, + scene: 4, ); if (res['status']) { SmartDialog.showToast(type == 'forward' ? '转发成功' : '发布成功'); diff --git a/lib/pages/video/detail/reply_new/view.dart b/lib/pages/video/detail/reply_new/view.dart index a94b6071..029e015a 100644 --- a/lib/pages/video/detail/reply_new/view.dart +++ b/lib/pages/video/detail/reply_new/view.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/http/dynamics.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/common/reply_type.dart'; import 'package:pilipala/models/video/reply/emote.dart'; @@ -40,6 +41,8 @@ class _VideoReplyNewDialogState extends State double keyboardHeight = 0.0; // 键盘高度 final _debouncer = Debouncer(milliseconds: 200); // 设置延迟时间 String toolbarType = 'input'; + RxBool isForward = false.obs; + RxBool showForward = false.obs; @override void initState() { @@ -52,6 +55,10 @@ class _VideoReplyNewDialogState extends State _autoFocus(); // 监听聚焦状态 _focuslistener(); + final String routePath = Get.currentRoute; + if (routePath.startsWith('/video')) { + showForward.value = true; + } } _autoFocus() async { @@ -88,6 +95,16 @@ class _VideoReplyNewDialogState extends State Get.back(result: { 'data': ReplyItemModel.fromJson(result['data']['reply'], ''), }); + + /// 投稿、番剧页面 + if (isForward.value) { + await DynamicsHttp.dynamicCreate( + mid: 0, + rawText: message, + oid: widget.oid!, + scene: 5, + ); + } } else { SmartDialog.showToast(result['msg']); } @@ -145,7 +162,6 @@ class _VideoReplyNewDialogState extends State double _keyboardHeight = EdgeInsets.fromViewPadding( View.of(context).viewInsets, View.of(context).devicePixelRatio) .bottom; - print('_keyboardHeight: $_keyboardHeight'); return Container( clipBehavior: Clip.hardEdge, decoration: BoxDecoration( @@ -225,9 +241,37 @@ class _VideoReplyNewDialogState extends State toolbarType: toolbarType, selected: toolbarType == 'emote', ), + const SizedBox(width: 6), + Obx( + () => showForward.value + ? TextButton.icon( + onPressed: () { + isForward.value = !isForward.value; + }, + icon: Icon( + isForward.value + ? Icons.check_box + : Icons.check_box_outline_blank, + size: 22), + label: const Text('转发到动态'), + style: ButtonStyle( + foregroundColor: MaterialStateProperty.all( + isForward.value + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ), + ), + ) + : const SizedBox(), + ), const Spacer(), - TextButton( - onPressed: () => submitReplyAdd(), child: const Text('发送')) + SizedBox( + height: 36, + child: FilledButton( + onPressed: () => submitReplyAdd(), + child: const Text('发送'), + ), + ), ], ), ), From c42ce2f1f96c797237b4fca38690d5fae2053810 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 21 Apr 2024 17:38:07 +0800 Subject: [PATCH 008/106] =?UTF-8?q?mod:=20=E7=95=AA=E5=89=A7=E4=BC=A0?= =?UTF-8?q?=E9=80=92aid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/bangumi/introduction/controller.dart | 1 + lib/pages/bangumi/widgets/bangumi_panel.dart | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 2098302d..b26028cf 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -236,6 +236,7 @@ class BangumiIntroController extends GetxController { videoDetailCtr.bvid = bvid; videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; + videoDetailCtr.oid.value = aid; videoDetailCtr.queryVideoUrl(); // 重新请求评论 try { diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index b01f3be7..3e965f34 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -85,7 +85,9 @@ class _BangumiPanelState extends State { item.cid, item.aid, ); - _bottomSheetController?.close(); + if (_bottomSheetController != null) { + _bottomSheetController?.close(); + } currentIndex = i; scrollToIndex(); } From b83ac38c6099a6cadf9a38f7542ccc5c24706cad Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 21 Apr 2024 19:25:42 +0800 Subject: [PATCH 009/106] =?UTF-8?q?mod:=20scheme=20=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/app_scheme.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index ffe90e35..9009df6f 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -162,9 +162,14 @@ class PiliSchame { final String host = value.host!; final String? path = value.path; Map? query = value.query; - RegExp regExp = RegExp(r'^(www\.)?m?\.(bilibili\.com)$'); + RegExp regExp = RegExp(r'^((www\.)|(m\.))?bilibili\.com$'); if (regExp.hasMatch(host)) { - print('bilibili.com'); + print('bilibili.com host: $host'); + print('bilibili.com path: $path'); + final String lastPathSegment = path!.split('/').last; + if (lastPathSegment.contains('BV')) { + _videoPush(null, lastPathSegment); + } } else if (host.contains('live')) { int roomId = int.parse(path!.split('/').last); Get.toNamed( From 935073ce756ef21a8f07d2ec6d338742fff54a8b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 22 Apr 2024 23:51:31 +0800 Subject: [PATCH 010/106] =?UTF-8?q?mod:=20=E8=A7=86=E9=A2=91=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E9=A1=B5=E5=B8=83=E5=B1=80=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/view.dart | 335 +++++++++++++++---------------- 1 file changed, 166 insertions(+), 169 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 0152a2cb..f216fbcf 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -23,6 +23,7 @@ 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/storage.dart'; +import 'package:status_bar_control/status_bar_control.dart'; import '../../../plugin/pl_player/models/bottom_control_type.dart'; import '../../../services/shutdown_timer_service.dart'; @@ -61,10 +62,12 @@ class _VideoDetailPageState extends State late bool autoPiP; late Floating floating; bool isShowing = true; + late double statusHeight; @override void initState() { super.initState(); + getStatusHeight(); heroTag = Get.arguments['heroTag']; vdCtr = Get.put(VideoDetailController(), tag: heroTag); vdCtr.sheetHeight.value = localCache.get('sheetHeight'); @@ -203,6 +206,10 @@ class _VideoDetailPageState extends State }); } + getStatusHeight() async { + statusHeight = await StatusBarControl.getHeight; + } + @override void dispose() { shutdownTimerService.handleWaitingFinished(); @@ -281,6 +288,143 @@ class _VideoDetailPageState extends State } } + /// 手动播放 + Widget handlePlayPanel() { + return Stack( + children: [ + GestureDetector( + onTap: handlePlay, + child: Image.network( + vdCtr.videoItem['pic'], + width: Get.width, + height: videoHeight, + fit: BoxFit.cover, // 适应方式根据需要调整 + ), + ), + buildCustomAppBar(), + Positioned( + right: 12, + bottom: 10, + child: GestureDetector( + onTap: handlePlay, + child: Image.asset( + 'assets/images/play.png', + width: 60, + height: 60, + ), + ), + ), + ], + ); + } + + /// tabbar + Widget tabbarBuild() { + return Container( + width: double.infinity, + height: 45, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: Theme.of(context).dividerColor.withOpacity(0.1), + ), + ), + ), + child: Material( + child: Row( + children: [ + Expanded( + child: Obx( + () => TabBar( + padding: EdgeInsets.zero, + controller: vdCtr.tabCtr, + labelStyle: const TextStyle(fontSize: 13), + labelPadding: const EdgeInsets.symmetric(horizontal: 10.0), + dividerColor: Colors.transparent, + tabs: + vdCtr.tabs.map((String name) => Tab(text: name)).toList(), + ), + ), + ), + Flexible( + flex: 1, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Obx(() => AnimatedOpacity( + opacity: playerStatus.value != PlayerStatus.playing + ? 1 + : 0, + duration: const Duration(milliseconds: 100), + child: const Icon( + Icons.drag_handle_rounded, + size: 20, + color: Colors.grey, + ), + )), + const SizedBox(width: 8), + SizedBox( + height: 32, + child: TextButton( + style: ButtonStyle( + padding: MaterialStateProperty.all(EdgeInsets.zero), + ), + onPressed: () => vdCtr.showShootDanmakuSheet(), + child: + const Text('发弹幕', style: TextStyle(fontSize: 12)), + ), + ), + SizedBox( + width: 38, + height: 38, + child: Obx( + () => !vdCtr.isShowCover.value + ? IconButton( + onPressed: () { + plPlayerController?.isOpenDanmu.value = + !(plPlayerController?.isOpenDanmu.value ?? + false); + }, + icon: !(plPlayerController?.isOpenDanmu.value ?? + false) + ? SvgPicture.asset( + 'assets/images/video/danmu_close.svg', + // ignore: deprecated_member_use + color: Theme.of(context) + .colorScheme + .outline, + ) + : SvgPicture.asset( + 'assets/images/video/danmu_open.svg', + // ignore: deprecated_member_use + color: Theme.of(context) + .colorScheme + .primary, + ), + ) + : IconButton( + icon: SvgPicture.asset( + 'assets/images/video/danmu_close.svg', + // ignore: deprecated_member_use + color: Theme.of(context).colorScheme.outline, + ), + onPressed: () {}, + ), + ), + ), + const SizedBox(width: 18), + ], + ), + ), + ), + ], + ), + ), + ); + } + @override Widget build(BuildContext context) { final sizeContext = MediaQuery.sizeOf(context); @@ -338,162 +482,13 @@ class _VideoDetailPageState extends State }, ); - /// tabbar - Widget tabbarBuild = Container( - width: double.infinity, - height: 45, - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - width: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), - ), - ), - ), - child: Material( - child: Row( - children: [ - Flexible( - flex: 1, - child: Obx( - () => TabBar( - padding: EdgeInsets.zero, - controller: vdCtr.tabCtr, - labelStyle: const TextStyle(fontSize: 13), - labelPadding: - const EdgeInsets.symmetric(horizontal: 10.0), // 设置每个标签的宽度 - dividerColor: Colors.transparent, - tabs: vdCtr.tabs - .map( - (String name) => Tab(text: name), - ) - .toList(), - ), - ), - ), - Flexible( - flex: 1, - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Obx(() => AnimatedOpacity( - opacity: playerStatus.value != PlayerStatus.playing - ? 1 - : 0, - duration: const Duration(milliseconds: 100), - child: const Icon( - Icons.drag_handle_rounded, - size: 20, - color: Colors.grey, - ), - )), - const SizedBox(width: 8), - SizedBox( - height: 32, - child: TextButton( - style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - ), - onPressed: () => vdCtr.showShootDanmakuSheet(), - child: - const Text('发弹幕', style: TextStyle(fontSize: 12)), - ), - ), - SizedBox( - width: 38, - height: 38, - child: Obx( - () => !vdCtr.isShowCover.value - ? IconButton( - onPressed: () { - plPlayerController?.isOpenDanmu.value = - !(plPlayerController - ?.isOpenDanmu.value ?? - false); - }, - icon: - !(plPlayerController?.isOpenDanmu.value ?? - false) - ? SvgPicture.asset( - 'assets/images/video/danmu_close.svg', - // ignore: deprecated_member_use - color: Theme.of(context) - .colorScheme - .outline, - ) - : SvgPicture.asset( - 'assets/images/video/danmu_open.svg', - // ignore: deprecated_member_use - color: Theme.of(context) - .colorScheme - .primary, - ), - ) - : IconButton( - icon: SvgPicture.asset( - 'assets/images/video/danmu_close.svg', - // ignore: deprecated_member_use - color: - Theme.of(context).colorScheme.outline, - ), - onPressed: () {}, - ), - ), - ), - const SizedBox(width: 18), - ], - ), - )), - ], - ), - ), - ); - - /// 手动播放 - Widget handlePlayPanel() { - return Stack( - children: [ - GestureDetector( - onTap: () { - handlePlay(); - }, - child: NetworkImgLayer( - type: 'emote', - src: vdCtr.videoItem['pic'], - width: Get.width, - height: videoHeight.value, - ), - ), - Positioned( - top: 0, - left: 0, - right: 0, - child: buildCustomAppBar(), - ), - Positioned( - right: 12, - bottom: 10, - child: IconButton( - tooltip: '播放', - onPressed: () => handlePlay(), - icon: Image.asset( - 'assets/images/play.png', - width: 60, - height: 60, - )), - ), - ], - ); - } - Widget childWhenDisabled = SafeArea( top: MediaQuery.of(context).orientation == Orientation.portrait && plPlayerController?.isFullScreen.value == true, bottom: MediaQuery.of(context).orientation == Orientation.portrait && plPlayerController?.isFullScreen.value == true, - left: false, //plPlayerController?.isFullScreen.value != true, - right: false, //plPlayerController?.isFullScreen.value != true, + left: false, + right: false, child: Stack( children: [ Scaffold( @@ -511,12 +506,22 @@ class _VideoDetailPageState extends State controller: _extendNestCtr, headerSliverBuilder: (BuildContext context2, bool innerBoxIsScrolled) { + final Orientation orientation = + MediaQuery.of(context).orientation; + final bool isFullScreen = + plPlayerController?.isFullScreen.value == true; + final double expandedHeight = + orientation == Orientation.landscape || isFullScreen + ? (MediaQuery.sizeOf(context).height - + (orientation == Orientation.landscape + ? 0 + : MediaQuery.of(context).padding.top)) + : videoHeight.value; return [ Obx( () { - if (MediaQuery.of(context).orientation == - Orientation.landscape || - plPlayerController?.isFullScreen.value == true) { + if (orientation == Orientation.landscape || + isFullScreen) { enterFullScreen(); } else { exitFullScreen(); @@ -528,15 +533,7 @@ class _VideoDetailPageState extends State elevation: 0, scrolledUnderElevation: 0, forceElevated: innerBoxIsScrolled, - expandedHeight: MediaQuery.of(context).orientation == - Orientation.landscape || - plPlayerController?.isFullScreen.value == true - ? (MediaQuery.sizeOf(context).height - - (MediaQuery.of(context).orientation == - Orientation.landscape - ? 0 - : MediaQuery.of(context).padding.top)) - : videoHeight.value, + expandedHeight: expandedHeight, backgroundColor: Colors.black, flexibleSpace: FlexibleSpaceBar( background: PopScope( @@ -556,13 +553,13 @@ class _VideoDetailPageState extends State child: LayoutBuilder( builder: (BuildContext context, BoxConstraints boxConstraints) { - // final double maxWidth = - // boxConstraints.maxWidth; - // final double maxHeight = - // boxConstraints.maxHeight; return Stack( children: [ - if (isShowing) videoPlayerPanel, + if (isShowing) + Padding( + padding: EdgeInsets.only(top: 0), + child: videoPlayerPanel, + ), /// 关闭自动播放时 手动播放 Obx( @@ -604,7 +601,7 @@ class _VideoDetailPageState extends State color: Theme.of(context).colorScheme.background, child: Column( children: [ - tabbarBuild, + tabbarBuild(), Expanded( child: TabBarView( controller: vdCtr.tabCtr, From 926c99001ebd47b860073029419f3d93338ab346 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 22 Apr 2024 23:58:36 +0800 Subject: [PATCH 011/106] =?UTF-8?q?mod:=20=E8=A7=86=E9=A2=91=E7=AE=80?= =?UTF-8?q?=E4=BB=8B=E5=A2=9E=E5=8A=A0aid=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../introduction/widgets/intro_detail.dart | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/pages/video/detail/introduction/widgets/intro_detail.dart b/lib/pages/video/detail/introduction/widgets/intro_detail.dart index 1e9bb842..3ec92023 100644 --- a/lib/pages/video/detail/introduction/widgets/intro_detail.dart +++ b/lib/pages/video/detail/introduction/widgets/intro_detail.dart @@ -23,16 +23,34 @@ class IntroDetail extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); - SmartDialog.showToast('已复制'); - }, - child: Text( - videoDetail!.bvid!, - style: TextStyle( - fontSize: 13, color: Theme.of(context).colorScheme.primary), - ), + Row( + children: [ + GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); + SmartDialog.showToast('已复制'); + }, + child: Text( + videoDetail!.bvid!, + style: TextStyle( + fontSize: 13, + color: Theme.of(context).colorScheme.primary), + ), + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () { + Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); + SmartDialog.showToast('已复制'); + }, + child: Text( + videoDetail!.aid!.toString(), + style: TextStyle( + fontSize: 13, + color: Theme.of(context).colorScheme.primary), + ), + ) + ], ), const SizedBox(height: 4), Text.rich( From 31125435b11501e4236456e31541ab48aa996118 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 23 Apr 2024 23:40:40 +0800 Subject: [PATCH 012/106] =?UTF-8?q?opt:=20=E9=A6=96=E9=A1=B5=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E6=A0=8F=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/overlay_pop.dart | 1 + lib/common/widgets/video_card_v.dart | 283 +++++++++++---------------- lib/pages/home/view.dart | 87 ++++---- lib/pages/rcmd/view.dart | 20 -- 4 files changed, 160 insertions(+), 231 deletions(-) diff --git a/lib/common/widgets/overlay_pop.dart b/lib/common/widgets/overlay_pop.dart index fe9b9377..4f0a3899 100644 --- a/lib/common/widgets/overlay_pop.dart +++ b/lib/common/widgets/overlay_pop.dart @@ -62,6 +62,7 @@ class OverlayPop extends StatelessWidget { Expanded( child: Text( videoItem.title! as String, + style: Theme.of(context).textTheme.titleSmall, ), ), const SizedBox(width: 4), diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 0d96f7b7..0598f973 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.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 '../../models/model_rec_video_item.dart'; +import 'overlay_pop.dart'; import 'stat/danmu.dart'; import 'stat/view.dart'; import '../../http/dynamics.dart'; @@ -19,15 +20,15 @@ import 'network_img_layer.dart'; class VideoCardV extends StatelessWidget { final dynamic videoItem; final int crossAxisCount; - final Function()? longPress; - final Function()? longPressEnd; + // final Function()? longPress; + // final Function()? longPressEnd; const VideoCardV({ Key? key, required this.videoItem, required this.crossAxisCount, - this.longPress, - this.longPressEnd, + // this.longPress, + // this.longPressEnd, }) : super(key: key); bool isStringNumeric(String str) { @@ -131,59 +132,55 @@ class VideoCardV extends StatelessWidget { elevation: 0, clipBehavior: Clip.hardEdge, margin: EdgeInsets.zero, - child: GestureDetector( + child: InkWell( + onTap: () async => onPushDetail(heroTag), onLongPress: () { - if (longPress != null) { - longPress!(); - } + SmartDialog.show( + builder: (context) => OverlayPop( + videoItem: videoItem, + closeFn: () => SmartDialog.dismiss(), + ), + ); }, - // onLongPressEnd: (details) { - // if (longPressEnd != null) { - // longPressEnd!(); - // } - // }, - child: InkWell( - onTap: () async => onPushDetail(heroTag), - child: Column( - children: [ - AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder(builder: (context, boxConstraints) { - double maxWidth = boxConstraints.maxWidth; - double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: videoItem.pic, - width: maxWidth, - height: maxHeight, - ), + child: Column( + children: [ + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder(builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: videoItem.pic, + width: maxWidth, + height: maxHeight, ), - if (videoItem.duration > 0) - if (crossAxisCount == 1) ...[ - PBadge( - bottom: 10, - right: 10, - text: Utils.timeFormat(videoItem.duration), - ) - ] else ...[ - PBadge( - bottom: 6, - right: 7, - size: 'small', - type: 'gray', - text: Utils.timeFormat(videoItem.duration), - ) - ], - ], - ); - }), - ), - VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) - ], - ), + ), + if (videoItem.duration > 0) + if (crossAxisCount == 1) ...[ + PBadge( + bottom: 10, + right: 10, + text: Utils.timeFormat(videoItem.duration), + ) + ] else ...[ + PBadge( + bottom: 6, + right: 7, + size: 'small', + type: 'gray', + text: Utils.timeFormat(videoItem.duration), + ) + ], + ], + ); + }), + ), + VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) + ], ), ), ); @@ -196,122 +193,73 @@ class VideoContent extends StatelessWidget { const VideoContent( {Key? key, required this.videoItem, required this.crossAxisCount}) : super(key: key); + + Widget _buildBadge(String text, String type, [double fs = 12]) { + return PBadge( + text: text, + stack: 'normal', + size: 'small', + type: type, + fs: fs, + ); + } + @override Widget build(BuildContext context) { - return Expanded( - flex: crossAxisCount == 1 ? 0 : 1, - child: Padding( - padding: crossAxisCount == 1 - ? const EdgeInsets.fromLTRB(9, 9, 9, 4) - : const EdgeInsets.fromLTRB(5, 8, 5, 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Expanded( - child: Text( - videoItem.title, - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - ), - if (videoItem.goto == 'av' && crossAxisCount == 1) ...[ - const SizedBox(width: 10), - VideoPopupMenu( - size: 32, - iconSize: 18, - videoItem: videoItem, - ), - ], - ], - ), - if (crossAxisCount > 1) ...[ - const SizedBox(height: 2), - VideoStat( - videoItem: videoItem, - crossAxisCount: crossAxisCount, - ), - ], - if (crossAxisCount == 1) const SizedBox(height: 4), - Row( - children: [ - if (videoItem.goto == 'bangumi') ...[ - PBadge( - text: videoItem.bangumiBadge, - stack: 'normal', - size: 'small', - type: 'line', - fs: 9, - ) - ], - if (videoItem.rcmdReason != null && - videoItem.rcmdReason.content != '') ...[ - PBadge( - text: videoItem.rcmdReason.content, - stack: 'normal', - size: 'small', - type: 'color', - ) - ], - if (videoItem.goto == 'picture') ...[ - const PBadge( - text: '动态', - stack: 'normal', - size: 'small', - type: 'line', - fs: 9, - ) - ], - if (videoItem.isFollowed == 1) ...[ - const PBadge( - text: '已关注', - stack: 'normal', - size: 'small', - type: 'color', - ) - ], - Expanded( - flex: crossAxisCount == 1 ? 0 : 1, - child: Text( - videoItem.owner.name, - maxLines: 1, - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - ), - if (crossAxisCount == 1) ...[ - Text( - ' • ', - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - VideoStat( - videoItem: videoItem, - crossAxisCount: crossAxisCount, - ), - const Spacer(), - ], - if (videoItem.goto == 'av' && crossAxisCount != 1) ...[ - VideoPopupMenu( - size: 24, - iconSize: 14, - videoItem: videoItem, - ), - ] else ...[ - const SizedBox(height: 24) - ] - ], - ), + return Padding( + padding: crossAxisCount == 1 + ? const EdgeInsets.fromLTRB(9, 9, 9, 4) + : const EdgeInsets.fromLTRB(5, 8, 5, 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + videoItem.title, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + if (crossAxisCount > 1) ...[ + const SizedBox(height: 2), + VideoStat(videoItem: videoItem, crossAxisCount: crossAxisCount), ], - ), + if (crossAxisCount == 1) const SizedBox(height: 4), + Row( + children: [ + if (videoItem.goto == 'bangumi') + _buildBadge(videoItem.bangumiBadge, 'line', 9), + if (videoItem.rcmdReason?.content != null && + videoItem.rcmdReason.content != '') + _buildBadge(videoItem.rcmdReason.content, 'color'), + if (videoItem.goto == 'picture') _buildBadge('动态', 'line', 9), + if (videoItem.isFollowed == 1) _buildBadge('已关注', 'color'), + Expanded( + flex: crossAxisCount == 1 ? 0 : 1, + child: Text( + videoItem.owner.name, + maxLines: 1, + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: Theme.of(context).colorScheme.outline, + ), + ), + ), + if (crossAxisCount == 1) ...[ + const SizedBox(width: 10), + VideoStat( + videoItem: videoItem, + crossAxisCount: crossAxisCount, + ), + const Spacer(), + ], + if (videoItem.goto == 'av') + VideoPopupMenu( + size: 24, + iconSize: 14, + videoItem: videoItem, + ), + ], + ), + ], ), ); } @@ -383,7 +331,6 @@ class VideoPopupMenu extends StatelessWidget { size: iconSize, ), position: PopupMenuPosition.under, - // constraints: const BoxConstraints(maxHeight: 35), onSelected: (String type) {}, itemBuilder: (BuildContext context) => >[ PopupMenuItem( diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index cc228f6b..a25389bd 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -214,6 +214,34 @@ class UserInfoWidget extends StatelessWidget { final VoidCallback? callback; final HomeController? ctr; + Widget buildLoggedInWidget(context) { + return Stack( + children: [ + NetworkImgLayer( + type: 'avatar', + width: 34, + height: 34, + src: userFace, + ), + Positioned.fill( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => callback?.call(), + splashColor: Theme.of(context) + .colorScheme + .primaryContainer + .withOpacity(0.3), + borderRadius: const BorderRadius.all( + Radius.circular(50), + ), + ), + ), + ) + ], + ); + } + @override Widget build(BuildContext context) { return Row( @@ -231,31 +259,7 @@ class UserInfoWidget extends StatelessWidget { const SizedBox(width: 8), Obx( () => userLogin.value - ? Stack( - children: [ - NetworkImgLayer( - type: 'avatar', - width: 34, - height: 34, - src: userFace, - ), - Positioned.fill( - child: Material( - color: Colors.transparent, - child: InkWell( - onTap: () => callback?.call(), - splashColor: Theme.of(context) - .colorScheme - .primaryContainer - .withOpacity(0.3), - borderRadius: const BorderRadius.all( - Radius.circular(50), - ), - ), - ), - ) - ], - ) + ? buildLoggedInWidget(context) : DefaultUser(callback: () => callback!()), ), ], @@ -402,30 +406,27 @@ class SearchBar extends StatelessWidget { color: colorScheme.onSecondaryContainer.withOpacity(0.05), child: InkWell( splashColor: colorScheme.primaryContainer.withOpacity(0.3), - onTap: () => Get.toNamed( - '/search', - parameters: {'hintText': ctr!.defaultSearch.value}, - ), - child: Row( - children: [ - const SizedBox(width: 14), - Icon( - Icons.search_outlined, - color: colorScheme.onSecondaryContainer, - ), - const SizedBox(width: 10), - Obx( - () => Expanded( - child: Text( + onTap: () => Get.toNamed('/search', + parameters: {'hintText': ctr!.defaultSearch.value}), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: Row( + children: [ + Icon( + Icons.search_outlined, + color: colorScheme.onSecondaryContainer, + ), + const SizedBox(width: 10), + Obx( + () => Text( ctr!.defaultSearch.value, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: colorScheme.outline), ), ), - ), - const SizedBox(width: 15), - ], + ], + ), ), ), ), diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index acc1e654..67567870 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -5,9 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/skeleton/video_card_v.dart'; -import 'package:pilipala/common/widgets/animated_dialog.dart'; import 'package:pilipala/common/widgets/http_error.dart'; -import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/common/widgets/video_card_v.dart'; import 'package:pilipala/utils/main_stream.dart'; @@ -118,16 +116,6 @@ class _RcmdPageState extends State ); } - OverlayEntry _createPopupDialog(videoItem) { - return OverlayEntry( - builder: (context) => AnimatedDialog( - closeFn: _rcmdController.popupDialog?.remove, - child: OverlayPop( - videoItem: videoItem, closeFn: _rcmdController.popupDialog?.remove), - ), - ); - } - Widget contentGrid(ctr, videoList) { // double maxWidth = Get.size.width; // int baseWidth = 500; @@ -158,14 +146,6 @@ class _RcmdPageState extends State ? VideoCardV( videoItem: videoList[index], crossAxisCount: crossAxisCount, - longPress: () { - _rcmdController.popupDialog = - _createPopupDialog(videoList[index]); - Overlay.of(context).insert(_rcmdController.popupDialog!); - }, - longPressEnd: () { - _rcmdController.popupDialog?.remove(); - }, ) : const VideoCardVSkeleton(); }, From ab45d2e6a68a5000c82e038a3f1308ab88b4be0d Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 24 Apr 2024 23:56:07 +0800 Subject: [PATCH 013/106] =?UTF-8?q?opt:=20=E9=A6=96=E9=A1=B5=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E5=8D=A1=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_v.dart | 310 ++++++++++++++------------- 1 file changed, 157 insertions(+), 153 deletions(-) diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 0598f973..9916aa7a 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/utils/feed_back.dart'; import '../../models/model_rec_video_item.dart'; import 'overlay_pop.dart'; import 'stat/danmu.dart'; @@ -20,15 +21,11 @@ import 'network_img_layer.dart'; class VideoCardV extends StatelessWidget { final dynamic videoItem; final int crossAxisCount; - // final Function()? longPress; - // final Function()? longPressEnd; const VideoCardV({ Key? key, required this.videoItem, required this.crossAxisCount, - // this.longPress, - // this.longPressEnd, }) : super(key: key); bool isStringNumeric(String str) { @@ -128,60 +125,56 @@ class VideoCardV extends StatelessWidget { @override Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(videoItem.id); - return Card( - elevation: 0, - clipBehavior: Clip.hardEdge, - margin: EdgeInsets.zero, - child: InkWell( - onTap: () async => onPushDetail(heroTag), - onLongPress: () { - SmartDialog.show( - builder: (context) => OverlayPop( - videoItem: videoItem, - closeFn: () => SmartDialog.dismiss(), - ), - ); - }, - child: Column( - children: [ - AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder(builder: (context, boxConstraints) { - double maxWidth = boxConstraints.maxWidth; - double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: videoItem.pic, - width: maxWidth, - height: maxHeight, - ), + return InkWell( + onTap: () async => onPushDetail(heroTag), + onLongPress: () { + SmartDialog.show( + builder: (context) => OverlayPop( + videoItem: videoItem, + closeFn: () => SmartDialog.dismiss(), + ), + ); + }, + borderRadius: BorderRadius.circular(16), + child: Column( + children: [ + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder(builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: videoItem.pic, + width: maxWidth, + height: maxHeight, ), - if (videoItem.duration > 0) - if (crossAxisCount == 1) ...[ - PBadge( - bottom: 10, - right: 10, - text: Utils.timeFormat(videoItem.duration), - ) - ] else ...[ - PBadge( - bottom: 6, - right: 7, - size: 'small', - type: 'gray', - text: Utils.timeFormat(videoItem.duration), - ) - ], - ], - ); - }), - ), - VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) - ], - ), + ), + if (videoItem.duration > 0) + if (crossAxisCount == 1) ...[ + PBadge( + bottom: 10, + right: 10, + text: Utils.timeFormat(videoItem.duration), + ) + ] else ...[ + PBadge( + bottom: 6, + right: 7, + size: 'small', + type: 'gray', + text: Utils.timeFormat(videoItem.duration), + ) + ], + ], + ); + }), + ), + VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) + ], ), ); } @@ -252,11 +245,28 @@ class VideoContent extends StatelessWidget { const Spacer(), ], if (videoItem.goto == 'av') - VideoPopupMenu( - size: 24, - iconSize: 14, - videoItem: videoItem, - ), + SizedBox( + width: 24, + height: 24, + child: IconButton( + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) { + return MorePanel(videoItem: videoItem); + }, + ); + }, + icon: Icon( + Icons.more_vert_outlined, + color: Theme.of(context).colorScheme.outline, + size: 14, + ), + ), + ) ], ), ], @@ -279,15 +289,9 @@ class VideoStat extends StatelessWidget { Widget build(BuildContext context) { return Row( children: [ - StatView( - theme: 'gray', - view: videoItem.stat.view, - ), + StatView(theme: 'gray', view: videoItem.stat.view), const SizedBox(width: 8), - StatDanMu( - theme: 'gray', - danmu: videoItem.stat.danmu, - ), + StatDanMu(theme: 'gray', danmu: videoItem.stat.danmu), if (videoItem is RecVideoItemModel) ...[ crossAxisCount > 1 ? const Spacer() : const SizedBox(width: 8), RichText( @@ -306,98 +310,98 @@ class VideoStat extends StatelessWidget { } } -class VideoPopupMenu extends StatelessWidget { - final double? size; - final double? iconSize; +class MorePanel extends StatelessWidget { final dynamic videoItem; + const MorePanel({super.key, required this.videoItem}); - const VideoPopupMenu({ - Key? key, - required this.size, - required this.iconSize, - required this.videoItem, - }) : super(key: key); + Future menuActionHandler(String type) async { + switch (type) { + case 'block': + blockUser(); + break; + case 'watchLater': + var res = await UserHttp.toViewLater(bvid: videoItem.bvid as String); + SmartDialog.showToast(res['msg']); + Get.back(); + break; + default: + } + } + + void blockUser() async { + SmartDialog.show( + useSystem: true, + animationType: SmartAnimationType.centerFade_otherSlide, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('提示'), + content: Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' + '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'), + actions: [ + TextButton( + onPressed: () => SmartDialog.dismiss(), + child: Text( + '点错了', + style: TextStyle(color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () async { + var res = await VideoHttp.relationMod( + mid: videoItem.owner.mid, + act: 5, + reSrc: 11, + ); + SmartDialog.dismiss(); + SmartDialog.showToast(res['msg'] ?? '成功'); + }, + child: const Text('确认'), + ) + ], + ); + }, + ); + } @override Widget build(BuildContext context) { - return SizedBox( - width: size, - height: size, - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: Icon( - Icons.more_vert_outlined, - color: Theme.of(context).colorScheme.outline, - size: iconSize, - ), - position: PopupMenuPosition.under, - onSelected: (String type) {}, - itemBuilder: (BuildContext context) => >[ - PopupMenuItem( - onTap: () async { - var res = - await UserHttp.toViewLater(bvid: videoItem.bvid as String); - SmartDialog.showToast(res['msg']); - }, - value: 'pause', - height: 40, - child: const Row( - children: [ - Icon(Icons.watch_later_outlined, size: 16), - SizedBox(width: 6), - Text('稍后再看', style: TextStyle(fontSize: 13)) - ], + return Container( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + onTap: () => Get.back(), + child: Container( + height: 35, + padding: const EdgeInsets.only(bottom: 2), + child: Center( + child: Container( + width: 32, + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.outline, + borderRadius: const BorderRadius.all(Radius.circular(3))), + ), + ), ), ), - const PopupMenuDivider(), - PopupMenuItem( - onTap: () async { - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: Text( - '确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' - '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'), - actions: [ - TextButton( - onPressed: () => SmartDialog.dismiss(), - child: Text( - '点错了', - style: TextStyle( - color: Theme.of(context).colorScheme.outline), - ), - ), - TextButton( - onPressed: () async { - var res = await VideoHttp.relationMod( - mid: videoItem.owner.mid, - act: 5, - reSrc: 11, - ); - SmartDialog.dismiss(); - SmartDialog.showToast(res['msg'] ?? '成功'); - }, - child: const Text('确认'), - ) - ], - ); - }, - ); - }, - value: 'pause', - height: 40, - child: Row( - children: [ - const Icon(Icons.block, size: 16), - const SizedBox(width: 6), - Text('拉黑:${videoItem.owner.name}', - style: const TextStyle(fontSize: 13)) - ], + ListTile( + onTap: () async => await menuActionHandler('block'), + minLeadingWidth: 0, + leading: const Icon(Icons.block, size: 19), + title: Text( + '拉黑up主 「${videoItem.owner.name}」', + style: Theme.of(context).textTheme.titleSmall, ), ), + ListTile( + onTap: () async => await menuActionHandler('watchLater'), + minLeadingWidth: 0, + leading: const Icon(Icons.watch_later_outlined, size: 19), + title: + Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall), + ), ], ), ); From 1f426881f2c4ae43f5f58695ff342d175460f2a8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 25 Apr 2024 22:42:42 +0800 Subject: [PATCH 014/106] =?UTF-8?q?mod:=20=E4=BD=BF=E7=94=A8feed=5Fversion?= =?UTF-8?q?=20V3=E6=8E=A8=E8=8D=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/video.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http/video.dart b/lib/http/video.dart index d43656b2..f8e19060 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -35,7 +35,7 @@ class VideoHttp { Api.recommendListWeb, data: { 'version': 1, - 'feed_version': 'V8', + 'feed_version': 'V3', 'homepage_ver': 1, 'ps': ps, 'fresh_idx': freshIdx, From c6f5bc561c5f4f5c275b569338132be9df41f6f8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 25 Apr 2024 23:18:21 +0800 Subject: [PATCH 015/106] =?UTF-8?q?feat:=20up=E6=8A=95=E7=A8=BF=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E5=85=85=E7=94=B5=E4=B8=93=E5=B1=9E=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_h.dart | 9 +++++++++ lib/pages/member_archive/view.dart | 1 + 2 files changed, 10 insertions(+) diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index 99059a9e..25e701ac 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -23,6 +23,7 @@ class VideoCardH extends StatelessWidget { this.showView = true, this.showDanmaku = true, this.showPubdate = false, + this.showCharge = false, }); // ignore: prefer_typing_uninitialized_variables final videoItem; @@ -33,6 +34,7 @@ class VideoCardH extends StatelessWidget { final bool showView; final bool showDanmaku; final bool showPubdate; + final bool showCharge; @override Widget build(BuildContext context) { @@ -121,6 +123,13 @@ class VideoCardH extends StatelessWidget { // videoItem.rcmdReason.content != '') // pBadge(videoItem.rcmdReason.content, context, // 6.0, 6.0, null, null), + if (showCharge && videoItem?.isChargingSrc) + const PBadge( + text: '充电专属', + right: 6.0, + top: 6.0, + type: 'primary', + ), ], ); }, diff --git a/lib/pages/member_archive/view.dart b/lib/pages/member_archive/view.dart index 3103683a..f38ca0cb 100644 --- a/lib/pages/member_archive/view.dart +++ b/lib/pages/member_archive/view.dart @@ -79,6 +79,7 @@ class _MemberArchivePageState extends State { videoItem: list[index], showOwner: false, showPubdate: true, + showCharge: true, ); }, childCount: list.length, From 4e66a3f9e7ab379a5501f40ea5fabd983e0a8480 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 26 Apr 2024 23:22:26 +0800 Subject: [PATCH 016/106] =?UTF-8?q?opt:=20=E8=AF=84=E8=AE=BA=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=98=E5=85=88=E5=B1=95=E7=A4=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/dynamics/detail/view.dart | 6 +- lib/pages/video/detail/controller.dart | 5 +- lib/pages/video/detail/reply/view.dart | 9 +- .../detail/reply/widgets/reply_item.dart | 133 +++++++++--------- .../video/detail/reply_reply/controller.dart | 10 +- lib/pages/video/detail/reply_reply/view.dart | 14 +- 6 files changed, 99 insertions(+), 78 deletions(-) diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index c6ec682a..757ba0ce 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -106,7 +106,7 @@ class _DynamicDetailPageState extends State } // 查看二级评论 - void replyReply(replyItem) { + void replyReply(replyItem, currentReply) { int oid = replyItem.oid; int rpid = replyItem.rpid!; Get.to( @@ -324,8 +324,8 @@ class _DynamicDetailPageState extends State replyItem: replyList[index], showReplyRow: true, replyLevel: '1', - replyReply: (replyItem) => - replyReply(replyItem), + replyReply: (replyItem, currentReply) => + replyReply(replyItem, currentReply), replyType: ReplyType.values[replyType], addReply: (replyItem) { replyList[index] diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4d40e535..4613c7ca 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -161,11 +161,11 @@ class VideoDetailController extends GetxController getSubtitle(); } - showReplyReplyPanel() { + showReplyReplyPanel(oid, fRpid, firstFloor, currentReply) { replyReplyBottomSheetCtr = scaffoldKey.currentState?.showBottomSheet((BuildContext context) { return VideoReplyReplyPanel( - oid: oid.value, + oid: oid, rpid: fRpid, closePanel: () => { fRpid = 0, @@ -174,6 +174,7 @@ class VideoDetailController extends GetxController replyType: ReplyType.video, source: 'videoDetail', sheetHeight: sheetHeight.value, + currentReply: currentReply, ); }); replyReplyBottomSheetCtr?.closed.then((value) { diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 2a167fe9..3b4891b8 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -110,14 +110,15 @@ class _VideoReplyPanelState extends State } // 展示二级回复 - void replyReply(replyItem) { + void replyReply(replyItem, currentReply) { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); if (replyItem != null) { videoDetailCtr.oid.value = replyItem.oid; videoDetailCtr.fRpid = replyItem.rpid!; videoDetailCtr.firstFloor = replyItem; - videoDetailCtr.showReplyReplyPanel(); + videoDetailCtr.showReplyReplyPanel( + replyItem.oid, replyItem.rpid!, replyItem, currentReply); } } @@ -228,8 +229,8 @@ class _VideoReplyPanelState extends State .replyList[index], showReplyRow: true, replyLevel: replyLevel, - replyReply: (replyItem) => - replyReply(replyItem), + replyReply: (replyItem, currentReply) => + replyReply(replyItem, currentReply), replyType: ReplyType.video, ); } diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 50fe20d4..8a8e4af7 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -12,7 +12,6 @@ import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/reply_new/index.dart'; import 'package:pilipala/utils/feed_back.dart'; -import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/url_utils.dart'; import 'package:pilipala/utils/utils.dart'; @@ -45,7 +44,7 @@ class ReplyItem extends StatelessWidget { onTap: () { feedBack(); if (replyReply != null) { - replyReply!(replyItem); + replyReply!(replyItem, null); } }, onLongPress: () { @@ -59,28 +58,23 @@ class ReplyItem extends StatelessWidget { }, ); }, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), - child: content(context), - ), - Divider( - indent: 55, - endIndent: 15, - height: 0.3, - color: Theme.of(context) - .colorScheme - .onInverseSurface - .withOpacity(0.5), - ) - ], + child: Container( + padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: + Theme.of(context).colorScheme.onInverseSurface.withOpacity(0.5), + ))), + child: content(context), ), ), ); } Widget lfAvtar(BuildContext context, String heroTag) { + ColorScheme colorScheme = Theme.of(context).colorScheme; return Stack( children: [ Hero( @@ -100,11 +94,11 @@ class ReplyItem extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), - color: Theme.of(context).colorScheme.background, + color: colorScheme.background, ), child: Icon( Icons.offline_bolt, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, size: 16, ), ), @@ -117,7 +111,7 @@ class ReplyItem extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), - color: Theme.of(context).colorScheme.background, + color: colorScheme.background, ), child: Image.asset( 'assets/images/big-vip.png', @@ -131,6 +125,8 @@ class ReplyItem extends StatelessWidget { Widget content(BuildContext context) { final String heroTag = Utils.makeHeroTag(replyItem!.mid); + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -160,16 +156,17 @@ class ReplyItem extends StatelessWidget { style: TextStyle( color: replyItem!.member!.vip!['vipStatus'] > 0 ? const Color.fromARGB(255, 251, 100, 163) - : Theme.of(context).colorScheme.outline, + : colorScheme.outline, fontSize: 13, ), ), - const SizedBox(width: 6), - Image.asset( - 'assets/images/lv/lv${replyItem!.member!.level}.png', - height: 11, + Padding( + padding: const EdgeInsets.only(left: 6, right: 6), + child: Image.asset( + 'assets/images/lv/lv${replyItem!.member!.level}.png', + height: 11, + ), ), - const SizedBox(width: 6), if (replyItem!.isUp!) const PBadge( text: 'UP', @@ -184,9 +181,8 @@ class ReplyItem extends StatelessWidget { Text( Utils.dateFormat(replyItem!.ctime), style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: textTheme.labelSmall!.fontSize, + color: colorScheme.outline, ), ), if (replyItem!.replyControl != null && @@ -194,11 +190,8 @@ class ReplyItem extends StatelessWidget { Text( ' • ${replyItem!.replyControl!.location!}', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline), + fontSize: textTheme.labelSmall!.fontSize, + color: colorScheme.outline), ), ], ) @@ -256,6 +249,8 @@ class ReplyItem extends StatelessWidget { // 感谢、回复、复制 Widget bottonAction(BuildContext context, replyControl) { + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; return Row( children: [ const SizedBox(width: 32), @@ -287,15 +282,13 @@ class ReplyItem extends StatelessWidget { }, child: Row(children: [ Icon(Icons.reply, - size: 18, - color: - Theme.of(context).colorScheme.outline.withOpacity(0.8)), + size: 18, color: colorScheme.outline.withOpacity(0.8)), const SizedBox(width: 3), Text( '回复', style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: textTheme.labelMedium!.fontSize, + color: colorScheme.outline, ), ), ]), @@ -306,8 +299,8 @@ class ReplyItem extends StatelessWidget { Text( 'up主觉得很赞', style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + color: colorScheme.primary, + fontSize: textTheme.labelMedium!.fontSize), ), const SizedBox(width: 2), ], @@ -316,8 +309,8 @@ class ReplyItem extends StatelessWidget { Text( '热评', style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + color: colorScheme.primary, + fontSize: textTheme.labelMedium!.fontSize), ), const Spacer(), ZanButton(replyItem: replyItem, replyType: replyType), @@ -347,10 +340,13 @@ class ReplyItemRow extends StatelessWidget { Widget build(BuildContext context) { final bool isShow = replyControl!.isShow!; final int extraRow = replyControl != null && isShow ? 1 : 0; + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; + return Container( margin: const EdgeInsets.only(left: 42, right: 4, top: 0), child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, + color: colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), clipBehavior: Clip.hardEdge, animationDuration: Duration.zero, @@ -361,7 +357,9 @@ class ReplyItemRow extends StatelessWidget { for (int i = 0; i < replies!.length; i++) ...[ InkWell( // 一楼点击评论展开评论详情 - onTap: () => replyReply!(replyItem), + // onTap: () { + // replyReply?.call(replyItem, replies![i]); + // }, onLongPress: () { feedBack(); showModalBottomSheet( @@ -379,7 +377,7 @@ class ReplyItemRow extends StatelessWidget { 8, i == 0 && (extraRow == 1 || replies!.length > 1) ? 8 : 5, 8, - i == 0 && (extraRow == 1 || replies!.length > 1) ? 5 : 6, + 6, ), child: Text.rich( overflow: TextOverflow.ellipsis, @@ -393,7 +391,7 @@ class ReplyItemRow extends StatelessWidget { .textTheme .titleSmall! .fontSize, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -429,15 +427,14 @@ class ReplyItemRow extends StatelessWidget { if (extraRow == 1) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply!(replyItem), + onTap: () => replyReply!(replyItem, null), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), child: Text.rich( TextSpan( style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, + fontSize: textTheme.labelMedium!.fontSize, ), children: [ if (replyControl!.upReply!) @@ -445,7 +442,7 @@ class ReplyItemRow extends StatelessWidget { TextSpan( text: replyControl!.entryText!, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), ) ], @@ -464,6 +461,7 @@ InlineSpan buildContent( BuildContext context, replyItem, replyReply, fReplyItem) { final String routePath = Get.currentRoute; bool isVideoPage = routePath.startsWith('/video'); + ColorScheme colorScheme = Theme.of(context).colorScheme; // replyItem 当前回复内容 // replyReply 查看二楼回复(回复详情)回调 @@ -533,8 +531,10 @@ InlineSpan buildContent( TextSpan( text: str, recognizer: TapGestureRecognizer() - ..onTap = () => - replyReply?.call(replyItem.root == 0 ? replyItem : fReplyItem), + ..onTap = () => replyReply?.call( + replyItem.root == 0 ? replyItem : fReplyItem, + replyItem, + ), ), ); } @@ -564,7 +564,7 @@ InlineSpan buildContent( TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -584,7 +584,7 @@ InlineSpan buildContent( text: ' $matchStr ', style: isVideoPage ? TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ) : null, recognizer: TapGestureRecognizer() @@ -624,14 +624,14 @@ InlineSpan buildContent( child: Image.network( content.jumpUrl[matchStr]['prefix_icon'], height: 19, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), ) ], TextSpan( text: content.jumpUrl[matchStr]['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () async { @@ -721,7 +721,7 @@ InlineSpan buildContent( TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -747,7 +747,7 @@ InlineSpan buildContent( text: ' $matchStr ', style: isVideoPage ? TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ) : null, recognizer: TapGestureRecognizer() @@ -786,14 +786,14 @@ InlineSpan buildContent( child: Image.network( content.jumpUrl[patternStr]['prefix_icon'], height: 19, - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), ) ], TextSpan( text: content.jumpUrl[patternStr]['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -997,7 +997,8 @@ class MorePanel extends StatelessWidget { @override Widget build(BuildContext context) { - Color errorColor = Theme.of(context).colorScheme.error; + ColorScheme colorScheme = Theme.of(context).colorScheme; + TextTheme textTheme = Theme.of(context).textTheme; return Container( padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), child: Column( @@ -1013,7 +1014,7 @@ class MorePanel extends StatelessWidget { width: 32, height: 3, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.outline, + color: colorScheme.outline, borderRadius: const BorderRadius.all(Radius.circular(3))), ), ), @@ -1023,13 +1024,13 @@ class MorePanel extends StatelessWidget { onTap: () async => await menuActionHandler('copyAll'), minLeadingWidth: 0, leading: const Icon(Icons.copy_all_outlined, size: 19), - title: Text('复制全部', style: Theme.of(context).textTheme.titleSmall), + title: Text('复制全部', style: textTheme.titleSmall), ), ListTile( onTap: () async => await menuActionHandler('copyFreedom'), minLeadingWidth: 0, leading: const Icon(Icons.copy_outlined, size: 19), - title: Text('自由复制', style: Theme.of(context).textTheme.titleSmall), + title: Text('自由复制', style: textTheme.titleSmall), ), // ListTile( // onTap: () async => await menuActionHandler('block'), diff --git a/lib/pages/video/detail/reply_reply/controller.dart b/lib/pages/video/detail/reply_reply/controller.dart index e94aaea5..4c553e29 100644 --- a/lib/pages/video/detail/reply_reply/controller.dart +++ b/lib/pages/video/detail/reply_reply/controller.dart @@ -26,7 +26,7 @@ class VideoReplyReplyController extends GetxController { currentPage = 0; } - Future queryReplyList({type = 'init'}) async { + Future queryReplyList({type = 'init', currentReply}) async { if (type == 'init') { currentPage = 0; } @@ -63,6 +63,14 @@ class VideoReplyReplyController extends GetxController { // res['data'].replies.addAll(replyList); } } + if (replyList.isNotEmpty && currentReply != null) { + int indexToRemove = + replyList.indexWhere((item) => currentReply.rpid == item.rpid); + // 如果找到了指定ID的项,则移除 + if (indexToRemove != -1) { + replyList.removeAt(indexToRemove); + } + } isLoadingMore = false; return res; } diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index 3fe84c71..6441c600 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -20,6 +20,7 @@ class VideoReplyReplyPanel extends StatefulWidget { this.source, this.replyType, this.sheetHeight, + this.currentReply, super.key, }); final int? oid; @@ -29,6 +30,7 @@ class VideoReplyReplyPanel extends StatefulWidget { final String? source; final ReplyType? replyType; final double? sheetHeight; + final dynamic currentReply; @override State createState() => _VideoReplyReplyPanelState(); @@ -63,7 +65,9 @@ class _VideoReplyReplyPanelState extends State { }, ); - _futureBuilderFuture = _videoReplyReplyController.queryReplyList(); + _futureBuilderFuture = _videoReplyReplyController.queryReplyList( + currentReply: widget.currentReply, + ); } void replyReply(replyItem) {} @@ -107,7 +111,9 @@ class _VideoReplyReplyPanelState extends State { onRefresh: () async { setState(() {}); _videoReplyReplyController.currentPage = 0; - return await _videoReplyReplyController.queryReplyList(); + return await _videoReplyReplyController.queryReplyList( + currentReply: widget.currentReply, + ); }, child: CustomScrollView( controller: _videoReplyReplyController.scrollController, @@ -140,6 +146,10 @@ class _VideoReplyReplyPanelState extends State { if (snapshot.connectionState == ConnectionState.done) { Map? data = snapshot.data; if (data != null && data['status']) { + if (widget.currentReply != null) { + _videoReplyReplyController.replyList + .insert(0, widget.currentReply); + } // 请求成功 return Obx( () => SliverList( From 8273ff2e02f3900425465485c31d99ef3e5b5b15 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 26 Apr 2024 23:46:54 +0800 Subject: [PATCH 017/106] =?UTF-8?q?opt:=20=E8=AF=84=E8=AE=BA=E6=A1=86?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/reply.dart | 11 +--- lib/pages/dynamics/detail/controller.dart | 2 + lib/pages/dynamics/detail/view.dart | 63 +++++++++++--------- lib/pages/video/detail/reply/controller.dart | 2 + lib/pages/video/detail/reply/view.dart | 59 ++++++++++-------- lib/pages/video/detail/reply_new/view.dart | 22 ++++--- 6 files changed, 88 insertions(+), 71 deletions(-) diff --git a/lib/http/reply.dart b/lib/http/reply.dart index f080ed51..880f9072 100644 --- a/lib/http/reply.dart +++ b/lib/http/reply.dart @@ -22,19 +22,14 @@ class ReplyHttp { return { 'status': true, 'data': ReplyData.fromJson(res.data['data']), + 'code': 200, }; } else { - Map errMap = { - -400: '请求错误', - -404: '无此项', - 12002: '当前页面评论功能已关闭', - 12009: '评论主体的type不合法', - 12061: 'UP主已关闭评论区', - }; return { 'status': false, 'date': [], - 'msg': errMap[res.data['code']] ?? res.data['message'], + 'code': res.data['code'], + 'msg': res.data['message'], }; } } diff --git a/lib/pages/dynamics/detail/controller.dart b/lib/pages/dynamics/detail/controller.dart index 8e117383..f34de061 100644 --- a/lib/pages/dynamics/detail/controller.dart +++ b/lib/pages/dynamics/detail/controller.dart @@ -25,6 +25,7 @@ class DynamicDetailController extends GetxController { RxString sortTypeTitle = ReplySortType.time.titles.obs; RxString sortTypeLabel = ReplySortType.time.labels.obs; Box setting = GStrorage.setting; + RxInt replyReqCode = 200.obs; @override void onInit() { @@ -84,6 +85,7 @@ class DynamicDetailController extends GetxController { replyList.addAll(replies); } } + replyReqCode.value = res['code']; isLoadingMore = false; return res; } diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index 757ba0ce..11636b5b 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -369,35 +369,40 @@ class _DynamicDetailPageState extends State curve: Curves.easeInOut, ), ), - child: FloatingActionButton( - heroTag: null, - onPressed: () { - feedBack(); - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (BuildContext context) { - return VideoReplyNewDialog( - oid: _dynamicDetailController.oid ?? - IdUtils.bv2av(Get.parameters['bvid']!), - root: 0, - parent: 0, - replyType: ReplyType.values[replyType], - ); - }, - ).then( - (value) => { - // 完成评论,数据添加 - if (value != null && value['data'] != null) - { - _dynamicDetailController.replyList.add(value['data']), - _dynamicDetailController.acount.value++ - } - }, - ); - }, - tooltip: '评论动态', - child: const Icon(Icons.reply), + child: Obx( + () => _dynamicDetailController.replyReqCode.value == 12061 + ? const SizedBox() + : FloatingActionButton( + heroTag: null, + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (BuildContext context) { + return VideoReplyNewDialog( + oid: _dynamicDetailController.oid ?? + IdUtils.bv2av(Get.parameters['bvid']!), + root: 0, + parent: 0, + replyType: ReplyType.values[replyType], + ); + }, + ).then( + (value) => { + // 完成评论,数据添加 + if (value != null && value['data'] != null) + { + _dynamicDetailController.replyList + .add(value['data']), + _dynamicDetailController.acount.value++ + } + }, + ); + }, + tooltip: '评论动态', + child: const Icon(Icons.reply), + ), ), ), ); diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index 06ce26ff..b718c840 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -37,6 +37,7 @@ class VideoReplyController extends GetxController { RxString sortTypeLabel = ReplySortType.time.labels.obs; Box setting = GStrorage.setting; + RxInt replyReqCode = 200.obs; @override void onInit() { @@ -106,6 +107,7 @@ class VideoReplyController extends GetxController { replyList.addAll(replies); } } + replyReqCode.value = res['code']; isLoadingMore = false; return res; } diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 3b4891b8..420f349c 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -277,32 +277,39 @@ class _VideoReplyPanelState extends State parent: fabAnimationCtr, curve: Curves.easeInOut, )), - child: FloatingActionButton( - heroTag: null, - onPressed: () { - feedBack(); - showModalBottomSheet( - context: context, - isScrollControlled: true, - builder: (BuildContext context) { - return VideoReplyNewDialog( - oid: _videoReplyController.aid ?? - IdUtils.bv2av(Get.parameters['bvid']!), - root: 0, - parent: 0, - replyType: ReplyType.video, - ); - }, - ).then( - (value) => { - // 完成评论,数据添加 - if (value != null && value['data'] != null) - {_videoReplyController.replyList.add(value['data'])} - }, - ); - }, - tooltip: '发表评论', - child: const Icon(Icons.reply), + child: Obx( + () => _videoReplyController.replyReqCode.value == 12061 + ? const SizedBox() + : FloatingActionButton( + heroTag: null, + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (BuildContext context) { + return VideoReplyNewDialog( + oid: _videoReplyController.aid ?? + IdUtils.bv2av(Get.parameters['bvid']!), + root: 0, + parent: 0, + replyType: ReplyType.video, + ); + }, + ).then( + (value) => { + // 完成评论,数据添加 + if (value != null && value['data'] != null) + { + _videoReplyController.replyList + .add(value['data']) + } + }, + ); + }, + tooltip: '发表评论', + child: const Icon(Icons.reply), + ), ), ), ), diff --git a/lib/pages/video/detail/reply_new/view.dart b/lib/pages/video/detail/reply_new/view.dart index 029e015a..3da15f64 100644 --- a/lib/pages/video/detail/reply_new/view.dart +++ b/lib/pages/video/detail/reply_new/view.dart @@ -43,6 +43,7 @@ class _VideoReplyNewDialogState extends State String toolbarType = 'input'; RxBool isForward = false.obs; RxBool showForward = false.obs; + RxString message = ''.obs; @override void initState() { @@ -80,15 +81,15 @@ class _VideoReplyNewDialogState extends State Future submitReplyAdd() async { feedBack(); - String message = _replyContentController.text; + // String message = _replyContentController.text; var result = await VideoHttp.replyAdd( type: widget.replyType ?? ReplyType.video, oid: widget.oid!, root: widget.root!, parent: widget.parent!, message: widget.replyItem != null && widget.replyItem!.root != 0 - ? ' 回复 @${widget.replyItem!.member!.uname!} : $message' - : message, + ? ' 回复 @${widget.replyItem!.member!.uname!} : ${message.value}' + : message.value, ); if (result['status']) { SmartDialog.showToast(result['data']['success_toast']); @@ -100,7 +101,7 @@ class _VideoReplyNewDialogState extends State if (isForward.value) { await DynamicsHttp.dynamicCreate( mid: 0, - rawText: message, + rawText: message.value, oid: widget.oid!, scene: 5, ); @@ -188,7 +189,7 @@ class _VideoReplyNewDialogState extends State autovalidateMode: AutovalidateMode.onUserInteraction, child: TextField( controller: _replyContentController, - minLines: 1, + minLines: 3, maxLines: null, autofocus: false, focusNode: replyContentFocusNode, @@ -199,6 +200,9 @@ class _VideoReplyNewDialogState extends State fontSize: 14, )), style: Theme.of(context).textTheme.bodyLarge, + onChanged: (text) { + message.value = text; + }, ), ), ), @@ -267,9 +271,11 @@ class _VideoReplyNewDialogState extends State const Spacer(), SizedBox( height: 36, - child: FilledButton( - onPressed: () => submitReplyAdd(), - child: const Text('发送'), + child: Obx( + () => FilledButton( + onPressed: message.isNotEmpty ? submitReplyAdd : null, + child: const Text('发送'), + ), ), ), ], From b752214af3c09f885e312bf23ed99567e07c4a68 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 01:04:11 +0800 Subject: [PATCH 018/106] =?UTF-8?q?fix:=20durl=E6=A0=BC=E5=BC=8F=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/video/play/quality.dart | 8 ++ lib/pages/video/detail/controller.dart | 84 ++++++++++++------- .../video/detail/widgets/header_control.dart | 43 ++++++---- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/lib/models/video/play/quality.dart b/lib/models/video/play/quality.dart index 6cae84cc..7bedf62a 100644 --- a/lib/models/video/play/quality.dart +++ b/lib/models/video/play/quality.dart @@ -39,6 +39,14 @@ extension VideoQualityCode on VideoQuality { } return null; } + + static int? toCode(VideoQuality quality) { + final index = VideoQuality.values.indexOf(quality); + if (index != -1 && index < _codeList.length) { + return _codeList[index]; + } + return null; + } } extension VideoQualityDesc on VideoQuality { diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4d40e535..3cc43005 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -51,7 +51,7 @@ class VideoDetailController extends GetxController /// 播放器配置 画质 音质 解码格式 late VideoQuality currentVideoQa; AudioQuality? currentAudioQa; - late VideoDecodeFormats currentDecodeFormats; + VideoDecodeFormats? currentDecodeFormats; // 是否开始自动播放 存在多p的情况下,第二p需要为true RxBool autoPlay = true.obs; // 视频资源是否有效 @@ -107,6 +107,7 @@ class VideoDetailController extends GetxController BottomControlType.fullscreen, ].obs; RxDouble sheetHeight = 0.0.obs; + RxString archiveSourceType = 'dash'.obs; @override void onInit() { @@ -189,37 +190,43 @@ class VideoDetailController extends GetxController plPlayerController.isBuffering.value = false; plPlayerController.buffered.value = Duration.zero; - /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl - List videoList = - data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); - try { - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); - } catch (_) { - if (currentVideoQa == VideoQuality.dolbyVision) { - firstVideo = videoList.first; - currentDecodeFormats = - VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!; - } else { - // 当前格式不可用 - currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( - SettingBoxKey.defaultDecode, - defaultValue: VideoDecodeFormats.values.last.code))!; - firstVideo = videoList - .firstWhere((i) => i.codecs!.startsWith(currentDecodeFormats.code)); + if (archiveSourceType.value == 'dash') { + /// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl + List videoList = + data.dash!.video!.where((i) => i.id == currentVideoQa.code).toList(); + try { + firstVideo = videoList.firstWhere( + (i) => i.codecs!.startsWith(currentDecodeFormats?.code)); + } catch (_) { + if (currentVideoQa == VideoQuality.dolbyVision) { + firstVideo = videoList.first; + currentDecodeFormats = + VideoDecodeFormatsCode.fromString(videoList.first.codecs!)!; + } else { + // 当前格式不可用 + currentDecodeFormats = VideoDecodeFormatsCode.fromString(setting.get( + SettingBoxKey.defaultDecode, + defaultValue: VideoDecodeFormats.values.last.code))!; + firstVideo = videoList.firstWhere( + (i) => i.codecs!.startsWith(currentDecodeFormats?.code)); + } + } + videoUrl = firstVideo.baseUrl!; + + /// 根据currentAudioQa 重新设置audioUrl + if (currentAudioQa != null) { + final AudioItem firstAudio = data.dash!.audio!.firstWhere( + (AudioItem i) => i.id == currentAudioQa!.code, + orElse: () => data.dash!.audio!.first, + ); + audioUrl = firstAudio.baseUrl ?? ''; } } - videoUrl = firstVideo.baseUrl!; - /// 根据currentAudioQa 重新设置audioUrl - if (currentAudioQa != null) { - final AudioItem firstAudio = data.dash!.audio!.firstWhere( - (AudioItem i) => i.id == currentAudioQa!.code, - orElse: () => data.dash!.audio!.first, - ); - audioUrl = firstAudio.baseUrl ?? ''; + if (archiveSourceType.value == 'durl') { + cacheVideoQa = VideoQualityCode.toCode(currentVideoQa); + queryVideoUrl(); } - playerInit(); } @@ -272,7 +279,8 @@ class VideoDetailController extends GetxController // 视频链接 Future queryVideoUrl() async { - var result = await VideoHttp.videoUrl(cid: cid.value, bvid: bvid); + var result = + await VideoHttp.videoUrl(cid: cid.value, bvid: bvid, qn: cacheVideoQa); if (result['status']) { data = result['data']; if (data.acceptDesc!.isNotEmpty && data.acceptDesc!.contains('试看')) { @@ -290,8 +298,22 @@ class VideoDetailController extends GetxController } return result; } + if (data.durl != null) { + archiveSourceType.value = 'durl'; + videoUrl = data.durl!.first.url!; + audioUrl = ''; + defaultST = Duration.zero; + firstVideo = VideoItem(); + currentVideoQa = VideoQualityCode.fromCode(data.quality!)!; + if (autoPlay.value) { + await playerInit(); + isShowCover.value = false; + } + return result; + } final List allVideosList = data.dash!.video!; try { + archiveSourceType.value = 'dash'; // 当前可播放的最高质量视频 int currentHighVideoQa = allVideosList.first.quality!.code; // 预设的画质为null,则当前可用的最高质量 @@ -321,7 +343,7 @@ class VideoDetailController extends GetxController // 当前视频没有对应格式返回第一个 bool flag = false; for (var i in supportDecodeFormats) { - if (i.startsWith(currentDecodeFormats.code)) { + if (i.startsWith(currentDecodeFormats?.code)) { flag = true; } } @@ -335,7 +357,7 @@ class VideoDetailController extends GetxController /// 取出符合当前解码格式的videoItem try { firstVideo = videosList.firstWhere( - (e) => e.codecs!.startsWith(currentDecodeFormats.code)); + (e) => e.codecs!.startsWith(currentDecodeFormats?.code)); } catch (_) { firstVideo = videosList.first; } diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index e00311c5..6acd20d7 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -180,15 +180,16 @@ class _HeaderControlState extends State { '当前音质 ${widget.videoDetailCtr!.currentAudioQa!.description}', style: subTitleStyle), ), - ListTile( - onTap: () => {Get.back(), showSetDecodeFormats()}, - dense: true, - leading: const Icon(Icons.av_timer_outlined, size: 20), - title: const Text('解码格式', style: titleStyle), - subtitle: Text( - '当前解码格式 ${widget.videoDetailCtr!.currentDecodeFormats.description}', - style: subTitleStyle), - ), + if (widget.videoDetailCtr!.currentDecodeFormats != null) + ListTile( + onTap: () => {Get.back(), showSetDecodeFormats()}, + dense: true, + leading: const Icon(Icons.av_timer_outlined, size: 20), + title: const Text('解码格式', style: titleStyle), + subtitle: Text( + '当前解码格式 ${widget.videoDetailCtr!.currentDecodeFormats!.description}', + style: subTitleStyle), + ), ListTile( onTap: () => {Get.back(), showSetRepeat()}, dense: true, @@ -541,16 +542,24 @@ class _HeaderControlState extends State { /// 可用的质量分类 int userfulQaSam = 0; - final List video = videoInfo.dash!.video!; - final Set idSet = {}; - for (final VideoItem item in video) { - final int id = item.id!; - if (!idSet.contains(id)) { - idSet.add(id); - userfulQaSam++; + if (videoInfo.dash != null) { + // dash格式视频一次请求会返回所有可播放的清晰度video + final List video = videoInfo.dash!.video!; + final Set idSet = {}; + for (final VideoItem item in video) { + final int id = item.id!; + if (!idSet.contains(id)) { + idSet.add(id); + userfulQaSam++; + } } } + if (videoInfo.durl != null) { + // durl格式视频一次请求返回对应清晰度video + userfulQaSam = videoFormat.length - 1; + } + showModalBottomSheet( context: context, elevation: 0, @@ -707,7 +716,7 @@ class _HeaderControlState extends State { void showSetDecodeFormats() { // 当前选中的解码格式 final VideoDecodeFormats currentDecodeFormats = - widget.videoDetailCtr!.currentDecodeFormats; + widget.videoDetailCtr!.currentDecodeFormats!; final VideoItem firstVideo = widget.videoDetailCtr!.firstVideo; // 当前视频可用的解码格式 final List videoFormat = videoInfo.supportFormats!; From 0312c8d01d6d8623de6f23c3fc9af8b58f2a81e3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 12:35:43 +0800 Subject: [PATCH 019/106] =?UTF-8?q?feat:=20=E6=98=BE=E7=A4=BA=E8=81=94?= =?UTF-8?q?=E5=90=88=E6=8A=95=E7=A8=BFup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/video.dart | 15 +-- lib/models/video_detail_res.dart | 45 +++++++ lib/pages/video/detail/introduction/view.dart | 111 +++++++++++++----- .../introduction/widgets/staff_up_item.dart | 74 ++++++++++++ 4 files changed, 206 insertions(+), 39 deletions(-) create mode 100644 lib/pages/video/detail/introduction/widgets/staff_up_item.dart diff --git a/lib/http/video.dart b/lib/http/video.dart index d43656b2..bdfaedf7 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -192,22 +192,15 @@ class VideoHttp { // 视频信息 标题、简介 static Future videoIntro({required String bvid}) async { var res = await Request().get(Api.videoIntro, data: {'bvid': bvid}); - VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); - if (result.code == 0) { + if (res.data['code'] == 0) { + VideoDetailResponse result = VideoDetailResponse.fromJson(res.data); return {'status': true, 'data': result.data!}; } else { - Map errMap = { - -400: '请求错误', - -403: '权限不足', - -404: '视频资源失效', - 62002: '稿件不可见', - 62004: '稿件审核中', - }; return { 'status': false, 'data': null, - 'code': result.code, - 'msg': errMap[result.code] ?? '请求异常', + 'code': res.data['code'], + 'msg': res.data['message'], }; } } diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index 38e0b877..a82b6fbb 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -67,6 +67,7 @@ class VideoDetailData { String? likeIcon; bool? needJumpBv; String? epId; + List? staff; VideoDetailData({ this.bvid, @@ -103,6 +104,7 @@ class VideoDetailData { this.likeIcon, this.needJumpBv, this.epId, + this.staff, }); VideoDetailData.fromJson(Map json) { @@ -155,6 +157,9 @@ class VideoDetailData { if (json['redirect_url'] != null) { epId = resolveEpId(json['redirect_url']); } + staff = json["staff"] != null + ? List.from(json["staff"]!.map((e) => Staff.fromJson(e))) + : null; } String resolveEpId(url) { @@ -652,3 +657,43 @@ class EpisodeItem { bvid = json['bvid']; } } + +class Staff { + Staff({ + this.mid, + this.title, + this.name, + this.face, + this.vip, + }); + + int? mid; + String? title; + String? name; + String? face; + int? status; + Vip? vip; + + Staff.fromJson(Map json) { + mid = json['mid']; + title = json['title']; + name = json['name']; + face = json['face']; + vip = Vip.fromJson(json['vip']); + } +} + +class Vip { + Vip({ + this.type, + this.status, + }); + + int? type; + int? status; + + Vip.fromJson(Map json) { + type = json['type']; + status = json['status']; + } +} diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index a7eae6d2..597b6def 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -22,6 +22,7 @@ import 'widgets/fav_panel.dart'; import 'widgets/intro_detail.dart'; import 'widgets/page_panel.dart'; import 'widgets/season_panel.dart'; +import 'widgets/staff_up_item.dart'; class VideoIntroPanel extends StatefulWidget { final String bvid; @@ -409,32 +410,35 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ) ], - GestureDetector( - onTap: onPushMember, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 4), - child: Row( - children: [ - NetworkImgLayer( - type: 'avatar', - src: widget.videoDetail!.owner!.face, - width: 34, - height: 34, - fadeInDuration: Duration.zero, - fadeOutDuration: Duration.zero, - ), - const SizedBox(width: 10), - Text(owner.name, style: const TextStyle(fontSize: 13)), - const SizedBox(width: 6), - Text( - follower, - style: TextStyle( - fontSize: t.textTheme.labelSmall!.fontSize, - color: outline, + if (widget.videoDetail!.staff == null) + GestureDetector( + onTap: onPushMember, + child: Container( + padding: + const EdgeInsets.symmetric(vertical: 12, horizontal: 4), + child: Row( + children: [ + NetworkImgLayer( + type: 'avatar', + src: widget.videoDetail!.owner!.face, + width: 34, + height: 34, + fadeInDuration: Duration.zero, + fadeOutDuration: Duration.zero, ), - ), - const Spacer(), - Obx(() => AnimatedOpacity( + const SizedBox(width: 10), + Text(owner.name, style: const TextStyle(fontSize: 13)), + const SizedBox(width: 6), + Text( + follower, + style: TextStyle( + fontSize: t.textTheme.labelSmall!.fontSize, + color: outline, + ), + ), + const Spacer(), + Obx( + () => AnimatedOpacity( opacity: videoIntroController.followStatus.isEmpty ? 0 : 1, duration: const Duration(milliseconds: 50), @@ -474,11 +478,58 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ), ), - )), - ], + ), + ), + ], + ), ), ), - ), + if (widget.videoDetail!.staff != null) ...[ + const SizedBox(height: 15), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text.rich( + TextSpan( + style: TextStyle( + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + ), + children: [ + TextSpan( + text: '创作团队', + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(fontWeight: FontWeight.bold), + ), + const WidgetSpan(child: SizedBox(width: 6)), + TextSpan( + text: '${widget.videoDetail!.staff!.length}人', + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + ), + ) + ], + ), + ), + SizedBox( + height: 120, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ + for (int i = 0; + i < widget.videoDetail!.staff!.length; + i++) ...[ + StaffUpItem(item: widget.videoDetail!.staff![i]) + ], + ], + ), + ), + ], + ), + ] ], )), ); @@ -545,4 +596,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ); }); } + + // Widget StaffPanel(BuildContext context, videoIntroController) { + // return + // } } diff --git a/lib/pages/video/detail/introduction/widgets/staff_up_item.dart b/lib/pages/video/detail/introduction/widgets/staff_up_item.dart new file mode 100644 index 00000000..7b18d95d --- /dev/null +++ b/lib/pages/video/detail/introduction/widgets/staff_up_item.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/models/video_detail_res.dart'; +import 'package:pilipala/utils/utils.dart'; + +class StaffUpItem extends StatelessWidget { + final Staff item; + + const StaffUpItem({ + super.key, + required this.item, + }); + + @override + Widget build(BuildContext context) { + final String heroTag = Utils.makeHeroTag(item.mid); + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 15), + GestureDetector( + onTap: () => Get.toNamed( + '/member?mid=${item.mid}', + arguments: {'face': item.face, 'heroTag': heroTag}, + ), + child: Hero( + tag: heroTag, + child: NetworkImgLayer( + width: 45, + height: 45, + src: item.face, + type: 'avatar', + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 4), + child: SizedBox( + width: 85, + child: Text( + item.name!, + overflow: TextOverflow.ellipsis, + softWrap: false, + textAlign: TextAlign.center, + style: TextStyle( + color: item.vip!.status == 1 + ? const Color.fromARGB(255, 251, 100, 163) + : null, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 4), + child: SizedBox( + width: 85, + child: Text( + item.title!, + overflow: TextOverflow.ellipsis, + softWrap: false, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + fontSize: 12, + ), + ), + ), + ), + ], + ); + } +} From 29bdbbfe18d86fe3c5ee1755bb25902247525b89 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 15:32:05 +0800 Subject: [PATCH 020/106] mod: playCount calc --- lib/plugin/pl_player/controller.dart | 12 +++++------- lib/services/audio_handler.dart | 2 +- lib/services/audio_session.dart | 4 ++-- lib/services/shutdown_timer_service.dart | 18 +++++++++++------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index be72eccb..ca147fd1 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -101,7 +101,7 @@ class PlPlayerController { bool _isFirstTime = true; Timer? _timer; - late Timer? _timerForSeek; + Timer? _timerForSeek; Timer? _timerForVolume; Timer? _timerForShowingVolume; Timer? _timerForGettingVolume; @@ -335,8 +335,10 @@ class PlPlayerController { }) { // 如果实例尚未创建,则创建一个新实例 _instance ??= PlPlayerController._(); - _instance!._playerCount.value += 1; - _videoType.value = videoType; + if (videoType != 'none') { + _instance!._playerCount.value += 1; + _videoType.value = videoType; + } return _instance!; } @@ -1120,9 +1122,6 @@ class PlPlayerController { } Future dispose({String type = 'single'}) async { - print('dispose'); - print('dispose: ${playerCount.value}'); - // 每次减1,最后销毁 if (type == 'single' && playerCount.value > 1) { _playerCount.value -= 1; @@ -1132,7 +1131,6 @@ class PlPlayerController { } _playerCount.value = 0; try { - print('dispose dispose ---------'); _timer?.cancel(); _timerForVolume?.cancel(); _timerForGettingVolume?.cancel(); diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index bf98298b..b0ca8cd7 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -26,7 +26,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { static final List _item = []; Box setting = GStrorage.setting; bool enableBackgroundPlay = false; - PlPlayerController player = PlPlayerController.getInstance(); + PlPlayerController player = PlPlayerController.getInstance(videoType: 'none'); VideoPlayerServiceHandler() { revalidateSetting(); diff --git a/lib/services/audio_session.dart b/lib/services/audio_session.dart index ea83a30a..53b497ae 100644 --- a/lib/services/audio_session.dart +++ b/lib/services/audio_session.dart @@ -18,7 +18,7 @@ class AudioSessionHandler { session.configure(const AudioSessionConfiguration.music()); session.interruptionEventStream.listen((event) { - final player = PlPlayerController.getInstance(); + final player = PlPlayerController.getInstance(videoType: 'none'); if (event.begin) { if (!player.playerStatus.playing) return; switch (event.type) { @@ -51,7 +51,7 @@ class AudioSessionHandler { // 耳机拔出暂停 session.becomingNoisyEventStream.listen((_) { - final player = PlPlayerController.getInstance(); + final player = PlPlayerController.getInstance(videoType: 'none'); if (player.playerStatus.playing) { player.pause(); } diff --git a/lib/services/shutdown_timer_service.dart b/lib/services/shutdown_timer_service.dart index aa9c5ceb..156b63c8 100644 --- a/lib/services/shutdown_timer_service.dart +++ b/lib/services/shutdown_timer_service.dart @@ -29,8 +29,8 @@ class ShutdownTimerService { return; } SmartDialog.showToast("设置 $scheduledExitInMinutes 分钟后定时关闭"); - _shutdownTimer = Timer(Duration(minutes: scheduledExitInMinutes), - () => _shutdownDecider()); + _shutdownTimer = Timer( + Duration(minutes: scheduledExitInMinutes), () => _shutdownDecider()); } void _showTimeUpButPauseDialog() { @@ -59,7 +59,7 @@ class ShutdownTimerService { // Start the 10-second timer to auto close the dialog _autoCloseDialogTimer?.cancel(); _autoCloseDialogTimer = Timer(const Duration(seconds: 10), () { - SmartDialog.dismiss();// Close the dialog + SmartDialog.dismiss(); // Close the dialog _executeShutdown(); }); return AlertDialog( @@ -88,7 +88,8 @@ class ShutdownTimerService { _showShutdownDialog(); return; } - PlPlayerController plPlayerController = PlPlayerController.getInstance(); + PlPlayerController plPlayerController = + PlPlayerController.getInstance(videoType: 'none'); if (!exitApp && !waitForPlayingCompleted) { if (!plPlayerController.playerStatus.playing) { //仅提示用户 @@ -108,19 +109,22 @@ class ShutdownTimerService { //该方法依赖耦合实现,不够优雅 isWaiting = true; } - void handleWaitingFinished(){ - if(isWaiting){ + + void handleWaitingFinished() { + if (isWaiting) { _showShutdownDialog(); isWaiting = false; } } + void _executeShutdown() { if (exitApp) { //退出app exit(0); } else { //暂停播放 - PlPlayerController plPlayerController = PlPlayerController.getInstance(); + PlPlayerController plPlayerController = + PlPlayerController.getInstance(videoType: 'none'); if (plPlayerController.playerStatus.playing) { plPlayerController.pause(); waitForPlayingCompleted = true; From 0e52e0288c0d9772df5615bf0121788a201cc7b7 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 16:08:10 +0800 Subject: [PATCH 021/106] =?UTF-8?q?opt:=20=E4=BC=98=E5=8C=96=E6=8A=95?= =?UTF-8?q?=E5=B8=81Dialog=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bangumi/introduction/controller.dart | 66 ++++++++----------- lib/pages/setting/widgets/select_dialog.dart | 2 +- .../video/detail/introduction/controller.dart | 64 +++++++----------- 3 files changed, 52 insertions(+), 80 deletions(-) diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index b26028cf..575a77de 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -131,51 +131,37 @@ class BangumiIntroController extends GetxController { builder: (context) { return AlertDialog( title: const Text('选择投币个数'), - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 24), content: StatefulBuilder(builder: (context, StateSetter setState) { return Column( mainAxisSize: MainAxisSize.min, - children: [ - RadioListTile( - value: 1, - title: const Text('1枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - RadioListTile( - value: 2, - title: const Text('2枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - ], + children: [1, 2] + .map( + (e) => RadioListTile( + value: e, + title: Text('$e枚'), + groupValue: _tempThemeValue, + onChanged: (value) async { + _tempThemeValue = value!; + setState(() {}); + var res = await VideoHttp.coinVideo( + bvid: bvid, multiply: _tempThemeValue); + if (res['status']) { + SmartDialog.showToast('投币成功 👏'); + hasCoin.value = true; + bangumiDetail.value.stat!['coins'] = + bangumiDetail.value.stat!['coins'] + + _tempThemeValue; + } else { + SmartDialog.showToast(res['msg']); + } + Get.back(); + }, + ), + ) + .toList(), ); }), - actions: [ - TextButton(onPressed: () => Get.back(), child: const Text('取消')), - TextButton( - onPressed: () async { - var res = await VideoHttp.coinVideo( - bvid: bvid, multiply: _tempThemeValue); - if (res['status']) { - SmartDialog.showToast('投币成功 👏'); - hasCoin.value = true; - bangumiDetail.value.stat!['coins'] = - bangumiDetail.value.stat!['coins'] + _tempThemeValue; - } else { - SmartDialog.showToast(res['msg']); - } - Get.back(); - }, - child: const Text('确定'), - ) - ], ); }); } diff --git a/lib/pages/setting/widgets/select_dialog.dart b/lib/pages/setting/widgets/select_dialog.dart index 50229f9e..ab5f2ce4 100644 --- a/lib/pages/setting/widgets/select_dialog.dart +++ b/lib/pages/setting/widgets/select_dialog.dart @@ -29,7 +29,7 @@ class _SelectDialogState extends State> { return AlertDialog( title: Text(widget.title), - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 24), content: StatefulBuilder(builder: (context, StateSetter setState) { return SingleChildScrollView( child: Column( diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 6469b5c5..8d602b83 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -219,50 +219,36 @@ class VideoIntroController extends GetxController { builder: (context) { return AlertDialog( title: const Text('选择投币个数'), - contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), + contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 24), content: StatefulBuilder(builder: (context, StateSetter setState) { return Column( mainAxisSize: MainAxisSize.min, - children: [ - RadioListTile( - value: 1, - title: const Text('1枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - RadioListTile( - value: 2, - title: const Text('2枚'), - groupValue: _tempThemeValue, - onChanged: (value) { - _tempThemeValue = value!; - Get.appUpdate(); - }, - ), - ], + children: [1, 2] + .map( + (e) => RadioListTile( + value: e, + title: Text('$e枚'), + groupValue: _tempThemeValue, + onChanged: (value) async { + _tempThemeValue = value!; + setState(() {}); + var res = await VideoHttp.coinVideo( + bvid: bvid, multiply: _tempThemeValue); + if (res['status']) { + SmartDialog.showToast('投币成功 👏'); + hasCoin.value = true; + videoDetail.value.stat!.coin = + videoDetail.value.stat!.coin! + _tempThemeValue; + } else { + SmartDialog.showToast(res['msg']); + } + Get.back(); + }, + ), + ) + .toList(), ); }), - actions: [ - TextButton(onPressed: () => Get.back(), child: const Text('取消')), - TextButton( - onPressed: () async { - var res = await VideoHttp.coinVideo( - bvid: bvid, multiply: _tempThemeValue); - if (res['status']) { - SmartDialog.showToast('投币成功 👏'); - hasCoin.value = true; - videoDetail.value.stat!.coin = - videoDetail.value.stat!.coin! + _tempThemeValue; - } else { - SmartDialog.showToast(res['msg']); - } - Get.back(); - }, - child: const Text('确定')) - ], ); }); } From f24291134c84c864b5047ed90f1d7a628c30722b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 17:44:19 +0800 Subject: [PATCH 022/106] =?UTF-8?q?feat:=20=E5=90=88=E9=9B=86=E5=B0=81?= =?UTF-8?q?=E9=9D=A2=E5=B1=95=E7=A4=BA=E3=80=81=E5=B0=81=E9=9D=A2=E5=88=87?= =?UTF-8?q?=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/pages_bottom_sheet.dart | 44 ++++++++++++------- lib/models/model_hot_video_item.dart | 3 ++ lib/models/video_detail_res.dart | 6 +++ .../bangumi/introduction/controller.dart | 8 ++-- lib/pages/bangumi/introduction/view.dart | 4 +- lib/pages/bangumi/widgets/bangumi_panel.dart | 3 +- lib/pages/video/detail/controller.dart | 3 ++ .../video/detail/introduction/controller.dart | 12 +++-- lib/pages/video/detail/introduction/view.dart | 7 ++- .../introduction/widgets/page_panel.dart | 6 +-- .../introduction/widgets/season_panel.dart | 1 + lib/pages/video/detail/view.dart | 16 ++++--- 12 files changed, 78 insertions(+), 35 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index c64b58b6..54f14654 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../models/common/video_episode_type.dart'; @@ -44,25 +45,38 @@ class EpisodeBottomSheet { title = '第${episode.title}话 ${episode.longTitle!}'; break; } - return ListTile( + return InkWell( onTap: () { SmartDialog.showToast('切换至「$title」'); changeFucCall.call(episode, index); }, - dense: false, - leading: isCurrentIndex - ? Image.asset( - 'assets/images/live.gif', - color: primary, - height: 12, - ) - : null, - title: Text( - title, - style: TextStyle( - fontSize: 14, - color: isCurrentIndex ? primary : onSurface, - ), + child: Padding( + padding: const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8), + child: isFullScreen + ? Text( + title, + maxLines: 1, + style: TextStyle( + fontSize: 14, + color: isCurrentIndex ? primary : onSurface, + ), + ) + : Row( + children: [ + NetworkImgLayer(width: 130, height: 75, src: episode.cover), + const SizedBox(width: 10), + Expanded( + child: Text( + title, + maxLines: 2, + style: TextStyle( + fontSize: 14, + color: isCurrentIndex ? primary : onSurface, + ), + ), + ), + ], + ), ), ); } diff --git a/lib/models/model_hot_video_item.dart b/lib/models/model_hot_video_item.dart index db331a4c..ab7e6e04 100644 --- a/lib/models/model_hot_video_item.dart +++ b/lib/models/model_hot_video_item.dart @@ -23,6 +23,7 @@ class HotVideoItemModel { this.dimension, this.shortLinkV2, this.firstFrame, + this.cover, this.pubLocation, this.seasontype, this.isOgv, @@ -50,6 +51,7 @@ class HotVideoItemModel { Dimension? dimension; String? shortLinkV2; String? firstFrame; + String? cover; String? pubLocation; int? seasontype; bool? isOgv; @@ -77,6 +79,7 @@ class HotVideoItemModel { dimension = Dimension.fromMap(json['dimension']); shortLinkV2 = json["short_link_v2"]; firstFrame = json["first_frame"]; + cover = json["first_frame"]; pubLocation = json["pub_location"]; seasontype = json["seasontype"]; isOgv = json["isOgv"]; diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index a82b6fbb..b7b1b481 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -382,6 +382,7 @@ class Part { String? weblink; Dimension? dimension; String? firstFrame; + String? cover; Part({ this.cid, @@ -393,6 +394,7 @@ class Part { this.weblink, this.dimension, this.firstFrame, + this.cover, }); fromRawJson(String str) => Part.fromJson(json.decode(str)); @@ -411,6 +413,7 @@ class Part { ? null : Dimension.fromJson(json["dimension"]); firstFrame = json["first_frame"]; + cover = json["first_frame"]; } Map toJson() { @@ -634,6 +637,7 @@ class EpisodeItem { this.attribute, this.page, this.bvid, + this.cover, }); int? seasonId; int? sectionId; @@ -644,6 +648,7 @@ class EpisodeItem { int? attribute; Part? page; String? bvid; + String? cover; EpisodeItem.fromJson(Map json) { seasonId = json['season_id']; @@ -655,6 +660,7 @@ class EpisodeItem { attribute = json['attribute']; page = Part.fromJson(json['page']); bvid = json['bvid']; + cover = json['arc']['pic']; } } diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 575a77de..65cd5dd8 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -215,7 +215,7 @@ class BangumiIntroController extends GetxController { } // 修改分P或番剧分集 - Future changeSeasonOrbangu(bvid, cid, aid) async { + Future changeSeasonOrbangu(bvid, cid, aid, cover) async { // 重新获取视频资源 VideoDetailController videoDetailCtr = Get.find(tag: Get.arguments['heroTag']); @@ -223,6 +223,7 @@ class BangumiIntroController extends GetxController { videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; videoDetailCtr.oid.value = aid; + videoDetailCtr.cover.value = cover; videoDetailCtr.queryVideoUrl(); // 重新请求评论 try { @@ -281,7 +282,8 @@ class BangumiIntroController extends GetxController { int cid = episodes[nextIndex].cid!; String bvid = episodes[nextIndex].bvid!; int aid = episodes[nextIndex].aid!; - changeSeasonOrbangu(bvid, cid, aid); + String cover = episodes[nextIndex].cover!; + changeSeasonOrbangu(bvid, cid, aid, cover); } // 播放器底栏 选集 回调 @@ -302,7 +304,7 @@ class BangumiIntroController extends GetxController { sheetHeight: Get.size.height, isFullScreen: true, changeFucCall: (item, index) { - changeSeasonOrbangu(item.bvid, item.cid, item.aid); + changeSeasonOrbangu(item.bvid, item.cid, item.aid, item.cover); SmartDialog.dismiss(); }, ).buildShowContent(Get.context!), diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index e47db480..6876da79 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -322,8 +322,8 @@ class _BangumiInfoState extends State { pages: widget.bangumiDetail!.episodes!, cid: cid! ?? widget.bangumiDetail!.episodes!.first.cid!, sheetHeight: sheetHeight, - changeFuc: (bvid, cid, aid) => - bangumiIntroController.changeSeasonOrbangu(bvid, cid, aid), + changeFuc: (bvid, cid, aid, cover) => bangumiIntroController + .changeSeasonOrbangu(bvid, cid, aid, cover), bangumiDetail: bangumiIntroController.bangumiDetail.value, bangumiIntroController: bangumiIntroController, ) diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index 3e965f34..3df7ce25 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -84,11 +84,12 @@ class _BangumiPanelState extends State { item.bvid, item.cid, item.aid, + item.cover, ); if (_bottomSheetController != null) { _bottomSheetController?.close(); } - currentIndex = i; + currentIndex.value = i; scrollToIndex(); } diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 3cc43005..5fecde8d 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -73,6 +73,7 @@ class VideoDetailController extends GetxController ReplyItemModel? firstFloor; final scaffoldKey = GlobalKey(); RxString bgCover = ''.obs; + RxString cover = ''.obs; PlPlayerController plPlayerController = PlPlayerController.getInstance(); late VideoItem firstVideo; @@ -120,10 +121,12 @@ class VideoDetailController extends GetxController var args = argMap['videoItem']; if (args.pic != null && args.pic != '') { videoItem['pic'] = args.pic; + cover.value = args.pic; } } if (keys.contains('pic')) { videoItem['pic'] = argMap['pic']; + cover.value = argMap['pic']; } } tabCtr = TabController(length: 2, vsync: this); diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 8d602b83..b9a3ef93 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -432,7 +432,7 @@ class VideoIntroController extends GetxController { } // 修改分P或番剧分集 - Future changeSeasonOrbangu(bvid, cid, aid) async { + Future changeSeasonOrbangu(bvid, cid, aid, cover) async { // 重新获取视频资源 final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); @@ -447,6 +447,7 @@ class VideoIntroController extends GetxController { videoDetailCtr.oid.value = aid ?? IdUtils.bv2av(bvid); videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; + videoDetailCtr.cover.value = cover; videoDetailCtr.queryVideoUrl(); // 重新请求评论 try { @@ -494,6 +495,7 @@ class VideoIntroController extends GetxController { void nextPlay() { final List episodes = []; bool isPages = false; + late String cover; if (videoDetail.value.ugcSeason != null) { final UgcSeason ugcSeason = videoDetail.value.ugcSeason!; final List sections = ugcSeason.sections!; @@ -510,6 +512,7 @@ class VideoIntroController extends GetxController { final int currentIndex = episodes.indexWhere((e) => e.cid == lastPlayCid.value); int nextIndex = currentIndex + 1; + cover = episodes[nextIndex].cover; final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); final PlayRepeat platRepeat = videoDetailCtr.plPlayerController.playRepeat; @@ -526,7 +529,7 @@ class VideoIntroController extends GetxController { final int cid = episodes[nextIndex].cid!; final String rBvid = isPages ? bvid : episodes[nextIndex].bvid; final int rAid = isPages ? IdUtils.bv2av(bvid) : episodes[nextIndex].aid!; - changeSeasonOrbangu(rBvid, cid, rAid); + changeSeasonOrbangu(rBvid, cid, rAid, cover); } // 设置关注分组 @@ -591,10 +594,11 @@ class VideoIntroController extends GetxController { isFullScreen: true, changeFucCall: (item, index) { if (dataType == VideoEpidoesType.videoEpisode) { - changeSeasonOrbangu(IdUtils.av2bv(item.aid), item.cid, item.aid); + changeSeasonOrbangu( + IdUtils.av2bv(item.aid), item.cid, item.aid, item.cover); } if (dataType == VideoEpidoesType.videoPart) { - changeSeasonOrbangu(bvid, item.cid, null); + changeSeasonOrbangu(bvid, item.cid, null, item.cover); } SmartDialog.dismiss(); }, diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 597b6def..47404658 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -383,11 +383,12 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ? videoIntroController.lastPlayCid.value : widget.videoDetail!.pages!.first.cid, sheetHeight: videoDetailCtr.sheetHeight.value, - changeFuc: (bvid, cid, aid) => + changeFuc: (bvid, cid, aid, cover) => videoIntroController.changeSeasonOrbangu( bvid, cid, aid, + cover, ), videoIntroCtr: videoIntroController, ), @@ -401,10 +402,12 @@ class _VideoInfoState extends State with TickerProviderStateMixin { pages: widget.videoDetail!.pages!, cid: videoIntroController.lastPlayCid.value, sheetHeight: videoDetailCtr.sheetHeight.value, - changeFuc: (cid) => videoIntroController.changeSeasonOrbangu( + changeFuc: (cid, cover) => + videoIntroController.changeSeasonOrbangu( videoIntroController.bvid, cid, null, + cover, ), videoIntroCtr: videoIntroController, ), diff --git a/lib/pages/video/detail/introduction/widgets/page_panel.dart b/lib/pages/video/detail/introduction/widgets/page_panel.dart index 83db2d52..266f5566 100644 --- a/lib/pages/video/detail/introduction/widgets/page_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/page_panel.dart @@ -58,7 +58,7 @@ class _PagesPanelState extends State { } void changeFucCall(item, i) async { - widget.changeFuc?.call(item.cid); + widget.changeFuc?.call(item.cid, item.cover); currentIndex.value = i; _bottomSheetController?.close(); scrollToIndex(); @@ -129,7 +129,7 @@ class _PagesPanelState extends State { ), ), Container( - height: 35, + height: 55, margin: const EdgeInsets.only(bottom: 8), child: ListView.builder( scrollDirection: Axis.horizontal, @@ -163,7 +163,7 @@ class _PagesPanelState extends State { Expanded( child: Text( widget.pages[i].pagePart!, - maxLines: 1, + maxLines: 2, style: TextStyle( fontSize: 13, color: isCurrentIndex diff --git a/lib/pages/video/detail/introduction/widgets/season_panel.dart b/lib/pages/video/detail/introduction/widgets/season_panel.dart index 2afefcb4..fdfec6f9 100644 --- a/lib/pages/video/detail/introduction/widgets/season_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/season_panel.dart @@ -67,6 +67,7 @@ class _SeasonPanelState extends State { IdUtils.av2bv(item.aid), item.cid, item.aid, + item.cover, ); currentIndex.value = i; _bottomSheetController?.close(); diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 0152a2cb..7f1d6039 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -458,11 +458,17 @@ class _VideoDetailPageState extends State onTap: () { handlePlay(); }, - child: NetworkImgLayer( - type: 'emote', - src: vdCtr.videoItem['pic'], - width: Get.width, - height: videoHeight.value, + child: Obx( + () => AnimatedOpacity( + duration: const Duration(milliseconds: 100), // 渐变动画的持续时间 + opacity: 1, // 设置不透明度 + child: NetworkImgLayer( + type: 'emote', + src: vdCtr.cover.value, + width: Get.width, + height: videoHeight.value, + ), + ), ), ), Positioned( From 257596cb9eb025ccc674c413c575e59fe4c0cf7e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 20:40:23 +0800 Subject: [PATCH 023/106] =?UTF-8?q?mod:=20=E9=BB=98=E8=AE=A4=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E7=A1=AC=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/setting/play_setting.dart | 2 +- lib/pages/video/detail/controller.dart | 4 ++-- lib/plugin/pl_player/controller.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index 07d736e3..4a8495e5 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -131,7 +131,7 @@ class _PlaySettingState extends State { title: '开启硬解', subTitle: '以较低功耗播放视频', setKey: SettingBoxKey.enableHA, - defaultVal: true, + defaultVal: false, ), const SetSwitchItem( title: '观看人数', diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 4613c7ca..127e81a7 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -59,7 +59,7 @@ class VideoDetailController extends GetxController // 封面图的展示 RxBool isShowCover = true.obs; // 硬解 - RxBool enableHA = true.obs; + RxBool enableHA = false.obs; /// 本地存储 Box userInfoCache = GStrorage.userInfo; @@ -128,7 +128,7 @@ class VideoDetailController extends GetxController tabCtr = TabController(length: 2, vsync: this); autoPlay.value = setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true); - enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: true); + enableHA.value = setting.get(SettingBoxKey.enableHA, defaultValue: false); enableRelatedVideo = setting.get(SettingBoxKey.enableRelatedVideo, defaultValue: true); if (userInfo == null || diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index be72eccb..a31ce0b8 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -351,7 +351,7 @@ class PlPlayerController { // 初始化播放速度 double speed = 1.0, // 硬件加速 - bool enableHA = true, + bool enableHA = false, double? width, double? height, Duration? duration, From cbb7b90bf9ce8678fc2a9f585a5b4f8a3a21a016 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 22:11:56 +0800 Subject: [PATCH 024/106] mod --- lib/common/widgets/network_img_layer.dart | 1 - lib/pages/video/detail/widgets/header_control.dart | 2 +- lib/utils/utils.dart | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 173db853..bda8ee5c 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -36,7 +36,6 @@ class NetworkImgLayer extends StatelessWidget { final int defaultImgQuality = GlobalData().imgQuality; final String imageUrl = '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp'; - // print(imageUrl); int? memCacheWidth, memCacheHeight; double aspectRatio = (width / height).toDouble(); diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 6acd20d7..544d93e0 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -446,7 +446,7 @@ class _HeaderControlState extends State { children: [ RadioListTile( value: -1, - title: const Text('关闭弹幕'), + title: const Text('关闭字幕'), groupValue: tempThemeValue, onChanged: (value) { tempThemeValue = value!; diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 987f57c1..b40e9bfe 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -109,7 +109,6 @@ class Utils { toInt: false, formatType: formatType); } - print('distance: $distance'); if (distance <= 60) { return '刚刚'; } else if (distance <= 3600) { From aff39c291dc669158277301541cb98c9ed8ec0b0 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 27 Apr 2024 22:17:10 +0800 Subject: [PATCH 025/106] =?UTF-8?q?fix:=20=E5=90=88=E9=9B=86cover=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/pages_bottom_sheet.dart | 46 +++++++++++++++++++----------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index 54f14654..00233a07 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -45,25 +45,37 @@ class EpisodeBottomSheet { title = '第${episode.title}话 ${episode.longTitle!}'; break; } - return InkWell( - onTap: () { - SmartDialog.showToast('切换至「$title」'); - changeFucCall.call(episode, index); - }, - child: Padding( - padding: const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8), - child: isFullScreen - ? Text( - title, - maxLines: 1, + return isFullScreen || episode?.cover == null + ? ListTile( + onTap: () { + SmartDialog.showToast('切换至「$title」'); + changeFucCall.call(episode, index); + }, + dense: false, + leading: isCurrentIndex + ? Image.asset( + 'assets/images/live.gif', + color: primary, + height: 12, + ) + : null, + title: Text(title, style: TextStyle( fontSize: 14, color: isCurrentIndex ? primary : onSurface, - ), - ) - : Row( + ))) + : InkWell( + onTap: () { + SmartDialog.showToast('切换至「$title」'); + changeFucCall.call(episode, index); + }, + child: Padding( + padding: + const EdgeInsets.only(left: 14, right: 14, top: 8, bottom: 8), + child: Row( children: [ - NetworkImgLayer(width: 130, height: 75, src: episode.cover), + NetworkImgLayer( + width: 130, height: 75, src: episode?.cover ?? ''), const SizedBox(width: 10), Expanded( child: Text( @@ -77,8 +89,8 @@ class EpisodeBottomSheet { ), ], ), - ), - ); + ), + ); } Widget buildTitle() { From c653a60f05501f983bb0d98c529fb240409bba6e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 00:06:08 +0800 Subject: [PATCH 026/106] =?UTF-8?q?feat:=20=E6=B4=BB=E5=8A=A8=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=8A=A8=E6=80=81=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/dynamics/result.dart | 3 + lib/pages/dynamics/widgets/forward_panel.dart | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index 2f7c2d40..bc7105d1 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -414,6 +414,7 @@ class DynamicMajorModel { this.none, this.type, this.courses, + this.common, }); DynamicArchiveModel? archive; @@ -429,6 +430,7 @@ class DynamicMajorModel { // MAJOR_TYPE_OPUS 图文/文章 String? type; Map? courses; + Map? common; DynamicMajorModel.fromJson(Map json) { archive = json['archive'] != null @@ -452,6 +454,7 @@ class DynamicMajorModel { json['none'] != null ? DynamicNoneModel.fromJson(json['none']) : null; type = json['type']; courses = json['courses'] ?? {}; + common = json['common'] ?? {}; } } diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index 5a8d9f17..76c7b24e 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/utils/utils.dart'; import 'additional_panel.dart'; @@ -182,6 +183,61 @@ Widget forWard(item, context, ctr, source, {floor = 1}) { ) ], ); + // 活动 + case 'DYNAMIC_TYPE_COMMON_SQUARE': + return Padding( + padding: const EdgeInsets.only(top: 8), + child: InkWell( + onTap: () { + Get.toNamed('/webview', parameters: { + 'url': item.modules.moduleDynamic.major.common['jump_url'], + 'type': 'url', + 'pageTitle': item.modules.moduleDynamic.major.common['title'] + }); + }, + child: Container( + width: double.infinity, + padding: + const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10), + color: Theme.of(context).dividerColor.withOpacity(0.08), + child: Row( + children: [ + NetworkImgLayer( + width: 45, + height: 45, + src: item.modules.moduleDynamic.major.common['cover'], + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + item.modules.moduleDynamic.major.common['title'], + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Text( + item.modules.moduleDynamic.major.common['desc'], + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ) + ], + ), + // TextButton(onPressed: () {}, child: Text('123')) + ), + ), + ); default: return const SizedBox( width: double.infinity, From 750e9d2b58635d70c0627d64adaf1ea5dd7621db Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 07:39:55 +0800 Subject: [PATCH 027/106] =?UTF-8?q?revert:=20=E8=AF=84=E8=AE=BA=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=98=E5=85=88=E5=B1=95=E7=A4=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/dynamics/detail/view.dart | 6 +++--- lib/pages/video/detail/controller.dart | 3 +-- lib/pages/video/detail/reply/view.dart | 8 ++++---- .../video/detail/reply/widgets/reply_item.dart | 6 ++---- lib/pages/video/detail/reply_reply/controller.dart | 10 +--------- lib/pages/video/detail/reply_reply/view.dart | 14 ++------------ 6 files changed, 13 insertions(+), 34 deletions(-) diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index 11636b5b..bd07921b 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -106,7 +106,7 @@ class _DynamicDetailPageState extends State } // 查看二级评论 - void replyReply(replyItem, currentReply) { + void replyReply(replyItem) { int oid = replyItem.oid; int rpid = replyItem.rpid!; Get.to( @@ -324,8 +324,8 @@ class _DynamicDetailPageState extends State replyItem: replyList[index], showReplyRow: true, replyLevel: '1', - replyReply: (replyItem, currentReply) => - replyReply(replyItem, currentReply), + replyReply: (replyItem) => + replyReply(replyItem), replyType: ReplyType.values[replyType], addReply: (replyItem) { replyList[index] diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index c6c4bef6..8efc8ea1 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -165,7 +165,7 @@ class VideoDetailController extends GetxController getSubtitle(); } - showReplyReplyPanel(oid, fRpid, firstFloor, currentReply) { + showReplyReplyPanel(oid, fRpid, firstFloor) { replyReplyBottomSheetCtr = scaffoldKey.currentState?.showBottomSheet((BuildContext context) { return VideoReplyReplyPanel( @@ -178,7 +178,6 @@ class VideoDetailController extends GetxController replyType: ReplyType.video, source: 'videoDetail', sheetHeight: sheetHeight.value, - currentReply: currentReply, ); }); replyReplyBottomSheetCtr?.closed.then((value) { diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 420f349c..4c533647 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -110,7 +110,7 @@ class _VideoReplyPanelState extends State } // 展示二级回复 - void replyReply(replyItem, currentReply) { + void replyReply(replyItem) { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); if (replyItem != null) { @@ -118,7 +118,7 @@ class _VideoReplyPanelState extends State videoDetailCtr.fRpid = replyItem.rpid!; videoDetailCtr.firstFloor = replyItem; videoDetailCtr.showReplyReplyPanel( - replyItem.oid, replyItem.rpid!, replyItem, currentReply); + replyItem.oid, replyItem.rpid!, replyItem); } } @@ -229,8 +229,8 @@ class _VideoReplyPanelState extends State .replyList[index], showReplyRow: true, replyLevel: replyLevel, - replyReply: (replyItem, currentReply) => - replyReply(replyItem, currentReply), + replyReply: (replyItem) => + replyReply(replyItem), replyType: ReplyType.video, ); } diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 8a8e4af7..ecc2dd02 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -531,10 +531,8 @@ InlineSpan buildContent( TextSpan( text: str, recognizer: TapGestureRecognizer() - ..onTap = () => replyReply?.call( - replyItem.root == 0 ? replyItem : fReplyItem, - replyItem, - ), + ..onTap = () => + replyReply?.call(replyItem.root == 0 ? replyItem : fReplyItem), ), ); } diff --git a/lib/pages/video/detail/reply_reply/controller.dart b/lib/pages/video/detail/reply_reply/controller.dart index 4c553e29..e94aaea5 100644 --- a/lib/pages/video/detail/reply_reply/controller.dart +++ b/lib/pages/video/detail/reply_reply/controller.dart @@ -26,7 +26,7 @@ class VideoReplyReplyController extends GetxController { currentPage = 0; } - Future queryReplyList({type = 'init', currentReply}) async { + Future queryReplyList({type = 'init'}) async { if (type == 'init') { currentPage = 0; } @@ -63,14 +63,6 @@ class VideoReplyReplyController extends GetxController { // res['data'].replies.addAll(replyList); } } - if (replyList.isNotEmpty && currentReply != null) { - int indexToRemove = - replyList.indexWhere((item) => currentReply.rpid == item.rpid); - // 如果找到了指定ID的项,则移除 - if (indexToRemove != -1) { - replyList.removeAt(indexToRemove); - } - } isLoadingMore = false; return res; } diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index 6441c600..3fe84c71 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -20,7 +20,6 @@ class VideoReplyReplyPanel extends StatefulWidget { this.source, this.replyType, this.sheetHeight, - this.currentReply, super.key, }); final int? oid; @@ -30,7 +29,6 @@ class VideoReplyReplyPanel extends StatefulWidget { final String? source; final ReplyType? replyType; final double? sheetHeight; - final dynamic currentReply; @override State createState() => _VideoReplyReplyPanelState(); @@ -65,9 +63,7 @@ class _VideoReplyReplyPanelState extends State { }, ); - _futureBuilderFuture = _videoReplyReplyController.queryReplyList( - currentReply: widget.currentReply, - ); + _futureBuilderFuture = _videoReplyReplyController.queryReplyList(); } void replyReply(replyItem) {} @@ -111,9 +107,7 @@ class _VideoReplyReplyPanelState extends State { onRefresh: () async { setState(() {}); _videoReplyReplyController.currentPage = 0; - return await _videoReplyReplyController.queryReplyList( - currentReply: widget.currentReply, - ); + return await _videoReplyReplyController.queryReplyList(); }, child: CustomScrollView( controller: _videoReplyReplyController.scrollController, @@ -146,10 +140,6 @@ class _VideoReplyReplyPanelState extends State { if (snapshot.connectionState == ConnectionState.done) { Map? data = snapshot.data; if (data != null && data['status']) { - if (widget.currentReply != null) { - _videoReplyReplyController.replyList - .insert(0, widget.currentReply); - } // 请求成功 return Obx( () => SliverList( From 8a6b4f987f4aeabe91c0d2d98adc898be044521f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 22:03:19 +0800 Subject: [PATCH 028/106] revert: NavigationBar Color --- lib/main.dart | 59 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3877685c..43bcf930 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -65,6 +65,20 @@ void main() async { }, ); + // 小白条、导航栏沉浸 + if (Platform.isAndroid) { + List versionParts = Platform.version.split('.'); + int androidVersion = int.parse(versionParts[0]); + if (androidVersion >= 29) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + } + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + systemNavigationBarDividerColor: Colors.transparent, + statusBarColor: Colors.transparent, + )); + } + Data.init(); GlobalData(); PiliSchame.init(); @@ -130,26 +144,33 @@ class MyApp extends StatelessWidget { ); } - ThemeData themeData = ThemeData( - colorScheme: currentThemeValue == ThemeType.dark - ? darkColorScheme - : lightColorScheme, - ); + // ThemeData themeData = ThemeData( + // colorScheme: currentThemeValue == ThemeType.dark + // ? darkColorScheme + // : lightColorScheme, + // ); - // 小白条、导航栏沉浸 - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( - systemNavigationBarColor: GlobalData().enableMYBar - ? const Color(0x00010000) - : themeData.canvasColor, - systemNavigationBarDividerColor: GlobalData().enableMYBar - ? const Color(0x00010000) - : themeData.canvasColor, - systemNavigationBarIconBrightness: currentThemeValue == ThemeType.dark - ? Brightness.light - : Brightness.dark, - statusBarColor: Colors.transparent, - )); + // // 小白条、导航栏沉浸 + // if (Platform.isAndroid) { + // List versionParts = Platform.version.split('.'); + // int androidVersion = int.parse(versionParts[0]); + // if (androidVersion >= 29) { + // SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + // } + // SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( + // systemNavigationBarColor: GlobalData().enableMYBar + // ? const Color(0x00010000) + // : themeData.canvasColor, + // systemNavigationBarDividerColor: GlobalData().enableMYBar + // ? const Color(0x00010000) + // : themeData.canvasColor, + // systemNavigationBarIconBrightness: + // currentThemeValue == ThemeType.dark + // ? Brightness.light + // : Brightness.dark, + // statusBarColor: Colors.transparent, + // )); + // } // 图片缓存 // PaintingBinding.instance.imageCache.maximumSizeBytes = 1000 << 20; From bc4fb0e0ae40cb9a77ebe18893f8a4cbd34071c5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 22:27:14 +0800 Subject: [PATCH 029/106] fix: videoDetail cover null --- lib/pages/video/detail/controller.dart | 27 ++++++++++--------- .../video/detail/introduction/controller.dart | 1 + lib/utils/app_scheme.dart | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index c6c4bef6..bb099255 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -115,20 +115,15 @@ class VideoDetailController extends GetxController super.onInit(); final Map argMap = Get.arguments; userInfo = userInfoCache.get('userInfoCache'); - var keys = argMap.keys.toList(); - if (keys.isNotEmpty) { - if (keys.contains('videoItem')) { - var args = argMap['videoItem']; - if (args.pic != null && args.pic != '') { - videoItem['pic'] = args.pic; - cover.value = args.pic; - } - } - if (keys.contains('pic')) { - videoItem['pic'] = argMap['pic']; - cover.value = argMap['pic']; - } + if (argMap.containsKey('videoItem')) { + var args = argMap['videoItem']; + updateCover(args.pic); } + + if (argMap.containsKey('pic')) { + updateCover(argMap['pic']); + } + tabCtr = TabController(length: 2, vsync: this); autoPlay.value = setting.get(SettingBoxKey.autoPlayEnable, defaultValue: true); @@ -551,4 +546,10 @@ class VideoDetailController extends GetxController }, ); } + + void updateCover(String? pic) { + if (pic != null && pic != '') { + cover.value = videoItem['pic'] = pic; + } + } } diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index b9a3ef93..2ced79f0 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -90,6 +90,7 @@ class VideoIntroController extends GetxController { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); videoDetailCtr.tabs.value = ['简介', '评论 ${result['data']?.stat?.reply}']; + videoDetailCtr.cover.value = result['data'].pic ?? ''; // 获取到粉丝数再返回 await queryUserStat(); } diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 9009df6f..69fa717d 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -117,7 +117,7 @@ class PiliSchame { // ignore: always_specify_types (e) => Get.toNamed('/video?bvid=$bvid&cid=$cid', arguments: { - 'pic': null, + 'pic': '', 'heroTag': heroTag, }), ); From 811487bdd42f696b7ee56c4dd8c43fed2c787217 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 28 Apr 2024 23:03:33 +0800 Subject: [PATCH 030/106] =?UTF-8?q?fix:=20=E9=87=8D=E5=9B=9E=E5=89=8D?= =?UTF-8?q?=E5=8F=B0=E5=BC=B9=E5=B9=95=E5=A0=86=E7=A7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/view.dart | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 7f1d6039..199e6b88 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -38,7 +38,7 @@ class VideoDetailPage extends StatefulWidget { } class _VideoDetailPageState extends State - with TickerProviderStateMixin, RouteAware { + with TickerProviderStateMixin, RouteAware, WidgetsBindingObserver { late VideoDetailController vdCtr; PlPlayerController? plPlayerController; final ScrollController _extendNestCtr = ScrollController(); @@ -61,6 +61,8 @@ class _VideoDetailPageState extends State late bool autoPiP; late Floating floating; bool isShowing = true; + // 生命周期监听 + late final AppLifecycleListener _lifecycleListener; @override void initState() { @@ -96,6 +98,8 @@ class _VideoDetailPageState extends State floating = vdCtr.floating!; autoEnterPip(); } + WidgetsBinding.instance.addObserver(this); + lifecycleListener(); } // 获取视频资源,初始化播放器 @@ -219,6 +223,8 @@ class _VideoDetailPageState extends State floating.dispose(); } appbarStream.close(); + WidgetsBinding.instance.removeObserver(this); + _lifecycleListener.dispose(); super.dispose(); } @@ -281,6 +287,29 @@ class _VideoDetailPageState extends State } } + // 生命周期监听 + void lifecycleListener() { + _lifecycleListener = AppLifecycleListener( + // onResume: () => _handleTransition('resume'), + // 后台 + // onInactive: () => _handleTransition('inactive'), + // 在Android和iOS端不生效 + // onHide: () => _handleTransition('hide'), + onShow: () => _handleTransition('show'), + onPause: () => _handleTransition('pause'), + onRestart: () => _handleTransition('restart'), + onDetach: () => _handleTransition('detach'), + ); + } + + void _handleTransition(String name) { + switch (name) { + case 'show' || 'restart': + plPlayerController?.danmakuController?.clear(); + break; + } + } + @override Widget build(BuildContext context) { final sizeContext = MediaQuery.sizeOf(context); From 0bb26aa46757eec6b3e5855e2e90e5f0fe4d167b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 29 Apr 2024 13:16:25 +0800 Subject: [PATCH 031/106] fix: videoDetail cover null --- lib/common/pages_bottom_sheet.dart | 2 +- lib/models/video_detail_res.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index 00233a07..2a56eb41 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -45,7 +45,7 @@ class EpisodeBottomSheet { title = '第${episode.title}话 ${episode.longTitle!}'; break; } - return isFullScreen || episode?.cover == null + return isFullScreen || episode?.cover == null || episode?.cover == '' ? ListTile( onTap: () { SmartDialog.showToast('切换至「$title」'); diff --git a/lib/models/video_detail_res.dart b/lib/models/video_detail_res.dart index b7b1b481..ae272375 100644 --- a/lib/models/video_detail_res.dart +++ b/lib/models/video_detail_res.dart @@ -412,8 +412,8 @@ class Part { dimension = json["dimension"] == null ? null : Dimension.fromJson(json["dimension"]); - firstFrame = json["first_frame"]; - cover = json["first_frame"]; + firstFrame = json["first_frame"] ?? ''; + cover = json["first_frame"] ?? ''; } Map toJson() { From 3c8a92209fa5b1725df883b9b9cc62a369708e76 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 29 Apr 2024 13:41:25 +0800 Subject: [PATCH 032/106] =?UTF-8?q?revert:=20=E8=AF=84=E8=AE=BA=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E4=BC=98=E5=85=88=E5=B1=95=E7=A4=BA=E4=BA=8C=E7=BA=A7?= =?UTF-8?q?=E8=AF=84=E8=AE=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/widgets/reply_item.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index ecc2dd02..468d2541 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -427,7 +427,7 @@ class ReplyItemRow extends StatelessWidget { if (extraRow == 1) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply!(replyItem, null), + onTap: () => replyReply!(replyItem), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), From bab0985e86f147087d8f0793ad5e9da08f67d0df Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 30 Apr 2024 15:49:00 +0800 Subject: [PATCH 033/106] =?UTF-8?q?mod:=20=E5=85=B3=E6=B3=A8=E6=8C=89?= =?UTF-8?q?=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/introduction/view.dart | 74 ++++++++----------- 1 file changed, 32 insertions(+), 42 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index a7eae6d2..8a92e9be 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -134,7 +134,6 @@ class _VideoInfoState extends State with TickerProviderStateMixin { late double sheetHeight; late final dynamic owner; late final dynamic follower; - late final dynamic followStatus; late int mid; late String memberHeroTag; late bool enableAi; @@ -163,7 +162,6 @@ class _VideoInfoState extends State with TickerProviderStateMixin { owner = widget.videoDetail!.owner; follower = Utils.numFormat(videoIntroController.userStat['follower']); - followStatus = videoIntroController.followStatus; enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true); _expandableCtr = ExpandableController(initialExpanded: false); } @@ -434,47 +432,39 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ), const Spacer(), - Obx(() => AnimatedOpacity( - opacity: - videoIntroController.followStatus.isEmpty ? 0 : 1, - duration: const Duration(milliseconds: 50), - child: SizedBox( - height: 32, - child: Obx( - () => videoIntroController.followStatus.isNotEmpty - ? TextButton( - onPressed: - videoIntroController.actionRelationMod, - style: TextButton.styleFrom( - padding: const EdgeInsets.only( - left: 8, right: 8), - foregroundColor: - followStatus['attribute'] != 0 - ? outline - : t.colorScheme.onPrimary, - backgroundColor: - followStatus['attribute'] != 0 - ? t.colorScheme.onInverseSurface - : t.colorScheme - .primary, // 设置按钮背景色 - ), - child: Text( - followStatus['attribute'] != 0 - ? '已关注' - : '关注', - style: TextStyle( - fontSize: t - .textTheme.labelMedium!.fontSize), - ), - ) - : ElevatedButton( - onPressed: - videoIntroController.actionRelationMod, - child: const Text('关注'), + Obx( + () { + final bool isFollowed = + videoIntroController.followStatus['attribute'] != 0; + return videoIntroController.followStatus.isEmpty + ? const SizedBox() + : SizedBox( + height: 32, + child: TextButton( + onPressed: + videoIntroController.actionRelationMod, + style: TextButton.styleFrom( + padding: const EdgeInsets.only( + left: 8, + right: 8, ), - ), - ), - )), + foregroundColor: isFollowed + ? outline + : t.colorScheme.onPrimary, + backgroundColor: isFollowed + ? t.colorScheme.onInverseSurface + : t.colorScheme.primary, // 设置按钮背景色 + ), + child: Text( + isFollowed ? '已关注' : '关注', + style: TextStyle( + fontSize: t.textTheme.labelMedium!.fontSize, + ), + ), + ), + ); + }, + ) ], ), ), From ba1a5486bfd259651b230f79e9d6963caf0d2f06 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 30 Apr 2024 22:40:22 +0800 Subject: [PATCH 034/106] =?UTF-8?q?opt:=20=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E6=97=B6=E8=AE=B0=E5=BF=86=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugin/pl_player/controller.dart | 14 ++++++++------ pubspec.lock | 27 +++++++++++++++------------ pubspec.yaml | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 8ee6faa0..4b6c44a1 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -395,7 +395,7 @@ class PlPlayerController { } // 配置Player 音轨、字幕等等 _videoPlayerController = await _createVideoController( - dataSource, _looping, enableHA, width, height); + dataSource, _looping, enableHA, width, height, seekTo); // 获取视频时长 00:00 _duration.value = duration ?? _videoPlayerController!.state.duration; updateDurationSecond(); @@ -426,6 +426,7 @@ class PlPlayerController { bool enableHA, double? width, double? height, + Duration seekTo, ) async { // 每次配置时先移除监听 removeListeners(); @@ -507,8 +508,9 @@ class PlPlayerController { play: false, ); } - player.open( - Media(dataSource.videoSource!, httpHeaders: dataSource.httpHeaders), + await player.open( + Media(dataSource.videoSource!, + httpHeaders: dataSource.httpHeaders, start: seekTo), play: false, ); // 音轨 @@ -530,9 +532,9 @@ class PlPlayerController { // } /// 跳转播放 - if (seekTo != Duration.zero) { - await this.seekTo(seekTo); - } + // if (seekTo != Duration.zero) { + // await this.seekTo(seekTo); + // } /// 自动播放 if (_autoPlay) { diff --git a/pubspec.lock b/pubspec.lock index a64c85c0..46d1e646 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -873,10 +873,11 @@ packages: media_kit: dependency: "direct main" description: - name: media_kit - sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a" - url: "https://pub.flutter-io.cn" - source: hosted + path: media_kit + ref: HEAD + resolved-ref: "7775f8b1aa5ec77815d5739bf25549fe37f17cae" + url: "https://github.com/media-kit/media-kit" + source: git version: "1.1.10+1" media_kit_libs_android_video: dependency: transitive @@ -913,10 +914,11 @@ packages: media_kit_libs_video: dependency: "direct main" description: - name: media_kit_libs_video - sha256: "3688e0c31482074578652bf038ce6301a5d21e1eda6b54fc3117ffeb4bdba067" - url: "https://pub.flutter-io.cn" - source: hosted + path: "libs/universal/media_kit_libs_video" + ref: HEAD + resolved-ref: "7775f8b1aa5ec77815d5739bf25549fe37f17cae" + url: "https://github.com/media-kit/media-kit" + source: git version: "1.0.4" media_kit_libs_windows_video: dependency: transitive @@ -937,10 +939,11 @@ packages: media_kit_video: dependency: "direct main" description: - name: media_kit_video - sha256: c048d11a19e379aebbe810647636e3fc6d18374637e2ae12def4ff8a4b99a882 - url: "https://pub.flutter-io.cn" - source: hosted + path: media_kit_video + ref: HEAD + resolved-ref: "7775f8b1aa5ec77815d5739bf25549fe37f17cae" + url: "https://github.com/media-kit/media-kit" + source: git version: "1.2.4" meta: dependency: transitive diff --git a/pubspec.yaml b/pubspec.yaml index 27b8b720..5ea6386e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -165,6 +165,20 @@ dev_dependencies: hive_generator: ^2.0.0 build_runner: ^2.4.8 +dependency_overrides: + media_kit: + git: + url: https://github.com/media-kit/media-kit + path: media_kit + media_kit_video: + git: + url: https://github.com/media-kit/media-kit + path: media_kit_video + media_kit_libs_video: + git: + url: https://github.com/media-kit/media-kit + path: libs/universal/media_kit_libs_video + flutter_launcher_icons: android: true ios: true From 68c73fde5655dfdac36ad311ea08955462dfc3a8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 30 Apr 2024 22:47:02 +0800 Subject: [PATCH 035/106] fix: videoDetail info copy --- lib/pages/video/detail/introduction/view.dart | 7 ++ .../introduction/widgets/intro_detail.dart | 82 ++++++++++--------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 168e6ea7..9103c130 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,4 +1,5 @@ import 'package:expandable/expandable.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; @@ -265,6 +266,12 @@ class _VideoInfoState extends State with TickerProviderStateMixin { GestureDetector( behavior: HitTestBehavior.translucent, onTap: () => showIntroDetail(), + onLongPress: () async { + feedBack(); + await Clipboard.setData( + ClipboardData(text: widget.videoDetail!.title!)); + SmartDialog.showToast('标题已复制'); + }, child: ExpandablePanel( controller: _expandableCtr, collapsed: Text( diff --git a/lib/pages/video/detail/introduction/widgets/intro_detail.dart b/lib/pages/video/detail/introduction/widgets/intro_detail.dart index 3ec92023..78c621c0 100644 --- a/lib/pages/video/detail/introduction/widgets/intro_detail.dart +++ b/lib/pages/video/detail/introduction/widgets/intro_detail.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/utils.dart'; class IntroDetail extends StatelessWidget { @@ -16,44 +17,47 @@ class IntroDetail extends StatelessWidget { Widget build(BuildContext context) { return SizedBox( width: double.infinity, - child: SelectableRegion( - focusNode: FocusNode(), - selectionControls: MaterialTextSelectionControls(), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 4), - Row( - children: [ - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); - SmartDialog.showToast('已复制'); - }, - child: Text( - videoDetail!.bvid!, - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.primary), - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + Row( + children: [ + GestureDetector( + onTap: () { + feedBack(); + Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); + SmartDialog.showToast('已复制'); + }, + child: Text( + videoDetail!.bvid!, + style: TextStyle( + fontSize: 13, + color: Theme.of(context).colorScheme.primary), ), - const SizedBox(width: 10), - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: videoDetail!.bvid!)); - SmartDialog.showToast('已复制'); - }, - child: Text( - videoDetail!.aid!.toString(), - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.primary), - ), - ) - ], - ), - const SizedBox(height: 4), - Text.rich( + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () { + feedBack(); + Clipboard.setData( + ClipboardData(text: videoDetail!.aid!.toString())); + SmartDialog.showToast('已复制'); + }, + child: Text( + videoDetail!.aid!.toString(), + style: TextStyle( + fontSize: 13, + color: Theme.of(context).colorScheme.primary), + ), + ) + ], + ), + const SizedBox(height: 4), + SelectableRegion( + focusNode: FocusNode(), + selectionControls: MaterialTextSelectionControls(), + child: Text.rich( style: const TextStyle(height: 1.4), TextSpan( children: [ @@ -61,8 +65,8 @@ class IntroDetail extends StatelessWidget { ], ), ), - ], - ), + ), + ], ), ); } From 389747d6f47b4b7a4e76049d1db1ec5c35ae9910 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 30 Apr 2024 23:30:28 +0800 Subject: [PATCH 036/106] =?UTF-8?q?v1.0.22=20=E6=9B=B4=E6=96=B0=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- change_log/1.0.22.0430.md | 27 +++++++++++++++++++++++++++ pubspec.yaml | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 change_log/1.0.22.0430.md diff --git a/change_log/1.0.22.0430.md b/change_log/1.0.22.0430.md new file mode 100644 index 00000000..29f8aecf --- /dev/null +++ b/change_log/1.0.22.0430.md @@ -0,0 +1,27 @@ +## 1.0.22 + +### 功能 ++ 字幕 ++ 全屏时选集 ++ 动态转发 ++ 评论视频并转发 ++ 收藏夹删除 ++ 合集显示封面 ++ 底部导航栏编辑、排序功能 ++ 历史记录进度条展示 ++ 直播画质切换 ++ 排行榜功能 ++ 视频详情页推荐视频开关 ++ 显示联合投稿up + +### 修复 ++ 收藏夹个数错误 ++ 封面保存权限问题 ++ 合集最后1p未展示 ++ up主页关注按钮触发灰屏 + +### 优化 ++ 视频简介查看逻辑 + +更多更新日志可在Github上查看 +问题反馈、功能建议请查看「关于」页面。 diff --git a/pubspec.yaml b/pubspec.yaml index 5ea6386e..7cfbbca8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.21+1021 +version: 1.0.22+1022 environment: sdk: ">=3.0.0 <4.0.0" From 7dbd832a8077d6abf3106a91bfc32355aa394eb3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 1 May 2024 19:46:27 +0800 Subject: [PATCH 037/106] =?UTF-8?q?feat:=20=E9=95=BF=E6=8C=89=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E5=B0=81=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner/Info.plist | 2 + lib/common/widgets/overlay_pop.dart | 87 ------- lib/common/widgets/video_card_h.dart | 219 +++++++++--------- lib/common/widgets/video_card_v.dart | 15 +- lib/models/bangumi/list.dart | 3 + lib/models/search/result.dart | 24 +- lib/pages/bangumi/widgets/bangumu_card_v.dart | 170 ++++++-------- .../fav_detail/widget/fav_video_card.dart | 7 + lib/pages/hot/view.dart | 21 -- lib/pages/later/view.dart | 2 +- lib/pages/live/view.dart | 20 -- lib/pages/live/widgets/live_item.dart | 111 ++++----- lib/pages/member_seasons/widgets/item.dart | 7 + lib/pages/rank/zone/view.dart | 21 -- .../search_panel/widgets/live_panel.dart | 16 +- .../widgets/media_bangumi_panel.dart | 2 +- .../search_panel/widgets/video_panel.dart | 6 +- .../widget/sub_video_card.dart | 7 + lib/pages/video/detail/related/view.dart | 27 --- lib/utils/download.dart | 90 ++++--- lib/utils/image_save.dart | 88 +++++++ 21 files changed, 430 insertions(+), 515 deletions(-) delete mode 100644 lib/common/widgets/overlay_pop.dart create mode 100644 lib/utils/image_save.dart diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 65906625..1e7d9fed 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -49,6 +49,8 @@ NSPhotoLibraryAddUsageDescription 请允许APP保存图片到相册 + NSPhotoLibraryUsageDescription + 请允许APP保存图片到相册 NSCameraUsageDescription App需要您的同意,才能访问相册 NSAppleMusicUsageDescription diff --git a/lib/common/widgets/overlay_pop.dart b/lib/common/widgets/overlay_pop.dart deleted file mode 100644 index 4f0a3899..00000000 --- a/lib/common/widgets/overlay_pop.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'package:flutter/material.dart'; -import '../../utils/download.dart'; -import '../constants.dart'; -import 'network_img_layer.dart'; - -class OverlayPop extends StatelessWidget { - const OverlayPop({super.key, this.videoItem, this.closeFn}); - - final dynamic videoItem; - final Function? closeFn; - - @override - Widget build(BuildContext context) { - final double imgWidth = MediaQuery.sizeOf(context).width - 8 * 2; - return Container( - margin: const EdgeInsets.symmetric(horizontal: 8), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, - borderRadius: BorderRadius.circular(10.0), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - children: [ - NetworkImgLayer( - width: imgWidth, - height: imgWidth / StyleString.aspectRatio, - src: videoItem.pic! as String, - quality: 100, - ), - Positioned( - right: 8, - top: 8, - child: Container( - width: 30, - height: 30, - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.3), - borderRadius: - const BorderRadius.all(Radius.circular(20))), - child: IconButton( - style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - ), - onPressed: () => closeFn!(), - icon: const Icon( - Icons.close, - size: 18, - color: Colors.white, - ), - ), - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.fromLTRB(12, 10, 8, 10), - child: Row( - children: [ - Expanded( - child: Text( - videoItem.title! as String, - style: Theme.of(context).textTheme.titleSmall, - ), - ), - const SizedBox(width: 4), - IconButton( - tooltip: '保存封面图', - onPressed: () async { - await DownloadUtils.downloadImg( - videoItem.pic != null - ? videoItem.pic as String - : videoItem.cover as String, - ); - // closeFn!(); - }, - icon: const Icon(Icons.download, size: 20), - ) - ], - )), - ], - ), - ); - } -} diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index 25e701ac..df0c29b7 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/utils/image_save.dart'; import '../../http/search.dart'; import '../../http/user.dart'; import '../../http/video.dart'; @@ -16,8 +17,7 @@ class VideoCardH extends StatelessWidget { const VideoCardH({ super.key, required this.videoItem, - this.longPress, - this.longPressEnd, + this.onPressedFn, this.source = 'normal', this.showOwner = true, this.showView = true, @@ -27,8 +27,8 @@ class VideoCardH extends StatelessWidget { }); // ignore: prefer_typing_uninitialized_variables final videoItem; - final Function()? longPress; - final Function()? longPressEnd; + final Function()? onPressedFn; + // normal 推荐, later 稍后再看, search 搜索 final String source; final bool showOwner; final bool showView; @@ -45,109 +45,103 @@ class VideoCardH extends StatelessWidget { type = videoItem.type; } catch (_) {} final String heroTag = Utils.makeHeroTag(aid); - return GestureDetector( - onLongPress: () { - if (longPress != null) { - longPress!(); + return InkWell( + onTap: () async { + try { + if (type == 'ketang') { + SmartDialog.showToast('课堂视频暂不支持播放'); + return; + } + final int cid = + videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid); + Get.toNamed('/video?bvid=$bvid&cid=$cid', + arguments: {'videoItem': videoItem, 'heroTag': heroTag}); + } catch (err) { + SmartDialog.showToast(err.toString()); } }, - // onLongPressEnd: (details) { - // if (longPressEnd != null) { - // longPressEnd!(); - // } - // }, - child: InkWell( - onTap: () async { - try { - if (type == 'ketang') { - SmartDialog.showToast('课堂视频暂不支持播放'); - return; - } - final int cid = - videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid); - Get.toNamed('/video?bvid=$bvid&cid=$cid', - arguments: {'videoItem': videoItem, 'heroTag': heroTag}); - } catch (err) { - SmartDialog.showToast(err.toString()); - } - }, - child: Padding( - padding: const EdgeInsets.fromLTRB( - StyleString.safeSpace, 5, StyleString.safeSpace, 5), - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints boxConstraints) { - final double width = (boxConstraints.maxWidth - - StyleString.cardSpace * - 6 / - MediaQuery.textScalerOf(context).scale(1.0)) / - 2; - return Container( - constraints: const BoxConstraints(minHeight: 88), - height: width / StyleString.aspectRatio, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder( - builder: (BuildContext context, - BoxConstraints boxConstraints) { - final double maxWidth = boxConstraints.maxWidth; - final double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: videoItem.pic as String, - width: maxWidth, - height: maxHeight, - ), + onLongPress: () => imageSaveDialog( + context, + videoItem, + SmartDialog.dismiss, + ), + child: Padding( + padding: const EdgeInsets.fromLTRB( + StyleString.safeSpace, 5, StyleString.safeSpace, 5), + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints boxConstraints) { + final double width = (boxConstraints.maxWidth - + StyleString.cardSpace * + 6 / + MediaQuery.textScalerOf(context).scale(1.0)) / + 2; + return Container( + constraints: const BoxConstraints(minHeight: 88), + height: width / StyleString.aspectRatio, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder( + builder: (BuildContext context, + BoxConstraints boxConstraints) { + final double maxWidth = boxConstraints.maxWidth; + final double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: videoItem.pic as String, + width: maxWidth, + height: maxHeight, ), - if (videoItem.duration != 0) - PBadge( - text: Utils.timeFormat(videoItem.duration!), - right: 6.0, - bottom: 6.0, - type: 'gray', - ), - if (type != 'video') - PBadge( - text: type, - left: 6.0, - bottom: 6.0, - type: 'primary', - ), - // if (videoItem.rcmdReason != null && - // videoItem.rcmdReason.content != '') - // pBadge(videoItem.rcmdReason.content, context, - // 6.0, 6.0, null, null), - if (showCharge && videoItem?.isChargingSrc) - const PBadge( - text: '充电专属', - right: 6.0, - top: 6.0, - type: 'primary', - ), - ], - ); - }, - ), + ), + if (videoItem.duration != 0) + PBadge( + text: Utils.timeFormat(videoItem.duration!), + right: 6.0, + bottom: 6.0, + type: 'gray', + ), + if (type != 'video') + PBadge( + text: type, + left: 6.0, + bottom: 6.0, + type: 'primary', + ), + // if (videoItem.rcmdReason != null && + // videoItem.rcmdReason.content != '') + // pBadge(videoItem.rcmdReason.content, context, + // 6.0, 6.0, null, null), + if (showCharge && videoItem?.isChargingSrc) + const PBadge( + text: '充电专属', + right: 6.0, + top: 6.0, + type: 'primary', + ), + ], + ); + }, ), - VideoContent( - videoItem: videoItem, - source: source, - showOwner: showOwner, - showView: showView, - showDanmaku: showDanmaku, - showPubdate: showPubdate, - ) - ], - ), - ); - }, - ), + ), + VideoContent( + videoItem: videoItem, + source: source, + showOwner: showOwner, + showView: showView, + showDanmaku: showDanmaku, + showPubdate: showPubdate, + onPressedFn: onPressedFn, + ) + ], + ), + ); + }, ), ), ); @@ -162,6 +156,7 @@ class VideoContent extends StatelessWidget { final bool showView; final bool showDanmaku; final bool showPubdate; + final Function()? onPressedFn; const VideoContent({ super.key, @@ -171,6 +166,7 @@ class VideoContent extends StatelessWidget { this.showView = true, this.showDanmaku = true, this.showPubdate = false, + this.onPressedFn, }); @override @@ -181,7 +177,7 @@ class VideoContent extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (videoItem.title is String) ...[ + if (source == 'normal' || source == 'later') ...[ Text( videoItem.title as String, textAlign: TextAlign.start, @@ -196,7 +192,7 @@ class VideoContent extends StatelessWidget { maxLines: 2, text: TextSpan( children: [ - for (final i in videoItem.title) ...[ + for (final i in videoItem.titleList) ...[ TextSpan( text: i['text'] as String, style: TextStyle( @@ -374,6 +370,19 @@ class VideoContent extends StatelessWidget { ], ), ), + if (source == 'later') ...[ + IconButton( + style: ButtonStyle( + padding: MaterialStateProperty.all(EdgeInsets.zero), + ), + onPressed: () => onPressedFn?.call(), + icon: Icon( + Icons.clear_outlined, + color: Theme.of(context).colorScheme.outline, + size: 18, + ), + ) + ], ], ), ], diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 9916aa7a..6a97d7e7 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.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:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/image_save.dart'; import '../../models/model_rec_video_item.dart'; -import 'overlay_pop.dart'; import 'stat/danmu.dart'; import 'stat/view.dart'; import '../../http/dynamics.dart'; @@ -127,14 +127,11 @@ class VideoCardV extends StatelessWidget { String heroTag = Utils.makeHeroTag(videoItem.id); return InkWell( onTap: () async => onPushDetail(heroTag), - onLongPress: () { - SmartDialog.show( - builder: (context) => OverlayPop( - videoItem: videoItem, - closeFn: () => SmartDialog.dismiss(), - ), - ); - }, + onLongPress: () => imageSaveDialog( + context, + videoItem, + SmartDialog.dismiss, + ), borderRadius: BorderRadius.circular(16), child: Column( children: [ diff --git a/lib/models/bangumi/list.dart b/lib/models/bangumi/list.dart index c15014d0..fe71bb61 100644 --- a/lib/models/bangumi/list.dart +++ b/lib/models/bangumi/list.dart @@ -30,6 +30,7 @@ class BangumiListItemModel { BangumiListItemModel({ this.badge, this.badgeType, + this.pic, this.cover, // this.firstEp, this.indexShow, @@ -50,6 +51,7 @@ class BangumiListItemModel { String? badge; int? badgeType; + String? pic; String? cover; String? indexShow; int? isFinish; @@ -70,6 +72,7 @@ class BangumiListItemModel { BangumiListItemModel.fromJson(Map json) { badge = json['badge'] == '' ? null : json['badge']; badgeType = json['badge_type']; + pic = json['cover']; cover = json['cover']; indexShow = json['index_show']; isFinish = json['is_finish']; diff --git a/lib/models/search/result.dart b/lib/models/search/result.dart index 418fb99d..81917b72 100644 --- a/lib/models/search/result.dart +++ b/lib/models/search/result.dart @@ -25,6 +25,7 @@ class SearchVideoItemModel { this.aid, this.bvid, this.title, + this.titleList, this.description, this.pic, // this.play, @@ -54,8 +55,8 @@ class SearchVideoItemModel { String? arcurl; int? aid; String? bvid; - List? title; - // List? titleList; + String? title; + List? titleList; String? description; String? pic; // String? play; @@ -82,8 +83,9 @@ class SearchVideoItemModel { aid = json['aid']; bvid = json['bvid']; mid = json['mid']; - // title = json['title'].replaceAll(RegExp(r'<.*?>'), ''); - title = Em.regTitle(json['title']); + title = json['title'].replaceAll(RegExp(r'<.*?>'), ''); + // title = Em.regTitle(json['title']); + titleList = Em.regTitle(json['title']); description = json['description']; pic = json['pic'] != null && json['pic'].startsWith('//') ? 'https:${json['pic']}' @@ -232,6 +234,7 @@ class SearchLiveItemModel { this.userCover, this.type, this.title, + this.titleList, this.cover, this.pic, this.online, @@ -251,7 +254,8 @@ class SearchLiveItemModel { String? face; String? userCover; String? type; - List? title; + String? title; + List? titleList; String? cover; String? pic; int? online; @@ -272,7 +276,8 @@ class SearchLiveItemModel { face = json['uface']; userCover = json['user_cover']; type = json['type']; - title = Em.regTitle(json['title']); + title = json['title'].replaceAll(RegExp(r'<.*?>'), ''); + titleList = Em.regTitle(json['title']); cover = json['cover']; pic = json['cover']; online = json['online']; @@ -302,6 +307,7 @@ class SearchMBangumiItemModel { this.type, this.mediaId, this.title, + this.titleList, this.orgTitle, this.mediaType, this.cv, @@ -328,7 +334,8 @@ class SearchMBangumiItemModel { String? type; int? mediaId; - List? title; + String? title; + List? titleList; String? orgTitle; int? mediaType; String? cv; @@ -355,7 +362,8 @@ class SearchMBangumiItemModel { SearchMBangumiItemModel.fromJson(Map json) { type = json['type']; mediaId = json['media_id']; - title = Em.regTitle(json['title']); + title = json['title'].replaceAll(RegExp(r'<.*?>'), ''); + titleList = Em.regTitle(json['title']); orgTitle = json['org_title']; mediaType = json['media_type']; cv = json['cv']; diff --git a/lib/pages/bangumi/widgets/bangumu_card_v.dart b/lib/pages/bangumi/widgets/bangumu_card_v.dart index c1233ddf..3c8f6d2a 100644 --- a/lib/pages/bangumi/widgets/bangumu_card_v.dart +++ b/lib/pages/bangumi/widgets/bangumu_card_v.dart @@ -5,7 +5,9 @@ import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/http/search.dart'; import 'package:pilipala/models/bangumi/info.dart'; +import 'package:pilipala/models/bangumi/list.dart'; import 'package:pilipala/models/common/search_type.dart'; +import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; @@ -14,109 +16,87 @@ class BangumiCardV extends StatelessWidget { const BangumiCardV({ super.key, required this.bangumiItem, - this.longPress, - this.longPressEnd, }); - final bangumiItem; - final Function()? longPress; - final Function()? longPressEnd; + final BangumiListItemModel bangumiItem; @override Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(bangumiItem.mediaId); - return Card( - elevation: 0, - clipBehavior: Clip.hardEdge, - margin: EdgeInsets.zero, - child: GestureDetector( - // onLongPress: () { - // if (longPress != null) { - // longPress!(); - // } - // }, - // onLongPressEnd: (details) { - // if (longPressEnd != null) { - // longPressEnd!(); - // } - // }, - child: InkWell( - onTap: () async { - final int seasonId = bangumiItem.seasonId; - SmartDialog.showLoading(msg: '获取中...'); - final res = await SearchHttp.bangumiInfo(seasonId: seasonId); - SmartDialog.dismiss().then((value) { - if (res['status']) { - if (res['data'].episodes.isEmpty) { - SmartDialog.showToast('资源加载失败'); - return; - } - EpisodeItem episode = res['data'].episodes.first; - String bvid = episode.bvid!; - int cid = episode.cid!; - String pic = episode.cover!; - String heroTag = Utils.makeHeroTag(cid); - Get.toNamed( - '/video?bvid=$bvid&cid=$cid&seasonId=$seasonId', - arguments: { - 'pic': pic, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - 'bangumiItem': res['data'], - }, + return InkWell( + onTap: () async { + final int seasonId = bangumiItem.seasonId!; + SmartDialog.showLoading(msg: '获取中...'); + final res = await SearchHttp.bangumiInfo(seasonId: seasonId); + SmartDialog.dismiss().then((value) { + if (res['status']) { + if (res['data'].episodes.isEmpty) { + SmartDialog.showToast('资源加载失败'); + return; + } + EpisodeItem episode = res['data'].episodes.first; + String bvid = episode.bvid!; + int cid = episode.cid!; + String pic = episode.cover!; + String heroTag = Utils.makeHeroTag(cid); + Get.toNamed( + '/video?bvid=$bvid&cid=$cid&seasonId=$seasonId', + arguments: { + 'pic': pic, + 'heroTag': heroTag, + 'videoType': SearchType.media_bangumi, + 'bangumiItem': res['data'], + }, + ); + } + }); + }, + onLongPress: () => + imageSaveDialog(context, bangumiItem, SmartDialog.dismiss), + child: Column( + children: [ + ClipRRect( + borderRadius: const BorderRadius.all( + StyleString.imgRadius, + ), + child: AspectRatio( + aspectRatio: 0.65, + child: LayoutBuilder(builder: (context, boxConstraints) { + final double maxWidth = boxConstraints.maxWidth; + final double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: bangumiItem.cover, + width: maxWidth, + height: maxHeight, + ), + ), + if (bangumiItem.badge != null) + PBadge( + text: bangumiItem.badge, + top: 6, + right: 6, + bottom: null, + left: null), + if (bangumiItem.order != null) + PBadge( + text: bangumiItem.order, + top: null, + right: null, + bottom: 6, + left: 6, + type: 'gray', + ), + ], ); - } - }); - }, - child: Column( - children: [ - ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: StyleString.imgRadius, - topRight: StyleString.imgRadius, - bottomLeft: StyleString.imgRadius, - bottomRight: StyleString.imgRadius, - ), - child: AspectRatio( - aspectRatio: 0.65, - child: LayoutBuilder(builder: (context, boxConstraints) { - final double maxWidth = boxConstraints.maxWidth; - final double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: bangumiItem.cover, - width: maxWidth, - height: maxHeight, - ), - ), - if (bangumiItem.badge != null) - PBadge( - text: bangumiItem.badge, - top: 6, - right: 6, - bottom: null, - left: null), - if (bangumiItem.order != null) - PBadge( - text: bangumiItem.order, - top: null, - right: null, - bottom: 6, - left: 6, - type: 'gray', - ), - ], - ); - }), - ), - ), - BangumiContent(bangumiItem: bangumiItem) - ], + }), + ), ), - ), + BangumiContent(bangumiItem: bangumiItem) + ], ), ); } diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 1c4008ff..79e5c073 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -1,3 +1,4 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:pilipala/common/constants.dart'; @@ -7,6 +8,7 @@ import 'package:pilipala/http/search.dart'; import 'package:pilipala/http/video.dart'; import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/utils/id_utils.dart'; +import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import '../../../common/widgets/badge.dart'; @@ -61,6 +63,11 @@ class FavVideoCardH extends StatelessWidget { epId != null ? SearchType.media_bangumi : SearchType.video, }); }, + onLongPress: () => imageSaveDialog( + context, + videoItem, + SmartDialog.dismiss, + ), child: Column( children: [ Padding( diff --git a/lib/pages/hot/view.dart b/lib/pages/hot/view.dart index e2e20e73..80d08e7b 100644 --- a/lib/pages/hot/view.dart +++ b/lib/pages/hot/view.dart @@ -3,8 +3,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; -import 'package:pilipala/common/widgets/animated_dialog.dart'; -import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; @@ -78,15 +76,6 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { return VideoCardH( videoItem: _hotController.videoList[index], showPubdate: true, - longPress: () { - _hotController.popupDialog = _createPopupDialog( - _hotController.videoList[index]); - Overlay.of(context) - .insert(_hotController.popupDialog!); - }, - longPressEnd: () { - _hotController.popupDialog?.remove(); - }, ); }, childCount: _hotController.videoList.length), ), @@ -122,14 +111,4 @@ class _HotPageState extends State with AutomaticKeepAliveClientMixin { ), ); } - - OverlayEntry _createPopupDialog(videoItem) { - return OverlayEntry( - builder: (context) => AnimatedDialog( - closeFn: _hotController.popupDialog?.remove, - child: OverlayPop( - videoItem: videoItem, closeFn: _hotController.popupDialog?.remove), - ), - ); - } } diff --git a/lib/pages/later/view.dart b/lib/pages/later/view.dart index d4695154..7c6e158d 100644 --- a/lib/pages/later/view.dart +++ b/lib/pages/later/view.dart @@ -84,7 +84,7 @@ class _LaterPageState extends State { return VideoCardH( videoItem: videoItem, source: 'later', - longPress: () => _laterController.toViewDel( + onPressedFn: () => _laterController.toViewDel( aid: videoItem.aid)); }, childCount: _laterController.laterList.length), ) diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart index c61d20b3..83605495 100644 --- a/lib/pages/live/view.dart +++ b/lib/pages/live/view.dart @@ -5,9 +5,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/skeleton/video_card_v.dart'; -import 'package:pilipala/common/widgets/animated_dialog.dart'; import 'package:pilipala/common/widgets/http_error.dart'; -import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/utils/main_stream.dart'; import 'controller.dart'; @@ -112,16 +110,6 @@ class _LivePageState extends State ); } - OverlayEntry _createPopupDialog(liveItem) { - return OverlayEntry( - builder: (context) => AnimatedDialog( - closeFn: _liveController.popupDialog?.remove, - child: OverlayPop( - videoItem: liveItem, closeFn: _liveController.popupDialog?.remove), - ), - ); - } - Widget contentGrid(ctr, liveList) { // double maxWidth = Get.size.width; // int baseWidth = 500; @@ -152,14 +140,6 @@ class _LivePageState extends State ? LiveCardV( liveItem: liveList[index], crossAxisCount: crossAxisCount, - longPress: () { - _liveController.popupDialog = - _createPopupDialog(liveList[index]); - Overlay.of(context).insert(_liveController.popupDialog!); - }, - longPressEnd: () { - _liveController.popupDialog?.remove(); - }, ) : const VideoCardVSkeleton(); }, diff --git a/lib/pages/live/widgets/live_item.dart b/lib/pages/live/widgets/live_item.dart index 9218d4fb..f70ba82b 100644 --- a/lib/pages/live/widgets/live_item.dart +++ b/lib/pages/live/widgets/live_item.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/models/live/item.dart'; +import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; @@ -9,81 +11,66 @@ import 'package:pilipala/common/widgets/network_img_layer.dart'; class LiveCardV extends StatelessWidget { final LiveItemModel liveItem; final int crossAxisCount; - final Function()? longPress; - final Function()? longPressEnd; const LiveCardV({ Key? key, required this.liveItem, required this.crossAxisCount, - this.longPress, - this.longPressEnd, }) : super(key: key); @override Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(liveItem.roomId); - return Card( - elevation: 0, - clipBehavior: Clip.hardEdge, - margin: EdgeInsets.zero, - child: GestureDetector( - onLongPress: () { - if (longPress != null) { - longPress!(); - } - }, - // onLongPressEnd: (details) { - // if (longPressEnd != null) { - // longPressEnd!(); - // } - // }, - child: InkWell( - onTap: () async { - Get.toNamed('/liveRoom?roomid=${liveItem.roomId}', - arguments: {'liveItem': liveItem, 'heroTag': heroTag}); - }, - child: Column( - children: [ - ClipRRect( - borderRadius: const BorderRadius.all(StyleString.imgRadius), - child: AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder(builder: (context, boxConstraints) { - double maxWidth = boxConstraints.maxWidth; - double maxHeight = boxConstraints.maxHeight; - return Stack( - children: [ - Hero( - tag: heroTag, - child: NetworkImgLayer( - src: liveItem.cover!, - width: maxWidth, - height: maxHeight, + return InkWell( + onLongPress: () => imageSaveDialog( + context, + liveItem, + SmartDialog.dismiss, + ), + borderRadius: BorderRadius.circular(16), + onTap: () async { + Get.toNamed('/liveRoom?roomid=${liveItem.roomId}', + arguments: {'liveItem': liveItem, 'heroTag': heroTag}); + }, + child: Column( + children: [ + ClipRRect( + borderRadius: const BorderRadius.all(StyleString.imgRadius), + child: AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder(builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return Stack( + children: [ + Hero( + tag: heroTag, + child: NetworkImgLayer( + src: liveItem.cover!, + width: maxWidth, + height: maxHeight, + ), + ), + if (crossAxisCount != 1) + Positioned( + left: 0, + right: 0, + bottom: 0, + child: AnimatedOpacity( + opacity: 1, + duration: const Duration(milliseconds: 200), + child: VideoStat( + liveItem: liveItem, ), ), - if (crossAxisCount != 1) - Positioned( - left: 0, - right: 0, - bottom: 0, - child: AnimatedOpacity( - opacity: 1, - duration: const Duration(milliseconds: 200), - child: VideoStat( - liveItem: liveItem, - ), - ), - ), - ], - ); - }), - ), - ), - LiveContent(liveItem: liveItem, crossAxisCount: crossAxisCount) - ], + ), + ], + ); + }), + ), ), - ), + LiveContent(liveItem: liveItem, crossAxisCount: crossAxisCount) + ], ), ); } diff --git a/lib/pages/member_seasons/widgets/item.dart b/lib/pages/member_seasons/widgets/item.dart index 4df74b70..85b763b7 100644 --- a/lib/pages/member_seasons/widgets/item.dart +++ b/lib/pages/member_seasons/widgets/item.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/badge.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/common/widgets/stat/view.dart'; import 'package:pilipala/http/search.dart'; +import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/utils.dart'; class MemberSeasonsItem extends StatelessWidget { @@ -29,6 +31,11 @@ class MemberSeasonsItem extends StatelessWidget { Get.toNamed('/video?bvid=${seasonItem.bvid}&cid=$cid', arguments: {'videoItem': seasonItem, 'heroTag': heroTag}); }, + onLongPress: () => imageSaveDialog( + context, + seasonItem, + SmartDialog.dismiss, + ), child: Column( children: [ AspectRatio( diff --git a/lib/pages/rank/zone/view.dart b/lib/pages/rank/zone/view.dart index 04631a8c..72d81f95 100644 --- a/lib/pages/rank/zone/view.dart +++ b/lib/pages/rank/zone/view.dart @@ -3,8 +3,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; -import 'package:pilipala/common/widgets/animated_dialog.dart'; -import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; @@ -82,15 +80,6 @@ class _ZonePageState extends State return VideoCardH( videoItem: _zoneController.videoList[index], showPubdate: true, - longPress: () { - _zoneController.popupDialog = _createPopupDialog( - _zoneController.videoList[index]); - Overlay.of(context) - .insert(_zoneController.popupDialog!); - }, - longPressEnd: () { - _zoneController.popupDialog?.remove(); - }, ); }, childCount: _zoneController.videoList.length), ), @@ -126,14 +115,4 @@ class _ZonePageState extends State ), ); } - - OverlayEntry _createPopupDialog(videoItem) { - return OverlayEntry( - builder: (context) => AnimatedDialog( - closeFn: _zoneController.popupDialog?.remove, - child: OverlayPop( - videoItem: videoItem, closeFn: _zoneController.popupDialog?.remove), - ), - ); - } } diff --git a/lib/pages/search_panel/widgets/live_panel.dart b/lib/pages/search_panel/widgets/live_panel.dart index 6fb5f5b8..5f797f09 100644 --- a/lib/pages/search_panel/widgets/live_panel.dart +++ b/lib/pages/search_panel/widgets/live_panel.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/utils.dart'; Widget searchLivePanel(BuildContext context, ctr, list) { @@ -42,15 +44,15 @@ class LiveItem extends StatelessWidget { Get.toNamed('/liveRoom?roomid=${liveItem.roomid}', arguments: {'liveItem': liveItem, 'heroTag': heroTag}); }, + onLongPress: () => imageSaveDialog( + context, + liveItem, + SmartDialog.dismiss, + ), child: Column( children: [ ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: StyleString.imgRadius, - topRight: StyleString.imgRadius, - bottomLeft: StyleString.imgRadius, - bottomRight: StyleString.imgRadius, - ), + borderRadius: const BorderRadius.all(StyleString.imgRadius), child: AspectRatio( aspectRatio: StyleString.aspectRatio, child: LayoutBuilder(builder: (context, boxConstraints) { @@ -108,7 +110,7 @@ class LiveContent extends StatelessWidget { RichText( text: TextSpan( children: [ - for (var i in liveItem.title) ...[ + for (var i in liveItem.titleList) ...[ TextSpan( text: i['text'], style: TextStyle( diff --git a/lib/pages/search_panel/widgets/media_bangumi_panel.dart b/lib/pages/search_panel/widgets/media_bangumi_panel.dart index 18799d3a..7d88b183 100644 --- a/lib/pages/search_panel/widgets/media_bangumi_panel.dart +++ b/lib/pages/search_panel/widgets/media_bangumi_panel.dart @@ -63,7 +63,7 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) { style: TextStyle( color: Theme.of(context).colorScheme.onSurface), children: [ - for (var i in i.title) ...[ + for (var i in i.titleList) ...[ TextSpan( text: i['text'], style: TextStyle( diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index b96ff004..c24a007c 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -35,7 +35,11 @@ class SearchVideoPanel extends StatelessWidget { padding: index == 0 ? const EdgeInsets.only(top: 2) : EdgeInsets.zero, - child: VideoCardH(videoItem: i, showPubdate: true), + child: VideoCardH( + videoItem: i, + showPubdate: true, + source: 'search', + ), ); }, ), diff --git a/lib/pages/subscription_detail/widget/sub_video_card.dart b/lib/pages/subscription_detail/widget/sub_video_card.dart index 11aebc39..dcdee4ef 100644 --- a/lib/pages/subscription_detail/widget/sub_video_card.dart +++ b/lib/pages/subscription_detail/widget/sub_video_card.dart @@ -1,3 +1,4 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:pilipala/common/constants.dart'; @@ -5,6 +6,7 @@ import 'package:pilipala/common/widgets/stat/danmu.dart'; import 'package:pilipala/common/widgets/stat/view.dart'; import 'package:pilipala/http/search.dart'; import 'package:pilipala/models/common/search_type.dart'; +import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import '../../../common/widgets/badge.dart'; @@ -40,6 +42,11 @@ class SubVideoCardH extends StatelessWidget { 'videoType': SearchType.video, }); }, + onLongPress: () => imageSaveDialog( + context, + videoItem, + SmartDialog.dismiss, + ), child: Column( children: [ Padding( diff --git a/lib/pages/video/detail/related/view.dart b/lib/pages/video/detail/related/view.dart index 0912724e..fe3b0dca 100644 --- a/lib/pages/video/detail/related/view.dart +++ b/lib/pages/video/detail/related/view.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/skeleton/video_card_h.dart'; -import 'package:pilipala/common/widgets/animated_dialog.dart'; import 'package:pilipala/common/widgets/http_error.dart'; -import 'package:pilipala/common/widgets/overlay_pop.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; import './controller.dart'; @@ -54,20 +52,6 @@ class _RelatedVideoPanelState extends State child: VideoCardH( videoItem: relatedVideoList[index], showPubdate: true, - longPress: () { - try { - _releatedController.popupDialog = - _createPopupDialog(_releatedController - .relatedVideoList[index]); - Overlay.of(context) - .insert(_releatedController.popupDialog!); - } catch (err) { - return {}; - } - }, - longPressEnd: () { - _releatedController.popupDialog?.remove(); - }, ), ); } @@ -89,15 +73,4 @@ class _RelatedVideoPanelState extends State }, ); } - - OverlayEntry _createPopupDialog(videoItem) { - return OverlayEntry( - builder: (BuildContext context) => AnimatedDialog( - closeFn: _releatedController.popupDialog?.remove, - child: OverlayPop( - videoItem: videoItem, - closeFn: _releatedController.popupDialog?.remove), - ), - ); - } } diff --git a/lib/utils/download.dart b/lib/utils/download.dart index 2aff8999..42dbbecf 100644 --- a/lib/utils/download.dart +++ b/lib/utils/download.dart @@ -15,24 +15,7 @@ class DownloadUtils { PermissionStatus status = await Permission.storage.status; if (status == PermissionStatus.denied || status == PermissionStatus.permanentlyDenied) { - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: const Text('存储权限未授权'), - actions: [ - TextButton( - onPressed: () async { - openAppSettings(); - }, - child: const Text('去授权'), - ) - ], - ); - }, - ); + await permissionDialog('提示', '存储权限未授权'); return false; } else { return true; @@ -45,24 +28,7 @@ class DownloadUtils { PermissionStatus status = await Permission.photos.status; if (status == PermissionStatus.denied || status == PermissionStatus.permanentlyDenied) { - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: const Text('相册权限未授权'), - actions: [ - TextButton( - onPressed: () async { - openAppSettings(); - }, - child: const Text('去授权'), - ) - ], - ); - }, - ); + await permissionDialog('提示', '相册权限未授权'); return false; } else { return true; @@ -72,17 +38,16 @@ class DownloadUtils { static Future downloadImg(String imgUrl, {String imgType = 'cover'}) async { try { - if (!Platform.isAndroid || !await requestPhotoPer()) { - return false; - } - final androidInfo = await DeviceInfoPlugin().androidInfo; - if (androidInfo.version.sdkInt <= 32) { - if (!await requestStoragePer()) { - return false; - } - } else { - if (!await requestPhotoPer()) { - return false; + if (Platform.isAndroid) { + final androidInfo = await DeviceInfoPlugin().androidInfo; + if (androidInfo.version.sdkInt <= 32) { + if (!await requestStoragePer()) { + return false; + } + } else { + if (!await requestPhotoPer()) { + return false; + } } } @@ -101,13 +66,38 @@ class DownloadUtils { ); SmartDialog.dismiss(); if (result.isSuccess) { - await SmartDialog.showToast('「${'$picName.$imgSuffix'}」已保存 '); + SmartDialog.showToast('「${'$picName.$imgSuffix'}」已保存 '); + return true; + } else { + await permissionDialog('保存失败', '相册权限未授权'); + return false; } - return true; } catch (err) { SmartDialog.dismiss(); SmartDialog.showToast(err.toString()); - return true; + return false; } } + + static Future permissionDialog(String title, String content, + {Function? onGranted}) async { + await SmartDialog.show( + useSystem: true, + animationType: SmartAnimationType.centerFade_otherSlide, + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: Text(content), + actions: [ + TextButton( + onPressed: () async { + openAppSettings(); + }, + child: const Text('去授权'), + ) + ], + ); + }, + ); + } } diff --git a/lib/utils/image_save.dart b/lib/utils/image_save.dart new file mode 100644 index 00000000..0cd6915c --- /dev/null +++ b/lib/utils/image_save.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:pilipala/common/constants.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/download.dart'; + +Future imageSaveDialog(context, videoItem, closeFn) { + final double imgWidth = + MediaQuery.sizeOf(context).width - StyleString.safeSpace * 2; + return SmartDialog.show( + animationType: SmartAnimationType.centerScale_otherSlide, + builder: (context) => Container( + margin: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.background, + borderRadius: BorderRadius.circular(10.0), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + NetworkImgLayer( + width: imgWidth, + height: imgWidth / StyleString.aspectRatio, + src: videoItem.pic! as String, + quality: 100, + ), + Positioned( + right: 8, + top: 8, + child: Container( + width: 30, + height: 30, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + borderRadius: + const BorderRadius.all(Radius.circular(20))), + child: IconButton( + style: ButtonStyle( + padding: MaterialStateProperty.all(EdgeInsets.zero), + ), + onPressed: () => closeFn!(), + icon: const Icon( + Icons.close, + size: 18, + color: Colors.white, + ), + ), + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.fromLTRB(12, 10, 8, 10), + child: Row( + children: [ + Expanded( + child: Text( + videoItem.title! as String, + style: Theme.of(context).textTheme.titleSmall, + ), + ), + const SizedBox(width: 4), + IconButton( + tooltip: '保存封面图', + onPressed: () async { + bool saveStatus = await DownloadUtils.downloadImg( + videoItem.pic != null + ? videoItem.pic as String + : videoItem.cover as String, + ); + // 保存成功,自动关闭弹窗 + if (saveStatus) { + closeFn?.call(); + } + }, + icon: const Icon(Icons.download, size: 20), + ) + ], + ), + ), + ], + ), + ), + ); +} From e361e09ddfefb964ebd0f7135b8ce788d1e00f60 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 1 May 2024 20:02:34 +0800 Subject: [PATCH 038/106] =?UTF-8?q?fix:=20=E8=AE=A2=E9=98=85=E8=AF=A6?= =?UTF-8?q?=E6=83=85type=E5=8C=BA=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/subscription/widgets/item.dart | 1 + lib/pages/subscription_detail/controller.dart | 11 +++++++---- lib/pages/subscription_detail/view.dart | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/pages/subscription/widgets/item.dart b/lib/pages/subscription/widgets/item.dart index 5b2a0134..0d424611 100644 --- a/lib/pages/subscription/widgets/item.dart +++ b/lib/pages/subscription/widgets/item.dart @@ -25,6 +25,7 @@ class SubItem extends StatelessWidget { parameters: { 'heroTag': heroTag, 'seasonId': subFolderItem.id.toString(), + 'type': subFolderItem.type.toString(), }, ), child: Padding( diff --git a/lib/pages/subscription_detail/controller.dart b/lib/pages/subscription_detail/controller.dart index 4245df2c..e69f4be0 100644 --- a/lib/pages/subscription_detail/controller.dart +++ b/lib/pages/subscription_detail/controller.dart @@ -14,13 +14,16 @@ class SubDetailController extends GetxController { RxList subList = [].obs; RxString loadingText = '加载中...'.obs; int mediaCount = 0; + late int channelType; @override void onInit() { item = Get.arguments; - if (Get.parameters.keys.isNotEmpty) { - seasonId = int.parse(Get.parameters['seasonId']!); - heroTag = Get.parameters['heroTag']!; + final parameters = Get.parameters; + if (parameters.isNotEmpty) { + seasonId = int.tryParse(parameters['seasonId'] ?? '') ?? 0; + heroTag = parameters['heroTag'] ?? ''; + channelType = int.tryParse(parameters['type'] ?? '') ?? 0; } super.onInit(); } @@ -31,7 +34,7 @@ class SubDetailController extends GetxController { return; } isLoadingMore = true; - var res = type == 21 + var res = channelType == 21 ? await UserHttp.userSeasonList( seasonId: seasonId, ps: 20, diff --git a/lib/pages/subscription_detail/view.dart b/lib/pages/subscription_detail/view.dart index 63352429..4ca241fe 100644 --- a/lib/pages/subscription_detail/view.dart +++ b/lib/pages/subscription_detail/view.dart @@ -198,8 +198,8 @@ class _SubDetailPageState extends State { future: _futureBuilderFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - Map data = snapshot.data; - if (data['status']) { + Map? data = snapshot.data; + if (data != null && data['status']) { if (_subDetailController.item.mediaCount == 0) { return const NoData(); } else { @@ -219,7 +219,7 @@ class _SubDetailPageState extends State { } } else { return HttpError( - errMsg: data['msg'], + errMsg: data?['msg'] ?? '请求异常', fn: () => setState(() {}), ); } From 91ad0fa03dc44ddc3694367b8902db0be34003b0 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 1 May 2024 20:22:52 +0800 Subject: [PATCH 039/106] =?UTF-8?q?fix:=20=E6=9F=A5=E7=9C=8B=E8=AF=84?= =?UTF-8?q?=E8=AE=BA=E8=AF=A6=E6=83=85=E7=82=B9=E5=87=BB=E5=8C=BA=E5=9F=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/widgets/reply_item.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 468d2541..ef4cd15c 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -44,7 +44,7 @@ class ReplyItem extends StatelessWidget { onTap: () { feedBack(); if (replyReply != null) { - replyReply!(replyItem, null); + replyReply!(replyItem); } }, onLongPress: () { @@ -358,7 +358,7 @@ class ReplyItemRow extends StatelessWidget { InkWell( // 一楼点击评论展开评论详情 // onTap: () { - // replyReply?.call(replyItem, replies![i]); + // replyReply?.call(replyItem); // }, onLongPress: () { feedBack(); From 291312bde70df30258692759fcb31ed030f0b133 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 1 May 2024 20:44:38 +0800 Subject: [PATCH 040/106] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E5=8C=BA?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E8=A7=86=E9=A2=91=E9=A1=B5pic=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/search.dart | 16 ++++++++++++++++ lib/pages/video/detail/controller.dart | 2 +- lib/utils/url_utils.dart | 6 ++++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/http/search.dart b/lib/http/search.dart index 18481ea8..cf1a1b49 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -163,4 +163,20 @@ class SearchHttp { }; } } + + static Future> ab2cWithPic( + {int? aid, String? bvid}) async { + Map data = {}; + if (aid != null) { + data['aid'] = aid; + } else if (bvid != null) { + data['bvid'] = bvid; + } + final dynamic res = + await Request().get(Api.ab2c, data: {...data}); + return { + 'cid': res.data['data'].first['cid'], + 'pic': res.data['data'].first['first_frame'], + }; + } } diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 6dd6425f..f7f9e848 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -547,7 +547,7 @@ class VideoDetailController extends GetxController } void updateCover(String? pic) { - if (pic != null && pic != '') { + if (pic != null) { cover.value = videoItem['pic'] = pic; } } diff --git a/lib/utils/url_utils.dart b/lib/utils/url_utils.dart index cf0ef9e2..20f9cb0d 100644 --- a/lib/utils/url_utils.dart +++ b/lib/utils/url_utils.dart @@ -42,12 +42,14 @@ class UrlUtils { final Map matchRes = IdUtils.matchAvorBv(input: pathSegment); if (matchRes.containsKey('BV')) { final String bv = matchRes['BV']; - final int cid = await SearchHttp.ab2c(bvid: bv); + final Map res = await SearchHttp.ab2cWithPic(bvid: bv); + final int cid = res['cid']; + final String pic = res['pic']; final String heroTag = Utils.makeHeroTag(bv); await Get.toNamed( '/video?bvid=$bv&cid=$cid', arguments: { - 'pic': '', + 'pic': pic, 'heroTag': heroTag, }, ); From 8082550da6d4a8c6a722243085418186fd57ab7d Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 1 May 2024 22:51:55 +0800 Subject: [PATCH 041/106] =?UTF-8?q?fix:=20=E5=85=A8=E5=B1=8F=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/view.dart | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index b87350a5..bcacbbbb 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -535,20 +535,20 @@ class _VideoDetailPageState extends State controller: _extendNestCtr, headerSliverBuilder: (BuildContext context2, bool innerBoxIsScrolled) { - final Orientation orientation = - MediaQuery.of(context).orientation; - final bool isFullScreen = - plPlayerController?.isFullScreen.value == true; - final double expandedHeight = - orientation == Orientation.landscape || isFullScreen - ? (MediaQuery.sizeOf(context).height - - (orientation == Orientation.landscape - ? 0 - : MediaQuery.of(context).padding.top)) - : videoHeight.value; return [ Obx( () { + final Orientation orientation = + MediaQuery.of(context).orientation; + final bool isFullScreen = + plPlayerController?.isFullScreen.value == true; + final double expandedHeight = + orientation == Orientation.landscape || isFullScreen + ? (MediaQuery.sizeOf(context).height - + (orientation == Orientation.landscape + ? 0 + : MediaQuery.of(context).padding.top)) + : videoHeight.value; if (orientation == Orientation.landscape || isFullScreen) { enterFullScreen(); From b85067f7ebdc2e257e4a826f0c74ff41125f40f3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 1 May 2024 23:41:18 +0800 Subject: [PATCH 042/106] =?UTF-8?q?opt:=20=E7=B3=BB=E7=BB=9F=E7=BA=A7?= =?UTF-8?q?=E8=B7=B3=E8=BD=ACav=E3=80=81bangumi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/app_scheme.dart | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 69fa717d..5bfb955c 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -167,8 +167,21 @@ class PiliSchame { print('bilibili.com host: $host'); print('bilibili.com path: $path'); final String lastPathSegment = path!.split('/').last; - if (lastPathSegment.contains('BV')) { - _videoPush(null, lastPathSegment); + if (path.startsWith('/video')) { + if (lastPathSegment.contains('BV')) { + _videoPush(null, lastPathSegment); + } + if (lastPathSegment.contains('av')) { + _videoPush(matchNum(lastPathSegment)[0], null); + } + } + if (path.startsWith('/bangumi')) { + if (lastPathSegment.contains('ss')) { + _bangumiPush(matchNum(lastPathSegment).first, null); + } + if (lastPathSegment.contains('ep')) { + _bangumiPush(null, matchNum(lastPathSegment).first); + } } } else if (host.contains('live')) { int roomId = int.parse(path!.split('/').last); From 61505c61273dab58fd804ccce6485af4afc19e84 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 2 May 2024 22:19:20 +0800 Subject: [PATCH 043/106] opt: RoutePush bangumi --- lib/common/widgets/video_card_v.dart | 25 +++-------- lib/pages/bangumi/widgets/bangumu_card_v.dart | 37 +++------------ lib/pages/dynamics/controller.dart | 21 +-------- lib/pages/history/widgets/item.dart | 27 +++-------- .../widgets/media_bangumi_panel.dart | 25 ++--------- .../whisper_detail/widget/chat_item.dart | 45 ++++++++++++++----- lib/utils/app_scheme.dart | 44 ++++-------------- lib/utils/route_push.dart | 44 ++++++++++++++++++ 8 files changed, 111 insertions(+), 157 deletions(-) create mode 100644 lib/utils/route_push.dart diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 6a97d7e7..15fbc6fc 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -3,14 +3,13 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/image_save.dart'; +import 'package:pilipala/utils/route_push.dart'; import '../../models/model_rec_video_item.dart'; import 'stat/danmu.dart'; import 'stat/view.dart'; import '../../http/dynamics.dart'; -import '../../http/search.dart'; import '../../http/user.dart'; import '../../http/video.dart'; -import '../../models/common/search_type.dart'; import '../../utils/id_utils.dart'; import '../../utils/utils.dart'; import '../constants.dart'; @@ -42,23 +41,11 @@ class VideoCardV extends StatelessWidget { return; } int epId = videoItem.param; - SmartDialog.showLoading(msg: '资源获取中'); - var result = await SearchHttp.bangumiInfo(seasonId: null, epId: epId); - if (result['status']) { - var bangumiDetail = result['data']; - int cid = bangumiDetail.episodes!.first.cid; - String bvid = IdUtils.av2bv(bangumiDetail.episodes!.first.aid); - SmartDialog.dismiss().then( - (value) => Get.toNamed( - '/video?bvid=$bvid&cid=$cid&epId=$epId', - arguments: { - 'pic': videoItem.pic, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - }, - ), - ); - } + RoutePush.bangumiPush( + null, + epId, + heroTag: heroTag, + ); break; case 'av': String bvid = videoItem.bvid ?? IdUtils.av2bv(videoItem.aid); diff --git a/lib/pages/bangumi/widgets/bangumu_card_v.dart b/lib/pages/bangumi/widgets/bangumu_card_v.dart index 3c8f6d2a..a1d7a931 100644 --- a/lib/pages/bangumi/widgets/bangumu_card_v.dart +++ b/lib/pages/bangumi/widgets/bangumu_card_v.dart @@ -1,13 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/common/widgets/badge.dart'; -import 'package:pilipala/http/search.dart'; -import 'package:pilipala/models/bangumi/info.dart'; import 'package:pilipala/models/bangumi/list.dart'; -import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/utils/image_save.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; @@ -24,32 +21,12 @@ class BangumiCardV extends StatelessWidget { Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(bangumiItem.mediaId); return InkWell( - onTap: () async { - final int seasonId = bangumiItem.seasonId!; - SmartDialog.showLoading(msg: '获取中...'); - final res = await SearchHttp.bangumiInfo(seasonId: seasonId); - SmartDialog.dismiss().then((value) { - if (res['status']) { - if (res['data'].episodes.isEmpty) { - SmartDialog.showToast('资源加载失败'); - return; - } - EpisodeItem episode = res['data'].episodes.first; - String bvid = episode.bvid!; - int cid = episode.cid!; - String pic = episode.cover!; - String heroTag = Utils.makeHeroTag(cid); - Get.toNamed( - '/video?bvid=$bvid&cid=$cid&seasonId=$seasonId', - arguments: { - 'pic': pic, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - 'bangumiItem': res['data'], - }, - ); - } - }); + onTap: () { + RoutePush.bangumiPush( + bangumiItem.seasonId, + null, + heroTag: heroTag, + ); }, onLongPress: () => imageSaveDialog(context, bangumiItem, SmartDialog.dismiss), diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index b7676663..6814704c 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -14,6 +14,7 @@ import 'package:pilipala/models/dynamics/up.dart'; import 'package:pilipala/models/live/item.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/id_utils.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; @@ -220,25 +221,7 @@ class DynamicsController extends GetxController { print('DYNAMIC_TYPE_PGC_UNION 番剧'); DynamicArchiveModel pgc = item.modules.moduleDynamic.major.pgc; if (pgc.epid != null) { - SmartDialog.showLoading(msg: '获取中...'); - var res = await SearchHttp.bangumiInfo(epId: pgc.epid); - SmartDialog.dismiss(); - if (res['status']) { - EpisodeItem episode = res['data'].episodes.first; - String bvid = episode.bvid!; - int cid = episode.cid!; - String pic = episode.cover!; - String heroTag = Utils.makeHeroTag(cid); - Get.toNamed( - '/video?bvid=$bvid&cid=$cid&seasonId=${res['data'].seasonId}', - arguments: { - 'pic': pic, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - 'bangumiItem': res['data'], - }, - ); - } + RoutePush.bangumiPush(null, pgc.epid); } break; } diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 39c6931d..ba5f6b5c 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -7,13 +7,13 @@ import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/http/search.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/video.dart'; -import 'package:pilipala/models/bangumi/info.dart'; import 'package:pilipala/models/common/business_type.dart'; import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/models/live/item.dart'; import 'package:pilipala/pages/history_search/index.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/id_utils.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/utils.dart'; class HistoryItem extends StatelessWidget { @@ -101,26 +101,11 @@ class HistoryItem extends StatelessWidget { } } else { if (videoItem.history.epid != '') { - SmartDialog.showLoading(msg: '获取中...'); - var res = - await SearchHttp.bangumiInfo(epId: videoItem.history.epid); - SmartDialog.dismiss(); - if (res['status']) { - EpisodeItem episode = res['data'].episodes.first; - String bvid = episode.bvid!; - int cid = episode.cid!; - String pic = episode.cover!; - String heroTag = Utils.makeHeroTag(cid); - Get.toNamed( - '/video?bvid=$bvid&cid=$cid&seasonId=${res['data'].seasonId}', - arguments: { - 'pic': pic, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - 'bangumiItem': res['data'], - }, - ); - } + RoutePush.bangumiPush( + null, + videoItem.history.epid, + heroTag: heroTag, + ); } } } else { diff --git a/lib/pages/search_panel/widgets/media_bangumi_panel.dart b/lib/pages/search_panel/widgets/media_bangumi_panel.dart index 7d88b183..5bba0ab8 100644 --- a/lib/pages/search_panel/widgets/media_bangumi_panel.dart +++ b/lib/pages/search_panel/widgets/media_bangumi_panel.dart @@ -7,6 +7,7 @@ import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/http/search.dart'; import 'package:pilipala/models/bangumi/info.dart'; import 'package:pilipala/models/common/search_type.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/utils.dart'; Widget searchMbangumiPanel(BuildContext context, ctr, list) { @@ -108,28 +109,8 @@ Widget searchMbangumiPanel(BuildContext context, ctr, list) { SizedBox( height: 32, child: ElevatedButton( - onPressed: () async { - SmartDialog.showLoading(msg: '获取中...'); - var res = await SearchHttp.bangumiInfo( - seasonId: i.seasonId); - SmartDialog.dismiss().then((value) { - if (res['status']) { - EpisodeItem episode = res['data'].episodes.first; - String bvid = episode.bvid!; - int cid = episode.cid!; - String pic = episode.cover!; - String heroTag = Utils.makeHeroTag(cid); - Get.toNamed( - '/video?bvid=$bvid&cid=$cid&seasonId=${i.seasonId}', - arguments: { - 'pic': pic, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - 'bangumiItem': res['data'], - }, - ); - } - }); + onPressed: () { + RoutePush.bangumiPush(i.seasonId, null); }, child: const Text('观看'), ), diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 4fd49254..743cf901 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/storage.dart'; @@ -49,6 +50,13 @@ class ChatItem extends StatelessWidget { this.e_infos, }); + static List matchNum(String str) { + final RegExp regExp = RegExp(r'\d+'); + final Iterable matches = regExp.allMatches(str); + + return matches.map((Match match) => int.parse(match.group(0)!)).toList(); + } + @override Widget build(BuildContext context) { bool isOwner = @@ -154,16 +162,33 @@ class ChatItem extends StatelessWidget { GestureDetector( onTap: () async { SmartDialog.showLoading(); - var bvid = content["bvid"]; + final String bvid = content["bvid"]; + // 16番剧 5投稿 + final int source = content["source"]; + final String? url = content["url"]; + final int cid = await SearchHttp.ab2c(bvid: bvid); final String heroTag = Utils.makeHeroTag(bvid); - SmartDialog.dismiss().then( - (e) => Get.toNamed('/video?bvid=$bvid&cid=$cid', - arguments: { - 'pic': content['thumb'], - 'heroTag': heroTag, - }), - ); + await SmartDialog.dismiss(); + if (source == 5) { + Get.toNamed( + '/video?bvid=$bvid&cid=$cid', + arguments: { + 'pic': content['thumb'], + 'heroTag': heroTag, + }, + ); + } + if (source == 16) { + if (url != null) { + final String area = url.split('/').last; + if (area.startsWith('ep')) { + RoutePush.bangumiPush(null, matchNum(area).first); + } else if (area.startsWith('ss')) { + RoutePush.bangumiPush(matchNum(area).first, null); + } + } + } }, child: NetworkImgLayer( width: 220, @@ -183,7 +208,7 @@ class ChatItem extends StatelessWidget { ), const SizedBox(height: 1), Text( - content['author'], + content['author'] ?? '', style: TextStyle( letterSpacing: 0.6, height: 1.5, @@ -206,7 +231,7 @@ class ChatItem extends StatelessWidget { SmartDialog.dismiss().then( (e) => Get.toNamed('/video?bvid=$bvid&cid=$cid', arguments: { - 'pic': content['thumb'], + 'pic': content['thumb'] ?? '', 'heroTag': heroTag, }), ); diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 5bfb955c..5b77434d 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -2,6 +2,7 @@ import 'package:appscheme/appscheme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/utils/route_push.dart'; import '../http/search.dart'; import '../models/common/search_type.dart'; import 'id_utils.dart'; @@ -68,7 +69,7 @@ class PiliSchame { } else if (host == 'bangumi') { if (path.startsWith('/season')) { final String seasonId = path.split('/').last; - _bangumiPush(int.parse(seasonId), null); + RoutePush.bangumiPush(int.parse(seasonId), null); } } else if (host == 'opus') { if (path.startsWith('/detail')) { @@ -126,35 +127,6 @@ class PiliSchame { } } - // 番剧跳转 - static Future _bangumiPush(int? seasonId, int? epId) async { - SmartDialog.showLoading(msg: '获取中...'); - try { - var result = await SearchHttp.bangumiInfo(seasonId: seasonId, epId: epId); - if (result['status']) { - var bangumiDetail = result['data']; - final int cid = bangumiDetail.episodes!.first.cid; - final String bvid = IdUtils.av2bv(bangumiDetail.episodes!.first.aid); - final String heroTag = Utils.makeHeroTag(cid); - var epId = bangumiDetail.episodes!.first.id; - SmartDialog.dismiss().then( - (e) => Get.toNamed( - '/video?bvid=$bvid&cid=$cid&epId=$epId', - arguments: { - 'pic': bangumiDetail.cover, - 'heroTag': heroTag, - 'videoType': SearchType.media_bangumi, - }, - ), - ); - } else { - SmartDialog.showToast(result['msg']); - } - } catch (e) { - SmartDialog.showToast('番剧获取失败:$e'); - } - } - static Future _fullPathPush(SchemeEntity value) async { // https://m.bilibili.com/bangumi/play/ss39708 // https | m.bilibili.com | /bangumi/play/ss39708 @@ -177,10 +149,10 @@ class PiliSchame { } if (path.startsWith('/bangumi')) { if (lastPathSegment.contains('ss')) { - _bangumiPush(matchNum(lastPathSegment).first, null); + RoutePush.bangumiPush(matchNum(lastPathSegment).first, null); } if (lastPathSegment.contains('ep')) { - _bangumiPush(null, matchNum(lastPathSegment).first); + RoutePush.bangumiPush(null, matchNum(lastPathSegment).first); } } } else if (host.contains('live')) { @@ -233,9 +205,9 @@ class PiliSchame { case 'bangumi': print('番剧'); if (area.startsWith('ep')) { - _bangumiPush(null, matchNum(area).first); + RoutePush.bangumiPush(null, matchNum(area).first); } else if (area.startsWith('ss')) { - _bangumiPush(matchNum(area).first, null); + RoutePush.bangumiPush(matchNum(area).first, null); } break; case 'video': @@ -276,12 +248,12 @@ class PiliSchame { static void _handleEpisodePath(String lastPathSegment, String redirectUrl) { final String seasonId = _extractIdFromPath(lastPathSegment); - _bangumiPush(null, matchNum(seasonId).first); + RoutePush.bangumiPush(null, matchNum(seasonId).first); } static void _handleSeasonPath(String lastPathSegment, String redirectUrl) { final String seasonId = _extractIdFromPath(lastPathSegment); - _bangumiPush(matchNum(seasonId).first, null); + RoutePush.bangumiPush(matchNum(seasonId).first, null); } static String _extractIdFromPath(String lastPathSegment) { diff --git a/lib/utils/route_push.dart b/lib/utils/route_push.dart new file mode 100644 index 00000000..e00123b4 --- /dev/null +++ b/lib/utils/route_push.dart @@ -0,0 +1,44 @@ +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/http/search.dart'; +import 'package:pilipala/models/bangumi/info.dart'; +import 'package:pilipala/models/common/search_type.dart'; +import 'package:pilipala/utils/utils.dart'; + +class RoutePush { + // 番剧跳转 + static Future bangumiPush(int? seasonId, int? epId, + {String? heroTag}) async { + SmartDialog.showLoading(msg: '获取中...'); + try { + var result = await SearchHttp.bangumiInfo(seasonId: seasonId, epId: epId); + await SmartDialog.dismiss(); + if (result['status']) { + if (result['data'].episodes.isEmpty) { + SmartDialog.showToast('资源获取失败'); + return; + } + final BangumiInfoModel bangumiDetail = result['data']; + final EpisodeItem episode = bangumiDetail.episodes!.first; + final int epId = episode.id!; + final int cid = episode.cid!; + final String bvid = episode.bvid!; + final String cover = episode.cover!; + final Map arguments = { + 'pic': cover, + 'videoType': SearchType.media_bangumi, + // 'bangumiItem': bangumiDetail, + }; + arguments['heroTag'] = heroTag ?? Utils.makeHeroTag(cid); + Get.toNamed( + '/video?bvid=$bvid&cid=$cid&epId=$epId', + arguments: arguments, + ); + } else { + SmartDialog.showToast(result['msg']); + } + } catch (e) { + SmartDialog.showToast('番剧获取失败:$e'); + } + } +} From b8efe249deae10161c0c6c5218bfa49f0e2c4bae Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 2 May 2024 23:33:58 +0800 Subject: [PATCH 044/106] =?UTF-8?q?opt:=20up=E4=B8=BB=E6=8A=95=E7=A8=BF?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E7=95=AA=E5=89=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_h.dart | 17 ++++++++++++++ .../whisper_detail/widget/chat_item.dart | 11 ++------- lib/utils/app_scheme.dart | 23 +++++++------------ lib/utils/url_utils.dart | 2 +- lib/utils/utils.dart | 7 ++++++ 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index df0c29b7..4c0729a3 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:pilipala/http/constants.dart'; import 'package:pilipala/utils/image_save.dart'; +import 'package:pilipala/utils/route_push.dart'; +import 'package:pilipala/utils/url_utils.dart'; import '../../http/search.dart'; import '../../http/user.dart'; import '../../http/video.dart'; @@ -52,6 +55,20 @@ class VideoCardH extends StatelessWidget { SmartDialog.showToast('课堂视频暂不支持播放'); return; } + if (showCharge && videoItem?.typeid == 33) { + final String redirectUrl = await UrlUtils.parseRedirectUrl( + '${HttpString.baseUrl}/video/$bvid/'); + final String lastPathSegment = redirectUrl.split('/').last; + if (lastPathSegment.contains('ss')) { + RoutePush.bangumiPush( + Utils.matchNum(lastPathSegment).first, null); + } + if (lastPathSegment.contains('ep')) { + RoutePush.bangumiPush( + null, Utils.matchNum(lastPathSegment).first); + } + return; + } final int cid = videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid); Get.toNamed('/video?bvid=$bvid&cid=$cid', diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 743cf901..ad11e4c3 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -50,13 +50,6 @@ class ChatItem extends StatelessWidget { this.e_infos, }); - static List matchNum(String str) { - final RegExp regExp = RegExp(r'\d+'); - final Iterable matches = regExp.allMatches(str); - - return matches.map((Match match) => int.parse(match.group(0)!)).toList(); - } - @override Widget build(BuildContext context) { bool isOwner = @@ -183,9 +176,9 @@ class ChatItem extends StatelessWidget { if (url != null) { final String area = url.split('/').last; if (area.startsWith('ep')) { - RoutePush.bangumiPush(null, matchNum(area).first); + RoutePush.bangumiPush(null, Utils.matchNum(area).first); } else if (area.startsWith('ss')) { - RoutePush.bangumiPush(matchNum(area).first, null); + RoutePush.bangumiPush(Utils.matchNum(area).first, null); } } } diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 5b77434d..fff78b39 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -144,15 +144,15 @@ class PiliSchame { _videoPush(null, lastPathSegment); } if (lastPathSegment.contains('av')) { - _videoPush(matchNum(lastPathSegment)[0], null); + _videoPush(Utils.matchNum(lastPathSegment)[0], null); } } if (path.startsWith('/bangumi')) { if (lastPathSegment.contains('ss')) { - RoutePush.bangumiPush(matchNum(lastPathSegment).first, null); + RoutePush.bangumiPush(Utils.matchNum(lastPathSegment).first, null); } if (lastPathSegment.contains('ep')) { - RoutePush.bangumiPush(null, matchNum(lastPathSegment).first); + RoutePush.bangumiPush(null, Utils.matchNum(lastPathSegment).first); } } } else if (host.contains('live')) { @@ -205,9 +205,9 @@ class PiliSchame { case 'bangumi': print('番剧'); if (area.startsWith('ep')) { - RoutePush.bangumiPush(null, matchNum(area).first); + RoutePush.bangumiPush(null, Utils.matchNum(area).first); } else if (area.startsWith('ss')) { - RoutePush.bangumiPush(matchNum(area).first, null); + RoutePush.bangumiPush(Utils.matchNum(area).first, null); } break; case 'video': @@ -223,7 +223,7 @@ class PiliSchame { break; case 'read': print('专栏'); - String id = 'cv${matchNum(query!['id']!).first}'; + String id = 'cv${Utils.matchNum(query!['id']!).first}'; Get.toNamed('/htmlRender', parameters: { 'url': value.dataString!, 'title': '', @@ -239,21 +239,14 @@ class PiliSchame { } } - static List matchNum(String str) { - final RegExp regExp = RegExp(r'\d+'); - final Iterable matches = regExp.allMatches(str); - - return matches.map((Match match) => int.parse(match.group(0)!)).toList(); - } - static void _handleEpisodePath(String lastPathSegment, String redirectUrl) { final String seasonId = _extractIdFromPath(lastPathSegment); - RoutePush.bangumiPush(null, matchNum(seasonId).first); + RoutePush.bangumiPush(null, Utils.matchNum(seasonId).first); } static void _handleSeasonPath(String lastPathSegment, String redirectUrl) { final String seasonId = _extractIdFromPath(lastPathSegment); - RoutePush.bangumiPush(matchNum(seasonId).first, null); + RoutePush.bangumiPush(Utils.matchNum(seasonId).first, null); } static String _extractIdFromPath(String lastPathSegment) { diff --git a/lib/utils/url_utils.dart b/lib/utils/url_utils.dart index 20f9cb0d..99886e09 100644 --- a/lib/utils/url_utils.dart +++ b/lib/utils/url_utils.dart @@ -16,7 +16,7 @@ class UrlUtils { }; try { final response = await dio.get(url); - if (response.statusCode == 302) { + if (response.statusCode == 302 || response.statusCode == 301) { redirectUrl = response.headers['location']?.first as String; if (redirectUrl.endsWith('/')) { redirectUrl = redirectUrl.substring(0, redirectUrl.length - 1); diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index b40e9bfe..e50c295c 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -383,4 +383,11 @@ class Utils { List randomBytes = generateRandomBytes(minLength, maxLength); return base64.encode(randomBytes); } + + static List matchNum(String str) { + final RegExp regExp = RegExp(r'\d+'); + final Iterable matches = regExp.allMatches(str); + + return matches.map((Match match) => int.parse(match.group(0)!)).toList(); + } } From b2eaec15b165187a201ddb8d1c0b17d948f025f7 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 3 May 2024 15:58:54 +0800 Subject: [PATCH 045/106] =?UTF-8?q?opt:=20=E8=A7=86=E9=A2=91=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E5=8A=9F=E8=83=BD=E6=8B=93=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_h.dart | 218 +++++++++++++++------------ lib/common/widgets/video_card_v.dart | 10 ++ 2 files changed, 130 insertions(+), 98 deletions(-) diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index 4c0729a3..1265477f 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.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:pilipala/http/constants.dart'; +import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/image_save.dart'; import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/url_utils.dart'; @@ -276,115 +277,29 @@ class VideoContent extends StatelessWidget { theme: 'gray', danmu: videoItem.stat.danmaku as int, ), - const Spacer(), - // SizedBox( - // width: 20, - // height: 20, - // child: IconButton( - // tooltip: '稍后再看', - // style: ButtonStyle( - // padding: MaterialStateProperty.all(EdgeInsets.zero), - // ), - // onPressed: () async { - // var res = - // await UserHttp.toViewLater(bvid: videoItem.bvid); - // SmartDialog.showToast(res['msg']); - // }, - // icon: Icon( - // Icons.more_vert_outlined, - // color: Theme.of(context).colorScheme.outline, - // size: 14, - // ), - // ), - // ), if (source == 'normal') SizedBox( width: 24, height: 24, - child: PopupMenuButton( + child: IconButton( padding: EdgeInsets.zero, + onPressed: () { + feedBack(); + showModalBottomSheet( + context: context, + useRootNavigator: true, + isScrollControlled: true, + builder: (context) { + return MorePanel(videoItem: videoItem); + }, + ); + }, icon: Icon( Icons.more_vert_outlined, color: Theme.of(context).colorScheme.outline, size: 14, ), - position: PopupMenuPosition.under, - // constraints: const BoxConstraints(maxHeight: 35), - onSelected: (String type) {}, - itemBuilder: (BuildContext context) => - >[ - PopupMenuItem( - onTap: () async { - var res = await UserHttp.toViewLater( - bvid: videoItem.bvid as String); - SmartDialog.showToast(res['msg']); - }, - value: 'pause', - height: 40, - child: const Row( - children: [ - Icon(Icons.watch_later_outlined, size: 16), - SizedBox(width: 6), - Text('稍后再看', style: TextStyle(fontSize: 13)) - ], - ), - ), - const PopupMenuDivider(), - PopupMenuItem( - onTap: () async { - SmartDialog.show( - useSystem: true, - animationType: - SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: Text( - '确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' - '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'), - actions: [ - TextButton( - onPressed: () => SmartDialog.dismiss(), - child: Text( - '点错了', - style: TextStyle( - color: Theme.of(context) - .colorScheme - .outline), - ), - ), - TextButton( - onPressed: () async { - var res = await VideoHttp.relationMod( - mid: videoItem.owner.mid, - act: 5, - reSrc: 11, - ); - SmartDialog.dismiss(); - SmartDialog.showToast(res['code'] == 0 - ? '成功' - : res['msg']); - }, - child: const Text('确认'), - ) - ], - ); - }, - ); - }, - value: 'pause', - height: 40, - child: Row( - children: [ - const Icon(Icons.block, size: 16), - const SizedBox(width: 6), - Text('拉黑:${videoItem.owner.name}', - style: const TextStyle(fontSize: 13)) - ], - ), - ), - ], ), ), if (source == 'later') ...[ @@ -408,3 +323,110 @@ class VideoContent extends StatelessWidget { ); } } + +class MorePanel extends StatelessWidget { + final dynamic videoItem; + const MorePanel({super.key, required this.videoItem}); + + Future menuActionHandler(String type) async { + switch (type) { + case 'block': + blockUser(); + break; + case 'watchLater': + var res = await UserHttp.toViewLater(bvid: videoItem.bvid as String); + SmartDialog.showToast(res['msg']); + Get.back(); + break; + default: + } + } + + void blockUser() async { + SmartDialog.show( + useSystem: true, + animationType: SmartAnimationType.centerFade_otherSlide, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('提示'), + content: Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' + '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除'), + actions: [ + TextButton( + onPressed: () => SmartDialog.dismiss(), + child: Text( + '点错了', + style: TextStyle(color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () async { + var res = await VideoHttp.relationMod( + mid: videoItem.owner.mid, + act: 5, + reSrc: 11, + ); + SmartDialog.dismiss(); + SmartDialog.showToast(res['msg'] ?? '成功'); + }, + child: const Text('确认'), + ) + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + onTap: () => Get.back(), + child: Container( + height: 35, + padding: const EdgeInsets.only(bottom: 2), + child: Center( + child: Container( + width: 32, + height: 3, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.outline, + borderRadius: const BorderRadius.all(Radius.circular(3))), + ), + ), + ), + ), + ListTile( + onTap: () async => await menuActionHandler('block'), + minLeadingWidth: 0, + leading: const Icon(Icons.block, size: 19), + title: Text( + '拉黑up主 「${videoItem.owner.name}」', + style: Theme.of(context).textTheme.titleSmall, + ), + ), + ListTile( + onTap: () async => await menuActionHandler('watchLater'), + minLeadingWidth: 0, + leading: const Icon(Icons.watch_later_outlined, size: 19), + title: + Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall), + ), + ListTile( + onTap: () => + imageSaveDialog(context, videoItem, SmartDialog.dismiss), + minLeadingWidth: 0, + leading: const Icon(Icons.photo_outlined, size: 19), + title: + Text('查看视频封面', style: Theme.of(context).textTheme.titleSmall), + ), + const SizedBox(height: 20), + ], + ), + ); + } +} diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 15fbc6fc..7b56152f 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -233,6 +233,7 @@ class VideoContent extends StatelessWidget { width: 24, height: 24, child: IconButton( + padding: EdgeInsets.zero, onPressed: () { feedBack(); showModalBottomSheet( @@ -386,6 +387,15 @@ class MorePanel extends StatelessWidget { title: Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall), ), + ListTile( + onTap: () => + imageSaveDialog(context, videoItem, SmartDialog.dismiss), + minLeadingWidth: 0, + leading: const Icon(Icons.photo_outlined, size: 19), + title: + Text('查看视频封面', style: Theme.of(context).textTheme.titleSmall), + ), + const SizedBox(height: 20), ], ), ); From 81af23e870a4fcb5ff11ee2981c508d520548999 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 3 May 2024 21:04:03 +0800 Subject: [PATCH 046/106] mod: MainActivity --- android/app/src/main/AndroidManifest.xml | 2 +- .../kotlin/com/guozhigq/pilipala/MainActivity.kt | 6 ++++-- pubspec.lock | 14 +++++++------- pubspec.yaml | 4 ++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index c52d8447..f119eb1e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -45,7 +45,7 @@ android:fullBackupContent="false" tools:replace="android:allowBackup"> Date: Fri, 3 May 2024 21:41:04 +0800 Subject: [PATCH 047/106] =?UTF-8?q?mod:=20=E5=BA=95=E9=83=A8=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E6=A0=8Fsdk=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 43bcf930..066bb599 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -67,9 +68,8 @@ void main() async { // 小白条、导航栏沉浸 if (Platform.isAndroid) { - List versionParts = Platform.version.split('.'); - int androidVersion = int.parse(versionParts[0]); - if (androidVersion >= 29) { + final androidInfo = await DeviceInfoPlugin().androidInfo; + if (androidInfo.version.sdkInt >= 29) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( From a32be2c5c622f5f05544e2c6d214efa7bdf4efb7 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 3 May 2024 21:42:01 +0800 Subject: [PATCH 048/106] =?UTF-8?q?fix:=20=E5=8D=8A=E5=B1=8F=E6=97=B6?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E5=AE=8C=E6=88=90=E7=8A=B6=E6=80=81=E6=A0=8F?= =?UTF-8?q?=E6=B6=88=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugin/pl_player/controller.dart | 35 +--------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 4b6c44a1..2fc16924 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -978,41 +978,8 @@ class PlPlayerController { } else { await landScape(); } - - // bool isValid = - // direction.value == 'vertical' || mode == FullScreenMode.vertical - // ? true - // : false; - // var result = await showDialog( - // context: Get.context!, - // useSafeArea: false, - // builder: (context) => Dialog.fullscreen( - // backgroundColor: Colors.black, - // child: SafeArea( - // // 忽略手机安全区域 - // top: isValid, - // left: false, - // right: false, - // bottom: isValid, - // child: PLVideoPlayer( - // controller: this, - // headerControl: headerControl, - // bottomControl: bottomControl, - // danmuWidget: danmuWidget, - // ), - // ), - // ), - // ); - // if (result == null) { - // // 退出全屏 - // StatusBarControl.setHidden(false, animation: StatusBarAnimation.FADE); - // exitFullScreen(); - // await verticalScreen(); - // toggleFullScreen(false); - // } - } else if (isFullScreen.value) { + } else if (isFullScreen.value && !status) { StatusBarControl.setHidden(false, animation: StatusBarAnimation.FADE); - // Get.back(); exitFullScreen(); await verticalScreen(); toggleFullScreen(false); From dafbb838636298a75edd14d98e1079cf2f2a805e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 3 May 2024 22:58:14 +0800 Subject: [PATCH 049/106] =?UTF-8?q?opt:=20=E5=AA=92=E4=BD=93=E5=BA=93?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=99=BB=E5=BD=95=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/dynamics.dart | 1 + lib/http/user.dart | 24 +++++++++++++++---- lib/pages/dynamics/controller.dart | 4 ++-- lib/pages/dynamics/view.dart | 32 ++++++++++++-------------- lib/pages/fav/controller.dart | 9 ++++++-- lib/pages/fav/view.dart | 19 +++++++++++---- lib/pages/history/controller.dart | 7 ++++++ lib/pages/history/view.dart | 19 +++++++++++---- lib/pages/later/controller.dart | 14 +++++++++++ lib/pages/later/view.dart | 21 ++++++++++++----- lib/pages/mine/controller.dart | 10 ++------ lib/pages/subscription/controller.dart | 9 ++++++-- lib/pages/subscription/view.dart | 15 ++++++++++-- lib/utils/route_push.dart | 24 +++++++++++++++++++ 14 files changed, 157 insertions(+), 51 deletions(-) diff --git a/lib/http/dynamics.dart b/lib/http/dynamics.dart index 63dea4ff..69619361 100644 --- a/lib/http/dynamics.dart +++ b/lib/http/dynamics.dart @@ -41,6 +41,7 @@ class DynamicsHttp { 'status': false, 'data': [], 'msg': res.data['message'], + 'code': res.data['code'], }; } } diff --git a/lib/http/user.dart b/lib/http/user.dart index dfdf187e..972acfdd 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -62,7 +62,8 @@ class UserHttp { return { 'status': false, 'data': [], - 'msg': res.data['message'] ?? '账号未登录' + 'msg': res.data['message'], + 'code': res.data['code'], }; } } @@ -111,7 +112,12 @@ class UserHttp { 'data': {'list': list, 'count': res.data['data']['count']} }; } else { - return {'status': false, 'data': [], 'msg': res.data['message']}; + return { + 'status': false, + 'data': [], + 'msg': res.data['message'], + 'code': res.data['code'], + }; } } @@ -126,7 +132,12 @@ class UserHttp { if (res.data['code'] == 0) { return {'status': true, 'data': HistoryData.fromJson(res.data['data'])}; } else { - return {'status': false, 'data': [], 'msg': res.data['message']}; + return { + 'status': false, + 'data': [], + 'msg': res.data['message'], + 'code': res.data['code'], + }; } } @@ -326,7 +337,12 @@ class UserHttp { 'data': SubFolderModelData.fromJson(res.data['data']) }; } else { - return {'status': false, 'msg': res.data['message']}; + return { + 'status': false, + 'data': [], + 'msg': res.data['message'], + 'code': res.data['code'], + }; } } diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index 6814704c..9bed3685 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -71,7 +71,7 @@ class DynamicsController extends GetxController { Future queryFollowDynamic({type = 'init'}) async { if (!userLogin.value) { - return {'status': false, 'msg': '账号未登录'}; + return {'status': false, 'msg': '账号未登录', 'code': -101}; } if (type == 'init') { dynamicsList.clear(); @@ -229,7 +229,7 @@ class DynamicsController extends GetxController { Future queryFollowUp({type = 'init'}) async { if (!userLogin.value) { - return {'status': false, 'msg': '账号未登录'}; + return {'status': false, 'msg': '账号未登录', 'code': -101}; } if (type == 'init') { upData.value.upList = []; diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index 82a555b1..da15239d 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -11,6 +11,7 @@ import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/models/dynamics/result.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/main_stream.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/storage.dart'; import '../mine/controller.dart'; @@ -224,8 +225,8 @@ class _DynamicsPageState extends State if (snapshot.data == null) { return const SliverToBoxAdapter(child: SizedBox()); } - Map data = snapshot.data; - if (data['status']) { + Map? data = snapshot.data; + if (data != null && data['status']) { List list = _dynamicsController.dynamicsList; return Obx( @@ -248,24 +249,21 @@ class _DynamicsPageState extends State } }, ); - } else if (data['msg'] == "账号未登录") { - return HttpError( - errMsg: data['msg'], - btnText: "去登录", - fn: () { - mineController.onLogin(); - }, - ); } else { return HttpError( - errMsg: data['msg'], + errMsg: data?['msg'] ?? '请求异常', + btnText: data?['code'] == -101 ? '去登录' : null, fn: () { - setState(() { - _futureBuilderFuture = - _dynamicsController.queryFollowDynamic(); - _futureBuilderFutureUp = - _dynamicsController.queryFollowUp(); - }); + if (data?['code'] == -101) { + RoutePush.loginRedirectPush(); + } else { + setState(() { + _futureBuilderFuture = + _dynamicsController.queryFollowDynamic(); + _futureBuilderFutureUp = + _dynamicsController.queryFollowUp(); + }); + } }, ); } diff --git a/lib/pages/fav/controller.dart b/lib/pages/fav/controller.dart index 2307d303..8fcbf971 100644 --- a/lib/pages/fav/controller.dart +++ b/lib/pages/fav/controller.dart @@ -17,10 +17,15 @@ class FavController extends GetxController { int pageSize = 60; RxBool hasMore = true.obs; - Future queryFavFolder({type = 'init'}) async { + @override + void onInit() { userInfo = userInfoCache.get('userInfoCache'); + super.onInit(); + } + + Future queryFavFolder({type = 'init'}) async { if (userInfo == null) { - return {'status': false, 'msg': '账号未登录'}; + return {'status': false, 'msg': '账号未登录', 'code': -101}; } if (!hasMore.value) { return; diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index 424a885d..b8d37f50 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/pages/fav/index.dart'; import 'package:pilipala/pages/fav/widgets/item.dart'; +import 'package:pilipala/utils/route_push.dart'; class FavPage extends StatefulWidget { const FavPage({super.key}); @@ -57,8 +58,8 @@ class _FavPageState extends State { future: _futureBuilderFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - Map data = snapshot.data as Map; - if (data['status']) { + Map? data = snapshot.data; + if (data != null && data['status']) { return Obx( () => ListView.builder( controller: scrollController, @@ -74,8 +75,18 @@ class _FavPageState extends State { physics: const NeverScrollableScrollPhysics(), slivers: [ HttpError( - errMsg: data['msg'], - fn: () => setState(() {}), + errMsg: data?['msg'] ?? '请求异常', + btnText: data?['code'] == -101 ? '去登录' : null, + fn: () { + if (data?['code'] == -101) { + RoutePush.loginRedirectPush(); + } else { + setState(() { + _futureBuilderFuture = + _favController.queryFavFolder(); + }); + } + }, ), ], ); diff --git a/lib/pages/history/controller.dart b/lib/pages/history/controller.dart index a1f18113..64953e3b 100644 --- a/lib/pages/history/controller.dart +++ b/lib/pages/history/controller.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/user.dart'; import 'package:pilipala/models/user/history.dart'; +import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/utils/storage.dart'; class HistoryController extends GetxController { @@ -15,14 +16,20 @@ class HistoryController extends GetxController { RxBool isLoading = false.obs; RxBool enableMultiple = false.obs; RxInt checkedCount = 0.obs; + Box userInfoCache = GStrorage.userInfo; + UserInfoData? userInfo; @override void onInit() { super.onInit(); historyStatus(); + userInfo = userInfoCache.get('userInfoCache'); } Future queryHistoryList({type = 'init'}) async { + if (userInfo == null) { + return {'status': false, 'msg': '账号未登录', 'code': -101}; + } int max = 0; int viewAt = 0; if (type == 'onload') { diff --git a/lib/pages/history/view.dart b/lib/pages/history/view.dart index 92e1eee7..f9695aed 100644 --- a/lib/pages/history/view.dart +++ b/lib/pages/history/view.dart @@ -5,6 +5,7 @@ import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/pages/history/index.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'widgets/item.dart'; @@ -183,8 +184,8 @@ class _HistoryPageState extends State { if (snapshot.data == null) { return const SliverToBoxAdapter(child: SizedBox()); } - Map data = snapshot.data; - if (data['status']) { + Map? data = snapshot.data; + if (data != null && data['status']) { return Obx( () => _historyController.historyList.isNotEmpty ? SliverList( @@ -209,8 +210,18 @@ class _HistoryPageState extends State { ); } else { return HttpError( - errMsg: data['msg'], - fn: () => setState(() {}), + errMsg: data?['msg'] ?? '请求异常', + btnText: data?['code'] == -101 ? '去登录' : null, + fn: () { + if (data?['code'] == -101) { + RoutePush.loginRedirectPush(); + } else { + setState(() { + _futureBuilderFuture = + _historyController.queryHistoryList(); + }); + } + }, ); } } else { diff --git a/lib/pages/later/controller.dart b/lib/pages/later/controller.dart index 3de51901..f7dfea9f 100644 --- a/lib/pages/later/controller.dart +++ b/lib/pages/later/controller.dart @@ -1,16 +1,30 @@ 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/user.dart'; import 'package:pilipala/models/model_hot_video_item.dart'; +import 'package:pilipala/models/user/info.dart'; +import 'package:pilipala/utils/storage.dart'; class LaterController extends GetxController { final ScrollController scrollController = ScrollController(); RxList laterList = [].obs; int count = 0; RxBool isLoading = false.obs; + Box userInfoCache = GStrorage.userInfo; + UserInfoData? userInfo; + + @override + void onInit() { + super.onInit(); + userInfo = userInfoCache.get('userInfoCache'); + } Future queryLaterList() async { + if (userInfo == null) { + return {'status': false, 'msg': '账号未登录', 'code': -101}; + } isLoading.value = true; var res = await UserHttp.seeYouLater(); if (res['status']) { diff --git a/lib/pages/later/view.dart b/lib/pages/later/view.dart index 7c6e158d..0a02cb79 100644 --- a/lib/pages/later/view.dart +++ b/lib/pages/later/view.dart @@ -5,6 +5,7 @@ import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; import 'package:pilipala/pages/later/index.dart'; +import 'package:pilipala/utils/route_push.dart'; class LaterPage extends StatefulWidget { const LaterPage({super.key}); @@ -72,8 +73,8 @@ class _LaterPageState extends State { future: _futureBuilderFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { - Map data = snapshot.data as Map; - if (data['status']) { + Map? data = snapshot.data; + if (data != null && data['status']) { return Obx( () => _laterController.laterList.isNotEmpty && !_laterController.isLoading.value @@ -96,10 +97,18 @@ class _LaterPageState extends State { ); } else { return HttpError( - errMsg: data['msg'], - fn: () => setState(() { - _futureBuilderFuture = _laterController.queryLaterList(); - }), + errMsg: data?['msg'] ?? '请求异常', + btnText: data?['code'] == -101 ? '去登录' : null, + fn: () { + if (data?['code'] == -101) { + RoutePush.loginRedirectPush(); + } else { + setState(() { + _futureBuilderFuture = + _laterController.queryLaterList(); + }); + } + }, ); } } else { diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index 5ad9e852..a61bb820 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -6,6 +6,7 @@ import 'package:pilipala/http/user.dart'; import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/user/stat.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/storage.dart'; class MineController extends GetxController { @@ -33,14 +34,7 @@ class MineController extends GetxController { onLogin() async { if (!userLogin.value) { - Get.toNamed( - '/webview', - parameters: { - 'url': 'https://passport.bilibili.com/h5-app/passport/login', - 'type': 'login', - 'pageTitle': '登录bilibili', - }, - ); + RoutePush.loginPush(); // Get.toNamed('/loginPage'); } else { int mid = userInfo.value.mid!; diff --git a/lib/pages/subscription/controller.dart b/lib/pages/subscription/controller.dart index 7be8d22c..d8a76d44 100644 --- a/lib/pages/subscription/controller.dart +++ b/lib/pages/subscription/controller.dart @@ -17,10 +17,15 @@ class SubController extends GetxController { int pageSize = 20; RxBool hasMore = true.obs; - Future querySubFolder({type = 'init'}) async { + @override + void onInit() { + super.onInit(); userInfo = userInfoCache.get('userInfoCache'); + } + + Future querySubFolder({type = 'init'}) async { if (userInfo == null) { - return {'status': false, 'msg': '账号未登录'}; + return {'status': false, 'msg': '账号未登录', 'code': -101}; } var res = await UserHttp.userSubFolder( pn: currentPage, diff --git a/lib/pages/subscription/view.dart b/lib/pages/subscription/view.dart index 2d7d0cb5..5e6e4664 100644 --- a/lib/pages/subscription/view.dart +++ b/lib/pages/subscription/view.dart @@ -2,6 +2,7 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/utils/route_push.dart'; import 'controller.dart'; import 'widgets/item.dart'; @@ -68,8 +69,18 @@ class _SubPageState extends State { physics: const NeverScrollableScrollPhysics(), slivers: [ HttpError( - errMsg: data?['msg'], - fn: () => setState(() {}), + errMsg: data?['msg'] ?? '请求异常', + btnText: data?['code'] == -101 ? '去登录' : null, + fn: () { + if (data?['code'] == -101) { + RoutePush.loginRedirectPush(); + } else { + setState(() { + _futureBuilderFuture = + _subController.querySubFolder(); + }); + } + }, ), ], ); diff --git a/lib/utils/route_push.dart b/lib/utils/route_push.dart index e00123b4..9ee28846 100644 --- a/lib/utils/route_push.dart +++ b/lib/utils/route_push.dart @@ -41,4 +41,28 @@ class RoutePush { SmartDialog.showToast('番剧获取失败:$e'); } } + + // 登录跳转 + static Future loginPush() async { + await Get.toNamed( + '/webview', + parameters: { + 'url': 'https://passport.bilibili.com/h5-app/passport/login', + 'type': 'login', + 'pageTitle': '登录bilibili', + }, + ); + } + + // 登录跳转 + static Future loginRedirectPush() async { + await Get.offAndToNamed( + '/webview', + parameters: { + 'url': 'https://passport.bilibili.com/h5-app/passport/login', + 'type': 'login', + 'pageTitle': '登录bilibili', + }, + ); + } } From 15f7c4a8021658bfb5012d14b9a04b94cc5ea24e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 4 May 2024 23:22:24 +0800 Subject: [PATCH 050/106] =?UTF-8?q?v1.0.23=20=E6=9B=B4=E6=96=B0=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- change_log/1.0.23.0504.md | 14 ++++++++++++++ pubspec.yaml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 change_log/1.0.23.0504.md diff --git a/change_log/1.0.23.0504.md b/change_log/1.0.23.0504.md new file mode 100644 index 00000000..afd401fa --- /dev/null +++ b/change_log/1.0.23.0504.md @@ -0,0 +1,14 @@ +## 1.0.23 + +### 功能 ++ 封面下载 + + +### 修复 ++ 全屏问题 ++ 视频播放器灰屏问题 ++ 评论区点击区域问题 + + +更多更新日志可在Github上查看 +问题反馈、功能建议请查看「关于」页面。 diff --git a/pubspec.yaml b/pubspec.yaml index fd34a8f6..a269cd6f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.22+1022 +version: 1.0.23+1023 environment: sdk: ">=3.0.0 <4.0.0" From bb4325768f0e12d018e2d5ff33d434f056b35fed Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 5 May 2024 10:06:26 +0800 Subject: [PATCH 051/106] =?UTF-8?q?fix:=20=E8=A7=86=E9=A2=91=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=99=A8=E5=B0=81=E9=9D=A2=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/network_img_layer.dart | 3 +++ lib/pages/video/detail/view.dart | 12 +++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index bda8ee5c..d2772478 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -34,6 +34,9 @@ class NetworkImgLayer extends StatelessWidget { @override Widget build(BuildContext context) { final int defaultImgQuality = GlobalData().imgQuality; + if (src == '' || src == null) { + return placeholder(context); + } final String imageUrl = '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp'; int? memCacheWidth, memCacheHeight; diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index bcacbbbb..2c35858f 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -323,11 +323,13 @@ class _VideoDetailPageState extends State children: [ GestureDetector( onTap: handlePlay, - child: Image.network( - vdCtr.videoItem['pic'], - width: Get.width, - height: videoHeight, - fit: BoxFit.cover, // 适应方式根据需要调整 + child: Obx( + () => NetworkImgLayer( + src: vdCtr.cover.value, + width: Get.width, + height: videoHeight, + type: 'emote', + ), ), ), buildCustomAppBar(), From 93d8e19a8ca1d74b7ff3eb6c389aa38201954dc0 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 5 May 2024 17:00:35 +0800 Subject: [PATCH 052/106] =?UTF-8?q?fix:=20=E5=8A=A8=E6=80=81=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=E8=AF=A6=E6=83=85=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/dynamics/detail/view.dart | 2 +- lib/pages/dynamics/widgets/dynamic_panel.dart | 3 +-- lib/pages/dynamics/widgets/video_panel.dart | 13 +++++-------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index bd07921b..e83b5547 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -196,7 +196,7 @@ class _DynamicDetailPageState extends State centerTitle: false, titleSpacing: 0, title: StreamBuilder( - stream: titleStreamC.stream.distinct(), + stream: titleStreamC.stream, initialData: false, builder: (context, AsyncSnapshot snapshot) { return AnimatedOpacity( diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart index d273a1a6..cc5dcbb1 100644 --- a/lib/pages/dynamics/widgets/dynamic_panel.dart +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/pages/dynamics/index.dart'; -import '../../../models/dynamics/result.dart'; import 'action_panel.dart'; import 'author_panel.dart'; import 'content_panel.dart'; import 'forward_panel.dart'; class DynamicPanel extends StatelessWidget { - final DynamicItemModel item; + final dynamic item; final String? source; DynamicPanel({required this.item, this.source, Key? key}) : super(key: key); final DynamicsController _dynamicsController = Get.put(DynamicsController()); diff --git a/lib/pages/dynamics/widgets/video_panel.dart b/lib/pages/dynamics/widgets/video_panel.dart index 32a6e21c..828fb283 100644 --- a/lib/pages/dynamics/widgets/video_panel.dart +++ b/lib/pages/dynamics/widgets/video_panel.dart @@ -80,14 +80,11 @@ Widget videoSeasonWidget(item, context, type, {floor = 1}) { double width = box.maxWidth; return Stack( children: [ - Hero( - tag: content.bvid, - child: NetworkImgLayer( - type: floor == 1 ? 'emote' : null, - width: width, - height: width / StyleString.aspectRatio, - src: content.cover, - ), + NetworkImgLayer( + type: floor == 1 ? 'emote' : null, + width: width, + height: width / StyleString.aspectRatio, + src: content.cover, ), if (content.badge != null && type == 'pgc') PBadge( From e65389040f5be4a628928502f6488bd759035532 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 5 May 2024 17:53:54 +0800 Subject: [PATCH 053/106] =?UTF-8?q?feat:=20=E6=90=9C=E7=B4=A2=E8=AE=A1?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 3 ++ lib/http/search.dart | 24 +++++++++ lib/models/search/all.dart | 9 ++++ lib/pages/search_result/controller.dart | 19 +++++++ lib/pages/search_result/view.dart | 68 +++++++++++++------------ 5 files changed, 91 insertions(+), 32 deletions(-) create mode 100644 lib/models/search/all.dart diff --git a/lib/http/api.dart b/lib/http/api.dart index 1735902c..42fc03b8 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -520,4 +520,7 @@ class Api { /// 删除收藏夹 static const String delFavFolder = '/x/v3/fav/folder/del'; + + /// 搜索结果计数 + static const String searchCount = '/x/web-interface/wbi/search/all/v2'; } diff --git a/lib/http/search.dart b/lib/http/search.dart index cf1a1b49..9b493a84 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -1,5 +1,7 @@ import 'dart:convert'; import 'package:hive/hive.dart'; +import 'package:pilipala/models/search/all.dart'; +import 'package:pilipala/utils/wbi_sign.dart'; import '../models/bangumi/info.dart'; import '../models/common/search_type.dart'; import '../models/search/hot.dart'; @@ -179,4 +181,26 @@ class SearchHttp { 'pic': res.data['data'].first['first_frame'], }; } + + static Future> searchCount( + {required String keyword}) async { + Map data = { + 'keyword': keyword, + 'web_location': 333.999, + }; + Map params = await WbiSign().makSign(data); + final dynamic res = await Request().get(Api.searchCount, data: params); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': SearchAllModel.fromJson(res.data['data']), + }; + } else { + return { + 'status': false, + 'data': [], + 'msg': '请求错误 🙅', + }; + } + } } diff --git a/lib/models/search/all.dart b/lib/models/search/all.dart new file mode 100644 index 00000000..796400da --- /dev/null +++ b/lib/models/search/all.dart @@ -0,0 +1,9 @@ +class SearchAllModel { + SearchAllModel({this.topTList}); + + Map? topTList; + + SearchAllModel.fromJson(Map json) { + topTList = json['top_tlist']; + } +} diff --git a/lib/pages/search_result/controller.dart b/lib/pages/search_result/controller.dart index 9914d82b..02a9e63b 100644 --- a/lib/pages/search_result/controller.dart +++ b/lib/pages/search_result/controller.dart @@ -1,8 +1,11 @@ import 'package:get/get.dart'; +import 'package:pilipala/http/search.dart'; +import 'package:pilipala/models/common/search_type.dart'; class SearchResultController extends GetxController { String? keyword; int tabIndex = 0; + RxList searchTabs = [].obs; @override void onInit() { @@ -10,5 +13,21 @@ class SearchResultController extends GetxController { if (Get.parameters.keys.isNotEmpty) { keyword = Get.parameters['keyword']; } + searchTabs.value = SearchType.values + .map((type) => {'label': type.label, 'id': type.type}) + .toList(); + querySearchCount(); + } + + Future querySearchCount() async { + var result = await SearchHttp.searchCount(keyword: keyword!); + if (result['status']) { + for (var i in searchTabs) { + final count = result['data'].topTList[i['id']]; + i['count'] = count > 99 ? '99+' : count.toString(); + } + searchTabs.refresh(); + } + return result; } } diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index ff5bf780..96fdd91d 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -13,7 +13,7 @@ class SearchResultPage extends StatefulWidget { class _SearchResultPageState extends State with TickerProviderStateMixin { - late SearchResultController? _searchResultController; + late SearchResultController _searchResultController; late TabController? _tabController; @override @@ -25,7 +25,7 @@ class _SearchResultPageState extends State _tabController = TabController( vsync: this, length: SearchType.values.length, - initialIndex: _searchResultController!.tabIndex, + initialIndex: _searchResultController.tabIndex, ); } @@ -46,7 +46,7 @@ class _SearchResultPageState extends State child: SizedBox( width: double.infinity, child: Text( - '${_searchResultController!.keyword}', + '${_searchResultController.keyword}', style: Theme.of(context).textTheme.titleMedium, ), ), @@ -64,35 +64,39 @@ class _SearchResultPageState extends State splashColor: Colors.transparent, // 点击时的水波纹颜色设置为透明 highlightColor: Colors.transparent, // 点击时的背景高亮颜色设置为透明 ), - child: TabBar( - controller: _tabController, - tabs: [ - for (var i in SearchType.values) Tab(text: i.label), - ], - isScrollable: true, - indicatorWeight: 0, - indicatorPadding: - const EdgeInsets.symmetric(horizontal: 3, vertical: 8), - indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: const BorderRadius.all(Radius.circular(20)), - ), - indicatorSize: TabBarIndicatorSize.tab, - labelColor: Theme.of(context).colorScheme.onSecondaryContainer, - labelStyle: const TextStyle(fontSize: 13), - dividerColor: Colors.transparent, - unselectedLabelColor: Theme.of(context).colorScheme.outline, - tabAlignment: TabAlignment.start, - onTap: (index) { - if (index == _searchResultController!.tabIndex) { - Get.find( - tag: SearchType.values[index].type + - _searchResultController!.keyword!) - .animateToTop(); - } + child: Obx( + () => (TabBar( + controller: _tabController, + tabs: [ + for (var i in _searchResultController.searchTabs) + Tab(text: "${i['label']} ${i['count'] ?? ''}") + ], + isScrollable: true, + indicatorWeight: 0, + indicatorPadding: + const EdgeInsets.symmetric(horizontal: 3, vertical: 8), + indicator: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + indicatorSize: TabBarIndicatorSize.tab, + labelColor: + Theme.of(context).colorScheme.onSecondaryContainer, + labelStyle: const TextStyle(fontSize: 13), + dividerColor: Colors.transparent, + unselectedLabelColor: Theme.of(context).colorScheme.outline, + tabAlignment: TabAlignment.start, + onTap: (index) { + if (index == _searchResultController.tabIndex) { + Get.find( + tag: SearchType.values[index].type + + _searchResultController.keyword!) + .animateToTop(); + } - _searchResultController!.tabIndex = index; - }, + _searchResultController.tabIndex = index; + }, + )), ), ), ), @@ -102,7 +106,7 @@ class _SearchResultPageState extends State children: [ for (var i in SearchType.values) ...{ SearchPanel( - keyword: _searchResultController!.keyword, + keyword: _searchResultController.keyword, searchType: i, tag: DateTime.now().millisecondsSinceEpoch.toString(), ) From db824681fd6a8d9b53df047315e169c9df5f33df Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 5 May 2024 21:00:12 +0800 Subject: [PATCH 054/106] =?UTF-8?q?fix:=20=E9=80=80=E5=87=BA=E5=85=A8?= =?UTF-8?q?=E5=B1=8F=E6=8C=89=E9=92=AE=E6=97=A0=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugin/pl_player/view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 6a5f22ec..d359391e 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -334,7 +334,7 @@ class _PLVideoPlayerState extends State color: Colors.white, ), ), - fuc: () => _.triggerFullScreen(), + fuc: () => _.triggerFullScreen(status: !_.isFullScreen.value), ), }; final List list = []; From 0162b9614e278fabd83066f35823d259f28db733 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 6 May 2024 23:14:12 +0800 Subject: [PATCH 055/106] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E5=8C=BA?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/reply/widgets/reply_item.dart | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index ef4cd15c..b5972ed8 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -12,6 +12,7 @@ import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/reply_new/index.dart'; import 'package:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/url_utils.dart'; import 'package:pilipala/utils/utils.dart'; @@ -642,23 +643,25 @@ InlineSpan buildContent( '', ); } else { - final String redirectUrl = - await UrlUtils.parseRedirectUrl(matchStr); - if (redirectUrl == matchStr) { - Clipboard.setData(ClipboardData(text: matchStr)); - SmartDialog.showToast('地址可能有误'); - return; - } - final String pathSegment = Uri.parse(redirectUrl).path; - final String lastPathSegment = - pathSegment.split('/').last; - if (lastPathSegment.startsWith('BV')) { + final String pathSegment = Uri.parse(matchStr).path; + Map matchRes = IdUtils.matchAvorBv(input: pathSegment); + List matchKeys = matchRes.keys.toList(); + if (matchKeys.isNotEmpty) { UrlUtils.matchUrlPush( - lastPathSegment, + matchRes.containsKey('AV') + ? matchRes['AV']! as int + : matchRes['BV'], title, - redirectUrl, + matchStr, ); } else { + final String redirectUrl = + await UrlUtils.parseRedirectUrl(matchStr); + if (redirectUrl == matchStr) { + Clipboard.setData(ClipboardData(text: matchStr)); + SmartDialog.showToast('地址可能有误'); + return; + } Get.toNamed( '/webview', parameters: { From 2fefe325877f12bb99cbf29f0dcf9f334798b8de Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 6 May 2024 23:24:19 +0800 Subject: [PATCH 056/106] =?UTF-8?q?mod:=20=E9=BB=98=E8=AE=A4=E4=B8=8D?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=8D=87=E7=BA=A7=E6=A0=87=E8=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/about/index.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/about/index.dart b/lib/pages/about/index.dart index b381691a..81d3c3f4 100644 --- a/lib/pages/about/index.dart +++ b/lib/pages/about/index.dart @@ -218,7 +218,7 @@ class AboutController extends GetxController { RxString currentVersion = ''.obs; RxString remoteVersion = ''.obs; late LatestDataModel remoteAppInfo; - RxBool isUpdate = true.obs; + RxBool isUpdate = false.obs; RxBool isLoading = true.obs; late LatestDataModel data; From 4f10e6a869d1d61ea10343a00721d259a30572e7 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 7 May 2024 00:01:44 +0800 Subject: [PATCH 057/106] =?UTF-8?q?fix:=20=E5=8A=A8=E6=80=81=E6=9C=AA?= =?UTF-8?q?=E8=AF=BB=E6=A0=87=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/main/controller.dart | 2 +- lib/pages/main/view.dart | 64 +++++++++++++++++----------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index a77d9304..2ef2bf7f 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -40,10 +40,10 @@ class MainController extends GetxController { dynamicBadgeType.value = DynamicBadgeMode.values[setting.get( SettingBoxKey.dynamicBadgeMode, defaultValue: DynamicBadgeMode.number.code)]; + setNavBarConfig(); if (dynamicBadgeType.value != DynamicBadgeMode.hidden) { getUnreadDynamic(); } - setNavBarConfig(); } void onBackPressed(BuildContext context) { diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 617fcf83..29573501 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -138,14 +138,14 @@ class _MainAppState extends State with SingleTickerProviderStateMixin { duration: const Duration(milliseconds: 500), offset: Offset(0, snapshot.data ? 0 : 1), child: GlobalData().enableMYBar - ? NavigationBar( - onDestinationSelected: (value) => setIndex(value), - selectedIndex: _mainController.selectedIndex, - destinations: [ - ..._mainController.navigationBars.map((e) { - return NavigationDestination( - icon: Obx( - () => Badge( + ? Obx( + () => NavigationBar( + onDestinationSelected: (value) => setIndex(value), + selectedIndex: _mainController.selectedIndex, + destinations: [ + ..._mainController.navigationBars.map((e) { + return NavigationDestination( + icon: Badge( label: _mainController .dynamicBadgeType.value == DynamicBadgeMode.number @@ -159,25 +159,25 @@ class _MainAppState extends State with SingleTickerProviderStateMixin { e['count'] > 0, child: e['icon'], ), - ), - selectedIcon: e['selectIcon'], - label: e['label'], - ); - }).toList(), - ], + selectedIcon: e['selectIcon'], + label: e['label'], + ); + }).toList(), + ], + ), ) - : BottomNavigationBar( - currentIndex: _mainController.selectedIndex, - type: BottomNavigationBarType.fixed, - onTap: (value) => setIndex(value), - iconSize: 16, - selectedFontSize: 12, - unselectedFontSize: 12, - items: [ - ..._mainController.navigationBars.map((e) { - return BottomNavigationBarItem( - icon: Obx( - () => Badge( + : Obx( + () => BottomNavigationBar( + currentIndex: _mainController.selectedIndex, + type: BottomNavigationBarType.fixed, + onTap: (value) => setIndex(value), + iconSize: 16, + selectedFontSize: 12, + unselectedFontSize: 12, + items: [ + ..._mainController.navigationBars.map((e) { + return BottomNavigationBarItem( + icon: Badge( label: _mainController .dynamicBadgeType.value == DynamicBadgeMode.number @@ -191,12 +191,12 @@ class _MainAppState extends State with SingleTickerProviderStateMixin { e['count'] > 0, child: e['icon'], ), - ), - activeIcon: e['selectIcon'], - label: e['label'], - ); - }).toList(), - ], + activeIcon: e['selectIcon'], + label: e['label'], + ); + }).toList(), + ], + ), ), ); }, From 7ff6884342be8d0bd54feed50c8fd8f9c3410717 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 7 May 2024 23:10:27 +0800 Subject: [PATCH 058/106] =?UTF-8?q?fix:=20pathSegments=E8=B6=8A=E7=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/webview/controller.dart | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/pages/webview/controller.dart b/lib/pages/webview/controller.dart index f26f4284..40f84ff6 100644 --- a/lib/pages/webview/controller.dart +++ b/lib/pages/webview/controller.dart @@ -52,15 +52,19 @@ class WebviewController extends GetxController { loadProgress.value = progress; }, onPageStarted: (String url) { - final String str = Uri.parse(url).pathSegments[0]; - final Map matchRes = IdUtils.matchAvorBv(input: str); - final List matchKeys = matchRes.keys.toList(); - if (matchKeys.isNotEmpty) { - if (matchKeys.first == 'BV') { - Get.offAndToNamed( - '/searchResult', - parameters: {'keyword': matchRes['BV']}, - ); + final List pathSegments = Uri.parse(url).pathSegments; + if (pathSegments.isNotEmpty && + url != 'https://passport.bilibili.com/h5-app/passport/login') { + final String str = pathSegments[0]; + final Map matchRes = IdUtils.matchAvorBv(input: str); + final List matchKeys = matchRes.keys.toList(); + if (matchKeys.isNotEmpty) { + if (matchKeys.first == 'BV') { + Get.offAndToNamed( + '/searchResult', + parameters: {'keyword': matchRes['BV']}, + ); + } } } }, From c2a176ad2fd5d20e4ad4aed1f68102b5425b45c2 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 7 May 2024 23:53:31 +0800 Subject: [PATCH 059/106] fix: issues #718 --- lib/services/audio_handler.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index b0ca8cd7..bf98298b 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -26,7 +26,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { static final List _item = []; Box setting = GStrorage.setting; bool enableBackgroundPlay = false; - PlPlayerController player = PlPlayerController.getInstance(videoType: 'none'); + PlPlayerController player = PlPlayerController.getInstance(); VideoPlayerServiceHandler() { revalidateSetting(); From 250131d2b0925fef686eb4634657bd80eab085bb Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 8 May 2024 22:42:18 +0800 Subject: [PATCH 060/106] =?UTF-8?q?fix:=20=E5=88=86p=E5=AD=97=E5=B9=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/introduction/controller.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 2ced79f0..9ed04870 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -450,6 +450,7 @@ class VideoIntroController extends GetxController { videoDetailCtr.danmakuCid.value = cid; videoDetailCtr.cover.value = cover; videoDetailCtr.queryVideoUrl(); + videoDetailCtr.getSubtitle(); // 重新请求评论 try { /// 未渲染回复组件时可能异常 From 6380c138e8f0e2c85f6ae73b8b24deccd6d78b33 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 8 May 2024 23:19:02 +0800 Subject: [PATCH 061/106] =?UTF-8?q?typo:=20=E5=8E=86=E5=8F=B2=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/interceptor.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/http/interceptor.dart b/lib/http/interceptor.dart index a5359283..10b5aee5 100644 --- a/lib/http/interceptor.dart +++ b/lib/http/interceptor.dart @@ -46,7 +46,7 @@ class ApiInterceptor extends Interceptor { // 处理网络请求错误 // handler.next(err); String url = err.requestOptions.uri.toString(); - if (!url.contains('heartBeat')) { + if (!url.contains('heartbeat')) { SmartDialog.showToast( await dioError(err), displayType: SmartToastType.onlyRefresh, From 5807999296c0806309e3dd809c068764147ee9be Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 8 May 2024 23:19:29 +0800 Subject: [PATCH 062/106] =?UTF-8?q?mod:=20scheme=20BVAV=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/app_scheme.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index fff78b39..8502dc7f 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -4,7 +4,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/utils/route_push.dart'; import '../http/search.dart'; -import '../models/common/search_type.dart'; import 'id_utils.dart'; import 'url_utils.dart'; import 'utils.dart'; @@ -140,11 +139,13 @@ class PiliSchame { print('bilibili.com path: $path'); final String lastPathSegment = path!.split('/').last; if (path.startsWith('/video')) { - if (lastPathSegment.contains('BV')) { - _videoPush(null, lastPathSegment); - } - if (lastPathSegment.contains('av')) { - _videoPush(Utils.matchNum(lastPathSegment)[0], null); + Map matchRes = IdUtils.matchAvorBv(input: path); + if (matchRes.containsKey('AV')) { + _videoPush(matchRes['AV']! as int, null); + } else if (matchRes.containsKey('BV')) { + _videoPush(null, matchRes['BV'] as String); + } else { + SmartDialog.showToast('投稿匹配失败'); } } if (path.startsWith('/bangumi')) { From 37654c5eab465672eba646855431eba229ed7f2e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 9 May 2024 00:00:59 +0800 Subject: [PATCH 063/106] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E5=8C=BA?= =?UTF-8?q?=E9=93=BE=E6=8E=A5=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/widgets/reply_item.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index b5972ed8..4ff13065 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -657,11 +657,11 @@ InlineSpan buildContent( } else { final String redirectUrl = await UrlUtils.parseRedirectUrl(matchStr); - if (redirectUrl == matchStr) { - Clipboard.setData(ClipboardData(text: matchStr)); - SmartDialog.showToast('地址可能有误'); - return; - } + // if (redirectUrl == matchStr) { + // Clipboard.setData(ClipboardData(text: matchStr)); + // SmartDialog.showToast('地址可能有误'); + // return; + // } Get.toNamed( '/webview', parameters: { From b8e3764345aaf66e2cbad0c73f8d5d2ce2e1f8d0 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 10 May 2024 23:45:51 +0800 Subject: [PATCH 064/106] fix: login Box has already been closed --- lib/pages/webview/controller.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/pages/webview/controller.dart b/lib/pages/webview/controller.dart index 40f84ff6..bdacc652 100644 --- a/lib/pages/webview/controller.dart +++ b/lib/pages/webview/controller.dart @@ -110,6 +110,9 @@ class WebviewController extends GetxController { SmartDialog.showToast('登录成功'); try { Box userInfoCache = GStrorage.userInfo; + if (!userInfoCache.isOpen) { + userInfoCache = await Hive.openBox('userInfo'); + } await userInfoCache.put('userInfoCache', result['data']); final HomeController homeCtr = Get.find(); From 14b7ac438f25d97711a70301eb5ded8ad455da5a Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 11 May 2024 23:50:41 +0800 Subject: [PATCH 065/106] =?UTF-8?q?fix:=20=E7=9B=B4=E6=92=AD=E5=85=A8?= =?UTF-8?q?=E5=B1=8F=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/live_room/widgets/bottom_control.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index e5a9d6c9..4dd7c538 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -153,7 +153,8 @@ class _BottomControlState extends State { size: 20, color: Colors.white, ), - fuc: () => widget.controller!.triggerFullScreen(), + fuc: () => widget.controller!.triggerFullScreen( + status: !(widget.controller!.isFullScreen.value)), ), ], ), From 79bde1b7ff03158a36d18fd8885bc3fa080fd3b2 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 13 May 2024 23:16:25 +0800 Subject: [PATCH 066/106] =?UTF-8?q?mod:=20=E5=8E=86=E5=8F=B2=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E9=95=BF=E6=8C=89=E5=9C=86=E8=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/history/widgets/item.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index ba5f6b5c..00ebd511 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -198,7 +198,8 @@ class HistoryItem extends StatelessWidget { duration: const Duration(milliseconds: 200), child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular( + StyleString.imgRadius.x), color: Colors.black.withOpacity( ctr!.enableMultiple.value && videoItem.checked From 68d35a7ed8830c4b352389dd59c4aa60d335ac34 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 13 May 2024 23:37:22 +0800 Subject: [PATCH 067/106] =?UTF-8?q?feat:=20=E6=90=9C=E7=B4=A2=E5=88=86?= =?UTF-8?q?=E5=8C=BAUI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 2 +- lib/http/search.dart | 2 + lib/pages/search/widgets/search_text.dart | 7 +- lib/pages/search_panel/controller.dart | 14 +- .../search_panel/widgets/video_panel.dart | 125 +++++++++++++++++- 5 files changed, 142 insertions(+), 8 deletions(-) diff --git a/lib/http/api.dart b/lib/http/api.dart index 42fc03b8..77c168d0 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -189,7 +189,7 @@ class Api { 'https://s.search.bilibili.com/main/suggest'; // 分类搜索 - static const String searchByType = '/x/web-interface/search/type'; + static const String searchByType = '/x/web-interface/wbi/search/type'; // 记录视频播放进度 // https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/video/report.md diff --git a/lib/http/search.dart b/lib/http/search.dart index 9b493a84..70980547 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -75,6 +75,7 @@ class SearchHttp { required page, String? order, int? duration, + int? tid, }) async { var reqData = { 'search_type': searchType.type, @@ -84,6 +85,7 @@ class SearchHttp { 'page': page, if (order != null) 'order': order, if (duration != null) 'duration': duration, + if (tid != null) 'tid': tid, }; var res = await Request().get(Api.searchByType, data: reqData); if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) { diff --git a/lib/pages/search/widgets/search_text.dart b/lib/pages/search/widgets/search_text.dart index 039a851b..5e91a4cd 100644 --- a/lib/pages/search/widgets/search_text.dart +++ b/lib/pages/search/widgets/search_text.dart @@ -5,12 +5,14 @@ class SearchText extends StatelessWidget { final Function? onSelect; final int? searchTextIdx; final Function? onLongSelect; + final bool isSelect; const SearchText({ super.key, this.searchText, this.onSelect, this.searchTextIdx, this.onLongSelect, + this.isSelect = false, }); @override @@ -34,7 +36,10 @@ class SearchText extends StatelessWidget { child: Text( searchText!, style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant), + color: isSelect + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.onSurfaceVariant, + ), ), ), ), diff --git a/lib/pages/search_panel/controller.dart b/lib/pages/search_panel/controller.dart index 85952e90..56d83601 100644 --- a/lib/pages/search_panel/controller.dart +++ b/lib/pages/search_panel/controller.dart @@ -16,14 +16,18 @@ class SearchPanelController extends GetxController { RxString order = ''.obs; // 视频时长筛选 仅用于搜索视频 RxInt duration = 0.obs; + // 视频分区筛选 仅用于搜索视频 + RxInt tid = (-1).obs; Future onSearch({type = 'init'}) async { var result = await SearchHttp.searchByType( - searchType: searchType!, - keyword: keyword!, - page: page.value, - order: searchType!.type != 'video' ? null : order.value, - duration: searchType!.type != 'video' ? null : duration.value); + searchType: searchType!, + keyword: keyword!, + page: page.value, + order: searchType!.type != 'video' ? null : order.value, + duration: searchType!.type != 'video' ? null : duration.value, + tid: searchType!.type != 'video' ? null : tid.value, + ); if (result['status']) { if (type == 'onRefresh') { resultList.value = result['data'].list; diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index c24a007c..06ee5d4b 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -3,6 +3,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; import 'package:pilipala/models/common/search_type.dart'; +import 'package:pilipala/pages/search/widgets/search_text.dart'; import 'package:pilipala/pages/search_panel/index.dart'; class SearchVideoPanel extends StatelessWidget { @@ -94,7 +95,7 @@ class SearchVideoPanel extends StatelessWidget { style: ButtonStyle( padding: MaterialStateProperty.all(EdgeInsets.zero), ), - onPressed: () => controller.onShowFilterDialog(ctr), + onPressed: () => controller.onShowFilterSheet(ctr), icon: Icon( Icons.filter_list_outlined, size: 18, @@ -165,7 +166,33 @@ class VideoPanelController extends GetxController { {'label': '30-60分钟', 'value': 3}, {'label': '60分钟+', 'value': 4}, ]; + List> partFiltersList = [ + {'label': '全部', 'value': -1}, + {'label': '动画', 'value': 1}, + {'label': '番剧', 'value': 13}, + {'label': '国创', 'value': 167}, + {'label': '音乐', 'value': 3}, + {'label': '舞蹈', 'value': 129}, + {'label': '游戏', 'value': 4}, + {'label': '知识', 'value': 36}, + {'label': '科技', 'value': 188}, + {'label': '运动', 'value': 234}, + {'label': '汽车', 'value': 223}, + {'label': '生活', 'value': 160}, + {'label': '美食', 'value': 211}, + {'label': '动物', 'value': 217}, + {'label': '鬼畜', 'value': 119}, + {'label': '时尚', 'value': 155}, + {'label': '资讯', 'value': 202}, + {'label': '娱乐', 'value': 5}, + {'label': '影视', 'value': 181}, + {'label': '记录', 'value': 177}, + {'label': '电影', 'value': 23}, + {'label': '电视', 'value': 11}, + ]; + RxInt currentTimeFilterval = 0.obs; + RxInt currentPartFilterval = (-1).obs; @override void onInit() { @@ -219,4 +246,100 @@ class VideoPanelController extends GetxController { }, ); } + + onShowFilterSheet(searchPanelCtr) { + showModalBottomSheet( + context: Get.context!, + builder: (context) { + return StatefulBuilder( + builder: (context, StateSetter setState) { + return Container( + color: Theme.of(Get.context!).colorScheme.surface, + padding: const EdgeInsets.only(top: 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ListTile( + title: Text('内容时长'), + ), + Padding( + padding: const EdgeInsets.only( + left: 14, + right: 14, + bottom: 14, + ), + child: Wrap( + spacing: 10, + runSpacing: 10, + direction: Axis.horizontal, + textDirection: TextDirection.ltr, + children: [ + for (var i in timeFiltersList) + Obx( + () => SearchText( + searchText: i['label'], + searchTextIdx: i['value'], + isSelect: + currentTimeFilterval.value == i['value'], + onSelect: (value) async { + currentTimeFilterval.value = i['value']; + setState(() {}); + SmartDialog.showToast("「${i['label']}」的筛选结果"); + SearchPanelController ctr = + Get.find( + tag: 'video${searchPanelCtr.keyword!}'); + ctr.duration.value = i['value']; + Get.back(); + SmartDialog.showLoading(msg: '获取中'); + await ctr.onRefresh(); + SmartDialog.dismiss(); + }, + onLongSelect: (value) => {}, + ), + ) + ], + ), + ), + const ListTile( + title: Text('内容分区'), + ), + Padding( + padding: const EdgeInsets.only(left: 14, right: 14), + child: Wrap( + spacing: 10, + runSpacing: 10, + direction: Axis.horizontal, + textDirection: TextDirection.ltr, + children: [ + for (var i in partFiltersList) + SearchText( + searchText: i['label'], + searchTextIdx: i['value'], + isSelect: currentPartFilterval.value == i['value'], + onSelect: (value) async { + currentPartFilterval.value = i['value']; + setState(() {}); + SmartDialog.showToast("「${i['label']}」的筛选结果"); + SearchPanelController ctr = + Get.find( + tag: 'video${searchPanelCtr.keyword!}'); + ctr.tid.value = i['value']; + Get.back(); + SmartDialog.showLoading(msg: '获取中'); + await ctr.onRefresh(); + SmartDialog.dismiss(); + }, + onLongSelect: (value) => {}, + ) + ], + ), + ) + ], + ), + ); + }, + ); + }, + ); + } } From 31e8ee8d34023b6d541088836432eba556123853 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 13 May 2024 23:55:17 +0800 Subject: [PATCH 068/106] =?UTF-8?q?fix:=20=E7=95=AA=E5=89=A7=E6=97=A0?= =?UTF-8?q?=E8=AF=84=E5=88=86=E5=AF=BC=E8=87=B4=E7=9A=84=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/bangumi/introduction/view.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index 6876da79..95d4d898 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -194,7 +194,8 @@ class _BangumiInfoState extends State { src: widget.bangumiDetail!.cover!, ), PBadge( - text: '评分 ${widget.bangumiDetail!.rating!['score']!}', + text: + '评分 ${widget.bangumiDetail?.rating?['score']! ?? '暂无'}', top: null, right: 6, bottom: 6, From 44f2a168ce79b62c315f5706152240c3396a1562 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 15 May 2024 23:55:04 +0800 Subject: [PATCH 069/106] =?UTF-8?q?opt:=20=E6=92=AD=E6=94=BE=E5=99=A8?= =?UTF-8?q?=E5=8D=95=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/live_room/controller.dart | 3 +-- lib/pages/video/detail/controller.dart | 2 +- lib/plugin/pl_player/controller.dart | 19 +++++++++---------- lib/plugin/pl_player/view.dart | 10 +++++----- lib/services/audio_handler.dart | 2 +- lib/services/audio_session.dart | 4 ++-- lib/services/shutdown_timer_service.dart | 4 ++-- 7 files changed, 21 insertions(+), 23 deletions(-) diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 5c2a9800..4e67fa2c 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -17,8 +17,7 @@ class LiveRoomController extends GetxController { double volume = 0.0; // 静音状态 RxBool volumeOff = false.obs; - PlPlayerController plPlayerController = - PlPlayerController.getInstance(videoType: 'live'); + PlPlayerController plPlayerController = PlPlayerController(videoType: 'live'); Rx roomInfoH5 = RoomInfoH5Model().obs; late bool enableCDN; late int currentQn; diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index f7f9e848..722af317 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -74,7 +74,7 @@ class VideoDetailController extends GetxController final scaffoldKey = GlobalKey(); RxString bgCover = ''.obs; RxString cover = ''.obs; - PlPlayerController plPlayerController = PlPlayerController.getInstance(); + PlPlayerController plPlayerController = PlPlayerController(); late VideoItem firstVideo; late AudioItem firstAudio; diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 93d67703..03c2efbe 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -123,6 +123,7 @@ class PlPlayerController { PreferredSizeWidget? bottomControl; Widget? danmuWidget; late RxList subtitles; + String videoType = 'archive'; /// 数据加载监听 Stream get onDataStatusChanged => dataStatus.status.stream; @@ -220,7 +221,7 @@ class PlPlayerController { Rx get playerCount => _playerCount; /// - Rx get videoType => _videoType; + // Rx get videoType => _videoType; /// 弹幕开关 Rx isOpenDanmu = false.obs; @@ -274,8 +275,7 @@ class PlPlayerController { } // 添加一个私有构造函数 - PlPlayerController._() { - _videoType = videoType; + PlPlayerController._internal(this.videoType) { isOpenDanmu.value = setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: false); blockTypes = @@ -330,11 +330,11 @@ class PlPlayerController { } // 获取实例 传参 - static PlPlayerController getInstance({ + factory PlPlayerController({ String videoType = 'archive', }) { // 如果实例尚未创建,则创建一个新实例 - _instance ??= PlPlayerController._(); + _instance ??= PlPlayerController._internal(videoType); if (videoType != 'none') { _instance!._playerCount.value += 1; _videoType.value = videoType; @@ -443,7 +443,7 @@ class PlPlayerController { configuration: PlayerConfiguration( // 默认缓存 5M 大小 bufferSize: - videoType.value == 'live' ? 32 * 1024 * 1024 : 5 * 1024 * 1024, + videoType == 'live' ? 32 * 1024 * 1024 : 5 * 1024 * 1024, ), ); @@ -541,7 +541,7 @@ class PlPlayerController { } /// 设置倍速 - if (videoType.value == 'live') { + if (videoType == 'live') { await setPlaybackSpeed(1.0); } else { if (_playbackSpeed.value != 1.0) { @@ -933,7 +933,7 @@ class PlPlayerController { /// 设置长按倍速状态 live模式下禁用 void setDoubleSpeedStatus(bool val) { - if (videoType.value == 'live') { + if (videoType == 'live') { return; } if (controlsLock.value) { @@ -1015,7 +1015,7 @@ class PlPlayerController { if (!_enableHeart) { return false; } - if (videoType.value == 'live') { + if (videoType == 'live') { return; } // 播放状态变化时,更新 @@ -1114,7 +1114,6 @@ class PlPlayerController { // _buffered.close(); // _showControls.close(); // _controlsLock.close(); - // playerStatus.status.close(); // dataStatus.status.close(); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index d359391e..cff4611a 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -652,7 +652,7 @@ class _PLVideoPlayerState extends State }, onDoubleTapDown: (TapDownDetails details) { // live模式下禁用 锁定时🔒禁用 - if (_.videoType.value == 'live' || _.controlsLock.value) { + if (_.videoType == 'live' || _.controlsLock.value) { return; } final double totalWidth = MediaQuery.sizeOf(context).width; @@ -679,7 +679,7 @@ class _PLVideoPlayerState extends State /// 水平位置 快进 live模式下禁用 onHorizontalDragUpdate: (DragUpdateDetails details) { // live模式下禁用 锁定时🔒禁用 - if (_.videoType.value == 'live' || _.controlsLock.value) { + if (_.videoType == 'live' || _.controlsLock.value) { return; } // final double tapPosition = details.localPosition.dx; @@ -695,7 +695,7 @@ class _PLVideoPlayerState extends State _.onChangedSliderStart(); }, onHorizontalDragEnd: (DragEndDetails details) { - if (_.videoType.value == 'live' || _.controlsLock.value) { + if (_.videoType == 'live' || _.controlsLock.value) { return; } _.onChangedSliderEnd(); @@ -826,7 +826,7 @@ class _PLVideoPlayerState extends State return const SizedBox(); } - if (_.videoType.value == 'live') { + if (_.videoType == 'live') { return const SizedBox(); } if (value > max || max <= 0) { @@ -879,7 +879,7 @@ class _PLVideoPlayerState extends State // 锁 Obx( () => Visibility( - visible: _.videoType.value != 'live' && _.isFullScreen.value, + visible: _.videoType != 'live' && _.isFullScreen.value, child: Align( alignment: Alignment.centerLeft, child: FractionalTranslation( diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index bf98298b..853c58d0 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -26,7 +26,7 @@ class VideoPlayerServiceHandler extends BaseAudioHandler with SeekHandler { static final List _item = []; Box setting = GStrorage.setting; bool enableBackgroundPlay = false; - PlPlayerController player = PlPlayerController.getInstance(); + PlPlayerController player = PlPlayerController(); VideoPlayerServiceHandler() { revalidateSetting(); diff --git a/lib/services/audio_session.dart b/lib/services/audio_session.dart index 53b497ae..d1d2a466 100644 --- a/lib/services/audio_session.dart +++ b/lib/services/audio_session.dart @@ -18,7 +18,7 @@ class AudioSessionHandler { session.configure(const AudioSessionConfiguration.music()); session.interruptionEventStream.listen((event) { - final player = PlPlayerController.getInstance(videoType: 'none'); + final player = PlPlayerController(videoType: 'none'); if (event.begin) { if (!player.playerStatus.playing) return; switch (event.type) { @@ -51,7 +51,7 @@ class AudioSessionHandler { // 耳机拔出暂停 session.becomingNoisyEventStream.listen((_) { - final player = PlPlayerController.getInstance(videoType: 'none'); + final player = PlPlayerController(videoType: 'none'); if (player.playerStatus.playing) { player.pause(); } diff --git a/lib/services/shutdown_timer_service.dart b/lib/services/shutdown_timer_service.dart index 156b63c8..06993f62 100644 --- a/lib/services/shutdown_timer_service.dart +++ b/lib/services/shutdown_timer_service.dart @@ -89,7 +89,7 @@ class ShutdownTimerService { return; } PlPlayerController plPlayerController = - PlPlayerController.getInstance(videoType: 'none'); + PlPlayerController(videoType: 'none'); if (!exitApp && !waitForPlayingCompleted) { if (!plPlayerController.playerStatus.playing) { //仅提示用户 @@ -124,7 +124,7 @@ class ShutdownTimerService { } else { //暂停播放 PlPlayerController plPlayerController = - PlPlayerController.getInstance(videoType: 'none'); + PlPlayerController(videoType: 'none'); if (plPlayerController.playerStatus.playing) { plPlayerController.pause(); waitForPlayingCompleted = true; From f23a21f6dce39cffc0fb2879a321d3f3b514ba05 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 16 May 2024 23:04:47 +0800 Subject: [PATCH 070/106] =?UTF-8?q?feat:=20=E5=8A=A8=E6=80=81=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/dynamics/result.dart | 3 + lib/pages/dynamics/widgets/forward_panel.dart | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart index bc7105d1..64a6e5b1 100644 --- a/lib/models/dynamics/result.dart +++ b/lib/models/dynamics/result.dart @@ -415,6 +415,7 @@ class DynamicMajorModel { this.type, this.courses, this.common, + this.music, }); DynamicArchiveModel? archive; @@ -431,6 +432,7 @@ class DynamicMajorModel { String? type; Map? courses; Map? common; + Map? music; DynamicMajorModel.fromJson(Map json) { archive = json['archive'] != null @@ -455,6 +457,7 @@ class DynamicMajorModel { type = json['type']; courses = json['courses'] ?? {}; common = json['common'] ?? {}; + music = json['music'] ?? {}; } } diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index 76c7b24e..f8b90a81 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -238,6 +238,61 @@ Widget forWard(item, context, ctr, source, {floor = 1}) { ), ), ); + case 'DYNAMIC_TYPE_MUSIC': + final Map music = item.modules.moduleDynamic.major.music; + return Padding( + padding: const EdgeInsets.only(top: 8), + child: InkWell( + onTap: () { + Get.toNamed('/webview', parameters: { + 'url': "https:${music['jump_url']}", + 'type': 'url', + 'pageTitle': music['title'] + }); + }, + child: Container( + width: double.infinity, + padding: + const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10), + color: Theme.of(context).dividerColor.withOpacity(0.08), + child: Row( + children: [ + NetworkImgLayer( + width: 45, + height: 45, + src: music['cover'], + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + music['title'], + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + Text( + music['label'], + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ) + ], + ), + // TextButton(onPressed: () {}, child: Text('123')) + ), + ), + ); default: return const SizedBox( width: double.infinity, From eae39c480c9f99887695f1755fd6acb36f5720bc Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 18 May 2024 19:29:57 +0800 Subject: [PATCH 071/106] =?UTF-8?q?mod:=20playInit=20autoplay=20=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/controller.dart | 4 ++-- lib/pages/video/detail/view.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 722af317..38c62d7e 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -233,7 +233,7 @@ class VideoDetailController extends GetxController audio, seekToTime, duration, - bool autoplay = true, + bool? autoplay, }) async { /// 设置/恢复 屏幕亮度 if (brightness != null) { @@ -266,7 +266,7 @@ class VideoDetailController extends GetxController cid: cid.value, enableHeart: enableHeart, isFirstTime: isFirstTime, - autoplay: autoplay, + autoplay: autoplay ?? autoPlay.value, ); /// 开启自动全屏时,在player初始化完成后立即传入headerControl diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 2c35858f..6f751e52 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -176,7 +176,7 @@ class _VideoDetailPageState extends State /// 未开启自动播放时触发播放 Future handlePlay() async { - await vdCtr.playerInit(); + await vdCtr.playerInit(autoplay: true); plPlayerController = vdCtr.plPlayerController; plPlayerController!.addStatusLister(playerListener); vdCtr.autoPlay.value = true; @@ -266,7 +266,7 @@ class _VideoDetailPageState extends State } vdCtr.isFirstTime = false; final bool autoplay = autoPlayEnable; - vdCtr.playerInit(autoplay: autoplay); + vdCtr.playerInit(); /// 未开启自动播放时,未播放跳转下一页返回/播放后跳转下一页返回 vdCtr.autoPlay.value = !vdCtr.isShowCover.value; From cb7cd0a2f0658ca84d48b213760aee80decff555 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 19 May 2024 19:57:13 +0800 Subject: [PATCH 072/106] feat: videoDetail menu edit --- assets/images/coin.png | Bin 0 -> 7159 bytes lib/models/common/action_type.dart | 94 ++++++++++++++++ lib/pages/setting/pages/action_menu_set.dart | 100 ++++++++++++++++++ lib/pages/setting/style_setting.dart | 5 + lib/pages/video/detail/introduction/view.dart | 28 ++--- .../introduction/widgets/action_item.dart | 54 ++++++---- lib/router/app_pages.dart | 4 + lib/utils/storage.dart | 3 +- 8 files changed, 249 insertions(+), 39 deletions(-) create mode 100644 assets/images/coin.png create mode 100644 lib/models/common/action_type.dart create mode 100644 lib/pages/setting/pages/action_menu_set.dart diff --git a/assets/images/coin.png b/assets/images/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..bc2952a7a5cf519a331b83c0f268eef88769d471 GIT binary patch literal 7159 zcmai3XEa<vI?2oo<*AX$uJ|9 zbE)c;5wTPqLBNLDXyI`F_$sdFW^)=nesPzJh7-d7Tk-$I#4N)}`MRL7DXk^Ce63JJ z$@|x~Dt)%t|F(sSB|<)Jwbk{iJW~8(_(!4PBksrHCfo7KN9jac37>Zv1N(QM&AyBK zr6Q{qIyv=nqi|5paxTn8tu9Ps`T@6=^q%B)@V@A&uz#M=&%bz?S5^*F<32*K3>Lq3 zVXCYAgH*bFr5u6k<-WPOe*5v6)S&0*WP^jaVU`j396F&bw*nD7yp@`KZ zf_Bfei3C%9{_H8dcljj8=IFOlR=nC(1>f%J2`k5Joj9#YKV0weokY&;Ba0H6&ZavJ z-`kJUtqiVj-R64NcxCU+tIcgOuD!4d!s@}{U5PNqxU%EJs~0&lomZ&`ck18=J=A); zb?~oe*?p-K*30XWEGdh}g@sRLjkpq!)vYGro@xZx9t*R_g`PET$k5@)GQTZ9J^Ip3 zhi=jp_$_R~_P|jrsiCnAy?(ms>v?kAYr%H%_Zc&~C#(w6&{!%z0lH5u2k{X5QrdV? z>xSUJRZ<+M1Tb_)0bVO6@f26cL}69`JOaG|*3rf&If+G(*Y-T_=f3;wHgy@fWS)E& zHluGHXednEwVc-1VNG-0^Lk9BHQQqGkTFM?w(8#C9bi$K>jVvL?rb^II?Ez=s94`P z|DpD2@$y-3KQj|!lYV#<|FExhgWWbZY_vAw`%md~ed)g9;CYj2=Oa~3!(Ri{A-X8v zpx$XkRN%?|H7(bPeTDT$U2Rn5Pt08M4%Dr=hUddQ3bO}vgt~_!e--cCO+GX`r6@mF z4)W?sy!%7r`bKCnc77>HZbRWXU4Qf!i{94oamm_O@#VKk*x?6i_IbSE{(qqL@pX>6g6tMuMySM63bXjKKQW`zugF43{dpMj=NYW(uw%8RJ+=#W zI?~pKSmdm9yVR-Bt?)~To7;!c|EzB$#BF(@wND79z8upagtno+y&?wL1Om$oC)Mkz?W>meIH|OtG$Eu09UW5x;^+{3Pb=)_j+O07=RCt<= zvDJ3?+-3010YS=Mw`{sCT}H(Vj8IsLVh$DT(sSUnyxOSFSSV_e;wcryI^ye~*LfKWB*0r%2$vcM19va@SGLQVv5rKjb7b-dKIVwZtba{LV?Nauw z4~NDSM}5AC{0d;OV4IsBZW5tZ;O)rno#Li7l~M2ob00O-f|9b_@h@czYKS^W*^iiF z8Esz>@pwWp6&sLaJH&b$=P@Q_@`O+0$9gxKdvw2I16+{7=P&FjN*)+bsfk0h^`^>Y$s z1Jl{Rze6gqdDR;=?7fNt1SYa`L%)B^8jU_a>8lF|`!Pxs@J@1uy!=`;zD(PFYkhQm zhqhbq(~@455`m}W;==ln7oTFf1hALu97-*24?!-b8%C-e2;|NQ_$GFB(7W9kU59@N z)6IT0UUMUwXIY{111C|1&)!n|fcE;n)ld*K>*r#LNCb zNDed2a>}ny*$^chgGqo-gJcIKPu7@TPaB?3sSNzuW`>pPiJa;N)ml43RU@x~Hp$PD<*cS3_SGnAH+P{(iOgzWiuelm zy;)VB^g6EwzBe=8r-$}bJ#h>aWW=$aC%E=(R+|mAJJx?}+2nS&yHE|}r}<_O$y7J4+{c!?hJv;GL$Qx-qLBx5v2?txK2h=+ z#IJ9zS)3%_ZJg0of3vwC)xJ?KRVM)R#<{Bf{4r!98A36E&b~=zN8rh9apQ~mfI4Q& zl9EWHY{TE+aQnRZ(ZYtnlilpbM`D~A4WP5JcJ8<{ngMj24hFJ2N!k0C=cAl0K_eTZ zt8|s*nLV>nHyCjHRFUN@+2|^Xsh8`ja9RhsWa#$(OkM0^OMr3Y;K>6dp&Ht75<@Zu z!i%bN`?*JQ>S830vo~#l&QomI(bRIh+cRbQtH7p$vyzgKBnH%0<3Uf&ad9=e!JCdq z3GoodNF`M%Vg$Llzj0}f4?8ZoS{E893BBNrRYj*bm2z1af$&Yz8ZC2_;QFcc`ApgfE@m_6@j3NSowGS>vcBjyf(feK zguOKg%X=Epv;?eJ+yLx6jm>F-Z|6@5{qjzVj^P>QWv%w?sg#7s6!o6mOL9(b0!`1eQFzt7 z{wCnv&gTR~k6phrGQZ$|4P~nvHPiM!DZ~n_A z4>-!;5yStQTKT3*2Kz~0@txrO*UwltY>P7MX&8gB&2Mv=Hi}hpSgS2nMz!YE`f5Ef z{To&zQPW?zohc;Mu)k6;!g$Kb=dAW1yDb~x4;J!$>T4B-g1L<;8z3Gtz~?ZVwo}`` z=ZR*?Qcv>#U{5ZNoB%Q-6uz2$(=haqpperZP%$u8q0qYzlW+dzeMb5Y7yMbAqHDPV z(B&ZfhXSTXKyp*q95nLy;jE|on>S!zy+fOTNawa$7Y>dMfN84C=(Sq_a%JpNs?7K` zirCMB2yi#NhlHr9!=s0!G-)VgFvhdPgvzLtSD?9(#7 znZYH~qFt1M0SiOU-+rLWm4ie#d<9N|E^=bIWoiab4f_7G_PYrz?5(ra+nNWJai!Kc z3aAA~oIkx_?jG~w{0cA(e4zp1eZV@bu|{J=jG4VOfemZCpr|~y(d)%EkFFp$ZlJ*z zoLsvDr!_gZTSohkQ^p57p>ok9&S$YJ&5y|noJ*tq%AeBFvt6sx#r{cN`tjxMZ*B}V z{_5IGl{Fr$+g(bV$EEZyw^fc$uNf-4KfC9~T(opPy!jgNsMDM6eRCdt$MBo+Lwm(6 ziUmXZY%ch<kP$X5Z#1YG)4EL>;v@HohmWj$TvEO`G}z} zYVkwBeo&MYQ2CQ&A=sgbW-$xE#U&$-Z@>PagwI9ia<@<66W-Ac(9Vwddl_R5h!CBc zG3K{kL(FVG?M8#RxCzhOZWWJJ04VgU`hks8Ysy(&VTKk<4&!z~2Y_BQSX~)E1!xDw zjZhS5iqhhNJa9`oI76`NxlhZBOVLv^26!eH;Xb15DkKN2{*^+x6nt@)5w3)i&RHwt zQboiRTkG>>88hLm&*R^zDW)<%LjjT^#IZmUj4A#$wo7v>s@Dt)x+uDf{hLTspnLvV6%+(ehY}w; zmDXjAH9@v_To}8w#qmpTPoIYf&1}4u>wMgSLK%m!^H6Hvqp>?#&;ipCmB69~I= zP@-4DjsyVY4qWP|N}u$C6Pa zyr3P!P383j*$5`MBdZ8j*h!B!{YKGMTkJI?Nr;+j0dNJVw(v2(QWOtGChlmb^a6lg zC*Vy`187H|qcuIw&&>zKib3?2@B4d=I3f|tE=TS#Lb6{FoXnnV8(!p+{|LB5$;Az{ z2A+ikYYI^lb@B4v0??(6Z)6L!Nz#a(@Wm~_d`BeR`P(5|EYG6-v%-`dpfFoZx|R)= zhuTCF&VuQe4f!WSUSJRO1L?LT@x~wn`^b_8B1pf-g^J8Y=6W3qP?Ix+MF#y5GYXVs zzKgYC?AM?$J5&V5U}?^{KJMlrn%Mf;XlVM-kfb*+_j1mf#LdW(1kI9glLva(V}Ras zF{)ERm`uhjH$m8G=je1&Wr!^4y>g`>nKHEF2GZ3)d-^%Q6Cjra<`%`BR@x6yDmBy{ zHxkQrZYkWy{uxyWN-Ck&iKNU~( zWp)o*2#?mOWTYj1%yvQZY>#qXKaek|QheO(^CysR0;xjTK}l3c){!iQu@FM}trG|C zqY5YrCR2^jqeeTmTMjzX|*d>wip!(kJ z!p}ZGWEgbn^dT6EXIQ{dF&V4f$)GFc1>o6F*#N?qI-mq9NVB>2W%IJvD((_Ov>zC; zu{ehOwMC3t{exWrr>uB6A3XckT-Ko<(By@ar-Nz~l#rN2z7VMueFfhr{wL{>qc8VT za4)%7;@3;z(18rs?VL0QEcpD3zelnAO%41*Jxptp02w{oQt!yIhddsb>ZGuGBcG;& zCe_KaJv4fb1KcqwV3SW|970g^gl~qV3WF7Ipei19>cs%90ZzXU1|?=Vpp*nBPwXgP8yQTOq*RrTP3P>%daQQbea)PLeks}Xrr+6LA*Ka(u5c}R5qmD52lqO8pTp!r6U29u7)!;n}G=UUpKi0-g@d0#GkcZcR&@3mbP6tml39i)NU^5%gvTlEWZ)^j?U!1zv=LD z!cwU^j(5y)=1!4??g7o-RxJ@awi=BZ4I`dZMR1?u?4Yfu((sKL{p)@z`uM8nN^5c^K%u4`D8*BuHq@?_UtvzAyTb`C1qB-=ha`Nx9t3_oxpo6^h1 zLM2H4wb#om6&YhU*B0U$ZCn{SJPNu9LdmLBv_B-54aox;Io4ZZr9HA#Llq594)q}s z+cQB$`Ze5Z{@TNP4~)m;&mmcs2b5Y(vE&1i%W@XGUhgHH_fpNnD!&_Ng!Rvttj~Ri zNGcPl#OH#pRBRk(9sH(aeY|t8Fn{1(j_%`RG1ESs!f+A&cf!ONSwps)>!a zVZ*@Vw=oUde@rIMA9m=!>^7h6(R}C;9$^*&KBeOG^$(0(%Gjin-dU9vwE021SmV3A z3pQF;IZ#Oc!*hWuKZ1EpRWFD{=m*1t#}vz7#veSv>qt)Ccay~l3?j}M_W^Sb> zanl})m_^+3yBa@tnNLoh!B$qRt9@J-uDM^O)Yw_e5fK!-#Hhf<4~$C1tYDZ+VR*j2 z{AXn_JknafKU@GSfFq;bO$J00#NCOj=YfX{vw@|#%eclfp=l9mVYiTjtw?C3fz@>` z64MaIIvWz}K}O^ZXYc3Z0QPjEN28^=OFvS~3bHRx_2$Opi5)U+-2V1_n7e#)<_Bm& zPx&(X!U8W>knt#XH`GULXw_N{>k=#HTX{r7$qnCfh zx#>2(>CSNv;(8i+@0HuB6L)}((vj_K;ACWkoW_Gkca-~j4<3I0x4&E;JFSuX-cPN1 zPTh(Ela&}+8UF9VvIY8T5A@WKUU-)00i*sUX0gY_>-?{$-IJLMSGW$I2ivT{Oio1U z9K+mo%PCIl%UPt$X72CNc{zD~9%J>anzm~xLt4ovwS|KGIL&hCdKI7CUGl6pHbbD{R_;~c|h%se}} zrD8#cvGbkY-XL9k?27}j;imls*~h=d@@E$;iY=ulsFvNxE(CR+#E=Z4$~mA#@or`07naUm?|czbR&_QxkoW|i^+tLG?WF2;EYGN+Xu zq{gQryB(ta#Js$)LG(M@QD^CaMY$*DJ?*4ZBwR+z1Jj!7e9TGb-_M0z8I+;Gv^lR? z)8teeQF2KBc46zCd*)gEhIaC%ql<(yDSIs+^?_Cn;Kf;qd{u&}$2A5?Bs==_6Q>lD z{wGM17^~LvGEx5({$?LdGm?b%>LS}?NmC1#2Asc6Xn(J@63(7#_mS#17$zM&d#6xK zRZYf(wPmrB);c{Isu~g(iD{%>353^R*Ho(LUkQ;?-yx zwd~$Igjqu3uA7dwQG^J?w=jk!&+A2roChWuZy(m~Q(KKkC8DPWUb}`eKP5Kkiu(Ac ztUt)act5wB=+d~|3OuN7HtL$%QB0$rT6|^H@07(_lJNDBf7^$r+dNc$%~nDcwuQAx zsqVpgo+C)J1?jgwX)jscx&ElNw3f?%S@~`1<8Xo56>eiau0M1B+ZQO?|Gpn1&hT(C l{=<}~mvg`V-P`>?i}iJ^lzFK-(e&S({%sST25l$Qe*pGzPR;-T literal 0 HcmV?d00001 diff --git a/lib/models/common/action_type.dart b/lib/models/common/action_type.dart new file mode 100644 index 00000000..2284df6c --- /dev/null +++ b/lib/models/common/action_type.dart @@ -0,0 +1,94 @@ +// 操作类型的枚举值:点赞 不喜欢 收藏 投币 稍后再看 下载封面 后台播放 听视频 分享 下载视频 +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +enum ActionType { + like, + coin, + collect, + watchLater, + share, + dislike, + downloadCover, + copyLink, + threeAction, + // backgroundPlay, + // listenVideo, + // downloadVideo, +} + +extension ActionTypeExtension on ActionType { + String get value => [ + 'like', + 'coin', + 'collect', + 'watchLater', + 'share', + 'dislike', + 'downloadCover', + 'copyLink', + // 'backgroundPlay', + // 'listenVideo', + // 'downloadVideo', + ][index]; + String get label => [ + '点赞视频', + '投币', + '收藏视频', + '稍后再看', + '视频分享', + '不喜欢', + '下载封面', + '复制链接', + // '后台播放', + // '听视频', + // '下载视频', + ][index]; +} + +List actionMenuConfig = [ + { + 'icon': const Icon(Icons.thumb_up_alt_outlined), + 'label': '点赞视频', + 'value': ActionType.like, + }, + { + 'icon': Image.asset( + 'assets/images/coin.png', + width: 26, + color: IconTheme.of(Get.context!).color!.withOpacity(0.65), + ), + 'label': '投币', + 'value': ActionType.coin, + }, + { + 'icon': const Icon(Icons.star_border), + 'label': '收藏视频', + 'value': ActionType.collect, + }, + { + 'icon': const Icon(Icons.watch_later_outlined), + 'label': '稍后再看', + 'value': ActionType.watchLater, + }, + { + 'icon': const Icon(Icons.share), + 'label': '视频分享', + 'value': ActionType.share, + }, + { + 'icon': const Icon(Icons.thumb_down_alt_outlined), + 'label': '不喜欢', + 'value': ActionType.dislike, + }, + { + 'icon': const Icon(Icons.image_outlined), + 'label': '下载封面', + 'value': ActionType.downloadCover, + }, + { + 'icon': const Icon(Icons.link_outlined), + 'label': '复制链接', + 'value': ActionType.copyLink, + }, +]; diff --git a/lib/pages/setting/pages/action_menu_set.dart b/lib/pages/setting/pages/action_menu_set.dart new file mode 100644 index 00000000..f7d92e17 --- /dev/null +++ b/lib/pages/setting/pages/action_menu_set.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/models/common/action_type.dart'; +import '../../../utils/storage.dart'; + +class ActionMenuSetPage extends StatefulWidget { + const ActionMenuSetPage({super.key}); + + @override + State createState() => _ActionMenuSetPageState(); +} + +class _ActionMenuSetPageState extends State { + Box settingStorage = GStrorage.setting; + late List actionTypeSort; + late List allLabels; + + @override + void initState() { + super.initState(); + actionTypeSort = settingStorage.get(SettingBoxKey.actionTypeSort, + defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); + allLabels = actionMenuConfig; + allLabels.sort((a, b) { + int indexA = actionTypeSort.indexOf((a['value'] as ActionType).value); + int indexB = actionTypeSort.indexOf((b['value'] as ActionType).value); + if (indexA == -1) indexA = actionTypeSort.length; + if (indexB == -1) indexB = actionTypeSort.length; + return indexA.compareTo(indexB); + }); + } + + void saveEdit() { + List sortedTabbar = allLabels + .where((i) => actionTypeSort.contains((i['value'] as ActionType).value)) + .map((i) => (i['value'] as ActionType).value) + .toList(); + settingStorage.put(SettingBoxKey.actionTypeSort, sortedTabbar); + SmartDialog.showToast('保存成功,下次启动时生效'); + } + + void onReorder(int oldIndex, int newIndex) { + setState(() { + if (newIndex > oldIndex) { + newIndex -= 1; + } + final tabsItem = allLabels.removeAt(oldIndex); + allLabels.insert(newIndex, tabsItem); + }); + } + + @override + Widget build(BuildContext context) { + final listTiles = [ + for (int i = 0; i < allLabels.length; i++) ...[ + CheckboxListTile( + key: Key((allLabels[i]['value'] as ActionType).value), + value: actionTypeSort + .contains((allLabels[i]['value'] as ActionType).value), + onChanged: (bool? newValue) { + String actionTypeId = (allLabels[i]['value'] as ActionType).value; + if (!newValue!) { + actionTypeSort.remove(actionTypeId); + } else { + actionTypeSort.add(actionTypeId); + } + setState(() {}); + }, + title: Row( + children: [ + allLabels[i]['icon'], + const SizedBox(width: 8), + Text(allLabels[i]['label']), + ], + ), + secondary: const Icon(Icons.drag_indicator_rounded), + ) + ] + ]; + + return Scaffold( + appBar: AppBar( + title: const Text('视频操作菜单'), + actions: [ + TextButton(onPressed: () => saveEdit(), child: const Text('保存')), + const SizedBox(width: 12) + ], + ), + body: ReorderableListView( + onReorder: onReorder, + physics: const NeverScrollableScrollPhysics(), + footer: SizedBox( + height: MediaQuery.of(context).padding.bottom + 30, + ), + children: listTiles, + ), + ); + } +} diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 364eabf0..20fdada0 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -289,6 +289,11 @@ class _StyleSettingState extends State { onTap: () => Get.toNamed('/navbarSetting'), title: Text('底部导航栏设置', style: titleStyle), ), + ListTile( + dense: false, + onTap: () => Get.toNamed('/actionMenuSet'), + title: Text('操作菜单设置', style: titleStyle), + ), if (Platform.isAndroid) ListTile( dense: false, diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 9103c130..dab81f18 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,7 +1,6 @@ import 'package:expandable/expandable.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; @@ -539,26 +538,21 @@ class _VideoInfoState extends State with TickerProviderStateMixin { builder: (BuildContext context, BoxConstraints constraints) { return Container( margin: const EdgeInsets.only(top: 6, bottom: 4), - height: constraints.maxWidth / 5 * 0.8, - child: GridView.count( - physics: const NeverScrollableScrollPhysics(), - primary: false, - padding: EdgeInsets.zero, - crossAxisCount: 5, - childAspectRatio: 1.25, - children: [ + height: constraints.maxWidth / 5, + child: ListView( + scrollDirection: Axis.horizontal, + children: [ Obx( () => ActionItem( - icon: const Icon(FontAwesomeIcons.thumbsUp), - selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), + icon: const Icon(Icons.thumb_up_alt_outlined), + selectIcon: const Icon(Icons.thumb_up), onTap: handleState(videoIntroController.actionLikeVideo), selectStatus: videoIntroController.hasLike.value, text: widget.videoDetail!.stat!.like!.toString()), ), Obx( () => ActionItem( - icon: const Icon(FontAwesomeIcons.b), - selectIcon: const Icon(FontAwesomeIcons.b), + icon: Image.asset('assets/images/coin.png', width: 30), onTap: handleState(videoIntroController.actionCoinVideo), selectStatus: videoIntroController.hasCoin.value, text: widget.videoDetail!.stat!.coin!.toString(), @@ -566,8 +560,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), Obx( () => ActionItem( - icon: const Icon(FontAwesomeIcons.star), - selectIcon: const Icon(FontAwesomeIcons.solidStar), + icon: const Icon(Icons.star_border), + selectIcon: const Icon(Icons.star), onTap: () => showFavBottomSheet(), onLongPress: () => showFavBottomSheet(type: 'longPress'), selectStatus: videoIntroController.hasFav.value, @@ -575,7 +569,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), ), ActionItem( - icon: const Icon(FontAwesomeIcons.clock), + icon: const Icon(Icons.watch_later_outlined), onTap: () async { final res = await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid); @@ -585,7 +579,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { text: '稍后看', ), ActionItem( - icon: const Icon(FontAwesomeIcons.shareFromSquare), + icon: const Icon(Icons.share), onTap: () => videoIntroController.actionShareVideo(), selectStatus: false, text: '分享', diff --git a/lib/pages/video/detail/introduction/widgets/action_item.dart b/lib/pages/video/detail/introduction/widgets/action_item.dart index 022d9223..2a89afe7 100644 --- a/lib/pages/video/detail/introduction/widgets/action_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_item.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:pilipala/common/constants.dart'; import 'package:pilipala/utils/feed_back.dart'; class ActionItem extends StatelessWidget { - final Icon? icon; + final dynamic icon; final Icon? selectIcon; final Function? onTap; final Function? onLongPress; @@ -31,26 +32,37 @@ class ActionItem extends StatelessWidget { if (onLongPress != null) {onLongPress!()} }, borderRadius: StyleString.mdRadius, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 4), - selectStatus - ? Icon(selectIcon!.icon!, - size: 18, color: Theme.of(context).colorScheme.primary) - : Icon(icon!.icon!, - size: 18, color: Theme.of(context).colorScheme.outline), - const SizedBox(height: 6), - Text( - text ?? '', - style: TextStyle( - color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, - ), - ) - ], + child: SizedBox( + width: (Get.size.width - 24) / 5, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 4), + icon is Icon + ? Icon( + selectStatus ? selectIcon!.icon ?? icon!.icon : icon!.icon, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ) + : Image.asset( + 'assets/images/coin.png', + width: 25, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ), + const SizedBox(height: 6), + Text( + text ?? '', + style: TextStyle( + color: + selectStatus ? Theme.of(context).colorScheme.primary : null, + fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, + ), + ) + ], + ), ), ); } diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 7fda1bd8..2ca333f8 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -35,6 +35,7 @@ import '../pages/search/index.dart'; import '../pages/search_result/index.dart'; import '../pages/setting/extra_setting.dart'; import '../pages/setting/index.dart'; +import '../pages/setting/pages/action_menu_set.dart'; import '../pages/setting/pages/color_select.dart'; import '../pages/setting/pages/display_mode.dart'; import '../pages/setting/pages/font_size_select.dart'; @@ -174,6 +175,9 @@ class Routes { // navigation bar CustomGetPage( name: '/navbarSetting', page: () => const NavigationBarSetPage()), + // 操作菜单 + CustomGetPage( + name: '/actionMenuSet', page: () => const ActionMenuSetPage()), ]; } diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 29cf1846..4a163446 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -149,7 +149,8 @@ class SettingBoxKey { tabbarSort = 'tabbarSort', // 首页tabbar dynamicBadgeMode = 'dynamicBadgeMode', enableGradientBg = 'enableGradientBg', - navBarSort = 'navBarSort'; + navBarSort = 'navBarSort', + actionTypeSort = 'actionTypeSort'; } class LocalCacheKey { From ed28e98bbae2d38971ae2ae16c15871e2f8c5c84 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 20 May 2024 23:45:38 +0800 Subject: [PATCH 073/106] =?UTF-8?q?opt:=20=E6=8E=A8=E8=8D=90=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E6=8B=89=E9=BB=91=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/common/widgets/video_card_v.dart | 37 ++++++++++++++++++++++------ lib/http/video.dart | 10 ++++++-- lib/pages/rcmd/controller.dart | 7 ++++++ lib/pages/rcmd/view.dart | 1 + 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 7b56152f..14476cdf 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -20,11 +20,13 @@ import 'network_img_layer.dart'; class VideoCardV extends StatelessWidget { final dynamic videoItem; final int crossAxisCount; + final Function? blockUserCb; const VideoCardV({ Key? key, required this.videoItem, required this.crossAxisCount, + this.blockUserCb, }) : super(key: key); bool isStringNumeric(String str) { @@ -157,7 +159,11 @@ class VideoCardV extends StatelessWidget { ); }), ), - VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount) + VideoContent( + videoItem: videoItem, + crossAxisCount: crossAxisCount, + blockUserCb: blockUserCb, + ) ], ), ); @@ -167,9 +173,14 @@ class VideoCardV extends StatelessWidget { class VideoContent extends StatelessWidget { final dynamic videoItem; final int crossAxisCount; - const VideoContent( - {Key? key, required this.videoItem, required this.crossAxisCount}) - : super(key: key); + final Function? blockUserCb; + + const VideoContent({ + Key? key, + required this.videoItem, + required this.crossAxisCount, + this.blockUserCb, + }) : super(key: key); Widget _buildBadge(String text, String type, [double fs = 12]) { return PBadge( @@ -241,7 +252,10 @@ class VideoContent extends StatelessWidget { useRootNavigator: true, isScrollControlled: true, builder: (context) { - return MorePanel(videoItem: videoItem); + return MorePanel( + videoItem: videoItem, + blockUserCb: blockUserCb, + ); }, ); }, @@ -297,11 +311,17 @@ class VideoStat extends StatelessWidget { class MorePanel extends StatelessWidget { final dynamic videoItem; - const MorePanel({super.key, required this.videoItem}); + final Function? blockUserCb; + const MorePanel({ + super.key, + required this.videoItem, + this.blockUserCb, + }); Future menuActionHandler(String type) async { switch (type) { case 'block': + Get.back(); blockUser(); break; case 'watchLater': @@ -338,7 +358,10 @@ class MorePanel extends StatelessWidget { reSrc: 11, ); SmartDialog.dismiss(); - SmartDialog.showToast(res['msg'] ?? '成功'); + if (res['status']) { + blockUserCb?.call(videoItem.owner.mid); + } + SmartDialog.showToast(res['msg']); }, child: const Text('确认'), ) diff --git a/lib/http/video.dart b/lib/http/video.dart index bf5921d6..7c1d9ba6 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -387,9 +387,15 @@ class VideoHttp { 'csrf': await Request.getCsrf(), }); if (res.data['code'] == 0) { - return {'status': true, 'data': res.data['data']}; + if (act == 5) { + List blackMidsList = + setting.get(SettingBoxKey.blackMidsList, defaultValue: [-1]); + blackMidsList.add(mid); + setting.put(SettingBoxKey.blackMidsList, blackMidsList); + } + return {'status': true, 'data': res.data['data'], 'msg': '成功'}; } else { - return {'status': false, 'data': []}; + return {'status': false, 'data': [], 'msg': res.data['message']}; } } diff --git a/lib/pages/rcmd/controller.dart b/lib/pages/rcmd/controller.dart index 28ff055b..2d606b12 100644 --- a/lib/pages/rcmd/controller.dart +++ b/lib/pages/rcmd/controller.dart @@ -1,4 +1,5 @@ import 'package:flutter/cupertino.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/video.dart'; @@ -106,4 +107,10 @@ class RcmdController extends GetxController { duration: const Duration(milliseconds: 500), curve: Curves.easeInOut); } } + + void blockUserCb(mid) { + videoList.removeWhere((e) => e.owner.mid == mid); + videoList.refresh(); + SmartDialog.showToast('已移除相关视频'); + } } diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index 67567870..29a8d469 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -146,6 +146,7 @@ class _RcmdPageState extends State ? VideoCardV( videoItem: videoList[index], crossAxisCount: crossAxisCount, + blockUserCb: (mid) => ctr.blockUserCb(mid), ) : const VideoCardVSkeleton(); }, From 2dfd2d4dc16d42ffbf42d6ed9c112066c8177e2e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 23 May 2024 00:32:59 +0800 Subject: [PATCH 074/106] =?UTF-8?q?opt:=20=E8=A7=86=E9=A2=91=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=A0=8F=E5=AE=89=E5=85=A8=E5=8C=BA=E5=9F=9F=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugin/pl_player/view.dart | 46 +++++++++---------- lib/plugin/pl_player/widgets/app_bar_ani.dart | 4 ++ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index cff4611a..ff0888be 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -768,37 +768,33 @@ class _PLVideoPlayerState extends State ), // 头部、底部控制条 - SafeArea( - top: false, - bottom: false, - child: Obx( - () => Column( - children: [ - if (widget.headerControl != null || _.headerControl != null) - ClipRect( - child: AppBarAni( - controller: animationController, - visible: !_.controlsLock.value && _.showControls.value, - position: 'top', - child: widget.headerControl ?? _.headerControl!, - ), - ), - const Spacer(), + Obx( + () => Column( + children: [ + if (widget.headerControl != null || _.headerControl != null) ClipRect( child: AppBarAni( controller: animationController, visible: !_.controlsLock.value && _.showControls.value, - position: 'bottom', - child: widget.bottomControl ?? - BottomControl( - controller: widget.controller, - triggerFullScreen: _.triggerFullScreen, - buildBottomControl: buildBottomControl(), - ), + position: 'top', + child: widget.headerControl ?? _.headerControl!, ), ), - ], - ), + const Spacer(), + ClipRect( + child: AppBarAni( + controller: animationController, + visible: !_.controlsLock.value && _.showControls.value, + position: 'bottom', + child: widget.bottomControl ?? + BottomControl( + controller: widget.controller, + triggerFullScreen: _.triggerFullScreen, + buildBottomControl: buildBottomControl(), + ), + ), + ), + ], ), ), diff --git a/lib/plugin/pl_player/widgets/app_bar_ani.dart b/lib/plugin/pl_player/widgets/app_bar_ani.dart index 53eaad16..a1db5807 100644 --- a/lib/plugin/pl_player/widgets/app_bar_ani.dart +++ b/lib/plugin/pl_player/widgets/app_bar_ani.dart @@ -29,6 +29,10 @@ class AppBarAni extends StatelessWidget implements PreferredSizeWidget { curve: Curves.linear, )), child: Container( + padding: EdgeInsets.only( + left: MediaQuery.of(context).padding.left, + right: MediaQuery.of(context).padding.right, + ), decoration: BoxDecoration( gradient: position! == 'top' ? const LinearGradient( From c387cb83e7809c36456c85a82ccb1fa930d2a19f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 24 May 2024 23:54:25 +0800 Subject: [PATCH 075/106] =?UTF-8?q?mod:=20=E6=94=B6=E8=97=8F=E5=A4=B9?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/media/view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index 6541680a..cc413e59 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -105,7 +105,7 @@ class _MediaPageState extends State color: Theme.of(context).dividerColor.withOpacity(0.1), ), ListTile( - onTap: () {}, + onTap: () => Get.toNamed('/fav'), leading: null, dense: true, title: Padding( From 732beb38a71a20cb2980d3c40d473b4b64b68fd1 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 25 May 2024 15:31:00 +0800 Subject: [PATCH 076/106] =?UTF-8?q?opt:=20=E8=AF=84=E8=AE=BA=E5=8C=BA?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/reply/widgets/reply_item.dart | 41 ++++++------------- lib/utils/app_scheme.dart | 24 +++++++++-- 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 4ff13065..55c16f7d 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -1,3 +1,4 @@ +import 'package:appscheme/appscheme.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -11,6 +12,7 @@ import 'package:pilipala/models/video/reply/item.dart'; import 'package:pilipala/pages/preview/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/pages/video/detail/reply_new/index.dart'; +import 'package:pilipala/utils/app_scheme.dart'; import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/storage.dart'; @@ -643,34 +645,17 @@ InlineSpan buildContent( '', ); } else { - final String pathSegment = Uri.parse(matchStr).path; - Map matchRes = IdUtils.matchAvorBv(input: pathSegment); - List matchKeys = matchRes.keys.toList(); - if (matchKeys.isNotEmpty) { - UrlUtils.matchUrlPush( - matchRes.containsKey('AV') - ? matchRes['AV']! as int - : matchRes['BV'], - title, - matchStr, - ); - } else { - final String redirectUrl = - await UrlUtils.parseRedirectUrl(matchStr); - // if (redirectUrl == matchStr) { - // Clipboard.setData(ClipboardData(text: matchStr)); - // SmartDialog.showToast('地址可能有误'); - // return; - // } - Get.toNamed( - '/webview', - parameters: { - 'url': redirectUrl, - 'type': 'url', - 'pageTitle': title - }, - ); - } + Uri uri = Uri.parse(matchStr); + SchemeEntity scheme = SchemeEntity( + scheme: uri.scheme, + host: uri.host, + port: uri.port, + path: uri.path, + query: uri.queryParameters, + source: '', + dataString: matchStr, + ); + PiliSchame.fullPathPush(scheme); } } else { if (appUrlSchema.startsWith('bilibili://search')) { diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 8502dc7f..a83b7809 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -95,7 +95,7 @@ class PiliSchame { } } if (scheme == 'https') { - _fullPathPush(value); + fullPathPush(value); } } @@ -126,7 +126,7 @@ class PiliSchame { } } - static Future _fullPathPush(SchemeEntity value) async { + static Future fullPathPush(SchemeEntity value) async { // https://m.bilibili.com/bangumi/play/ss39708 // https | m.bilibili.com | /bangumi/play/ss39708 // final String scheme = value.scheme!; @@ -135,8 +135,6 @@ class PiliSchame { Map? query = value.query; RegExp regExp = RegExp(r'^((www\.)|(m\.))?bilibili\.com$'); if (regExp.hasMatch(host)) { - print('bilibili.com host: $host'); - print('bilibili.com path: $path'); final String lastPathSegment = path!.split('/').last; if (path.startsWith('/video')) { Map matchRes = IdUtils.matchAvorBv(input: path); @@ -236,6 +234,24 @@ class PiliSchame { print('个人空间'); Get.toNamed('/member?mid=$area', arguments: {'face': ''}); break; + default: + final Map map = + IdUtils.matchAvorBv(input: area.split('?').first); + if (map.containsKey('AV')) { + _videoPush(map['AV']! as int, null); + } else if (map.containsKey('BV')) { + _videoPush(null, map['BV'] as String); + } else { + Get.toNamed( + '/webview', + parameters: { + 'url': value.dataString ?? "", + 'type': 'url', + 'pageTitle': '' + }, + ); + } + break; } } } From 95685c4fdf04e8e0c725c7257755b641d7ca169f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 25 May 2024 16:16:23 +0800 Subject: [PATCH 077/106] =?UTF-8?q?mod:=20=E5=8E=86=E5=8F=B2=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E6=90=9C=E7=B4=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/history/widgets/item.dart | 2 +- lib/pages/history_search/controller.dart | 12 +- lib/pages/history_search/view.dart | 150 ++++++++--------------- 3 files changed, 59 insertions(+), 105 deletions(-) diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 00ebd511..baebfedb 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -244,7 +244,7 @@ class HistoryItem extends StatelessWidget { ), ), ), - videoItem.progress != 0 + videoItem.progress != 0 && videoItem.duration != 0 ? Positioned( left: 3, right: 3, diff --git a/lib/pages/history_search/controller.dart b/lib/pages/history_search/controller.dart index 90ac7a02..a6c79e6a 100644 --- a/lib/pages/history_search/controller.dart +++ b/lib/pages/history_search/controller.dart @@ -10,9 +10,8 @@ class HistorySearchController extends GetxController { final FocusNode searchFocusNode = FocusNode(); RxString searchKeyWord = ''.obs; String hintText = '搜索'; - RxString loadingStatus = 'init'.obs; + RxBool loadingStatus = false.obs; RxString loadingText = '加载中...'.obs; - bool hasRequest = false; late int mid; RxString uname = ''.obs; int pn = 1; @@ -36,8 +35,7 @@ class HistorySearchController extends GetxController { // 提交搜索内容 void submit() { - loadingStatus.value = 'loading'; - if (hasRequest) { + if (!loadingStatus.value) { pn = 1; searchHistories(); } @@ -48,6 +46,7 @@ class HistorySearchController extends GetxController { if (type == 'onLoad' && loadingText.value == '没有更多了') { return; } + loadingStatus.value = true; var res = await UserHttp.searchHistory( pn: pn, keyword: controller.value.text, @@ -63,9 +62,8 @@ class HistorySearchController extends GetxController { loadingText.value = '没有更多了'; } pn += 1; - hasRequest = true; } - loadingStatus.value = 'finish'; + loadingStatus.value = false; return res; } @@ -86,6 +84,6 @@ class HistorySearchController extends GetxController { historyList.removeWhere((e) => e.kid == kid); SmartDialog.showToast(res['msg']); } - loadingStatus.value = 'finish'; + // loadingStatus.value = fasle; } } diff --git a/lib/pages/history_search/view.dart b/lib/pages/history_search/view.dart index 5bde691d..f5bcae64 100644 --- a/lib/pages/history_search/view.dart +++ b/lib/pages/history_search/view.dart @@ -2,7 +2,6 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/skeleton/video_card_h.dart'; -import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/common/widgets/no_data.dart'; import 'package:pilipala/pages/history/widgets/item.dart'; @@ -16,20 +15,19 @@ class HistorySearchPage extends StatefulWidget { } class _HistorySearchPageState extends State { - final HistorySearchController _historySearchCtr = - Get.put(HistorySearchController()); + final HistorySearchController _hisCtr = Get.put(HistorySearchController()); late ScrollController scrollController; @override void initState() { super.initState(); - scrollController = _historySearchCtr.scrollController; + scrollController = _hisCtr.scrollController; scrollController.addListener( () { if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 300) { EasyThrottle.throttle('history', const Duration(seconds: 1), () { - _historySearchCtr.onLoad(); + _hisCtr.onLoad(); }); } }, @@ -50,19 +48,19 @@ class _HistorySearchPageState extends State { titleSpacing: 0, actions: [ IconButton( - onPressed: () => _historySearchCtr.submit(), + onPressed: () => _hisCtr.submit(), icon: const Icon(Icons.search_outlined, size: 22)), const SizedBox(width: 10) ], title: Obx( () => TextField( autofocus: true, - focusNode: _historySearchCtr.searchFocusNode, - controller: _historySearchCtr.controller.value, + focusNode: _hisCtr.searchFocusNode, + controller: _hisCtr.controller.value, textInputAction: TextInputAction.search, - onChanged: (value) => _historySearchCtr.onChange(value), + onChanged: (value) => _hisCtr.onChange(value), decoration: InputDecoration( - hintText: _historySearchCtr.hintText, + hintText: _hisCtr.hintText, border: InputBorder.none, suffixIcon: IconButton( icon: Icon( @@ -70,103 +68,61 @@ class _HistorySearchPageState extends State { size: 22, color: Theme.of(context).colorScheme.outline, ), - onPressed: () => _historySearchCtr.onClear(), + onPressed: () => _hisCtr.onClear(), ), ), - onSubmitted: (String value) => _historySearchCtr.submit(), + onSubmitted: (String value) => _hisCtr.submit(), ), ), ), body: Obx( - () => Column( - children: _historySearchCtr.loadingStatus.value == 'init' - ? [const SizedBox()] - : [ - Expanded( - child: FutureBuilder( - future: _historySearchCtr.searchHistories(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - Map data = snapshot.data as Map; - if (data['status']) { - return Obx( - () => _historySearchCtr.historyList.isNotEmpty - ? ListView.builder( - controller: scrollController, - itemCount: - _historySearchCtr.historyList.length + - 1, - itemBuilder: (context, index) { - if (index == - _historySearchCtr - .historyList.length) { - return Container( - height: MediaQuery.of(context) - .padding - .bottom + - 60, - padding: EdgeInsets.only( - bottom: MediaQuery.of(context) - .padding - .bottom), - child: Center( - child: Obx( - () => Text( - _historySearchCtr - .loadingText.value, - style: TextStyle( - color: Theme.of(context) - .colorScheme - .outline, - fontSize: 13), - ), - ), - ), - ); - } else { - return HistoryItem( - videoItem: _historySearchCtr - .historyList[index], - ctr: _historySearchCtr, - onChoose: null, - onUpdateMultiple: () => null, - ); - } - }, - ) - : _historySearchCtr.loadingStatus.value == - 'loading' - ? const SizedBox(child: Text('加载中...')) - : const CustomScrollView( - slivers: [ - NoData(), - ], - ), - ); - } else { - return CustomScrollView( - slivers: [ - HttpError( - errMsg: data['msg'], - fn: () => setState(() {}), - ) - ], - ); - } + () { + return _hisCtr.loadingStatus.value && _hisCtr.historyList.isEmpty + ? ListView.builder( + itemCount: 10, + itemBuilder: (context, index) { + return const VideoCardHSkeleton(); + }, + ) + : _hisCtr.historyList.isNotEmpty + ? ListView.builder( + controller: scrollController, + itemCount: _hisCtr.historyList.length + 1, + itemBuilder: (context, index) { + if (index == _hisCtr.historyList.length) { + return Container( + height: MediaQuery.of(context).padding.bottom + 60, + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).padding.bottom), + child: Center( + child: Obx( + () => Text( + _hisCtr.loadingText.value, + style: TextStyle( + color: + Theme.of(context).colorScheme.outline, + fontSize: 13, + ), + ), + ), + ), + ); } else { - // 骨架屏 - return ListView.builder( - itemCount: 10, - itemBuilder: (context, index) { - return const VideoCardHSkeleton(); - }, + return HistoryItem( + videoItem: _hisCtr.historyList[index], + ctr: _hisCtr, + onChoose: null, + onUpdateMultiple: () => null, ); } }, - ), - ), - ], - ), + ) + : const CustomScrollView( + slivers: [ + NoData(), + ], + ); + }, ), ); } From 1cefdb68b7692833acbe561865a8793af21294c0 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 25 May 2024 16:38:16 +0800 Subject: [PATCH 078/106] =?UTF-8?q?opt:=20=E9=AA=A8=E6=9E=B6=E5=B1=8F?= =?UTF-8?q?=E8=A1=A5=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/fav/view.dart | 8 +++++++- lib/pages/subscription/view.dart | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/pages/fav/view.dart b/lib/pages/fav/view.dart index b8d37f50..4f48213e 100644 --- a/lib/pages/fav/view.dart +++ b/lib/pages/fav/view.dart @@ -1,6 +1,7 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/pages/fav/index.dart'; import 'package:pilipala/pages/fav/widgets/item.dart'; @@ -93,7 +94,12 @@ class _FavPageState extends State { } } else { // 骨架屏 - return const Text('请求中'); + return ListView.builder( + itemBuilder: (context, index) { + return const VideoCardHSkeleton(); + }, + itemCount: 10, + ); } }, ), diff --git a/lib/pages/subscription/view.dart b/lib/pages/subscription/view.dart index 5e6e4664..bcc03cc3 100644 --- a/lib/pages/subscription/view.dart +++ b/lib/pages/subscription/view.dart @@ -1,6 +1,7 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:pilipala/common/skeleton/video_card_h.dart'; import 'package:pilipala/common/widgets/http_error.dart'; import 'package:pilipala/utils/route_push.dart'; import 'controller.dart'; @@ -87,7 +88,12 @@ class _SubPageState extends State { } } else { // 骨架屏 - return const Text('请求中'); + return ListView.builder( + itemBuilder: (context, index) { + return const VideoCardHSkeleton(); + }, + itemCount: 10, + ); } }, ), From d6e24096e0197e389122f463eaf31f075306272b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 26 May 2024 15:48:28 +0800 Subject: [PATCH 079/106] =?UTF-8?q?opt:=20=E8=A7=86=E9=A2=91=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E9=A1=B5Hero=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/view.dart | 167 +++++++++++++++---------------- 1 file changed, 78 insertions(+), 89 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 6f751e52..bf156c71 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -525,11 +525,10 @@ class _VideoDetailPageState extends State Scaffold( resizeToAvoidBottomInset: false, key: vdCtr.scaffoldKey, - backgroundColor: Colors.black, appBar: PreferredSize( preferredSize: const Size.fromHeight(0), child: AppBar( - backgroundColor: Colors.transparent, + backgroundColor: Colors.black, elevation: 0, ), ), @@ -559,8 +558,7 @@ class _VideoDetailPageState extends State } return SliverAppBar( automaticallyImplyLeading: false, - // 假装使用一个非空变量,避免Obx检测不到而罢工 - pinned: vdCtr.autoPlay.value, + pinned: true, elevation: 0, scrolledUnderElevation: 0, forceElevated: innerBoxIsScrolled, @@ -568,47 +566,42 @@ class _VideoDetailPageState extends State backgroundColor: Colors.black, flexibleSpace: FlexibleSpaceBar( background: PopScope( - canPop: plPlayerController?.isFullScreen.value != - true, - onPopInvoked: (bool didPop) { - if (plPlayerController?.isFullScreen.value == - true) { - plPlayerController! - .triggerFullScreen(status: false); - } - if (MediaQuery.of(context).orientation == - Orientation.landscape) { - verticalScreen(); - } - }, - child: LayoutBuilder( - builder: (BuildContext context, - BoxConstraints boxConstraints) { - return Stack( - children: [ - if (isShowing) - Padding( - padding: EdgeInsets.only(top: 0), - child: videoPlayerPanel, - ), + canPop: + plPlayerController?.isFullScreen.value != true, + onPopInvoked: (bool didPop) { + if (plPlayerController?.isFullScreen.value == + true) { + plPlayerController! + .triggerFullScreen(status: false); + } + if (MediaQuery.of(context).orientation == + Orientation.landscape) { + verticalScreen(); + } + }, + child: Hero( + tag: heroTag, + child: Stack( + children: [ + if (isShowing) videoPlayerPanel, - /// 关闭自动播放时 手动播放 - Obx( - () => Visibility( - visible: !vdCtr.autoPlay.value && - vdCtr.isShowCover.value, - child: Positioned( - top: 0, - left: 0, - right: 0, - child: handlePlayPanel(), - ), - ), + /// 关闭自动播放时 手动播放 + Obx( + () => Visibility( + visible: !vdCtr.autoPlay.value && + vdCtr.isShowCover.value, + child: Positioned( + top: 0, + left: 0, + right: 0, + child: handlePlayPanel(), ), - ], - ); - }, - )), + ), + ), + ], + ), + ), + ), ), ); }, @@ -627,55 +620,51 @@ class _VideoDetailPageState extends State : pinnedHeaderHeight; }, onlyOneScrollInBody: true, - body: ColoredBox( - key: Key(heroTag), - color: Theme.of(context).colorScheme.background, - child: Column( - children: [ - tabbarBuild(), - Expanded( - child: TabBarView( - controller: vdCtr.tabCtr, - children: [ - Builder( - builder: (BuildContext context) { - return CustomScrollView( - key: const PageStorageKey('简介'), - slivers: [ - if (vdCtr.videoType == SearchType.video) ...[ - VideoIntroPanel(bvid: vdCtr.bvid), - ] else if (vdCtr.videoType == - SearchType.media_bangumi) ...[ - Obx(() => BangumiIntroPanel( - cid: vdCtr.cid.value)), - ], - SliverToBoxAdapter( - child: Divider( - indent: 12, - endIndent: 12, - color: Theme.of(context) - .dividerColor - .withOpacity(0.06), - ), - ), - if (vdCtr.videoType == SearchType.video && - vdCtr.enableRelatedVideo) - const RelatedVideoPanel(), + body: Column( + children: [ + tabbarBuild(), + Expanded( + child: TabBarView( + controller: vdCtr.tabCtr, + children: [ + Builder( + builder: (BuildContext context) { + return CustomScrollView( + key: const PageStorageKey('简介'), + slivers: [ + if (vdCtr.videoType == SearchType.video) ...[ + VideoIntroPanel(bvid: vdCtr.bvid), + ] else if (vdCtr.videoType == + SearchType.media_bangumi) ...[ + Obx(() => + BangumiIntroPanel(cid: vdCtr.cid.value)), ], - ); - }, + SliverToBoxAdapter( + child: Divider( + indent: 12, + endIndent: 12, + color: Theme.of(context) + .dividerColor + .withOpacity(0.06), + ), + ), + if (vdCtr.videoType == SearchType.video && + vdCtr.enableRelatedVideo) + const RelatedVideoPanel(), + ], + ); + }, + ), + Obx( + () => VideoReplyPanel( + bvid: vdCtr.bvid, + oid: vdCtr.oid.value, ), - Obx( - () => VideoReplyPanel( - bvid: vdCtr.bvid, - oid: vdCtr.oid.value, - ), - ) - ], - ), + ) + ], ), - ], - ), + ), + ], ), ), ), From 5c0edf873b8c1e959041e563c0598bac8c8afa0f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 26 May 2024 16:26:39 +0800 Subject: [PATCH 080/106] =?UTF-8?q?fix:=20=E5=A4=96=E9=93=BE=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=20pic=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/url_utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/url_utils.dart b/lib/utils/url_utils.dart index 99886e09..573f9f9d 100644 --- a/lib/utils/url_utils.dart +++ b/lib/utils/url_utils.dart @@ -44,7 +44,7 @@ class UrlUtils { final String bv = matchRes['BV']; final Map res = await SearchHttp.ab2cWithPic(bvid: bv); final int cid = res['cid']; - final String pic = res['pic']; + final String? pic = res['pic']; final String heroTag = Utils.makeHeroTag(bv); await Get.toNamed( '/video?bvid=$bv&cid=$cid', From 63d5752d3e797f53b1db7c327952bc94ab9ca06d Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 26 May 2024 17:30:42 +0800 Subject: [PATCH 081/106] =?UTF-8?q?fix:=20=E8=BF=9E=E7=BB=AD=E5=BF=AB?= =?UTF-8?q?=E8=BF=9B=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugin/pl_player/view.dart | 4 ++-- lib/plugin/pl_player/widgets/backward_seek.dart | 7 +++++++ lib/plugin/pl_player/widgets/forward_seek.dart | 7 +++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index ff0888be..df68da2f 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -935,7 +935,7 @@ class _PLVideoPlayerState extends State begin: 0.0, end: _hideSeekBackwardButton.value ? 0.0 : 1.0, ), - duration: const Duration(milliseconds: 500), + duration: const Duration(milliseconds: 200), builder: (BuildContext context, double value, Widget? child) => Opacity( @@ -978,7 +978,7 @@ class _PLVideoPlayerState extends State begin: 0.0, end: _hideSeekForwardButton.value ? 0.0 : 1.0, ), - duration: const Duration(milliseconds: 500), + duration: const Duration(milliseconds: 200), builder: (BuildContext context, double value, Widget? child) => Opacity( diff --git a/lib/plugin/pl_player/widgets/backward_seek.dart b/lib/plugin/pl_player/widgets/backward_seek.dart index 35de0ae6..8fddf80a 100644 --- a/lib/plugin/pl_player/widgets/backward_seek.dart +++ b/lib/plugin/pl_player/widgets/backward_seek.dart @@ -20,6 +20,13 @@ class BackwardSeekIndicatorState extends State { Timer? timer; + @override + void setState(VoidCallback fn) { + if (mounted) { + super.setState(fn); + } + } + @override void initState() { super.initState(); diff --git a/lib/plugin/pl_player/widgets/forward_seek.dart b/lib/plugin/pl_player/widgets/forward_seek.dart index 43ddd322..7e3886ce 100644 --- a/lib/plugin/pl_player/widgets/forward_seek.dart +++ b/lib/plugin/pl_player/widgets/forward_seek.dart @@ -20,6 +20,13 @@ class ForwardSeekIndicatorState extends State { Timer? timer; + @override + void setState(VoidCallback fn) { + if (mounted) { + super.setState(fn); + } + } + @override void initState() { super.initState(); From 4aa47f4a7bd31cd3085f9200b692884685bb9b41 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 26 May 2024 23:18:37 +0800 Subject: [PATCH 082/106] =?UTF-8?q?fix:=20pip=E8=BF=9B=E5=85=A5=20?= =?UTF-8?q?=E8=AF=84=E8=AE=BA=E5=8C=BA=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/controller.dart | 2 -- lib/pages/video/detail/reply/view.dart | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index b718c840..c1929434 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -1,5 +1,4 @@ import 'package:easy_debounce/easy_throttle.dart'; -import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/http/reply.dart'; @@ -15,7 +14,6 @@ class VideoReplyController extends GetxController { this.rpid, this.replyLevel, ); - final ScrollController scrollController = ScrollController(); // 视频aid 请求时使用的oid int? aid; // 层级 2为楼中楼 diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 4c533647..653fe7e0 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -67,13 +67,12 @@ class _VideoReplyPanelState extends State vsync: this, duration: const Duration(milliseconds: 300)); _futureBuilderFuture = _videoReplyController.queryReplyList(); - + scrollController = ScrollController(); fabAnimationCtr.forward(); scrollListener(); } void scrollListener() { - scrollController = _videoReplyController.scrollController; scrollController.addListener( () { if (scrollController.position.pixels >= @@ -185,7 +184,8 @@ class _VideoReplyPanelState extends State builder: (BuildContext context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { var data = snapshot.data; - if (data['status']) { + if (_videoReplyController.replyList.isNotEmpty || + (data && data['status'])) { // 请求成功 return Obx( () => _videoReplyController.isLoadingMore && From 1c6047a3268ab1d01a4a0059912c2b5604aeb267 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 27 May 2024 23:54:33 +0800 Subject: [PATCH 083/106] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 470e9a35..228d17bb 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ QQ频道: https://pd.qq.com/s/365esodk3 - [x] 音质选择(视视频而定) - [x] 解码格式选择(视视频而定) - [x] 弹幕 - - [ ] 字幕 + - [x] 字幕 - [x] 记忆播放 - [x] 视频比例:高度/宽度适应、填充、包含等 From 6b4d24f59566ee12142408b9720809adc23cc86b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 28 May 2024 22:58:51 +0800 Subject: [PATCH 084/106] =?UTF-8?q?opt:=20=E5=8A=A8=E6=80=81=E9=A1=B5up?= =?UTF-8?q?=E4=B8=BB=E7=82=B9=E5=87=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/dynamics/widgets/up_panel.dart | 54 +++++++++++++----------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index fd0ae642..ee522cbb 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -1,3 +1,4 @@ +import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; @@ -30,6 +31,31 @@ class _UpPanelState extends State { liveList = widget.upData.liveList!; } + void onClickUp(data, i) { + currentMid = data.mid; + Get.find().mid.value = data.mid; + Get.find().upInfo.value = data; + Get.find().onSelectUp(data.mid); + int liveLen = liveList.length; + int upLen = upList.length; + double itemWidth = contentWidth + itemPadding.horizontal; + double screenWidth = MediaQuery.sizeOf(context).width; + double moveDistance = 0.0; + if (itemWidth * (upList.length + liveList.length) <= screenWidth) { + } else if ((upLen - i - 0.5) * itemWidth > screenWidth / 2) { + moveDistance = (i + liveLen + 0.5) * itemWidth + 46 - screenWidth / 2; + } else { + moveDistance = (upLen + liveLen) * itemWidth + 46 - screenWidth; + } + data.hasUpdate = false; + scrollController.animateTo( + moveDistance, + duration: const Duration(milliseconds: 200), + curve: Curves.linear, + ); + setState(() {}); + } + @override Widget build(BuildContext context) { listFormat(); @@ -120,30 +146,10 @@ class _UpPanelState extends State { onTap: () { feedBack(); if (data.type == 'up') { - currentMid = data.mid; - Get.find().mid.value = data.mid; - Get.find().upInfo.value = data; - Get.find().onSelectUp(data.mid); - int liveLen = liveList.length; - int upLen = upList.length; - double itemWidth = contentWidth + itemPadding.horizontal; - double screenWidth = MediaQuery.sizeOf(context).width; - double moveDistance = 0.0; - if (itemWidth * (upList.length + liveList.length) <= screenWidth) { - } else if ((upLen - i - 0.5) * itemWidth > screenWidth / 2) { - moveDistance = - (i + liveLen + 0.5) * itemWidth + 46 - screenWidth / 2; - } else { - moveDistance = (upLen + liveLen) * itemWidth + 46 - screenWidth; - } - data.hasUpdate = false; - scrollController.animateTo( - moveDistance, - duration: const Duration(milliseconds: 500), - curve: Curves.easeInOut, - ); - - setState(() {}); + EasyThrottle.throttle('follow', const Duration(milliseconds: 300), + () { + onClickUp(data, i); + }); } else if (data.type == 'live') { LiveItemModel liveItem = LiveItemModel.fromJson({ 'title': data.title, From eef9e3ae9eb3713a14b55fd04f0880132d623beb Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 30 May 2024 23:58:42 +0800 Subject: [PATCH 085/106] opt: loading Ani --- assets/loading.json | 1 + assets/trail_loading.json | 1 + lib/pages/video/detail/introduction/view.dart | 12 ++++++------ lib/plugin/pl_player/view.dart | 7 ++++--- pubspec.lock | 8 ++++++++ pubspec.yaml | 8 +++++--- 6 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 assets/loading.json create mode 100644 assets/trail_loading.json diff --git a/assets/loading.json b/assets/loading.json new file mode 100644 index 00000000..38bccbed --- /dev/null +++ b/assets/loading.json @@ -0,0 +1 @@ +{"v":"5.7.11","fr":60,"ip":0,"op":81,"w":1920,"h":1080,"nm":"Loading Dots","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Dot4","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":25,"s":[25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":39,"s":[100]},{"t":55,"s":[25]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[1142,540,0],"to":[0,-6.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":39,"s":[1142,500,0],"to":[0,0,0],"ti":[0,-6.667,0]},{"t":55,"s":[1142,540,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-284,92,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":25,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":39,"s":[75,75,100]},{"t":55,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[120,120],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.0039,0.6157,0.5686,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-284,92],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Dot3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":17,"s":[25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":31,"s":[100]},{"t":47,"s":[25]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":17,"s":[1022,540,0],"to":[0,-6.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":31,"s":[1022,500,0],"to":[0,0,0],"ti":[0,-6.667,0]},{"t":47,"s":[1022,540,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-284,92,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":17,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":31,"s":[75,75,100]},{"t":47,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[120,120],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.0039,0.6157,0.5686,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-284,92],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Dot2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9,"s":[25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":23,"s":[100]},{"t":39,"s":[25]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":9,"s":[902,540,0],"to":[0,-6.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":23,"s":[902,500,0],"to":[0,0,0],"ti":[0,0,0]},{"t":39,"s":[902,540,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-284,92,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":9,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":23,"s":[75,75,100]},{"t":39,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[120,120],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.0039,0.6157,0.5686,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-284,92],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":360,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Dot1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":14,"s":[100]},{"t":30,"s":[25]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[782,540,0],"to":[0,-6.667,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":14,"s":[782,500,0],"to":[0,0,0],"ti":[0,-6.667,0]},{"t":30,"s":[782,540,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-284,92,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":14,"s":[75,75,100]},{"t":30,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[120,120],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.0039,0.6157,0.5686,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-284,92],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":360,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/assets/trail_loading.json b/assets/trail_loading.json new file mode 100644 index 00000000..9fb39ea6 --- /dev/null +++ b/assets/trail_loading.json @@ -0,0 +1 @@ +{"v":"4.6.8","fr":60,"ip":0,"op":106,"w":500,"h":500,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 5","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":20,"s":[0],"e":[360]},{"t":110}]},"p":{"a":0,"k":[251,250,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[10,10]},"p":{"a":0,"k":[0,-100]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0,0.7294118,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":20,"op":620,"st":20,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 4","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":15,"s":[0],"e":[360]},{"t":105}]},"p":{"a":0,"k":[251,250,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20]},"p":{"a":0,"k":[0,-100]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0,0.7294118,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":15,"op":615,"st":15,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 3","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":10,"s":[0],"e":[360]},{"t":100}]},"p":{"a":0,"k":[251,250,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[30,30]},"p":{"a":0,"k":[0,-100]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0,0.7294118,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":10,"op":610,"st":10,"bm":0,"sr":1},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 2","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":5,"s":[0],"e":[360]},{"t":95}]},"p":{"a":0,"k":[251,250,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[40,40]},"p":{"a":0,"k":[0,-100]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0,0.7294118,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":5,"op":605,"st":5,"bm":0,"sr":1},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"n":["0p667_1_0p333_0"],"t":0,"s":[0],"e":[360]},{"t":90}]},"p":{"a":0,"k":[250,250,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":0,"s":[50,50],"e":[40,40]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"n":["0p667_1_0p333_0","0p667_1_0p333_0"],"t":84,"s":[40,40],"e":[50,50]},{"t":100}]},"p":{"a":0,"k":[0,-100]},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0,0.7294118,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":600,"st":0,"bm":0,"sr":1}]} \ No newline at end of file diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 9103c130..06a026aa 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -5,6 +5,7 @@ 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/widgets/http_error.dart'; import 'package:pilipala/pages/video/detail/index.dart'; @@ -97,11 +98,14 @@ class _VideoIntroPanelState extends State ); } } else { - return const SliverToBoxAdapter( + return SliverToBoxAdapter( child: SizedBox( height: 100, child: Center( - child: CircularProgressIndicator(), + child: Lottie.asset( + 'assets/loading.json', + width: 200, + ), ), ), ); @@ -595,8 +599,4 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ); }); } - - // Widget StaffPanel(BuildContext context, videoIntroController) { - // return - // } } diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index df68da2f..6508b624 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -7,6 +7,7 @@ import 'package:flutter_volume_controller/flutter_volume_controller.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; +import 'package:lottie/lottie.dart'; import 'package:media_kit/media_kit.dart'; import 'package:media_kit_video/media_kit_video.dart'; import 'package:pilipala/models/common/gesture_mode.dart'; @@ -909,9 +910,9 @@ class _PLVideoPlayerState extends State colors: [Colors.black26, Colors.transparent], ), ), - child: Image.asset( - 'assets/images/loading.gif', - height: 25, + child: Lottie.asset( + 'assets/loading.json', + width: 200, ), ), ); diff --git a/pubspec.lock b/pubspec.lock index 8f8a5cae..7ff7ef0d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -846,6 +846,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" + lottie: + dependency: "direct main" + description: + name: lottie + sha256: "6a24ade5d3d918c306bb1c21a6b9a04aab0489d51a2582522eea820b4093b62b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.2" mailer: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a269cd6f..10a0f065 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -146,6 +146,7 @@ dependencies: expandable: ^5.0.1 # 投屏 dlna_dart: ^0.0.8 + lottie: ^3.1.2 dev_dependencies: flutter_test: @@ -166,15 +167,15 @@ dev_dependencies: build_runner: ^2.4.8 dependency_overrides: - media_kit: + media_kit: git: url: https://github.com/media-kit/media-kit path: media_kit - media_kit_video: + media_kit_video: git: url: https://github.com/media-kit/media-kit path: media_kit_video - media_kit_libs_video: + media_kit_libs_video: git: url: https://github.com/media-kit/media-kit path: libs/universal/media_kit_libs_video @@ -205,6 +206,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: + - assets/ - assets/images/ - assets/images/lv/ - assets/images/logo/ From e1572c0962b43cf89fb32b02aeb6ceabdb63960f Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 31 May 2024 23:37:27 +0800 Subject: [PATCH 086/106] =?UTF-8?q?fix:=20=E9=94=81=E5=AE=9A=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E4=B8=8B=E9=81=BF=E5=85=8D=E6=89=8B=E5=8A=BF=E9=80=80?= =?UTF-8?q?=E5=87=BA=E5=85=A8=E5=B1=8F=20issues=20#753?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/plugin/pl_player/view.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index df68da2f..a695e752 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -733,14 +733,18 @@ class _PLVideoPlayerState extends State const double threshold = 7.0; // 滑动阈值 final bool flag = fullScreenGestureMode != FullScreenGestureMode.values.last; - if (dy > _distance.value && dy > threshold) { + if (dy > _distance.value && + dy > threshold && + !_.controlsLock.value) { if (_.isFullScreen.value ^ flag) { lastFullScreenToggleTime = DateTime.now(); // 下滑退出全屏 await widget.controller.triggerFullScreen(status: flag); } _distance.value = 0.0; - } else if (dy < _distance.value && dy < -threshold) { + } else if (dy < _distance.value && + dy < -threshold && + !_.controlsLock.value) { if (!_.isFullScreen.value ^ flag) { lastFullScreenToggleTime = DateTime.now(); // 上滑进入全屏 From 2358ba42e1867b1aa52c7278e10e2fe811455a33 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 1 Jun 2024 00:21:04 +0800 Subject: [PATCH 087/106] opt: pip issues #752 --- lib/pages/video/detail/view.dart | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index bf156c71..fa531684 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -99,7 +99,6 @@ class _VideoDetailPageState extends State fullScreenStatusListener(); if (Platform.isAndroid) { floating = vdCtr.floating!; - autoEnterPip(); } WidgetsBinding.instance.addObserver(this); lifecycleListener(); @@ -128,8 +127,9 @@ class _VideoDetailPageState extends State } // 播放器状态监听 - void playerListener(PlayerStatus? status) async { - playerStatus.value = status!; + void playerListener(PlayerStatus status) async { + playerStatus.value = status; + autoEnterPip(status: status); if (status == PlayerStatus.completed) { // 结束播放退出全屏 if (autoExitFullcreen) { @@ -181,6 +181,7 @@ class _VideoDetailPageState extends State plPlayerController!.addStatusLister(playerListener); vdCtr.autoPlay.value = true; vdCtr.isShowCover.value = false; + autoEnterPip(status: PlayerStatus.playing); } void fullScreenStatusListener() { @@ -287,10 +288,12 @@ class _VideoDetailPageState extends State .subscribe(this, ModalRoute.of(context)! as PageRoute); } - void autoEnterPip() { + void autoEnterPip({PlayerStatus? status}) { final String routePath = Get.currentRoute; if (autoPiP && routePath.startsWith('/video')) { - floating.toggleAutoPip(autoEnter: autoPiP); + floating.toggleAutoPip( + autoEnter: autoPiP && status == PlayerStatus.playing, + ); } } @@ -314,6 +317,15 @@ class _VideoDetailPageState extends State case 'show' || 'restart': plPlayerController?.danmakuController?.clear(); break; + case 'pause': + vdCtr.hiddenReplyReplyPanel(); + if (vdCtr.videoType == SearchType.video) { + videoIntroController.hiddenEpisodeBottomSheet(); + } + if (vdCtr.videoType == SearchType.media_bangumi) { + bangumiIntroController.hiddenEpisodeBottomSheet(); + } + break; } } From bde44af9a0afd283c247c6fac7bcd6eb740eb730 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 1 Jun 2024 22:43:27 +0800 Subject: [PATCH 088/106] opt: main.daat code --- lib/main.dart | 314 ++++++++++++++++++++++++++++---------------------- 1 file changed, 177 insertions(+), 137 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 066bb599..1a2ce989 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -23,7 +23,7 @@ import 'package:pilipala/utils/app_scheme.dart'; import 'package:pilipala/utils/data.dart'; import 'package:pilipala/utils/global_data.dart'; import 'package:pilipala/utils/storage.dart'; -import 'package:media_kit/media_kit.dart'; // Provides [Player], [Media], [Playlist] etc. +import 'package:media_kit/media_kit.dart'; import 'package:pilipala/utils/recommend_filter.dart'; import 'package:catcher_2/catcher_2.dart'; import './services/loggeer.dart'; @@ -31,59 +31,42 @@ import './services/loggeer.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); MediaKit.ensureInitialized(); - SystemChrome.setPreferredOrientations( - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]) - .then((_) async { - await GStrorage.init(); - await setupServiceLocator(); - clearLogs(); - Request(); - await Request.setCookie(); - RecommendFilter(); + await SystemChrome.setPreferredOrientations( + [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); + await GStrorage.init(); + await setupServiceLocator(); + clearLogs(); + Request(); + await Request.setCookie(); - // 异常捕获 logo记录 - final Catcher2Options debugConfig = Catcher2Options( - SilentReportMode(), - [ - FileHandler(await getLogsPath()), - ConsoleHandler( - enableDeviceParameters: false, - enableApplicationParameters: false, - ) - ], - ); + // 异常捕获 logo记录 + final Catcher2Options releaseConfig = Catcher2Options( + SilentReportMode(), + [FileHandler(await getLogsPath())], + ); - final Catcher2Options releaseConfig = Catcher2Options( - SilentReportMode(), - [FileHandler(await getLogsPath())], - ); + Catcher2( + releaseConfig: releaseConfig, + runAppFunction: () { + runApp(const MyApp()); + }, + ); - Catcher2( - debugConfig: debugConfig, - releaseConfig: releaseConfig, - runAppFunction: () { - runApp(const MyApp()); - }, - ); - - // 小白条、导航栏沉浸 - if (Platform.isAndroid) { - final androidInfo = await DeviceInfoPlugin().androidInfo; - if (androidInfo.version.sdkInt >= 29) { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - } - SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( - systemNavigationBarColor: Colors.transparent, - systemNavigationBarDividerColor: Colors.transparent, - statusBarColor: Colors.transparent, - )); + // 小白条、导航栏沉浸 + if (Platform.isAndroid) { + final androidInfo = await DeviceInfoPlugin().androidInfo; + if (androidInfo.version.sdkInt >= 29) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } + SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( + systemNavigationBarColor: Colors.transparent, + systemNavigationBarDividerColor: Colors.transparent, + statusBarColor: Colors.transparent, + )); + } - Data.init(); - GlobalData(); - PiliSchame.init(); - DisableBatteryOpt(); - }); + PiliSchame.init(); + DisableBatteryOpt(); } class MyApp extends StatelessWidget { @@ -124,6 +107,39 @@ class MyApp extends StatelessWidget { } catch (_) {} } + if (Platform.isAndroid) { + return AndroidApp( + brandColor: brandColor, + isDynamicColor: isDynamicColor, + currentThemeValue: currentThemeValue, + textScale: textScale, + ); + } else { + return OtherApp( + brandColor: brandColor, + currentThemeValue: currentThemeValue, + textScale: textScale, + ); + } + } +} + +class AndroidApp extends StatelessWidget { + const AndroidApp({ + super.key, + required this.brandColor, + required this.isDynamicColor, + required this.currentThemeValue, + required this.textScale, + }); + + final Color brandColor; + final bool isDynamicColor; + final ThemeType currentThemeValue; + final double textScale; + + @override + Widget build(BuildContext context) { return DynamicColorBuilder( builder: ((ColorScheme? lightDynamic, ColorScheme? darkDynamic) { ColorScheme? lightColorScheme; @@ -143,96 +159,120 @@ class MyApp extends StatelessWidget { brightness: Brightness.dark, ); } - - // ThemeData themeData = ThemeData( - // colorScheme: currentThemeValue == ThemeType.dark - // ? darkColorScheme - // : lightColorScheme, - // ); - - // // 小白条、导航栏沉浸 - // if (Platform.isAndroid) { - // List versionParts = Platform.version.split('.'); - // int androidVersion = int.parse(versionParts[0]); - // if (androidVersion >= 29) { - // SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - // } - // SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( - // systemNavigationBarColor: GlobalData().enableMYBar - // ? const Color(0x00010000) - // : themeData.canvasColor, - // systemNavigationBarDividerColor: GlobalData().enableMYBar - // ? const Color(0x00010000) - // : themeData.canvasColor, - // systemNavigationBarIconBrightness: - // currentThemeValue == ThemeType.dark - // ? Brightness.light - // : Brightness.dark, - // statusBarColor: Colors.transparent, - // )); - // } - - // 图片缓存 - // PaintingBinding.instance.imageCache.maximumSizeBytes = 1000 << 20; - return GetMaterialApp( - title: 'PiliPala', - theme: ThemeData( - colorScheme: currentThemeValue == ThemeType.dark - ? darkColorScheme - : lightColorScheme, - snackBarTheme: SnackBarThemeData( - actionTextColor: lightColorScheme.primary, - backgroundColor: lightColorScheme.secondaryContainer, - closeIconColor: lightColorScheme.secondary, - contentTextStyle: TextStyle(color: lightColorScheme.secondary), - elevation: 20, - ), - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: ZoomPageTransitionsBuilder( - allowEnterRouteSnapshotting: false, - ), - }, - ), - ), - darkTheme: ThemeData( - colorScheme: currentThemeValue == ThemeType.light - ? lightColorScheme - : darkColorScheme, - snackBarTheme: SnackBarThemeData( - actionTextColor: darkColorScheme.primary, - backgroundColor: darkColorScheme.secondaryContainer, - closeIconColor: darkColorScheme.secondary, - contentTextStyle: TextStyle(color: darkColorScheme.secondary), - elevation: 20, - ), - ), - localizationsDelegates: const [ - GlobalCupertinoLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - locale: const Locale("zh", "CN"), - supportedLocales: const [Locale("zh", "CN"), Locale("en", "US")], - fallbackLocale: const Locale("zh", "CN"), - getPages: Routes.getPages, - home: const MainApp(), - builder: (BuildContext context, Widget? child) { - return FlutterSmartDialog( - toastBuilder: (String msg) => CustomToast(msg: msg), - child: MediaQuery( - data: MediaQuery.of(context) - .copyWith(textScaler: TextScaler.linear(textScale)), - child: child!, - ), - ); - }, - navigatorObservers: [ - VideoDetailPage.routeObserver, - SearchPage.routeObserver, - ], + return BuildMainApp( + lightColorScheme: lightColorScheme, + darkColorScheme: darkColorScheme, + currentThemeValue: currentThemeValue, + textScale: textScale, ); }), ); } } + +class OtherApp extends StatelessWidget { + const OtherApp({ + super.key, + required this.brandColor, + required this.currentThemeValue, + required this.textScale, + }); + + final Color brandColor; + final ThemeType currentThemeValue; + final double textScale; + + @override + Widget build(BuildContext context) { + return BuildMainApp( + lightColorScheme: ColorScheme.fromSeed( + seedColor: brandColor, + brightness: Brightness.light, + ), + darkColorScheme: ColorScheme.fromSeed( + seedColor: brandColor, + brightness: Brightness.dark, + ), + currentThemeValue: currentThemeValue, + textScale: textScale, + ); + } +} + +class BuildMainApp extends StatelessWidget { + const BuildMainApp({ + super.key, + required this.lightColorScheme, + required this.darkColorScheme, + required this.currentThemeValue, + required this.textScale, + }); + + final ColorScheme lightColorScheme; + final ColorScheme darkColorScheme; + final ThemeType currentThemeValue; + final double textScale; + + @override + Widget build(BuildContext context) { + final SnackBarThemeData snackBarTheme = SnackBarThemeData( + actionTextColor: lightColorScheme.primary, + backgroundColor: lightColorScheme.secondaryContainer, + closeIconColor: lightColorScheme.secondary, + contentTextStyle: TextStyle(color: lightColorScheme.secondary), + elevation: 20, + ); + + return GetMaterialApp( + title: 'PiliPala', + theme: ThemeData( + colorScheme: currentThemeValue == ThemeType.dark + ? darkColorScheme + : lightColorScheme, + snackBarTheme: snackBarTheme, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: ZoomPageTransitionsBuilder( + allowEnterRouteSnapshotting: false, + ), + }, + ), + ), + darkTheme: ThemeData( + colorScheme: currentThemeValue == ThemeType.light + ? lightColorScheme + : darkColorScheme, + snackBarTheme: snackBarTheme, + ), + localizationsDelegates: const [ + GlobalCupertinoLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + locale: const Locale("zh", "CN"), + supportedLocales: const [Locale("zh", "CN"), Locale("en", "US")], + fallbackLocale: const Locale("zh", "CN"), + getPages: Routes.getPages, + home: const MainApp(), + builder: (BuildContext context, Widget? child) { + return FlutterSmartDialog( + toastBuilder: (String msg) => CustomToast(msg: msg), + child: MediaQuery( + data: MediaQuery.of(context) + .copyWith(textScaler: TextScaler.linear(textScale)), + child: child!, + ), + ); + }, + navigatorObservers: [ + VideoDetailPage.routeObserver, + SearchPage.routeObserver, + ], + onInit: () { + RecommendFilter(); + Data.init(); + GlobalData(); + }, + ); + } +} From 8f26884164a5a114529b02efc1875c5387e32bfc Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 2 Jun 2024 01:04:51 +0800 Subject: [PATCH 089/106] =?UTF-8?q?upgrade:=20=E4=BE=9D=E8=B5=96=E5=8D=87?= =?UTF-8?q?=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/build.gradle | 2 +- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile.lock | 14 +- ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- lib/pages/bangumi/view.dart | 7 +- .../pl_player/widgets/bottom_control.dart | 3 +- pubspec.lock | 160 ++++++++++-------- pubspec.yaml | 32 ++-- 9 files changed, 116 insertions(+), 108 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 713d7f6e..674e96f4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.7.10' + ext.kotlin_version = '1.9.0' repositories { google() mavenCentral() diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e105..7c569640 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 2c1a635b..04fe6670 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -10,7 +10,6 @@ PODS: - connectivity_plus (0.0.1): - Flutter - FlutterMacOS - - ReachabilitySwift - device_info_plus (0.0.1): - Flutter - Flutter (1.0.0) @@ -41,7 +40,6 @@ PODS: - FlutterMacOS - permission_handler_apple (9.3.0): - Flutter - - ReachabilitySwift (5.0.0) - saver_gallery (0.0.1): - Flutter - screen_brightness_ios (0.1.0): @@ -101,7 +99,6 @@ SPEC REPOS: trunk: - FMDB - GT3Captcha-iOS - - ReachabilitySwift - Toast EXTERNAL SOURCES: @@ -167,9 +164,9 @@ SPEC CHECKSUMS: audio_service: f509d65da41b9521a61f1c404dd58651f265a567 audio_session: 4f3e461722055d21515cf3261b64c973c062f345 auto_orientation: 102ed811a5938d52c86520ddd7ecd3a126b5d39d - connectivity_plus: e2dad488011aeb593e219360e804c43cc1af5770 + connectivity_plus: ddd7f30999e1faaef5967c23d5b6d503d10434db device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83 flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529 fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265 @@ -182,7 +179,6 @@ SPEC CHECKSUMS: package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 - ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 saver_gallery: 2b4e584106fde2407ab51560f3851564963e6b78 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5 @@ -190,11 +186,11 @@ SPEC CHECKSUMS: status_bar_control: 7c84146799e6a076315cc1550f78ef53aae3e446 system_proxy: bec1a5c5af67dd3e3ebf43979400a8756c04cc44 Toast: ec33c32b8688982cecc6348adeae667c1b9938da - url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9 - wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47 + wakelock_plus: 78ec7c5b202cab7761af8e2b2b3d0671be6c4ae1 webview_cookie_manager: eaf920722b493bd0f7611b5484771ca53fed03f7 - webview_flutter_wkwebview: 4f3e50f7273d31e5500066ed267e3ae4309c5ae4 + webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36 PODFILE CHECKSUM: 637cd290bed23275b5f5ffcc7eb1e73d0a5fb2be diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index bac856d2..55565d40 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a6b826db..5e31d3d3 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ ), ); } else { - return nil; + return const SizedBox(); } } else { - return nil; + return const SizedBox(); } }, ), @@ -216,7 +215,7 @@ class _BangumiPageState extends State (BuildContext context, int index) { return bangumiList!.isNotEmpty ? BangumiCardV(bangumiItem: bangumiList[index]) - : nil; + : const SizedBox(); }, childCount: bangumiList!.isNotEmpty ? bangumiList!.length : 10, ), diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart index 35e7792a..b3ff37db 100644 --- a/lib/plugin/pl_player/widgets/bottom_control.dart +++ b/lib/plugin/pl_player/widgets/bottom_control.dart @@ -1,7 +1,6 @@ import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:nil/nil.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; import 'package:pilipala/utils/feed_back.dart'; @@ -36,7 +35,7 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { final int max = _.durationSeconds.value; final int buffer = _.bufferedSeconds.value; if (value > max || max <= 0) { - return nil; + return const SizedBox(); } return Padding( padding: const EdgeInsets.only(left: 7, right: 7, bottom: 6), diff --git a/pubspec.lock b/pubspec.lock index 8f8a5cae..de434f2e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,14 +17,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.2.0" - animations: - dependency: "direct main" - description: - name: animations - sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.0.11" appscheme: dependency: "direct main" description: @@ -101,10 +93,10 @@ packages: dependency: "direct main" description: name: audio_video_progress_bar - sha256: ccc7d7b83d2a16c52d4a7fb332faabd1baa053fb0e4c16815aefd3945ab33b81 + sha256: "552b1f73c56c4c88407999e0a8507176f60c56de3e6d63bc20a0eab48467d4c9" url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.2" + version: "2.0.3" auto_orientation: dependency: "direct main" description: @@ -213,10 +205,10 @@ packages: dependency: "direct main" description: name: catcher_2 - sha256: "9cf33d2befd10058374e5fc6177577fdd938d73d9c06810de81cf91311a7ce98" + sha256: "2c2c6f8cf8c817730cd1dbb010d55292396930e7a3d42c04c3039e3fd411a2f8" url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.3" + version: "1.2.6" characters: dependency: transitive description: @@ -269,10 +261,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: e9feae83b1849f61bad9f6f33ee00646e3410d54ce0821e02f262f9901dad3c9 + sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8 url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.1" + version: "6.0.3" connectivity_plus_platform_interface: dependency: transitive description: @@ -301,10 +293,10 @@ packages: dependency: transitive description: name: cross_file - sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" url: "https://pub.flutter-io.cn" source: hosted - version: "0.3.3+8" + version: "0.3.4+1" crypto: dependency: "direct main" description: @@ -333,10 +325,10 @@ packages: dependency: "direct main" description: name: custom_sliding_segmented_control - sha256: "05b73fa48d57218bfdf806bad68a859812b216cd81fe81c6cbefde89f39eb257" + sha256: "53c3e931c3ae1f696085d1ec70ac8e934da836595a9b7d9b88fdd0fcbf2a5574" url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.1" + version: "1.8.3" dart_style: dependency: transitive description: @@ -461,10 +453,10 @@ packages: dependency: transitive description: name: extended_image_library - sha256: "9b55fc5ebc65fad984de66b8f177a1bef2a84d79203c9c213f75ff83c2c29edd" + sha256: c9caee8fe9b6547bd41c960c4f2d1ef8e34321804de6a1777f1d614a24247ad6 url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.1" + version: "4.0.4" extended_list: dependency: transitive description: @@ -621,10 +613,10 @@ packages: dependency: "direct main" description: name: flutter_volume_controller - sha256: "0f10cc759499cb6c3e152a8f6ff8e5ce385b99db7e1f586d1a29d8e6c11f4082" + sha256: fa4c36dfe7ef7f423704f34ab8e64e00b4a30a90aa6e56f251e9dba649efcd7f url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.1" + version: "1.3.2" flutter_web_plugins: dependency: transitive description: flutter @@ -722,10 +714,10 @@ packages: dependency: transitive description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.2" + version: "1.2.1" http2: dependency: transitive description: @@ -770,10 +762,10 @@ packages: dependency: transitive description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf url: "https://pub.flutter-io.cn" source: hosted - version: "0.18.1" + version: "0.19.0" io: dependency: transitive description: @@ -798,6 +790,30 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.8.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "10.0.4" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.3" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" lints: dependency: transitive description: @@ -834,10 +850,10 @@ packages: dependency: "direct main" description: name: logger - sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac" + sha256: af05cc8714f356fd1f3888fb6741cbe9fbe25cdb6eedbab80e1a6db21047d4a4 url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.2+1" + version: "2.3.0" logging: dependency: transitive description: @@ -850,26 +866,26 @@ packages: dependency: transitive description: name: mailer - sha256: "57f6dd1496699999a7bfd0aa6be0645384f477f4823e16d4321c40a434346382" + sha256: d25d89555c1031abacb448f07b801d7c01b4c21d4558e944b12b64394c84a3cb url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.1" + version: "6.1.0" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.flutter-io.cn" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.flutter-io.cn" source: hosted - version: "0.5.0" + version: "0.8.0" media_kit: dependency: "direct main" description: @@ -949,10 +965,10 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.flutter-io.cn" source: hosted - version: "1.10.0" + version: "1.12.0" mime: dependency: transitive description: @@ -961,14 +977,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.4" - nil: - dependency: "direct main" - description: - name: nil - sha256: ef05770c48942876d843bf6a4822d35e5da0ff893a61f1d5ad96d15c4a659136 - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.1.1" nm: dependency: transitive description: @@ -1022,10 +1030,10 @@ packages: dependency: "direct main" description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -1435,10 +1443,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.1" + version: "0.7.0" timing: dependency: transitive description: @@ -1467,10 +1475,10 @@ packages: dependency: "direct main" description: name: universal_platform - sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc + sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0+1" + version: "1.1.0" uri_parser: dependency: transitive description: @@ -1483,10 +1491,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 + sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" url: "https://pub.flutter-io.cn" source: hosted - version: "6.2.2" + version: "6.2.6" url_launcher_android: dependency: transitive description: @@ -1499,10 +1507,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" url: "https://pub.flutter-io.cn" source: hosted - version: "6.2.1" + version: "6.3.0" url_launcher_linux: dependency: transitive description: @@ -1531,10 +1539,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9" + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.2" + version: "2.3.1" url_launcher_windows: dependency: transitive description: @@ -1591,6 +1599,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.4.0+2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + url: "https://pub.flutter-io.cn" + source: hosted + version: "14.2.1" volume_controller: dependency: transitive description: @@ -1603,18 +1619,18 @@ packages: dependency: "direct main" description: name: wakelock_plus - sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d + sha256: "104d94837bb28c735894dcd592877e990149c380e6358b00c04398ca1426eed4" url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.4" + version: "1.2.1" wakelock_plus_platform_interface: dependency: transitive description: name: wakelock_plus_platform_interface - sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385" + sha256: "582f2f7aecc7376332d961a0dd1efa9378ce117657e0ade55d9ff72699a55e82" url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.0" + version: "1.2.0" watcher: dependency: transitive description: @@ -1635,10 +1651,10 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.flutter-io.cn" source: hosted - version: "0.3.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: @@ -1659,34 +1675,34 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: d81b68e88cc353e546afb93fb38958e3717282c5ac6e5d3be4a4aef9fc3c1413 + sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522" url: "https://pub.flutter-io.cn" source: hosted - version: "4.5.0" + version: "4.8.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: e313dcdf45d4c95bcb8960351ef2389b7f0687b90bc92483f7f7983ae5758456 + sha256: f42447ca49523f11d8f70abea55ea211b3cafe172dd7a0e7ac007bb35dd356dc url: "https://pub.flutter-io.cn" source: hosted - version: "3.13.0" + version: "3.16.4" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "68e86162aa8fc646ae859e1585995c096c95fc2476881fa0c4a8d10f56013a5a" + sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d url: "https://pub.flutter-io.cn" source: hosted - version: "2.8.0" + version: "2.10.0" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "4d062ad505390ecef1c4bfb6001cd857a51e00912cc9dfb66edb1886a9ebd80c" + sha256: "7affdf9d680c015b11587181171d3cad8093e449db1f7d9f0f08f4f33d24f9a0" url: "https://pub.flutter-io.cn" source: hosted - version: "3.10.2" + version: "3.13.1" win32: dependency: transitive description: @@ -1728,5 +1744,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index a269cd6f..b9390dd9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,7 +44,7 @@ dependencies: dio: ^5.4.1 cookie_jar: ^4.0.8 dio_cookie_manager: ^3.1.1 - connectivity_plus: ^6.0.1 + connectivity_plus: ^6.0.3 dio_http2_adapter: ^2.3.1+1 # 图片 @@ -66,7 +66,7 @@ dependencies: # cookie 管理 webview_cookie_manager: ^2.0.6 # 浏览器 - webview_flutter: ^4.5.0 + webview_flutter: ^4.8.0 # 解决sliver滑动不同步 extended_nested_scroll_view: ^6.2.1 # 上拉加载 @@ -79,7 +79,7 @@ dependencies: flutter_smart_dialog: ^4.9.4 # 下滑关闭 dismissible_page: ^1.0.2 - custom_sliding_segmented_control: ^1.7.5 + custom_sliding_segmented_control: ^1.8.3 # 加密 crypto: ^3.0.3 encrypt: ^5.0.3 @@ -94,19 +94,18 @@ dependencies: audio_session: ^0.1.18 # 音量、亮度、屏幕控制 - flutter_volume_controller: ^1.3.1 + flutter_volume_controller: ^1.3.2 screen_brightness: ^0.2.2+1 - wakelock_plus: ^1.1.1 - universal_platform: ^1.0.0+1 + wakelock_plus: ^1.1.6 + universal_platform: ^1.1.0 # 进度条 - audio_video_progress_bar: ^2.0.2 + audio_video_progress_bar: ^2.0.3 auto_orientation: ^2.3.1 protobuf: ^3.0.0 - animations: ^2.0.11 # 获取appx信息 - package_info_plus: ^4.1.0 - url_launcher: ^6.1.14 + package_info_plus: ^4.2.0 + url_launcher: ^6.2.6 flutter_svg: ^2.0.10+1 # 防抖节流 easy_debounce: ^2.0.3 @@ -136,10 +135,9 @@ dependencies: gt3_flutter_plugin: ^0.0.8 uuid: ^3.0.7 scrollable_positioned_list: ^0.3.8 - nil: ^1.1.1 - catcher_2: ^1.2.3 - logger: ^2.0.2+1 - path: 1.8.3 + catcher_2: ^1.2.6 + logger: ^2.3.0 + path: ^1.9.0 # 电池优化 disable_battery_optimization: ^1.1.1 # 展开/收起 @@ -166,15 +164,15 @@ dev_dependencies: build_runner: ^2.4.8 dependency_overrides: - media_kit: + media_kit: git: url: https://github.com/media-kit/media-kit path: media_kit - media_kit_video: + media_kit_video: git: url: https://github.com/media-kit/media-kit path: media_kit_video - media_kit_libs_video: + media_kit_libs_video: git: url: https://github.com/media-kit/media-kit path: libs/universal/media_kit_libs_video From 3b1ad133db0a9e8bdec5d47ec44e030dc4ee8367 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 2 Jun 2024 22:32:00 +0800 Subject: [PATCH 090/106] mod: logs replace# --- lib/pages/setting/pages/logs.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pages/setting/pages/logs.dart b/lib/pages/setting/pages/logs.dart index 0958edb8..f497aee5 100644 --- a/lib/pages/setting/pages/logs.dart +++ b/lib/pages/setting/pages/logs.dart @@ -41,7 +41,8 @@ class _LogsPageState extends State { .replaceAll('DEVICE INFO', '设备信息') .replaceAll('APP INFO', '应用信息') .replaceAll('ERROR', '错误信息') - .replaceAll('STACK TRACE', '错误堆栈'); + .replaceAll('STACK TRACE', '错误堆栈') + .replaceAll('#', 'Line'); }).toList(); List> result = []; for (String i in contentList) { @@ -50,7 +51,7 @@ class _LogsPageState extends State { .split("\n") .map((l) { if (l.startsWith("Crash occurred on")) { - date = DateTime.parse( + date = DateTime.tryParse( l.split("Crash occurred on")[1].trim().split('.')[0], ); return ""; From e0e1c6b08af706f79856074ba4b3ea5a53806fc4 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 4 Jun 2024 23:59:23 +0800 Subject: [PATCH 091/106] upgrade: color --- lib/common/pages_bottom_sheet.dart | 2 +- lib/common/skeleton/skeleton.dart | 4 ++-- lib/common/widgets/stat/danmu.dart | 2 +- lib/common/widgets/stat/view.dart | 2 +- .../introduction/widgets/intro_detail.dart | 4 ++-- lib/pages/dynamics/view.dart | 5 ++--- lib/pages/dynamics/widgets/additional_panel.dart | 2 +- lib/pages/dynamics/widgets/author_panel.dart | 2 +- lib/pages/dynamics/widgets/up_panel.dart | 4 ++-- lib/pages/search/widgets/search_text.dart | 5 ++++- lib/pages/setting/pages/font_size_select.dart | 2 +- .../detail/introduction/widgets/fav_panel.dart | 2 +- .../detail/introduction/widgets/group_panel.dart | 2 +- .../detail/introduction/widgets/menu_row.dart | 4 ++-- lib/pages/video/detail/reply_new/view.dart | 2 +- lib/pages/video/detail/reply_reply/view.dart | 2 +- lib/pages/video/detail/widgets/ai_detail.dart | 2 +- lib/pages/video/detail/widgets/app_bar.dart | 2 +- .../video/detail/widgets/header_control.dart | 16 ++++++++-------- lib/utils/image_save.dart | 2 +- 20 files changed, 35 insertions(+), 33 deletions(-) diff --git a/lib/common/pages_bottom_sheet.dart b/lib/common/pages_bottom_sheet.dart index 2a56eb41..49e9b4d8 100644 --- a/lib/common/pages_bottom_sheet.dart +++ b/lib/common/pages_bottom_sheet.dart @@ -124,7 +124,7 @@ class EpisodeBottomSheet { }); return Container( height: sheetHeight, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Column( children: [ buildTitle(), diff --git a/lib/common/skeleton/skeleton.dart b/lib/common/skeleton/skeleton.dart index 34e87f55..b17a55fc 100644 --- a/lib/common/skeleton/skeleton.dart +++ b/lib/common/skeleton/skeleton.dart @@ -13,8 +13,8 @@ class Skeleton extends StatelessWidget { var shimmerGradient = LinearGradient( colors: [ Colors.transparent, - Theme.of(context).colorScheme.background.withAlpha(10), - Theme.of(context).colorScheme.background.withAlpha(10), + Theme.of(context).colorScheme.surface.withAlpha(10), + Theme.of(context).colorScheme.surface.withAlpha(10), Colors.transparent, ], stops: const [ diff --git a/lib/common/widgets/stat/danmu.dart b/lib/common/widgets/stat/danmu.dart index c1c439db..511839a0 100644 --- a/lib/common/widgets/stat/danmu.dart +++ b/lib/common/widgets/stat/danmu.dart @@ -14,7 +14,7 @@ class StatDanMu extends StatelessWidget { Map colorObject = { 'white': Colors.white, 'gray': Theme.of(context).colorScheme.outline, - 'black': Theme.of(context).colorScheme.onBackground.withOpacity(0.8), + 'black': Theme.of(context).colorScheme.onSurface.withOpacity(0.8), }; Color color = colorObject[theme]!; return Row( diff --git a/lib/common/widgets/stat/view.dart b/lib/common/widgets/stat/view.dart index 2665e2d4..5359c979 100644 --- a/lib/common/widgets/stat/view.dart +++ b/lib/common/widgets/stat/view.dart @@ -14,7 +14,7 @@ class StatView extends StatelessWidget { Map colorObject = { 'white': Colors.white, 'gray': Theme.of(context).colorScheme.outline, - 'black': Theme.of(context).colorScheme.onBackground.withOpacity(0.8), + 'black': Theme.of(context).colorScheme.onSurface.withOpacity(0.8), }; Color color = colorObject[theme]!; return Row( diff --git a/lib/pages/bangumi/introduction/widgets/intro_detail.dart b/lib/pages/bangumi/introduction/widgets/intro_detail.dart index c5bbd566..07684a86 100644 --- a/lib/pages/bangumi/introduction/widgets/intro_detail.dart +++ b/lib/pages/bangumi/introduction/widgets/intro_detail.dart @@ -20,10 +20,10 @@ class IntroDetail extends StatelessWidget { sheetHeight = localCache.get('sheetHeight'); TextStyle smallTitle = TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.onBackground, + color: Theme.of(context).colorScheme.onSurface, ); return Container( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, padding: const EdgeInsets.only(left: 14, right: 14), height: sheetHeight, child: Column( diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index da15239d..258ad531 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -162,13 +162,12 @@ class _DynamicsPageState extends State decoration: BoxDecoration( color: Theme.of(context) .colorScheme - .surfaceVariant + .surfaceContainerHighest .withOpacity(0.7), borderRadius: BorderRadius.circular(20), ), thumbDecoration: BoxDecoration( - color: - Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(20), ), duration: const Duration(milliseconds: 300), diff --git a/lib/pages/dynamics/widgets/additional_panel.dart b/lib/pages/dynamics/widgets/additional_panel.dart index fa11f217..50e1b6d3 100644 --- a/lib/pages/dynamics/widgets/additional_panel.dart +++ b/lib/pages/dynamics/widgets/additional_panel.dart @@ -19,7 +19,7 @@ Widget addWidget(item, context, type, {floor = 1}) { }; Color bgColor = floor == 1 ? Theme.of(context).dividerColor.withOpacity(0.08) - : Theme.of(context).colorScheme.background; + : Theme.of(context).colorScheme.surface; switch (type) { case 'ADDITIONAL_TYPE_UGC': // 转发的投稿 diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index 0d3baecd..8acdc26a 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -52,7 +52,7 @@ class AuthorPanel extends StatelessWidget { color: item.modules.moduleAuthor!.vip != null && item.modules.moduleAuthor!.vip['status'] > 0 ? const Color.fromARGB(255, 251, 100, 163) - : Theme.of(context).colorScheme.onBackground, + : Theme.of(context).colorScheme.onSurface, fontSize: Theme.of(context).textTheme.titleSmall!.fontSize, ), ), diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index ee522cbb..f8c973a0 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -69,7 +69,7 @@ class _UpPanelState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, padding: const EdgeInsets.only(left: 16, right: 16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -95,7 +95,7 @@ class _UpPanelState extends State { ), Container( height: 90, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Row( children: [ Flexible( diff --git a/lib/pages/search/widgets/search_text.dart b/lib/pages/search/widgets/search_text.dart index 039a851b..1b96d412 100644 --- a/lib/pages/search/widgets/search_text.dart +++ b/lib/pages/search/widgets/search_text.dart @@ -16,7 +16,10 @@ class SearchText extends StatelessWidget { @override Widget build(BuildContext context) { return Material( - color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.5), + color: Theme.of(context) + .colorScheme + .surfaceContainerHighest + .withOpacity(0.5), borderRadius: BorderRadius.circular(6), child: Padding( padding: EdgeInsets.zero, diff --git a/lib/pages/setting/pages/font_size_select.dart b/lib/pages/setting/pages/font_size_select.dart index 4985c83f..f5ca6be3 100644 --- a/lib/pages/setting/pages/font_size_select.dart +++ b/lib/pages/setting/pages/font_size_select.dart @@ -66,7 +66,7 @@ class _FontSizeSelectPageState extends State { .colorScheme .primary .withOpacity(0.3))), - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, ), child: Row( children: [ diff --git a/lib/pages/video/detail/introduction/widgets/fav_panel.dart b/lib/pages/video/detail/introduction/widgets/fav_panel.dart index 517caeaa..5ef78967 100644 --- a/lib/pages/video/detail/introduction/widgets/fav_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/fav_panel.dart @@ -29,7 +29,7 @@ class _FavPanelState extends State { Widget build(BuildContext context) { return Container( height: sheetHeight, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Column( children: [ AppBar( diff --git a/lib/pages/video/detail/introduction/widgets/group_panel.dart b/lib/pages/video/detail/introduction/widgets/group_panel.dart index 64ff913d..dcdaf9c5 100644 --- a/lib/pages/video/detail/introduction/widgets/group_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/group_panel.dart @@ -57,7 +57,7 @@ class _GroupPanelState extends State { Widget build(BuildContext context) { return Container( height: sheetHeight, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Column( children: [ AppBar( diff --git a/lib/pages/video/detail/introduction/widgets/menu_row.dart b/lib/pages/video/detail/introduction/widgets/menu_row.dart index c175aff1..a26c86f0 100644 --- a/lib/pages/video/detail/introduction/widgets/menu_row.dart +++ b/lib/pages/video/detail/introduction/widgets/menu_row.dart @@ -12,7 +12,7 @@ class MenuRow extends StatelessWidget { Widget build(BuildContext context) { return Container( width: double.infinity, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, padding: const EdgeInsets.only(top: 9, bottom: 9, left: 12), child: SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -84,7 +84,7 @@ class MenuRow extends StatelessWidget { style: TextStyle( fontSize: 13, color: selectStatus - ? Theme.of(context).colorScheme.onBackground + ? Theme.of(context).colorScheme.onSurface : Theme.of(context).colorScheme.outline), ), ), diff --git a/lib/pages/video/detail/reply_new/view.dart b/lib/pages/video/detail/reply_new/view.dart index 3da15f64..d7355d81 100644 --- a/lib/pages/video/detail/reply_new/view.dart +++ b/lib/pages/video/detail/reply_new/view.dart @@ -170,7 +170,7 @@ class _VideoReplyNewDialogState extends State topLeft: Radius.circular(12), topRight: Radius.circular(12), ), - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, ), child: Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index 3fe84c71..6dda9512 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -78,7 +78,7 @@ class _VideoReplyReplyPanelState extends State { Widget build(BuildContext context) { return Container( height: widget.source == 'videoDetail' ? widget.sheetHeight : null, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, child: Column( children: [ if (widget.source == 'videoDetail') diff --git a/lib/pages/video/detail/widgets/ai_detail.dart b/lib/pages/video/detail/widgets/ai_detail.dart index 882a9a8b..197d6124 100644 --- a/lib/pages/video/detail/widgets/ai_detail.dart +++ b/lib/pages/video/detail/widgets/ai_detail.dart @@ -23,7 +23,7 @@ class AiDetail extends StatelessWidget { Widget build(BuildContext context) { sheetHeight = localCache.get('sheetHeight'); return Container( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, padding: const EdgeInsets.only(left: 14, right: 14), height: sheetHeight, child: Column( diff --git a/lib/pages/video/detail/widgets/app_bar.dart b/lib/pages/video/detail/widgets/app_bar.dart index efc0b593..b16623ad 100644 --- a/lib/pages/video/detail/widgets/app_bar.dart +++ b/lib/pages/video/detail/widgets/app_bar.dart @@ -29,7 +29,7 @@ class ScrollAppBar extends StatelessWidget { opacity: scrollDistance / (videoHeight - kToolbarHeight), child: Container( height: statusBarHeight + kToolbarHeight, - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, padding: EdgeInsets.only(top: statusBarHeight), child: AppBar( primary: false, diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 544d93e0..3ff74b44 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -93,7 +93,7 @@ class _HeaderControlState extends State { height: 460, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -317,7 +317,7 @@ class _HeaderControlState extends State { height: 500, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -377,7 +377,7 @@ class _HeaderControlState extends State { inactiveThumbColor: Theme.of(context).colorScheme.primaryContainer, inactiveTrackColor: - Theme.of(context).colorScheme.background, + Theme.of(context).colorScheme.surface, splashRadius: 10.0, // boolean variable value value: shutdownTimerService.waitForPlayingCompleted, @@ -570,7 +570,7 @@ class _HeaderControlState extends State { height: 310, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -660,7 +660,7 @@ class _HeaderControlState extends State { height: 250, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -734,7 +734,7 @@ class _HeaderControlState extends State { height: 250, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -828,7 +828,7 @@ class _HeaderControlState extends State { height: 580, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -1084,7 +1084,7 @@ class _HeaderControlState extends State { height: 250, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), diff --git a/lib/utils/image_save.dart b/lib/utils/image_save.dart index 0cd6915c..0b77b7cc 100644 --- a/lib/utils/image_save.dart +++ b/lib/utils/image_save.dart @@ -12,7 +12,7 @@ Future imageSaveDialog(context, videoItem, closeFn) { builder: (context) => Container( margin: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background, + color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(10.0), ), child: Column( From 7fc4f3fd4145acacdf116a82ff04ce8aa68002f3 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 6 Jun 2024 00:28:46 +0800 Subject: [PATCH 092/106] =?UTF-8?q?fix:=20=E9=A6=96=E9=A1=B5app=E6=8E=A8?= =?UTF-8?q?=E8=8D=90=E5=85=B3=E6=B3=A8=E7=8A=B6=E6=80=81=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/home/rcmd/result.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/models/home/rcmd/result.dart b/lib/models/home/rcmd/result.dart index 78747d1a..0098fe95 100644 --- a/lib/models/home/rcmd/result.dart +++ b/lib/models/home/rcmd/result.dart @@ -69,9 +69,10 @@ class RecVideoItemAppModel { : null; // 由于app端api并不会直接返回与owner的关注状态 // 所以借用推荐原因是否为“已关注”、“新关注”等判别关注状态,从而与web端接口等效 + RegExp regex = RegExp(r'已关注|新关注'); isFollowed = rcmdReason != null && rcmdReason!.content != null && - rcmdReason!.content!.contains('关注') + regex.hasMatch(rcmdReason!.content!) ? 1 : 0; // 如果是,就无需再显示推荐原因,交由view统一处理即可 From f8897f74bfae9b2d86d8d30625f3816ab9797462 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 7 Jun 2024 23:48:48 +0800 Subject: [PATCH 093/106] =?UTF-8?q?feat:=20web=E7=AB=AF=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 4 +- lib/http/login.dart | 99 ++++++++++++++++++++++--------- lib/pages/login/controller.dart | 80 ++++++++++++++++++++++--- lib/pages/login/view.dart | 37 +++++++----- lib/pages/mine/controller.dart | 5 +- lib/pages/webview/controller.dart | 52 +--------------- lib/pages/webview/view.dart | 4 +- lib/utils/login.dart | 58 ++++++++++++++++++ 8 files changed, 231 insertions(+), 108 deletions(-) diff --git a/lib/http/api.dart b/lib/http/api.dart index 42fc03b8..8a72479b 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -400,10 +400,12 @@ class Api { '${HttpString.passBaseUrl}/x/passport-login/captcha?source=main_web'; // web端短信验证码 - static const String smsCode = + static const String webSmsCode = '${HttpString.passBaseUrl}/x/passport-login/web/sms/send'; // web端验证码登录 + static const String webSmsLogin = + "${HttpString.passBaseUrl}/x/passport-login/web/login/sms"; // web端密码登录 diff --git a/lib/http/login.dart b/lib/http/login.dart index ff3fee23..13236623 100644 --- a/lib/http/login.dart +++ b/lib/http/login.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:crypto/crypto.dart'; import 'package:dio/dio.dart'; import 'package:encrypt/encrypt.dart'; +import 'package:pilipala/http/constants.dart'; import 'package:uuid/uuid.dart'; import '../models/login/index.dart'; import '../utils/login.dart'; @@ -21,32 +22,32 @@ class LoginHttp { } } - static Future sendSmsCode({ - int? cid, - required int tel, - required String token, - required String challenge, - required String validate, - required String seccode, - }) async { - var res = await Request().post( - Api.appSmsCode, - data: { - 'cid': cid, - 'tel': tel, - "source": "main_web", - 'token': token, - 'challenge': challenge, - 'validate': validate, - 'seccode': seccode, - }, - options: Options( - contentType: Headers.formUrlEncodedContentType, - // headers: {'user-agent': ApiConstants.userAgent} - ), - ); - print(res); - } + // static Future sendSmsCode({ + // int? cid, + // required int tel, + // required String token, + // required String challenge, + // required String validate, + // required String seccode, + // }) async { + // var res = await Request().post( + // Api.appSmsCode, + // data: { + // 'cid': cid, + // 'tel': tel, + // "source": "main_web", + // 'token': token, + // 'challenge': challenge, + // 'validate': validate, + // 'seccode': seccode, + // }, + // options: Options( + // contentType: Headers.formUrlEncodedContentType, + // // headers: {'user-agent': ApiConstants.userAgent} + // ), + // ); + // print(res); + // } // web端验证码 static Future sendWebSmsCode({ @@ -60,6 +61,7 @@ class LoginHttp { Map data = { 'cid': cid, 'tel': tel, + "source": "main_web", 'token': token, 'challenge': challenge, 'validate': validate, @@ -67,17 +69,56 @@ class LoginHttp { }; FormData formData = FormData.fromMap({...data}); var res = await Request().post( - Api.smsCode, + Api.webSmsCode, data: formData, options: Options( contentType: Headers.formUrlEncodedContentType, ), ); - print(res); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': res.data['data'], + }; + } else { + return {'status': false, 'data': [], 'msg': res.data['message']}; + } } // web端验证码登录 - static Future loginInByWebSmsCode() async {} + static Future loginInByWebSmsCode({ + int? cid, + required int tel, + required int code, + required String captchaKey, + }) async { + // webSmsLogin + Map data = { + "cid": cid, + "tel": tel, + "code": code, + "source": "main_mini", + "keep": 0, + "captcha_key": captchaKey, + "go_url": HttpString.baseUrl + }; + FormData formData = FormData.fromMap({...data}); + var res = await Request().post( + Api.webSmsLogin, + data: formData, + options: Options( + contentType: Headers.formUrlEncodedContentType, + ), + ); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': res.data['data'], + }; + } else { + return {'status': false, 'data': [], 'msg': res.data['message']}; + } + } // web端密码登录 static Future liginInByWebPwd() async {} diff --git a/lib/pages/login/controller.dart b/lib/pages/login/controller.dart index c002fdf9..e47653e2 100644 --- a/lib/pages/login/controller.dart +++ b/lib/pages/login/controller.dart @@ -1,11 +1,16 @@ +import 'dart:async'; +import 'dart:developer'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:get/get_rx/get_rx.dart'; import 'package:pilipala/http/login.dart'; import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart'; import 'package:pilipala/models/login/index.dart'; +import 'package:pilipala/pages/webview/index.dart'; +import 'package:pilipala/utils/login.dart'; class LoginPageController extends GetxController { final GlobalKey mobFormKey = GlobalKey(); @@ -26,9 +31,19 @@ class LoginPageController extends GetxController { final Gt3FlutterPlugin captcha = Gt3FlutterPlugin(); + // 倒计时60s + RxInt seconds = 60.obs; + late Timer timer; + RxBool smsCodeSendStatus = false.obs; + // 默认密码登录 RxInt loginType = 0.obs; + late String captchaLey; + + late int tel; + late int webSmsCode; + // 监听pageView切换 void onPageChange(int index) { currentIndex.value = index; @@ -43,6 +58,7 @@ class LoginPageController extends GetxController { curve: Curves.easeInOut, ); passwordTextFieldNode.requestFocus(); + (mobFormKey.currentState as FormState).save(); } } @@ -86,18 +102,32 @@ class LoginPageController extends GetxController { } } - // 验证码登录 - void loginInByCode() { - if ((msgCodeFormKey.currentState as FormState).validate()) {} + // web端验证码登录 + void loginInByCode() async { + if ((msgCodeFormKey.currentState as FormState).validate()) { + (msgCodeFormKey.currentState as FormState).save(); + var res = await LoginHttp.loginInByWebSmsCode( + cid: 86, + tel: tel, + code: webSmsCode, + captchaKey: captchaLey, + ); + if (res['status']) { + log(res.toString()); + LoginUtils.confirmLogin('', null); + } else { + SmartDialog.showToast(res['msg']); + } + } } - // app端验证码 - void getMsgCode() async { + // 获取app端验证码 + void getAppMsgCode() async { getCaptcha((data) async { CaptchaDataModel captchaData = data; var res = await LoginHttp.sendAppSmsCode( cid: 86, - tel: 13734077064, + tel: tel, token: captchaData.token!, challenge: captchaData.geetest!.challenge!, validate: captchaData.validate!, @@ -121,7 +151,7 @@ class LoginPageController extends GetxController { captcha.addEventHandler(onShow: (Map message) async { SmartDialog.dismiss(); }, onClose: (Map message) async { - SmartDialog.showToast('关闭验证'); + SmartDialog.showToast('取消验证'); }, onResult: (Map message) async { debugPrint("Captcha result: $message"); String code = message["code"]; @@ -201,4 +231,40 @@ class LoginPageController extends GetxController { captcha.startCaptcha(registerData); } else {} } + + // 获取web端验证码 + void getWebMsgCode() async { + getCaptcha((data) async { + CaptchaDataModel captchaData = data; + var res = await LoginHttp.sendWebSmsCode( + cid: 86, + tel: tel, + token: captchaData.token!, + challenge: captchaData.geetest!.challenge!, + validate: captchaData.validate!, + seccode: captchaData.seccode!, + ); + if (res['status']) { + captchaLey = res['data']['captcha_key']; + SmartDialog.showToast('验证码已发送'); + // 倒计时60s + smsCodeSendStatus.value = true; + startTimer(); + } else { + SmartDialog.showToast(res['msg']); + } + }); + } + + void startTimer() { + timer = Timer.periodic(const Duration(seconds: 1), (timer) { + if (seconds.value > 0) { + seconds.value--; + } else { + seconds.value = 60; + smsCodeSendStatus.value = false; + timer.cancel(); + } + }); + } } diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index 6521e9d9..ae0a60b9 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -93,9 +93,7 @@ class _LoginPageState extends State { validator: (v) { return v!.trim().isNotEmpty ? null : "手机号码不能为空"; }, - onSaved: (val) { - print(val); - }, + onSaved: (val) => _loginPageCtr.tel = int.parse(val!), onEditingComplete: () { _loginPageCtr.nextStep(); }, @@ -308,21 +306,28 @@ class _LoginPageState extends State { ? null : "验证码不能为空"; }, - onSaved: (val) { - print(val); - }, + onSaved: (val) => _loginPageCtr.webSmsCode = + int.parse(val!), ), - Positioned( - right: 8, - top: 4, - child: Center( - child: TextButton( - onPressed: () => - _loginPageCtr.getMsgCode(), - child: const Text('获取验证码'), + Obx(() { + return Positioned( + right: 8, + top: 0, + child: Center( + child: TextButton( + onPressed: _loginPageCtr + .smsCodeSendStatus.value + ? null + : () => + _loginPageCtr.getWebMsgCode(), + child: _loginPageCtr + .smsCodeSendStatus.value + ? Text( + '重新获取(${_loginPageCtr.seconds.value}s)') + : const Text('获取验证码')), ), - ), - ), + ); + }) ], ), ), diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index a61bb820..153a7162 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -6,7 +6,6 @@ import 'package:pilipala/http/user.dart'; import 'package:pilipala/models/common/theme_type.dart'; import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/user/stat.dart'; -import 'package:pilipala/utils/route_push.dart'; import 'package:pilipala/utils/storage.dart'; class MineController extends GetxController { @@ -34,8 +33,8 @@ class MineController extends GetxController { onLogin() async { if (!userLogin.value) { - RoutePush.loginPush(); - // Get.toNamed('/loginPage'); + // RoutePush.loginPush(); + Get.toNamed('/loginPage'); } else { int mid = userInfo.value.mid!; String face = userInfo.value.face!; diff --git a/lib/pages/webview/controller.dart b/lib/pages/webview/controller.dart index bdacc652..e0ff113c 100644 --- a/lib/pages/webview/controller.dart +++ b/lib/pages/webview/controller.dart @@ -76,7 +76,7 @@ class WebviewController extends GetxController { (url.startsWith( 'https://passport.bilibili.com/web/sso/exchange_cookie') || url.startsWith('https://m.bilibili.com/'))) { - confirmLogin(url); + LoginUtils.confirmLogin(url, controller); } }, onWebResourceError: (WebResourceError error) {}, @@ -97,54 +97,4 @@ class WebviewController extends GetxController { ) ..loadRequest(Uri.parse(url)); } - - confirmLogin(url) async { - var content = ''; - if (url != null) { - content = '${content + url}; \n'; - } - try { - await SetCookie.onSet(); - final result = await UserHttp.userInfo(); - if (result['status'] && result['data'].isLogin) { - SmartDialog.showToast('登录成功'); - try { - Box userInfoCache = GStrorage.userInfo; - if (!userInfoCache.isOpen) { - userInfoCache = await Hive.openBox('userInfo'); - } - await userInfoCache.put('userInfoCache', result['data']); - - final HomeController homeCtr = Get.find(); - homeCtr.updateLoginStatus(true); - homeCtr.userFace.value = result['data'].face; - final MediaController mediaCtr = Get.find(); - mediaCtr.mid = result['data'].mid; - await LoginUtils.refreshLoginStatus(true); - } catch (err) { - SmartDialog.show(builder: (BuildContext context) { - return AlertDialog( - title: const Text('登录遇到问题'), - content: Text(err.toString()), - actions: [ - TextButton( - onPressed: () => controller.reload(), - child: const Text('确认'), - ) - ], - ); - }); - } - Get.back(); - } else { - // 获取用户信息失败 - SmartDialog.showToast(result['msg']); - Clipboard.setData(ClipboardData(text: result['msg'])); - } - } catch (e) { - SmartDialog.showNotify(msg: e.toString(), notifyType: NotifyType.warning); - content = content + e.toString(); - Clipboard.setData(ClipboardData(text: content)); - } - } } diff --git a/lib/pages/webview/view.dart b/lib/pages/webview/view.dart index 8edd2189..cba40ad1 100644 --- a/lib/pages/webview/view.dart +++ b/lib/pages/webview/view.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:pilipala/utils/login.dart'; import 'package:url_launcher/url_launcher.dart'; import 'controller.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -43,7 +44,8 @@ class _WebviewPageState extends State { Obx( () => _webviewController.type.value == 'login' ? TextButton( - onPressed: () => _webviewController.confirmLogin(null), + onPressed: () => + LoginUtils.confirmLogin(null, _webviewController), child: const Text('刷新登录状态'), ) : const SizedBox(), diff --git a/lib/utils/login.dart b/lib/utils/login.dart index 59c53027..2687a8c2 100644 --- a/lib/utils/login.dart +++ b/lib/utils/login.dart @@ -2,12 +2,18 @@ import 'dart:convert'; import 'dart:math'; import 'package:crypto/crypto.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; +import 'package:hive/hive.dart'; +import 'package:pilipala/http/user.dart'; import 'package:pilipala/pages/dynamics/index.dart'; import 'package:pilipala/pages/home/index.dart'; import 'package:pilipala/pages/media/index.dart'; import 'package:pilipala/pages/mine/index.dart'; +import 'package:pilipala/utils/cookie.dart'; +import 'package:pilipala/utils/storage.dart'; import 'package:uuid/uuid.dart'; class LoginUtils { @@ -57,4 +63,56 @@ class LoginUtils { String uuid = getUUID() + getUUID(); return 'XY${uuid.substring(0, 35).toUpperCase()}'; } + + static confirmLogin(url, controller) async { + var content = ''; + if (url != null) { + content = '${content + url}; \n'; + } + try { + await SetCookie.onSet(); + final result = await UserHttp.userInfo(); + if (result['status'] && result['data'].isLogin) { + SmartDialog.showToast('登录成功'); + try { + Box userInfoCache = GStrorage.userInfo; + if (!userInfoCache.isOpen) { + userInfoCache = await Hive.openBox('userInfo'); + } + await userInfoCache.put('userInfoCache', result['data']); + + final HomeController homeCtr = Get.find(); + homeCtr.updateLoginStatus(true); + homeCtr.userFace.value = result['data'].face; + final MediaController mediaCtr = Get.find(); + mediaCtr.mid = result['data'].mid; + await LoginUtils.refreshLoginStatus(true); + } catch (err) { + SmartDialog.show(builder: (BuildContext context) { + return AlertDialog( + title: const Text('登录遇到问题'), + content: Text(err.toString()), + actions: [ + TextButton( + onPressed: controller != null + ? () => controller.reload() + : SmartDialog.dismiss, + child: const Text('确认'), + ) + ], + ); + }); + } + Get.back(); + } else { + // 获取用户信息失败 + SmartDialog.showToast(result['msg']); + Clipboard.setData(ClipboardData(text: result['msg'])); + } + } catch (e) { + SmartDialog.showNotify(msg: e.toString(), notifyType: NotifyType.warning); + content = content + e.toString(); + Clipboard.setData(ClipboardData(text: content)); + } + } } From 9888aba62e93b87c75832c543697302930c588e5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 00:26:08 +0800 Subject: [PATCH 094/106] =?UTF-8?q?feat:=20web=E7=AB=AF=E5=AF=86=E7=A0=81?= =?UTF-8?q?=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 2 ++ lib/http/login.dart | 38 ++++++++++++++++++++++++++ lib/pages/login/controller.dart | 47 +++++++++++++++++++++++++++------ lib/pages/login/view.dart | 2 +- 4 files changed, 80 insertions(+), 9 deletions(-) diff --git a/lib/http/api.dart b/lib/http/api.dart index 8a72479b..e0b92c02 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -408,6 +408,8 @@ class Api { "${HttpString.passBaseUrl}/x/passport-login/web/login/sms"; // web端密码登录 + static const String loginInByWebPwd = + "${HttpString.passBaseUrl}/x/passport-login/web/login"; // app端短信验证码 static const String appSmsCode = diff --git a/lib/http/login.dart b/lib/http/login.dart index 13236623..a97360c7 100644 --- a/lib/http/login.dart +++ b/lib/http/login.dart @@ -214,4 +214,42 @@ class LoginHttp { ); print(res); } + + // web端密码登录 + static Future loginInByWebPwd({ + required int username, + required String password, + required String token, + required String challenge, + required String validate, + required String seccode, + }) async { + Map data = { + 'username': username, + 'password': password, + 'keep': 0, + 'token': token, + 'challenge': challenge, + 'validate': validate, + 'seccode': seccode, + 'source': 'main-fe-header', + "go_url": HttpString.baseUrl + }; + FormData formData = FormData.fromMap({...data}); + var res = await Request().post( + Api.loginInByWebPwd, + data: formData, + options: Options( + contentType: Headers.formUrlEncodedContentType, + ), + ); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': res.data['data'], + }; + } else { + return {'status': false, 'data': [], 'msg': res.data['message']}; + } + } } diff --git a/lib/pages/login/controller.dart b/lib/pages/login/controller.dart index e47653e2..354076f9 100644 --- a/lib/pages/login/controller.dart +++ b/lib/pages/login/controller.dart @@ -1,15 +1,13 @@ import 'dart:async'; -import 'dart:developer'; import 'dart:io'; +import 'package:encrypt/encrypt.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import 'package:get/get_rx/get_rx.dart'; import 'package:pilipala/http/login.dart'; import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart'; import 'package:pilipala/models/login/index.dart'; -import 'package:pilipala/pages/webview/index.dart'; import 'package:pilipala/utils/login.dart'; class LoginPageController extends GetxController { @@ -39,7 +37,7 @@ class LoginPageController extends GetxController { // 默认密码登录 RxInt loginType = 0.obs; - late String captchaLey; + late String captchaKey; late int tel; late int webSmsCode; @@ -102,6 +100,39 @@ class LoginPageController extends GetxController { } } + // web端密码登录 + void loginInByWebPassword() async { + if ((passwordFormKey.currentState as FormState).validate()) { + getCaptcha((data) async { + CaptchaDataModel captchaData = data; + var webKeyRes = await LoginHttp.getWebKey(); + if (webKeyRes['status']) { + String rhash = webKeyRes['data']['hash']; + String key = webKeyRes['data']['key']; + dynamic publicKey = RSAKeyParser().parse(key); + String passwordEncryptyed = Encrypter(RSA(publicKey: publicKey)) + .encrypt(rhash + passwordTextController.text) + .base64; + var res = await LoginHttp.loginInByWebPwd( + username: tel, + password: passwordEncryptyed, + token: captchaData.token!, + challenge: captchaData.geetest!.challenge!, + validate: captchaData.validate!, + seccode: captchaData.seccode!, + ); + if (res['status']) { + await LoginUtils.confirmLogin('', null); + } else { + SmartDialog.showToast(res['msg']); + } + } else { + SmartDialog.showToast(webKeyRes['msg']); + } + }); + } + } + // web端验证码登录 void loginInByCode() async { if ((msgCodeFormKey.currentState as FormState).validate()) { @@ -110,11 +141,10 @@ class LoginPageController extends GetxController { cid: 86, tel: tel, code: webSmsCode, - captchaKey: captchaLey, + captchaKey: captchaKey, ); if (res['status']) { - log(res.toString()); - LoginUtils.confirmLogin('', null); + await LoginUtils.confirmLogin('', null); } else { SmartDialog.showToast(res['msg']); } @@ -245,7 +275,7 @@ class LoginPageController extends GetxController { seccode: captchaData.seccode!, ); if (res['status']) { - captchaLey = res['data']['captcha_key']; + captchaKey = res['data']['captcha_key']; SmartDialog.showToast('验证码已发送'); // 倒计时60s smsCodeSendStatus.value = true; @@ -256,6 +286,7 @@ class LoginPageController extends GetxController { }); } + // 验证码倒计时 void startTimer() { timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (seconds.value > 0) { diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index ae0a60b9..2f406706 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -234,7 +234,7 @@ class _LoginPageState extends State { .primary, // 设置按钮背景色 ), onPressed: () => - _loginPageCtr.loginInByAppPassword(), + _loginPageCtr.loginInByWebPassword(), child: const Text('确认登录'), ) ], From 4fe8366c2fe6013f8f9f941ebc6b33437709975e Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 00:42:45 +0800 Subject: [PATCH 095/106] upgrade: gt3 plugin --- pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index fdcd517c..406fbca4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -674,10 +674,10 @@ packages: dependency: "direct main" description: name: gt3_flutter_plugin - sha256: f12bff2bfbcf27467833f8d564dcc24ee2f1b3254a7c7cf5eb2c4590baf11cc1 + sha256: "08f35692e937770ad6b3e2017eb8ef81839a82b8a63f5acf3abab14b688fc36c" url: "https://pub.flutter-io.cn" source: hosted - version: "0.0.8" + version: "0.1.0" hive: dependency: "direct main" description: @@ -981,10 +981,10 @@ packages: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.4" + version: "1.0.5" nm: dependency: transitive description: @@ -1054,10 +1054,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.1.3" path_provider_android: dependency: transitive description: @@ -1070,10 +1070,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 url: "https://pub.flutter-io.cn" source: hosted - version: "2.3.1" + version: "2.4.0" path_provider_linux: dependency: transitive description: @@ -1238,10 +1238,10 @@ packages: dependency: "direct main" description: name: saver_gallery - sha256: "2657953427ebe5a3b2d08157d41587c01923ccce3f1a616d55082be7470f8530" + sha256: "0f740608072053a0da3b19cc5812a87e36f5c3c0b959d2475c4eb3d697f4a782" url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.1" + version: "3.0.3" screen_brightness: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index f758d308..f02c2ead 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -132,7 +132,7 @@ dependencies: # html渲染 flutter_html: ^3.0.0-beta.2 # 极验 - gt3_flutter_plugin: ^0.0.8 + gt3_flutter_plugin: ^0.1.0 uuid: ^3.0.7 scrollable_positioned_list: ^0.3.8 catcher_2: ^1.2.6 From 3a94281310ecf86ccdd0a5d21853b9ed38dceff6 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 03:14:37 +0800 Subject: [PATCH 096/106] =?UTF-8?q?feat:=20web=E7=AB=AF=E6=89=AB=E7=A0=81?= =?UTF-8?q?=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 12 +++- lib/http/login.dart | 27 +++++++ lib/pages/login/controller.dart | 35 +++++++++ lib/pages/login/view.dart | 121 ++++++++++++++++++++++++++------ pubspec.lock | 16 +++++ pubspec.yaml | 2 + 6 files changed, 190 insertions(+), 23 deletions(-) diff --git a/lib/http/api.dart b/lib/http/api.dart index e0b92c02..b0fc0556 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -405,11 +405,19 @@ class Api { // web端验证码登录 static const String webSmsLogin = - "${HttpString.passBaseUrl}/x/passport-login/web/login/sms"; + '${HttpString.passBaseUrl}/x/passport-login/web/login/sms'; // web端密码登录 static const String loginInByWebPwd = - "${HttpString.passBaseUrl}/x/passport-login/web/login"; + '${HttpString.passBaseUrl}/x/passport-login/web/login'; + + // web端二维码 + static const String qrCodeApi = + '${HttpString.passBaseUrl}/x/passport-login/web/qrcode/generate'; + + // 扫码登录 + static const String loginInByQrcode = + '${HttpString.passBaseUrl}/x/passport-login/web/qrcode/poll'; // app端短信验证码 static const String appSmsCode = diff --git a/lib/http/login.dart b/lib/http/login.dart index a97360c7..2437b72a 100644 --- a/lib/http/login.dart +++ b/lib/http/login.dart @@ -252,4 +252,31 @@ class LoginHttp { return {'status': false, 'data': [], 'msg': res.data['message']}; } } + + // web端登录二维码 + static Future getWebQrcode() async { + var res = await Request().get(Api.qrCodeApi); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': res.data['data'], + }; + } else { + return {'status': false, 'data': [], 'msg': res.data['message']}; + } + } + + // web端二维码轮询登录状态 + static Future queryWebQrcodeStatus(String qrcodeKey) async { + var res = await Request() + .get(Api.loginInByQrcode, data: {'qrcode_key': qrcodeKey}); + if (res.data['data']['code'] == 0) { + return { + 'status': true, + 'data': res.data['data'], + }; + } else { + return {'status': false, 'data': [], 'msg': res.data['message']}; + } + } } diff --git a/lib/pages/login/controller.dart b/lib/pages/login/controller.dart index 354076f9..b5ddba16 100644 --- a/lib/pages/login/controller.dart +++ b/lib/pages/login/controller.dart @@ -42,6 +42,10 @@ class LoginPageController extends GetxController { late int tel; late int webSmsCode; + RxInt validSeconds = 180.obs; + late Timer validTimer; + late String qrcodeKey; + // 监听pageView切换 void onPageChange(int index) { currentIndex.value = index; @@ -298,4 +302,35 @@ class LoginPageController extends GetxController { } }); } + + // 获取登录二维码 + Future getWebQrcode() async { + var res = await LoginHttp.getWebQrcode(); + validSeconds.value = 180; + if (res['status']) { + qrcodeKey = res['data']['qrcode_key']; + validTimer = Timer.periodic(const Duration(seconds: 1), (validTimer) { + if (validSeconds.value > 0) { + validSeconds.value--; + queryWebQrcodeStatus(); + } else { + getWebQrcode(); + validTimer.cancel(); + } + }); + return res; + } else { + SmartDialog.showToast(res['msg']); + } + } + + // 轮询二维码登录状态 + Future queryWebQrcodeStatus() async { + var res = await LoginHttp.queryWebQrcodeStatus(qrcodeKey); + if (res['status']) { + await LoginUtils.confirmLogin('', null); + validTimer.cancel(); + Get.back(); + } + } } diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index 2f406706..cd91ea26 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:qr_flutter/qr_flutter.dart'; import 'controller.dart'; @@ -37,6 +38,105 @@ class _LoginPageState extends State { icon: const Icon(Icons.arrow_back), ), ), + actions: [ + IconButton( + tooltip: '浏览器打开', + onPressed: () { + Get.offNamed( + '/webview', + parameters: { + 'url': 'https://passport.bilibili.com/h5-app/passport/login', + 'type': 'login', + 'pageTitle': '登录bilibili', + }, + ); + }, + icon: const Icon(Icons.language), + ), + IconButton( + tooltip: '二维码登录', + onPressed: () { + showDialog( + context: context, + builder: (context) { + return StatefulBuilder( + builder: (context, StateSetter setState) { + return AlertDialog( + title: Row( + children: [ + const Text('扫码登录'), + IconButton( + onPressed: () { + setState(() {}); + }, + icon: const Icon(Icons.refresh), + ), + ], + ), + contentPadding: const EdgeInsets.fromLTRB(0, 0, 0, 4), + content: AspectRatio( + aspectRatio: 1, + child: Container( + width: 200, + padding: const EdgeInsets.all(12), + child: FutureBuilder( + future: _loginPageCtr.getWebQrcode(), + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.done) { + if (snapshot.data == null) { + return const SizedBox(); + } + Map data = snapshot.data as Map; + return QrImageView( + data: data['data']['url'], + backgroundColor: Colors.transparent, + ); + } else { + return const Center( + child: SizedBox( + width: 40, + height: 40, + child: CircularProgressIndicator(), + ), + ); + } + }, + ), + ), + ), + actions: [ + TextButton( + onPressed: () {}, + child: Obx(() { + return Text( + '有效期: ${_loginPageCtr.validSeconds.value}s', + style: Theme.of(context).textTheme.titleMedium, + ); + }), + ), + TextButton( + onPressed: () {}, + child: Text( + '检查登录状态', + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .titleMedium! + .fontSize, + ), + ), + ) + ], + ); + }); + }, + ); + }, + icon: const Icon(Icons.qr_code), + ), + const SizedBox(width: 22), + ], ), body: PageView( physics: const NeverScrollableScrollPhysics(), @@ -99,27 +199,6 @@ class _LoginPageState extends State { }, ), ), - GestureDetector( - onTap: () { - Get.offNamed( - '/webview', - parameters: { - 'url': - 'https://passport.bilibili.com/h5-app/passport/login', - 'type': 'login', - 'pageTitle': '登录bilibili', - }, - ); - }, - child: Padding( - padding: const EdgeInsets.only(left: 2), - child: Text( - '使用网页端登录', - style: TextStyle( - color: Theme.of(context).colorScheme.primary), - ), - ), - ), const Spacer(), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/pubspec.lock b/pubspec.lock index 406fbca4..5c6f2b43 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1218,6 +1218,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.1.0" + qr: + dependency: transitive + description: + name: qr + sha256: "64957a3930367bf97cc211a5af99551d630f2f4625e38af10edd6b19131b64b3" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + qr_flutter: + dependency: "direct main" + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.1.0" rxdart: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f02c2ead..66187abf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -145,6 +145,8 @@ dependencies: # 投屏 dlna_dart: ^0.0.8 lottie: ^3.1.2 + # 二维码 + qr_flutter: ^4.1.0 dev_dependencies: flutter_test: From aee52b02470f91db723b24a9ce2b9a6dbc573c10 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 04:09:00 +0800 Subject: [PATCH 097/106] =?UTF-8?q?opt:=20=E6=B6=88=E6=81=AF=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=A2=9E=E5=8A=A0=E9=AA=A8=E6=9E=B6=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/whisper/view.dart | 270 +++++++++++++++++++----------------- 1 file changed, 142 insertions(+), 128 deletions(-) diff --git a/lib/pages/whisper/view.dart b/lib/pages/whisper/view.dart index fa7ad60b..fa95463b 100644 --- a/lib/pages/whisper/view.dart +++ b/lib/pages/whisper/view.dart @@ -1,6 +1,7 @@ import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:pilipala/common/skeleton/skeleton.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/utils/utils.dart'; @@ -102,134 +103,83 @@ class _WhisperPageState extends State { }, child: SingleChildScrollView( controller: _scrollController, - child: Column( - children: [ - FutureBuilder( - future: _futureBuilderFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - Map? data = snapshot.data; - if (data != null && data['status']) { - RxList sessionList = _whisperController.sessionList; - return Obx( - () => sessionList.isEmpty - ? const SizedBox() - : ListView.separated( - itemCount: sessionList.length, - shrinkWrap: true, - physics: - const NeverScrollableScrollPhysics(), - itemBuilder: (_, int i) { - return ListTile( - onTap: () { - sessionList[i].unreadCount = 0; - sessionList.refresh(); - Get.toNamed( - '/whisperDetail', - parameters: { - 'talkerId': sessionList[i] - .talkerId - .toString(), - 'name': sessionList[i] - .accountInfo - .name, - 'face': sessionList[i] - .accountInfo - .face, - 'mid': sessionList[i] - .accountInfo - .mid - .toString(), - }, - ); - }, - leading: Badge( - isLabelVisible: - sessionList[i].unreadCount > 0, - label: Text(sessionList[i] - .unreadCount - .toString()), - alignment: Alignment.topRight, - child: NetworkImgLayer( - width: 45, - height: 45, - type: 'avatar', - src: sessionList[i] - .accountInfo - .face, - ), - ), - title: Text( - sessionList[i].accountInfo.name), - subtitle: Text( - sessionList[i].lastMsg.content != - null && - sessionList[i] - .lastMsg - .content != - '' - ? (sessionList[i] - .lastMsg - .content['text'] ?? - sessionList[i] - .lastMsg - .content['content'] ?? - sessionList[i] - .lastMsg - .content['title'] ?? - sessionList[i] - .lastMsg - .content[ - 'reply_content'] ?? - '不支持的消息类型') - : '不支持的消息类型', - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .labelMedium! - .copyWith( - color: Theme.of(context) - .colorScheme - .outline)), - trailing: Text( - Utils.dateFormat(sessionList[i] - .lastMsg - .timestamp), - style: Theme.of(context) - .textTheme - .labelSmall! - .copyWith( - color: Theme.of(context) - .colorScheme - .outline), - ), - ); - }, - separatorBuilder: - (BuildContext context, int index) { - return Divider( - indent: 72, - endIndent: 20, - height: 6, - color: Colors.grey.withOpacity(0.1), - ); - }, - ), - ); - } else { - // 请求错误 - return Center( - child: Text(data?['msg'] ?? '请求异常'), - ); - } - } else { - // 骨架屏 - return const SizedBox(); - } - }, - ) - ], + child: FutureBuilder( + future: _futureBuilderFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + Map? data = snapshot.data; + if (data != null && data['status']) { + RxList sessionList = _whisperController.sessionList; + return Obx( + () => sessionList.isEmpty + ? const SizedBox() + : ListView.separated( + itemCount: sessionList.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (_, int i) { + return SessionItem( + sessionItem: sessionList[i], + changeFucCall: () => + sessionList.refresh(), + ); + }, + separatorBuilder: + (BuildContext context, int index) { + return Divider( + indent: 72, + endIndent: 20, + height: 6, + color: Colors.grey.withOpacity(0.1), + ); + }, + ), + ); + } else { + // 请求错误 + return Center( + child: Text(data?['msg'] ?? '请求异常'), + ); + } + } else { + // 骨架屏 + return ListView.builder( + itemCount: 15, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, int i) { + return Skeleton( + child: ListTile( + leading: Container( + width: 45, + height: 45, + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .onInverseSurface, + borderRadius: BorderRadius.circular(25), + ), + ), + title: Container( + width: 100, + height: 14, + color: Theme.of(context) + .colorScheme + .onInverseSurface, + ), + subtitle: Container( + width: 80, + height: 14, + color: Theme.of(context) + .colorScheme + .onInverseSurface, + ), + ), + ); + }, + ); + } + }, ), ), ), @@ -239,3 +189,67 @@ class _WhisperPageState extends State { ); } } + +class SessionItem extends StatelessWidget { + final dynamic sessionItem; + final Function changeFucCall; + + const SessionItem({ + super.key, + required this.sessionItem, + required this.changeFucCall, + }); + + @override + Widget build(BuildContext context) { + final content = sessionItem.lastMsg.content; + return ListTile( + onTap: () { + sessionItem.unreadCount = 0; + changeFucCall.call(); + Get.toNamed( + '/whisperDetail', + parameters: { + 'talkerId': sessionItem.talkerId.toString(), + 'name': sessionItem.accountInfo.name, + 'face': sessionItem.accountInfo.face, + 'mid': sessionItem.accountInfo.mid.toString(), + }, + ); + }, + leading: Badge( + isLabelVisible: sessionItem.unreadCount > 0, + label: Text(sessionItem.unreadCount.toString()), + alignment: Alignment.topRight, + child: NetworkImgLayer( + width: 45, + height: 45, + type: 'avatar', + src: sessionItem.accountInfo.face, + ), + ), + title: Text(sessionItem.accountInfo.name), + subtitle: Text( + content != null && content != '' + ? (content['text'] ?? + content['content'] ?? + content['title'] ?? + content['reply_content'] ?? + '不支持的消息类型') + : '不支持的消息类型', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .labelMedium! + .copyWith(color: Theme.of(context).colorScheme.outline)), + trailing: Text( + Utils.dateFormat(sessionItem.lastMsg.timestamp), + style: Theme.of(context) + .textTheme + .labelSmall! + .copyWith(color: Theme.of(context).colorScheme.outline), + ), + ); + } +} From f4b7f77e440cbd8d51558f74312a4e4439fc1f8c Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 13:29:36 +0800 Subject: [PATCH 098/106] upgrade: new version syntax --- lib/common/widgets/http_error.dart | 2 +- lib/common/widgets/video_card_h.dart | 2 +- lib/pages/bangumi/introduction/view.dart | 8 ++++---- lib/pages/bangumi/widgets/bangumi_panel.dart | 2 +- lib/pages/dynamics/widgets/author_panel.dart | 2 +- lib/pages/fav_detail/widget/fav_video_card.dart | 2 +- lib/pages/history/widgets/item.dart | 5 ++--- lib/pages/home/view.dart | 8 ++++---- lib/pages/live_room/widgets/bottom_control.dart | 2 +- lib/pages/login/view.dart | 6 ++---- lib/pages/media/view.dart | 4 ++-- lib/pages/member/view.dart | 5 ++--- lib/pages/search_panel/widgets/video_panel.dart | 2 +- lib/pages/setting/extra_setting.dart | 6 +++--- lib/pages/setting/style_setting.dart | 6 +++--- lib/pages/setting/widgets/switch_item.dart | 6 +++--- .../video/detail/introduction/widgets/page_panel.dart | 2 +- lib/pages/video/detail/reply/widgets/reply_item.dart | 2 +- lib/pages/video/detail/reply_new/toolbar_icon_button.dart | 4 ++-- lib/pages/video/detail/reply_new/view.dart | 2 +- lib/pages/video/detail/view.dart | 2 +- lib/pages/video/detail/widgets/ai_detail.dart | 2 +- lib/pages/video/detail/widgets/header_control.dart | 8 ++++---- lib/pages/whisper_detail/view.dart | 6 +++--- lib/plugin/pl_player/view.dart | 6 +++--- lib/plugin/pl_player/widgets/common_btn.dart | 2 +- lib/plugin/pl_player/widgets/play_pause_btn.dart | 2 +- lib/utils/image_save.dart | 2 +- 28 files changed, 52 insertions(+), 56 deletions(-) diff --git a/lib/common/widgets/http_error.dart b/lib/common/widgets/http_error.dart index cbc6659b..b130faae 100644 --- a/lib/common/widgets/http_error.dart +++ b/lib/common/widgets/http_error.dart @@ -34,7 +34,7 @@ class HttpError extends StatelessWidget { fn!(); }, style: ButtonStyle( - backgroundColor: MaterialStateProperty.resolveWith((states) { + backgroundColor: WidgetStateProperty.resolveWith((states) { return Theme.of(context).colorScheme.primary.withAlpha(20); }), ), diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index 1265477f..c674b223 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -305,7 +305,7 @@ class VideoContent extends StatelessWidget { if (source == 'later') ...[ IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () => onPressedFn?.call(), icon: Icon( diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index 95d4d898..bb85be1a 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -232,11 +232,11 @@ class _BangumiInfoState extends State { height: 34, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all( - EdgeInsets.zero), + padding: + WidgetStateProperty.all(EdgeInsets.zero), backgroundColor: - MaterialStateProperty.resolveWith( - (Set states) { + WidgetStateProperty.resolveWith( + (Set states) { return t.colorScheme.primaryContainer .withOpacity(0.7); }), diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index 3df7ce25..345a47b6 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -139,7 +139,7 @@ class _BangumiPanelState extends State { height: 34, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () { widget.bangumiIntroController?.bottomSheetController = diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index 8acdc26a..e66e2a91 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -82,7 +82,7 @@ class AuthorPanel extends StatelessWidget { height: 32, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () { showModalBottomSheet( diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 79e5c073..72d7b4a0 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -217,7 +217,7 @@ class VideoContent extends StatelessWidget { bottom: -4, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () { showDialog( diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index baebfedb..8e71df6f 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -217,11 +217,10 @@ class HistoryItem extends StatelessWidget { curve: Curves.easeInOut, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( EdgeInsets.zero), backgroundColor: - MaterialStateProperty - .resolveWith( + WidgetStateProperty.resolveWith( (states) { return Colors.white .withOpacity(0.8); diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index a25389bd..0c45a262 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -278,8 +278,8 @@ class DefaultUser extends StatelessWidget { height: 38, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - backgroundColor: MaterialStateProperty.resolveWith((states) { + padding: WidgetStateProperty.all(EdgeInsets.zero), + backgroundColor: WidgetStateProperty.resolveWith((states) { return Theme.of(context).colorScheme.onInverseSurface; }), ), @@ -371,8 +371,8 @@ class CustomChip extends StatelessWidget { ), backgroundColor: secondaryContainer, selectedColor: secondaryContainer, - color: MaterialStateProperty.resolveWith( - (Set states) => secondaryContainer.withAlpha(200)), + color: WidgetStateProperty.resolveWith( + (Set states) => secondaryContainer.withAlpha(200)), padding: const EdgeInsets.fromLTRB(7, 1, 7, 1), label: Text(label, style: chipTextStyle), onPressed: () => onTap(), diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index 4dd7c538..6abb1260 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -124,7 +124,7 @@ class _BottomControlState extends State { height: 34, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () async { bool canUsePiP = false; diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index cd91ea26..ecc53af2 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -253,8 +253,7 @@ class _LoginPageState extends State { IconButton( style: ButtonStyle( backgroundColor: - MaterialStateProperty.resolveWith( - (states) { + WidgetStateProperty.resolveWith((states) { return Theme.of(context) .colorScheme .primary @@ -344,8 +343,7 @@ class _LoginPageState extends State { IconButton( style: ButtonStyle( backgroundColor: - MaterialStateProperty.resolveWith( - (states) { + WidgetStateProperty.resolveWith((states) { return Theme.of(context) .colorScheme .primary diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index cc413e59..f6a033e5 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -178,10 +178,10 @@ class _MediaPageState extends State child: Center( child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all( + padding: WidgetStateProperty.all( EdgeInsets.zero), backgroundColor: - MaterialStateProperty.resolveWith( + WidgetStateProperty.resolveWith( (states) { return Theme.of(context) .colorScheme diff --git a/lib/pages/member/view.dart b/lib/pages/member/view.dart index b6648647..bb0d92be 100644 --- a/lib/pages/member/view.dart +++ b/lib/pages/member/view.dart @@ -90,9 +90,8 @@ class _MemberPageState extends State () => Text( _memberController.memberInfo.value.name ?? '', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onBackground, + color: + Theme.of(context).colorScheme.onSurface, fontSize: 14), ), ), diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index c24a007c..3207a8ea 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -92,7 +92,7 @@ class SearchVideoPanel extends StatelessWidget { height: 32, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () => controller.onShowFilterDialog(ctr), icon: Icon( diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index aaaa8b84..885a831c 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -240,10 +240,10 @@ class _ExtraSettingState extends State { alignment: Alignment.centerRight, scale: 0.8, child: Switch( - thumbIcon: MaterialStateProperty.resolveWith( - (Set states) { + thumbIcon: WidgetStateProperty.resolveWith( + (Set states) { if (states.isNotEmpty && - states.first == MaterialState.selected) { + states.first == WidgetState.selected) { return const Icon(Icons.done); } return null; // All other states will use the default thumbIcon. diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 364eabf0..e07bef66 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -69,10 +69,10 @@ class _StyleSettingState extends State { alignment: Alignment.centerRight, scale: 0.8, child: Switch( - thumbIcon: MaterialStateProperty.resolveWith( - (Set states) { + thumbIcon: WidgetStateProperty.resolveWith( + (Set states) { if (states.isNotEmpty && - states.first == MaterialState.selected) { + states.first == WidgetState.selected) { return const Icon(Icons.done); } return null; // All other states will use the default thumbIcon. diff --git a/lib/pages/setting/widgets/switch_item.dart b/lib/pages/setting/widgets/switch_item.dart index d0c2bbf2..36c4433e 100644 --- a/lib/pages/setting/widgets/switch_item.dart +++ b/lib/pages/setting/widgets/switch_item.dart @@ -70,9 +70,9 @@ class _SetSwitchItemState extends State { alignment: Alignment.centerRight, // 缩放Switch的大小后保持右侧对齐, 避免右侧空隙过大 scale: 0.8, child: Switch( - thumbIcon: MaterialStateProperty.resolveWith( - (Set states) { - if (states.isNotEmpty && states.first == MaterialState.selected) { + thumbIcon: + WidgetStateProperty.resolveWith((Set states) { + if (states.isNotEmpty && states.first == WidgetState.selected) { return const Icon(Icons.done); } return null; // All other states will use the default thumbIcon. diff --git a/lib/pages/video/detail/introduction/widgets/page_panel.dart b/lib/pages/video/detail/introduction/widgets/page_panel.dart index 266f5566..c8111847 100644 --- a/lib/pages/video/detail/introduction/widgets/page_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/page_panel.dart @@ -106,7 +106,7 @@ class _PagesPanelState extends State { height: 34, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () { widget.videoIntroCtr.bottomSheetController = diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 55c16f7d..08e4d405 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -97,7 +97,7 @@ class ReplyItem extends StatelessWidget { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(7), - color: colorScheme.background, + color: colorScheme.surface, ), child: Icon( Icons.offline_bolt, diff --git a/lib/pages/video/detail/reply_new/toolbar_icon_button.dart b/lib/pages/video/detail/reply_new/toolbar_icon_button.dart index c4390796..bf810ce2 100644 --- a/lib/pages/video/detail/reply_new/toolbar_icon_button.dart +++ b/lib/pages/video/detail/reply_new/toolbar_icon_button.dart @@ -27,8 +27,8 @@ class ToolbarIconButton extends StatelessWidget { ? Theme.of(context).colorScheme.onSecondaryContainer : Theme.of(context).colorScheme.outline, style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - backgroundColor: MaterialStateProperty.resolveWith((states) { + padding: WidgetStateProperty.all(EdgeInsets.zero), + backgroundColor: WidgetStateProperty.resolveWith((states) { return selected ? Theme.of(context).colorScheme.secondaryContainer : null; diff --git a/lib/pages/video/detail/reply_new/view.dart b/lib/pages/video/detail/reply_new/view.dart index d7355d81..a136f623 100644 --- a/lib/pages/video/detail/reply_new/view.dart +++ b/lib/pages/video/detail/reply_new/view.dart @@ -259,7 +259,7 @@ class _VideoReplyNewDialogState extends State size: 22), label: const Text('转发到动态'), style: ButtonStyle( - foregroundColor: MaterialStateProperty.all( + foregroundColor: WidgetStateProperty.all( isForward.value ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.outline, diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index fa531684..a0f5d6bc 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -412,7 +412,7 @@ class _VideoDetailPageState extends State height: 32, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () => vdCtr.showShootDanmakuSheet(), child: diff --git a/lib/pages/video/detail/widgets/ai_detail.dart b/lib/pages/video/detail/widgets/ai_detail.dart index 197d6124..37d51106 100644 --- a/lib/pages/video/detail/widgets/ai_detail.dart +++ b/lib/pages/video/detail/widgets/ai_detail.dart @@ -108,7 +108,7 @@ class AiDetail extends StatelessWidget { fontSize: 13, color: Theme.of(context) .colorScheme - .onBackground, + .onSurface, height: 1.5, ), children: [ diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 3ff74b44..d839a1eb 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -1248,7 +1248,7 @@ class _HeaderControlState extends State { height: 34, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () => showShootDanmakuSheet(), child: const Text( @@ -1263,7 +1263,7 @@ class _HeaderControlState extends State { child: Obx( () => IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () { _.isOpenDanmu.value = !_.isOpenDanmu.value; @@ -1286,7 +1286,7 @@ class _HeaderControlState extends State { height: 34, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () async { bool canUsePiP = false; @@ -1330,7 +1330,7 @@ class _HeaderControlState extends State { height: 34, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () => showSetSpeedSheet(), child: Text( diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index 1701be33..042afca1 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -95,9 +95,9 @@ class _WhisperDetailPageState extends State height: 34, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), - backgroundColor: MaterialStateProperty.resolveWith( - (Set states) { + padding: WidgetStateProperty.all(EdgeInsets.zero), + backgroundColor: WidgetStateProperty.resolveWith( + (Set states) { return Theme.of(context) .colorScheme .primaryContainer diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 34140be8..0e405884 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -279,7 +279,7 @@ class _PLVideoPlayerState extends State widget.showEposideCb?.call(); }, style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), child: const Text( '选集', @@ -294,7 +294,7 @@ class _PLVideoPlayerState extends State child: TextButton( onPressed: () => _.toggleVideoFit(), style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), child: Obx( () => Text( @@ -311,7 +311,7 @@ class _PLVideoPlayerState extends State height: 34, child: TextButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () {}, child: Obx( diff --git a/lib/plugin/pl_player/widgets/common_btn.dart b/lib/plugin/pl_player/widgets/common_btn.dart index 5f33311c..bf9467a8 100644 --- a/lib/plugin/pl_player/widgets/common_btn.dart +++ b/lib/plugin/pl_player/widgets/common_btn.dart @@ -17,7 +17,7 @@ class ComBtn extends StatelessWidget { height: 34, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () { fuc!(); diff --git a/lib/plugin/pl_player/widgets/play_pause_btn.dart b/lib/plugin/pl_player/widgets/play_pause_btn.dart index 6cbe31f0..7547a1cb 100644 --- a/lib/plugin/pl_player/widgets/play_pause_btn.dart +++ b/lib/plugin/pl_player/widgets/play_pause_btn.dart @@ -68,7 +68,7 @@ class PlayOrPauseButtonState extends State height: 34, child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: player.playOrPause, color: Colors.white, diff --git a/lib/utils/image_save.dart b/lib/utils/image_save.dart index 0b77b7cc..0727ad68 100644 --- a/lib/utils/image_save.dart +++ b/lib/utils/image_save.dart @@ -39,7 +39,7 @@ Future imageSaveDialog(context, videoItem, closeFn) { const BorderRadius.all(Radius.circular(20))), child: IconButton( style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + padding: WidgetStateProperty.all(EdgeInsets.zero), ), onPressed: () => closeFn!(), icon: const Icon( From 897551bf237c65ec364507aa1c3d1cff865c6851 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 15:35:45 +0800 Subject: [PATCH 099/106] =?UTF-8?q?fix:=20=E7=A7=81=E4=BF=A1=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E7=B1=BB=E5=9E=8B=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../whisper_detail/widget/chat_item.dart | 203 +++++++++--------- 1 file changed, 101 insertions(+), 102 deletions(-) diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index ad11e4c3..0d37e8b3 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -259,115 +259,114 @@ class ChatItem extends StatelessWidget { ); case MsgType.auto_reply_push: return Container( - constraints: const BoxConstraints( - maxWidth: 300.0, // 设置最大宽度为200.0 + constraints: const BoxConstraints( + maxWidth: 300.0, // 设置最大宽度为200.0 + ), + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .secondaryContainer + .withOpacity(0.4), + borderRadius: const BorderRadius.all( + Radius.circular(16), ), - decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.4), - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - bottomLeft: Radius.circular(6), - bottomRight: Radius.circular(16), - ), - ), - margin: const EdgeInsets.all(12), - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - content['main_title'], - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context), - fontWeight: FontWeight.bold, - ), + ), + margin: const EdgeInsets.all(12), + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + content['main_title'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context), + fontWeight: FontWeight.bold, ), - for (var i in content['sub_cards']) ...[ - const SizedBox(height: 6), - GestureDetector( - onTap: () async { - RegExp bvRegex = RegExp(r'BV[0-9A-Za-z]{10}', - caseSensitive: false); - Iterable matches = - bvRegex.allMatches(i['jump_url']); - if (matches.isNotEmpty) { - Match match = matches.first; - String bvid = match.group(0)!; - try { - SmartDialog.showLoading(); - final int cid = await SearchHttp.ab2c(bvid: bvid); - final String heroTag = Utils.makeHeroTag(bvid); - SmartDialog.dismiss().then( - (e) => Get.toNamed( - '/video?bvid=$bvid&cid=$cid', - arguments: { - 'pic': i['cover_url'], - 'heroTag': heroTag, - }), - ); - } catch (err) { - SmartDialog.dismiss(); - SmartDialog.showToast(err.toString()); - } - } else { - SmartDialog.showToast('未匹配到 BV 号'); - Get.toNamed('/webview', - arguments: {'url': i['jump_url']}); - } - }, - child: Row( + ), + for (var i in content['sub_cards']) ...[ + const SizedBox(height: 6), + GestureDetector( + onTap: () async { + RegExp bvRegex = + RegExp(r'BV[0-9A-Za-z]{10}', caseSensitive: false); + Iterable matches = + bvRegex.allMatches(i['jump_url']); + if (matches.isNotEmpty) { + Match match = matches.first; + String bvid = match.group(0)!; + try { + SmartDialog.showLoading(); + final int cid = await SearchHttp.ab2c(bvid: bvid); + final String heroTag = Utils.makeHeroTag(bvid); + SmartDialog.dismiss().then( + (e) => Get.toNamed( + '/video?bvid=$bvid&cid=$cid', + arguments: { + 'pic': i['cover_url'], + 'heroTag': heroTag, + }), + ); + } catch (err) { + SmartDialog.dismiss(); + SmartDialog.showToast(err.toString()); + } + } else { + SmartDialog.showToast('未匹配到 BV 号'); + Get.toNamed('/webview', + arguments: {'url': i['jump_url']}); + } + }, + child: Row( + children: [ + NetworkImgLayer( + width: 130, + height: 130 * 9 / 16, + src: i['cover_url'], + ), + const SizedBox(width: 6), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - NetworkImgLayer( - width: 130, - height: 130 * 9 / 16, - src: i['cover_url'], + Text( + i['field1'], + maxLines: 2, + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context), + fontWeight: FontWeight.bold, + ), + ), + Text( + i['field2'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context).withOpacity(0.6), + fontSize: 12, + ), + ), + Text( + i['field3'], + style: TextStyle( + letterSpacing: 0.6, + height: 1.5, + color: textColor(context).withOpacity(0.6), + fontSize: 12, + ), ), - const SizedBox(width: 6), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - i['field1'], - maxLines: 2, - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context), - fontWeight: FontWeight.bold, - ), - ), - Text( - i['field2'], - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context).withOpacity(0.6), - fontSize: 12, - ), - ), - Text( - Utils.timeFormat(int.parse(i['field3'])), - style: TextStyle( - letterSpacing: 0.6, - height: 1.5, - color: textColor(context).withOpacity(0.6), - fontSize: 12, - ), - ), - ], - )), ], )), - ], + ], + ), + ), ], - )); + ], + ), + ); default: return Text( content != null && content != '' From a03d159a86b338c6ca6e7cc145cb83b86e603870 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 17:36:55 +0800 Subject: [PATCH 100/106] =?UTF-8?q?mod:=20=E5=86=85=E5=AE=B9=E5=88=86?= =?UTF-8?q?=E5=8C=BA=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/search.dart | 4 ++-- lib/pages/search/widgets/search_text.dart | 10 ++++++---- lib/pages/search_panel/controller.dart | 6 +++--- lib/pages/search_panel/widgets/video_panel.dart | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/http/search.dart b/lib/http/search.dart index 70980547..075defc7 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -75,7 +75,7 @@ class SearchHttp { required page, String? order, int? duration, - int? tid, + int? tids, }) async { var reqData = { 'search_type': searchType.type, @@ -85,7 +85,7 @@ class SearchHttp { 'page': page, if (order != null) 'order': order, if (duration != null) 'duration': duration, - if (tid != null) 'tid': tid, + if (tids != null && tids != -1) 'tids': tids, }; var res = await Request().get(Api.searchByType, data: reqData); if (res.data['code'] == 0 && res.data['data']['numPages'] > 0) { diff --git a/lib/pages/search/widgets/search_text.dart b/lib/pages/search/widgets/search_text.dart index fbd1cfc6..d3ffafea 100644 --- a/lib/pages/search/widgets/search_text.dart +++ b/lib/pages/search/widgets/search_text.dart @@ -18,10 +18,12 @@ class SearchText extends StatelessWidget { @override Widget build(BuildContext context) { return Material( - color: Theme.of(context) - .colorScheme - .surfaceContainerHighest - .withOpacity(0.5), + color: isSelect + ? Theme.of(context).colorScheme.primaryContainer + : Theme.of(context) + .colorScheme + .surfaceContainerHighest + .withOpacity(0.5), borderRadius: BorderRadius.circular(6), child: Padding( padding: EdgeInsets.zero, diff --git a/lib/pages/search_panel/controller.dart b/lib/pages/search_panel/controller.dart index 56d83601..35113198 100644 --- a/lib/pages/search_panel/controller.dart +++ b/lib/pages/search_panel/controller.dart @@ -16,8 +16,8 @@ class SearchPanelController extends GetxController { RxString order = ''.obs; // 视频时长筛选 仅用于搜索视频 RxInt duration = 0.obs; - // 视频分区筛选 仅用于搜索视频 - RxInt tid = (-1).obs; + // 视频分区筛选 仅用于搜索视频 -1时不传 + RxInt tids = (-1).obs; Future onSearch({type = 'init'}) async { var result = await SearchHttp.searchByType( @@ -26,7 +26,7 @@ class SearchPanelController extends GetxController { page: page.value, order: searchType!.type != 'video' ? null : order.value, duration: searchType!.type != 'video' ? null : duration.value, - tid: searchType!.type != 'video' ? null : tid.value, + tids: searchType!.type != 'video' ? null : tids.value, ); if (result['status']) { if (type == 'onRefresh') { diff --git a/lib/pages/search_panel/widgets/video_panel.dart b/lib/pages/search_panel/widgets/video_panel.dart index 06ee5d4b..15745bde 100644 --- a/lib/pages/search_panel/widgets/video_panel.dart +++ b/lib/pages/search_panel/widgets/video_panel.dart @@ -323,7 +323,7 @@ class VideoPanelController extends GetxController { SearchPanelController ctr = Get.find( tag: 'video${searchPanelCtr.keyword!}'); - ctr.tid.value = i['value']; + ctr.tids.value = i['value']; Get.back(); SmartDialog.showLoading(msg: '获取中'); await ctr.onRefresh(); From b37232931bc0c838b37af1cd2d6620afb0ca293b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 17:45:27 +0800 Subject: [PATCH 101/106] =?UTF-8?q?mod:=20=E9=BB=98=E8=AE=A4=E4=B8=8D?= =?UTF-8?q?=E8=B0=83=E7=94=A8=E7=94=B5=E6=B1=A0=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1a2ce989..05c0476c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,7 +17,6 @@ import 'package:pilipala/pages/search/index.dart'; import 'package:pilipala/pages/video/detail/index.dart'; import 'package:pilipala/router/app_pages.dart'; import 'package:pilipala/pages/main/view.dart'; -import 'package:pilipala/services/disable_battery_opt.dart'; import 'package:pilipala/services/service_locator.dart'; import 'package:pilipala/utils/app_scheme.dart'; import 'package:pilipala/utils/data.dart'; @@ -66,7 +65,6 @@ void main() async { } PiliSchame.init(); - DisableBatteryOpt(); } class MyApp extends StatelessWidget { From be3bffa33cee1d142d78bb7917c288ef9502ed37 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 8 Jun 2024 17:54:40 +0800 Subject: [PATCH 102/106] =?UTF-8?q?opt:=20=E6=88=91=E7=9A=84=E8=AE=A2?= =?UTF-8?q?=E9=98=85=E9=A1=B5=E9=9D=A2=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/subscription/view.dart | 31 +++++++++++++++--------- lib/pages/subscription/widgets/item.dart | 19 +++++++-------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/lib/pages/subscription/view.dart b/lib/pages/subscription/view.dart index bcc03cc3..e1d1820d 100644 --- a/lib/pages/subscription/view.dart +++ b/lib/pages/subscription/view.dart @@ -53,18 +53,25 @@ class _SubPageState extends State { if (snapshot.connectionState == ConnectionState.done) { Map? data = snapshot.data; if (data != null && data['status']) { - return Obx( - () => ListView.builder( - controller: scrollController, - itemCount: _subController.subFolderData.value.list!.length, - itemBuilder: (context, index) { - return SubItem( - subFolderItem: - _subController.subFolderData.value.list![index], - cancelSub: _subController.cancelSub); - }, - ), - ); + if (_subController.subFolderData.value.list!.isNotEmpty) { + return Obx( + () => ListView.builder( + controller: scrollController, + itemCount: _subController.subFolderData.value.list!.length, + itemBuilder: (context, index) { + return SubItem( + subFolderItem: + _subController.subFolderData.value.list![index], + cancelSub: _subController.cancelSub); + }, + ), + ); + } else { + return const CustomScrollView( + physics: NeverScrollableScrollPhysics(), + slivers: [HttpError(errMsg: '', btnText: '没有数据', fn: null)], + ); + } } else { return CustomScrollView( physics: const NeverScrollableScrollPhysics(), diff --git a/lib/pages/subscription/widgets/item.dart b/lib/pages/subscription/widgets/item.dart index 0d424611..6c1cc2b9 100644 --- a/lib/pages/subscription/widgets/item.dart +++ b/lib/pages/subscription/widgets/item.dart @@ -114,16 +114,15 @@ class VideoContent extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - SizedBox( - height: 35, - width: 35, - child: IconButton( - onPressed: () => cancelSub?.call(subFolderItem), - style: TextButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.outline, - padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), - ), - icon: const Icon(Icons.delete_outline, size: 18), + IconButton( + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + onPressed: () => cancelSub?.call(subFolderItem), + icon: Icon( + Icons.clear_outlined, + color: Theme.of(context).colorScheme.outline, + size: 18, ), ) ], From 006ba8bc59f1898f77d7c95c4a8013a861455514 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 9 Jun 2024 14:51:59 +0800 Subject: [PATCH 103/106] =?UTF-8?q?feat:=20=E4=B8=80=E9=94=AE=E4=B8=89?= =?UTF-8?q?=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Podfile.lock | 6 +- lib/models/common/action_type.dart | 1 - lib/pages/setting/pages/action_menu_set.dart | 10 +- lib/pages/setting/style_setting.dart | 10 +- .../video/detail/introduction/controller.dart | 55 ++-- lib/pages/video/detail/introduction/view.dart | 234 ++++++++++++++---- .../introduction/widgets/action_item.dart | 39 +-- lib/utils/global_data.dart | 3 +- 8 files changed, 246 insertions(+), 112 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 04fe6670..a400600f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -23,7 +23,7 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) - - gt3_flutter_plugin (0.0.8): + - gt3_flutter_plugin (0.0.9): - Flutter - GT3Captcha-iOS - GT3Captcha-iOS (0.15.8.3) @@ -171,13 +171,13 @@ SPEC CHECKSUMS: flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529 fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - gt3_flutter_plugin: bfa1f26e9a09dc00401514be5ed437f964cabf23 + gt3_flutter_plugin: 5bd2c08d3c19cbb6ee3b08f4358439e54c8ab2ee GT3Captcha-iOS: 5e3b1077834d8a9d6f4d64a447a30af3e14affe6 media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85 - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 saver_gallery: 2b4e584106fde2407ab51560f3851564963e6b78 screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625 diff --git a/lib/models/common/action_type.dart b/lib/models/common/action_type.dart index 2284df6c..b888be17 100644 --- a/lib/models/common/action_type.dart +++ b/lib/models/common/action_type.dart @@ -11,7 +11,6 @@ enum ActionType { dislike, downloadCover, copyLink, - threeAction, // backgroundPlay, // listenVideo, // downloadVideo, diff --git a/lib/pages/setting/pages/action_menu_set.dart b/lib/pages/setting/pages/action_menu_set.dart index f7d92e17..7a4fd9ba 100644 --- a/lib/pages/setting/pages/action_menu_set.dart +++ b/lib/pages/setting/pages/action_menu_set.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/models/common/action_type.dart'; +import 'package:pilipala/utils/global_data.dart'; import '../../../utils/storage.dart'; class ActionMenuSetPage extends StatefulWidget { @@ -12,14 +13,14 @@ class ActionMenuSetPage extends StatefulWidget { } class _ActionMenuSetPageState extends State { - Box settingStorage = GStrorage.setting; + Box setting = GStrorage.setting; late List actionTypeSort; late List allLabels; @override void initState() { super.initState(); - actionTypeSort = settingStorage.get(SettingBoxKey.actionTypeSort, + actionTypeSort = setting.get(SettingBoxKey.actionTypeSort, defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); allLabels = actionMenuConfig; allLabels.sort((a, b) { @@ -36,8 +37,9 @@ class _ActionMenuSetPageState extends State { .where((i) => actionTypeSort.contains((i['value'] as ActionType).value)) .map((i) => (i['value'] as ActionType).value) .toList(); - settingStorage.put(SettingBoxKey.actionTypeSort, sortedTabbar); - SmartDialog.showToast('保存成功,下次启动时生效'); + setting.put(SettingBoxKey.actionTypeSort, sortedTabbar); + GlobalData().actionTypeSort = sortedTabbar; + SmartDialog.showToast('操作成功'); } void onReorder(int oldIndex, int newIndex) { diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index 20fdada0..5fca0c86 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -289,11 +289,11 @@ class _StyleSettingState extends State { onTap: () => Get.toNamed('/navbarSetting'), title: Text('底部导航栏设置', style: titleStyle), ), - ListTile( - dense: false, - onTap: () => Get.toNamed('/actionMenuSet'), - title: Text('操作菜单设置', style: titleStyle), - ), + // ListTile( + // dense: false, + // onTap: () => Get.toNamed('/actionMenuSet'), + // title: Text('操作菜单设置', style: titleStyle), + // ), if (Platform.isAndroid) ListTile( dense: false, diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 9ed04870..9c542f21 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -38,6 +38,8 @@ class VideoIntroController extends GetxController { RxBool hasCoin = false.obs; // 是否收藏 RxBool hasFav = false.obs; + // 是否不喜欢 + RxBool hasDisLike = false.obs; Box userInfoCache = GStrorage.userInfo; bool userLogin = false; Rx favFolderData = FavFolderData().obs; @@ -153,36 +155,16 @@ class VideoIntroController extends GetxController { SmartDialog.showToast('🙏 UP已经收到了~'); return false; } - SmartDialog.show( - useSystem: true, - animationType: SmartAnimationType.centerFade_otherSlide, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('提示'), - content: const Text('一键三连 给UP送温暖'), - actions: [ - TextButton( - onPressed: () => SmartDialog.dismiss(), - child: const Text('点错了')), - TextButton( - onPressed: () async { - var result = await VideoHttp.oneThree(bvid: bvid); - if (result['status']) { - hasLike.value = result["data"]["like"]; - hasCoin.value = result["data"]["coin"]; - hasFav.value = result["data"]["fav"]; - SmartDialog.showToast('三连成功 🎉'); - } else { - SmartDialog.showToast(result['msg']); - } - SmartDialog.dismiss(); - }, - child: const Text('确认'), - ) - ], - ); - }, - ); + var result = await VideoHttp.oneThree(bvid: bvid); + print('🤣🦴:${result["data"]}'); + if (result['status']) { + hasLike.value = result["data"]["like"]; + hasCoin.value = result["data"]["coin"]; + hasFav.value = result["data"]["fav"]; + SmartDialog.showToast('三连成功'); + } else { + SmartDialog.showToast(result['msg']); + } } // (取消)点赞 @@ -193,9 +175,8 @@ class VideoIntroController extends GetxController { } var result = await VideoHttp.likeVideo(bvid: bvid, type: !hasLike.value); if (result['status']) { - // hasLike.value = result["data"] == 1 ? true : false; if (!hasLike.value) { - SmartDialog.showToast('点赞成功 👍'); + SmartDialog.showToast('点赞成功'); hasLike.value = true; videoDetail.value.stat!.like = videoDetail.value.stat!.like! + 1; } else if (hasLike.value) { @@ -215,6 +196,10 @@ class VideoIntroController extends GetxController { SmartDialog.showToast('账号未登录'); return; } + if (hasCoin.value) { + SmartDialog.showToast('已投过币了'); + return; + } showDialog( context: Get.context!, builder: (context) { @@ -236,7 +221,7 @@ class VideoIntroController extends GetxController { var res = await VideoHttp.coinVideo( bvid: bvid, multiply: _tempThemeValue); if (res['status']) { - SmartDialog.showToast('投币成功 👏'); + SmartDialog.showToast('投币成功'); hasCoin.value = true; videoDetail.value.stat!.coin = videoDetail.value.stat!.coin! + _tempThemeValue; @@ -269,7 +254,7 @@ class VideoIntroController extends GetxController { if (result['status']) { // 重新获取收藏状态 await queryHasFavVideo(); - SmartDialog.showToast('✅ 操作成功'); + SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); } @@ -299,7 +284,7 @@ class VideoIntroController extends GetxController { Get.back(); // 重新获取收藏状态 await queryHasFavVideo(); - SmartDialog.showToast('✅ 操作成功'); + SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); } diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index ceec8fa4..91287c59 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,3 +1,6 @@ +import 'dart:ffi'; + +import 'package:easy_debounce/easy_throttle.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -15,6 +18,7 @@ import 'package:pilipala/models/video_detail_res.dart'; import 'package:pilipala/pages/video/detail/introduction/controller.dart'; import 'package:pilipala/pages/video/detail/widgets/ai_detail.dart'; import 'package:pilipala/utils/feed_back.dart'; +import 'package:pilipala/utils/global_data.dart'; import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/utils.dart'; import '../../../../http/user.dart'; @@ -146,13 +150,18 @@ class _VideoInfoState extends State with TickerProviderStateMixin { RxBool isExpand = false.obs; late ExpandableController _expandableCtr; - void Function()? handleState(Future Function() action) { + // 一键三连动画 + late AnimationController _controller; + late Animation _scaleTransition; + final RxDouble _progress = 0.0.obs; + + void Function()? handleState(Future Function() action) { return isProcessing ? null : () async { - setState(() => isProcessing = true); - await action(); - setState(() => isProcessing = false); + isProcessing = true; + await action.call(); + isProcessing = false; }; } @@ -169,6 +178,25 @@ class _VideoInfoState extends State with TickerProviderStateMixin { follower = Utils.numFormat(videoIntroController.userStat['follower']); enableAi = setting.get(SettingBoxKey.enableAi, defaultValue: true); _expandableCtr = ExpandableController(initialExpanded: false); + + /// 一键三连动画 + _controller = AnimationController( + duration: const Duration(milliseconds: 1500), + reverseDuration: const Duration(milliseconds: 300), + vsync: this, + ); + _scaleTransition = Tween(begin: 0.5, end: 1.5).animate(_controller) + ..addListener(() async { + _progress.value = _scaleTransition.value - 0.5; + if (_progress.value == 1) { + if (_controller.status == AnimationStatus.completed) { + await videoIntroController.actionOneThree(); + } + _progress.value = 0; + _scaleTransition.removeListener(() {}); + _controller.stop(); + } + }); } // 收藏 @@ -249,6 +277,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { @override void dispose() { _expandableCtr.dispose(); + _controller.dispose(); + _scaleTransition.removeListener(() {}); super.dispose(); } @@ -538,6 +568,157 @@ class _VideoInfoState extends State with TickerProviderStateMixin { } Widget actionGrid(BuildContext context, videoIntroController) { + final actionTypeSort = GlobalData().actionTypeSort; + + Widget progressWidget(progress) { + return SizedBox( + width: 68, + height: 68, + child: CircularProgressIndicator( + value: progress.value, + strokeWidth: 4, + ), + ); + } + + Map menuListWidgets = { + 'like': Obx( + () { + bool likeStatus = videoIntroController.hasLike.value; + ColorScheme colorScheme = Theme.of(context).colorScheme; + return Stack( + alignment: Alignment.center, + children: [ + progressWidget(_progress), + InkWell( + onTapDown: (details) { + feedBack(); + _controller.forward(); + }, + onTapUp: (TapUpDetails details) { + if (_progress.value == 0) { + feedBack(); + EasyThrottle.throttle( + 'my-throttler', const Duration(milliseconds: 200), () { + videoIntroController.actionLikeVideo(); + }); + } + _controller.reverse(); + }, + borderRadius: StyleString.mdRadius, + child: SizedBox( + width: (Get.size.width - 24) / 5, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 4), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: + (Widget child, Animation animation) { + return ScaleTransition( + scale: animation, child: child); + }, + child: Icon( + key: ValueKey(likeStatus), + likeStatus + ? Icons.thumb_up + : Icons.thumb_up_alt_outlined, + color: likeStatus + ? colorScheme.primary + : colorScheme.outline, + ), + ), + const SizedBox(height: 6), + Text( + widget.videoDetail!.stat!.like!.toString(), + style: TextStyle( + color: likeStatus ? colorScheme.primary : null, + fontSize: + Theme.of(context).textTheme.labelSmall!.fontSize, + ), + ) + ], + ), + ), + ), + ], + ); + }, + ), + 'coin': Obx( + () => Stack( + alignment: Alignment.center, + children: [ + progressWidget(_progress), + ActionItem( + icon: Image.asset('assets/images/coin.png', width: 30), + onTap: handleState(videoIntroController.actionCoinVideo), + selectStatus: videoIntroController.hasCoin.value, + text: widget.videoDetail!.stat!.coin!.toString(), + ), + ], + ), + ), + 'collect': Obx( + () => Stack( + alignment: Alignment.center, + children: [ + progressWidget(_progress), + ActionItem( + icon: const Icon(Icons.star_border), + selectIcon: const Icon(Icons.star), + onTap: () => showFavBottomSheet(), + onLongPress: () => showFavBottomSheet(type: 'longPress'), + selectStatus: videoIntroController.hasFav.value, + text: widget.videoDetail!.stat!.favorite!.toString(), + ), + ], + ), + ), + 'watchLater': ActionItem( + icon: const Icon(Icons.watch_later_outlined), + onTap: () async { + final res = + await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid); + SmartDialog.showToast(res['msg']); + }, + selectStatus: false, + text: '稍后看', + ), + 'share': ActionItem( + icon: const Icon(Icons.share), + onTap: () => videoIntroController.actionShareVideo(), + selectStatus: false, + text: '分享', + ), + 'dislike': Obx( + () => ActionItem( + icon: const Icon(Icons.thumb_down_alt_outlined), + selectIcon: const Icon(Icons.thumb_down), + onTap: () {}, + selectStatus: videoIntroController.hasDisLike.value, + text: '不喜欢', + ), + ), + 'downloadCover': ActionItem( + icon: const Icon(Icons.image_outlined), + onTap: () {}, + selectStatus: false, + text: '下载封面', + ), + 'copyLink': ActionItem( + icon: const Icon(Icons.link_outlined), + onTap: () {}, + selectStatus: false, + text: '复制链接', + ), + }; + final List list = []; + for (var i = 0; i < actionTypeSort.length; i++) { + list.add(menuListWidgets[actionTypeSort[i]]!); + } + return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { return Container( @@ -545,50 +726,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { height: constraints.maxWidth / 5, child: ListView( scrollDirection: Axis.horizontal, - children: [ - Obx( - () => ActionItem( - icon: const Icon(Icons.thumb_up_alt_outlined), - selectIcon: const Icon(Icons.thumb_up), - onTap: handleState(videoIntroController.actionLikeVideo), - selectStatus: videoIntroController.hasLike.value, - text: widget.videoDetail!.stat!.like!.toString()), - ), - Obx( - () => ActionItem( - icon: Image.asset('assets/images/coin.png', width: 30), - onTap: handleState(videoIntroController.actionCoinVideo), - selectStatus: videoIntroController.hasCoin.value, - text: widget.videoDetail!.stat!.coin!.toString(), - ), - ), - Obx( - () => ActionItem( - icon: const Icon(Icons.star_border), - selectIcon: const Icon(Icons.star), - onTap: () => showFavBottomSheet(), - onLongPress: () => showFavBottomSheet(type: 'longPress'), - selectStatus: videoIntroController.hasFav.value, - text: widget.videoDetail!.stat!.favorite!.toString(), - ), - ), - ActionItem( - icon: const Icon(Icons.watch_later_outlined), - onTap: () async { - final res = - await UserHttp.toViewLater(bvid: widget.videoDetail!.bvid); - SmartDialog.showToast(res['msg']); - }, - selectStatus: false, - text: '稍后看', - ), - ActionItem( - icon: const Icon(Icons.share), - onTap: () => videoIntroController.actionShareVideo(), - selectStatus: false, - text: '分享', - ), - ], + children: list, ), ); }); diff --git a/lib/pages/video/detail/introduction/widgets/action_item.dart b/lib/pages/video/detail/introduction/widgets/action_item.dart index 2a89afe7..af409dfc 100644 --- a/lib/pages/video/detail/introduction/widgets/action_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_item.dart @@ -38,20 +38,29 @@ class ActionItem extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox(height: 4), - icon is Icon - ? Icon( - selectStatus ? selectIcon!.icon ?? icon!.icon : icon!.icon, - color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - ) - : Image.asset( - 'assets/images/coin.png', - width: 25, - color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - ), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + transitionBuilder: (Widget child, Animation animation) { + return ScaleTransition(scale: animation, child: child); + }, + child: icon is Icon + ? Icon( + selectStatus + ? selectIcon!.icon ?? icon!.icon + : icon!.icon, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ) + : Image.asset( + key: ValueKey(selectStatus), + 'assets/images/coin.png', + width: 25, + color: selectStatus + ? Theme.of(context).colorScheme.primary + : Theme.of(context).colorScheme.outline, + ), + ), const SizedBox(height: 6), Text( text ?? '', @@ -60,7 +69,7 @@ class ActionItem extends StatelessWidget { selectStatus ? Theme.of(context).colorScheme.primary : null, fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, ), - ) + ), ], ), ), diff --git a/lib/utils/global_data.dart b/lib/utils/global_data.dart index 29791210..97bff5a5 100644 --- a/lib/utils/global_data.dart +++ b/lib/utils/global_data.dart @@ -11,7 +11,8 @@ class GlobalData { bool enablePlayerControlAnimation = true; final bool enableMYBar = setting.get(SettingBoxKey.enableMYBar, defaultValue: true); - + List actionTypeSort = setting.get(SettingBoxKey.actionTypeSort, + defaultValue: ['like', 'coin', 'collect', 'watchLater', 'share']); // 私有构造函数 GlobalData._(); From d94ddca9056f1f00f8b2a7412a3cdcf86e07edfa Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 10 Jun 2024 00:58:04 +0800 Subject: [PATCH 104/106] =?UTF-8?q?opt:=20=E4=B8=89=E8=BF=9E=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=9D=A1=E6=A0=B7=E5=BC=8F&=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/introduction/view.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 91287c59..22f2dfe2 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -1,5 +1,3 @@ -import 'dart:ffi'; - import 'package:easy_debounce/easy_throttle.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/services.dart'; @@ -576,7 +574,7 @@ class _VideoInfoState extends State with TickerProviderStateMixin { height: 68, child: CircularProgressIndicator( value: progress.value, - strokeWidth: 4, + strokeWidth: 2, ), ); } @@ -593,6 +591,10 @@ class _VideoInfoState extends State with TickerProviderStateMixin { InkWell( onTapDown: (details) { feedBack(); + if (videoIntroController.userInfo == null) { + SmartDialog.showToast('账号未登录'); + return; + } _controller.forward(); }, onTapUp: (TapUpDetails details) { From 61c29d30829a59d189225abfc1eae830fc0d1ff4 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 10 Jun 2024 01:09:28 +0800 Subject: [PATCH 105/106] =?UTF-8?q?fix:=20=E8=B7=B3=E8=BD=AC=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/login/controller.dart | 6 +++--- lib/pages/login/view.dart | 30 +++++++++++++----------------- lib/pages/mine/controller.dart | 3 +-- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/lib/pages/login/controller.dart b/lib/pages/login/controller.dart index b5ddba16..fbb06e2f 100644 --- a/lib/pages/login/controller.dart +++ b/lib/pages/login/controller.dart @@ -31,7 +31,7 @@ class LoginPageController extends GetxController { // 倒计时60s RxInt seconds = 60.obs; - late Timer timer; + Timer? timer; RxBool smsCodeSendStatus = false.obs; // 默认密码登录 @@ -43,7 +43,7 @@ class LoginPageController extends GetxController { late int webSmsCode; RxInt validSeconds = 180.obs; - late Timer validTimer; + Timer? validTimer; late String qrcodeKey; // 监听pageView切换 @@ -329,7 +329,7 @@ class LoginPageController extends GetxController { var res = await LoginHttp.queryWebQrcodeStatus(qrcodeKey); if (res['status']) { await LoginUtils.confirmLogin('', null); - validTimer.cancel(); + validTimer?.cancel(); Get.back(); } } diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index cd91ea26..85a8adf0 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -15,8 +15,10 @@ class _LoginPageState extends State { final LoginPageController _loginPageCtr = Get.put(LoginPageController()); @override - void initState() { - super.initState(); + void dispose() { + _loginPageCtr.validTimer?.cancel(); + _loginPageCtr.timer?.cancel(); + super.dispose(); } @override @@ -51,7 +53,7 @@ class _LoginPageState extends State { }, ); }, - icon: const Icon(Icons.language), + icon: const Icon(Icons.language, size: 20), ), IconButton( tooltip: '二维码登录', @@ -90,7 +92,7 @@ class _LoginPageState extends State { Map data = snapshot.data as Map; return QrImageView( data: data['data']['url'], - backgroundColor: Colors.transparent, + backgroundColor: Colors.white, ); } else { return const Center( @@ -131,9 +133,11 @@ class _LoginPageState extends State { ); }); }, - ); + ).then((value) { + _loginPageCtr.validTimer!.cancel(); + }); }, - icon: const Icon(Icons.qr_code), + icon: const Icon(Icons.qr_code, size: 20), ), const SizedBox(width: 22), ], @@ -164,17 +168,9 @@ class _LoginPageState extends State { fontSize: 34, fontWeight: FontWeight.w500), ), - Row( - children: [ - Text( - '请使用您的 BiliBili 账号登录。', - style: Theme.of(context).textTheme.titleSmall!, - ), - GestureDetector( - onTap: () {}, - child: const Icon(Icons.info_outline, size: 16), - ) - ], + Text( + '请使用您的 BiliBili 账号登录。', + style: Theme.of(context).textTheme.titleSmall!, ), Container( margin: const EdgeInsets.only(top: 38, bottom: 15), diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index 153a7162..75c50d82 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -33,8 +33,7 @@ class MineController extends GetxController { onLogin() async { if (!userLogin.value) { - // RoutePush.loginPush(); - Get.toNamed('/loginPage'); + Get.toNamed('/loginPage', preventDuplicates: false); } else { int mid = userInfo.value.mid!; String face = userInfo.value.face!; From 51be62cd26f06364d9a8ef923ed13b874ce6c88d Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 10 Jun 2024 12:50:15 +0800 Subject: [PATCH 106/106] =?UTF-8?q?opt:=20=E4=B8=80=E9=94=AE=E4=B8=89?= =?UTF-8?q?=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/introduction/view.dart | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 22f2dfe2..3b89d1de 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -185,7 +185,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ); _scaleTransition = Tween(begin: 0.5, end: 1.5).animate(_controller) ..addListener(() async { - _progress.value = _scaleTransition.value - 0.5; + _progress.value = + double.parse((_scaleTransition.value - 0.5).toStringAsFixed(3)); if (_progress.value == 1) { if (_controller.status == AnimationStatus.completed) { await videoIntroController.actionOneThree(); @@ -570,8 +571,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { Widget progressWidget(progress) { return SizedBox( - width: 68, - height: 68, + width: 33, + height: 33, child: CircularProgressIndicator( value: progress.value, strokeWidth: 2, @@ -585,16 +586,15 @@ class _VideoInfoState extends State with TickerProviderStateMixin { bool likeStatus = videoIntroController.hasLike.value; ColorScheme colorScheme = Theme.of(context).colorScheme; return Stack( - alignment: Alignment.center, children: [ - progressWidget(_progress), + Positioned(child: progressWidget(_progress), top: 15, left: 24), InkWell( onTapDown: (details) { feedBack(); - if (videoIntroController.userInfo == null) { - SmartDialog.showToast('账号未登录'); - return; - } + // if (videoIntroController.userInfo == null) { + // SmartDialog.showToast('账号未登录'); + // return; + // } _controller.forward(); }, onTapUp: (TapUpDetails details) { @@ -650,9 +650,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), 'coin': Obx( () => Stack( - alignment: Alignment.center, children: [ - progressWidget(_progress), + Positioned(child: progressWidget(_progress), top: 15, left: 24), ActionItem( icon: Image.asset('assets/images/coin.png', width: 30), onTap: handleState(videoIntroController.actionCoinVideo), @@ -664,9 +663,8 @@ class _VideoInfoState extends State with TickerProviderStateMixin { ), 'collect': Obx( () => Stack( - alignment: Alignment.center, children: [ - progressWidget(_progress), + Positioned(child: progressWidget(_progress), top: 15, left: 24), ActionItem( icon: const Icon(Icons.star_border), selectIcon: const Icon(Icons.star),