diff --git a/lib/pages/live_room/controller.dart b/lib/pages/live_room/controller.dart index e46dcf0ee..2eba97336 100644 --- a/lib/pages/live_room/controller.dart +++ b/lib/pages/live_room/controller.dart @@ -30,45 +30,46 @@ import 'package:get/get.dart'; class LiveRoomController extends GetxController { LiveRoomController(this.heroTag); final String heroTag; - late int roomId; - dynamic liveItem; - double volume = 0.0; - // 静音状态 - RxBool volumeOff = false.obs; + + int roomId = int.parse(Get.parameters['roomid']!); PlPlayerController plPlayerController = PlPlayerController.getInstance( isLive: true, ); + + RxBool isLoaded = false.obs; Rx roomInfoH5 = Rx(null); + // dm + LiveDmInfoData? dmInfo; + bool showDanmaku = true; + DanmakuController? controller; + List? savedDanmaku; RxList messages = [].obs; RxBool disableAutoScroll = false.obs; - double? brightness; - DanmakuController? controller; - bool showDanmaku = true; + LiveMessageStream? msgStream; + late final ScrollController scrollController = ScrollController() + ..addListener(listener); int? currentQn; - late List<({int code, String desc})> acceptQnList = []; RxString currentQnDesc = ''.obs; + final RxBool isPortrait = false.obs; + late List<({int code, String desc})> acceptQnList = []; - List? savedDanmaku; - - AccountService accountService = Get.find(); late final isLogin = accountService.isLogin.value; - - LiveDmInfoData? dmInfo; + AccountService accountService = Get.find(); @override void onInit() { super.onInit(); - roomId = int.parse(Get.parameters['roomid']!); + queryLiveUrl(); queryLiveInfoH5(); if (Accounts.get(AccountType.heartbeat).isLogin && !Pref.historyPause) { VideoHttp.roomEntryAction(roomId: roomId); } } - Future playerInit(String source) async { - await plPlayerController.setDataSource( + Future playerInit(String source) { + return plPlayerController.setDataSource( DataSource( videoSource: source, audioSource: null, @@ -84,9 +85,7 @@ class LiveRoomController extends GetxController { ); } - final RxBool isPortrait = false.obs; - - Future queryLiveInfo() async { + Future queryLiveUrl() async { if (currentQn == null) { await Connectivity().checkConnectivity().then((res) { currentQn = res.contains(ConnectivityResult.wifi) @@ -102,7 +101,7 @@ class LiveRoomController extends GetxController { if (res['status']) { RoomPlayInfoData data = res['data']; if (data.liveStatus != 1) { - _dialog(title: '当前直播间未开播'); + _showDialog('当前直播间未开播'); return; } if (data.roomId != null) { @@ -127,7 +126,7 @@ class LiveRoomController extends GetxController { .description; String videoUrl = VideoUtils.getCdnUrl(item); await playerInit(videoUrl); - return res; + isLoaded.value = true; } } @@ -143,14 +142,12 @@ class LiveRoomController extends GetxController { ); } else { if (res['msg'] != null) { - _dialog(title: res['msg']); + _showDialog(res['msg']); } } } - void _dialog({ - required String title, - }) { + void _showDialog(String title) { Get.dialog( AlertDialog( title: Text(title), @@ -173,10 +170,6 @@ class LiveRoomController extends GetxController { ); } - LiveMessageStream? msgStream; - late final ScrollController scrollController = ScrollController() - ..addListener(listener); - void scrollToBottom() { if (disableAutoScroll.value) return; if (scrollController.hasClients) { @@ -264,7 +257,7 @@ class LiveRoomController extends GetxController { currentQnDesc.value = LiveQuality.values .firstWhere((element) => element.code == currentQn) .description; - return queryLiveInfo(); + return queryLiveUrl(); } void initDm(LiveDmInfoData info) { diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index ea6453a50..2ecaf2980 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -37,26 +37,22 @@ class LiveRoomPage extends StatefulWidget { class _LiveRoomPageState extends State with WidgetsBindingObserver { + late final String heroTag; late final int _roomId; late final LiveRoomController _liveRoomController; late final PlPlayerController plPlayerController; - late Future? _futureBuilderFuture; bool get isFullScreen => plPlayerController.isFullScreen.value; - bool isShowCover = true; - bool isPlay = true; - StreamSubscription? _listener; - int latestAddedPosition = -1; bool? _isFullScreen; bool? _isPipMode; - void playCallBack() { - plPlayerController.play(); - } + final GlobalKey chatKey = GlobalKey(); + final GlobalKey playerKey = GlobalKey(); + final GlobalKey videoPlayerKey = GlobalKey(); - late final String heroTag; + final Color _color = const Color(0xFFEEEEEE); @override void initState() { @@ -68,9 +64,8 @@ class _LiveRoomPageState extends State LiveRoomController(heroTag), tag: heroTag, ); - PlPlayerController.setPlayCallBack(playCallBack); - videoSourceInit(); - _futureBuilderFuture = _liveRoomController.queryLiveInfo(); + plPlayerController = _liveRoomController.plPlayerController; + PlPlayerController.setPlayCallBack(plPlayerController.play); plPlayerController ..autoEnterFullscreen() ..addStatusLister(playerListener); @@ -115,10 +110,6 @@ class _LiveRoomPageState extends State : 15 * plPlayerController.danmakuFontScaleFS; } - void videoSourceInit() { - plPlayerController = _liveRoomController.plPlayerController; - } - @override void dispose() { videoPlayerServiceHandler.onVideoDetailDispose(heroTag); @@ -145,8 +136,21 @@ class _LiveRoomPageState extends State } } - final GlobalKey videoPlayerKey = GlobalKey(); - final GlobalKey playerKey = GlobalKey(); + @override + Widget build(BuildContext context) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _updateFontSize(); + }); + + final isPortrait = context.isPortrait; + if (Platform.isAndroid) { + return Floating().isPipMode + ? videoPlayerPanel() + : childWhenDisabled(isPortrait); + } else { + return childWhenDisabled(isPortrait); + } + } Widget videoPlayerPanel({Color? fill, Alignment? alignment}) { return PopScope( @@ -156,66 +160,59 @@ class _LiveRoomPageState extends State plPlayerController.triggerFullScreen(status: false); } }, - child: FutureBuilder( - key: videoPlayerKey, - future: _futureBuilderFuture, - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.hasData && snapshot.data['status']) { - final roomInfoH5 = _liveRoomController.roomInfoH5.value; - return PLVideoPlayer( - key: playerKey, - fill: fill, - alignment: alignment, + child: Obx(() { + if (_liveRoomController.isLoaded.value) { + final roomInfoH5 = _liveRoomController.roomInfoH5.value; + return PLVideoPlayer( + key: playerKey, + fill: fill, + alignment: alignment, + plPlayerController: plPlayerController, + headerControl: LiveHeaderControl( + title: roomInfoH5?.roomInfo?.title, + upName: roomInfoH5?.anchorInfo?.baseInfo?.uname, plPlayerController: plPlayerController, - headerControl: LiveHeaderControl( - title: roomInfoH5?.roomInfo?.title, - upName: roomInfoH5?.anchorInfo?.baseInfo?.uname, - plPlayerController: plPlayerController, - onSendDanmaku: onSendDanmaku, - onPlayAudio: _liveRoomController.queryLiveInfo, - ), - bottomControl: BottomControl( - plPlayerController: plPlayerController, - liveRoomCtr: _liveRoomController, - onRefresh: () { - _futureBuilderFuture = _liveRoomController.queryLiveInfo(); - }, - ), - danmuWidget: Obx( - () => AnimatedOpacity( - opacity: plPlayerController.enableShowDanmaku.value ? 1 : 0, - duration: const Duration(milliseconds: 100), - child: DanmakuScreen( - createdController: (DanmakuController e) { - plPlayerController.danmakuController = - _liveRoomController.controller = e; - }, - option: DanmakuOption( - fontSize: _getFontSize(isFullScreen), - fontWeight: plPlayerController.fontWeight, - area: plPlayerController.showArea, - opacity: plPlayerController.danmakuOpacity, - hideTop: plPlayerController.blockTypes.contains(5), - hideScroll: plPlayerController.blockTypes.contains(2), - hideBottom: plPlayerController.blockTypes.contains(4), - duration: - plPlayerController.danmakuDuration / - plPlayerController.playbackSpeed, - staticDuration: - plPlayerController.danmakuStaticDuration / - plPlayerController.playbackSpeed, - strokeWidth: plPlayerController.strokeWidth, - lineHeight: plPlayerController.danmakuLineHeight, - ), + onSendDanmaku: onSendDanmaku, + onPlayAudio: _liveRoomController.queryLiveUrl, + ), + bottomControl: BottomControl( + plPlayerController: plPlayerController, + liveRoomCtr: _liveRoomController, + onRefresh: _liveRoomController.queryLiveUrl, + ), + danmuWidget: Obx( + () => AnimatedOpacity( + opacity: plPlayerController.enableShowDanmaku.value ? 1 : 0, + duration: const Duration(milliseconds: 100), + child: DanmakuScreen( + createdController: (DanmakuController e) { + plPlayerController.danmakuController = + _liveRoomController.controller = e; + }, + option: DanmakuOption( + fontSize: _getFontSize(isFullScreen), + fontWeight: plPlayerController.fontWeight, + area: plPlayerController.showArea, + opacity: plPlayerController.danmakuOpacity, + hideTop: plPlayerController.blockTypes.contains(5), + hideScroll: plPlayerController.blockTypes.contains(2), + hideBottom: plPlayerController.blockTypes.contains(4), + duration: + plPlayerController.danmakuDuration / + plPlayerController.playbackSpeed, + staticDuration: + plPlayerController.danmakuStaticDuration / + plPlayerController.playbackSpeed, + strokeWidth: plPlayerController.strokeWidth, + lineHeight: plPlayerController.danmakuLineHeight, ), ), ), - ); - } else { - return const SizedBox.shrink(); - } - }, - ), + ), + ); + } + return const SizedBox.shrink(); + }), ); } @@ -256,21 +253,23 @@ class _LiveRoomPageState extends State .value ?.roomInfo ?.appBackground; + Widget child; + if (appBackground?.isNotEmpty == true) { + final size = Get.size; + child = CachedNetworkImage( + fit: BoxFit.cover, + width: size.width, + height: size.height, + imageUrl: appBackground!.http2https, + ); + } else { + child = Image.asset( + 'assets/images/live/default_bg.webp', + fit: BoxFit.cover, + ); + } return Positioned.fill( - child: Opacity( - opacity: 0.6, - child: appBackground?.isNotEmpty == true - ? CachedNetworkImage( - fit: BoxFit.cover, - width: Get.width, - height: Get.height, - imageUrl: appBackground!.http2https, - ) - : Image.asset( - 'assets/images/live/default_bg.webp', - fit: BoxFit.cover, - ), - ), + child: Opacity(opacity: 0.6, child: child), ); }, ), @@ -285,7 +284,25 @@ class _LiveRoomPageState extends State if (_liveRoomController.isPortrait.value) { return _buildPP; } - return _buildPH; + return Column( + children: [ + _buildAppBar, + Obx( + () { + final size = Get.size; + return Container( + color: Colors.black, + width: size.width, + height: isFullScreen + ? size.height + : size.width * 9 / 16, + child: videoPlayerPanel(), + ); + }, + ), + ..._buildBottomWidget, + ], + ); }, ) : Column( @@ -301,13 +318,6 @@ class _LiveRoomPageState extends State ); } - Widget get _buildPH => Column( - children: [ - _buildAppBar, - ..._buildBodyP, - ], - ); - Widget get _buildPP => Stack( clipBehavior: Clip.none, children: [ @@ -351,26 +361,6 @@ class _LiveRoomPageState extends State ], ); - @override - Widget build(BuildContext context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - _updateFontSize(); - }); - return OrientationBuilder( - builder: (BuildContext context, Orientation orientation) { - if (Platform.isAndroid) { - return Floating().isPipMode - ? videoPlayerPanel() - : childWhenDisabled(orientation == Orientation.portrait); - } else { - return childWhenDisabled(orientation == Orientation.portrait); - } - }, - ); - } - - final Color _color = const Color(0xFFEEEEEE); - PreferredSizeWidget get _buildAppBar { final color = Theme.of(context).colorScheme.onSurfaceVariant; return AppBar( @@ -421,8 +411,7 @@ class _LiveRoomPageState extends State actions: [ IconButton( tooltip: '刷新', - onPressed: () => - _futureBuilderFuture = _liveRoomController.queryLiveInfo(), + onPressed: _liveRoomController.queryLiveUrl, icon: const Icon(Icons.refresh, size: 20), ), PopupMenuButton( @@ -497,15 +486,18 @@ class _LiveRoomPageState extends State child: Row( children: [ Obx( - () => Container( - margin: EdgeInsets.only( - bottom: MediaQuery.paddingOf(context).bottom, - ), - color: isFullScreen ? Colors.black : null, - width: isFullScreen ? Get.size.width : videoWidth, - height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16, - child: videoPlayerPanel(fill: Colors.transparent), - ), + () { + final size = Get.size; + return Container( + margin: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom, + ), + color: isFullScreen ? Colors.black : null, + width: isFullScreen ? size.width : videoWidth, + height: isFullScreen ? size.height : size.width * 9 / 16, + child: videoPlayerPanel(fill: Colors.transparent), + ); + }, ), Expanded( child: Column( @@ -518,20 +510,6 @@ class _LiveRoomPageState extends State ); } - List get _buildBodyP => [ - Obx( - () => Container( - color: Colors.black, - width: Get.size.width, - height: isFullScreen ? Get.size.height : Get.size.width * 9 / 16, - child: videoPlayerPanel(), - ), - ), - ..._buildBottomWidget, - ]; - - final GlobalKey chatKey = GlobalKey(); - List get _buildBottomWidget => [ Expanded(child: _buildChatWidget()), _buildInputWidget, diff --git a/lib/pages/save_panel/view.dart b/lib/pages/save_panel/view.dart index 2ba23a803..3ee84a323 100644 --- a/lib/pages/save_panel/view.dart +++ b/lib/pages/save_panel/view.dart @@ -252,9 +252,7 @@ class _SavePanelState extends State { mimeType: 'image/png', ), ], - sharePositionOrigin: await Utils.isIpad() - ? Rect.fromLTWH(0, 0, Get.width, Get.height / 2) - : null, + sharePositionOrigin: await Utils.sharePositionOrigin, ), ); } else { diff --git a/lib/pages/setting/pages/color_select.dart b/lib/pages/setting/pages/color_select.dart index d249bade4..dde568fc4 100644 --- a/lib/pages/setting/pages/color_select.dart +++ b/lib/pages/setting/pages/color_select.dart @@ -53,6 +53,7 @@ class _ColorSelectPageState extends State { TextStyle subTitleStyle = theme.textTheme.labelMedium!.copyWith( color: theme.colorScheme.outline, ); + final size = Get.size; return Scaffold( appBar: AppBar(title: const Text('选择应用主题')), body: SafeArea( @@ -240,8 +241,8 @@ class _ColorSelectPageState extends State { ...[ IgnorePointer( child: Container( - height: Get.height / 2, - width: Get.width, + height: size.height / 2, + width: size.width, color: theme.colorScheme.surface, child: const HomePage(), ), diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index d5e96f45c..7e18b7086 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -136,10 +136,10 @@ class VideoDetailController extends GetxController duration: const Duration(milliseconds: 200), ); late final double minVideoHeight = Get.mediaQuery.size.shortestSide * 9 / 16; - late final double maxVideoHeight = max( - Get.mediaQuery.size.longestSide * 0.65, - Get.mediaQuery.size.shortestSide, - ); + late final double maxVideoHeight = () { + final size = Get.mediaQuery.size; + return max(size.longestSide * 0.65, size.shortestSide); + }(); late double videoHeight = minVideoHeight; void animToTop() { @@ -1304,7 +1304,7 @@ class VideoDetailController extends GetxController videoUrl = VideoUtils.getCdnUrl(firstVideo); /// 优先顺序 设置中指定质量 -> 当前可选的最高质量 - late AudioItem? firstAudio; + AudioItem? firstAudio; final List audiosList = data.dash!.audio ?? []; if (data.dash!.dolby?.audio != null && data.dash!.dolby!.audio!.isNotEmpty) { diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 0eb497ccf..84b0545ad 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -190,10 +190,11 @@ class _VideoDetailPageVState extends State final isVertical = videoDetailController.isVertical.value; final mode = plPlayerController?.mode; + late final size = Get.size; if (!(mode == FullScreenMode.vertical || (mode == FullScreenMode.auto && isVertical) || (mode == FullScreenMode.ratio && - (Get.height / Get.width < 1.25 || isVertical)))) { + (isVertical || size.height / size.width < 1.25)))) { landScape(); } }); diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 2208b7e2a..b74957411 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -895,14 +895,8 @@ class HeaderControlState extends State { mimeType: Headers.jsonContentType, ), ], - sharePositionOrigin: await Utils.isIpad() - ? Rect.fromLTWH( - 0, - 0, - Get.width, - Get.height / 2, - ) - : null, + sharePositionOrigin: + await Utils.sharePositionOrigin, ), ); } diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 05ffdebdf..601d75db9 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -1377,10 +1377,11 @@ class PlPlayerController { fsProcessing = false; return; } + late final size = Get.size; if (mode == FullScreenMode.vertical || (mode == FullScreenMode.auto && isVertical) || (mode == FullScreenMode.ratio && - (Get.height / Get.width < 1.25 || isVertical))) { + (isVertical || size.height / size.width < 1.25))) { await verticalScreenForTwoSeconds(); } else { await landScape(); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 49379311e..8dfa47342 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -86,8 +86,8 @@ class _PLVideoPlayerState extends State with TickerProviderStateMixin { late AnimationController animationController; late VideoController videoController; - late VideoIntroController? videoIntroController; - late PgcIntroController? pgcIntroController; + VideoIntroController? videoIntroController; + PgcIntroController? pgcIntroController; final GlobalKey _playerKey = GlobalKey(); final GlobalKey key = GlobalKey(); diff --git a/lib/utils/image_util.dart b/lib/utils/image_util.dart index 61d8f6717..1296d8f76 100644 --- a/lib/utils/image_util.dart +++ b/lib/utils/image_util.dart @@ -7,7 +7,6 @@ import 'package:PiliPlus/utils/utils.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:get/get.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:live_photo_maker/live_photo_maker.dart'; import 'package:path_provider/path_provider.dart'; @@ -31,9 +30,7 @@ class ImageUtil { SharePlus.instance.share( ShareParams( files: [XFile(path)], - sharePositionOrigin: await Utils.isIpad() - ? Rect.fromLTWH(0, 0, Get.width, Get.height / 2) - : null, + sharePositionOrigin: await Utils.sharePositionOrigin, ), ); } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index fdc8f4b92..bae888e2b 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -40,14 +40,25 @@ class Utils { return _isIpad!; } + static Future get sharePositionOrigin async { + if (await Utils.isIpad()) { + final size = Get.size; + return Rect.fromLTWH( + 0, + 0, + size.width, + size.height / 2, + ); + } + return null; + } + static Future shareText(String text) async { try { SharePlus.instance.share( ShareParams( text: text, - sharePositionOrigin: await Utils.isIpad() - ? Rect.fromLTWH(0, 0, Get.width, Get.height / 2) - : null, + sharePositionOrigin: await sharePositionOrigin, ), ); } catch (e) {