diff --git a/lib/features/main_screen/main_screen.dart b/lib/features/main_screen/main_screen.dart index 30c0d718..40b3a932 100644 --- a/lib/features/main_screen/main_screen.dart +++ b/lib/features/main_screen/main_screen.dart @@ -104,6 +104,9 @@ class _MainScreenState extends State { bool _handleGlobalKeyEvent(KeyEvent event) { if (event is! KeyDownEvent) return false; + // A dialog or sheet is on top: the screen's shortcuts must not reach + // through it (Ctrl+N over the welcome tour opened a second dialog, #1820). + if (ModalRoute.of(context)?.isCurrent == false) return false; final keyboard = HardwareKeyboard.instance; final shortcut = MainScreenShortcuts.resolve( diff --git a/test/features/main_screen/sidebar_toggle_test.dart b/test/features/main_screen/sidebar_toggle_test.dart index 9c51bd26..ad815eb9 100644 --- a/test/features/main_screen/sidebar_toggle_test.dart +++ b/test/features/main_screen/sidebar_toggle_test.dart @@ -1,6 +1,9 @@ -import 'package:flutter/widgets.dart'; +import 'dart:async'; import 'dart:io'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; + import 'package:flutter/material.dart' as material; import 'package:flutter_test/flutter_test.dart'; import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; @@ -47,8 +50,7 @@ void main() { }); group('Fluid Collapsible Sidebar (#557)', () { - test('AppSettings preserves sidebarVisible across sets and gets', - () async { + test('AppSettings preserves sidebarVisible across sets and gets', () async { expect(await AppSettings.instance.getSidebarVisible(), isTrue); await AppSettings.instance.setSidebarVisible(false); @@ -252,6 +254,53 @@ void main() { ); }); + testWidgets('Ctrl+B does not reach through an open dialog (#1820)', + (tester) async { + await tester.pumpWidget( + queryaThemeTestShell( + child: const material.SizedBox( + width: 1200, + height: 800, + child: MainScreen(), + ), + ), + ); + await tester.pumpAndSettle(); + + bool sidebarHidden() => find + .ancestor( + of: find.byType(ConnectionsPanel, skipOffstage: false), + matching: find.byWidgetPredicate( + (w) => w is material.Offstage && w.offstage, + skipOffstage: false, + ), + ) + .evaluate() + .isNotEmpty; + + final context = tester.element(find.byType(MainScreen)); + unawaited(material.showDialog( + context: context, + builder: (_) => const material.AlertDialog(content: Text('modal')), + )); + await tester.pumpAndSettle(); + + await tester.sendKeyDownEvent(LogicalKeyboardKey.controlLeft); + await tester.sendKeyEvent(LogicalKeyboardKey.keyB); + await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft); + await tester.pumpAndSettle(); + expect(sidebarHidden(), isFalse); + + material.Navigator.of(context).pop(); + await tester.pumpAndSettle(); + + await tester.sendKeyDownEvent(LogicalKeyboardKey.controlLeft); + await tester.sendKeyEvent(LogicalKeyboardKey.keyB); + await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft); + await tester.pumpAndSettle(); + expect(sidebarHidden(), isTrue); + }); + testWidgets( 'isolates workspace layout constraints during sidebar spring animation (#984)', (tester) async {