From 71ccb9c0e51dce5437a14e7311f36b13f0f2ac8a Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 6 Feb 2024 11:01:36 +0800 Subject: [PATCH 01/17] =?UTF-8?q?fix:=20=E6=94=B6=E8=97=8F=E5=9B=BD?= =?UTF-8?q?=E5=88=9B=E8=B7=B3=E8=BD=AC=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/fav_detail/widget/fav_video_card.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index 9394fbe3a..d988a0e11 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -27,7 +27,9 @@ class FavVideoCardH extends StatelessWidget { onTap: () async { // int? seasonId; String? epId; - if (videoItem.ogv != null && videoItem.ogv['type_name'] == '番剧') { + if (videoItem.ogv != null && + (videoItem.ogv['type_name'] == '番剧' || + videoItem.ogv['type_name'] == '国创')) { videoItem.cid = await SearchHttp.ab2c(bvid: bvid); // seasonId = videoItem.ogv['season_id']; epId = videoItem.epId; From 083739e562a5ec3d40c4597d79103611f264796a Mon Sep 17 00:00:00 2001 From: guozhigq Date: Tue, 6 Feb 2024 11:13:33 +0800 Subject: [PATCH 02/17] =?UTF-8?q?mod:=20=E6=94=B6=E8=97=8F=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E5=86=85=E5=AE=B9=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fav_detail/widget/fav_video_card.dart | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index d988a0e11..a4f22f6b5 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -9,6 +9,7 @@ import 'package:pilipala/models/common/search_type.dart'; import 'package:pilipala/utils/id_utils.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import '../../../common/widgets/badge.dart'; // 收藏视频卡片 - 水平布局 class FavVideoCardH extends StatelessWidget { @@ -86,22 +87,21 @@ class FavVideoCardH extends StatelessWidget { height: maxHeight, ), ), - Positioned( - right: 4, - bottom: 4, - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 1, horizontal: 6), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(4), - color: Colors.black54.withOpacity(0.4)), - child: Text( - Utils.timeFormat(videoItem.duration!), - style: const TextStyle( - fontSize: 11, color: Colors.white), - ), + PBadge( + text: Utils.timeFormat(videoItem.duration!), + right: 6.0, + bottom: 6.0, + type: 'gray', + ), + if (videoItem.ogv != null) ...[ + PBadge( + text: videoItem.ogv['type_name'], + top: 6.0, + right: 6.0, + bottom: null, + left: null, ), - ) + ], ], ); }, @@ -143,19 +143,30 @@ class VideoContent extends StatelessWidget { maxLines: 2, overflow: TextOverflow.ellipsis, ), + if (videoItem.ogv != null) ...[ + Text( + videoItem.intro, + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: Theme.of(context).colorScheme.outline, + ), + ), + ], const Spacer(), Text( - Utils.dateFormat(videoItem.ctime!), + Utils.dateFormat(videoItem.favTime), style: TextStyle( fontSize: 11, color: Theme.of(context).colorScheme.outline), ), - Text( - videoItem.owner.name, - style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + if (videoItem.owner.name != '') ...[ + Text( + videoItem.owner.name, + style: TextStyle( + fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: Theme.of(context).colorScheme.outline, + ), ), - ), + ], Row( children: [ StatView( From d258474a5a69b75542ae040830c3cd9b7343b873 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 7 Feb 2024 22:23:29 +0800 Subject: [PATCH 03/17] =?UTF-8?q?mod:=20=E7=9B=B4=E6=92=AD=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=86=85=E5=AE=B9=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/images/live/default_bg.webp | Bin 0 -> 16312 bytes lib/http/api.dart | 4 + lib/http/live.dart | 19 +++ lib/main.dart | 2 - lib/models/live/room_info_h5.dart | 130 +++++++++++++++++++ lib/pages/live_room/controller.dart | 19 ++- lib/pages/live_room/view.dart | 193 +++++++++++++++------------- lib/plugin/pl_player/view.dart | 3 +- pubspec.yaml | 1 + 9 files changed, 279 insertions(+), 92 deletions(-) create mode 100644 assets/images/live/default_bg.webp create mode 100644 lib/models/live/room_info_h5.dart diff --git a/assets/images/live/default_bg.webp b/assets/images/live/default_bg.webp new file mode 100644 index 0000000000000000000000000000000000000000..a58259dea48887982df1f1be955cf73c489bf232 GIT binary patch literal 16312 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 json) { + roomInfo = RoomInfo.fromJson(json['room_info']); + anchorInfo = AnchorInfo.fromJson(json['anchor_info']); + isRoomFeed = json['is_room_feed']; + watchedShow = json['watched_show']; + likeInfoV3 = LikeInfoV3.fromJson(json['like_info_v3']); + blockInfo = json['block_info']; + } +} + +class RoomInfo { + RoomInfo({ + this.uid, + this.roomId, + this.title, + this.cover, + this.description, + this.liveStatus, + this.liveStartTime, + this.areaId, + this.areaName, + this.parentAreaId, + this.parentAreaName, + this.online, + this.background, + this.appBackground, + this.liveId, + }); + + int? uid; + int? roomId; + String? title; + String? cover; + String? description; + int? liveStatus; + int? liveStartTime; + int? areaId; + String? areaName; + int? parentAreaId; + String? parentAreaName; + int? online; + String? background; + String? appBackground; + String? liveId; + + RoomInfo.fromJson(Map json) { + uid = json['uid']; + roomId = json['room_id']; + title = json['title']; + cover = json['cover']; + description = json['description']; + liveStatus = json['liveS_satus']; + liveStartTime = json['live_start_time']; + areaId = json['area_id']; + areaName = json['area_name']; + parentAreaId = json['parent_area_id']; + parentAreaName = json['parent_area_name']; + online = json['online']; + background = json['background']; + appBackground = json['app_background']; + liveId = json['live_id']; + } +} + +class AnchorInfo { + AnchorInfo({ + this.baseInfo, + this.relationInfo, + }); + + BaseInfo? baseInfo; + RelationInfo? relationInfo; + + AnchorInfo.fromJson(Map json) { + baseInfo = BaseInfo.fromJson(json['base_info']); + relationInfo = RelationInfo.fromJson(json['relation_info']); + } +} + +class BaseInfo { + BaseInfo({ + this.uname, + this.face, + }); + + String? uname; + String? face; + + BaseInfo.fromJson(Map json) { + uname = json['uname']; + face = json['face']; + } +} + +class RelationInfo { + RelationInfo({this.attention}); + + int? attention; + + RelationInfo.fromJson(Map json) { + attention = json['attention']; + } +} + +class LikeInfoV3 { + LikeInfoV3({this.totalLikes}); + + int? totalLikes; + + LikeInfoV3.fromJson(Map json) { + totalLikes = json['total_likes']; + } +} diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index 2f489fec9..56da0a78b 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -4,6 +4,8 @@ import 'package:pilipala/http/live.dart'; import 'package:pilipala/models/live/room_info.dart'; import 'package:pilipala/plugin/pl_player/index.dart'; +import '../../models/live/room_info_h5.dart'; + class LiveRoomController extends GetxController { String cover = ''; late int roomId; @@ -21,6 +23,7 @@ class LiveRoomController extends GetxController { // controlsStyle: ControlsStyle.live, // enabledButtons: const EnabledButtons(pip: true), // ); + Rx roomInfoH5 = RoomInfoH5Model().obs; @override void onInit() { @@ -37,10 +40,11 @@ class LiveRoomController extends GetxController { } } queryLiveInfo(); + queryLiveInfoH5(); } - playerInit(source) { - plPlayerController.setDataSource( + playerInit(source) async { + await plPlayerController.setDataSource( DataSource( videoSource: source, audioSource: null, @@ -66,7 +70,8 @@ class LiveRoomController extends GetxController { String videoUrl = (item.urlInfo?.first.host)! + item.baseUrl! + item.urlInfo!.first.extra!; - playerInit(videoUrl); + await playerInit(videoUrl); + return res; } } @@ -80,4 +85,12 @@ class LiveRoomController extends GetxController { volumeOff.value = true; } } + + Future queryLiveInfoH5() async { + var res = await LiveHttp.liveRoomInfoH5(roomId: roomId); + if (res['status']) { + roomInfoH5.value = res['data']; + } + return res; + } } diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index 5ac382e68..f727bfd0c 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -19,6 +19,8 @@ class LiveRoomPage extends StatefulWidget { class _LiveRoomPageState extends State { final LiveRoomController _liveRoomController = Get.put(LiveRoomController()); PlPlayerController? plPlayerController; + late Future? _futureBuilder; + late Future? _futureBuilderFuture; bool isShowCover = true; bool isPlay = true; @@ -39,6 +41,8 @@ class _LiveRoomPageState extends State { if (Platform.isAndroid) { floating = Floating(); } + _futureBuilder = _liveRoomController.queryLiveInfoH5(); + _futureBuilderFuture = _liveRoomController.queryLiveInfo(); } @override @@ -52,57 +56,110 @@ class _LiveRoomPageState extends State { @override Widget build(BuildContext context) { + Widget videoPlayerPanel = FutureBuilder( + future: _futureBuilderFuture, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData && snapshot.data['status']) { + return PLVideoPlayer( + controller: plPlayerController!, + bottomControl: BottomControl( + controller: plPlayerController, + liveRoomCtr: _liveRoomController, + floating: floating, + ), + ); + } else { + return const SizedBox(); + } + }, + ); + Widget childWhenDisabled = Scaffold( primary: true, - appBar: PreferredSize( - preferredSize: Size.fromHeight( - MediaQuery.of(context).orientation == Orientation.portrait ? 56 : 0, - ), - child: AppBar( - centerTitle: false, - titleSpacing: 0, - title: _liveRoomController.liveItem != null - ? Row( - children: [ - NetworkImgLayer( - width: 34, - height: 34, - type: 'avatar', - src: _liveRoomController.liveItem.face, - ), - const SizedBox(width: 10), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _liveRoomController.liveItem.uname, - style: const TextStyle(fontSize: 14), - ), - const SizedBox(height: 1), - if (_liveRoomController.liveItem.watchedShow != null) - Text( - _liveRoomController - .liveItem.watchedShow['text_large'] ?? - '', - style: const TextStyle(fontSize: 12)), - ], - ), - ], - ) - : const SizedBox(), - // actions: [ - // SizedBox( - // height: 34, - // child: ElevatedButton(onPressed: () {}, child: const Text('关注')), - // ), - // const SizedBox(width: 12), - // ], - ), - ), - body: Column( + backgroundColor: Colors.black, + body: Stack( children: [ - Stack( + Obx( + () => + _liveRoomController.roomInfoH5.value.roomInfo?.appBackground != + '' + ? Positioned.fill( + child: Opacity( + opacity: 0.8, + child: NetworkImgLayer( + width: Get.width, + height: Get.height, + src: _liveRoomController + .roomInfoH5.value.roomInfo?.appBackground ?? + '', + ), + ), + ) + : Image.asset( + 'assets/images/live/default_bg.webp', + width: Get.width, + height: Get.height, + ), + ), + Column( children: [ + AppBar( + centerTitle: false, + titleSpacing: 0, + backgroundColor: Colors.transparent, + foregroundColor: Colors.white, + toolbarHeight: + MediaQuery.of(context).orientation == Orientation.portrait + ? 56 + : 0, + title: FutureBuilder( + future: _futureBuilder, + builder: (context, snapshot) { + if (snapshot.data == null) { + return const SizedBox(); + } + Map data = snapshot.data as Map; + if (data['status']) { + return Obx( + () => Row( + children: [ + NetworkImgLayer( + width: 34, + height: 34, + type: 'avatar', + src: _liveRoomController + .roomInfoH5.value.anchorInfo!.baseInfo!.face, + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _liveRoomController.roomInfoH5.value + .anchorInfo!.baseInfo!.uname!, + style: const TextStyle(fontSize: 14), + ), + const SizedBox(height: 1), + if (_liveRoomController + .roomInfoH5.value.watchedShow != + null) + Text( + _liveRoomController.roomInfoH5.value + .watchedShow!['text_large'] ?? + '', + style: const TextStyle(fontSize: 12), + ), + ], + ), + ], + ), + ); + } else { + return const SizedBox(); + } + }, + ), + ), PopScope( canPop: plPlayerController?.isFullScreen.value != true, onPopInvoked: (bool didPop) { @@ -120,55 +177,19 @@ class _LiveRoomPageState extends State { Orientation.landscape ? Get.size.height : Get.size.width * 9 / 16, - child: plPlayerController!.videoPlayerController != null - ? PLVideoPlayer( - controller: plPlayerController!, - bottomControl: BottomControl( - controller: plPlayerController, - liveRoomCtr: _liveRoomController, - floating: floating, - ), - ) - : const SizedBox(), + child: videoPlayerPanel, ), ), - // if (_liveRoomController.liveItem != null && - // _liveRoomController.liveItem.cover != null) - // Visibility( - // visible: isShowCover, - // child: Positioned( - // top: 0, - // left: 0, - // right: 0, - // child: NetworkImgLayer( - // type: 'emote', - // src: _liveRoomController.liveItem.cover, - // width: Get.size.width, - // height: videoHeight, - // ), - // ), - // ), ], ), ], ), ); - Widget childWhenEnabled = AspectRatio( - aspectRatio: 16 / 9, - child: plPlayerController!.videoPlayerController != null - ? PLVideoPlayer( - controller: plPlayerController!, - bottomControl: BottomControl( - controller: plPlayerController, - liveRoomCtr: _liveRoomController, - ), - ) - : const SizedBox(), - ); if (Platform.isAndroid) { return PiPSwitcher( childWhenDisabled: childWhenDisabled, - childWhenEnabled: childWhenEnabled, + childWhenEnabled: videoPlayerPanel, + floating: floating, ); } else { return childWhenDisabled; diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 3980453b6..d073945b7 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -586,6 +586,7 @@ class _PLVideoPlayerState extends State ), /// 进度条 live模式下禁用 + Obx( () { final int value = _.sliderPositionSeconds.value; @@ -609,7 +610,7 @@ class _PLVideoPlayerState extends State } if (_.videoType.value == 'live') { - return nil; + return const SizedBox(); } if (value > max || max <= 0) { return nil; diff --git a/pubspec.yaml b/pubspec.yaml index 16df4ad78..9597eab75 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -188,6 +188,7 @@ flutter: - assets/images/ - assets/images/lv/ - assets/images/logo/ + - assets/images/live/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware From c39e91073b616626d4b8109443b9d877bc1ba782 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Wed, 7 Feb 2024 22:57:30 +0800 Subject: [PATCH 04/17] =?UTF-8?q?feat:=20=E5=BA=94=E7=94=A8=E5=86=85?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/about/index.dart | 25 ++++++ lib/utils/cache_manage.dart | 154 ++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 lib/utils/cache_manage.dart diff --git a/lib/pages/about/index.dart b/lib/pages/about/index.dart index 5df05d312..0f159ce76 100644 --- a/lib/pages/about/index.dart +++ b/lib/pages/about/index.dart @@ -7,6 +7,7 @@ import 'package:pilipala/http/index.dart'; import 'package:pilipala/models/github/latest.dart'; import 'package:pilipala/utils/utils.dart'; import 'package:url_launcher/url_launcher.dart'; +import '../../utils/cache_manage.dart'; class AboutPage extends StatefulWidget { const AboutPage({super.key}); @@ -17,6 +18,19 @@ class AboutPage extends StatefulWidget { class _AboutPageState extends State { final AboutController _aboutController = Get.put(AboutController()); + String cacheSize = ''; + + @override + void initState() { + super.initState(); + // 读取缓存占用 + getCacheSize(); + } + + Future getCacheSize() async { + final res = await CacheManage().loadApplicationCache(); + setState(() => cacheSize = res); + } @override Widget build(BuildContext context) { @@ -138,6 +152,17 @@ class _AboutPageState extends State { title: const Text('错误日志'), trailing: Icon(Icons.arrow_forward_ios, size: 16, color: outline), ), + ListTile( + onTap: () async { + var cleanStatus = await CacheManage().clearCacheAll(); + if (cleanStatus) { + getCacheSize(); + } + }, + title: const Text('清除缓存'), + subtitle: Text('图片及网络缓存 $cacheSize', style: subTitleStyle), + trailing: Icon(Icons.arrow_forward_ios, size: 16, color: outline), + ), ], ), ), diff --git a/lib/utils/cache_manage.dart b/lib/utils/cache_manage.dart new file mode 100644 index 000000000..e250ab70c --- /dev/null +++ b/lib/utils/cache_manage.dart @@ -0,0 +1,154 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; + +class CacheManage { + CacheManage._internal(); + + static final CacheManage cacheManage = CacheManage._internal(); + + factory CacheManage() => cacheManage; + + // 获取缓存目录 + Future loadApplicationCache() async { + /// clear all of image in memory + // clearMemoryImageCache(); + /// get ImageCache + // var res = getMemoryImageCache(); + + // 缓存大小 + double cacheSize = 0; + // cached_network_image directory + Directory tempDirectory = await getTemporaryDirectory(); + // get_storage directory + Directory docDirectory = await getApplicationDocumentsDirectory(); + + // 获取缓存大小 + if (tempDirectory.existsSync()) { + double value = await getTotalSizeOfFilesInDir(tempDirectory); + cacheSize += value; + } + + /// 获取缓存大小 dioCache + if (docDirectory.existsSync()) { + double value = 0; + String dioCacheFileName = + '${docDirectory.path}${Platform.pathSeparator}DioCache.db'; + var dioCacheFile = File(dioCacheFileName); + if (dioCacheFile.existsSync()) { + value = await getTotalSizeOfFilesInDir(dioCacheFile); + } + cacheSize += value; + } + + return formatSize(cacheSize); + } + + // 循环计算文件的大小(递归) + Future getTotalSizeOfFilesInDir(final FileSystemEntity file) async { + if (file is File) { + int length = await file.length(); + return double.parse(length.toString()); + } + if (file is Directory) { + final List children = file.listSync(); + double total = 0; + for (final FileSystemEntity child in children) { + total += await getTotalSizeOfFilesInDir(child); + } + return total; + } + return 0; + } + + // 缓存大小格式转换 + String formatSize(double value) { + List unitArr = ['B', 'K', 'M', 'G']; + int index = 0; + while (value > 1024) { + index++; + value = value / 1024; + } + String size = value.toStringAsFixed(2); + return size + unitArr[index]; + } + + // 清除缓存 + Future clearCacheAll() async { + bool cleanStatus = await SmartDialog.show( + useSystem: true, + animationType: SmartAnimationType.centerFade_otherSlide, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('提示'), + content: const Text('该操作将清除图片及网络请求缓存数据,确认清除?'), + actions: [ + TextButton( + onPressed: (() => {SmartDialog.dismiss()}), + child: Text( + '取消', + style: TextStyle(color: Theme.of(context).colorScheme.outline), + ), + ), + TextButton( + onPressed: () async { + SmartDialog.dismiss(); + SmartDialog.showLoading(msg: '正在清除...'); + try { + // 清除缓存 图片缓存 + await clearLibraryCache(); + Timer(const Duration(milliseconds: 500), () { + SmartDialog.dismiss().then((res) { + SmartDialog.showToast('清除完成'); + }); + }); + } catch (err) { + SmartDialog.dismiss(); + SmartDialog.showToast(err.toString()); + } + }, + child: const Text('确认'), + ) + ], + ); + }, + ).then((res) { + return true; + }); + return cleanStatus; + } + + /// 清除 Documents 目录下的 DioCache.db + Future clearApplicationCache() async { + Directory directory = await getApplicationDocumentsDirectory(); + if (directory.existsSync()) { + String dioCacheFileName = + '${directory.path}${Platform.pathSeparator}DioCache.db'; + var dioCacheFile = File(dioCacheFileName); + if (dioCacheFile.existsSync()) { + dioCacheFile.delete(); + } + } + } + + // 清除 Library/Caches 目录及文件缓存 + Future clearLibraryCache() async { + var appDocDir = await getTemporaryDirectory(); + if (appDocDir.existsSync()) { + await appDocDir.delete(recursive: true); + } + } + + /// 递归方式删除目录及文件 + Future deleteDirectory(FileSystemEntity file) async { + if (file is Directory) { + final List children = file.listSync(); + for (final FileSystemEntity child in children) { + await deleteDirectory(child); + } + } + await file.delete(); + } +} From 0d5d33a365a4b103fe886865bc890ce0c9976976 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 8 Feb 2024 10:29:26 +0800 Subject: [PATCH 05/17] =?UTF-8?q?feat:=20up=E6=8A=95=E7=A8=BF=E6=8E=92?= =?UTF-8?q?=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/member_archive/controller.dart | 14 +++++--- lib/pages/member_archive/view.dart | 44 ++++++------------------ 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/lib/pages/member_archive/controller.dart b/lib/pages/member_archive/controller.dart index 785cd7647..4c41de4ca 100644 --- a/lib/pages/member_archive/controller.dart +++ b/lib/pages/member_archive/controller.dart @@ -25,7 +25,7 @@ class MemberArchiveController extends GetxController { // 获取用户投稿 Future getMemberArchive(type) async { - if (type == 'onRefresh') { + if (type == 'init') { pn = 1; } var res = await MemberHttp.memberArchive( @@ -34,7 +34,12 @@ class MemberArchiveController extends GetxController { order: currentOrder['type']!, ); if (res['status']) { - archivesList.addAll(res['data'].list.vlist); + if (type == 'init') { + archivesList.value = res['data'].list.vlist; + } + if (type == 'onLoad') { + archivesList.addAll(res['data'].list.vlist); + } count = res['data'].page['count']; pn += 1; } @@ -42,13 +47,14 @@ class MemberArchiveController extends GetxController { } toggleSort() async { - pn = 1; - int index = orderList.indexOf(currentOrder); + List typeList = orderList.map((e) => e['type']!).toList(); + int index = typeList.indexOf(currentOrder['type']!); if (index == orderList.length - 1) { currentOrder.value = orderList.first; } else { currentOrder.value = orderList[index + 1]; } + getMemberArchive('init'); } // 上拉加载 diff --git a/lib/pages/member_archive/view.dart b/lib/pages/member_archive/view.dart index 5091026e9..0b5417b4d 100644 --- a/lib/pages/member_archive/view.dart +++ b/lib/pages/member_archive/view.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; import 'package:pilipala/utils/utils.dart'; +import '../../common/constants.dart'; import 'controller.dart'; class MemberArchivePage extends StatefulWidget { @@ -48,39 +49,16 @@ class _MemberArchivePageState extends State { titleSpacing: 0, centerTitle: false, title: Text('他的投稿', style: Theme.of(context).textTheme.titleMedium), - // actions: [ - // Obx( - // () => PopupMenuButton( - // padding: EdgeInsets.zero, - // tooltip: '投稿排序', - // icon: Icon( - // Icons.more_vert_outlined, - // color: Theme.of(context).colorScheme.outline, - // ), - // position: PopupMenuPosition.under, - // onSelected: (String type) {}, - // itemBuilder: (BuildContext context) => >[ - // for (var i in _memberArchivesController.orderList) ...[ - // PopupMenuItem( - // onTap: () {}, - // value: _memberArchivesController.currentOrder['label'], - // child: Row( - // mainAxisSize: MainAxisSize.min, - // children: [ - // Text(i['label']!), - // if (_memberArchivesController.currentOrder['label'] == - // i['label']) ...[ - // const SizedBox(width: 10), - // const Icon(Icons.done, size: 20), - // ], - // ], - // ), - // ), - // ] - // ], - // ), - // ), - // ], + actions: [ + Obx( + () => TextButton.icon( + icon: const Icon(Icons.sort, size: 20), + onPressed: _memberArchivesController.toggleSort, + label: Text(_memberArchivesController.currentOrder['label']!), + ), + ), + const SizedBox(width: 6), + ], ), body: CustomScrollView( controller: _memberArchivesController.scrollController, From fb8b2de115a1ebb84a583500e5e7e0561f74922b Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 8 Feb 2024 21:27:22 +0800 Subject: [PATCH 06/17] =?UTF-8?q?feat:=20up=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/api.dart | 3 + lib/http/member.dart | 37 +++++++ lib/pages/follow/view.dart | 42 ++++++++ lib/pages/follow/widgets/follow_item.dart | 2 +- lib/pages/follow_search/controller.dart | 73 +++++++++++++ lib/pages/follow_search/index.dart | 4 + lib/pages/follow_search/view.dart | 121 ++++++++++++++++++++++ lib/router/app_pages.dart | 6 +- 8 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 lib/pages/follow_search/controller.dart create mode 100644 lib/pages/follow_search/index.dart create mode 100644 lib/pages/follow_search/view.dart diff --git a/lib/http/api.dart b/lib/http/api.dart index 532ca3419..77694de7e 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -214,6 +214,9 @@ class Api { // https://api.bilibili.com/x/relation/tags static const String followingsClass = '/x/relation/tags'; + // 搜索follow + static const followSearch = '/x/relation/followings/search'; + // 粉丝 // vmid 用户id pn 页码 ps 每页个数,最大50 order: desc // order_type 排序规则 最近访问传空,最常访问传 attention diff --git a/lib/http/member.dart b/lib/http/member.dart index bf84b6eb7..6b6df7fe3 100644 --- a/lib/http/member.dart +++ b/lib/http/member.dart @@ -461,4 +461,41 @@ class MemberHttp { }; } } + + // 搜索follow + static Future getfollowSearch({ + required int mid, + required int ps, + required int pn, + required String name, + }) async { + Map data = { + 'vmid': mid, + 'pn': pn, + 'ps': ps, + 'order': 'desc', + 'order_type': 'attention', + 'gaia_source': 'main_web', + 'name': name, + 'web_location': 333.999, + }; + Map params = await WbiSign().makSign(data); + var res = await Request().get(Api.followSearch, data: { + ...data, + 'w_rid': params['w_rid'], + 'wts': params['wts'], + }); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': FollowDataModel.fromJson(res.data['data']) + }; + } else { + return { + 'status': false, + 'data': [], + 'msg': res.data['message'], + }; + } + } } diff --git a/lib/pages/follow/view.dart b/lib/pages/follow/view.dart index a9fcab4e6..9633e7f01 100644 --- a/lib/pages/follow/view.dart +++ b/lib/pages/follow/view.dart @@ -37,6 +37,29 @@ class _FollowPageState extends State { : '${_followController.name}的关注', style: Theme.of(context).textTheme.titleMedium, ), + actions: [ + IconButton( + onPressed: () => Get.toNamed('/followSearch?mid=$mid'), + icon: const Icon(Icons.search_outlined), + ), + PopupMenuButton( + icon: const Icon(Icons.more_vert), + itemBuilder: (BuildContext context) => [ + PopupMenuItem( + onTap: () => Get.toNamed('/blackListPage'), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.block, size: 19), + SizedBox(width: 10), + Text('黑名单管理'), + ], + ), + ) + ], + ), + const SizedBox(width: 6), + ], ), body: Obx( () => !_followController.isOwner.value @@ -87,3 +110,22 @@ class _FollowPageState extends State { ); } } + +class _FakeAPI { + static const List _kOptions = [ + 'aardvark', + 'bobcat', + 'chameleon', + ]; + // Searches the options, but injects a fake "network" delay. + static Future> search(String query) async { + await Future.delayed( + const Duration(seconds: 1)); // Fake 1 second delay. + if (query == '') { + return const Iterable.empty(); + } + return _kOptions.where((String option) { + return option.contains(query.toLowerCase()); + }); + } +} diff --git a/lib/pages/follow/widgets/follow_item.dart b/lib/pages/follow/widgets/follow_item.dart index ac9cc01be..d21a89bc8 100644 --- a/lib/pages/follow/widgets/follow_item.dart +++ b/lib/pages/follow/widgets/follow_item.dart @@ -42,7 +42,7 @@ class FollowItem extends StatelessWidget { overflow: TextOverflow.ellipsis, ), dense: true, - trailing: ctr!.isOwner.value + trailing: ctr != null && ctr!.isOwner.value ? SizedBox( height: 34, child: TextButton( diff --git a/lib/pages/follow_search/controller.dart b/lib/pages/follow_search/controller.dart new file mode 100644 index 000000000..9fd1590d8 --- /dev/null +++ b/lib/pages/follow_search/controller.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/http/member.dart'; + +import '../../models/follow/result.dart'; + +class FollowSearchController extends GetxController { + Rx controller = TextEditingController().obs; + final FocusNode searchFocusNode = FocusNode(); + RxString searchKeyWord = ''.obs; + String hintText = '搜索'; + RxString loadingStatus = 'init'.obs; + late int mid = 1; + RxString uname = ''.obs; + int ps = 20; + int pn = 1; + RxList followList = [].obs; + RxInt total = 0.obs; + + @override + void onInit() { + super.onInit(); + mid = int.parse(Get.parameters['mid']!); + } + + // 清空搜索 + void onClear() { + if (searchKeyWord.value.isNotEmpty && controller.value.text != '') { + controller.value.clear(); + searchKeyWord.value = ''; + } else { + Get.back(); + } + } + + void onChange(value) { + searchKeyWord.value = value; + } + + // 提交搜索内容 + void submit() { + loadingStatus.value = 'loading'; + searchFollow(); + } + + Future searchFollow({type = 'init'}) async { + if (controller.value.text == '') { + return {'status': true, 'data': [].obs}; + } + if (type == 'init') { + ps = 1; + } + var res = await MemberHttp.getfollowSearch( + mid: mid, + ps: ps, + pn: pn, + name: controller.value.text, + ); + if (res['status']) { + if (type == 'init') { + followList.value = res['data'].list; + } else { + followList.addAll(res['data'].list); + } + total.value = res['data'].total; + } + return res; + } + + void onLoad() { + searchFollow(type: 'onLoad'); + } +} diff --git a/lib/pages/follow_search/index.dart b/lib/pages/follow_search/index.dart new file mode 100644 index 000000000..805d8c476 --- /dev/null +++ b/lib/pages/follow_search/index.dart @@ -0,0 +1,4 @@ +library follow_search; + +export './controller.dart'; +export './view.dart'; diff --git a/lib/pages/follow_search/view.dart b/lib/pages/follow_search/view.dart new file mode 100644 index 000000000..6be426767 --- /dev/null +++ b/lib/pages/follow_search/view.dart @@ -0,0 +1,121 @@ +import 'package:easy_debounce/easy_throttle.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/pages/follow_search/index.dart'; + +import '../follow/widgets/follow_item.dart'; + +class FollowSearchPage extends StatefulWidget { + const FollowSearchPage({super.key}); + + @override + State createState() => _FollowSearchPageState(); +} + +class _FollowSearchPageState extends State { + final FollowSearchController _followSearchController = + Get.put(FollowSearchController()); + late Future? _futureBuilder; + final ScrollController scrollController = ScrollController(); + + @override + void initState() { + super.initState(); + _futureBuilder = _followSearchController.searchFollow(); + scrollController.addListener( + () { + if (scrollController.position.pixels >= + scrollController.position.maxScrollExtent - 200) { + EasyThrottle.throttle( + 'my-throttler', const Duration(milliseconds: 500), () { + _followSearchController.onLoad(); + }); + } + }, + ); + } + + void reRequest() { + setState(() { + _futureBuilder = _followSearchController.searchFollow(); + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + titleSpacing: 0, + actions: [ + IconButton( + onPressed: reRequest, + icon: const Icon(CupertinoIcons.search, size: 22), + ), + const SizedBox(width: 6), + ], + title: TextField( + autofocus: true, + focusNode: _followSearchController.searchFocusNode, + controller: _followSearchController.controller.value, + textInputAction: TextInputAction.search, + onChanged: (value) => _followSearchController.onChange(value), + decoration: InputDecoration( + hintText: _followSearchController.hintText, + border: InputBorder.none, + suffixIcon: IconButton( + icon: Icon( + Icons.clear, + size: 22, + color: Theme.of(context).colorScheme.outline, + ), + onPressed: () => _followSearchController.onClear(), + ), + ), + onSubmitted: (String value) => reRequest(), + ), + ), + body: FutureBuilder( + future: _futureBuilder, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + var data = snapshot.data; + if (data == null) { + return CustomScrollView( + slivers: [ + HttpError(errMsg: snapshot.data['msg'], fn: reRequest) + ], + ); + } + if (data['status']) { + RxList followList = _followSearchController.followList; + return Obx( + () => followList.isNotEmpty + ? ListView.builder( + controller: scrollController, + itemCount: followList.length, + itemBuilder: ((context, index) { + return FollowItem( + item: followList[index], + ); + }), + ) + : CustomScrollView( + slivers: [HttpError(errMsg: '未搜索到结果', fn: reRequest)], + ), + ); + } else { + return CustomScrollView( + slivers: [ + HttpError(errMsg: snapshot.data['msg'], fn: reRequest) + ], + ); + } + } else { + return const SizedBox(); + } + }), + ); + } +} diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index ff5066301..45d7cad17 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; +import 'package:pilipala/pages/follow_search/view.dart'; import 'package:pilipala/pages/setting/pages/logs.dart'; import '../pages/about/index.dart'; @@ -104,7 +105,8 @@ class Routes { CustomGetPage( name: '/replyReply', page: () => const VideoReplyReplyPanel()), // 推荐设置 - CustomGetPage(name: '/recommendSetting', page: () => const RecommendSetting()), + CustomGetPage( + name: '/recommendSetting', page: () => const RecommendSetting()), // 播放设置 CustomGetPage(name: '/playSetting', page: () => const PlaySetting()), // 外观设置 @@ -156,6 +158,8 @@ class Routes { name: '/memberSeasons', page: () => const MemberSeasonsPage()), // 日志 CustomGetPage(name: '/logs', page: () => const LogsPage()), + // 搜索关注 + CustomGetPage(name: '/followSearch', page: () => const FollowSearchPage()), ]; } From 94f3b7c1e4797fbf04f3ee7124af5e5a50ea2481 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 8 Feb 2024 21:33:02 +0800 Subject: [PATCH 07/17] =?UTF-8?q?fix:=20minePage=20=E8=B7=AF=E7=94=B1?= =?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/mine/controller.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index d1e17a83c..5ad9e8524 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -119,7 +119,7 @@ class MineController extends GetxController { SmartDialog.showToast('账号未登录'); return; } - Get.toNamed('/follow?mid=${userInfo.value.mid}'); + Get.toNamed('/follow?mid=${userInfo.value.mid}', preventDuplicates: false); } pushFans() { @@ -127,7 +127,7 @@ class MineController extends GetxController { SmartDialog.showToast('账号未登录'); return; } - Get.toNamed('/fan?mid=${userInfo.value.mid}'); + Get.toNamed('/fan?mid=${userInfo.value.mid}', preventDuplicates: false); } pushDynamic() { @@ -135,6 +135,7 @@ class MineController extends GetxController { SmartDialog.showToast('账号未登录'); return; } - Get.toNamed('/memberDynamics?mid=${userInfo.value.mid}'); + Get.toNamed('/memberDynamics?mid=${userInfo.value.mid}', + preventDuplicates: false); } } From 10b928474bfc96ccc32fd33d0a6b3b1ad5c1eea6 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Thu, 8 Feb 2024 22:46:39 +0800 Subject: [PATCH 08/17] mod --- lib/pages/live/widgets/live_item.dart | 36 ++++++++++++------ lib/pages/live_room/view.dart | 55 +++++++++++++++++---------- 2 files changed, 59 insertions(+), 32 deletions(-) diff --git a/lib/pages/live/widgets/live_item.dart b/lib/pages/live/widgets/live_item.dart index 8fa797fb2..9218d4fbe 100644 --- a/lib/pages/live/widgets/live_item.dart +++ b/lib/pages/live/widgets/live_item.dart @@ -184,18 +184,32 @@ class VideoStat extends StatelessWidget { tileMode: TileMode.mirror, ), ), - child: RichText( - maxLines: 1, - textAlign: TextAlign.justify, - softWrap: false, - text: TextSpan( - style: const TextStyle(fontSize: 11, color: Colors.white), - children: [ - TextSpan(text: liveItem!.areaName!), - TextSpan(text: liveItem!.watchedShow!['text_small']), - ], - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + liveItem!.areaName!, + style: const TextStyle(fontSize: 11, color: Colors.white), + ), + Text( + liveItem!.watchedShow!['text_small'], + style: const TextStyle(fontSize: 11, color: Colors.white), + ), + ], ), + + // child: RichText( + // maxLines: 1, + // textAlign: TextAlign.justify, + // softWrap: false, + // text: TextSpan( + // style: const TextStyle(fontSize: 11, color: Colors.white), + // children: [ + // TextSpan(text: liveItem!.areaName!), + // TextSpan(text: liveItem!.watchedShow!['text_small']), + // ], + // ), + // ), ); } } diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index f727bfd0c..20dfe403b 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -79,27 +79,40 @@ class _LiveRoomPageState extends State { backgroundColor: Colors.black, body: Stack( children: [ - Obx( - () => - _liveRoomController.roomInfoH5.value.roomInfo?.appBackground != - '' - ? Positioned.fill( - child: Opacity( - opacity: 0.8, - child: NetworkImgLayer( - width: Get.width, - height: Get.height, - src: _liveRoomController - .roomInfoH5.value.roomInfo?.appBackground ?? - '', - ), - ), - ) - : Image.asset( - 'assets/images/live/default_bg.webp', - width: Get.width, - height: Get.height, - ), + // Obx( + // () => Positioned.fill( + // child: Opacity( + // opacity: 0.8, + // child: _liveRoomController + // .roomInfoH5.value.roomInfo?.appBackground != + // '' && + // _liveRoomController + // .roomInfoH5.value.roomInfo?.appBackground != + // null + // ? NetworkImgLayer( + // width: Get.width, + // height: Get.height, + // src: _liveRoomController + // .roomInfoH5.value.roomInfo?.appBackground ?? + // '', + // ) + // : Image.asset( + // 'assets/images/live/default_bg.webp', + // width: Get.width, + // height: Get.height, + // ), + // ), + // ), + // ), + Positioned.fill( + child: Opacity( + opacity: 0.8, + child: Image.asset( + 'assets/images/live/default_bg.webp', + width: Get.width, + height: Get.height, + ), + ), ), Column( children: [ From d0f036ec35a20f30b09b87d89cec0d813081c368 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 9 Feb 2024 09:32:28 +0800 Subject: [PATCH 09/17] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E5=9B=9E?= =?UTF-8?q?=E5=A4=8D=E5=A4=9A=E5=BC=A0=E5=9B=BE=E7=89=87=E6=8B=89=E4=BC=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/widgets/reply_item.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 7991a3666..d67782937 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -797,8 +797,7 @@ InlineSpan buildContent( ), ), ); - } - if (len > 1) { + } else if (len > 1) { List list = []; for (var i = 0; i < len; i++) { picList.add(content.pictures[i]['img_src']); @@ -816,10 +815,11 @@ InlineSpan buildContent( ); }, child: NetworkImgLayer( - src: content.pictures[i]['img_src'], - width: box.maxWidth, - height: box.maxWidth, - ), + src: content.pictures[i]['img_src'], + width: box.maxWidth, + height: box.maxWidth, + origAspectRatio: content.pictures[i]['img_width'] / + content.pictures[i]['img_height']), ); }, ), From 44a162762cc134ec2b752021d05c89096fd8f2e6 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Fri, 9 Feb 2024 23:24:26 +0800 Subject: [PATCH 10/17] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E8=B7=AF=E7=94=B1=E8=B7=B3=E8=BD=AC=20issues=20#405?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/reply/widgets/reply_item.dart | 74 +++++++++++++------ lib/utils/url_utils.dart | 61 +++++++++++++++ 2 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 lib/utils/url_utils.dart diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 7991a3666..fb76f4d45 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -1,7 +1,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.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:hive/hive.dart'; import 'package:pilipala/common/widgets/badge.dart'; @@ -12,10 +11,9 @@ 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'; - import 'zan.dart'; Box setting = GStrorage.setting; @@ -541,7 +539,6 @@ InlineSpan buildContent( // fReplyItem 父级回复内容,用作二楼回复(回复详情)展示 final content = replyItem.content; final List spanChilds = []; - bool hasMatchMember = false; // 投票 if (content.vote.isNotEmpty) { @@ -591,7 +588,7 @@ InlineSpan buildContent( if (patternStr.isNotEmpty) { patternStr += "|"; } - patternStr += r'(\b\d{1,2}[::]\d{2}\b)'; + patternStr += r'(\b\d{1,2}[::]\d{2}(?:[::]\d{2})?\b)'; final RegExp pattern = RegExp(patternStr); List matchedStrs = []; void addPlainTextSpan(str) { @@ -639,7 +636,9 @@ InlineSpan buildContent( }, ), ); - } else if (RegExp(r'^\b[0-9]{1,2}[::][0-9]{2}\b$').hasMatch(matchStr)) { + } else if (RegExp(r'^\b\d{1,2}[::]\d{2}(?:[::]\d{2})?\b$') + .hasMatch(matchStr)) { + matchStr = matchStr.replaceAll(':', ':'); spanChilds.add( TextSpan( text: ' $matchStr ', @@ -650,7 +649,6 @@ InlineSpan buildContent( ..onTap = () { // 跳转到指定位置 try { - matchStr = matchStr.replaceAll(':', ':'); SmartDialog.showToast('跳转至:$matchStr'); Get.find(tag: Get.arguments['heroTag']) .plPlayerController @@ -692,16 +690,54 @@ InlineSpan buildContent( color: Theme.of(context).colorScheme.primary, ), recognizer: TapGestureRecognizer() - ..onTap = () { + ..onTap = () async { + final String title = content.jumpUrl[matchStr]['title']; if (appUrlSchema == '') { - final String str = Uri.parse(matchStr).pathSegments[0]; - final Map matchRes = IdUtils.matchAvorBv(input: str); - final List matchKeys = matchRes.keys.toList(); - if (matchKeys.isNotEmpty) { - if (matchKeys.first == 'BV') { + final String redirectUrl = + await UrlUtils.parseRedirectUrl(matchStr); + final String pathSegment = Uri.parse(redirectUrl).path; + final String lastPathSegment = + pathSegment.split('/').last; + if (lastPathSegment.startsWith('BV')) { + UrlUtils.matchUrlPush( + lastPathSegment, + title, + redirectUrl, + ); + } else { + Get.toNamed( + '/webview', + parameters: { + 'url': redirectUrl, + 'type': 'url', + 'pageTitle': title + }, + ); + } + } else { + if (appUrlSchema.startsWith('bilibili://search')) { + Get.toNamed('/searchResult', + parameters: {'keyword': title}); + } else if (matchStr.startsWith('https://b23.tv')) { + final String redirectUrl = + await UrlUtils.parseRedirectUrl(matchStr); + final String pathSegment = Uri.parse(redirectUrl).path; + final String lastPathSegment = + pathSegment.split('/').last; + if (lastPathSegment.startsWith('BV')) { + UrlUtils.matchUrlPush( + lastPathSegment, + title, + redirectUrl, + ); + } else { Get.toNamed( - '/searchResult', - parameters: {'keyword': matchRes['BV']}, + '/webview', + parameters: { + 'url': redirectUrl, + 'type': 'url', + 'pageTitle': title + }, ); } } else { @@ -710,16 +746,10 @@ InlineSpan buildContent( parameters: { 'url': matchStr, 'type': 'url', - 'pageTitle': '' + 'pageTitle': title }, ); } - } else { - if (appUrlSchema.startsWith('bilibili://search')) { - Get.toNamed('/searchResult', parameters: { - 'keyword': content.jumpUrl[matchStr]['title'] - }); - } } }, ) diff --git a/lib/utils/url_utils.dart b/lib/utils/url_utils.dart new file mode 100644 index 000000000..bac6cdfa0 --- /dev/null +++ b/lib/utils/url_utils.dart @@ -0,0 +1,61 @@ +import 'package:dio/dio.dart'; +import 'package:get/get.dart'; + +import '../http/search.dart'; +import 'id_utils.dart'; +import 'utils.dart'; + +class UrlUtils { + // 302重定向路由截取 + static Future parseRedirectUrl(String url) async { + late String redirectUrl; + final dio = Dio(); + dio.options.followRedirects = false; + dio.options.validateStatus = (status) { + return status == 200 || status == 301 || status == 302; + }; + final response = await dio.get(url); + if (response.statusCode == 302) { + redirectUrl = response.headers['location']?.first as String; + if (redirectUrl.endsWith('/')) { + redirectUrl = redirectUrl.substring(0, redirectUrl.length - 1); + } + } else { + if (url.endsWith('/')) { + url = url.substring(0, url.length - 1); + } + return url; + } + return redirectUrl; + } + + // 匹配url路由跳转 + static matchUrlPush( + String pathSegment, + String title, + String redirectUrl, + ) async { + 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 String heroTag = Utils.makeHeroTag(bv); + await Get.toNamed( + '/video?bvid=$bv&cid=$cid', + arguments: { + 'pic': '', + 'heroTag': heroTag, + }, + ); + } else { + await Get.toNamed( + '/webview', + parameters: { + 'url': redirectUrl, + 'type': 'url', + 'pageTitle': title, + }, + ); + } + } +} From 3d5ebe7e99a1340e14618ca934d5600ee591a3b8 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 10 Feb 2024 19:57:10 +0800 Subject: [PATCH 11/17] =?UTF-8?q?fix:=20=E8=A7=86=E9=A2=91=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E9=A1=B5=E8=AF=84=E8=AE=BA=E9=87=8D=E5=A4=8D=E8=AF=B7?= =?UTF-8?q?=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/controller.dart | 3 +++ lib/pages/video/detail/reply/view.dart | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index 5781cbba2..bfcd0e809 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -53,6 +53,9 @@ class VideoReplyController extends GetxController { } Future queryReplyList({type = 'init'}) async { + if (isLoadingMore) { + return; + } isLoadingMore = true; if (type == 'init') { currentPage = 0; diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index b2c67b1e4..9b7546af2 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -75,7 +75,8 @@ class _VideoReplyPanelState extends State () { if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 300) { - EasyThrottle.throttle('replylist', const Duration(seconds: 2), () { + EasyThrottle.throttle('replylist', const Duration(milliseconds: 200), + () { _videoReplyController.onLoad(); }); } From 289cc99bc2a88cce0b0f6596a78ee0c40594bdb6 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 11 Feb 2024 09:10:45 +0800 Subject: [PATCH 12/17] mod --- lib/pages/member_archive/view.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/pages/member_archive/view.dart b/lib/pages/member_archive/view.dart index 0b5417b4d..438673235 100644 --- a/lib/pages/member_archive/view.dart +++ b/lib/pages/member_archive/view.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:pilipala/common/widgets/video_card_h.dart'; import 'package:pilipala/utils/utils.dart'; -import '../../common/constants.dart'; import 'controller.dart'; class MemberArchivePage extends StatefulWidget { @@ -26,8 +25,7 @@ class _MemberArchivePageState extends State { final String heroTag = Utils.makeHeroTag(mid); _memberArchivesController = Get.put(MemberArchiveController(), tag: heroTag); - _futureBuilderFuture = - _memberArchivesController.getMemberArchive('onRefresh'); + _futureBuilderFuture = _memberArchivesController.getMemberArchive('init'); scrollController = _memberArchivesController.scrollController; scrollController.addListener( () { From e2fd01a6d5154d3f068a60b0bbecad3420447c04 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 11 Feb 2024 18:47:51 +0800 Subject: [PATCH 13/17] =?UTF-8?q?fix:=20video=20Storage=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/main.dart | 1 - lib/utils/storage.dart | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5849f8a33..fc2149ded 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -70,7 +70,6 @@ void main() async { statusBarColor: Colors.transparent, )); Data.init(); - GStrorage.lazyInit(); PiliSchame.init(); }); } diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 1b0b0c371..41ec0ce8f 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -42,6 +42,8 @@ class GStrorage { return deletedEntries > 10; }, ); + // 视频设置 + video = await Hive.openBox('video'); } static void regAdapter() { @@ -52,11 +54,6 @@ class GStrorage { Hive.registerAdapter(HotSearchItemAdapter()); } - static Future lazyInit() async { - // 视频设置 - video = await Hive.openBox('video'); - } - static Future close() async { // user.compact(); // user.close(); From b264427be603759271d954535cfb12bfbd05eb16 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sun, 11 Feb 2024 23:07:44 +0800 Subject: [PATCH 14/17] =?UTF-8?q?fix:=20=E5=88=87=E6=8D=A2=E5=90=88?= =?UTF-8?q?=E9=9B=86=E8=AF=84=E8=AE=BA=E4=B8=8D=E5=88=B7=E6=96=B0=20issues?= =?UTF-8?q?=20#326=20#525?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/controller.dart | 6 ++++-- lib/pages/video/detail/introduction/controller.dart | 1 + lib/pages/video/detail/reply/controller.dart | 1 + lib/pages/video/detail/reply/view.dart | 11 +++++++---- lib/pages/video/detail/view.dart | 7 +++++-- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index f36eb589d..0162654f8 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -19,6 +19,7 @@ import 'package:pilipala/utils/utils.dart'; import 'package:pilipala/utils/video_utils.dart'; import 'package:screen_brightness/screen_brightness.dart'; +import '../../../utils/id_utils.dart'; import 'widgets/header_control.dart'; class VideoDetailController extends GetxController @@ -61,7 +62,7 @@ class VideoDetailController extends GetxController Box localCache = GStrorage.localCache; Box setting = GStrorage.setting; - int oid = 0; + RxInt oid = 0.obs; // 评论id 请求楼中楼评论使用 int fRpid = 0; @@ -135,13 +136,14 @@ class VideoDetailController extends GetxController defaultValue: VideoDecodeFormats.values.last.code); cacheAudioQa = setting.get(SettingBoxKey.defaultAudioQa, defaultValue: AudioQuality.hiRes.code); + oid.value = IdUtils.bv2av(Get.parameters['bvid']!); } showReplyReplyPanel() { PersistentBottomSheetController? ctr = scaffoldKey.currentState?.showBottomSheet((BuildContext context) { return VideoReplyReplyPanel( - oid: oid, + oid: oid.value, rpid: fRpid, closePanel: () => { fRpid = 0, diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index d1298fcce..fc92fb56a 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -476,6 +476,7 @@ class VideoIntroController extends GetxController { final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); videoDetailCtr.bvid = bvid; + videoDetailCtr.oid.value = aid; videoDetailCtr.cid.value = cid; videoDetailCtr.danmakuCid.value = cid; videoDetailCtr.queryVideoUrl(); diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index bfcd0e809..e564ef02e 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -59,6 +59,7 @@ class VideoReplyController extends GetxController { isLoadingMore = true; if (type == 'init') { currentPage = 0; + noMore.value = ''; } if (noMore.value == '没有更多了') { return; diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 9b7546af2..8489cbb17 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -16,11 +16,13 @@ import 'widgets/reply_item.dart'; class VideoReplyPanel extends StatefulWidget { final String? bvid; + final int? oid; final int rpid; final String? replyLevel; const VideoReplyPanel({ this.bvid, + this.oid, this.rpid = 0, this.replyLevel, super.key, @@ -48,16 +50,17 @@ class _VideoReplyPanelState extends State @override void initState() { super.initState(); - int oid = widget.bvid != null ? IdUtils.bv2av(widget.bvid!) : 0; + // int oid = widget.bvid != null ? IdUtils.bv2av(widget.bvid!) : 0; heroTag = Get.arguments['heroTag']; replyLevel = widget.replyLevel ?? '1'; if (replyLevel == '2') { _videoReplyController = Get.put( - VideoReplyController(oid, widget.rpid.toString(), replyLevel), + VideoReplyController(widget.oid, widget.rpid.toString(), replyLevel), tag: widget.rpid.toString()); } else { - _videoReplyController = - Get.put(VideoReplyController(oid, '', replyLevel), tag: heroTag); + _videoReplyController = Get.put( + VideoReplyController(widget.oid, '', replyLevel), + tag: heroTag); } fabAnimationCtr = AnimationController( diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 3644fa41d..14311cc95 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -570,8 +570,11 @@ class _VideoDetailPageState extends State ); }, ), - VideoReplyPanel( - bvid: videoDetailController.bvid, + Obx( + () => VideoReplyPanel( + bvid: videoDetailController.bvid, + oid: videoDetailController.oid.value, + ), ) ], ), From 89026e671c01b4b6d8fc686c44fa01b47c6d87dd Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 12 Feb 2024 10:07:29 +0800 Subject: [PATCH 15/17] =?UTF-8?q?mod:=20=E6=94=B6=E8=97=8F=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E7=9B=B8=E5=85=B3=20issues=20#51=20#534?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/http/video.dart | 8 +- .../fav_detail/widget/fav_video_card.dart | 172 +++++++++--------- .../video/detail/introduction/controller.dart | 5 +- 3 files changed, 99 insertions(+), 86 deletions(-) diff --git a/lib/http/video.dart b/lib/http/video.dart index d0faabaad..0df814be6 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -51,7 +51,7 @@ class VideoHttp { (i['owner'] != null && !blackMidsList.contains(i['owner']['mid']))) { RecVideoItemModel videoItem = RecVideoItemModel.fromJson(i); - if (!RecommendFilter.filter(videoItem)){ + if (!RecommendFilter.filter(videoItem)) { list.add(videoItem); } } @@ -98,7 +98,7 @@ class VideoHttp { (i['args'] != null && !blackMidsList.contains(i['args']['up_mid']))) { RecVideoItemAppModel videoItem = RecVideoItemAppModel.fromJson(i); - if (!RecommendFilter.filter(videoItem)){ + if (!RecommendFilter.filter(videoItem)) { list.add(videoItem); } } @@ -217,7 +217,7 @@ class VideoHttp { List list = []; for (var i in res.data['data']) { HotVideoItemModel videoItem = HotVideoItemModel.fromJson(i); - if (!RecommendFilter.filter(videoItem, relatedVideos: true)){ + if (!RecommendFilter.filter(videoItem, relatedVideos: true)) { list.add(videoItem); } } @@ -322,7 +322,7 @@ class VideoHttp { if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { - return {'status': false, 'data': []}; + return {'status': false, 'data': [], 'msg': res.data['message']}; } } diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index a4f22f6b5..a3c1e8e57 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -130,97 +130,107 @@ class VideoContent extends StatelessWidget { return Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(10, 2, 6, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Stack( children: [ - Text( - videoItem.title, - textAlign: TextAlign.start, - style: const TextStyle( - fontWeight: FontWeight.w500, - letterSpacing: 0.3, - ), - maxLines: 2, - overflow: TextOverflow.ellipsis, - ), - if (videoItem.ogv != null) ...[ - Text( - videoItem.intro, - style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - ], - const Spacer(), - Text( - Utils.dateFormat(videoItem.favTime), - style: TextStyle( - fontSize: 11, color: Theme.of(context).colorScheme.outline), - ), - if (videoItem.owner.name != '') ...[ - Text( - videoItem.owner.name, - style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), - ), - ], - Row( + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - StatView( - theme: 'gray', - view: videoItem.cntInfo['play'], + Text( + videoItem.title, + textAlign: TextAlign.start, + style: const TextStyle( + fontWeight: FontWeight.w500, + letterSpacing: 0.3, + ), + maxLines: 2, + overflow: TextOverflow.ellipsis, ), - const SizedBox(width: 8), - StatDanMu(theme: 'gray', danmu: videoItem.cntInfo['danmaku']), - const Spacer(), - SizedBox( - width: 26, - height: 26, - child: IconButton( - style: ButtonStyle( - padding: MaterialStateProperty.all(EdgeInsets.zero), + if (videoItem.ogv != null) ...[ + Text( + videoItem.intro, + style: TextStyle( + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, + color: Theme.of(context).colorScheme.outline, ), - onPressed: () { - showDialog( - context: Get.context!, - builder: (context) { - return AlertDialog( - title: const Text('提示'), - content: const Text('要取消收藏吗?'), - actions: [ - TextButton( - onPressed: () => Get.back(), - child: Text( - '取消', - style: TextStyle( - color: Theme.of(context) - .colorScheme - .outline), - )), - TextButton( - onPressed: () async { - await callFn!(); - Get.back(); - }, - child: const Text('确定取消'), - ) - ], - ); - }, - ); - }, - icon: Icon( - Icons.clear_outlined, + ), + ], + const Spacer(), + Text( + Utils.dateFormat(videoItem.favTime), + style: TextStyle( + fontSize: 11, + color: Theme.of(context).colorScheme.outline), + ), + if (videoItem.owner.name != '') ...[ + Text( + videoItem.owner.name, + style: TextStyle( + fontSize: + Theme.of(context).textTheme.labelMedium!.fontSize, color: Theme.of(context).colorScheme.outline, - size: 18, ), ), + ], + Padding( + padding: const EdgeInsets.only(top: 2), + child: Row( + children: [ + StatView( + theme: 'gray', + view: videoItem.cntInfo['play'], + ), + const SizedBox(width: 8), + StatDanMu( + theme: 'gray', danmu: videoItem.cntInfo['danmaku']), + const Spacer(), + ], + ), ), ], ), + Positioned( + right: 0, + bottom: -4, + child: IconButton( + style: ButtonStyle( + padding: MaterialStateProperty.all(EdgeInsets.zero), + ), + onPressed: () { + showDialog( + context: Get.context!, + builder: (context) { + return AlertDialog( + title: const Text('提示'), + content: const Text('要取消收藏吗?'), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text( + '取消', + style: TextStyle( + color: + Theme.of(context).colorScheme.outline), + )), + TextButton( + onPressed: () async { + await callFn!(); + Get.back(); + }, + child: const Text('确定取消'), + ) + ], + ); + }, + ); + }, + icon: Icon( + Icons.clear_outlined, + color: Theme.of(context).colorScheme.outline, + size: 18, + ), + ), + ), ], ), ), diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index fc92fb56a..4672b4bd0 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -298,7 +298,6 @@ class VideoIntroController extends GetxController { await queryVideoInFolder(); int defaultFolderId = favFolderData.value.list!.first.id!; int favStatus = favFolderData.value.list!.first.favState!; - print('favStatus: $favStatus'); var result = await VideoHttp.favVideo( aid: IdUtils.bv2av(bvid), addIds: favStatus == 0 ? '$defaultFolderId' : '', @@ -310,6 +309,8 @@ class VideoIntroController extends GetxController { await queryHasFavVideo(); SmartDialog.showToast('✅ 操作成功'); } + } else { + SmartDialog.showToast(result['msg']); } return; } @@ -340,6 +341,8 @@ class VideoIntroController extends GetxController { await queryHasFavVideo(); SmartDialog.showToast('✅ 操作成功'); } + } else { + SmartDialog.showToast(result['msg']); } } From 5e59db85be3ccfd7a3ee9ad6cc50c97021f507e5 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Mon, 12 Feb 2024 16:51:05 +0800 Subject: [PATCH 16/17] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E7=AC=94?= =?UTF-8?q?=E8=AE=B0=E8=B7=B3=E8=BD=AC=20issues=20#472?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/video/detail/reply/view.dart | 2 +- .../detail/reply/widgets/reply_item.dart | 55 +++++++++++++++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 8489cbb17..df8c75b14 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -114,7 +114,7 @@ class _VideoReplyPanelState extends State final VideoDetailController videoDetailCtr = Get.find(tag: heroTag); if (replyItem != null) { - videoDetailCtr.oid = replyItem.oid; + videoDetailCtr.oid.value = replyItem.oid; videoDetailCtr.fRpid = replyItem.rpid!; videoDetailCtr.firstFloor = replyItem; videoDetailCtr.showReplyReplyPanel(); diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 7991a3666..a9e1044e1 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -739,6 +739,47 @@ InlineSpan buildContent( }, ); + if (content.jumpUrl.keys.isNotEmpty) { + List unmatchedItems = content.jumpUrl.keys + .toList() + .where((item) => !content.message.contains(item)) + .toList(); + if (unmatchedItems.isNotEmpty) { + for (int i = 0; i < unmatchedItems.length; i++) { + String patternStr = unmatchedItems[i]; + spanChilds.addAll( + [ + if (content.jumpUrl[patternStr]?['prefix_icon'] != null) ...[ + WidgetSpan( + child: Image.network( + content.jumpUrl[patternStr]['prefix_icon'], + height: 19, + color: Theme.of(context).colorScheme.primary, + ), + ) + ], + TextSpan( + text: content.jumpUrl[patternStr]['title'], + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + Get.toNamed( + '/webview', + parameters: { + 'url': patternStr, + 'type': 'url', + 'pageTitle': content.jumpUrl[patternStr]['title'] + }, + ); + }, + ) + ], + ); + } + } + } // 图片渲染 if (content.pictures.isNotEmpty) { final List picList = []; @@ -753,11 +794,15 @@ InlineSpan buildContent( builder: (BuildContext context, BoxConstraints box) { double maxHeight = box.maxWidth * 0.6; // 设置最大高度 // double width = (box.maxWidth / 2).truncateToDouble(); - double height = ((box.maxWidth / - 2 * - pictureItem['img_height'] / - pictureItem['img_width'])) - .truncateToDouble(); + double height = 100; + try { + height = ((box.maxWidth / + 2 * + pictureItem['img_height'] / + pictureItem['img_width'])) + .truncateToDouble(); + } catch (_) {} + return GestureDetector( onTap: () { showDialog( From b817a0c80775c9ab5d7ca1521d98afc7e988f4da Mon Sep 17 00:00:00 2001 From: KoolShow <51787949+KoolShow@users.noreply.github.com> Date: Mon, 12 Feb 2024 17:20:18 +0800 Subject: [PATCH 17/17] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=AD=A3=E5=88=99?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=BC=8F=E4=BB=A5=E5=8C=B9=E9=85=8D=E5=90=AB?= =?UTF-8?q?=E5=B0=8F=E6=97=B6=E7=9A=84=E6=97=B6=E9=97=B4?= 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 929d9c03b..773ad3b1a 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -591,7 +591,7 @@ InlineSpan buildContent( if (patternStr.isNotEmpty) { patternStr += "|"; } - patternStr += r'(\b\d{1,2}[::]\d{2}\b)'; + patternStr += r'(\b(?:\d+[::])?[0-5]?[0-9][::][0-5]?[0-9]\b)'; final RegExp pattern = RegExp(patternStr); List matchedStrs = []; void addPlainTextSpan(str) { @@ -639,7 +639,7 @@ InlineSpan buildContent( }, ), ); - } else if (RegExp(r'^\b[0-9]{1,2}[::][0-9]{2}\b$').hasMatch(matchStr)) { + } else if (RegExp(r'^\b(?:\d+[::])?[0-5]?[0-9][::][0-5]?[0-9]\b$').hasMatch(matchStr)) { spanChilds.add( TextSpan( text: ' $matchStr ',