Skip to content

Conversation

@gspencergoog
Copy link
Contributor

Description

This adds a ShortcutsRegistry for ShortcutActivator to Intent mappings that can be modified from its descendants.

This is so that descendants can make shortcuts dynamically available to a larger portion of the app than just their descendants. This is a precursor needed by the new MenuBar, for instance, so that the menu bar itself can be placed where it likes, but the shortcuts it defines can be in effect for most, if not all, of the UI surface in the app. For example, the "Ctrl-Q" quit binding would need to work even if the focused widget wasn't a child of the MenuBar.

This just provides the shortcut to intent mapping, the actions activated by the intent are described in the context where they make sense. For example, defining a "Ctrl-C" shortcut mapped to a "CopyIntent" should perform different functions if it happens while a TextField has focus vs when a drawing has focus, so those different areas would need to define different actions mapped to "CopyIntent". A hypothetical "QuitIntent" would probably be active for the entire app, so would be mapped in an Actions widget near the top of the hierarchy.

Tests

  • Added tests for the new widget and registry.

@gspencergoog gspencergoog requested a review from goderbauer May 11, 2022 02:49
@flutter-dashboard flutter-dashboard bot added the framework flutter/packages/flutter repository. See also f: labels. label May 11, 2022
@gspencergoog gspencergoog force-pushed the shortcuts_registry branch 9 times, most recently from 979a118 to 4b66ac1 Compare May 13, 2022 23:32
@goderbauer
Copy link
Member

The analyzer seems unhappy with this one.

@gspencergoog gspencergoog force-pushed the shortcuts_registry branch 3 times, most recently from d905384 to f4e8507 Compare May 17, 2022 18:14
@goderbauer
Copy link
Member

Looks like the doc bot is unhappy.

@gspencergoog
Copy link
Contributor Author

Doc bot should be happy now.

Copy link
Member

Choose a reason for hiding this comment

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

One thing that's a little odd about this setup is the disconnect between getter and setter. The getter doesn't just return what you've set with the setter...

Copy link
Contributor Author

@gspencergoog gspencergoog May 18, 2022

Choose a reason for hiding this comment

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

Resolved that by not having ShortcutRegistry be a ShortcutManager, and linking the updates in a listener in the ShortcutRegistrar.

@gspencergoog
Copy link
Contributor Author

Okay, PTAL.

I got around the overriding of the shortcuts getter by making ShortcutRegistry not be a ShortcutManager, and registering for changes in the ShortcutRegistrar, which now has its own ShortcutManager that it copies the registered shortcuts to. It still means that if you set the shortcuts on ShortcutManager.of(context), that it can be overwritten by the registered shortcuts when they change, but each Shortcuts widget makes its own shortcut manager, and nobody really uses the manager directly.

I think we might want to deprecate and remove the Shortcuts.of and Shortcuts.maybeOf methods, because they're actually not that useful unless your ShortcutsManager subclass does something non-standard and you need to talk to it. Even in regular usage, the shortcuts you set on it will be overwritten by the shortcuts in the Shortcuts widget that owns it if they change.

Copy link
Member

@goderbauer goderbauer left a comment

Choose a reason for hiding this comment

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

LGTM

Comment on lines 1215 to 1207
Copy link
Member

Choose a reason for hiding this comment

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

I believe this is still stating the wrong thing.

Comment on lines 1290 to 1291
/// [ShortcutRegistryToken.replaceAll] and supply the token returned by
/// [ShortcutRegistry.addAll].
Copy link
Member

Choose a reason for hiding this comment

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

nit: you no longer have to supply the token.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. Fixed.

///
/// When the token is no longer needed, [dispose] should be called, and the
/// token should no longer be used.
class ShortcutRegistryToken {
Copy link
Member

Choose a reason for hiding this comment

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

Wondering: would ShortcutRegistryEntry be a better name for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that works too. I'll change it. I also considered "memento", since that's the name of the pattern, but it's esoteric.

Comment on lines +1337 to +1338
shortcuts: registry.shortcuts,
manager: manager,
Copy link
Member

Choose a reason for hiding this comment

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

This is a little strange in the (existing) Shortcuts API: You can pass a manager basically saying "hey, I want to manage the shortcuts manually" - but then the Shortcuts widget goes behind your back and modifies the manager...

(I was initially confused because you only update the manager when the shortcuts change, but they never get initially configured on it in this class)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I agree. The only use case I can see is if you supply some custom subclass of ShortcutManager, and you need to find it so you can talk to it. But you can do that yourself, and it really doesn't have anything to do with the official one.

I'll deprecate the of and maybeOf in another PR.

@goderbauer
Copy link
Member

I think we might want to deprecate and remove the Shortcuts.of and Shortcuts.maybeOf methods, because they're actually not that useful unless your ShortcutsManager subclass does something non-standard and you need to talk to it. Even in regular usage, the shortcuts you set on it will be overwritten by the shortcuts in the Shortcuts widget that owns it if they change.

I am in favor of this. The use case for that API seems unclear and actually directly interacting with the manager seems dangerous as it conflicts with what the Shortcuts widget does with it.

@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

/// ```
/// {@end-tool}
@protected
bool debugAssertNotDisposed() {
Copy link
Contributor

@passsy passsy May 23, 2022

Choose a reason for hiding this comment

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

This is a breaking change, breaking all classes that implement ChangeNotifier.

i.e. I'm using an alternative ChangeNotifier implementation that doesn't throw when disposed multiple times.

It could be implemented as extension instead

gspencergoog added a commit that referenced this pull request May 31, 2022
This reverts part of the change made in #103456 to expose a debug check for subclasses of ChangeNotifier to avoid code duplication. Instead of making debugAssertNotDisposed a public instance function, it is now a public static function. It makes it harder to call, slightly, but it means that everyone who implemented ChangeNotifier instead of extending it doesn't get broken.
camsim99 pushed a commit to camsim99/flutter that referenced this pull request Aug 10, 2022
This reverts part of the change made in flutter#103456 to expose a debug check for subclasses of ChangeNotifier to avoid code duplication. Instead of making debugAssertNotDisposed a public instance function, it is now a public static function. It makes it harder to call, slightly, but it means that everyone who implemented ChangeNotifier instead of extending it doesn't get broken.
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 30, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Aug 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants