From e2e809e2d5c326f1e4f66556fa99abc19d91403b Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Mon, 19 Oct 2026 16:53:23 +0800 Subject: [PATCH] =?UTF-8?q?fix(player):=20=E5=A2=9E=E5=8A=A0=E9=80=80?= =?UTF-8?q?=E5=87=BA=E6=B8=85=E5=B1=8F=E6=B5=AE=E5=8A=A8=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/l10n/app_en.arb | 1 + lib/l10n/app_id.arb | 1 + lib/l10n/app_localizations.dart | 6 +++ lib/l10n/app_localizations_en.dart | 3 ++ lib/l10n/app_localizations_id.dart | 3 ++ lib/l10n/app_localizations_zh.dart | 3 ++ lib/l10n/app_zh.arb | 1 + lib/pages/player/player_view.dart | 26 +++++++++++-- .../widgets/exit_clear_screen_button.dart | 34 +++++++++++++++++ test/player/player_fullscreen_test.dart | 38 ++++++++++++++++++- 10 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 lib/pages/player/widgets/exit_clear_screen_button.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index ccb0f0b..3d4ceef 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -47,6 +47,7 @@ } }, "clearScreen": "Clear screen", + "exitClearScreen": "Exit clear screen", "minutesAgo": "{count} min ago", "@minutesAgo": { "placeholders": { diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index eebf31f..6876854 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -47,6 +47,7 @@ } }, "clearScreen": "Bersihkan layar", + "exitClearScreen": "Keluar dari layar bersih", "minutesAgo": "{count} mnt lalu", "@minutesAgo": { "placeholders": { diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index ee63cd3..42042f4 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -346,6 +346,12 @@ abstract class AppLocalizations { /// **'Clear screen'** String get clearScreen; + /// No description provided for @exitClearScreen. + /// + /// In en, this message translates to: + /// **'Exit clear screen'** + String get exitClearScreen; + /// No description provided for @minutesAgo. /// /// In en, this message translates to: diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index dbafe08..a09195b 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -136,6 +136,9 @@ class AppLocalizationsEn extends AppLocalizations { @override String get clearScreen => 'Clear screen'; + @override + String get exitClearScreen => 'Exit clear screen'; + @override String minutesAgo(int count) { return '$count min ago'; diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart index 02e2e01..a1fadb8 100644 --- a/lib/l10n/app_localizations_id.dart +++ b/lib/l10n/app_localizations_id.dart @@ -136,6 +136,9 @@ class AppLocalizationsId extends AppLocalizations { @override String get clearScreen => 'Bersihkan layar'; + @override + String get exitClearScreen => 'Keluar dari layar bersih'; + @override String minutesAgo(int count) { return '$count mnt lalu'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 41821ad..c58a9a5 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -133,6 +133,9 @@ class AppLocalizationsZh extends AppLocalizations { @override String get clearScreen => '清屏'; + @override + String get exitClearScreen => '退出清屏'; + @override String minutesAgo(int count) { return '$count 分钟前'; diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 88d2dfd..42ebcaf 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -47,6 +47,7 @@ } }, "clearScreen": "清屏", + "exitClearScreen": "退出清屏", "minutesAgo": "{count} 分钟前", "@minutesAgo": { "placeholders": { diff --git a/lib/pages/player/player_view.dart b/lib/pages/player/player_view.dart index 23e9db4..8d3bb32 100644 --- a/lib/pages/player/player_view.dart +++ b/lib/pages/player/player_view.dart @@ -24,6 +24,7 @@ import '../../l10n/app_localizations.dart'; import 'player_binding.dart'; import 'player_logic.dart'; import 'widgets/home_feed_overlay.dart'; +import 'widgets/exit_clear_screen_button.dart'; import 'widgets/player_center_toggle.dart'; import 'widgets/player_featured_comment.dart'; import 'widgets/seek_progress_bar.dart'; @@ -213,9 +214,8 @@ class _PlayerPageState extends State with WidgetsBindingObserver { child: GestureDetector( key: const Key('home-feed-video-toggle'), behavior: HitTestBehavior.opaque, - onTap: () => logic.session.setUserWantsPlay( - !logic.session.userWantsPlay, - ), + onTap: () => + logic.session.setUserWantsPlay(!logic.session.userWantsPlay), ), ), if (widget.homeMode && @@ -447,6 +447,16 @@ class _PlayerPageState extends State with WidgetsBindingObserver { onTap: () => setState(() => _feedChromeVisible = true), ), ), + if (widget.homeMode && !_feedChromeVisible) + Positioned( + top: 8, + right: 12, + child: ExitClearScreenButton( + key: const Key('home-feed-exit-clear-screen'), + tooltip: l10n.exitClearScreen, + onPressed: () => setState(() => _feedChromeVisible = true), + ), + ), ], ); } @@ -762,6 +772,16 @@ class _PlaybackOverlayState extends State<_PlaybackOverlay> { ), ], ), + if (!_controlsVisible) + Positioned( + top: 8, + right: 12, + child: ExitClearScreenButton( + key: const Key('player-exit-clear-screen'), + tooltip: widget.l10n.exitClearScreen, + onPressed: () => setState(() => _controlsVisible = true), + ), + ), ], ), ); diff --git a/lib/pages/player/widgets/exit_clear_screen_button.dart b/lib/pages/player/widgets/exit_clear_screen_button.dart new file mode 100644 index 0000000..a2b1c51 --- /dev/null +++ b/lib/pages/player/widgets/exit_clear_screen_button.dart @@ -0,0 +1,34 @@ +// Author: fruit.com.cn + +import 'package:flutter/material.dart'; + +/// Shared floating action used to leave clear-screen mode. +class ExitClearScreenButton extends StatelessWidget { + const ExitClearScreenButton({ + super.key, + required this.tooltip, + required this.onPressed, + }); + + final String tooltip; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: 36, + height: 36, + child: IconButton( + tooltip: tooltip, + onPressed: onPressed, + padding: EdgeInsets.zero, + style: IconButton.styleFrom( + backgroundColor: const Color(0x80000000), + foregroundColor: Colors.white, + shape: const CircleBorder(), + ), + icon: const Icon(Icons.fullscreen_exit_rounded, size: 18), + ), + ); + } +} diff --git a/test/player/player_fullscreen_test.dart b/test/player/player_fullscreen_test.dart index 6dc0fcb..8122046 100644 --- a/test/player/player_fullscreen_test.dart +++ b/test/player/player_fullscreen_test.dart @@ -131,13 +131,27 @@ void main() { expect(find.byKey(const Key('player-controls-bottom')), findsNothing); expect(find.byType(PlayerCenterToggle), findsNothing); expect(find.byKey(const Key('player-video-tap')), findsOneWidget); + expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget); + expect( + tester.getSize(find.byKey(const Key('player-exit-clear-screen'))), + const Size(36, 36), + ); - await tester.tap(find.byKey(const Key('player-video-tap'))); + await tester.tap(find.byKey(const Key('player-exit-clear-screen'))); await tester.pump(); expect(find.byKey(const Key('player-controls-top')), findsOneWidget); expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget); expect(find.byType(PlayerCenterToggle), findsOneWidget); + expect(find.byKey(const Key('player-exit-clear-screen')), findsNothing); + + await tester.tap(find.byKey(const Key('player-clear-screen'))); + await tester.pump(); + expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget); + await tester.tap(find.byKey(const Key('player-video-tap'))); + await tester.pump(); + expect(find.byKey(const Key('player-controls-top')), findsOneWidget); + expect(find.byKey(const Key('player-exit-clear-screen')), findsNothing); }); testWidgets('should_fit_player_header_on_320_width', (tester) async { @@ -174,13 +188,33 @@ void main() { expect(find.byKey(const Key('home-feed-info-card')), findsNothing); expect(find.byKey(const Key('home-feed-scrim')), findsNothing); expect(find.byKey(const Key('home-feed-video-tap')), findsOneWidget); + expect( + find.byKey(const Key('home-feed-exit-clear-screen')), + findsOneWidget, + ); + expect( + tester.getSize(find.byKey(const Key('home-feed-exit-clear-screen'))), + const Size(36, 36), + ); - await tester.tap(find.byKey(const Key('home-feed-video-tap'))); + await tester.tap(find.byKey(const Key('home-feed-exit-clear-screen'))); await tester.pump(); expect(find.byKey(const Key('home-feed-title')), findsOneWidget); expect(find.byKey(const Key('home-feed-info-card')), findsOneWidget); expect(find.byKey(const Key('home-feed-scrim')), findsOneWidget); + expect(find.byKey(const Key('home-feed-exit-clear-screen')), findsNothing); + + await tester.tap(find.byKey(const Key('home-feed-clear-screen'))); + await tester.pump(); + expect( + find.byKey(const Key('home-feed-exit-clear-screen')), + findsOneWidget, + ); + await tester.tap(find.byKey(const Key('home-feed-video-tap'))); + await tester.pump(); + expect(find.byKey(const Key('home-feed-title')), findsOneWidget); + expect(find.byKey(const Key('home-feed-exit-clear-screen')), findsNothing); }); testWidgets('should_show_home_play_toggle_only_when_paused', (tester) async {