diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart index 89e1899d9..b591f08f2 100644 --- a/lib/common/widgets/network_img_layer.dart +++ b/lib/common/widgets/network_img_layer.dart @@ -49,37 +49,45 @@ class NetworkImgLayer extends StatelessWidget { memCacheWidth = width.cacheSize(context); // memCacheHeight = height.cacheSize(context); } - Widget res = src != null && src != '' - ? ClipRRect( - clipBehavior: Clip.antiAlias, - borderRadius: BorderRadius.circular( - type == 'avatar' - ? 50 - : type == 'emote' - ? 0 - : StyleString.imgRadius.x, - ), - child: CachedNetworkImage( - imageUrl: - '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp', - width: width, - height: - ignoreHeight == null || ignoreHeight == false ? height : null, - memCacheWidth: memCacheWidth, - memCacheHeight: memCacheHeight, - fit: BoxFit.cover, - fadeOutDuration: - fadeOutDuration ?? const Duration(milliseconds: 120), - fadeInDuration: - fadeInDuration ?? const Duration(milliseconds: 120), - filterQuality: FilterQuality.low, - errorWidget: (BuildContext context, String url, Object error) => - placeholder(context), - placeholder: (BuildContext context, String url) => - placeholder(context), - ), - ) - : placeholder(context); + late Widget res; + if (src?.isEmpty != false) { + res = placeholder(context); + } else { + String srcUrl = src!; + if (srcUrl.startsWith('http://')) { + srcUrl = srcUrl.substring(5); + } + if (srcUrl.startsWith('//')) { + srcUrl = 'https:$srcUrl'; + } + print(srcUrl); + res = ClipRRect( + clipBehavior: Clip.antiAlias, + borderRadius: BorderRadius.circular( + type == 'avatar' + ? 50 + : type == 'emote' + ? 0 + : StyleString.imgRadius.x, + ), + child: CachedNetworkImage( + imageUrl: + '$srcUrl@${quality ?? defaultImgQuality}q.webp', + width: width, + height: ignoreHeight == null || ignoreHeight == false ? height : null, + memCacheWidth: memCacheWidth, + memCacheHeight: memCacheHeight, + fit: BoxFit.cover, + fadeOutDuration: fadeOutDuration ?? const Duration(milliseconds: 120), + fadeInDuration: fadeInDuration ?? const Duration(milliseconds: 120), + filterQuality: FilterQuality.low, + errorWidget: (BuildContext context, String url, Object error) => + placeholder(context), + placeholder: (BuildContext context, String url) => + placeholder(context), + ), + ); + } if (semanticsLabel != null) { return Semantics( label: semanticsLabel, diff --git a/lib/http/api.dart b/lib/http/api.dart index 2c337dc0f..480576e7f 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -102,11 +102,10 @@ class Api { // csrf str CSRF Token(位于cookie) 必要 // 一键三连 - // https://api.bilibili.com/x/web-interface/archive/like/triple - // aid num 稿件avid 必要(可选) avid与bvid任选一个 - // bvid str 稿件bvid 必要(可选) avid与bvid任选一个 - // csrf str CSRF Token(位于cookie) 必要 - static const String oneThree = '/x/web-interface/archive/like/triple'; + // https://app.bilibili.com/x/v2/view/like/triple + // access_key str APP 登录 Token APP 方式必要 + // aid num 稿件 avid 必要 + static const String oneThree = '${HttpString.appBaseUrl}/x/v2/view/like/triple'; // 获取指定用户创建的所有收藏夹信息 // 该接口也能查询目标内容id存在于那些收藏夹中 diff --git a/lib/http/video.dart b/lib/http/video.dart index 43328c37e..01478e8aa 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -1,4 +1,5 @@ import 'dart:developer'; +import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:hive/hive.dart'; @@ -345,10 +346,12 @@ class VideoHttp { var res = await Request().post( Api.oneThree, queryParameters: { - 'bvid': bvid, - 'csrf': await Request.getCsrf(), + 'aid': IdUtils.bv2av(bvid), + 'access_key': GStorage.localCache + .get(LocalCacheKey.accessKey, defaultValue: {})['value'], }, ); + print(res); if (res.data['code'] == 0) { return {'status': true, 'data': res.data['data']}; } else { diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index 935bfc688..aa7c50529 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -69,7 +69,7 @@ class VideoDetailController extends GetxController // int fRpid = 0; // ReplyItemModel? firstFloor; - final scaffoldKey = GlobalKey(); + // final scaffoldKey = GlobalKey(); RxString bgCover = ''.obs; PlPlayerController? plPlayerController; diff --git a/lib/pages/video/introduction/detail/controller.dart b/lib/pages/video/introduction/detail/controller.dart index bdee2ee17..643816337 100644 --- a/lib/pages/video/introduction/detail/controller.dart +++ b/lib/pages/video/introduction/detail/controller.dart @@ -578,17 +578,18 @@ class VideoIntroController extends GetxController { bool prevPlay() { final List episodes = []; bool isPages = false; - if (videoDetail.value.ugcSeason != null) { + if (videoDetail.value.pages != null && + videoDetail.value.pages!.length > 1) { + isPages = true; + final List pages = videoDetail.value.pages!; + episodes.addAll(pages); + } else if (videoDetail.value.ugcSeason != null) { final UgcSeason ugcSeason = videoDetail.value.ugcSeason!; final List sections = ugcSeason.sections!; for (int i = 0; i < sections.length; i++) { final List episodesList = sections[i].episodes!; episodes.addAll(episodesList); } - } else if (videoDetail.value.pages != null) { - isPages = true; - final List pages = videoDetail.value.pages!; - episodes.addAll(pages); } final int currentIndex = @@ -613,16 +614,17 @@ class VideoIntroController extends GetxController { // 是否有下一集(必须存在分p、分集) bool hasNextEpisode() { final List episodes = []; - if (videoDetail.value.ugcSeason != null) { + if (videoDetail.value.pages != null && + videoDetail.value.pages!.length > 1) { + final List pages = videoDetail.value.pages!; + episodes.addAll(pages); + } else if (videoDetail.value.ugcSeason != null) { final UgcSeason ugcSeason = videoDetail.value.ugcSeason!; final List sections = ugcSeason.sections!; for (int i = 0; i < sections.length; i++) { final List episodesList = sections[i].episodes!; episodes.addAll(episodesList); } - } else if (videoDetail.value.pages != null) { - final List pages = videoDetail.value.pages!; - episodes.addAll(pages); } if (episodes.isEmpty) { return false; @@ -638,19 +640,21 @@ class VideoIntroController extends GetxController { /// 列表循环或者顺序播放时,自动播放下一个 bool nextPlay() { + print("entering nextPlay"); final List episodes = []; bool isPages = false; - if (videoDetail.value.ugcSeason != null) { + if (videoDetail.value.pages != null && + videoDetail.value.pages!.length > 1) { + isPages = true; + final List pages = videoDetail.value.pages!; + episodes.addAll(pages); + } else if (videoDetail.value.ugcSeason != null) { final UgcSeason ugcSeason = videoDetail.value.ugcSeason!; final List sections = ugcSeason.sections!; for (int i = 0; i < sections.length; i++) { final List episodesList = sections[i].episodes!; episodes.addAll(episodesList); } - } else if (videoDetail.value.pages != null) { - isPages = true; - final List pages = videoDetail.value.pages!; - episodes.addAll(pages); } PlayRepeat playRepeat = PlPlayerController.getInstance().playRepeat; if (episodes.isEmpty) { diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index c4dbeab5f..a2ddf301b 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -77,6 +77,7 @@ class _VideoDetailPageState extends State final GlobalKey relatedVideoPanelKey = GlobalKey(); final GlobalKey videoPlayerFutureKey = GlobalKey(); final GlobalKey videoReplyPanelKey = GlobalKey(); + final GlobalKey scaffoldKey = GlobalKey(); @override void initState() { @@ -204,6 +205,7 @@ class _VideoDetailPageState extends State // 播放器状态监听 void playerListener(PlayerStatus? status) async { + print("playerListener $status"); playerStatus = status!; switch (status) { case PlayerStatus.playing: @@ -683,7 +685,7 @@ class _VideoDetailPageState extends State right: false, //isFullScreen != true, child: Scaffold( resizeToAvoidBottomInset: false, - key: videoDetailController.scaffoldKey, + key: scaffoldKey, // backgroundColor: Colors.black, appBar: removeSafeArea ? null @@ -947,7 +949,7 @@ class _VideoDetailPageState extends State }); Widget get childWhenDisabledLandscape => Scaffold( resizeToAvoidBottomInset: false, - key: videoDetailController.scaffoldKey, + key: scaffoldKey, // backgroundColor: Colors.black, appBar: removeSafeArea ? null @@ -976,7 +978,7 @@ class _VideoDetailPageState extends State ); Widget get childWhenDisabledAlmostSquare => Scaffold( resizeToAvoidBottomInset: false, - key: videoDetailController.scaffoldKey, + key: scaffoldKey, // backgroundColor: Colors.black, appBar: removeSafeArea ? null diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index cb70c9e01..05fa525d8 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -59,11 +59,11 @@ class _WhisperDetailPageState extends State if (!mounted) return; WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; - // 键盘高度 - final viewInsets = EdgeInsets.fromViewPadding( - View.of(context).viewInsets, View.of(context).devicePixelRatio); _debouncer.run(() { if (!mounted) return; + // 键盘高度 + final viewInsets = EdgeInsets.fromViewPadding( + View.of(context).viewInsets, View.of(context).devicePixelRatio); if (keyboardHeight == 0) { emoteHeight = keyboardHeight = keyboardHeight == 0.0 ? viewInsets.bottom : keyboardHeight; diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 749578641..41a5a0f9b 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -602,9 +602,9 @@ class PlPlayerController { Player player = _videoPlayerController ?? Player( configuration: PlayerConfiguration( - // 默认缓冲 4M 大小 - bufferSize: bufferSize, - ), + // 默认缓冲 4M 大小 + bufferSize: bufferSize, + logLevel: MPVLogLevel.v), ); var pp = player.platform as NativePlayer; // 解除倍速限制 @@ -620,6 +620,12 @@ class PlPlayerController { // video-sync=display-resample await pp.setProperty("video-sync", setting.get(SettingBoxKey.videoSync, defaultValue: 'display-resample')); + // await pp.setProperty('vf', 'rotate=90'); + await pp.setProperty('force-seekable', 'yes'); + // await pp.setProperty("video-rotate", "no"); + // await pp.setProperty("video-zoom","0"); + // await pp.setProperty("vf", "tblend=c0_mode=difference,eq=contrast=2"); + // await pp.setProperty("vf", "scale") // // vo=gpu-next & gpu-context=android & gpu-api=opengl // await pp.setProperty("vo", "gpu-next"); // await pp.setProperty("gpu-context", "android"); @@ -798,6 +804,7 @@ class PlPlayerController { }), videoPlayerController!.stream.completed.listen((event) { if (event) { + print("stream completed"); playerStatus.status.value = PlayerStatus.completed; /// 触发回调事件 @@ -835,11 +842,16 @@ class PlPlayerController { videoPlayerServiceHandler.onStatusChange( playerStatus.status.value, event); }), - // videoPlayerController!.stream.log.listen((event) { - // print('videoPlayerController!.stream.log.listen'); - // print(event); - // SmartDialog.showToast('视频加载日志: $event'); - // }), + videoPlayerController!.stream.log.listen((event) { + // print('videoPlayerController!.stream.log.listen'); + // print('[pp] $event'); + // if (event.level == "v") { + if (isBuffering.value) { + _playerLog.value = "[${event.prefix}]${event.text}"; + } + // } + // SmartDialog.showToast('视频加载日志: $event'); + }), videoPlayerController!.stream.error.listen((String event) { // 直播的错误提示没有参考价值,均不予显示 if (videoType.value == 'live') return; diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 500f5de28..5f00729e1 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -422,7 +422,12 @@ class _PLVideoPlayerState extends State String bvid = widget.controller.bvid; final List episodes = []; late Function changeFucCall; - if (isSeason) { + if (isPage) { + final List pages = + videoIntroController!.videoDetail.value.pages!; + episodes.addAll(pages); + changeFucCall = videoIntroController!.changeSeasonOrbangu; + } else if (isSeason) { final List sections = videoIntroController!.videoDetail.value.ugcSeason!.sections!; for (int i = 0; i < sections.length; i++) { @@ -430,11 +435,6 @@ class _PLVideoPlayerState extends State episodes.addAll(episodesList); } changeFucCall = videoIntroController!.changeSeasonOrbangu; - } else if (isPage) { - final List pages = - videoIntroController!.videoDetail.value.pages!; - episodes.addAll(pages); - changeFucCall = videoIntroController!.changeSeasonOrbangu; } else if (isBangumi) { episodes.addAll( bangumiIntroController!.bangumiDetail.value.episodes!); @@ -1360,17 +1360,24 @@ class _PLVideoPlayerState extends State if (_.isBuffering.value) Obx(() { if (_.buffered.value == Duration.zero) { - return const Text( - 'Buffering...', - style: TextStyle(color: Colors.white, fontSize: 12), - semanticsLabel: '', + return SizedBox( + width: 180, + child: Text( + _.playerLog.value, + overflow: TextOverflow.ellipsis, + maxLines: 1, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, fontSize: 10), + semanticsLabel: '', + ), ); } String bufferStr = _.buffered.toString(); return Text( bufferStr.substring(0, bufferStr.length - 3), style: const TextStyle( - color: Colors.white, fontSize: 12), + color: Colors.white, fontSize: 10), semanticsLabel: '', ); }),