Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard shortcuts are set on the top-level scaffold #3458

Merged
merged 6 commits into from
Oct 25, 2021

Conversation

elliette
Copy link
Member

@elliette elliette commented Oct 18, 2021

Work towards #3457

Moves keyboard shortcuts to the top-level scaffold so that they can be triggered for a particular screen no matter where the focus is.

return MouseRegion(
onEnter: (_) {
if (!focusNode.hasFocus) {
focusNode.requestFocus();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 scenarios I'm curious about:

  1. what if a user is performing an eval and then clicks an auto complete suggestion that is overlapping with the code view area? Will the code view then take focus away from the eval text field?
  2. What if a user is searching (cmd + f), and then moves the mouse over the code view (for example maybe to click the forward / backward arrows in that search field)? Will the code view then take focus away from the search field?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should find a different way to fix this. Mouse hover should not change focus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'm now tackling this in a completely different way.

  1. A Screen widget exposes a public method that can be called to return all the keyboard shortcuts that should be registered for that screen
  2. When the Screens are built in DevToolsScaffold, the keyboard shortcuts are wrapped around the top-level Scaffold widget

This fixes the issue seen in #3457 (comment). I still need to reproduce landing on the empty debugger page to confirm that the file opener can now be triggered from there.

@elliette elliette changed the title Codeview tries to claim focus when the mouse enters its area Keyboard shortcuts are set on the top-level scaffold Oct 20, 2021
final Map<ShortcutActivator, Intent> shortcuts;
final Map<Type, Action<Intent>> actions;

static ShortcutsConfiguration empty =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this a factory constructor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this should be a const constructor taking a child widget once this is refactored to be a widget.
If this wasn't a widget, probably makes the most sense as a const static field.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know what you think of it now - it's a factory constructor, and it's passed to the widget

@@ -67,6 +67,10 @@ abstract class Screen {
/// Whether to show the console for this screen.
bool showConsole(bool embed) => false;

// Which keyboard shortcuts shoud be enabled for this screen.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use /// instead of // for dartdoc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know! Switched to ///

ShortcutsConfiguration({
@required this.shortcuts,
@required this.actions,
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert that shortcuts.length == actions.length

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

bottomNavigationBar: widget.embed ? null : _buildStatusLine(),
),
child: _maybeWrapInShortcuts(
scaffold, _currentScreen.keyboardShortcuts(context)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: trailing comma

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This line is now gone

@@ -470,6 +473,22 @@ class DevToolsScaffoldState extends State<DevToolsScaffold>
);
}

Widget _maybeWrapInShortcuts(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of making this a method, create a widget class KeyboardShortcuts that takes required named params. And you can change widget to child to match flutter naming conventions. The KeyboardShortcuts widget can handle the logic here in its build method

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, switched it to a widget

@@ -326,6 +326,29 @@ class DevToolsScaffoldState extends State<DevToolsScaffold>
],
);
final theme = Theme.of(context);
final scaffold = Scaffold(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of breaking this out into its own var, put back inline in the return statement and see my comment below regarding KeyboardShortcuts. Nesting widgets directly is preferred for build methods when possible. There are some cases where we need to break widgets out into local variables, but in this case, the var scaffold is only being used once, so we can leave directly in the widget tree.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sg, done!

@@ -44,6 +44,24 @@ class DebuggerScreen extends Screen {
@override
bool showConsole(bool embed) => true;

@override
ShortcutsConfiguration keyboardShortcuts(BuildContext context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe call this buildKeyboardShortcuts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

static ShortcutsConfiguration empty =
ShortcutsConfiguration(shortcuts: {}, actions: {});

bool isEmpty() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isEmpty should be a getter not a method in Dart.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, switched to getter

@@ -304,3 +308,20 @@ class BadgePainter extends CustomPainter {
return true;
}
}

class ShortcutsConfiguration {
ShortcutsConfiguration({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be a const constructor.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks!

@elliette elliette merged commit 3f21103 into flutter:master Oct 25, 2021
@elliette elliette deleted the file-opener-bug branch December 24, 2021 00:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants