Repository navigation
fix: expose skipTraversal in FocusableActionDetector - #187356
SRAYANSH-GUPTA wants to merge 6 commits into
Conversation
FocusableActionDetector internally uses a Focus widget but did not
expose the skipTraversal parameter, forcing users to reimplement the
widget to opt a node out of focus traversal.
Adds skipTraversal to FocusableActionDetector and forwards it to the
underlying Focus widget. Also adds a {@template} for Focus.skipTraversal
so the doc comment can be shared via {@macro}.
Fixes flutter#187093
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request adds the skipTraversal property to FocusableActionDetector and forwards it to the underlying Focus widget, while also updating documentation templates and adding a test. The review feedback recommends refactoring the new test to use separate final variables instead of reassigning focusWidget to adhere to the prefer_final_locals lint rule.
| testWidgets('FocusableActionDetector passes skipTraversal to Focus', (WidgetTester tester) async { | ||
| await tester.pumpWidget( | ||
| TestWidgetsApp( | ||
| home: FocusableActionDetector( | ||
| child: const Text('child'), | ||
| ), | ||
| ), | ||
| ); | ||
|
|
||
| // By default, skipTraversal is false. | ||
| Focus focusWidget = tester.widget<Focus>( | ||
| find | ||
| .descendant(of: find.byType(FocusableActionDetector), matching: find.byType(Focus)) | ||
| .first, | ||
| ); | ||
| expect(focusWidget.skipTraversal, isFalse); | ||
|
|
||
| // When skipTraversal is set to true, it is forwarded to the Focus widget. | ||
| await tester.pumpWidget( | ||
| TestWidgetsApp( | ||
| home: FocusableActionDetector( | ||
| skipTraversal: true, | ||
| child: const Text('child'), | ||
| ), | ||
| ), | ||
| ); | ||
|
|
||
| focusWidget = tester.widget<Focus>( | ||
| find | ||
| .descendant(of: find.byType(FocusableActionDetector), matching: find.byType(Focus)) | ||
| .first, | ||
| ); | ||
| expect(focusWidget.skipTraversal, isTrue); | ||
| }); |
There was a problem hiding this comment.
To adhere to Flutter's coding standards and the prefer_final_locals lint rule, avoid reassigning the focusWidget variable. Instead, use separate final variables for the default and updated states. This improves readability and ensures the variables are immutable.
testWidgets('FocusableActionDetector passes skipTraversal to Focus', (WidgetTester tester) async {
await tester.pumpWidget(
TestWidgetsApp(
home: FocusableActionDetector(
child: const Text('child'),
),
),
);
// By default, skipTraversal is false.
final Focus defaultFocus = tester.widget<Focus>(
find
.descendant(of: find.byType(FocusableActionDetector), matching: find.byType(Focus))
.first,
);
expect(defaultFocus.skipTraversal, isFalse);
// When skipTraversal is set to true, it is forwarded to the Focus widget.
await tester.pumpWidget(
TestWidgetsApp(
home: FocusableActionDetector(
skipTraversal: true,
child: const Text('child'),
),
),
);
final Focus updatedFocus = tester.widget<Focus>(
find
.descendant(of: find.byType(FocusableActionDetector), matching: find.byType(Focus))
.first,
);
expect(updatedFocus.skipTraversal, isTrue);
});References
- Follow Effective Dart style guidelines and standard Flutter lints (such as prefer_final_locals) to use final for local variables that are not reassigned. (link)
dkwingsmt
left a comment
There was a problem hiding this comment.
LGTM. Great work, thank you!
Hari-07
left a comment
There was a problem hiding this comment.
LGTM, thanks for contributing!
|
Try |
| /// | ||
| /// The optional [consumesKey] argument defaults to true. | ||
| DoNothingAction({bool consumesKey = true}) : _consumesKey = consumesKey; | ||
| /// The optional [_consumesKey] argument defaults to true. |
There was a problem hiding this comment.
Did an analyzer error tell you to do this? I think [consumesKey] is correct in the document. Just the constructor needs to use _consumesKey. This is the new private parameter syntax sugar.
(I'm sorry that your simple change triggers so many unrelated analyzer warnings...)
|
Flutter master is still on dart 3.10 , so the new private named constructor probably can't be used yet. Not sure whats the timeline of bumping to 3.12 |
|
That makes total sense. If we had enabled that rule we would probably have converted the entire repo at the same time. Also I would prefer this PR not containing these refactors about |
|
This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
|
This pull request is being closed because it has not been updated in the last 21 days after a request for more information. If you are still working on this, please feel free to reopen it or file a new pull request. Thanks for your contribution. |
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
|
Thanks for your contribution! Since I haven't seen a reply, I'm going to reluctantly close this pull request for now, but if you get time to address the comments, we'd be more than happy to take a look at a new patch. If you do send a new patch, it would be very useful to reference this one in the description in order to help reviewers see the previous context. |
`FocusableActionDetector` wraps a `Focus` widget internally and forwards
`focusNode`, `autofocus`, `descendantsAreFocusable`, and
`descendantsAreTraversable`, but not `skipTraversal`. That leaves no way
to keep a `FocusableActionDetector` in the focus chain for key events
while excluding it from focus traversal, even though the inner `Focus`
already supports exactly that.
This adds a `skipTraversal` parameter to `FocusableActionDetector` and
passes it straight through to the inner `Focus`. It is typed `bool?` to
match `Focus.skipTraversal`, so the default of `null` keeps the current
behavior and `Focus` still resolves it to `false` unless a focus node
overrides it. The `skipTraversal` documentation on `Focus` is pulled
into a `{@template flutter.widgets.Focus.skipTraversal}` block so
`FocusableActionDetector` can reuse it with `{@macro}`, the same
convention already used for `descendantsAreFocusable` and
`descendantsAreTraversable`.
This revives flutter#187356, which picked up an LGTM before it was auto closed
after 21 days without a reply. That earlier PR also bundled some
unrelated private named parameter changes that drew review comments, so
this version is trimmed down to just the `skipTraversal` forwarding plus
its test.
Fixes flutter#187093
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
FocusableActionDetector internally uses a Focus widget but did not expose the skipTraversal parameter, forcing users to reimplement the widget to opt a node out of focus traversal.
Adds skipTraversal to FocusableActionDetector and forwards it to the underlying Focus widget. Also adds a {@template} for Focus.skipTraversal so the doc comment can be shared via {@macro}.
Fixes #187093