diff --git a/lib/main.dart b/lib/main.dart index 1b660c8c2..9ba35073c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -312,14 +312,18 @@ class MyApp extends StatelessWidget { if (plCtr.isFullScreen.value) { plCtr ..triggerFullScreen(status: false) - ..controlsLock.value = false; + ..controlsLock.value = false + ..showControls.value = false; return; } if (plCtr.isDesktopPip) { - plCtr.exitDesktopPip().whenComplete( - () => plCtr.initialFocalPoint = Offset.zero, - ); + plCtr + ..exitDesktopPip().whenComplete( + () => plCtr.initialFocalPoint = Offset.zero, + ) + ..controlsLock.value = false + ..showControls.value = false; return; } } diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index 5f22286dd..be9c308a3 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -345,6 +345,10 @@ class _LiveRoomPageState extends State return PopScope( canPop: !isFullScreen, onPopInvokedWithResult: (bool didPop, Object? result) { + if (plPlayerController.controlsLock.value) { + plPlayerController.onLockControl(false); + return; + } if (isFullScreen) { plPlayerController.triggerFullScreen(status: false); } diff --git a/lib/pages/live_room/widgets/bottom_control.dart b/lib/pages/live_room/widgets/bottom_control.dart index f1f8e4eb0..879863b97 100644 --- a/lib/pages/live_room/widgets/bottom_control.dart +++ b/lib/pages/live_room/widgets/bottom_control.dart @@ -120,7 +120,7 @@ class _BottomControlState extends State with HeaderMixin { CustomIcons.dm_settings, color: Colors.white, ), - onTap: showSetDanmaku, + onTap: () => showSetDanmaku(isLive: true), ), Obx( () => PopupMenuButton( diff --git a/lib/pages/live_room/widgets/header_control.dart b/lib/pages/live_room/widgets/header_control.dart index 0925528fc..8ba67f543 100644 --- a/lib/pages/live_room/widgets/header_control.dart +++ b/lib/pages/live_room/widgets/header_control.dart @@ -127,7 +127,7 @@ class LiveHeaderControl extends StatelessWidget { } if (await Floating().isPipAvailable) { plPlayerController - ..hiddenControls(false) + ..showControls.value = false ..enterPip(); } }, diff --git a/lib/pages/msg_feed_top/at_me/view.dart b/lib/pages/msg_feed_top/at_me/view.dart index 470c7d1ea..be247505a 100644 --- a/lib/pages/msg_feed_top/at_me/view.dart +++ b/lib/pages/msg_feed_top/at_me/view.dart @@ -162,10 +162,11 @@ class _AtMePageState extends State { ), ], ), - trailing: item.item?.image != null && item.item?.image != "" + trailing: item.item?.image?.isNotEmpty == true ? NetworkImgLayer( width: 45, height: 45, + radius: 8, src: item.item?.image, ) : null, diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index 85b9947de..34b598076 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -164,6 +164,38 @@ class _LikeMePageState extends State { MsgLikeItem item, ValueChanged onRemove, ) { + final firstUser = item.users!.first; + Widget avatar; + if (item.users!.length == 1) { + avatar = NetworkImgLayer( + width: 45, + height: 45, + type: ImageType.avatar, + src: firstUser.avatar, + ); + } else { + avatar = SizedBox( + width: 45, + height: 45, + child: Stack( + clipBehavior: Clip.none, + children: [ + for (var j = 0; j < item.users!.length && j < 4; j++) ...[ + Positioned( + left: 15.0 * (j % 2), + top: 15.0 * (j ~/ 2), + child: NetworkImgLayer( + width: 30, + height: 30, + type: ImageType.avatar, + src: item.users![j].avatar, + ), + ), + ], + ], + ), + ); + } void onLongPress() => showDialog( context: context, builder: (context) { @@ -240,42 +272,12 @@ class _LikeMePageState extends State { }, onLongPress: onLongPress, onSecondaryTap: Utils.isMobile ? null : onLongPress, - leading: Column( - children: [ - const Spacer(), - SizedBox( - width: 50, - height: 50, - child: Stack( - clipBehavior: Clip.none, - children: [ - for ( - var j = 0; - j < item.users!.length && j < 4; - j++ - ) ...[ - Positioned( - left: 15 * (j % 2).toDouble(), - top: 15 * (j ~/ 2).toDouble(), - child: NetworkImgLayer( - width: item.users!.length > 1 ? 30 : 45, - height: item.users!.length > 1 ? 30 : 45, - type: ImageType.avatar, - src: item.users![j].avatar, - ), - ), - ], - ], - ), - ), - const Spacer(), - ], - ), + leading: avatar, title: Text.rich( TextSpan( children: [ TextSpan( - text: "${item.users![0].nickname}", + text: firstUser.nickname, style: theme.textTheme.titleSmall!.copyWith( height: 1.5, color: theme.colorScheme.primary, @@ -290,7 +292,7 @@ class _LikeMePageState extends State { ), ), TextSpan( - text: " 赞了我的${item.item?.business}", + text: ' 赞了我的${item.item?.business}', style: theme.textTheme.titleSmall!.copyWith( height: 1.5, color: theme.colorScheme.onSurfaceVariant, @@ -333,6 +335,7 @@ class _LikeMePageState extends State { NetworkImgLayer( width: 45, height: 45, + radius: 8, src: item.item!.image, ), if (item.noticeState == 1) ...[ diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index f781f69b9..3ab6cfbd4 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -102,7 +102,7 @@ mixin HeaderMixin on State { } /// 弹幕功能 - void showSetDanmaku() { + void showSetDanmaku({bool isLive = false}) { // 屏蔽类型 const List<({int value, String label})> blockTypesList = [ (value: 5, label: '顶部'), @@ -278,49 +278,51 @@ mixin HeaderMixin on State { ), ), const SizedBox(height: 10), - Row( - children: [ - Text('智能云屏蔽 $danmakuWeight 级'), - const Spacer(), - TextButton( - style: TextButton.styleFrom( - padding: EdgeInsets.zero, - minimumSize: Size.zero, - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - onPressed: () => Get - ..back() - ..toNamed( - '/danmakuBlock', - arguments: plPlayerController, + if (!isLive) ...[ + Row( + children: [ + Text('智能云屏蔽 $danmakuWeight 级'), + const Spacer(), + TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), - child: Text( - "屏蔽管理(${plPlayerController.filters.count})", + onPressed: () => Get + ..back() + ..toNamed( + '/danmakuBlock', + arguments: plPlayerController, + ), + child: Text( + "屏蔽管理(${plPlayerController.filters.count})", + ), + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + top: 0, + bottom: 6, + left: 10, + right: 10, + ), + child: SliderTheme( + data: sliderTheme, + child: Slider( + min: 0, + max: 10, + value: danmakuWeight.toDouble(), + divisions: 10, + label: '$danmakuWeight', + onChanged: updateDanmakuWeight, + onChangeEnd: (_) => + plPlayerController.putDanmakuSettings(), ), ), - ], - ), - Padding( - padding: const EdgeInsets.only( - top: 0, - bottom: 6, - left: 10, - right: 10, ), - child: SliderTheme( - data: sliderTheme, - child: Slider( - min: 0, - max: 10, - value: danmakuWeight.toDouble(), - divisions: 10, - label: '$danmakuWeight', - onChanged: updateDanmakuWeight, - onChangeEnd: (_) => - plPlayerController.putDanmakuSettings(), - ), - ), - ), + ], const Text('按类型屏蔽'), Padding( padding: const EdgeInsets.only(top: 12), @@ -2290,8 +2292,8 @@ class HeaderControlState extends State with HeaderMixin { return ListTile( dense: true, onTap: () { - plPlayerController.setPlayRepeat(i); Get.back(); + plPlayerController.setPlayRepeat(i); }, contentPadding: const EdgeInsets.symmetric( horizontal: 20, @@ -2317,13 +2319,16 @@ class HeaderControlState extends State with HeaderMixin { static final _format = DateFormat('HH:mm'); void startClock() { - clock ??= Timer.periodic(const Duration(seconds: 1), (Timer t) { - if (!mounted) { - cancelClock(); - return; - } + if (clock == null) { now.value = _format.format(DateTime.now()); - }); + clock = Timer.periodic(const Duration(seconds: 1), (Timer t) { + if (!mounted) { + cancelClock(); + return; + } + now.value = _format.format(DateTime.now()); + }); + } } void cancelClock() { @@ -2339,6 +2344,12 @@ class HeaderControlState extends State with HeaderMixin { final isFSOrPip = isFullScreen || plPlayerController.isDesktopPip; final showFSActionItem = !isFileSource && plPlayerController.showFSActionItem && isFSOrPip; + final showCurrTime = !isPortrait && (isFullScreen || !horizontalScreen); + if (showCurrTime) { + startClock(); + } else { + cancelClock(); + } return AppBar( elevation: 0, scrolledUnderElevation: 0, @@ -2457,22 +2468,16 @@ class HeaderControlState extends State with HeaderMixin { else const Spacer(), // show current datetime - Obx( - () { - if ((this.isFullScreen || !horizontalScreen) && !isPortrait) { - startClock(); - return Text( - now.value, - style: const TextStyle( - color: Colors.white, - fontSize: 13, - ), - ); - } - cancelClock(); - return const SizedBox.shrink(); - }, - ), + if (showCurrTime) + Obx( + () => Text( + now.value, + style: const TextStyle( + color: Colors.white, + fontSize: 13, + ), + ), + ), if (!isFileSource) ...[ if (!isFSOrPip) ...[ if (videoDetailCtr.isUgc) @@ -2629,7 +2634,7 @@ class HeaderControlState extends State with HeaderMixin { return; } if (await Floating().isPipAvailable) { - plPlayerController.hiddenControls(false); + plPlayerController.showControls.value = false; if (context.mounted && !videoPlayerServiceHandler!.enableBackgroundPlay) { final theme = Theme.of(context); diff --git a/lib/pages/video/widgets/player_focus.dart b/lib/pages/video/widgets/player_focus.dart index 024e3f587..d6c51c60a 100644 --- a/lib/pages/video/widgets/player_focus.dart +++ b/lib/pages/video/widgets/player_focus.dart @@ -158,12 +158,16 @@ class PlayerFocus extends StatelessWidget { return true; case LogicalKeyboardKey.keyF: - plPlayerController - ..triggerFullScreen( - status: !isFullScreen, - inAppFullScreen: HardwareKeyboard.instance.isShiftPressed, - ) - ..controlsLock.value = false; + final isFullScreen = this.isFullScreen; + if (isFullScreen && plPlayerController.controlsLock.value) { + plPlayerController + ..controlsLock.value = false + ..showControls.value = false; + } + plPlayerController.triggerFullScreen( + status: !isFullScreen, + inAppFullScreen: HardwareKeyboard.instance.isShiftPressed, + ); return true; case LogicalKeyboardKey.keyD: @@ -183,7 +187,8 @@ class PlayerFocus extends StatelessWidget { if (Utils.isDesktop && hasPlayer && !isFullScreen) { plPlayerController ..toggleDesktopPip() - ..controlsLock.value = false; + ..controlsLock.value = false + ..showControls.value = false; } return true; diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 9cd379384..cc296b056 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -1455,10 +1455,6 @@ class PlPlayerController { } } - void hiddenControls(bool val) { - showControls.value = val; - } - Timer? longPressTimer; void cancelLongPressTimer() { longPressTimer?.cancel(); diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index dec5235eb..b6eee0c87 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -1237,6 +1237,12 @@ class _PLVideoPlayerState extends State final buttons = event.buttons; final isSecondaryBtn = buttons == kSecondaryMouseButton; if (isSecondaryBtn || buttons == kMiddleMouseButton) { + final isFullScreen = this.isFullScreen; + if (isFullScreen && plPlayerController.controlsLock.value) { + plPlayerController + ..controlsLock.value = false + ..showControls.value = false; + } plPlayerController .triggerFullScreen( status: !isFullScreen, @@ -1836,85 +1842,86 @@ class _PLVideoPlayerState extends State maxHeight, ), - // 锁 - if (plPlayerController.showFsLockBtn && - (isFullScreen || plPlayerController.isDesktopPip)) - ViewSafeArea( - right: false, - child: Align( - alignment: Alignment.centerLeft, - child: FractionalTranslation( - translation: const Offset(1, -0.4), - child: Obx( - () => Offstage( - offstage: !plPlayerController.showControls.value, - child: DecoratedBox( - decoration: const BoxDecoration( - color: Color(0x45000000), - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - child: Obx(() { - final controlsLock = - plPlayerController.controlsLock.value; - return ComBtn( - tooltip: controlsLock ? '解锁' : '锁定', - icon: controlsLock - ? const Icon( - FontAwesomeIcons.lock, - size: 15, - color: Colors.white, - ) - : const Icon( - FontAwesomeIcons.lockOpen, - size: 15, - color: Colors.white, - ), - onTap: () => - plPlayerController.onLockControl(!controlsLock), - ); - }), - ), - ), - ), - ), - ), - ), - - // 截图 - if (isFullScreen && plPlayerController.showFsScreenshotBtn) - ViewSafeArea( - left: false, - child: Obx( - () => Align( - alignment: Alignment.centerRight, + if (isFullScreen || plPlayerController.isDesktopPip) ...[ + // 锁 + if (plPlayerController.showFsLockBtn) + ViewSafeArea( + right: false, + child: Align( + alignment: Alignment.centerLeft, child: FractionalTranslation( - translation: const Offset(-1, -0.4), - child: Offstage( - offstage: !plPlayerController.showControls.value, - child: DecoratedBox( - decoration: const BoxDecoration( - color: Color(0x45000000), - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - child: ComBtn( - tooltip: '截图', - icon: const Icon( - Icons.photo_camera, - size: 20, - color: Colors.white, + translation: const Offset(1, -0.4), + child: Obx( + () => Offstage( + offstage: !plPlayerController.showControls.value, + child: DecoratedBox( + decoration: const BoxDecoration( + color: Color(0x45000000), + borderRadius: BorderRadius.all(Radius.circular(8)), ), - onLongPress: - (Platform.isAndroid || kDebugMode) && !isLive - ? screenshotWebp - : null, - onTap: plPlayerController.takeScreenshot, + child: Obx(() { + final controlsLock = + plPlayerController.controlsLock.value; + return ComBtn( + tooltip: controlsLock ? '解锁' : '锁定', + icon: controlsLock + ? const Icon( + FontAwesomeIcons.lock, + size: 15, + color: Colors.white, + ) + : const Icon( + FontAwesomeIcons.lockOpen, + size: 15, + color: Colors.white, + ), + onTap: () => + plPlayerController.onLockControl(!controlsLock), + ); + }), ), ), ), ), ), ), - ), + + // 截图 + if (plPlayerController.showFsScreenshotBtn) + ViewSafeArea( + left: false, + child: Obx( + () => Align( + alignment: Alignment.centerRight, + child: FractionalTranslation( + translation: const Offset(-1, -0.4), + child: Offstage( + offstage: !plPlayerController.showControls.value, + child: DecoratedBox( + decoration: const BoxDecoration( + color: Color(0x45000000), + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + child: ComBtn( + tooltip: '截图', + icon: const Icon( + Icons.photo_camera, + size: 20, + color: Colors.white, + ), + onLongPress: + (Platform.isAndroid || kDebugMode) && !isLive + ? screenshotWebp + : null, + onTap: plPlayerController.takeScreenshot, + ), + ), + ), + ), + ), + ), + ), + ], Obx(() { if (plPlayerController.dataStatus.loading ||