fix(nav): preserve HTPC escape behavior

Use Flutter's supported desktop application-exit API so the second root Back press closes Plezy on Windows. Preserve fullscreen when video player navigation is enabled while keeping fullscreen-first Escape behavior for normal desktop use.

close #1582
This commit is contained in:
edde746
2026-07-16 20:43:10 +02:00
parent a244d249bd
commit 6df8aba097
5 changed files with 94 additions and 10 deletions
+24
View File
@@ -0,0 +1,24 @@
import 'dart:ui' as ui;
import 'package:flutter_test/flutter_test.dart';
import 'package:plezy/services/app_exit_service.dart';
void main() {
test('desktop exit uses the required application exit API', () async {
ui.AppExitType? requestedType;
int? requestedCode;
expect(
await AppExitService.requestExit(
exitApplicationForTesting: (exitType, exitCode) async {
requestedType = exitType;
requestedCode = exitCode;
return ui.AppExitResponse.exit;
},
),
isTrue,
);
expect(requestedType, ui.AppExitType.required);
expect(requestedCode, 0);
});
}
+41 -1
View File
@@ -428,6 +428,7 @@ void main() {
bool Function()? isChromePresented,
Future<bool> Function()? exitFullscreenIfActive,
bool physicalEscapeExitsFullscreen = true,
bool Function()? physicalEscapeExitsFullscreenProvider,
VoidCallback? exitPlayer,
VoidCallback? navigateHome,
bool Function()? isActive,
@@ -438,7 +439,7 @@ void main() {
dismissPrompt: dismissPrompt ?? () {},
isChromePresented: isChromePresented ?? () => chromeController.controlsPresented,
exitFullscreenIfActive: exitFullscreenIfActive ?? () async => false,
physicalEscapeExitsFullscreen: physicalEscapeExitsFullscreen,
physicalEscapeExitsFullscreen: physicalEscapeExitsFullscreenProvider ?? () => physicalEscapeExitsFullscreen,
exitPlayer: exitPlayer ?? () {},
navigateHome: navigateHome ?? () {},
isActive: isActive,
@@ -557,6 +558,31 @@ void main() {
expect(exits, 0);
});
testWidgets('enabling player navigation makes physical Escape preserve fullscreen', (tester) async {
final chromeController = PlayerChromeController();
addTearDown(chromeController.dispose);
var physicalEscapeExitsFullscreen = true;
var fullscreenChecks = 0;
var exits = 0;
final coordinator = coordinatorFor(
chromeController,
exitFullscreenIfActive: () async {
fullscreenChecks++;
return true;
},
physicalEscapeExitsFullscreenProvider: () => physicalEscapeExitsFullscreen,
exitPlayer: () => exits++,
);
physicalEscapeExitsFullscreen = false;
await pumpNavigationFocus(tester, coordinator);
await tester.sendKeyEvent(LogicalKeyboardKey.escape);
expect(fullscreenChecks, 0);
expect(chromeController.controlsVisible, isFalse);
expect(exits, 0);
});
testWidgets('macOS physical Escape stages through chrome and player without leaving fullscreen', (tester) async {
final chromeController = PlayerChromeController();
addTearDown(chromeController.dispose);
@@ -705,6 +731,20 @@ void main() {
});
});
group('shouldPhysicalEscapeExitFullscreen', () {
test('uses fullscreen-first behavior for normal Windows and Linux navigation', () {
expect(shouldPhysicalEscapeExitFullscreen(isMacOS: false, videoPlayerNavigationEnabled: false), isTrue);
});
test('preserves fullscreen when HTPC-style player navigation is enabled', () {
expect(shouldPhysicalEscapeExitFullscreen(isMacOS: false, videoPlayerNavigationEnabled: true), isFalse);
});
test('preserves native fullscreen inside the macOS player', () {
expect(shouldPhysicalEscapeExitFullscreen(isMacOS: true, videoPlayerNavigationEnabled: false), isFalse);
});
});
group('SkipMarkerButton', () {
testWidgets('tap activates skip', (tester) async {
final focusNode = FocusNode();