diff --git a/lib/common/widgets/html_render.dart b/lib/common/widgets/html_render.dart index 86c3b666e..ea0b9f460 100644 --- a/lib/common/widgets/html_render.dart +++ b/lib/common/widgets/html_render.dart @@ -36,7 +36,15 @@ Widget htmlRender({ if (isMall) { return const SizedBox.shrink(); } - + // bool inTable = + // extensionContext.element!.previousElementSibling == null || + // extensionContext.element!.nextElementSibling == null; + // imgUrl = Utils().imageUrl(imgUrl!); + // return CachedNetworkImage( + // imageUrl: imgUrl, + // width: isEmote ? 22 : null, + // height: isEmote ? 22 : null, + // ); String? clazz = attributes['class']; String? height = RegExp(r'max-height:(\d+)px') .firstMatch('${attributes['style']}') @@ -81,6 +89,7 @@ Widget htmlRender({ lineHeight: LineHeight.percent(160), letterSpacing: 0.3, ), + // 'br': Style(margin: Margins.zero, padding: HtmlPaddings.zero), 'body': Style(margin: Margins.zero, padding: HtmlPaddings.zero), 'a': Style( color: Theme.of(context).colorScheme.primary, @@ -91,6 +100,7 @@ Widget htmlRender({ ), 'p': Style( margin: Margins.only(bottom: 4), + // margin: Margins.zero, ), 'span': Style( fontSize: FontSize.large, @@ -118,6 +128,7 @@ Widget htmlRender({ 'figcaption': Style( fontSize: FontSize.large, textAlign: TextAlign.center, + // margin: Margins.only(top: 4), ), 'strong': Style(fontWeight: FontWeight.bold), 'figure': Style( diff --git a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart index d846d7809..6b00551c7 100644 --- a/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart +++ b/lib/common/widgets/interactiveviewer_gallery/interactiveviewer_gallery.dart @@ -458,6 +458,23 @@ class _InteractiveviewerGalleryState extends State imageUrl: Utils.thumbnailImgUrl(widget.sources[index].url), ); }, + // fit: BoxFit.contain, + // progressIndicatorBuilder: (context, url, progress) { + // return Center( + // child: SizedBox( + // width: 150.0, + // child: + // LinearProgressIndicator(value: progress.progress ?? 0), + // ), + // ); + // }, + // errorListener: (value) { + // WidgetsBinding.instance.addPostFrameCallback((_) { + // setState(() { + // _thumbList[index] = false; + // }); + // }); + // }, ), SourceType.livePhoto => Obx(() => currentIndex.value == index ? IgnorePointer( diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 8dbb861ba..3635811ac 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -106,6 +106,7 @@ class NetworkImgLayer extends StatelessWidget { width: width, height: height, cacheWidth: width.cacheSize(context), + // cacheHeight: height.cacheSize(context), ), ), ); diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index ac92d0722..077cd0370 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -45,6 +45,7 @@ class VideoCardV extends StatelessWidget { PageUtils.toVideoPage( 'bvid=$bvid&cid=$cid', arguments: { + // 'videoItem': videoItem, 'pic': videoItem.pic, 'heroTag': heroTag, }, @@ -57,6 +58,7 @@ class VideoCardV extends StatelessWidget { String uri = videoItem.uri!; String id = ''; if (uri.startsWith('bilibili://article/')) { + // https://www.bilibili.com/read/cv27063554 dynamicType = 'read'; RegExp regex = RegExp(r'\d+'); Match match = regex.firstMatch(uri)!; diff --git a/lib/common/widgets/video_popup_menu.dart b/lib/common/widgets/video_popup_menu.dart index e7fa3faf3..2adb6a785 100644 --- a/lib/common/widgets/video_popup_menu.dart +++ b/lib/common/widgets/video_popup_menu.dart @@ -60,6 +60,7 @@ class VideoCustomActions { Icon(MdiIcons.accountCircleOutline, size: 16), () async { Get.toNamed('/member?mid=${videoItem.owner.mid}', arguments: { + // 'face': videoItem.owner.face, 'heroTag': '${videoItem.owner.mid}', }); }, @@ -144,6 +145,8 @@ class VideoCustomActions { onPressed: () async { SmartDialog.showLoading(msg: '正在提交'); var res = await VideoHttp.feedDislikeCancel( + // reasonId: r?.id, + // feedbackId: f?.id, id: v.param!, goto: v.goto!, ); diff --git a/lib/http/msg.dart b/lib/http/msg.dart index 185458aa2..96acac1d1 100644 --- a/lib/http/msg.dart +++ b/lib/http/msg.dart @@ -556,5 +556,36 @@ class MsgHttp { static String getDevId() { return Uuid().v4(); + // final List b = [ + // '0', + // '1', + // '2', + // '3', + // '4', + // '5', + // '6', + // '7', + // '8', + // '9', + // 'A', + // 'B', + // 'C', + // 'D', + // 'E', + // 'F' + // ]; + // final List s = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".split(''); + // for (int i = 0; i < s.length; i++) { + // if ('-' == s[i] || '4' == s[i]) { + // continue; + // } + // final int randomInt = Random().nextInt(16); + // if ('x' == s[i]) { + // s[i] = b[randomInt]; + // } else { + // s[i] = b[3 & randomInt | 8]; + // } + // } + // return s.join(); } } diff --git a/lib/http/user.dart b/lib/http/user.dart index 75b5d1dd9..3476eef1f 100644 --- a/lib/http/user.dart +++ b/lib/http/user.dart @@ -418,6 +418,30 @@ class UserHttp { return {'status': false, 'msg': res.data['message']}; } } + // // 相互关系查询 + // static Future relationSearch(int mid) async { + // Map params = await WbiSign.makSign({ + // 'mid': mid, + // 'token': '', + // 'platform': 'web', + // 'web_location': 1550101, + // }); + // var res = await Request().get( + // Api.relationSearch, + // data: { + // 'mid': mid, + // 'w_rid': params['w_rid'], + // 'wts': params['wts'], + // }, + // ); + // if (res.data['code'] == 0) { + // // relation 主动状态 + // // 被动状态 + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'msg': res.data['message']}; + // } + // } // 搜索历史记录 static Future> searchHistory( diff --git a/lib/http/video.dart b/lib/http/video.dart index f0f58c912..b45d8de2b 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -24,6 +24,9 @@ import 'api.dart'; import 'init.dart'; import 'login.dart'; +/// res.data['code'] == 0 请求正常返回结果 +/// res.data['data'] 为结果 +/// 返回{'status': bool, 'data': List} /// view层根据 status 判断渲染逻辑 class VideoHttp { static bool enableRcmdDynamic = @@ -371,6 +374,28 @@ class VideoHttp { } } + // 获取点赞状态 + // static Future hasLikeVideo({required String bvid}) async { + // var res = + // await Request().get(Api.hasLikeVideo, queryParameters: {'bvid': bvid}); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'msg': res.data['message']}; + // } + // } + + // 获取投币状态 + // static Future hasCoinVideo({required String bvid}) async { + // var res = + // await Request().get(Api.hasCoinVideo, queryParameters: {'bvid': bvid}); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'msg': res.data['message']}; + // } + // } + // 投币 static Future coinVideo({ required String bvid, @@ -395,6 +420,17 @@ class VideoHttp { } } + // 获取收藏状态 + // static Future hasFavVideo({required int aid}) async { + // var res = + // await Request().get(Api.hasFavVideo, queryParameters: {'aid': aid}); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'msg': res.data['message']}; + // } + // } + // 一键三连 bangumi static Future triple({dynamic epId, required dynamic seasonId}) async { var res = await Request().post( @@ -456,6 +492,11 @@ class VideoHttp { 'like': type ? '0' : '1', }, options: Options(contentType: Headers.formUrlEncodedContentType), + // queryParameters: { + // 'bvid': bvid, + // 'like': type ? 1 : 2, + // 'csrf': Accounts.main.csrf, + // }, ); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; @@ -500,6 +541,7 @@ class VideoHttp { var res = await Request().get(Api.feedDislike, queryParameters: { 'goto': goto, 'id': id, + // 'mid': mid, if (reasonId != null) 'reason_id': reasonId, if (feedbackId != null) 'feedback_id': feedbackId, 'build': '1', @@ -521,9 +563,11 @@ class VideoHttp { if (Accounts.get(AccountType.recommend).accessKey.isNullOrEmpty) { return {'status': false, 'msg': "请退出账号后重新登录"}; } + // assert ((reasonId != null) ^ (feedbackId != null)); var res = await Request().get(Api.feedDislikeCancel, queryParameters: { 'goto': goto, 'id': id, + // 'mid': mid, if (reasonId != null) 'reason_id': reasonId, if (feedbackId != null) 'feedback_id': feedbackId, 'build': '1', @@ -583,6 +627,33 @@ class VideoHttp { } } + // (取消)收藏 bangumi + // static Future favBangumi({ + // required dynamic epId, + // String? addIds, + // String? delIds, + // }) async { + // var res = await Request().post( + // Api.favBangumi, + // data: { + // 'resources': '$epId:24', + // 'add_media_ids': addIds ?? '', + // 'del_media_ids': delIds ?? '', + // 'csrf': Accounts.main.csrf, + // }, + // options: Options( + // headers: { + // 'Content-Type': Headers.formUrlEncodedContentType, + // }, + // ), + // ); + // if (res.data['code'] == 0) { + // return {'status': true, 'data': res.data['data']}; + // } else { + // return {'status': false, 'msg': res.data['message']}; + // } + // } + static Future copyOrMoveFav({ required bool isCopy, required bool isFav, @@ -782,6 +853,7 @@ class VideoHttp { subType, }) async { await Request().post(Api.heartBeat, queryParameters: { + // 'aid': aid, 'bvid': bvid, 'cid': cid, if (epid != null) 'epid': epid, @@ -917,10 +989,26 @@ class VideoHttp { ); if (res.data['code'] == 0) { dynamic data = res.data['data']; + /* + [ + { + "id": 1430455228267894300, + "lan": "ai-zh", + "lan_doc": "中文(自动生成)", + "is_lock": false, + "subtitle_url": "//aisubtitle.hdslb.com/bfs/ai_subtitle/prod/15508958271448462983dacf99a49f40ccdf91a4df8d925e2b58?auth_key=1708941835-aaa0e44844594386ad356795733983a2-0-89af73c6aad5a1fca43b02113fa9d485", + "type": 1, + "id_str": "1430455228267894272", + "ai_type": 0, + "ai_status": 2 + } + ] + */ return { 'status': true, 'subtitles': data['subtitle']['subtitles'], 'view_points': data['view_points'], + // 'last_play_time': data['last_play_time'], 'last_play_cid': data['last_play_cid'], 'interaction': data['interaction'], }; diff --git a/lib/models/user/fav_detail.dart b/lib/models/user/fav_detail.dart index 01a8f4306..ebef6c5bd 100644 --- a/lib/models/user/fav_detail.dart +++ b/lib/models/user/fav_detail.dart @@ -62,4 +62,7 @@ class FavDetailItemData extends BaseVideoItemModel with MultiSelectData { static final _digitRegExp = RegExp(r'\d+'); String resolveEpId(String url) => _digitRegExp.firstMatch(url)!.group(0)!; + + // @override + // bool isFollowed; } diff --git a/lib/models/video/play/quality.dart b/lib/models/video/play/quality.dart index e41faa9c4..34cb858d3 100644 --- a/lib/models/video/play/quality.dart +++ b/lib/models/video/play/quality.dart @@ -59,6 +59,7 @@ extension VideoQualityDesc on VideoQuality { String get description => _descList[index]; } +/// enum AudioQuality { k64, k132, k192, dolby, hiRes } extension AudioQualityCode on AudioQuality { diff --git a/lib/models/video/play/url.dart b/lib/models/video/play/url.dart index 268e709b3..4a6ed23f1 100644 --- a/lib/models/video/play/url.dart +++ b/lib/models/video/play/url.dart @@ -16,6 +16,7 @@ class PlayUrlModel { this.seekType, this.dash, this.supportFormats, + // this.highFormat, this.lastPlayTime, this.lastPlayCid, }); @@ -35,6 +36,7 @@ class PlayUrlModel { Dash? dash; List? durl; List? supportFormats; + // String? highFormat; int? lastPlayTime; int? lastPlayCid; @@ -173,9 +175,8 @@ class VideoItem { baseUrl = json['baseUrl']; var backupUrls = json['backupUrl']?.toList() ?? []; backupUrl = backupUrls.isNotEmpty - ? backupUrls.firstWhere((i) => !_isMCDNorPCDN(i), - orElse: () => backupUrls.first) - : ''; + ? backupUrls.firstWhere((i) => !_isMCDNorPCDN(i), orElse: () => backupUrls.first) + : ''; bandWidth = json['bandWidth']; mimeType = json['mime_type']; codecs = json['codecs']; @@ -247,9 +248,8 @@ class AudioItem { baseUrl = json['baseUrl']; var backupUrls = json['backupUrl']?.toList() ?? []; backupUrl = backupUrls.isNotEmpty - ? backupUrls.firstWhere((i) => !_isMCDNorPCDN(i), - orElse: () => backupUrls.first) - : ''; + ? backupUrls.firstWhere((i) => !_isMCDNorPCDN(i), orElse: () => backupUrls.first) + : ''; bandWidth = json['bandWidth']; mimeType = json['mime_type']; codecs = json['codecs']; diff --git a/lib/pages/about/index.dart b/lib/pages/about/index.dart index 66885b077..d47315187 100644 --- a/lib/pages/about/index.dart +++ b/lib/pages/about/index.dart @@ -254,6 +254,14 @@ Commit Hash: ${BuildConfig.commitHash}''', Get.back(); String res = jsonEncode(Accounts.account.toMap()); Utils.copyText(res); + // if (context.mounted) { + // showDialog( + // context: context, + // builder: (context) => AlertDialog( + // content: SelectableText('$res'), + // ), + // ); + // } }, ), ListTile( diff --git a/lib/pages/bangumi/introduction/controller.dart b/lib/pages/bangumi/introduction/controller.dart index 3f2e98a74..be172827b 100644 --- a/lib/pages/bangumi/introduction/controller.dart +++ b/lib/pages/bangumi/introduction/controller.dart @@ -103,6 +103,7 @@ class BangumiIntroController var result = await UserHttp.videoTags(bvid: bvid); if (result['status']) { videoTags = result['data']; + // debugPrint('tags: ${result['data']}'); } } @@ -561,6 +562,10 @@ class BangumiIntroController scriptContent['props']['pageProps']['followState']['isFollowed']; followStatus.value = scriptContent['props']['pageProps']['followState']['followStatus']; + // int progress = scriptContent['props']['pageProps']['dehydratedState'] + // ['queries'][0]['state']['data']['result'] + // ['play_view_business_info']['user_status']['watch_progress'] + // ['current_watch_progress']; } } catch (_) {} } diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index 05e14aaaf..26251ecfa 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -394,6 +394,16 @@ class _BangumiInfoState extends State { ], ), const SizedBox(height: 6), + // 点赞收藏转发 布局样式1 + // SingleChildScrollView( + // padding: const EdgeInsets.only(top: 7, bottom: 7), + // scrollDirection: Axis.horizontal, + // child: actionRow( + // context, + // bangumiIntroController, + // videoDetailCtr, + // ), + // ), // 点赞收藏转发 布局样式2 actionGrid(context, bangumiIntroController), // 番剧分p diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index 863abec71..3d497db53 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -68,8 +68,24 @@ class _BangumiPanelState extends State { super.dispose(); } + // void changeFucCall(item, i) async { + // if (item.badge != null && item.badge == '会员' && vipStatus != 1) { + // SmartDialog.showToast('需要大会员'); + // return; + // } + // await widget.changeFuc!( + // item.bvid, + // item.cid, + // item.aid, + // ); + // currentIndex = i; + // setState(() {}); + // scrollToIndex(); + // } + void scrollToIndex() { WidgetsBinding.instance.addPostFrameCallback((_) { + // 在回调函数中获取更新后的状态 listViewScrollCtr.animateTo( (currentIndex * 150.0).clamp(listViewScrollCtr.position.minScrollExtent, listViewScrollCtr.position.maxScrollExtent), @@ -132,12 +148,11 @@ class _BangumiPanelState extends State { scrollDirection: Axis.horizontal, itemCount: widget.pages.length, itemExtent: 150, - itemBuilder: (BuildContext context, int index) { - final item = widget.pages[index]; + itemBuilder: (BuildContext context, int i) { return Container( width: 150, margin: EdgeInsets.only( - right: index == widget.pages.length - 1 ? 0 : 10, + right: i == widget.pages.length - 1 ? 0 : 10, ), child: Material( color: Theme.of(context).colorScheme.onInverseSurface, @@ -145,19 +160,24 @@ class _BangumiPanelState extends State { clipBehavior: Clip.hardEdge, child: InkWell( onTap: () { - if (item.badge != null && - item.badge == '会员' && + if (widget.pages[i].badge != null && + widget.pages[i].badge == '会员' && vipStatus != 1) { SmartDialog.showToast('需要大会员'); + // return; } widget.changeFuc( - item.epId, - item.bvid, - item.cid, - item.aid, - item.cover, + widget.pages[i].epId, + widget.pages[i].bvid, + widget.pages[i].cid, + widget.pages[i].aid, + widget.pages[i].cover, ); + // currentIndex = i; + // setState(() {}); + // scrollToIndex(); }, + //changeFucCall(widget.pages[i], i), child: Padding( padding: const EdgeInsets.symmetric( vertical: 8, horizontal: 10), @@ -166,7 +186,7 @@ class _BangumiPanelState extends State { children: [ Row( children: [ - if (index == currentIndex) ...[ + if (i == currentIndex) ...[ Image.asset( 'assets/images/live.png', color: Theme.of(context).colorScheme.primary, @@ -177,32 +197,32 @@ class _BangumiPanelState extends State { ], Expanded( child: Text( - item.title ?? '第${index + 1}话', - maxLines: (item.longTitle != null && - item.longTitle != '') + widget.pages[i].title ?? '第${i + 1}话', + maxLines: (widget.pages[i].longTitle != null && + widget.pages[i].longTitle != '') ? 1 : 2, style: TextStyle( fontSize: 13, - color: index == currentIndex + color: i == currentIndex ? Theme.of(context).colorScheme.primary : Theme.of(context) .colorScheme .onSurface), )), const SizedBox(width: 2), - if (item.badge != null) ...[ + if (widget.pages[i].badge != null) ...[ const Spacer(), - if (item.badge == '会员') ...[ + if (widget.pages[i].badge == '会员') ...[ Image.asset( 'assets/images/big-vip.png', height: 16, semanticLabel: "大会员", ), ], - if (item.badge != '会员') ...[ + if (widget.pages[i].badge != '会员') ...[ Text( - item.badge!, + widget.pages[i].badge!, style: TextStyle( fontSize: 11, color: @@ -213,15 +233,15 @@ class _BangumiPanelState extends State { ] ], ), - if (item.longTitle != null && - item.longTitle != '') ...[ + if (widget.pages[i].longTitle != null && + widget.pages[i].longTitle != '') ...[ const SizedBox(height: 3), Text( - item.longTitle!, + widget.pages[i].longTitle!, maxLines: 1, style: TextStyle( fontSize: 13, - color: index == currentIndex + color: i == currentIndex ? Theme.of(context).colorScheme.primary : Theme.of(context) .colorScheme diff --git a/lib/pages/danmaku_block/view.dart b/lib/pages/danmaku_block/view.dart index 27a88d607..545da3fcf 100644 --- a/lib/pages/danmaku_block/view.dart +++ b/lib/pages/danmaku_block/view.dart @@ -70,6 +70,7 @@ class _DanmakuBlockPageState extends State { TextField( controller: textController, autofocus: true, + //decoration: InputDecoration(hintText: hintText), ) ]), actions: [ diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart index 5d89c16bc..12dc339cf 100644 --- a/lib/pages/dynamics/controller.dart +++ b/lib/pages/dynamics/controller.dart @@ -70,6 +70,7 @@ class DynamicsController extends GetxController Future queryFollowing2() async { if (upData.value.upList != null && upData.value.upList!.length >= allFollowedUpsTotal) { + // SmartDialog.showToast('没有更多了'); return; } var res = await FollowHttp.followings( @@ -186,6 +187,7 @@ class DynamicsController extends GetxController await controller.onRefresh(); } + // 返回顶部并刷新 @override void animateToTop() async { controller.animateToTop(); diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index 839f63e85..5a8d18320 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -31,6 +31,7 @@ import '../../../utils/grid.dart'; import '../widgets/dynamic_panel.dart'; class DynamicDetailPage extends StatefulWidget { + // const DynamicDetailPage({super.key}); const DynamicDetailPage({super.key}); @override @@ -42,6 +43,7 @@ class _DynamicDetailPageState extends State late DynamicDetailController _dynamicDetailController; AnimationController? _fabAnimationCtr; final RxBool _visibleTitle = false.obs; + // String? action; // 回复类型 late int replyType; bool _isFabVisible = true; @@ -122,6 +124,8 @@ class _DynamicDetailPageState extends State Map args = Get.arguments; // 楼层 int floor = args['floor']; + // 从action栏点击进入 + // action = args.containsKey('action') ? args['action'] : null; // 评论类型 int commentType = args['item'].basic!['comment_type'] ?? 11; replyType = (commentType == 0) ? 11 : commentType; diff --git a/lib/pages/dynamics/tab/view.dart b/lib/pages/dynamics/tab/view.dart index 402a66489..629785a1a 100644 --- a/lib/pages/dynamics/tab/view.dart +++ b/lib/pages/dynamics/tab/view.dart @@ -144,7 +144,10 @@ class _DynamicsTabPageState sliver: dynamicsWaterfallFlow ? SliverWaterfallFlow.extent( maxCrossAxisExtent: Grid.smallCardWidth * 2, + //cacheExtent: 0.0, crossAxisSpacing: StyleString.cardSpace / 2, + // mainAxisSpacing: StyleString.cardSpace / 2, + lastChildLayoutTypeBuilder: (index) { if (index == loadingState.response!.length - 1) { controller.onLoadMore(); @@ -160,6 +163,7 @@ class _DynamicsTabPageState DynamicPanel( item: i, onRemove: controller.onRemove, + // onSetTop: controller.onSetTop, ), ] else ...[ for (var i in loadingState.response!) @@ -168,6 +172,7 @@ class _DynamicsTabPageState DynamicPanel( item: i, onRemove: controller.onRemove, + // onSetTop: controller.onSetTop, ), ] ], @@ -193,6 +198,7 @@ class _DynamicsTabPageState return DynamicPanel( item: item, onRemove: controller.onRemove, + // onSetTop: controller.onSetTop, ); } return const SizedBox.shrink(); diff --git a/lib/pages/dynamics/widgets/additional_panel.dart b/lib/pages/dynamics/widgets/additional_panel.dart index 4a6d9d8c6..9c7147b8c 100644 --- a/lib/pages/dynamics/widgets/additional_panel.dart +++ b/lib/pages/dynamics/widgets/additional_panel.dart @@ -131,6 +131,7 @@ Widget addWidget(item, context, type, {floor = 1}) { ) ], ), + // TextButton(onPressed: () {}, child: Text('123')) ), ), ) @@ -139,6 +140,60 @@ Widget addWidget(item, context, type, {floor = 1}) { case 'ADDITIONAL_TYPE_GOODS': // 商品 return const SizedBox(); + // return Padding( + // padding: const EdgeInsets.only(top: 6), + // child: InkWell( + // onTap: () {}, + // child: Container( + // padding: + // const EdgeInsets.only(left: 12, top: 8, right: 12, bottom: 8), + // decoration: BoxDecoration( + // color: bgColor, + // borderRadius: const BorderRadius.all(Radius.circular(6)), + // ), + // child: Row( + // children: [ + // NetworkImgLayer( + // width: 75, + // height: 75, + // src: dynamicProperty[type].items.first.cover, + // ), + // const SizedBox(width: 10), + // Expanded( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + // children: [ + // Text( + // dynamicProperty[type].items.first.name, + // maxLines: 1, + // overflow: TextOverflow.ellipsis, + // ), + // Text( + // dynamicProperty[type].items.first.brief, + // maxLines: 1, + // style: TextStyle( + // color: Theme.of(context).colorScheme.outline, + // fontSize: Theme.of(context) + // .textTheme + // .labelMedium! + // .fontSize, + // ), + // ), + // const SizedBox(height: 2), + // Text( + // dynamicProperty[type].items.first.price, + // style: TextStyle( + // color: Theme.of(context).colorScheme.primary, + // ), + // ), + // ], + // ), + // ), + // ], + // ), + // ), + // ),); case 'ADDITIONAL_TYPE_MATCH': return const SizedBox(); case 'ADDITIONAL_TYPE_COMMON': diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index 35bf123cc..ed13bf8b0 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -84,6 +84,7 @@ class AuthorPanel extends StatelessWidget { children: [ Text( item.modules.moduleAuthor.name, + // semanticsLabel: "UP主:${item.modules.moduleAuthor.name}", style: TextStyle( color: item.modules.moduleAuthor!.vip != null && item.modules.moduleAuthor!.vip['status'] > 0 && @@ -144,6 +145,20 @@ class AuthorPanel extends StatelessWidget { ? Row( mainAxisSize: MainAxisSize.min, children: [ + // GestureDetector( + // onTap: + // item.modules.moduleAuthor.decorate['jump_url'] != null + // ? () { + // Get.toNamed( + // '/webview', + // parameters: { + // 'url': + // '${item.modules.moduleAuthor.decorate['jump_url']}' + // }, + // ); + // } + // : null, + // child: Stack( clipBehavior: Clip.none, alignment: Alignment.centerRight, @@ -183,6 +198,7 @@ class AuthorPanel extends StatelessWidget { ), ], ), + // ), _moreWidget(context), ], ) @@ -266,6 +282,7 @@ class AuthorPanel extends StatelessWidget { } }, minLeadingWidth: 0, + // dense: true, leading: const Icon(Icons.watch_later_outlined, size: 19), title: Text( '稍后再看', diff --git a/lib/pages/dynamics/widgets/content_panel.dart b/lib/pages/dynamics/widgets/content_panel.dart index e9a5ae950..ef123e4d5 100644 --- a/lib/pages/dynamics/widgets/content_panel.dart +++ b/lib/pages/dynamics/widgets/content_panel.dart @@ -66,6 +66,7 @@ Widget content(bool isSave, BuildContext context, item, source, callback) { item.modules.moduleDynamic.major.opus.pics.isNotEmpty) Text.rich( picsNodes(), + // semanticsLabel: '动态图片', ), ], ), diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart index e1579c088..901bd428f 100644 --- a/lib/pages/dynamics/widgets/dynamic_panel.dart +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -29,6 +29,9 @@ class DynamicPanel extends StatelessWidget { @override Widget build(BuildContext context) { return Container( + // padding: source == 'detail' + // ? const EdgeInsets.only(bottom: 12) + // : EdgeInsets.zero, decoration: isSave || (source == 'detail' && Get.context!.orientation == Orientation.landscape) @@ -43,7 +46,11 @@ class DynamicPanel extends StatelessWidget { ), child: Material( elevation: 0, + // clipBehavior: Clip.hardEdge, color: Colors.transparent, + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(5), + // ), child: InkWell( onTap: source == 'detail' && [ diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index 89ad61651..6756f88ae 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -106,6 +106,22 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback, ], ), const SizedBox(height: 2), + + /// fix #话题跟content重复 + // if (item.modules.moduleDynamic.topic != null) ...[ + // Padding( + // padding: floor == 2 + // ? EdgeInsets.zero + // : const EdgeInsets.only(left: 12, right: 12), + // child: GestureDetector( + // child: Text( + // '#${item.modules.moduleDynamic.topic.name}', + // style: authorStyle, + // ), + // ), + // ), + // ], + if (richNodes != null) Text.rich( richNodes, @@ -124,7 +140,10 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback, if (hasPics) ...[ Text.rich( picsNodes(item.modules.moduleDynamic.major.opus.pics, callback), + // semanticsLabel: '动态图片', ), + // if (item.modules.moduleDynamic.additional != null) + // const SizedBox(height: 4), ], const SizedBox(height: 4), ], @@ -187,6 +206,11 @@ Widget forWard(bool isSave, item, BuildContext context, source, callback, : const SizedBox.shrink(), _ => const SizedBox.shrink(), }; + // return Container( + // padding: + // const EdgeInsets.only(left: 10, top: 12, right: 10, bottom: 10), + // color: Theme.of(context).dividerColor.withOpacity(0.08), + // child: articlePanel(item, context, floor: floor)); // 转发 case 'DYNAMIC_TYPE_FORWARD': return InkWell( diff --git a/lib/pages/dynamics/widgets/rich_node_panel.dart b/lib/pages/dynamics/widgets/rich_node_panel.dart index 607ff74fe..ef6acd2c8 100644 --- a/lib/pages/dynamics/widgets/rich_node_panel.dart +++ b/lib/pages/dynamics/widgets/rich_node_panel.dart @@ -40,6 +40,9 @@ InlineSpan? richNode(item, BuildContext context) { return null; } else { for (var i in richTextNodes) { + /// fix 渲染专栏时内容会重复 + // if (item.modules.moduleDynamic.major.opus.title == null && + // i.type == 'RICH_TEXT_NODE_TYPE_TEXT') { if (i.type == 'RICH_TEXT_NODE_TYPE_TEXT') { spanChildren.add( TextSpan(text: i.origText, style: const TextStyle(height: 1.65))); @@ -286,7 +289,121 @@ InlineSpan? richNode(item, BuildContext context) { } } - return TextSpan(children: spanChildren); + // if (contentType == 'major' && + // item.modules.moduleDynamic.major.opus.pics.isNotEmpty) { + // // 图片可能跟其他widget重复渲染 + // List pics = item.modules.moduleDynamic.major.opus.pics; + // int len = pics.length; + // List picList = []; + + // if (len == 1) { + // OpusPicsModel pictureItem = pics.first; + // picList.add(pictureItem.url!); + // spanChildren.add(const TextSpan(text: '\n')); + // spanChildren.add( + // WidgetSpan( + // child: LayoutBuilder( + // builder: (context, BoxConstraints box) { + // return GestureDetector( + // onTap: () { + // showDialog( + // useSafeArea: false, + // context: context, + // builder: (context) { + // return ImagePreview(initialPage: 0, imgList: picList); + // }, + // ); + // }, + // child: Padding( + // padding: const EdgeInsets.only(top: 4), + // child: NetworkImgLayer( + // src: pictureItem.url, + // width: box.maxWidth / 2, + // height: box.maxWidth * + // 0.5 * + // (pictureItem.height != null && + // pictureItem.width != null + // ? pictureItem.height! / pictureItem.width! + // : 1), + // ), + // ), + // ); + // }, + // ), + // ), + // ); + // } + // if (len > 1) { + // List list = []; + // for (var i = 0; i < len; i++) { + // picList.add(pics[i].url!); + // list.add( + // LayoutBuilder( + // builder: (context, BoxConstraints box) { + // return GestureDetector( + // onTap: () { + // showDialog( + // useSafeArea: false, + // context: context, + // builder: (context) { + // return ImagePreview(initialPage: i, imgList: picList); + // }, + // ); + // }, + // child: NetworkImgLayer( + // src: pics[i].url, + // width: box.maxWidth, + // height: box.maxWidth, + // ), + // ); + // }, + // ), + // ); + // } + // spanChildren.add( + // WidgetSpan( + // child: LayoutBuilder( + // builder: (context, BoxConstraints box) { + // double maxWidth = box.maxWidth; + // double crossCount = len < 3 ? 2 : 3; + // double height = maxWidth / + // crossCount * + // (len % crossCount == 0 + // ? len ~/ crossCount + // : len ~/ crossCount + 1) + + // 6; + // return Container( + // padding: const EdgeInsets.only(top: 6), + // height: height, + // child: GridView.count( + // padding: EdgeInsets.zero, + // physics: const NeverScrollableScrollPhysics(), + // crossAxisCount: crossCount.toInt(), + // mainAxisSpacing: 4.0, + // crossAxisSpacing: 4.0, + // childAspectRatio: 1, + // children: list, + // ), + // ); + // }, + // ), + // ), + // ); + // } + // spanChildren.add( + // WidgetSpan( + // child: NetworkImgLayer( + // src: pics.first.url, + // type: 'emote', + // width: 100, + // height: 200, + // ), + // ), + // ); + // } + return TextSpan( + children: spanChildren, + ); } } catch (err) { debugPrint('❌rich_node_panel err: $err'); diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index 41b11396c..0d376f2dc 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -109,14 +109,36 @@ class _UpPanelState extends State { feedBack(); if (data.type == 'up') { widget.dynamicsController.currentMid = data.mid; + // dynamicsController.mid.value = data.mid; widget.dynamicsController ..upInfo.value = data ..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(() {}); } else if (data.type == 'live') { + // LiveItemModel liveItem = LiveItemModel.fromJson({ + // 'title': data.title, + // 'uname': data.uname, + // 'face': data.face, + // 'roomid': data.roomId, + // }); Get.toNamed('/liveRoom?roomid=${data.roomId}'); } }, @@ -202,6 +224,29 @@ class _UpPanelState extends State { } } +// class _SliverHeaderDelegate extends SliverPersistentHeaderDelegate { +// _SliverHeaderDelegate({required this.height, required this.child}); + +// final double height; +// final Widget child; + +// @override +// Widget build( +// BuildContext context, double shrinkOffset, bool overlapsContent) { +// return child; +// } + +// @override +// double get maxExtent => height; + +// @override +// double get minExtent => height; + +// @override +// bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => +// true; +// } + class UpPanelSkeleton extends StatelessWidget { const UpPanelSkeleton({super.key}); diff --git a/lib/pages/dynamics/widgets/video_panel.dart b/lib/pages/dynamics/widgets/video_panel.dart index 56bbb040c..a68ccd963 100644 --- a/lib/pages/dynamics/widgets/video_panel.dart +++ b/lib/pages/dynamics/widgets/video_panel.dart @@ -55,12 +55,16 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) { double width = box.maxWidth; return Stack( children: [ + // Hero( + // tag: content.bvid, + // child: NetworkImgLayer( width: width, height: width / StyleString.aspectRatio, src: content.cover, semanticsLabel: content.title, ), + // ), if (content?.badge?['text'] != null) PBadge( text: content.badge['text'], @@ -157,6 +161,22 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) { ), const SizedBox(height: 6), ], + // const SizedBox(height: 4), + /// fix #话题跟content重复 + // if (item.modules.moduleDynamic.topic != null) ...[ + // Padding( + // padding: floor == 2 + // ? EdgeInsets.zero + // : const EdgeInsets.only(left: 12, right: 12), + // child: GestureDetector( + // child: Text( + // '#${item.modules.moduleDynamic.topic.name}', + // style: authorStyle, + // ), + // ), + // ), + // const SizedBox(height: 6), + // ], if (floor == 2 && item.modules.moduleDynamic.desc != null) ...[ if (richNodes != null) Text.rich(richNodes), const SizedBox(height: 6), diff --git a/lib/pages/fav/video/fav_folder_sort_page.dart b/lib/pages/fav/video/fav_folder_sort_page.dart index 26e88d93f..1a996d7d5 100644 --- a/lib/pages/fav/video/fav_folder_sort_page.dart +++ b/lib/pages/fav/video/fav_folder_sort_page.dart @@ -121,18 +121,15 @@ class _FavFolderSortPageState extends State { (index) { final item = sortList[index]; final key = item.id.toString(); - return SizedBox( + return FavItem( key: Key(key), - height: 98, - child: FavItem( - heroTag: key, - favFolderItem: item, - onLongPress: index == 0 - ? () { - SmartDialog.showToast('默认收藏夹不支持排序'); - } - : null, - ), + heroTag: key, + favFolderItem: item, + onLongPress: index == 0 + ? () { + SmartDialog.showToast('默认收藏夹不支持排序'); + } + : null, ); }, ), diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 33668b1d5..3447468f4 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -24,6 +24,7 @@ class FavDetailController @override void onInit() { + // item = Get.arguments; if (Get.parameters.keys.isNotEmpty) { mediaId = int.parse(Get.parameters['mediaId']!); heroTag = Get.parameters['heroTag']!; diff --git a/lib/pages/fav_detail/fav_sort_page.dart b/lib/pages/fav_detail/fav_sort_page.dart index feaa9e6cd..7d728efd5 100644 --- a/lib/pages/fav_detail/fav_sort_page.dart +++ b/lib/pages/fav_detail/fav_sort_page.dart @@ -1,3 +1,4 @@ +import 'package:PiliPlus/build_config.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/models/user/fav_detail.dart'; @@ -125,13 +126,20 @@ class _FavSortPageState extends State { ), children: sortList .map( - (item) => SizedBox( + (item) => Stack( key: Key(item.id.toString()), - height: 98, - child: FavVideoCardH( - isSort: true, - videoItem: item, - ), + children: [ + FavVideoCardH( + isSort: true, + videoItem: item, + ), + if (BuildConfig.isDebug) + Positioned( + top: 35, + right: 10, + child: Text(item.id.toString()), + ) + ], ), ) .toList(), diff --git a/lib/pages/hot/controller.dart b/lib/pages/hot/controller.dart index 4b5c62a9d..f054616da 100644 --- a/lib/pages/hot/controller.dart +++ b/lib/pages/hot/controller.dart @@ -7,6 +7,8 @@ import 'package:get/get.dart'; class HotController extends CommonListController, HotVideoItemModel> { + // int idx = 0; + late RxBool showHotRcmd = GStorage.showHotRcmd.obs; @override @@ -15,10 +17,24 @@ class HotController queryData(); } + // @override + // Future onRefresh() { + // idx = 0; + // return super.onRefresh(); + // } + @override Future>> customGetData() => VideoHttp.hotVideoList( pn: currentPage, ps: 20, ); + + // @override + // void handleSuccess(List currentList, List dataList) { + // idx = (dataList.last as Card?)?.smallCoverV5.base.idx.toInt() ?? 0; + // } + + // @override + // Future customGetData() => VideoHttp.hotVideoListGrpc(idx: idx); } diff --git a/lib/pages/html/view.dart b/lib/pages/html/view.dart index 26776a66f..0baf5234c 100644 --- a/lib/pages/html/view.dart +++ b/lib/pages/html/view.dart @@ -127,6 +127,16 @@ class _HtmlRenderPageState extends State } void listener() { + // 标题 + // if (scrollController.offset > 55 && !_visibleTitle) { + // _visibleTitle = true; + // titleStreamC.add(true); + // } else if (scrollController.offset <= 55 && _visibleTitle) { + // _visibleTitle = false; + // titleStreamC.add(false); + // } + + // fab按钮 final ScrollDirection direction1 = _htmlRenderCtr.scrollController.positions.first.userScrollDirection; late final ScrollDirection direction2 = diff --git a/lib/pages/live_room/send_dm_panel.dart b/lib/pages/live_room/send_dm_panel.dart index e324bf705..137dacd8d 100644 --- a/lib/pages/live_room/send_dm_panel.dart +++ b/lib/pages/live_room/send_dm_panel.dart @@ -230,6 +230,13 @@ class _ReplyPageState extends CommonPublishPageState { Get.back(); liveRoomController.savedDanmaku = null; SmartDialog.showToast('发送成功'); + // liveRoomController.plPlayerController.danmakuController?.addDanmaku( + // DanmakuContentItem( + // emoticonUnique ?? message, + // type: DanmakuItemType.scroll, + // selfSend: true, + // ), + // ); } else { SmartDialog.showToast(res['msg']); } diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index f1a2ff05a..70c8e8b33 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -126,6 +126,7 @@ class _LiveRoomPageState extends State ScreenBrightness().resetApplicationScreenBrightness(); PlPlayerController.setPlayCallBack(null); _liveRoomController.msgStream?.close(); + // floating?.dispose(); plPlayerController.removeStatusLister(playerListener); plPlayerController.dispose(); super.dispose(); @@ -422,14 +423,17 @@ class _LiveRoomPageState extends State ), ), ), + //刷新 IconButton( tooltip: '刷新', onPressed: () { _futureBuilderFuture = _liveRoomController.queryLiveInfo(); + // videoSourceInit(); }, icon: const Icon(Icons.refresh), ), + //内置浏览器打开 IconButton( tooltip: '浏览器打开', onPressed: () { diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index 5f57920ec..0c6626b24 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -46,7 +46,38 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { ), onTap: onRefresh, ), + // // ComBtn( + // icon: const Icon( + // Icons.subtitles_outlined, + // size: 18, + // color: Colors.white, + // ), + // fuc: () => Get.back(), + // ), const Spacer(), + // ComBtn( + // icon: const Icon( + // Icons.hd_outlined, + // size: 18, + // color: Colors.white, + // ), + // fuc: () => {}, + // ), + // const SizedBox(width: 4), + // Obx( + // () => ComBtn( + // icon: Icon( + // widget.liveRoomCtr!.volumeOff.value + // ? Icons.volume_off_outlined + // : Icons.volume_up_outlined, + // size: 18, + // color: Colors.white, + // ), + // fuc: () => {}, + // ), + // ), + // const SizedBox(width: 4), + Obx( () => IconButton( onPressed: () { @@ -144,3 +175,21 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { ); } } + +// class MSliderTrackShape extends RoundedRectSliderTrackShape { +// @override +// Rect getPreferredRect({ +// required RenderBox parentBox, +// Offset offset = Offset.zero, +// SliderThemeData? sliderTheme, +// bool isEnabled = false, +// bool isDiscrete = false, +// }) { +// const double trackHeight = 3; +// final double trackLeft = offset.dx; +// final double trackTop = +// offset.dy + (parentBox.size.height - trackHeight) / 2 + 4; +// final double trackWidth = parentBox.size.width; +// return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight); +// } +// } diff --git a/lib/pages/live_room/widgets/chat.dart b/lib/pages/live_room/widgets/chat.dart index d31315778..9c426e43c 100644 --- a/lib/pages/live_room/widgets/chat.dart +++ b/lib/pages/live_room/widgets/chat.dart @@ -65,6 +65,7 @@ class LiveRoomChat extends StatelessWidget { ); } catch (err) { debugPrint(err.toString()); + // SmartDialog.showToast(err.toString()); } }, ), diff --git a/lib/pages/login/controller.dart b/lib/pages/login/controller.dart index 68f207c92..e86265a48 100644 --- a/lib/pages/login/controller.dart +++ b/lib/pages/login/controller.dart @@ -628,9 +628,11 @@ class LoginPageController extends GetxController break; default: SmartDialog.showToast(res['msg']); + // login failed break; } } + // }); } bool isGeeArgumentValid(String? geeGt, String? geeChallenge) { @@ -642,7 +644,11 @@ class LoginPageController extends GetxController Future setAccount(Map tokenInfo, List cookieInfo) async { final account = LoginAccount(BiliCookieJar.fromList(cookieInfo), tokenInfo['access_token'], tokenInfo['refresh_token']); - await Future.wait([account.onChange(), AnonymousAccount().delete()]); + await Future.wait([ + account.onChange(), + AnonymousAccount().delete() + // .then((_) => Request.buvidActive(AnonymousAccount())) + ]); Accounts.accountMode.updateAll((_, a) => a == account ? account : a); if (Accounts.main.isLogin) { SmartDialog.showToast('登录成功'); diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index 2659914d3..6819c5771 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -22,6 +22,7 @@ class LoginPage extends StatefulWidget { class _LoginPageState extends State { final LoginPageController _loginPageCtr = Get.put(LoginPageController()); + // late Future> codeFuture; // 二维码生成时间 bool showPassword = false; GlobalKey globalKey = GlobalKey(); @@ -40,6 +41,7 @@ class _LoginPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + // const SizedBox(width: 20), TextButton.icon( onPressed: _loginPageCtr.refreshQRCode, icon: const Icon(Icons.refresh), @@ -62,6 +64,7 @@ class _LoginPageState extends State { Uint8List.fromList(pngBytes), fileName: picName, extension: 'png', + // 保存到 PiliPlus文件夹 androidRelativePath: "Pictures/PiliPlus", skipIfExists: false, ); @@ -105,6 +108,20 @@ class _LoginPageState extends State { ), ), ); + // return QrImageView( + // backgroundColor: Colors.white, + // eyeStyle: QrEyeStyle( + // eyeShape: QrEyeShape.square, + // color: Colors.black87, + // ), + // dataModuleStyle: QrDataModuleStyle( + // dataModuleShape: QrDataModuleShape.square, + // color: Colors.black87, + // ), + // data: _loginPageCtr.codeInfo.value['data']!['url']!, + // size: 200, + // semanticsLabel: '二维码', + // ); }), ), const SizedBox(height: 10), @@ -115,6 +132,10 @@ class _LoginPageState extends State { )), Obx(() => GestureDetector( onTap: () { + //以外部方式打开此链接 + // launchUrlString( + // _loginPageCtr.codeInfo.value['data']?['url'] ?? "", + // mode: LaunchMode.externalApplication); // 复制到剪贴板 Utils.copyText( _loginPageCtr.codeInfo.value['data']?['url'] ?? '', @@ -366,6 +387,7 @@ class _LoginPageState extends State { }); }, value: item, + // height: menuItemHeight, child: Row(children: [ Text(item['cname']), const Spacer(), @@ -378,7 +400,7 @@ class _LoginPageState extends State { ), const SizedBox(width: 6), SizedBox( - height: 24, + height: 24, // 这里设置固定高度 child: VerticalDivider( color: Theme.of(context) .colorScheme diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index 232ba8cd8..e8d2d5c9e 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -176,7 +176,7 @@ class MainController extends GetxController { void setCount([int count = 0]) async { if (dynIndex == -1 || navigationBars[dynIndex]['count'] == count) return; - navigationBars[dynIndex]['count'] = count; + navigationBars[dynIndex]['count'] = count; // 修改 count 属性为新的值 navigationBars.refresh(); } diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index b3276bac4..966ee2c3b 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -36,7 +36,7 @@ class _MainAppState extends State late final _homeController = Get.put(HomeController()); late final _dynamicController = Get.put(DynamicsController()); - late int _lastSelectTime = 0; + late int _lastSelectTime = 0; //上次点击时间 late bool enableMYBar; late bool useSideBar; @@ -192,7 +192,7 @@ class _MainAppState extends State value: SystemUiOverlayStyle( systemNavigationBarColor: Colors.transparent, systemNavigationBarIconBrightness: - Theme.of(context).brightness.reverse, + Theme.of(context).brightness.reverse, // 设置虚拟按键图标颜色 ), child: Scaffold( resizeToAvoidBottomInset: false, @@ -412,6 +412,11 @@ class _MainAppState extends State ? Text(count.toString()) : null, padding: const EdgeInsets.fromLTRB(6, 0, 6, 0), + // isLabelVisible: + // _mainController.dynamicBadgeType != DynamicBadgeMode.hidden && + // count > 0, + // backgroundColor: Theme.of(context).colorScheme.primary, + // textColor: Theme.of(context).colorScheme.onInverseSurface, child: icon, ) : icon; diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index a2ebda714..6b2f8f34b 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -297,9 +297,9 @@ class FavFolderItem extends StatelessWidget { .colorScheme .onInverseSurface .withOpacity(0.4), - offset: const Offset(4, -12), - blurRadius: 0.0, - spreadRadius: 0.0, + offset: const Offset(4, -12), // 阴影与容器的距离 + blurRadius: 0.0, // 高斯的标准偏差与盒子的形状卷积。 + spreadRadius: 0.0, // 在应用模糊之前,框应该膨胀的量。 ), ], ), diff --git a/lib/pages/member/member_page.dart b/lib/pages/member/member_page.dart index 81b8602c8..dd2154749 100644 --- a/lib/pages/member/member_page.dart +++ b/lib/pages/member/member_page.dart @@ -128,6 +128,7 @@ class _MemberPageNewState extends State { children: _userController.tab2!.map((item) { return switch (item.param!) { 'home' => MemberHome(heroTag: _heroTag), + // 'dynamic' => MemberDynamic(mid: _mid ?? -1), 'dynamic' => MemberDynamicsPage(mid: _mid), 'contribute' => Obx( () => MemberContribute( diff --git a/lib/pages/member/widget/edit_profile_page.dart b/lib/pages/member/widget/edit_profile_page.dart index 2e231b745..0d1aed821 100644 --- a/lib/pages/member/widget/edit_profile_page.dart +++ b/lib/pages/member/widget/edit_profile_page.dart @@ -189,6 +189,15 @@ class _EditProfilePageState extends State { onTap: () => Utils.copyText(loadingState.response['mid'].toString()), ), + // _divider, + // _item( + // title: '二维码名片', + // widget: Icon( + // Icons.qr_code, + // color: Theme.of(context).colorScheme.outline, + // ), + // onTap: () {}, + // ), _divider1, _item( title: '哔哩哔哩认证', diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index 3c641f8b6..3f359a6ac 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -155,6 +155,32 @@ class UserInfoCard extends StatelessWidget { height: 20, ), ], + // GestureDetector( + // onTap: () { + // Utils.copyText(card.mid.toString()); + // }, + // child: Container( + // padding: + // const EdgeInsets.symmetric(horizontal: 8, vertical: 2.5), + // decoration: BoxDecoration( + // color: Theme.of(context).colorScheme.secondaryContainer, + // borderRadius: const BorderRadius.all(Radius.circular(12)), + // ), + // child: Text( + // 'uid: ${card.mid}', + // style: TextStyle( + // height: 1, + // fontSize: 12, + // color: Theme.of(context).colorScheme.onSecondaryContainer, + // ), + // strutStyle: const StrutStyle( + // height: 1, + // leading: 0, + // fontSize: 12, + // ), + // ), + // ), + // ), ], ), ), @@ -381,18 +407,17 @@ class UserInfoCard extends StatelessWidget { ), ), TextSpan( - text: isOwner - ? '编辑资料' - : switch (relation) { - 0 => '关注', - 1 => '悄悄关注', - 2 => '已关注', - 4 || 6 => '已互关', - 128 => '移除黑名单', - -10 => '特别关注', // 该状态码并不是官方状态码 - _ => relation.toString(), - }, - ), + text: isOwner + ? '编辑资料' + : switch (relation) { + 0 => '关注', + 1 => '悄悄关注', + 2 => '已关注', + 4 || 6 => '已互关', + 128 => '移除黑名单', + -10 => '特别关注', // 该状态码并不是官方状态码 + _ => relation.toString(), + }), ], ), ), diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index 0b27a71d2..2d6d9334f 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -154,6 +154,8 @@ class MineController extends GetxController { ], ), ), + // duration: const Duration(seconds: 2), + // showCloseIcon: true, ); }, ).then((res) { diff --git a/lib/pages/mine/view.dart b/lib/pages/mine/view.dart index fa4ab26dc..fe7563673 100644 --- a/lib/pages/mine/view.dart +++ b/lib/pages/mine/view.dart @@ -40,7 +40,8 @@ class _MinePageState extends State { iconSize: 40.0, padding: const EdgeInsets.all(8), style: const ButtonStyle( - tapTargetSize: MaterialTapTargetSize.shrinkWrap, + tapTargetSize: + MaterialTapTargetSize.shrinkWrap, // the '2023' part ), tooltip: "${MineController.anonymity.value ? '退出' : '进入'}无痕模式", onPressed: () { @@ -60,7 +61,8 @@ class _MinePageState extends State { iconSize: 40.0, padding: const EdgeInsets.all(8), style: const ButtonStyle( - tapTargetSize: MaterialTapTargetSize.shrinkWrap, + tapTargetSize: + MaterialTapTargetSize.shrinkWrap, // the '2023' part ), tooltip: '切换至${_mineController.nextThemeType.description}主题', onPressed: _mineController.onChangeTheme, @@ -75,7 +77,8 @@ class _MinePageState extends State { iconSize: 40.0, padding: const EdgeInsets.all(8), style: const ButtonStyle( - tapTargetSize: MaterialTapTargetSize.shrinkWrap, + tapTargetSize: + MaterialTapTargetSize.shrinkWrap, // the '2023' part ), tooltip: '设置', onPressed: () => { diff --git a/lib/pages/msg_feed_top/sys_msg/view.dart b/lib/pages/msg_feed_top/sys_msg/view.dart index cadf80877..15342166d 100644 --- a/lib/pages/msg_feed_top/sys_msg/view.dart +++ b/lib/pages/msg_feed_top/sys_msg/view.dart @@ -159,6 +159,7 @@ class _SysMsgPageState extends State { } else if (matchStr.startsWith('【')) { try { bool isBV = match[3]?.startsWith('BV') == true; + // validate if (isBV) { IdUtils.bv2av(match[3]!); } else { diff --git a/lib/pages/search/controller.dart b/lib/pages/search/controller.dart index 0638a86cd..361d85d56 100644 --- a/lib/pages/search/controller.dart +++ b/lib/pages/search/controller.dart @@ -9,9 +9,6 @@ import 'package:PiliPlus/utils/storage.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; class SSearchController extends GetxController { - SSearchController(this.tag); - final String tag; - final searchFocusNode = FocusNode(); final controller = TextEditingController(); @@ -118,7 +115,6 @@ class SSearchController extends GetxController { await Get.toNamed( '/searchResult', parameters: { - 'tag': tag, 'keyword': controller.text, }, arguments: { diff --git a/lib/pages/search/view.dart b/lib/pages/search/view.dart index bfed6180d..95121e573 100644 --- a/lib/pages/search/view.dart +++ b/lib/pages/search/view.dart @@ -21,7 +21,7 @@ class SearchPage extends StatefulWidget { class _SearchPageState extends State { final _tag = Utils.generateRandomString(6); late final SSearchController _searchController = Get.put( - SSearchController(_tag), + SSearchController(), tag: _tag, ); @@ -67,6 +67,7 @@ class _SearchPageState extends State { controller: _searchController.controller, textInputAction: TextInputAction.search, onChanged: _searchController.onChange, + // textAlignVertical: TextAlignVertical.center, decoration: InputDecoration( hintText: _searchController.hintText, border: InputBorder.none, diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index 413020004..a932422e6 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -24,7 +24,6 @@ class _SearchResultPageState extends State late TabController _tabController; final String _tag = DateTime.now().millisecondsSinceEpoch.toString(); final bool? _isFromSearch = Get.arguments?['fromSearch']; - SSearchController? sSearchController; @override void initState() { @@ -36,21 +35,21 @@ class _SearchResultPageState extends State _tabController = TabController( vsync: this, - initialIndex: Get.arguments?['initIndex'] ?? 0, + initialIndex: Get.arguments?['initIndex'] != null + ? (Get.arguments?['initIndex'] as int) + : 0, length: SearchType.values.length, ); - if (_isFromSearch == true) { - try { - sSearchController = - Get.find(tag: Get.parameters['tag']); - } catch (_) {} + if (Get.arguments is int) { _tabController.addListener(listener); } } void listener() { - sSearchController?.initIndex = _tabController.index; + if (Get.isRegistered()) { + Get.find().initIndex = _tabController.index; + } } @override diff --git a/lib/pages/setting/pages/font_size_select.dart b/lib/pages/setting/pages/font_size_select.dart index 7f8f3ce67..e7f4139e8 100644 --- a/lib/pages/setting/pages/font_size_select.dart +++ b/lib/pages/setting/pages/font_size_select.dart @@ -12,6 +12,7 @@ class FontSizeSelectPage extends StatefulWidget { class _FontSizeSelectPageState extends State { List list = List.generate(16, (index) => 0.85 + index * 0.05); + //[0.85, 0.9, 0.95, 1.0, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3, 1.35]; late double minSize; late double maxSize; late double currentSize; diff --git a/lib/pages/setting/pages/logs.dart b/lib/pages/setting/pages/logs.dart index 0d3ebb4c7..5674a47f2 100644 --- a/lib/pages/setting/pages/logs.dart +++ b/lib/pages/setting/pages/logs.dart @@ -63,7 +63,7 @@ class _LogsPageState extends State { if (l.startsWith("Crash occurred on")) { try { date = DateTime.parse( - l.split("Crash occurred on")[1].trim(), + l.split("Crash occurred on")[1].trim(), //.split('.')[0], ); } catch (e) { debugPrint(e.toString()); @@ -111,6 +111,7 @@ class _LogsPageState extends State { actions: [ PopupMenuButton( onSelected: (String type) { + // 处理菜单项选择的逻辑 switch (type) { case 'copy': copyLogs(); diff --git a/lib/pages/setting/pages/play_speed_set.dart b/lib/pages/setting/pages/play_speed_set.dart index 47d439d7a..53cccfa4d 100644 --- a/lib/pages/setting/pages/play_speed_set.dart +++ b/lib/pages/setting/pages/play_speed_set.dart @@ -82,6 +82,7 @@ class _PlaySpeedPageState extends State { content: Column( mainAxisSize: MainAxisSize.min, children: [ + // const Text('输入你想要的视频倍速,例如:1.0'), const SizedBox(height: 12), TextField( autofocus: true, diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index 3a12d9903..e52a032cd 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -131,8 +131,10 @@ List get styleSettings => [ onChanged: (value) { if (value) { autoScreen(); + // SmartDialog.showToast('已开启横屏适配'); } else { AutoOrientation.portraitUpMode(); + // SmartDialog.showToast('已关闭横屏适配'); } }), SettingsModel( diff --git a/lib/pages/setting/widgets/switch_item.dart b/lib/pages/setting/widgets/switch_item.dart index e29ef8d73..4d7c263d4 100644 --- a/lib/pages/setting/widgets/switch_item.dart +++ b/lib/pages/setting/widgets/switch_item.dart @@ -133,7 +133,7 @@ class _SetSwitchItemState extends State { : null, leading: widget.leading, trailing: Transform.scale( - alignment: Alignment.centerRight, + alignment: Alignment.centerRight, // 缩放Switch的大小后保持右侧对齐, 避免右侧空隙过大 scale: 0.8, child: Switch( thumbIcon: @@ -141,7 +141,7 @@ class _SetSwitchItemState extends State { if (states.isNotEmpty && states.first == WidgetState.selected) { return const Icon(Icons.done); } - return null; + return null; // All other states will use the default thumbIcon. }), value: val, onChanged: switchChange, diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index 9112e5937..a2353d84a 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -102,6 +102,7 @@ class VideoDetailController extends GetxController Box get setting => GStorage.setting; + // late bool enableCDN; int? cacheVideoQa; late String cacheDecode; late String cacheSecondDecode; @@ -284,10 +285,14 @@ class VideoDetailController extends GetxController } danmakuCid.value = cid.value; + /// if (Platform.isAndroid) { floating = Floating(); } + // CDN优化 + // enableCDN = setting.get(SettingBoxKey.enableCDN, defaultValue: true); + // 预设的解码格式 cacheDecode = setting.get(SettingBoxKey.defaultDecode, defaultValue: VideoDecodeFormats.values.last.code); @@ -998,6 +1003,7 @@ class VideoDetailController extends GetxController } /// 更新画质、音质 + /// TODO 继续进度播放 updatePlayer() { isShowCover.value = false; playedTime = plPlayerController.position.value; @@ -1274,6 +1280,9 @@ class VideoDetailController extends GetxController orElse: () => videosList.first); setVideoHeight(); + // videoUrl = enableCDN + // ? VideoUtils.getCdnUrl(firstVideo) + // : (firstVideo.backupUrl ?? firstVideo.baseUrl!); videoUrl = VideoUtils.getCdnUrl(firstVideo); /// 优先顺序 设置中指定质量 -> 当前可选的最高质量 @@ -1299,6 +1308,9 @@ class VideoDetailController extends GetxController } firstAudio = audiosList.firstWhere((e) => e.id == closestNumber, orElse: () => audiosList.first); + // audioUrl = enableCDN + // ? VideoUtils.getCdnUrl(firstAudio) + // : (firstAudio.backupUrl ?? firstAudio.baseUrl!); audioUrl = VideoUtils.getCdnUrl(firstAudio); if (firstAudio.id != null) { currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; @@ -1458,6 +1470,9 @@ class VideoDetailController extends GetxController Future _querySubtitles() async { var res = await VideoHttp.subtitlesJson(bvid: bvid, cid: cid.value); + // if (!res["status"]) { + // SmartDialog.showToast('查询字幕错误,${res["msg"]}'); + // } if (res['status']) { // interactive video if (graphVersion == null) { diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 2837311c7..120835d0a 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -176,6 +176,11 @@ class VideoIntroController extends GetxController { lastPlayCid.value == 0) { lastPlayCid.value = videoDetail.value.pages!.first.cid!; } + // Get.find(tag: heroTag).tabs.value = [ + // '简介', + // '评论 ${result['data']!.stat!.reply}' + // ]; + // 获取到粉丝数再返回 queryUserStat(); } else { SmartDialog.showToast( @@ -269,10 +274,12 @@ class VideoIntroController extends GetxController { return; } if (videoDetail.value.stat?.like == null) { + // not init return; } 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(result['data']['toast']); hasLike.value = true; @@ -296,6 +303,7 @@ class VideoIntroController extends GetxController { var result = await VideoHttp.dislikeVideo(bvid: bvid, type: !hasDislike.value); if (result['status']) { + // hasLike.value = result["data"] == 1 ? true : false; if (!hasDislike.value) { SmartDialog.showToast('点踩成功'); hasDislike.value = true; @@ -304,6 +312,7 @@ class VideoIntroController extends GetxController { SmartDialog.showToast('取消踩'); hasDislike.value = false; } + // hasDislike.refresh(); } else { SmartDialog.showToast(result['msg']); } @@ -426,6 +435,8 @@ class VideoIntroController extends GetxController { Get.back(); hasFav.value = addMediaIdsNew.isNotEmpty || favIds?.length != delMediaIdsNew.length; + // 重新获取收藏状态 + // await queryHasFavVideo(); SmartDialog.showToast('操作成功'); } else { SmartDialog.showToast(result['msg']); @@ -570,6 +581,14 @@ class VideoIntroController extends GetxController { }, ); } + + // MemberController _ = Get.put(MemberController(mid: mid), + // tag: mid.toString()); + // await _.getInfo(); + // if (context.mounted) await _.actionRelationMod(context); + // followStatus['attribute'] = _.attribute.value; + // followStatus.refresh(); + // Get.delete(tag: mid.toString()); } // 修改分P或番剧分集 @@ -659,6 +678,10 @@ class VideoIntroController extends GetxController { bvid: bvid, cid: lastPlayCid.value, ); + // dynamic result = await GrpcRepo.playerOnline( + // aid: IdUtils.bv2av(bvid), + // cid: lastPlayCid.value, + // ); if (result['status']) { total.value = result['data']; } diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index c427b0982..b187c4fc4 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -54,6 +54,7 @@ class _VideoIntroPanelState extends State with AutomaticKeepAliveClientMixin { late VideoIntroController videoIntroController; + // 添加页面缓存 @override bool get wantKeepAlive => true; @@ -240,9 +241,11 @@ class _VideoInfoState extends State { return; } feedBack(); + // widget.showIntroDetail(); videoIntroController.expandableCtr?.toggle(); } + // 用户主页 onPushMember() { feedBack(); int? mid = !widget.loadingStatus @@ -253,8 +256,16 @@ class _VideoInfoState extends State { _horizontalMemberPage) { widget.onShowMemberPage(mid); } else { + // memberHeroTag = Utils.makeHeroTag(mid); + // String face = !loadingStatus + // ? videoDetail.owner!.face + // : videoItem['owner'].face; Get.toNamed( '/member?mid=$mid&from_view_aid=${videoDetailCtr.oid.value}', + // arguments: { + // 'face': face, + // 'heroTag': memberHeroTag, + // }, ); } } @@ -262,7 +273,7 @@ class _VideoInfoState extends State { @override Widget build(BuildContext context) { - final ThemeData themeData = Theme.of(context); + final ThemeData t = Theme.of(context); return SliverLayoutBuilder( builder: (BuildContext context, SliverConstraints constraints) { bool isHorizontal = context.orientation == Orientation.landscape && @@ -286,242 +297,266 @@ class _VideoInfoState extends State { onTap: () {}, child: Row( children: [ - if (videoItem['staff'] == null) ...[ - Expanded( - child: Align( - alignment: Alignment.centerLeft, - child: GestureDetector( - onTap: onPushMember, - behavior: HitTestBehavior.opaque, - child: Row( + Expanded( + child: videoItem['staff'] == null + ? Row( + mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - Obx( - () => Avatar( - avatar: videoIntroController.userStat - .value['card']?['face'] ?? - '', - size: 35, - isVip: (videoIntroController - .userStat.value['card'] - ?['vip']?['status'] ?? - -1) > - 0, - officialType: videoIntroController - .userStat.value['card'] - ?['official_verify']?['type'], - garbPendantImage: videoIntroController - .userStat.value['card'] - ?['pendant']?['image'], + GestureDetector( + onTap: onPushMember, + behavior: HitTestBehavior.opaque, + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Obx( + () => Avatar( + avatar: videoIntroController + .userStat + .value['card']?['face'] ?? + '', + size: 35, + isVip: (videoIntroController + .userStat + .value['card'] + ?['vip']?['status'] ?? + -1) > + 0, + officialType: videoIntroController + .userStat.value['card'] + ?['official_verify']?['type'], + garbPendantImage: + videoIntroController.userStat + .value['card'] + ?['pendant']?['image'], + ), + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Obx( + () => Text( + videoIntroController.userStat + .value['card'] + ?['name'] ?? + "", + maxLines: 1, + overflow: + TextOverflow.ellipsis, + style: TextStyle( + fontSize: 13, + color: (videoIntroController + .userStat + .value['card']?['vip'] + ?[ + 'status'] ?? + -1) > + 0 && + videoIntroController + .userStat + .value['card'] + ?[ + 'vip']?['type'] == + 2 + ? context.vipColor + : null, + ), + ), + ), + const SizedBox(height: 0), + Obx( + () => Text( + '${Utils.numFormat(videoIntroController.userStat.value['follower'])}粉丝 ${videoIntroController.userStat.value['archive_count'] != null ? '${Utils.numFormat(videoIntroController.userStat.value['archive_count'])}视频' : ''}', + style: TextStyle( + fontSize: 12, + color: + t.colorScheme.outline, + ), + ), + ), + ], + ), + ], ), ), - const SizedBox(width: 10), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Obx( - () => Text( - videoIntroController.userStat - .value['card']?['name'] ?? - "", - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 13, - color: (videoIntroController.userStat - .value[ - 'card']?['vip'] - ?['status'] ?? - -1) > - 0 && - videoIntroController - .userStat - .value['card'] - ?[ - 'vip']?['type'] == - 2 - ? context.vipColor - : null, - ), - ), - ), - const SizedBox(height: 0), - Obx( - () => Text( - '${Utils.numFormat(videoIntroController.userStat.value['follower'])}粉丝 ${videoIntroController.userStat.value['archive_count'] != null ? '${Utils.numFormat(videoIntroController.userStat.value['archive_count'])}视频' : ''}', - style: TextStyle( - fontSize: 12, - color: - themeData.colorScheme.outline, - ), - ), - ), - ], - ), + const Spacer(), + followButton(context, t), ], - ), - ), - ), - ), - followButton(context, themeData), - ] else - Expanded( - child: SelfSizedHorizontalList( - gapSize: 25, - itemCount: videoItem['staff'].length, - childBuilder: (index) => GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () { - int? ownerMid = !widget.loadingStatus - ? videoDetail.owner?.mid - : videoItem['owner']?.mid; - if (videoItem['staff'][index].mid == - ownerMid && - context.orientation == - Orientation.landscape && - _horizontalMemberPage) { - widget.onShowMemberPage(ownerMid); - } else { - Get.toNamed( - '/member?mid=${videoItem['staff'][index].mid}&from_view_aid=${videoDetailCtr.oid.value}', - ); - } - }, - child: Row( - children: [ - Stack( - clipBehavior: Clip.none, + ) + : SelfSizedHorizontalList( + gapSize: 25, + itemCount: videoItem['staff'].length, + childBuilder: (index) => GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + int? ownerMid = !widget.loadingStatus + ? videoDetail.owner?.mid + : videoItem['owner']?.mid; + if (videoItem['staff'][index].mid == + ownerMid && + context.orientation == + Orientation.landscape && + _horizontalMemberPage) { + widget.onShowMemberPage(ownerMid); + } else { + Get.toNamed( + '/member?mid=${videoItem['staff'][index].mid}&from_view_aid=${videoDetailCtr.oid.value}', + // arguments: { + // 'face': + // videoItem['staff'][index].face, + // 'heroTag': Utils.makeHeroTag( + // videoItem['staff'][index].mid), + // }, + ); + } + }, + child: Row( children: [ - NetworkImgLayer( - type: 'avatar', - src: videoItem['staff'][index].face, - width: 35, - height: 35, - fadeInDuration: Duration.zero, - fadeOutDuration: Duration.zero, + Stack( + clipBehavior: Clip.none, + children: [ + NetworkImgLayer( + type: 'avatar', + src: videoItem['staff'][index] + .face, + width: 35, + height: 35, + fadeInDuration: Duration.zero, + fadeOutDuration: Duration.zero, + ), + if ((videoItem['staff'][index] + .official?['type'] ?? + -1) != + -1) + Positioned( + right: -2, + bottom: -2, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context) + .colorScheme + .surface, + ), + child: Icon( + Icons.offline_bolt, + color: videoItem['staff'] + [index] + .official?[ + 'type'] == + 0 + ? Colors.yellow + : Colors + .lightBlueAccent, + size: 14, + ), + ), + ), + Positioned( + top: 0, + right: -6, + child: Obx(() => videoIntroController + .staffRelations[ + 'status'] == + true && + videoIntroController + .staffRelations[ + '${videoItem['staff'][index].mid}'] == + null + ? Material( + color: Colors.transparent, + child: InkWell( + customBorder: + const CircleBorder(), + onTap: () { + RequestUtils + .actionRelationMod( + context: context, + mid: videoItem[ + 'staff'] + [index] + .mid, + isFollow: false, + callback: (val) { + videoIntroController + .staffRelations[ + '${videoItem['staff'][index].mid}'] = true; + }, + ); + }, + child: Ink( + padding: + const EdgeInsets + .all(2), + decoration: + BoxDecoration( + color: Theme.of( + context) + .colorScheme + .secondaryContainer, + shape: + BoxShape.circle, + ), + child: Icon( + MdiIcons.plus, + size: 16, + color: Theme.of( + context) + .colorScheme + .onSecondaryContainer, + ), + ), + ), + ) + : const SizedBox.shrink()), + ), + ], ), - if ((videoItem['staff'][index] - .official?['type'] ?? - -1) != - -1) - Positioned( - right: -2, - bottom: -2, - child: Container( - decoration: BoxDecoration( - shape: BoxShape.circle, + const SizedBox(width: 8), + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + videoItem['staff'][index].name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 13, + color: videoItem['staff'][index] + .vip + .status > + 0 && + videoItem['staff'] + [index] + .vip + .type == + 2 + ? context.vipColor + : null, + ), + ), + Text( + videoItem['staff'][index].title, + style: TextStyle( + fontSize: 12, color: Theme.of(context) .colorScheme - .surface, - ), - child: Icon( - Icons.offline_bolt, - color: videoItem['staff'][index] - .official?[ - 'type'] == - 0 - ? Colors.yellow - : Colors.lightBlueAccent, - size: 14, + .outline, ), ), - ), - Positioned( - top: 0, - right: -6, - child: Obx(() => videoIntroController - .staffRelations[ - 'status'] == - true && - videoIntroController - .staffRelations[ - '${videoItem['staff'][index].mid}'] == - null - ? Material( - color: Colors.transparent, - child: InkWell( - customBorder: - const CircleBorder(), - onTap: () { - RequestUtils - .actionRelationMod( - context: context, - mid: videoItem['staff'] - [index] - .mid, - isFollow: false, - callback: (val) { - videoIntroController - .staffRelations[ - '${videoItem['staff'][index].mid}'] = true; - }, - ); - }, - child: Ink( - padding: - const EdgeInsets.all( - 2), - decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer, - shape: BoxShape.circle, - ), - child: Icon( - MdiIcons.plus, - size: 16, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, - ), - ), - ), - ) - : const SizedBox.shrink()), + ], ), ], ), - const SizedBox(width: 8), - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - videoItem['staff'][index].name, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 13, - color: videoItem['staff'][index] - .vip - .status > - 0 && - videoItem['staff'][index] - .vip - .type == - 2 - ? context.vipColor - : null, - ), - ), - Text( - videoItem['staff'][index].title, - style: TextStyle( - fontSize: 12, - color: Theme.of(context) - .colorScheme - .outline, - ), - ), - ], - ), - ], + ), ), - ), - ), - ), + ), if (isHorizontal) ...[ const SizedBox(width: 10), Expanded( @@ -568,7 +603,7 @@ class _VideoInfoState extends State { value: Utils.numFormat(!widget.loadingStatus ? videoDetail.stat?.view ?? '-' : videoItem['stat']?.view ?? '-'), - textColor: themeData.colorScheme.outline, + textColor: t.colorScheme.outline, ), const SizedBox(width: 10), StatDanMu( @@ -577,7 +612,7 @@ class _VideoInfoState extends State { value: Utils.numFormat(!widget.loadingStatus ? videoDetail.stat?.danmaku ?? '-' : videoItem['stat']?.danmu ?? '-'), - textColor: themeData.colorScheme.outline, + textColor: t.colorScheme.outline, ), const SizedBox(width: 10), Text( @@ -588,7 +623,7 @@ class _VideoInfoState extends State { formatType: 'detail'), style: TextStyle( fontSize: 12, - color: themeData.colorScheme.outline, + color: t.colorScheme.outline, ), ), if (MineController.anonymity.value) ...[ @@ -596,7 +631,7 @@ class _VideoInfoState extends State { Icon( MdiIcons.incognito, size: 15, - color: themeData.colorScheme.outline, + color: t.colorScheme.outline, semanticLabel: '无痕', ), ], @@ -607,7 +642,7 @@ class _VideoInfoState extends State { '${videoIntroController.total.value}人在看', style: TextStyle( fontSize: 12, - color: themeData.colorScheme.outline, + color: t.colorScheme.outline, ), ), ), @@ -701,6 +736,7 @@ class _VideoInfoState extends State { SelectableText.rich( style: const TextStyle( height: 1.4, + // fontSize: 13, ), TextSpan( children: [ @@ -762,6 +798,16 @@ class _VideoInfoState extends State { ), ), ), + // 点赞收藏转发 布局样式1 + // SingleChildScrollView( + // padding: const EdgeInsets.only(top: 7, bottom: 7), + // scrollDirection: Axis.horizontal, + // child: actionRow( + // context, + // videoIntroController, + // videoDetailCtr, + // ), + // ), // 点赞收藏转发 布局样式2 if (!isHorizontal) ...[ const SizedBox(height: 8), @@ -826,7 +872,7 @@ class _VideoInfoState extends State { switch (attr) { 1 => '悄悄关注', 2 => '已关注', - 4 || 6 => '已互关', + 6 => '已互关', 128 => '已拉黑', -10 => '特别关注', _ => '关注' @@ -840,108 +886,112 @@ class _VideoInfoState extends State { Widget actionGrid( BuildContext context, VideoIntroController videoIntroController) { - return Container( - margin: const EdgeInsets.only(top: 1), - height: 48, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Obx( - () => ActionItem( - icon: const Icon(FontAwesomeIcons.thumbsUp), - selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), - onTap: () => handleState(videoIntroController.actionLikeVideo), - onLongPress: () => - handleState(videoIntroController.actionOneThree), - selectStatus: videoIntroController.hasLike.value, + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Container( + margin: const EdgeInsets.only(top: 1), + height: 48, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Obx( + () => ActionItem( + icon: const Icon(FontAwesomeIcons.thumbsUp), + selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), + onTap: () => handleState(videoIntroController.actionLikeVideo), + onLongPress: () => + handleState(videoIntroController.actionOneThree), + selectStatus: videoIntroController.hasLike.value, + loadingStatus: widget.loadingStatus, + semanticsLabel: '点赞', + text: !widget.loadingStatus + ? Utils.numFormat(videoDetail.stat!.like!) + : '-', + needAnim: true, + hasTriple: videoIntroController.hasLike.value && + videoIntroController.hasCoin && + videoIntroController.hasFav.value, + callBack: (start) { + if (start) { + HapticFeedback.lightImpact(); + _coinKey.currentState?.controller?.forward(); + _favKey.currentState?.controller?.forward(); + } else { + _coinKey.currentState?.controller?.reverse(); + _favKey.currentState?.controller?.reverse(); + } + }, + ), + ), + Obx( + () => ActionItem( + icon: const Icon(FontAwesomeIcons.thumbsDown), + selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown), + onTap: () => + handleState(videoIntroController.actionDislikeVideo), + selectStatus: videoIntroController.hasDislike.value, + loadingStatus: widget.loadingStatus, + semanticsLabel: '点踩', + text: "点踩", + ), + ), + Obx( + () => ActionItem( + key: _coinKey, + icon: const Icon(FontAwesomeIcons.b), + selectIcon: const Icon(FontAwesomeIcons.b), + onTap: () => handleState(videoIntroController.actionCoinVideo), + selectStatus: videoIntroController.hasCoin, + loadingStatus: widget.loadingStatus, + semanticsLabel: '投币', + text: !widget.loadingStatus + ? Utils.numFormat(videoDetail.stat!.coin!) + : '-', + needAnim: true, + ), + ), + Obx( + () => ActionItem( + key: _favKey, + icon: const Icon(FontAwesomeIcons.star), + selectIcon: const Icon(FontAwesomeIcons.solidStar), + onTap: () => videoIntroController.showFavBottomSheet(context), + onLongPress: () => videoIntroController + .showFavBottomSheet(context, type: 'longPress'), + selectStatus: videoIntroController.hasFav.value, + loadingStatus: widget.loadingStatus, + semanticsLabel: '收藏', + text: !widget.loadingStatus + ? Utils.numFormat(videoDetail.stat!.favorite!) + : '-', + needAnim: true, + ), + ), + Obx( + () => ActionItem( + icon: const Icon(FontAwesomeIcons.clock), + selectIcon: const Icon(FontAwesomeIcons.solidClock), + onTap: () => handleState(videoIntroController.viewLater), + selectStatus: videoIntroController.hasLater.value, + loadingStatus: widget.loadingStatus, + semanticsLabel: '再看', + text: '再看', + ), + ), + ActionItem( + icon: const Icon(FontAwesomeIcons.shareFromSquare), + onTap: () => videoIntroController.actionShareVideo(context), + selectStatus: false, loadingStatus: widget.loadingStatus, - semanticsLabel: '点赞', + semanticsLabel: '分享', text: !widget.loadingStatus - ? Utils.numFormat(videoDetail.stat!.like!) - : '-', - needAnim: true, - hasTriple: videoIntroController.hasLike.value && - videoIntroController.hasCoin && - videoIntroController.hasFav.value, - callBack: (start) { - if (start) { - HapticFeedback.lightImpact(); - _coinKey.currentState?.controller?.forward(); - _favKey.currentState?.controller?.forward(); - } else { - _coinKey.currentState?.controller?.reverse(); - _favKey.currentState?.controller?.reverse(); - } - }, + ? Utils.numFormat(videoDetail.stat!.share!) + : '分享', ), - ), - Obx( - () => ActionItem( - icon: const Icon(FontAwesomeIcons.thumbsDown), - selectIcon: const Icon(FontAwesomeIcons.solidThumbsDown), - onTap: () => handleState(videoIntroController.actionDislikeVideo), - selectStatus: videoIntroController.hasDislike.value, - loadingStatus: widget.loadingStatus, - semanticsLabel: '点踩', - text: "点踩", - ), - ), - Obx( - () => ActionItem( - key: _coinKey, - icon: const Icon(FontAwesomeIcons.b), - selectIcon: const Icon(FontAwesomeIcons.b), - onTap: () => handleState(videoIntroController.actionCoinVideo), - selectStatus: videoIntroController.hasCoin, - loadingStatus: widget.loadingStatus, - semanticsLabel: '投币', - text: !widget.loadingStatus - ? Utils.numFormat(videoDetail.stat!.coin!) - : '-', - needAnim: true, - ), - ), - Obx( - () => ActionItem( - key: _favKey, - icon: const Icon(FontAwesomeIcons.star), - selectIcon: const Icon(FontAwesomeIcons.solidStar), - onTap: () => videoIntroController.showFavBottomSheet(context), - onLongPress: () => videoIntroController - .showFavBottomSheet(context, type: 'longPress'), - selectStatus: videoIntroController.hasFav.value, - loadingStatus: widget.loadingStatus, - semanticsLabel: '收藏', - text: !widget.loadingStatus - ? Utils.numFormat(videoDetail.stat!.favorite!) - : '-', - needAnim: true, - ), - ), - Obx( - () => ActionItem( - icon: const Icon(FontAwesomeIcons.clock), - selectIcon: const Icon(FontAwesomeIcons.solidClock), - onTap: () => handleState(videoIntroController.viewLater), - selectStatus: videoIntroController.hasLater.value, - loadingStatus: widget.loadingStatus, - semanticsLabel: '再看', - text: '再看', - ), - ), - ActionItem( - icon: const Icon(FontAwesomeIcons.shareFromSquare), - onTap: () => videoIntroController.actionShareVideo(context), - selectStatus: false, - loadingStatus: widget.loadingStatus, - semanticsLabel: '分享', - text: !widget.loadingStatus - ? Utils.numFormat(videoDetail.stat!.share!) - : '分享', - ), - ], - ), - ); + ], + ), + ); + }); } Widget actionRow( @@ -949,66 +999,63 @@ class _VideoInfoState extends State { VideoIntroController videoIntroController, VideoDetailController videoDetailCtr, ) { - return Row( - children: [ - Obx( - () => ActionRowItem( - icon: const Icon(FontAwesomeIcons.thumbsUp), - onTap: () => handleState(videoIntroController.actionLikeVideo), - selectStatus: videoIntroController.hasLike.value, - loadingStatus: widget.loadingStatus, - text: !widget.loadingStatus - ? videoDetail.stat!.like!.toString() - : '-', - ), - ), - const SizedBox(width: 8), - Obx( - () => ActionRowItem( - icon: const Icon(FontAwesomeIcons.b), - onTap: () => handleState(videoIntroController.actionCoinVideo), - selectStatus: videoIntroController.hasCoin, - loadingStatus: widget.loadingStatus, - text: !widget.loadingStatus - ? videoDetail.stat!.coin!.toString() - : '-', - ), - ), - const SizedBox(width: 8), - Obx( - () => ActionRowItem( - icon: const Icon(FontAwesomeIcons.heart), - onTap: () => videoIntroController.showFavBottomSheet(context), - onLongPress: () => videoIntroController.showFavBottomSheet(context, - type: 'longPress'), - selectStatus: videoIntroController.hasFav.value, - loadingStatus: widget.loadingStatus, - text: !widget.loadingStatus - ? videoDetail.stat!.favorite!.toString() - : '-', - ), - ), - const SizedBox(width: 8), - ActionRowItem( - icon: const Icon(FontAwesomeIcons.comment), - onTap: () { - videoDetailCtr.tabCtr.animateTo(1); - }, - selectStatus: false, + return Row(children: [ + Obx( + () => ActionRowItem( + icon: const Icon(FontAwesomeIcons.thumbsUp), + onTap: () => handleState(videoIntroController.actionLikeVideo), + selectStatus: videoIntroController.hasLike.value, loadingStatus: widget.loadingStatus, text: - !widget.loadingStatus ? videoDetail.stat!.reply!.toString() : '-', + !widget.loadingStatus ? videoDetail.stat!.like!.toString() : '-', ), - const SizedBox(width: 8), - ActionRowItem( + ), + const SizedBox(width: 8), + Obx( + () => ActionRowItem( + icon: const Icon(FontAwesomeIcons.b), + onTap: () => handleState(videoIntroController.actionCoinVideo), + selectStatus: videoIntroController.hasCoin, + loadingStatus: widget.loadingStatus, + text: + !widget.loadingStatus ? videoDetail.stat!.coin!.toString() : '-', + ), + ), + const SizedBox(width: 8), + Obx( + () => ActionRowItem( + icon: const Icon(FontAwesomeIcons.heart), + onTap: () => videoIntroController.showFavBottomSheet(context), + onLongPress: () => videoIntroController.showFavBottomSheet(context, + type: 'longPress'), + selectStatus: videoIntroController.hasFav.value, + loadingStatus: widget.loadingStatus, + text: !widget.loadingStatus + ? videoDetail.stat!.favorite!.toString() + : '-', + ), + ), + const SizedBox(width: 8), + ActionRowItem( + icon: const Icon(FontAwesomeIcons.comment), + onTap: () { + videoDetailCtr.tabCtr.animateTo(1); + }, + selectStatus: false, + loadingStatus: widget.loadingStatus, + text: !widget.loadingStatus ? videoDetail.stat!.reply!.toString() : '-', + ), + const SizedBox(width: 8), + ActionRowItem( icon: const Icon(FontAwesomeIcons.share), onTap: () => videoIntroController.actionShareVideo(context), selectStatus: false, loadingStatus: widget.loadingStatus, - text: '转发', - ), - ], - ); + // text: !loadingStatus + // ? videoDetail.stat!.share!.toString() + // : '-', + text: '转发'), + ]); } InlineSpan buildContent(BuildContext context, VideoDetailData content) { @@ -1032,6 +1079,7 @@ class _VideoInfoState extends State { String matchStr = match[0]!; if (RegExp(r'^av\d+$', caseSensitive: false).hasMatch(matchStr)) { try { + // validate int aid = int.parse(matchStr.substring(2)); IdUtils.av2bv(aid); spanChildren.add( @@ -1051,6 +1099,7 @@ class _VideoInfoState extends State { } else if (RegExp(r'^bv[a-z\d]{10}$', caseSensitive: false) .hasMatch(matchStr)) { try { + // validate IdUtils.bv2av(matchStr); spanChildren.add( TextSpan( diff --git a/lib/pages/video/detail/introduction/widgets/action_item.dart b/lib/pages/video/detail/introduction/widgets/action_item.dart index 8f1facf71..1f7a73950 100644 --- a/lib/pages/video/detail/introduction/widgets/action_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_item.dart @@ -150,9 +150,11 @@ class ActionItemState extends State onTapDown: (details) => _isThumbsUp ? _startLongPress() : null, onTapUp: (details) => _isThumbsUp ? _cancelLongPress() : null, onTapCancel: () => _isThumbsUp ? _cancelLongPress(true) : null, + // borderRadius: StyleString.mdRadius, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ + // const SizedBox(height: 2), Stack( alignment: Alignment.center, children: [ @@ -229,6 +231,7 @@ class _ArcPainter extends CustomPainter { ); const startAngle = -pi / 2; + // const sweepAngle = -2 * pi; canvas.drawArc(rect, startAngle, sweepAngle, false, paint); } diff --git a/lib/pages/video/detail/introduction/widgets/fav_panel.dart b/lib/pages/video/detail/introduction/widgets/fav_panel.dart index 4a3627603..9e12ad575 100644 --- a/lib/pages/video/detail/introduction/widgets/fav_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/fav_panel.dart @@ -147,6 +147,7 @@ class _FavPanelState extends State { ); } } else { + // 骨架屏 return const Center( child: CircularProgressIndicator(), ); diff --git a/lib/pages/video/detail/introduction/widgets/group_panel.dart b/lib/pages/video/detail/introduction/widgets/group_panel.dart index bd11a49ab..448ff4056 100644 --- a/lib/pages/video/detail/introduction/widgets/group_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/group_panel.dart @@ -152,6 +152,7 @@ class _GroupPanelState extends State { ); } } else { + // 骨架屏 return const Center( child: CircularProgressIndicator(), ); diff --git a/lib/pages/video/detail/introduction/widgets/page.dart b/lib/pages/video/detail/introduction/widgets/page.dart index 3873e6442..24ab57799 100644 --- a/lib/pages/video/detail/introduction/widgets/page.dart +++ b/lib/pages/video/detail/introduction/widgets/page.dart @@ -67,14 +67,15 @@ class _PagesPanelState extends State { if (!_scrollController.hasClients || pages.isEmpty) { return; } - const double itemWidth = 150; + const double itemWidth = 150; // 每个列表项的宽度 final double targetOffset = (pageIndex * itemWidth - itemWidth / 2).clamp( _scrollController.position.minScrollExtent, _scrollController.position.maxScrollExtent); + // 滑动至目标位置 _scrollController.animateTo( targetOffset, - duration: const Duration(milliseconds: 300), - curve: Curves.easeInOut, + duration: const Duration(milliseconds: 300), // 滑动动画持续时间 + curve: Curves.easeInOut, // 滑动动画曲线 ); } diff --git a/lib/pages/video/detail/introduction/widgets/season.dart b/lib/pages/video/detail/introduction/widgets/season.dart index e15197735..95ae5d603 100644 --- a/lib/pages/video/detail/introduction/widgets/season.dart +++ b/lib/pages/video/detail/introduction/widgets/season.dart @@ -61,6 +61,9 @@ class _SeasonPanelState extends State { } /// 取对应 season_id 的 episodes + // episodes = widget.ugcSeason.sections! + // .firstWhere((e) => e.seasonId == widget.ugcSeason.id) + // .episodes; currentIndex.value = episodes.indexWhere( (EpisodeItem e) => e.cid == _videoDetailController.seasonCid); _listener = _videoDetailController.cid.listen((int cid) { @@ -83,6 +86,17 @@ class _SeasonPanelState extends State { super.dispose(); } + // void changeFucCall(item, int i) async { + // await widget.changeFuc!( + // IdUtils.av2bv(item.aid), + // item.cid, + // item.aid, + // ); + // currentIndex = i; + // Get.back(); + // setState(() {}); + // } + @override Widget build(BuildContext context) { if (episodes.isEmpty) { diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index ce68bd9cd..13de64ba7 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -50,6 +50,7 @@ class _VideoReplyPanelState extends State String get heroTag => widget.heroTag; + // 添加页面缓存 @override bool get wantKeepAlive => true; diff --git a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart index 4588b6d9d..bccbf63c8 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart @@ -73,6 +73,12 @@ class ReplyItemGrpc extends StatelessWidget { }, onLongPress: () { feedBack(); + // showDialog( + // context: context, + // builder: (context) => AlertDialog( + // content: SelectableText(jsonEncode(replyItem.toProto3Json())), + // ), + // ); showModalBottomSheet( context: context, useSafeArea: true, @@ -113,6 +119,17 @@ class ReplyItemGrpc extends StatelessWidget { Positioned( top: 8, right: 12, + // child: GestureDetector( + // onTap: replyItem.member.garbCardJumpUrl.isNotEmpty + // ? () { + // Get.toNamed( + // 'webview', + // parameters: { + // 'url': replyItem.member.garbCardJumpUrl + // }, + // ); + // } + // : null, child: Stack( alignment: Alignment.centerRight, children: [ @@ -139,6 +156,7 @@ class ReplyItemGrpc extends StatelessWidget { ], ), ), + // ), SizedBox( width: double.infinity, child: _buildAuthorPanel(context), @@ -175,11 +193,12 @@ class ReplyItemGrpc extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, - children: [ + children: [ + /// fix Stack内GestureDetector onTap无效 Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, - children: [ + children: [ lfAvtar(), const SizedBox(width: 12), Column( @@ -312,8 +331,9 @@ class ReplyItemGrpc extends StatelessWidget { if (replyLevel != '') buttonAction(context, replyItem.replyControl), // 一楼的评论 if (replyLevel == '1' && - (replyItem.replies.isNotEmpty || - replyItem.replyControl.subReplyEntryText.isNotEmpty)) ...[ + ( //replyItem.replyControl!.isShow! || + replyItem.replies.isNotEmpty || + replyItem.replyControl.subReplyEntryText.isNotEmpty)) ...[ Padding( padding: const EdgeInsets.only(top: 5, bottom: 12), child: replyItemRow( @@ -597,15 +617,19 @@ class ReplyItemGrpc extends StatelessWidget { var position = textPainter.getPositionForOffset( Offset( textSize.width, - maxHeight, + maxHeight, // textSize.height, ), ); + // final endOffset = textPainter.getOffsetBefore(position.offset); message = message.substring(0, position.offset); } + // return TextSpan(text: message); + // 投票 if (content.hasVote()) { message.splitMapJoin(RegExp(r"\{vote:\d+?\}"), onMatch: (Match match) { + // String matchStr = match[0]!; spanChildren.add( TextSpan( text: '投票: ${content.vote.title}', @@ -631,7 +655,12 @@ class ReplyItemGrpc extends StatelessWidget { message = message.replaceAll(RegExp(r"\{vote:\d+?\}"), ""); } message = parse(message).body?.text ?? message; - + // .replaceAll('&', '&') + // .replaceAll('<', '<') + // .replaceAll('>', '>') + // .replaceAll('"', '"') + // .replaceAll(''', "'") + // .replaceAll(' ', ' '); // 构建正则表达式 final List specialTokens = [ ...content.emote.keys, @@ -657,6 +686,12 @@ class ReplyItemGrpc extends StatelessWidget { spanChildren.add(TextSpan( text: str, )); + // TextSpan( + // + // text: str, + // recognizer: TapGestureRecognizer() + // ..onTap = () => replyReply + // ?.call(replyItem.root == 0 ? replyItem : fReplyItem))))); } late final bool enableWordRe = @@ -965,6 +1000,7 @@ class ReplyItemGrpc extends StatelessWidget { ), ); } + // spanChildren.add(TextSpan(text: matchMember)); return TextSpan(children: spanChildren); } diff --git a/lib/pages/video/detail/reply/widgets/zan_grpc.dart b/lib/pages/video/detail/reply/widgets/zan_grpc.dart index 62eab522d..7abe7f37d 100644 --- a/lib/pages/video/detail/reply/widgets/zan_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/zan_grpc.dart @@ -23,6 +23,7 @@ class ZanButtonGrpc extends StatefulWidget { class _ZanButtonGrpcState extends State { Future onHateReply() async { feedBack(); + // SmartDialog.showLoading(msg: 'piliplus ...'); final int oid = widget.replyItem.oid.toInt(); final int rpid = widget.replyItem.id.toInt(); // 1 已点赞 2 不喜欢 0 未操作 @@ -45,6 +46,7 @@ class _ZanButtonGrpcState extends State { } widget.replyItem.replyControl.action = $fixnum.Int64(2); } else { + // replyItem.like = replyItem.like! - 1; widget.replyItem.replyControl.action = $fixnum.Int64(0); } setState(() {}); @@ -56,6 +58,7 @@ class _ZanButtonGrpcState extends State { // 评论点赞 Future onLikeReply() async { feedBack(); + // SmartDialog.showLoading(msg: 'piliplus ...'); final int oid = widget.replyItem.oid.toInt(); final int rpid = widget.replyItem.id.toInt(); // 1 已点赞 2 不喜欢 0 未操作 @@ -67,6 +70,7 @@ class _ZanButtonGrpcState extends State { rpid: rpid, action: action, ); + // SmartDialog.dismiss(); if (res['status']) { SmartDialog.showToast( widget.replyItem.replyControl.action.toInt() != 1 ? '点赞成功' : '取消赞'); diff --git a/lib/pages/video/detail/view_v.dart b/lib/pages/video/detail/view_v.dart index 2e9c96f30..bcb6ac99c 100644 --- a/lib/pages/video/detail/view_v.dart +++ b/lib/pages/video/detail/view_v.dart @@ -70,11 +70,14 @@ class _VideoDetailPageVState extends State late VideoDetailController videoDetailController; late VideoReplyController _videoReplyController; PlPlayerController? plPlayerController; + late StreamController appbarStream; late VideoIntroController videoIntroController; late BangumiIntroController bangumiIntroController; late final _introController = ScrollController(); late String heroTag; + double doubleOffset = 0; + // 自动退出全屏 late bool autoExitFullscreen; late bool autoPlayEnable; @@ -83,7 +86,12 @@ class _VideoDetailPageVState extends State late bool autoPiP; late bool pipNoDanmaku; late bool removeSafeArea; + // late bool showStatusBarBackgroundColor; + // final Floating floating = Floating(); + // 生命周期监听 + // late final AppLifecycleListener _lifecycleListener; bool isShowing = true; + // StreamSubscription? _bufferedListener; bool get isFullScreen => plPlayerController?.isFullScreen.value ?? false; bool get _shouldShowSeasonPanel => @@ -161,8 +169,13 @@ class _VideoDetailPageVState extends State setting.get(SettingBoxKey.enableVerticalExpand, defaultValue: false); removeSafeArea = setting.get(SettingBoxKey.videoPlayerRemoveSafeArea, defaultValue: false); + // showStatusBarBackgroundColor = setting.get( + // SettingBoxKey.videoPlayerShowStatusBarBackgroundColor, + // defaultValue: false); if (removeSafeArea) hideStatusBar(); videoSourceInit(); + appbarStreamListen(); + // lifecycleListener(); autoScreen(); if (Platform.isAndroid) { Utils.channel.setMethodCallHandler((call) async { @@ -223,6 +236,11 @@ class _VideoDetailPageVState extends State plPlayerController?.play(); } + // 流 + appbarStreamListen() { + appbarStream = StreamController(); + } + // 播放器状态监听 void playerListener(PlayerStatus? status) async { try { @@ -330,6 +348,27 @@ class _VideoDetailPageVState extends State await plPlayerController!.autoEnterFullscreen(); } + // // 生命周期监听 + // 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'), + // // 只作用于桌面端 + // onExitRequested: () { + // ScaffoldMessenger.maybeOf(context) + // ?.showSnackBar(const SnackBar(content: Text("拦截应用退出"))); + // return Future.value(AppExitResponse.cancel); + // }, + // ); + // } + @override void dispose() { _listenerDetail?.cancel(); @@ -357,12 +396,16 @@ class _VideoDetailPageVState extends State } videoDetailController.positionSubscription?.cancel(); videoIntroController.canelTimer(); + appbarStream.close(); + // floating.dispose(); + // videoDetailController.floating?.dispose(); videoIntroController.videoDetail.close(); videoDetailController.cid.close(); if (!horizontalScreen) { AutoOrientation.portraitUpMode(); } shutdownTimerService.handleWaitingFinished(); + // _bufferedListener?.cancel(); if (videoDetailController.plPlayerController.backToHome != true) { videoPlayerServiceHandler.onVideoDetailDispose(heroTag); } @@ -375,13 +418,16 @@ class _VideoDetailPageVState extends State PlPlayerController.updatePlayCount(); } VideoDetailPageV.routeObserver.unsubscribe(this); + // _lifecycleListener.dispose(); showStatusBar(); + // _animationController.dispose(); super.dispose(); } @override // 离开当前页面时 void didPushNext() async { + // _bufferedListener?.cancel(); if (videoDetailController.imageStatus) { return; } @@ -396,7 +442,11 @@ class _VideoDetailPageVState extends State videoDetailController.playerStatus = plPlayerController?.playerStatus.status.value; + /// 开启 + // if (setting.get(SettingBoxKey.enableAutoBrightness, defaultValue: true) + // as bool) { videoDetailController.brightness = plPlayerController?.brightness.value; + // } if (plPlayerController != null) { videoDetailController.makeHeartBeat(); videoDetailController.showVP = plPlayerController!.showVP.value; @@ -441,6 +491,7 @@ class _VideoDetailPageVState extends State } } super.didPopNext(); + // final bool autoplay = autoPlayEnable; videoDetailController.autoPlay.value = !videoDetailController.isShowCover.value; if (videoDetailController.isShowCover.value.not) { @@ -453,6 +504,29 @@ class _VideoDetailPageVState extends State await videoDetailController.playerInit(); } + // if (videoDetailController.playerStatus == PlayerStatus.playing) { + // plPlayerController?.play(); + // } + + /// 未开启自动播放时,未播放跳转下一页返回/播放后跳转下一页返回 + // if (autoplay) { + // // await Future.delayed(const Duration(milliseconds: 300)); + // debugPrint(plPlayerController); + // if (plPlayerController?.buffered.value == Duration.zero) { + // _bufferedListener = plPlayerController?.buffered.listen((p0) { + // debugPrint("p0"); + // debugPrint(p0); + // if (p0 > Duration.zero) { + // _bufferedListener!.cancel(); + // plPlayerController?.seekTo(videoDetailController.defaultST); + // plPlayerController?.play(); + // } + // }); + // } else { + // plPlayerController?.seekTo(videoDetailController.defaultST); + // plPlayerController?.play(); + // } + // } Future.delayed(const Duration(milliseconds: 600), () { AutoOrientation.fullAutoMode(); }); @@ -470,6 +544,17 @@ class _VideoDetailPageVState extends State : Theme.of(context); } + // void _handleTransition(String name) { + // switch (name) { + // case 'inactive': + // if (plPlayerController != null && + // playerStatus == PlayerStatus.playing) { + // autoEnterPip(); + // } + // break; + // } + // } + void enterPip() { if (Get.currentRoute.startsWith('/video') && videoDetailController.floating != null) { @@ -539,8 +624,8 @@ class _VideoDetailPageVState extends State bottom: !removeSafeArea && MediaQuery.of(context).orientation == Orientation.portrait && isFullScreen, - left: false, - right: false, + left: false, //!isFullScreen, + right: false, //!isFullScreen, child: Scaffold( resizeToAvoidBottomInset: false, key: videoDetailController.scaffoldKey, @@ -1096,6 +1181,41 @@ class _VideoDetailPageVState extends State ), ), ), + // Expanded( + // child: TabBarView( + // physics: const ClampingScrollPhysics(), + // controller: videoDetailController.tabCtr, + // children: [ + // CustomScrollView( + // key: const PageStorageKey('简介'), + // slivers: [ + // if (videoDetailController.videoType == + // SearchType.video) ...[ + // const VideoIntroPanel(), + // ] else if (videoDetailController.videoType == + // SearchType.media_bangumi) ...[ + // Obx(() => BangumiIntroPanel( + // cid: videoDetailController.cid.value)), + // ], + // SliverToBoxAdapter( + // child: Divider( + // indent: 12, + // endIndent: 12, + // color: themeData.dividerColor.withOpacity(0.06), + // ), + // ), + // const RelatedVideoPanel(), + // ], + // ), + // Obx( + // () => VideoReplyPanel( + // bvid: videoDetailController.bvid, + // oid: videoDetailController.oid.value, + // ), + // ) + // ], + // ), + // ), ], ); } @@ -1199,7 +1319,7 @@ class _VideoDetailPageVState extends State left: !removeSafeArea && !isFullScreen, right: !removeSafeArea && !isFullScreen, top: !removeSafeArea, - bottom: false, + bottom: false, //!removeSafeArea, child: childWhenDisabledLandscapeInner, ), ), @@ -1219,7 +1339,7 @@ class _VideoDetailPageVState extends State left: !removeSafeArea && !isFullScreen, right: !removeSafeArea && !isFullScreen, top: !removeSafeArea, - bottom: false, + bottom: false, //!removeSafeArea, child: childWhenDisabledAlmostSquareInner, ), ); @@ -1460,14 +1580,53 @@ class _VideoDetailPageVState extends State return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { + // if (!isShowing) { + // return ColoredBox(color: themeData.colorScheme.surface); + // } if (constraints.maxWidth > constraints.maxHeight * 1.25) { +// hideStatusBar(); +// videoDetailController.hiddenReplyReplyPanel(); return autoChoose(childWhenDisabledLandscape); } else if (constraints.maxWidth * (9 / 16) < (2 / 5) * constraints.maxHeight) { + // if (!isFullScreen) { + // if (!removeSafeArea) showStatusBar(); + // } return autoChoose(childWhenDisabled); } else { + // if (!isFullScreen) { + // if (!removeSafeArea) showStatusBar(); + // } return autoChoose(childWhenDisabledAlmostSquare); } + // + // final Orientation orientation = + // constraints.maxWidth > constraints.maxHeight * 1.25 + // ? Orientation.landscape + // : Orientation.portrait; + // if (orientation == Orientation.landscape) { + // if (!horizontalScreen) { + // hideStatusBar(); + // videoDetailController.hiddenReplyReplyPanel(); + // } + // } else { + // if (!isFullScreen) { + // showStatusBar(); + // } + // } + // if (Platform.isAndroid) { + // return PiPSwitcher( + // childWhenDisabled: + // !horizontalScreen || orientation == Orientation.portrait + // ? childWhenDisabled + // : childWhenDisabledLandscape, + // childWhenEnabled: childWhenEnabled, + // floating: floating, + // ); + // } + // return !horizontalScreen || orientation == Orientation.portrait + // ? childWhenDisabled + // : childWhenDisabledLandscape; }, ); } @@ -1512,7 +1671,8 @@ class _VideoDetailPageVState extends State labelStyle: TabBarTheme.of(context).labelStyle?.copyWith(fontSize: 13) ?? const TextStyle(fontSize: 13), - labelPadding: const EdgeInsets.symmetric(horizontal: 10.0), + labelPadding: + const EdgeInsets.symmetric(horizontal: 10.0), // 设置每个标签的宽度 dividerColor: Colors.transparent, dividerHeight: 0, onTap: (value) { @@ -1934,6 +2094,8 @@ class _VideoDetailPageVState extends State bvid: videoDetailController.bvid, aid: IdUtils.bv2av(videoDetailController.bvid), cid: videoDetailController.cid.value, + // count: videoIntroController.videoDetail.value.pages!.length, + // name: videoIntroController.videoDetail.value.pages!, isReversed: videoIntroController.videoDetail.value.isPageReversed, changeFucCall: videoDetailController.videoType == @@ -1984,6 +2146,10 @@ class _VideoDetailPageVState extends State videoIntroController.videoDetail.value.ugcSeason!.id, list: videoIntroController .videoDetail.value.ugcSeason!.sections!, + // count: videoIntroController + // .videoDetail.value.ugcSeason!.epCount!, + // name: + // videoIntroController.videoDetail.value.ugcSeason!.title!, bvid: videoDetailController.bvid, aid: IdUtils.bv2av(videoDetailController.bvid), cid: videoDetailController.seasonCid ?? 0, diff --git a/lib/pages/video/detail/widgets/ai_detail.dart b/lib/pages/video/detail/widgets/ai_detail.dart index 14a470b4d..8551f90b2 100644 --- a/lib/pages/video/detail/widgets/ai_detail.dart +++ b/lib/pages/video/detail/widgets/ai_detail.dart @@ -45,9 +45,11 @@ class _AiDetailState extends CommonCollapseSlidePageState { spanChildren.add( TextSpan( text: match.group(0), - style: TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle( + color: Theme.of(context).colorScheme.primary), // 设置颜色为蓝色 recognizer: TapGestureRecognizer() ..onTap = () { + // 处理点击事件 try { PageUtils.handleWebview(match.group(0)!); } catch (err) { diff --git a/lib/pages/video/detail/widgets/app_bar.dart b/lib/pages/video/detail/widgets/app_bar.dart index ca475093d..187292397 100644 --- a/lib/pages/video/detail/widgets/app_bar.dart +++ b/lib/pages/video/detail/widgets/app_bar.dart @@ -50,6 +50,15 @@ class ScrollAppBar extends StatelessWidget { ], ), ), + // actions: [ + // IconButton( + // onPressed: () {}, + // icon: const Icon( + // Icons.share, + // size: 20, + // )), + // const SizedBox(width: 12) + // ], ), ), ), diff --git a/lib/pages/video/detail/widgets/expandable_section.dart b/lib/pages/video/detail/widgets/expandable_section.dart new file mode 100644 index 000000000..8d8b2c422 --- /dev/null +++ b/lib/pages/video/detail/widgets/expandable_section.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; + +class ExpandedSection extends StatefulWidget { + final Widget? child; + final bool expand; + final double begin; + final double end; + + const ExpandedSection({ + super.key, + this.expand = false, + this.child, + this.begin = 0.0, + this.end = 1.0, + }); + + @override + State createState() => _ExpandedSectionState(); +} + +class _ExpandedSectionState extends State + with SingleTickerProviderStateMixin { + late AnimationController expandController; + late Animation animation; + + @override + void initState() { + super.initState(); + prepareAnimations(); + _runExpandCheck(); + } + + void prepareAnimations() { + expandController = AnimationController( + vsync: this, duration: const Duration(milliseconds: 400)); + Animation curve = CurvedAnimation( + parent: expandController, + curve: Curves.fastOutSlowIn, + ); + animation = Tween(begin: widget.begin, end: widget.end).animate(curve); + // animation = CurvedAnimation( + // parent: expandController, + // curve: Curves.fastOutSlowIn, + // ); + } + + void _runExpandCheck() { + if (widget.expand) { + expandController.forward(); + } else { + expandController.reverse(); + } + } + + @override + void didUpdateWidget(ExpandedSection oldWidget) { + super.didUpdateWidget(oldWidget); + _runExpandCheck(); + } + + @override + void dispose() { + expandController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SizeTransition( + axisAlignment: -1.0, + sizeFactor: animation, + child: widget.child, + ); + } +} diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 1b49f9193..d46fe29b0 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -131,6 +131,31 @@ class HeaderControlState extends State { padding: EdgeInsets.zero, children: [ const SizedBox(height: 14), + // ListTile( + // onTap: () {}, + // dense: true, + // enabled: false, + // leading: + // const Icon(Icons.network_cell_outlined, size: 20), + // title: Text('省流模式', style: titleStyle), + // subtitle: Text('低画质 | 减少视频缓存', style: subTitleStyle), + // trailing: Transform.scale( + // scale: 0.75, + // child: Switch( + // 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. + // }), + // value: false, + // onChanged: (value) => {}, + // ), + // ), + // ), + // if (videoDetailCtr.userInfo != null) ListTile( dense: true, onTap: () { @@ -339,6 +364,7 @@ class HeaderControlState extends State { }; }, ), + ListTile( dense: true, onTap: () => {Get.back(), showSetVideoQa()}, @@ -1227,6 +1253,7 @@ class HeaderControlState extends State { min: 0, max: 1, value: subtitleBgOpaticy, + // label: '${(subtitleBgOpaticy * 100).toInt()}%', onChanged: (double val) { updateOpacity(val.toPrecision(2)); }, @@ -1264,6 +1291,13 @@ class HeaderControlState extends State { {'value': 6, 'label': '彩色'}, ]; final List blockTypes = widget.controller.blockTypes; + // 显示区域 + // final List> showAreas = [ + // {'value': 0.25, 'label': '1/4屏'}, + // {'value': 0.5, 'label': '半屏'}, + // {'value': 0.75, 'label': '3/4屏'}, + // {'value': 1.0, 'label': '满屏'}, + // ]; // 智能云屏蔽 int danmakuWeight = widget.controller.danmakuWeight; // 显示区域 @@ -1780,6 +1814,7 @@ class HeaderControlState extends State { min: 1.0, max: 3.0, value: danmakuLineHeight, + // label: '$danmakuLineHeight', onChanged: (double val) { updateLineHeight(val.toPrecision(1)); }, @@ -2017,6 +2052,14 @@ class HeaderControlState extends State { return SizedBox.shrink(); }, ), + // ComBtn( + // icon: const Icon( + // FontAwesomeIcons.cropSimple, + // size: 15, + // color: Colors.white, + // ), + // fuc: () => _.screenshot(), + // ), if (videoDetailCtr.enableSponsorBlock == true) SizedBox( width: 42, @@ -2096,6 +2139,9 @@ class HeaderControlState extends State { !plPlayerController.isOpenDanmu.value; setting.put(SettingBoxKey.enableShowDanmaku, plPlayerController.isOpenDanmu.value); + // SmartDialog.showToast( + // "已${plPlayerController.isOpenDanmu.value ? '开启' : '关闭'}弹幕", + // displayTime: const Duration(seconds: 1)); }, icon: Icon( plPlayerController.isOpenDanmu.value @@ -2125,6 +2171,9 @@ class HeaderControlState extends State { SettingBoxKey.enableBackgroundPlay, defaultValue: true); if (!enableBackgroundPlay && mounted) { + // SmartDialog.showToast('建议开启【后台播放】功能\n避免画中画没有暂停按钮'); + // await Future.delayed(const Duration(seconds: 2), () { + // }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Column( @@ -2162,6 +2211,7 @@ class HeaderControlState extends State { plPlayerController .setBackgroundPlay(true); SmartDialog.showToast("请重新载入本页面刷新"); + // Get.back(); }, child: const Text('启用后台音频服务')), const SizedBox(width: 10), @@ -2460,6 +2510,9 @@ class HeaderControlState extends State { @override Widget build(BuildContext context) { + // final bool isLandscape = + // MediaQuery.of(context).orientation == Orientation.landscape; + return plPlayerController.showFSActionItem ? Obx(() => _buildHeader(true)) : _buildHeader(false); diff --git a/lib/pages/webdav/webdav.dart b/lib/pages/webdav/webdav.dart index cefd038b2..f1a8e6d7a 100644 --- a/lib/pages/webdav/webdav.dart +++ b/lib/pages/webdav/webdav.dart @@ -6,6 +6,9 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:webdav_client/webdav_client.dart' as webdav; class WebDav { + late String _webDavUri; + late String _webDavUsername; + late String _webDavPassword; late String _webdavDirectory; webdav.Client? _client; @@ -15,9 +18,9 @@ class WebDav { factory WebDav() => _instance; Future> init() async { - final webDavUri = GStorage.webdavUri; - final webDavUsername = GStorage.webdavUsername; - final webDavPassword = GStorage.webdavPassword; + _webDavUri = GStorage.webdavUri; + _webDavUsername = GStorage.webdavUsername; + _webDavPassword = GStorage.webdavPassword; _webdavDirectory = GStorage.webdavDirectory; if (_webdavDirectory.endsWith('/').not) { _webdavDirectory += '/'; @@ -27,9 +30,9 @@ class WebDav { try { _client = null; final client = webdav.newClient( - webDavUri, - user: webDavUsername, - password: webDavPassword, + _webDavUri, + user: _webDavUsername, + password: _webDavPassword, ) ..setHeaders({'accept-charset': 'utf-8'}) ..setConnectTimeout(4000) diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index 567ae8d96..3b1f9cc4b 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -160,6 +160,14 @@ class _WhisperDetailPageState style: TextStyle(fontSize: 14), ), ), + // ListTile( + // onTap: () { + // Get.back(); + // }, + // dense: true, + // title: const Text('删除', + // style: TextStyle(fontSize: 14)), + // ), ], ), ); diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 9c0682da4..92d5d08f5 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -397,9 +397,10 @@ class ChatItem extends StatelessWidget { onTap: () async { Get.toNamed('/htmlRender', parameters: { 'url': "https://www.bilibili.com/read/cv${content['rid']}/", + // 'url': url.startsWith('//') ? url.split('//').last : url, 'title': content['title'] ?? "", 'id': "cv${content['rid']}", - 'dynamicType': "read" + 'dynamicType': "read" //content['template_id'] ?? "", }); }, child: Column( diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 19c969635..217a69356 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -1074,7 +1074,20 @@ class PlPlayerController { _playbackSpeed.value = speed; } + /// 设置倍速 + // Future togglePlaybackSpeed() async { + // List allowedSpeeds = + // PlaySpeed.values.map((e) => e.value).toList(); + // int index = allowedSpeeds.indexOf(_playbackSpeed.value); + // if (index < allowedSpeeds.length - 1) { + // setPlaybackSpeed(allowedSpeeds[index + 1]); + // } else { + // setPlaybackSpeed(allowedSpeeds[0]); + // } + // } + /// 播放视频 + /// TODO _duration.value丢失 Future play({bool repeat = false, bool hideControls = true}) async { if (_playerCount.value == 0) return; // 播放时自动隐藏控制条 @@ -1091,6 +1104,14 @@ class PlPlayerController { // screenManager.setOverlays(false); audioSessionHandler.setActive(true); + + // Future.delayed(const Duration(milliseconds: 100), () { + // getCurrentVolume(); + // if (setting.get(SettingBoxKey.enableAutoBrightness, defaultValue: true) + // as bool) { + // getCurrentBrightness(); + // } + // }); } /// 暂停播放 @@ -1225,6 +1246,46 @@ class PlPlayerController { _videoFitDesc.value = videoFitType[value.index]['desc']; setVideoFit(); getPlayerKey?.call().currentState?.update(fit: value); + // showDialog( + // context: Get.context!, + // builder: (context) { + // return AlertDialog( + // title: const Text('视频尺寸'), + // content: StatefulBuilder(builder: (context, StateSetter setState) { + // return Wrap( + // alignment: WrapAlignment.start, + // spacing: 8, + // runSpacing: 2, + // children: [ + // for (var i in videoFitType) ...[ + // if (_videoFit.value == i['attr']) ...[ + // FilledButton( + // onPressed: () async { + // _videoFit.value = i['attr']; + // _videoFitDesc.value = i['desc']; + // setVideoFit(); + // Get.back(); + // }, + // child: Text(i['desc']), + // ), + // ] else ...[ + // FilledButton.tonal( + // onPressed: () async { + // _videoFit.value = i['attr']; + // _videoFitDesc.value = i['desc']; + // setVideoFit(); + // Get.back(); + // }, + // child: Text(i['desc']), + // ), + // ] + // ] + // ], + // ); + // }), + // ); + // }, + // ); } /// 缓存fit diff --git a/lib/plugin/pl_player/models/play_speed.dart b/lib/plugin/pl_player/models/play_speed.dart index 39a8898b3..66337e833 100644 --- a/lib/plugin/pl_player/models/play_speed.dart +++ b/lib/plugin/pl_player/models/play_speed.dart @@ -1,4 +1,5 @@ enum PlaySpeed { + // pointTwoFive, pointFive, pointSevenFive, @@ -13,6 +14,7 @@ enum PlaySpeed { extension PlaySpeedExtension on PlaySpeed { static final List _descList = [ + // '0.25', '0.5', '0.75', '正常', @@ -25,6 +27,7 @@ extension PlaySpeedExtension on PlaySpeed { String get description => _descList[index]; static final List _valueList = [ + // 0.25, 0.5, 0.75, 1.0, diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 04e1234eb..0f859f274 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -1645,7 +1645,7 @@ class _PLVideoPlayerState extends State ), ), ), - + // Obx(() { if (plPlayerController.dataStatus.loading || plPlayerController.isBuffering.value) { @@ -1888,6 +1888,14 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) { padding: EdgeInsets.only(left: left), child: UnconstrainedBox( child: ClipRRect( + // clipBehavior: Clip.antiAlias, + // decoration: BoxDecoration( + // border: Border.all( + // color: Colors.white, + // strokeAlign: BorderSide.strokeAlignOutside, + // ), + // borderRadius: BorderRadius.circular(scale == 2.5 ? 6 : 10), + // ), borderRadius: BorderRadius.circular(scale == 2.5 ? 6 : 10), child: Align( widthFactor: 0.1, diff --git a/lib/plugin/pl_player/widgets/backward_seek.dart b/lib/plugin/pl_player/widgets/backward_seek.dart index 6e0983c61..0c288fe7f 100644 --- a/lib/plugin/pl_player/widgets/backward_seek.dart +++ b/lib/plugin/pl_player/widgets/backward_seek.dart @@ -3,11 +3,13 @@ import 'dart:async'; import 'package:flutter/material.dart'; class BackwardSeekIndicator extends StatefulWidget { + // final void Function(Duration) onChanged; final ValueChanged onSubmitted; final int duration; const BackwardSeekIndicator({ super.key, + // required this.onChanged, required this.onSubmitted, required this.duration, }); @@ -41,6 +43,8 @@ class BackwardSeekIndicatorState extends State { timer = Timer(const Duration(milliseconds: 400), () { widget.onSubmitted.call(duration); }); + // widget.onChanged.call(value); + // 重复点击 快退秒数累加10 setState(() { duration += Duration(seconds: widget.duration); }); diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart index cdc34a4bb..ab095e039 100644 --- a/lib/plugin/pl_player/widgets/bottom_control.dart +++ b/lib/plugin/pl_player/widgets/bottom_control.dart @@ -50,7 +50,9 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { return Padding( padding: const EdgeInsets.only(left: 10, right: 10, bottom: 7), child: Semantics( + // label: '${(value / max * 100).round()}%', value: '${(value / max * 100).round()}%', + // enabled: false, child: Stack( clipBehavior: Clip.none, alignment: Alignment.bottomCenter, diff --git a/lib/plugin/pl_player/widgets/forward_seek.dart b/lib/plugin/pl_player/widgets/forward_seek.dart index 10d54a8b5..156f4e340 100644 --- a/lib/plugin/pl_player/widgets/forward_seek.dart +++ b/lib/plugin/pl_player/widgets/forward_seek.dart @@ -3,11 +3,13 @@ import 'dart:async'; import 'package:flutter/material.dart'; class ForwardSeekIndicator extends StatefulWidget { + // final void Function(Duration) onChanged; final ValueChanged onSubmitted; final int duration; const ForwardSeekIndicator({ super.key, + // required this.onChanged, required this.onSubmitted, required this.duration, }); @@ -41,6 +43,8 @@ class ForwardSeekIndicatorState extends State { timer = Timer(const Duration(milliseconds: 400), () { widget.onSubmitted.call(duration); }); + // widget.onChanged.call(value); + // 重复点击 快进秒数累加10 setState(() { duration += Duration(seconds: widget.duration); }); diff --git a/lib/plugin/pl_player/widgets/play_pause_btn.dart b/lib/plugin/pl_player/widgets/play_pause_btn.dart index 2e2a8f120..3ec37c1f5 100644 --- a/lib/plugin/pl_player/widgets/play_pause_btn.dart +++ b/lib/plugin/pl_player/widgets/play_pause_btn.dart @@ -77,6 +77,8 @@ class PlayOrPauseButtonState extends State player.playOrPause(); } }, + // iconSize: widget.iconSize ?? _theme(context).buttonBarButtonSize, + // color: widget.iconColor ?? _theme(context).buttonBarButtonColor, child: Center( child: AnimatedIcon( semanticLabel: @@ -87,6 +89,8 @@ class PlayOrPauseButtonState extends State icon: AnimatedIcons.play_pause, color: Colors.white, size: 20, + // size: widget.iconSize ?? _theme(context).buttonBarButtonSize, + // color: widget.iconColor ?? _theme(context).buttonBarButtonColor, ), ), ), diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 21c74d7fa..2d4f5fab9 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -100,6 +100,9 @@ class Routes { // 用户中心 CustomGetPage(name: '/member', page: () => const MemberPageNew()), CustomGetPage(name: '/memberSearch', page: () => const MemberSearchPage()), + // 二级回复 + // CustomGetPage( + // name: '/replyReply', page: () => const VideoReplyReplyPanel()), // 推荐流设置 CustomGetPage( name: '/recommendSetting', page: () => const RecommendSetting()), @@ -154,6 +157,10 @@ class Routes { // 用户动态 CustomGetPage( name: '/memberDynamics', page: () => const MemberDynamicsPage()), + // 用户最近投币 + // CustomGetPage(name: '/memberCoin', page: () => const MemberCoinPage()), + // 用户最近喜欢 + // CustomGetPage(name: '/memberLike', page: () => const MemberLikePage()), // 日志 CustomGetPage(name: '/logs', page: () => const LogsPage()), // 订阅 diff --git a/lib/utils/app_scheme.dart b/lib/utils/app_scheme.dart index 14f437ca6..13eab0ef5 100644 --- a/lib/utils/app_scheme.dart +++ b/lib/utils/app_scheme.dart @@ -595,6 +595,23 @@ class PiliScheme { } launchURL(); return false; + // case 'opus': + // String? id = uriDigitRegExp.firstMatch(path)?.group(1); + // if (id != null) { + // PageUtils.toDupNamed( + // '/htmlRender', + // parameters: { + // 'url': 'https://www.bilibili.com/opus/$id', + // 'title': '', + // 'id': id, + // 'dynamicType': 'opus' + // }, + // off: off, + // ); + // return true; + // } + // launchURL(); + // return false; case 'dynamic' || 'opus': bool hasMatch = await _onPushDynDetail(path, off); if (hasMatch.not) { diff --git a/lib/utils/download.dart b/lib/utils/download.dart index aee36b588..5b458e5cd 100644 --- a/lib/utils/download.dart +++ b/lib/utils/download.dart @@ -79,6 +79,24 @@ 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('去授权'), + // ) + // ], + // ); + // }, + // ); return false; } else { return true; diff --git a/lib/utils/em.dart b/lib/utils/em.dart index 6544159da..0ffd9952c 100644 --- a/lib/utils/em.dart +++ b/lib/utils/em.dart @@ -30,5 +30,15 @@ class Em { static String decodeHtmlEntities(String title) { return parse(title).body?.text ?? title; + // return title + // .replaceAll('<', '<') + // .replaceAll('>', '>') + // .replaceAll('"', '"') + // .replaceAll(''', "'") + // .replaceAll('"', '"') + // .replaceAll(''', "'") + // .replaceAll(' ', " ") + // .replaceAll('&', "&") + // .replaceAll(''', "'"); } } diff --git a/lib/utils/page_utils.dart b/lib/utils/page_utils.dart index 557746934..fda9be077 100644 --- a/lib/utils/page_utils.dart +++ b/lib/utils/page_utils.dart @@ -160,7 +160,8 @@ class PageUtils { contentPadding: const EdgeInsets.only(), title: const Text("额外等待视频播放完毕", style: titleStyle), trailing: Transform.scale( - alignment: Alignment.centerRight, + alignment: Alignment + .centerRight, // 缩放Switch的大小后保持右侧对齐, 避免右侧空隙过大 scale: 0.8, child: Switch( thumbIcon: WidgetStateProperty.resolveWith( @@ -188,15 +189,18 @@ class PageUtils { onTap: () { shutdownTimerService.exitApp = false; setState(() {}); + // Get.back(); }, text: " 暂停视频 ", selectStatus: !shutdownTimerService.exitApp, ), const Spacer(), + // const SizedBox(width: 10), ActionRowLineItem( onTap: () { shutdownTimerService.exitApp = true; setState(() {}); + // Get.back(); }, text: " 退出APP ", selectStatus: shutdownTimerService.exitApp, diff --git a/lib/utils/recommend_filter.dart b/lib/utils/recommend_filter.dart index 336c18a8c..5cd541ba4 100644 --- a/lib/utils/recommend_filter.dart +++ b/lib/utils/recommend_filter.dart @@ -4,6 +4,7 @@ import 'package:hive/hive.dart'; import 'storage.dart'; class RecommendFilter { + // static late int filterUnfollowedRatio; static late int minDurationForRcmd; static late int minPlayForRcmd; static late int minLikeRatioForRecommend; @@ -19,6 +20,8 @@ class RecommendFilter { static Box get setting => GStorage.setting; static void update() { + // filterUnfollowedRatio = + // setting.get(SettingBoxKey.filterUnfollowedRatio, defaultValue: 0); minDurationForRcmd = setting.get(SettingBoxKey.minDurationForRcmd, defaultValue: 0); minPlayForRcmd = setting.get(SettingBoxKey.minPlayForRcmd, defaultValue: 0); diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index bb51dd201..1f186b1ed 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -44,6 +44,10 @@ class GStorage { static late final Box setting; static late final Box video; + // static bool get isLogin => userInfo.get('userInfoCache') != null; + + // static get ownerMid => userInfo.get('userInfoCache')?.mid; + static List get speedList => List.from( video.get( VideoBoxKey.speedsList, @@ -638,6 +642,7 @@ class SettingBoxKey { // ignore: constant_identifier_names CDNService = 'CDNService', disableAudioCDN = 'disableAudioCDN', + // enableCDN = 'enableCDN', autoPiP = 'autoPiP', pipNoDanmaku = 'pipNoDanmaku', enableAutoLongPressSpeed = 'enableAutoLongPressSpeed', @@ -664,6 +669,7 @@ class SettingBoxKey { minLikeRatioForRecommend = 'minLikeRatioForRecommend', exemptFilterForFollowed = 'exemptFilterForFollowed', banWordForRecommend = 'banWordForRecommend', + //filterUnfollowedRatio = 'filterUnfollowedRatio', applyFilterToRelatedVideos = 'applyFilterToRelatedVideos', /// 其他 @@ -800,6 +806,8 @@ class SettingBoxKey { displayMode = 'displayMode', smallCardWidth = 'smallCardWidth', videoPlayerRemoveSafeArea = 'videoPlayerRemoveSafeArea', // 视频播放器移除安全边距 + // videoPlayerShowStatusBarBackgroundColor = + // 'videoPlayerShowStatusBarBackgroundColor', // 播放页状态栏显示为背景色 dynamicsWaterfallFlow = 'dynamicsWaterfallFlow', // 动态瀑布流 upPanelPosition = 'upPanelPosition', // up主面板位置 dynamicsShowAllFollowedUp = 'dynamicsShowAllFollowedUp', // 动态显示全部关注up @@ -810,6 +818,7 @@ class SettingBoxKey { tabbarSort = 'tabbarSort', // 首页tabbar dynamicBadgeMode = 'dynamicBadgeMode', msgBadgeMode = 'msgBadgeMode', + // msgUnReadType = 'msgUnReadType', msgUnReadTypeV2 = 'msgUnReadTypeV2', hiddenSettingUnlocked = 'hiddenSettingUnlocked', enableGradientBg = 'enableGradientBg', diff --git a/lib/utils/theme_utils.dart b/lib/utils/theme_utils.dart index fb2de4d94..b4f28c76c 100644 --- a/lib/utils/theme_utils.dart +++ b/lib/utils/theme_utils.dart @@ -81,6 +81,9 @@ class ThemeUtils { : null, shadowColor: Colors.transparent, ), + // dialogTheme: DialogTheme( + // surfaceTintColor: isDark ? colorScheme.onSurfaceVariant : null, + // ), progressIndicatorTheme: ProgressIndicatorThemeData( refreshBackgroundColor: colorScheme.onSecondary, ), diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 93bc15739..098f60f92 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -147,6 +147,14 @@ class Utils { return base64Encoded; } + // static String genRandomString(int length) { + // const characters = '0123456789abcdefghijklmnopqrstuvwxyz'; + // Random random = Random(); + // return List.generate( + // length, (index) => characters[random.nextInt(characters.length)]) + // .join(); + // } + static String genTraceId() { String randomId = generateRandomString(32);