## Description
This PRs changes the default value for the `platform` parameter used to simulate key events.
With this PR, the default value is "web" on web, otherwise it is the operating system name retrieved from `defaultTargetPlatform`.
Previously, for methods in `WidgetController`, it defaulted to âwebâ on web, and âandroidâ everywhere else. And for methods in `KeyEventSimulator` it defaulted to âwebâ on web, and the operating system that the test was running on everywhere else. Because the operating system was based on `Platform.operatingSystem`, it usually differed from the target platform the test was running on.
AFAIK, the `platform` parameter is only meaningful for simulating `RawKeyEvent`. Once `RawKeyboard` will be fully removed, the `platform` parameter wonât be needed.
@gspencergoog In the meantime, do you think it is worth merging this fix?
## Related Issue
Fixes to https://github.com/flutter/flutter/issues/133955
## Tests
Adds one test.
*Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.*
*List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.*
*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
## Description
This PRs changes the default value transit mode for key event simulation.
The default transit mode for key event simulation is currently `KeyDataTransitMode.rawKeyData` while on the framework side `KeyDataTransitMode.keyDataThenRawKeyData` is the preferred transit mode.
`KeyDataTransitMode.keyDataThenRawKeyData` is more accurate and can help detect issues.
For instance the following test will fail with `KeyDataTransitMode.rawKeyData` because raw keyboard logic for modifier keys is less accurate:
```dart
testWidgets('Press control left once', (WidgetTester tester) async {
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.keyDataThenRawKeyData;
final List<KeyEvent> events = <KeyEvent>[];
final FocusNode focusNode = FocusNode();
addTearDown(focusNode.dispose);
await tester.pumpWidget(
Focus(
focusNode: focusNode,
autofocus: true,
onKeyEvent: (_, KeyEvent event) {
events.add(event);
return KeyEventResult.handled;
},
child: Container(),
),
);
await simulateKeyDownEvent(LogicalKeyboardKey.controlLeft);
// This will fail when transit mode is KeyDataTransitMode.rawKeyData
// because a down event for controlRight is synthesized.
expect(events.length, 1);
debugKeyEventSimulatorTransitModeOverride = null;
});
```
And the following this test is ok with `KeyDataTransitMode.rawKeyData` but rightly fails with `KeyDataTransitMode.keyDataThenRawKeyData`:
```dart
testWidgets('Simulates consecutive key down events', (WidgetTester tester) async {
debugKeyEventSimulatorTransitModeOverride = KeyDataTransitMode.rawKeyData;
// Simulating several key down events without key up in between is tolerated
// when transit mode is KeyDataTransitMode.rawKeyData, it will trigger an
// assert on KeyDataTransitMode.keyDataThenRawKeyData.
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown);
debugKeyEventSimulatorTransitModeOverride = null;
});
```
## Related Issue
Related to https://github.com/flutter/flutter/issues/143845
## Tests
Adds two tests.
`DevFSBytesContent` (and it's descendant `DevFSStringContent`) have setters that change the underlying content. These are unused outside of tests, so this PR removes them. Amongst other things, this could help me refactor https://github.com/flutter/flutter/pull/144660 into something that has fewer pitfalls.
This is purely a refactoring.
We should always target the newest, and 34 is the newest. This isn't a requirement yet (like it is for 33+) but presumably it will be made required in the nearish future.
I was doing some debugging on a RenderSliver subclass, and found
that SliverConstraints.toString was missing the precedingScrollExtent
field.
Add that, and add both that field and userScrollDirection to the
`==` and hashCode implementations, which had been skipping them,
so that all three methods now handle all the class's fields.
Partial implementation of https://github.com/flutter/flutter/issues/143348
This enables asset transformation during hot reload (except for web, because that has its own implementation of `DevFS` ð). Asset transformers will be reapplied after changing any asset and performing a hot reload during `flutter run`.
Explicitly handle the case where the iOS device is not paired. On `flutter run` show an error and bail instead of trying and failing to launch on the device.
On this PR:
```
$ flutter run -d 00008110-0009588C2651401E
'iPhone' is not paired. Open Xcode and trust this computer when prompted.
$
```
Fixes https://github.com/flutter/flutter/issues/144447
Closes https://github.com/flutter/flutter/pull/144095
Originally, my aim was just to refactor (as per usual), but while messing around with the `TableBorder.symmetric` constructor, I realized that `borderRadius` was missing!
This pull request makes a few class constructors more efficient, and it fixes#144277 by adding the missing parameter.
<br>
This is for https://github.com/flutter/flutter/issues/127803: a text field should unregister from the scribble scope, when it becomes unfocusable.
When a `FocusNode` has listeners and its `_canRequestFocus` flag is set to true, it adds `+1` to `_focusabilityListeningDescendantCount` of all ancestors until it reaches the first ancestor with `descendantsAreFocusable = false`. When the a `FocusNode`'s `descendantsAreFocusable` changes, all listeners that contributed to its `_focusabilityListeningDescendantCount` will be notified.
## Description
This PR simplifies one external link in a commented section of the Android manifest template.
## Related Issue
Fixes https://github.com/flutter/flutter/issues/144249
## Tests
Documentation only PR.
I was talking with @tvolkert about the complex behavior of Shortcuts when a text field is focused. I created [this dartpad](https://dartpad.dev/?id=0b5c08fa85637422baa84927b7f1ee5f) to illustrate the problem, which shows a key being stolen from a text field by Shortcuts, and how to prevent that using DoNothingAndStopPropagationIntent.
This PR adds a section in the docs explaining how all of this works and how to override this "stealing" problem.
This allows relanding https://github.com/flutter/engine/pull/51056. The patch introduced a change where a static member is initialized from `View.generateViewId()` instead of conditionally using that API. Without an implementation for that in android.jar, the test will fail. The test in here currently is using a fake implementation that creates errors seen below.
See https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8754827734484522225/+/u/run_plugin_test/stdout#L46564_2 for failure. More detailed failure information is available locally in the `build` folder:
```
Mockito cannot mock this class: class io.flutter.embedding.android.FlutterActivity.
If you're not sure why you're getting this error, please open an issue on GitHub.
Java : 17
JVM vendor name : JetBrains s.r.o.
JVM vendor version : 17.0.7+0-17.0.7b1000.6-10550314
JVM name : OpenJDK 64-Bit Server VM
JVM version : 17.0.7+0-17.0.7b1000.6-10550314
JVM info : mixed mode
OS name : Mac OS X
OS version : 14.3.1
You are seeing this disclaimer because Mockito is configured to create inlined mocks.
You can learn about inline mocks and their limitations under item #39 of the Mockito class javadoc.
Underlying exception : org.mockito.exceptions.base.MockitoException: Cannot instrument class io.flutter.embedding.android.FlutterActivity because it or one of its supertypes could not be initialized
at app//dev.flutter.plugins.integration_test.FlutterDeviceScreenshotTest.getFlutterView_returnsFlutterViewForFlutterActivity(FlutterDeviceScreenshotTest.java:32)
at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base@17.0.7/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base@17.0.7/java.lang.reflect.Method.invoke(Unknown Source)
at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.7/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base@17.0.7/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base@17.0.7/java.lang.reflect.Method.invoke(Unknown Source)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: org.mockito.exceptions.base.MockitoException: Cannot instrument class io.flutter.embedding.android.FlutterActivity because it or one of its supertypes could not be initialized
at app//net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:168)
at app//net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:399)
at app//net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:190)
at app//net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:410)
... 44 more
Caused by: java.lang.RuntimeException: Method generateViewId in android.view.View not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.view.View.generateViewId(View.java)
at io.flutter.embedding.android.FlutterActivity.<clinit>(FlutterActivity.java:218)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Unknown Source)
at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.assureInitialization(InlineBytecodeGenerator.java:236)
at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.triggerRetransformation(InlineBytecodeGenerator.java:261)
at org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.mockClass(InlineBytecodeGenerator.java:218)
at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.lambda$mockClass$0(TypeCachingBytecodeGenerator.java:47)
at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:168)
at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:399)
at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:190)
at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:410)
at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.mockClass(TypeCachingBytecodeGenerator.java:40)
at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createMockType(InlineDelegateByteBuddyMockMaker.java:396)
at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.doCreateMock(InlineDelegateByteBuddyMockMaker.java:355)
at org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker.createMock(InlineDelegateByteBuddyMockMaker.java:334)
at org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker.createMock(InlineByteBuddyMockMaker.java:56)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:99)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:88)
at org.mockito.Mockito.mock(Mockito.java:2087)
at org.mockito.Mockito.mock(Mockito.java:2002)
... 44 more
```
This PR removes an irrelevant comment in `TextPainter` for `_computePaintOffsetFraction`. Also some typos are corrected and missing spaces/newlines added.
test-exempt: no functional change
Reverts flutter/flutter#144207
Initiated by: CaseyHillers
Reason for reverting: b/327301206 - Breaking a customer test
Original PR Author: LongCatIsLooong
Reviewed By: {gspencergoog}
This change reverts the following previous change:
Original Description:
`FocusNode.canRequestFocus` was doing a double traversal if no ancestor disallows focus. The last for loop only has to reach as far as the enclosing scope.
Also this caches the `FocusNode.enclosingScope` since the getter access happens much more frequently than node reparenting.
Reverts flutter/flutter#144001
Initiated by: Piinks
Reason for reverting: Failing goldens at the tip of tree
Original PR Author: QuncCccccc
Reviewed By: {HansMuller}
This change reverts the following previous change:
Original Description:
Reverts flutter/flutter#143973
This is a reland for #138521 with an updated g3fix(cl/605555997). Local test: cl/609608958.
Reverts flutter/flutter#143244
Initiated by: vashworth
Reason for reverting: Increased `flutter_framework_uncompressed_bytes` - see https://github.com/flutter/flutter/issues/144251
Original PR Author: vashworth
Reviewed By: {jmagman}
This change reverts the following previous change:
Original Description:
Replace `FlutterMacOS.framework` cached artifact with `FlutterMacOS.xcframework`. Also, update usage of `FlutterMacOS.framework` to use `FlutterMacOS.xcframework`.
Part of https://github.com/flutter/flutter/issues/126016.
So far `flutter build web --wasm` was always stripping wasm symbols
except if `--no-strip-wasm` is passed.
=> Ensure that in profile mode we also keep the symbols
`FocusNode.canRequestFocus` was doing a double traversal if no ancestor disallows focus. The last for loop only has to reach as far as the enclosing scope.
Also this caches the `FocusNode.enclosingScope` since the getter access happens much more frequently than node reparenting.
Replace `FlutterMacOS.framework` cached artifact with `FlutterMacOS.xcframework`. Also, update usage of `FlutterMacOS.framework` to use `FlutterMacOS.xcframework`.
Part of https://github.com/flutter/flutter/issues/126016.
When the daemon throws an exception, the receiving client is unable to surface stack traces from the daemon.
This is because it is sent with the `trace` key here:
1e8dd1e4d6/packages/flutter_tools/lib/src/daemon.dart (L308)
But the client tries to read it with the `stackTrace` key here:
1e8dd1e4d6/packages/flutter_tools/lib/src/daemon.dart (L343)
Thanks to @mraleph for spotting this!
*List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.*
b/326825892
Part of #137040 and #80374
- Differentiate pubspec and resolution errors
- Rename platform to platformKey
- Add TODO for rework logic of flag [throwOnPluginPubspecError]
- Swap for loop: handle by platform and then by plugin
This pull request is part of the effort to solve issue #136139.
The previous [`switch` expressions PR](https://github.com/flutter/flutter/pull/143496) was comprised of many simple changes throughout `flutter/lib/src/`, but due to some more in-depth refactoring in `flutter/lib/src/rendering/`, I decided to submit the changes to this directory as a separate pull request.
There was really just one function that I changed significantly; I'll add a comment for explanation.
### Context:
DDC modules are abstractions over how libraries are loaded/updated. The entirety of google3 uses the DDC/legacy module system due to its flexibility extensibility over the other two (ES6 and AMD/RequireJS). Unifying DDC's module system saves us from duplicating work and will allow us to have finer grained control over how JS modules are loaded. This is a a prerequisite to features such as hot reload.
### Overview:
This change plumbs a boolean flag through flutter_tools that switches between DDC (new) and AMD (current) modules. This mode is automatically applied when `--extra-front-end-options=--dartdevc-module-format=ddc` is specified alongside `flutter run`. Other important additions include:
* Splitting Flutter artifacts between DDC and AMD modules
* Adding unit tests for the DDC module system
* Additional bootstrapper logic for the DDC module system
We don't expect to see any user-visible behavior or performance differences.
This is dependent on [incoming module system support in DWDS](https://github.com/dart-lang/webdev/pull/2295) and [additional artifacts in the engine](https://github.com/flutter/engine/pull/47783).
This is part of a greater effort to deprecate the AMD module system: https://github.com/dart-lang/sdk/issues/52361
The original PR was reverted because the new caret positioning callpath triggered a skparagraph assert. The assert has been removed. Relanding the PR with no changes applied.
This pull request fixes#143803 by taking advantage of Dart's null-aware operators.
And unlike `switch` expressions ([9 PRs](https://github.com/flutter/flutter/pull/143634) and counting), the Flutter codebase is already fantastic when it comes to null-aware coding. After refactoring the entire repo, all the changes involving `?.` and `??` can fit into a single pull request.
https://github.com/flutter/flutter/issues/143956
I still did not include a dartfix since a dartfix that replaces `release` with `dispose` would change the semantics and may cause a runtime crash instead of a build error.
@Piinks does setting `bulkApply` to false force the user to apply the fix to every occurrence one by one in their IDE? If so then it seems that would be the way to go for this deprecation?
Adds a localized Close Button tooltip to the 'X' Button on a SnackBar, making it readable by screen readers.
Github Issue #143793
*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
Fixes an issue where if the `TextSpan` doesn't have a text style, the specified strutStyle is not applied.
Additionally, adds a migration flag for https://github.com/flutter/engine/pull/50385, for internal golden changes. It's only going to exist for a week.
This PR implements the functionality described above and hides it behind
the `--experimental-faster-testing` flag of `flutter test`.
### The following are some performance measurements from test runs
conducted on GitHub Actions
run 1 logs:
https://github.com/derekxu16/flutter_test_ci/actions/runs/8008029772/attempts/1
run 2 logs:
https://github.com/derekxu16/flutter_test_ci/actions/runs/8008029772/attempts/2
run 3 logs:
https://github.com/derekxu16/flutter_test_ci/actions/runs/8008029772/attempts/3
**length of `flutter test --reporter=expanded test/animation
test/foundation` step**
run 1: 54s
run 2: 52s
run 3: 56s
average: 54s
**length of `flutter test --experimental-faster-testing
--reporter=expanded test/animation test/foundation` step**
run 1: 27s
run 2: 27s
run 3: 29s
average: 27.67s (~48.77% shorter than 54s)
**length of `flutter test --reporter=expanded test/animation
test/foundation test/gestures test/painting test/physics test/rendering
test/scheduler test/semantics test/services` step**
run 1: 260s
run 2: 270s
run 3: 305s
average: 278.33s
**length of `flutter test --experimental-faster-testing
--reporter=expanded test/animation test/foundation test/gestures
test/painting test/physics test/rendering test/scheduler test/semantics
test/services` step**
from a clean build (right after deleting the build folder):
run 1: 215s
run 2: 227s
run 3: 245s
average: 229s (~17.72% shorter than 278.33s)
Note that in reality, `test/material` was not passed to `flutter test`
in the trials below. All of the test files under `test/material` except
for `test/material/icons_test.dart` were listed out individually
**length of `flutter test --reporter=expanded test/material` step**
run 1: 408s
run 2: 421s
run 3: 451s
average: 426.67s
**length of `flutter test --experimental-faster-testing
--reporter=expanded test/material` step**
run 1: 382s
run 2: 373s
run 3: 400s
average: 385s (~9.77% shorter than 426.67s)
---------
Co-authored-by: Dan Field <dnfield@google.com>
My RenderSliverMultiBoxAdaptor/RenderSliverFixedExtentList/RenderSliverVariedExtentList yak shave continues.
I've been subclassing RenderSliverVariedExtentList for SliverTree and have found some opportunities for clean up.
There is a larger clean up I'd like to do, but this week SliverTree comes first.
I noticed these methods were getting repeated ð, and I was about to repeat them again ð for the tree, so I figured bumping them up to the base class was better than continuing to copy-paste the same methods.
Multiple methods in `RenderSliverFixedExtentBoxAdaptor` pass a `double itemExtent` for computing things like what children will be laid out, what the max scroll offset will be, and how the children will be laid out.
Since `RenderSliverFixedExtentBoxAdaptor` was further subclassed to support a `itemExtentBuider` in `RenderSliverVariedExtentList`, these itemExtent parameters became useless when using that RenderObject. Reading through `RenderSliverFixedExtentBoxAdaptor.performLayout`, the remaining artifacts of passing around itemExtent make it hard to follow when it is irrelevant.
`RenderSliverFixedExtentBoxAdaptor.itemExtent` is available from these methods, so it does not need to pass it. It is redundant API.
Plus, if a bogus itemExtent is passed for some reason, errors will ensue and the layout will be incorrect. ð£ ð¥
Deprecating so we can remove these for a cleaner API. Unfortunately this is not supported by dart fix, but the fact that these methods are protected means usage outside of the framework is likely minimal.
fixes [`hourMinuteTextStyle` Material 3 default doesn't match the specs](https://github.com/flutter/flutter/issues/143748)
This updates `hourMinuteTextStyle` defaults to match Material 3 specs. `hourMinuteTextStyle` should use different font style for different entry modes based on the specs.
### Specs
![Screenshot 2024-02-20 at 15 06 40](https://github.com/flutter/flutter/assets/48603081/5198a5da-314d-401e-8d7f-d4a68b86e43c)
![Screenshot 2024-02-20 at 15 07 22](https://github.com/flutter/flutter/assets/48603081/79436ce4-fef6-480a-bc43-b628497e860f)
### Before
```dart
return _textTheme.displayMedium!.copyWith(color: _hourMinuteTextColor.resolve(states));
```
### After
```dart
return entryMode == TimePickerEntryMode.dial
? _textTheme.displayLarge!.copyWith(color: _hourMinuteTextColor.resolve(states))
: _textTheme.displayMedium!.copyWith(color: _hourMinuteTextColor.resolve(states));
```
This PR fixes#142885.
The issue is that in `_RepeatingSimulation` the initial time is calculated as follows:
```
(initialValue / (max - min)) * (period.inMicroseconds / Duration.microsecondsPerSecond)
```
This calculation does not work in general. For instance, if `max` is 300, `min` is 100, and `initialValue` is 100 then `initialValue / (max - min)` is 1/2 when it should be 0
The current tests work by happenstance because the numbers used happen to work. To reveal the bug I've added some more tests similar to the existing ones but with different numbers.
A "side-effect" of the incorrect calculation is that if `initialValue` is 0, then the animation will always start from `min` no matter what. For instance, in one of the tests, an `AnimationController` with the value 0 is told to `repeat` between 0.5 and 1.0, and this starts the animation from 0.5. To preserve this behavior, and to more generally handle the case where the initial value is out of bounds, this PR clamps the initial value to be within the lower and upper bounds of the repetition.
Just for reference, this calculation was introduced at https://github.com/flutter/flutter/pull/25125.
Reverts flutter/flutter#143281
Initiated by: LongCatIsLooong
Reason for reverting: https://github.com/flutter/flutter/issues/143797
Original PR Author: LongCatIsLooong
Reviewed By: {justinmc, jason-simmons}
This change reverts the following previous change:
Original Description:
The behavior largely remains the same, except:
1. The EOT cursor `(textLength, downstream)` for text ending in the opposite writing direction as the paragraph is now placed at the visual end of the last line.
For example, in a LTR paragraph, the EOT cursor for `aA` (lowercase for LTR and uppercase for RTL) is placed to the right of the line: `aA|` (it was `a|A` before).
This matches the behavior of most applications that do logical order arrow key navigation instead of visual order navigation.
And it makes the navigation order consistent for `aA\naA`:
```
|aA => aA| => aA| => aA => aA => aA
aA aA aA |aA aA| aA|
(1) (2) (3) (4) (5) (6)
```
This is indeed still pretty confusing as (2) and (3), as well as (5) and (6) are hard to distinguish (when the I beam has a large width they are actually visually distinguishable -- they use the same anchor but one gets painted to the left and the other to the right. I noticed that emacs does the same).
But logical order navigation will always be confusing in bidi text, in one way or another.
Interestingly there are 3 different behaviors I've observed in chrome:
- the chrome download dialog (which I think uses GTK text widgets but not sure which version) gives me 2 cursors when navigating bidi text, and
- its HTML fields only show one, and presumably they place the I beam at the **trailing edge** of the character (which makes more sense for backspacing I guess).
- On the other hand, its (new) omnibar seems to use visual order arrow navigation
Side note: we may need to update the "tap to place the caret here" logic to handle the case where the tap lands outside of the text and the text ends in the opposite writing direction.
2. Removed the logarithmic search. The same could be done using the characters package but when glyphInfo tells you about the baseline location in the future we probably don't need the `getBoxesForRange` call. This should fix https://github.com/flutter/flutter/issues/123424.
## Internal Tests
This is going to change the image output of some internal golden tests. I'm planning to merge https://github.com/flutter/flutter/pull/143281 before this to avoid updating the same golden files twice for invalid selections.
Previously we merged #142930, to solve issue #87061.
Since then, I discovered that the keyboard input wasn't being captured after the app had been paused and resumed. After some digging, I realized that the problem was due to [a line in editable_text.dart](d4b1b6e744/packages/flutter/lib/src/widgets/editable_text.dart (L3589)) that called the `focusNode.consumeKeyboardToken()` method.
Luckily, it's a very easy fix: we just use `requestFocus()` instead of `applyFocusChangesIfNeeded()`. @gspencergoog could you take a look when you have a chance?
Fixes https://github.com/flutter/flutter/issues/138912
Change `ItemExtentBuilder`'s return value nullable, it should return null if asked to build an item extent with a greater index than exists.
This PR is the 9áµÊ° step in the journey to solve issue #136139 and make the entire Flutter repo more readable.
(previous pull requests: #139048, #139882, #141591, #142279, #142634, #142793, #143293, #143496)
I did a pass through all of `packages/flutter/lib/src/` and found an abundance of `switch` statements to improve. Whereas #143496 focused on in-depth refactoring, this PR is full of simple, straightforward changes. (I ended up making some more complicated changes in `rendering/` and will file those separately after this PR is done.)
The behavior largely remains the same, except:
1. The EOT cursor `(textLength, downstream)` for text ending in the opposite writing direction as the paragraph is now placed at the visual end of the last line.
For example, in a LTR paragraph, the EOT cursor for `aA` (lowercase for LTR and uppercase for RTL) is placed to the right of the line: `aA|` (it was `a|A` before).
This matches the behavior of most applications that do logical order arrow key navigation instead of visual order navigation.
And it makes the navigation order consistent for `aA\naA`:
```
|aA => aA| => aA| => aA => aA => aA
aA aA aA |aA aA| aA|
(1) (2) (3) (4) (5) (6)
```
This is indeed still pretty confusing as (2) and (3), as well as (5) and (6) are hard to distinguish (when the I beam has a large width they are actually visually distinguishable -- they use the same anchor but one gets painted to the left and the other to the right. I noticed that emacs does the same).
But logical order navigation will always be confusing in bidi text, in one way or another.
Interestingly there are 3 different behaviors I've observed in chrome:
- the chrome download dialog (which I think uses GTK text widgets but not sure which version) gives me 2 cursors when navigating bidi text, and
- its HTML fields only show one, and presumably they place the I beam at the **trailing edge** of the character (which makes more sense for backspacing I guess).
- On the other hand, its (new) omnibar seems to use visual order arrow navigation
Side note: we may need to update the "tap to place the caret here" logic to handle the case where the tap lands outside of the text and the text ends in the opposite writing direction.
2. Removed the logarithmic search. The same could be done using the characters package but when glyphInfo tells you about the baseline location in the future we probably don't need the `getBoxesForRange` call. This should fix https://github.com/flutter/flutter/issues/123424.
## Internal Tests
This is going to change the image output of some internal golden tests. I'm planning to merge https://github.com/flutter/flutter/pull/143281 before this to avoid updating the same golden files twice for invalid selections.
This follows up on #143452, to slightly further address #95978.
The double- rather than triple-slash on the blank line caused it to be ignored by dartdoc, so that the two paragraphs it's intended to separate were getting joined as one paragraph instead.
Also expand this constructor's summary line slightly to mention its distinctive feature compared with the other constructor, and make other small fixes that I noticed in other docs on this class.
## Description
This PR is the third step for the M3 test migration for `InputDecorator`.
Step 1: https://github.com/flutter/flutter/pull/142981
Step 2: https://github.com/flutter/flutter/pull/143369
This PR moves some tests out of the 'Material2' group (the ones that are ok on M3).
@justinmc The diff is almost unreadable, I moved the tests as carefully as possible and I checked that before and after the number of tests is exactly the same.
## Related Issue
Related to https://github.com/flutter/flutter/issues/139076
## Tests
Move some tests from 'Material2' group to main().
## Description
This PR updates the `InputDecoration.contentPadding` documentation to detail both Material 3 and Material 2 default values.
## Related Issue
Follow-up to https://github.com/flutter/flutter/pull/142981.
## Tests
Documentation only.
Fixes https://github.com/flutter/flutter/issues/79495
This is basically a reland of https://github.com/flutter/flutter/pull/79607.
Currently when the cursor is invalid, arrow key navigation / typing / backspacing doesn't work since the cursor position is unknown.
Showing the cursor when the selection is invalid gives the user the wrong information about the current insert point in the text.
This is going to break internal golden tests.
Fixes https://github.com/flutter/flutter/issues/143405.
It was counter-intuitive that a SemanticsFinder without specifying a FlutterView would only search the nodes in the default view. This change makes it so that when no view is specified the semantics trees of all known FlutterViews are searched.
This PR is the 8áµÊ° step in the journey to solve issue #136139 and make the entire Flutter repo more readable.
(previous pull requests: #139048, #139882, #141591, #142279, #142634, #142793, #143293)
I did a pass through all of `packages/flutter/lib/src/` and found a whole bunch of `switch` statements to improve: most of them were really simple, but many involved some thorough refactoring.
This pull request is just the complicated stuff. ð I'll make comments to describe the changes, and then in the future there will be another PR (and it'll be much easier to review than this one).
fixes [Calling `setState` in a `MaterialStatesController` listener and `MaterialStateController.update` causes Exception](https://github.com/flutter/flutter/issues/138986)
### Description
`MaterialStatesController` listener calls `setState` during build when `MaterialStatesController.update` listener calls `notifyListeners`.
I tried fixing this issue by putting `notifyListeners` in a post-frame callback. However, this breaks existing customer tests (particularly super editor tests).
A safer approach would be to document that the listener's `setState` call should be in a post-frame callback to delay it and not call this during the build phase triggered by the `MaterialStatesController.update` in the widgets such as InkWell or buttons.
Update: Accidentally use `--O4` instead of `-O4` in `dev/devicelab/lib/tasks/web_benchmarks.dart` update.
Original description:
* Make `flutter build web` have one option that determins the
optimization level: `-O<level>` / `--optimization-level=<level>` =>
Defaulting to -O4 => Will apply to both dart2js and dart2wasm
* Deprecate `--dart2js-optimization=O<level>`
* Disentagle concept of optimization from concept of static symbols =>
Add a `--strip-wasm` / `--no-strip-wasm` flag that determins whether
static symbols are kept in the resulting wasm file.
* Remove copy&past'ed code in the tests for wasm build tests
* Cleanup some artifacts code, now that we no longer use `wasm-opt`
inside flutter tools
*Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.*
*List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.*
*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
Reverts flutter/flutter#143517
Initiated by: dnfield
Reason for reverting: broke CI, see https://ci.chromium.org/ui/p/flutter/builders/prod/Linux%20web_benchmarks_skwasm/3446/overview
Original PR Author: mkustermann
Reviewed By: {eyebrowsoffire}
This change reverts the following previous change:
Original Description:
* Make `flutter build web` have one option that determins the optimization level: `-O<level>` / `--optimization-level=<level>` => Defaulting to -O4 => Will apply to both dart2js and dart2wasm
* Deprecate `--dart2js-optimization=O<level>`
* Disentagle concept of optimization from concept of static symbols => Add a `--strip-wasm` / `--no-strip-wasm` flag that determins whether static symbols are kept in the resulting wasm file.
* Remove copy&past'ed code in the tests for wasm build tests
* Cleanup some artifacts code, now that we no longer use `wasm-opt` inside flutter tools
* Make `flutter build web` have one option that determins the
optimization level: `-O<level>` / `--optimization-level=<level>` =>
Defaulting to -O4 => Will apply to both dart2js and dart2wasm
* Deprecate `--dart2js-optimization=O<level>`
* Disentagle concept of optimization from concept of static symbols =>
Add a `--strip-wasm` / `--no-strip-wasm` flag that determins whether
static symbols are kept in the resulting wasm file.
* Remove copy&past'ed code in the tests for wasm build tests
* Cleanup some artifacts code, now that we no longer use `wasm-opt`
inside flutter tools
Reverts flutter/flutter#143386
Initiated by: Piinks
Reason for reverting: This broke a customer test.
Original PR Author: Piinks
Reviewed By: {goderbauer}
This change reverts the following previous change:
Original Description:
Fixes https://github.com/flutter/flutter/issues/143173
The `start` and `end` parameters of `SemanticsController.simulatedAccessibilityTraversal` were deprecated in https://github.com/flutter/flutter/issues/112413, but no tests were added that verified the new API. 😳
This change
- fixes a typo in an error message
- fixes the new `startNode` and `endNode` not being accounted for in setting the traversal range
- adds dart fixes for the deprecations
- adds tests for the new API that is meant to replace the deprecated one.
- Filed https://github.com/flutter/flutter/issues/143405 to follow up on the new API not working in multiple views.
Reverts flutter/flutter#143334
Initiated by: hangyujin
Reason for reverting: broke g3 tests
Original PR Author: hangyujin
Reviewed By: {LongCatIsLooong}
This change reverts the following previous change:
Original Description:
Add a semantics flag to text field to fix https://github.com/flutter/flutter/issues/143337 (in IOS the disabled text field is not read `dimmed`)
internal: b/322345393
Fixes https://github.com/flutter/flutter/issues/143173
The `start` and `end` parameters of `SemanticsController.simulatedAccessibilityTraversal` were deprecated in https://github.com/flutter/flutter/issues/112413, but no tests were added that verified the new API. ð³
This change
- fixes a typo in an error message
- fixes the new `startNode` and `endNode` not being accounted for in setting the traversal range
- adds dart fixes for the deprecations
- adds tests for the new API that is meant to replace the deprecated one.
- Filed https://github.com/flutter/flutter/issues/143405 to follow up on the new API not working in multiple views.
## Description
This PR is the second step for the M3 test migration for `InputDecorator` (step 1 was https://github.com/flutter/flutter/pull/142981).
This PR migrate the two first tests of the M2 section. Those were big tests. I splitted them in several testsn organized in groups, and I narrowed their scope when possible.
@justinmc I did not move yet the M2 tests to a separate file (I move them to a group) because it would mean we loss the line history which is useful during the migration. In the next step, I will focus on moving out some tests that are in the 'Material2' group (the ones that are ok with both M2 and M3).
## Related Issue
Related to https://github.com/flutter/flutter/issues/139076
## Tests
Adds several tests for M3.
## Description
This PR adds more documentation for `TextEditingController(String text)` constructor and it adds one example.
https://github.com/flutter/flutter/pull/96245 was a first improvement to the documentation.
https://github.com/flutter/flutter/issues/79495 tried to hide the cursor when an invalid selection is set but it was reverted.
https://github.com/flutter/flutter/pull/123777 mitigated the issue of having a default invalid selection: it takes care of setting a proper selection when a text field is focused and its controller selection is not initialized.
I will try changing the initial selection in another PR, but It will probably break several existing tests.
## Related Issue
Fixes https://github.com/flutter/flutter/issues/95978
## Tests
Adds 1 test for the new example.
Entire pr generated with [ktlint](https://github.com/pinterest/ktlint) --format. First step before enabling linting as part of presubmit for kotlin changes.
Add column information as table header for `flutter emulators` command.
**Before:**
```
2 available emulators:
Pixel_3_API_30 ⢠Pixel 3 API 30 ⢠Google ⢠android
Resizable_API_33 ⢠Resizable API 33 ⢠Google ⢠android
To run an emulator, run 'flutter emulators --launch <emulator id>'.
To create a new emulator, run 'flutter emulators --create [--name xyz]'.
You can find more information on managing emulators at the links below:
https://developer.android.com/studio/run/managing-avdshttps://developer.android.com/studio/command-line/avdmanager
```
**After:**
```
2 available emulators:
Id ⢠Name ⢠Manufacturer ⢠Platform
Pixel_3_API_30 ⢠Pixel 3 API 30 ⢠Google ⢠android
Resizable_API_33 ⢠Resizable API 33 ⢠Google ⢠android
To run an emulator, run 'flutter emulators --launch <emulator id>'.
To create a new emulator, run 'flutter emulators --create [--name xyz]'.
You can find more information on managing emulators at the links below:
https://developer.android.com/studio/run/managing-avdshttps://developer.android.com/studio/command-line/avdmanager
```
fixes#140656
* Flags to `dart compile wasm`
Some options are not relevant to a standalone user of `dart compile
wasm` (e.g. specyfing dart-sdk, platform file etc). => Those aren't
offered by the `dart compile wasm` tool directly. => We use the
`--extra-compiler-option=` instead which passes through arbitrary
options to the dart2wasm compiler. => We don't maintain compatibility of
those options, if we update them we'll ensure to also update flutter
tools
* Binaryen optimization passes
This change will mean we use the binaryen flags from Dart SDK which are
slightly different from the ones in flutter.
* Optimization configuration
This change will also start using the more standardized `-O` flag for
determining optimization levels. The meaning of those flags have been
mostly aligned with dart2js (with some differences remaining).
* Minimization
Using the new optimization flags, namely `-O4` for `--wasm-opt=full`,
will automatically enable the new `--minify` support. Minification is
Dart semantics preserving but changes the `<obj>.runtimeType.toString()`
to use minified names (just as in dart2js).
* Code size changes
Overall this change will reduce wonderous code size by around 10%.
Issue https://github.com/dart-lang/sdk/issues/54675
In service of https://github.com/flutter/flutter/issues/143348.
**Issue.** The `equals` implementation of `AssetsEntry` is incorrect. It compares `flavors` lists using reference equality. This PR addresses this.
This also adds a test to make sure valid asset `flavors` declarations are parsed correctly.
While we are here, this PR also includes a couple of refactorings:
* `flutter_manifest_test.dart` is a bit large. To better match our style guide, I've factored out some related tests into their own file.
* A couple of changes to the `_validateListType` function in `flutter_manifest.dart`:
* The function now returns a list of errors instead of accepting a list to append onto. This is more readable and also allows callers to know which errors were found by the call.
* The function is renamed to `_validateList` and now accepts an `Object?` instead of an `YamlList`. If the argument is null, an appropriate error message is contained in the output. This saves callers that are only interested in validation from having to write their own null-check, which they all did before.
* Some error strings were tweaked for increased readability and/or grammatical correctness.
fixes#87061
It doesn't matter whether I'm using Google Chrome, VS Code, Discord, or a Terminal window: any time a text cursor is blinking, it means that the characters I type will show up there.
And this isn't limited to text fields: if I repeatedly press `Tab` to navigate through a website, there's a visual indicator that goes away if I click away from the window, and it comes back if I click or `Alt+Tab` back into it.
<details open>
<summary>Example (Chrome):</summary>
![focus node](https://github.com/flutter/flutter/assets/10457200/bef42cd9-28e5-4214-b071-b7ef56b26609)
</details>
<details open>
<summary>This PR adds the same functionality to Flutter apps:</summary>
![Flutter demo](https://github.com/flutter/flutter/assets/10457200/6eb34c44-5fb0-4b27-aa10-6606a1eb187e)
</details>
Update dependencies to latest versions
Related to #142618Fixes#143219
- [ x I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
This is an attempt at a reland of https://github.com/flutter/flutter/pull/141396
The main changes here that are different than the original PR is fixes to wire up the `flutter test` command properly with the web renderer.
This is in service of https://github.com/flutter/flutter/pull/141194
This will make it easier to get the `flutter run -d <browser>` and `flutter build fuschia` cases easier to get under test.
This PR is the 7áµÊ° step in the journey to solve issue #136139 and make the entire Flutter repo more readable.
(previous pull requests: #139048, #139882, #141591, #142279, #142634, #142793)
This pull request covers everything in `packages/flutter/lib/src/widgets/`. Most of it should be really straightforward, but there was some refactoring in the `getOffsetToReveal()` function in `two_dimensional_viewport.dart`. I'll add some comments to describe those changes.
This is a direct revert of (the revert of (the reland of (the policy pr))): https://github.com/flutter/flutter/pull/143132.
The only change is:
1. to put a conditional all on one line, because the packages repository has a test that uses an old flutter project to make sure nothing regresses. The old project uses an old gradle version, and the old gradle version bundles an old groovy version, and the old groovy version has a bug where lines that start with `&&` don't always work: https://issues.apache.org/jira/browse/GROOVY-7218 (I enjoy that the revert reason ends up providing another strong justification to go forward with the policy). Also thanks to @reidbaker for pointing out this bug.
2. I also made a slight formatting change to the messages that print when out of the support bounds, which I think looks slightly better.
I tested this with on a branch that included a revert of https://github.com/flutter/flutter/pull/142008, and was able to recreate the failure and verify that it was resolved by 1).
fixes [The InputDecoration's suffix and prefix widget can be tapped even if it does not appear](https://github.com/flutter/flutter/issues/139916)
This PR also updates two existing tests to pass the tests for this PR. These tests are trying to tap prefix and suffix widgets when they're hidden. While the linked issue had visible prefix and suffix widgets https://github.com/flutter/flutter/issues/39376 for reproduction.
### Code sample
<details>
<summary>expand to view the code sample</summary>
```dart
import 'package:flutter/material.dart';
void main() {
runApp(MainApp());
}
class MainApp extends StatelessWidget {
final _messangerKey = GlobalKey<ScaffoldMessengerState>();
MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
scaffoldMessengerKey: _messangerKey,
home: Scaffold(
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16.0),
child: TextField(
decoration: InputDecoration(
labelText: 'Something',
prefix: GestureDetector(
onTap: () {
_messangerKey.currentState?.showSnackBar(
const SnackBar(content: Text('A tap has occurred')));
},
child: const Icon(Icons.search),
),
suffix: GestureDetector(
onTap: () {
_messangerKey.currentState?.showSnackBar(
const SnackBar(content: Text('A tap has occurred')));
},
child: const Icon(Icons.search),
),
),
),
),
),
);
}
}
```
</details>
### Before
![ScreenRecording2024-02-12at18 40 34-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/c101e0d6-ce5a-4b28-9626-28bcb83d2a5c)
### After
![ScreenRecording2024-02-12at18 40 10-ezgif com-video-to-gif-converter](https://github.com/flutter/flutter/assets/48603081/923b348e-8adf-4d64-9dc3-e75d30e3e2fb)
1. Remove `dev_target` from suggested Firebase Test Lab iOS script and use wildcard instead.
2. First run `flutter clean` before building to avoid collisions between runs.
3. Use `zip --must-match` in case the xctestrun or `Release-iphoneos` directories are missing (like ran with `--profile` instead of `--release` on purpose) to fail instead of zipping up only part of what's needed.
This came out of a discussion with FTL about these instructions and I tried to run them locally and avoided setting `dev_target`.
See also #74428
During golden test image comparison 2 lists of a different type are compared with the method "identical", so this will never be true. The test image is a _Uint8ArrayView while the master image is an Uint8List. So that results in always a heavy computation to get the difference between the test and the master image.
When you run this test snippet I go from 51 seconds to 14 seconds:
```dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
for (int i = 0; i < 100; i++) {
testWidgets('Small test', (WidgetTester tester) async {
await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr, child: Text('jo')));
await expectLater(find.byType(Text), matchesGoldenFile('main.png'));
});
}
}
```
This PR is the 6áµÊ° step in the journey to solve issue #136139 and make the entire Flutter repo more readable.
(previous pull requests: #139048, #139882, #141591, #142279, #142634)
The current focus is on `packages/flutter/lib/src/material/`. The previous 2 PRs covered files in this directory starting with letters `a-m`; this one takes care of everything else.
We already have a simple app in this repo that fully uses Gradle Kotlin DSL (see #141541). The next small step is to have at least one plugin that also uses Gradle Kotlin DSL. Let's use `integration_test` for that, since it's versioned with Flutter SDK.
Fixes https://github.com/flutter/flutter/issues/138610.
When `RenderImage` receives a new `Image` it only needs to fire up the layout machinery when the dimensions of the image have changed compared to the previous image. If the dimensions are the same, a repaint is sufficient.
Re land of https://github.com/flutter/flutter/pull/142000.
Differences:
1. Fixed the test that was failing in postsubmit. The reason was that the Flutter Gradle Plugin was being applied after KGP in that test, so we couldn't find the KGP version. This caused a log, and the test expects no logs. I moved FGP to after KGP
2. Added to the logs for when we can't find AGP. Change is from
> "Warning: unable to detect project AGP version. Skipping version checking."
to
> ~"Warning: unable to detect project AGP version. Skipping version checking. \nThis may be because you have applied the Flutter Gradle Plugin after AGP."~
update: the above is wrong, changed to
> "Warning: unable to detect project KGP version. Skipping version checking. \nThis may be because you have applied AGP after the Flutter Gradle Plugin."
3. Added a note to the app-level build.gradle templates that FGP must go last
> // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugin.
Dual Web Compile has had some issues where `flutter test` is not respecting the `--web-renderer` flag for some reason. I haven't gotten entirely to the bottom of the issue, but for now we need to rever these changes while I investigate. This reverts the following PRs:
https://github.com/flutter/flutter/pull/143128https://github.com/flutter/flutter/pull/141396
While doing this revert, I had a few merge conflicts with https://github.com/flutter/flutter/pull/142760, and I tried to resolve the merge conflicts within the spirit of that PR's change, but @chingjun I might need your input on whether the imports I have modified are okay with regards to the change you were making.
Fixes#142896
The original code below is to always place the selected item above(overlap) the popup button so that the selected item can always be visible: f8a77225f3/packages/flutter/lib/src/material/popup_menu.dart (L723-L732)
But when menu height is constrained and the menu itself is super long, the selected item still assumes there is enough space to push up all the items whose index is smaller than the selected index. As a result, every time when the menu is open, the calculation provides a different result to be the offset for the selected index, and then with a constrained height, the menu looks jumping all over the place based on the different selected index.
https://github.com/flutter/flutter/assets/36861262/ad761f95-0ff5-4311-a81d-dac56df879c5
Even though the original calculation is to make the selected item visible when open the menu, the menu doesn't auto scroll and only expands itself as much as possible to show the selected one. In this case, if the screen it too small to show the selected item, we still cannot see it. This can be fixed by using `Scrollable.ensureVisible()`(#143118).
So we remove the calculation in this PR and the menu will always show up based on the top left of the anchor(button).
https://github.com/flutter/flutter/assets/36861262/03272f26-9440-4ac4-a701-9a0b41776ff9
Reland of https://github.com/flutter/flutter/pull/142709.
The revert of the revert is in the first commit, the fix in the commit on top.
The move of the fakes for packages/flutter_tools/test/general.shard/resident_runner_test.dart was erroneous before, as it was trying to use setters instead of a private field. This PR changes the private `_devFS` field in the fake to be a public `fakeDevFS` in line with other fakes.
## Original PR description
Native assets in other build systems are not built with `package:native_assets_builder` invoking `build.dart` scripts. Instead all packages have their own blaze rules. Therefore we'd like to not depend on `package:native_assets_builder` from flutter tools in g3 at all.
This PR aims to move the imports of `native_assets_builder` and `native_assets_cli` into the `isolated/` directory and into the files with a `main` function that are not used in with other build systems.
In order to be able to remove all imports in files used by other build systems, two new interfaces are added `HotRunnerNativeAssetsBuilder` and `TestCompilerNativeAssetsBuilder`. New parameters are then piped all the way through from the entry points:
* bin/fuchsia_tester.dart
* lib/executable.dart
The build_system/targets dir is already excluded in other build systems.
So, after this PR only the two above files and build_system/targets import from `isolated/native_assets/` and only `isolated/native_assets/` import `package:native_assets_cli` and `package:native_assets_builder`.
Context:
* https://github.com/flutter/flutter/issues/142041
Adding `SingleChildScrollView` to `NavigationRail` may cause exception if the nav rail has some expanded widgets inside, like the issue: https://github.com/flutter/flutter/issues/143061. This PR is just to add a unit test to avoid causing this breaking again.
Policy per https://flutter.dev/go/android-dependency-versions.
https://github.com/flutter/flutter/issues/140913
~Still a WIP while I clean up some error handling, remove some prints, and figure out a Java test (more difficult than the others because I believe we can only install one java version per ci shard).~
~Also it looks like there are errors that I need to fix when this checking is applied to a project that uses the old way of applying AGP/KGP using the top-level `build.gradle` file (instead of the new template way of applying them in the `settings.gradle` file).~ Done, this is why [these lines exist](9af6bae6b9/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy (L72-L88)) in `flutter.groovy`. They just needed to be added
Since `WebReleaseBundle` is responsible for copying over the outputs from the subtargets, so it needs to be reflected in inputs and outputs so that things will be recopied when something changes.
Re-sets two jvmargs that were getting cleared because we set a value for `-Xmx`. Could help with https://github.com/flutter/flutter/issues/142957. Copied from comment here https://github.com/flutter/flutter/issues/142957:
>Two random things I ran into while looking into this that might help:
>
>1. Gradle has defaults for a couple of the jvmargs, and setting any one of them clears those defaults for the others (bug here https://github.com/gradle/gradle/issues/19750). This can cause the "Gradle daemon to consume more and more native memory until it crashes", though the bug typically has a different associated error. It seems worth it to re-set those defaults.
>2. There is a property we can set that will give us a heap dump on OOM ([-XX:HeapDumpOnOutOfMemoryError](https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/clopts001.html))
Mostly just a find and replace from `find . -name gradle.properties -exec sed -i '' 's/\-Xmx4G/-Xmx4G\ \-XX:MaxMetaspaceSize=2G\ \-XX:+HeapDumpOnOutOfMemoryError/g' {} \;`, with the templates and the one test that writes from a string replaced by hand. I didn't set a value for `MaxMetaspaceSize` in the template files because I want to make sure this value doesn't cause problems in ci first (changes to the templates are essentially un-revertable for those who `flutter create` while the changes exist).
This is part 3 of a broken down version of the #140101 refactor.
There's some TODOs showing where I think we should change the behaviour, but in this PR the behaviour is unchanged.
A future PR will remove the tests that are redundant with these tests, but I wanted to make sure we had both sets in the codebase at the same time first.
This PR includes a change to the golden control test so that we can verify that these specific values do work on main. It would be extremely surprising if not, but in the interests of rigour...
`precacheImage` was failing to dipose the `ImageInfo` it receives. That's part of the contract of being an image listener.
I'm doing this in the frame callback for the same reason as evicting it from the cache.
Update the `matchesGoldenFile()` / `LocalComparisonOutput` code to generate failure images for golden tests that fail when the image sizes do not match. This can make it far quicker to identify what is wrong with the test image.
Fixes https://github.com/flutter/flutter/issues/141488
- [ x I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
Reverts flutter/flutter#138545
Initiated by: zanderso
Reason for reverting: Failing in post-submit: https://ci.chromium.org/ui/p/flutter/builders/prod/Linux%20web_long_running_tests_5_5/14975/overview
```
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞═════════════════
The following FormatException was thrown running a test:
Invalid Shader Data
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.da
Original PR Author: bleroux
Reviewed By: {Piinks}
This change reverts the following previous change:
Original Description:
## Description
This PR activates the M3 `InkSparkle` splash animation on Android + CanvasKit.
Before it `InkSparkle` was only activated on native Android.
## Related Issue
Fixes https://github.com/flutter/flutter/issues/138487
## Tests
Updates several existing tests.
## Description
This PR activates the M3 `InkSparkle` splash animation on Android + CanvasKit.
Before it `InkSparkle` was only activated on native Android.
## Related Issue
Fixes https://github.com/flutter/flutter/issues/138487
## Tests
Updates several existing tests.
Previously, we were comparing the signed int `target_length` (returned by WideCharToMultiByte) to a size_t string length, resulting in a signed/unsigned comparison warning as follows:
```
windows\runner\utils.cpp(54,43): warning C4018: '>': signed/unsigned mismatch
```
WideCharToMultiByte returns:
* 0 on error
* the number of bytes written to the buffer pointed to by its fifth parameter, lpMultiByteStr, on success.
As a result it's safe to store the return value in an unsigned int, which eliminates the warning.
No changes to tests since this is dependent on end-user project settings/modifications and does not trigger a warning with default project settings.
Fixes: https://github.com/flutter/flutter/issues/134227
Reverts flutter/flutter#142709
Initiated by: vashworth
Reason for reverting: `Mac tool_tests_general` started failing on this commit: https://ci.chromium.org/ui/p/flutter/builders/prod/Mac%20tool_tests_general/15552/overview
Original PR Author: dcharkes
Reviewed By: {christopherfujino, chingjun, reidbaker}
This change reverts the following previous change:
Original Description:
Native assets in other build systems are not built with `package:native_assets_builder` invoking `build.dart` scripts. Instead all packages have their own blaze rules. Therefore we'd like to not depend on `package:native_assets_builder` from flutter tools in g3 at all.
This PR aims to move the imports of `native_assets_builder` and `native_assets_cli` into the `isolated/` directory and into the files with a `main` function that are not used in with other build systems.
In order to be able to remove all imports in files used by other build systems, two new interfaces are added `HotRunnerNativeAssetsBuilder` and `TestCompilerNativeAssetsBuilder`. New parameters are then piped all the way through from the entry points:
* bin/fuchsia_tester.dart
* lib/executable.dart
The build_system/targets dir is already excluded in other build systems.
So, after this PR only the two above files and build_system/targets import from `isolated/native_assets/` and only `isolated/native_assets/` import `package:native_assets_cli` and `package:native_assets_builder`.
Context:
* https://github.com/flutter/flutter/issues/142041
`destructiveRed` is an alias for `systemRed`, but, in the definition, the precise type information is lost.
This PR gives `destructiveRed` the type `CupertinoDynamicColor` (and not the superclass `Color`) like all the other colors defined in this file.
Native assets in other build systems are not built with `package:native_assets_builder` invoking `build.dart` scripts. Instead all packages have their own blaze rules. Therefore we'd like to not depend on `package:native_assets_builder` from flutter tools in g3 at all.
This PR aims to move the imports of `native_assets_builder` and `native_assets_cli` into the `isolated/` directory and into the files with a `main` function that are not used in with other build systems.
In order to be able to remove all imports in files used by other build systems, two new interfaces are added `HotRunnerNativeAssetsBuilder` and `TestCompilerNativeAssetsBuilder`. New parameters are then piped all the way through from the entry points:
* bin/fuchsia_tester.dart
* lib/executable.dart
The build_system/targets dir is already excluded in other build systems.
So, after this PR only the two above files and build_system/targets import from `isolated/native_assets/` and only `isolated/native_assets/` import `package:native_assets_cli` and `package:native_assets_builder`.
Context:
* https://github.com/flutter/flutter/issues/142041
Fixes#128696 (Motion checkbox)
This PR updates the Material 3 tab indicator animation, so that it stretches, as it can be seen in the showcase videos in the specification https://m3.material.io/components/tabs/accessibility#13ed756b-fb35-4bb3-ac8c-1157e49031d8
One thing to note is that the Material 3 videos have a tab transition duration of 700 ms, whereas currently in Flutter the duration is 300 ms. I recorded 4 comparison videos to see the difference better (current animation vs stretch animation and 300 ms vs 700 ms)
@Piinks You mentioned the other day that the default tab size could be updated in the future to better reflect the new size in M3. Maybe the `kTabScrollDuration` constant is another one that could end up being updated, as 300 ms for this animation feels too fast.
Here are the comparison videos (Material 3 spec showcase on the left and Flutter on the right)
## Original animation - 300 ms
https://github.com/flutter/flutter/assets/22084723/d5b594fd-52ea-4328-b8e2-ddb597c81f69
## New animation - 300 ms
https://github.com/flutter/flutter/assets/22084723/c822f7ab-3fc4-4403-a53b-872d047f6227
---
## Original animation - 700 ms
https://github.com/flutter/flutter/assets/22084723/fe39a32d-3d10-4c0d-98df-bd5e1c9336d0
## New animation - 700 ms
https://github.com/flutter/flutter/assets/22084723/8d4b0628-6312-40c2-bd99-b4bcb8e23ba9
---
## Code sample
```dart
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: TabExample(),
);
}
}
class TabExample extends StatelessWidget {
const TabExample({super.key});
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: 1,
length: 3,
child: Scaffold(
appBar: AppBar(
title: const Text('My saved media'),
bottom: const TabBar(
tabs: <Widget>[
Tab(
icon: Icon(Icons.videocam_outlined),
text: "Video",
),
Tab(
icon: Icon(Icons.photo_outlined),
text: "Photos",
),
Tab(
icon: Icon(Icons.audiotrack),
text: "Audio",
),
],
),
),
body: const TabBarView(
children: <Widget>[
Center(
child: Text("Tab 1"),
),
Center(
child: Text("Tab 2"),
),
Center(
child: Text("Tab 3"),
),
],
),
),
);
}
}
```
*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
This change affects Android and iOS devices using the TextField's context menu. After this change the context menu will fade out when scrolling the text and fade in when the scroll ends.
If the scroll ends and the selection is outside of the view, then the toolbar will be scheduled to show in a future scroll end. This toolbar scheduling can be invalidated if the `TextEditingValue` changed anytime between the scheduling and when the toolbar is ready to be shown.
This change also fixes a regression where the TextField context menu would not fade when the selection handles where not visible.
When using the native browser context menu this behavior is not controlled by Flutter.
https://github.com/flutter/flutter/assets/948037/3f46bcbb-ba6f-456c-8473-e42919b9d572Fixes#52425Fixes#105804Fixes#52426
â¦and removed the no-shuffle tag.
This PR fixes#142376 by fixing the flaky test in language_version_test.dart and removes the no-shuffle tag.
Â
## The Problem
The test expected the language version that is set at the top of the test file ('2.13' set in language_version_test.dart â line 14) but defaulted to the language version set in the file it is testing ('2.12' is set in language_version.dart).
This problem was hidden when some other test ran before this test and set up the language version correctly.
Â
## The Fix
Make the test itself load the default language version we are testing against.
This PR updates almost* all Gradle buildscripts in the Flutter repo the `example` and `dev` (in particular, in `dev/integration_tests` and in `dev/benchmarks`) directories to apply Flutter's Gradle plugins using the declarative `plugins {}` block.
*almost, because:
- add-to-app (aka hybrid) apps are not migrated (related https://github.com/flutter/flutter/issues/138756)
- apps that purposefully use build files to ensure backward compatibility (e.g. [`gradle_deprecated_settings`](https://github.com/flutter/flutter/tree/3.16.0/dev/integration_tests/gradle_deprecated_settings))
Add a new `BuildTargets` class that provides commonly used build targets. And avoid importing files from `build_system/targets` except from the top level entrypoints or from top level commands.
Also move `scene_importer.dart` and `shader_compiler.dart` into `build_system/tools` because they are not `Target` classes, but wrapper for certain tools.
With this change, we can ignore all files in `build_system/targets` internally and make PR #142709 easier to land internally. See cl/603434066 for the corresponding internal change.
Related to:
https://github.com/flutter/flutter/pull/142709https://github.com/flutter/flutter/issues/142041
Also note that I have opted to add a new variable in `globals.dart` for `BuildTargets` in this PR, but I know that we are trying to get rid of globals. Several alternatives that I was considering:
1. Add a new field in `BuildSystem` that returns a `BuildTargets` instance. Since `BuildSystem` is already in `globals`, we can access build targets using `globals.buildSystem.buildTargets` without adding a new global variable.
2. Properly inject the `BuildTargetsImpl` instance from the top level `executable.dart` and top level commands.
Let me know if you want me to do one of the above instead. Thanks!
This implements dual compile via the newly available flutter.js bootstrapping APIs for intelligent build fallback.
* Users can now use the `FlutterLoader.load` API from flutter.js
* Flutter tool injects build info into the `index.html` of the user so that the bootstrapper knows which build variants are available to bootstrap
* The semantics of the `--wasm` flag for `flutter build web` have changed:
- Instead of producing a separate `build/web_wasm` directory, the output goes to the `build/web` directory like a normal web build
- Produces a dual build that contains two build variants: dart2wasm+skwasm and dart2js+CanvasKit. The dart2wasm+skwasm will only work on Chrome in a cross-origin isolated context, all other environments will fall back to dart2js+CanvasKit.
- `--wasm` and `--web-renderer` are now mutually exclusive. Since there are multiple build variants with `--wasm`, the web renderer cannot be expressed via a single command-line flag. For now, we are hard coding what build variants are produced with the `--wasm` flag, but I plan on making this more customizable in the future.
* Build targets now can optionally provide a "build key" which can uniquely identify any specific parameterization of that build target. This way, the build target can invalidate itself by changing its build key. This works a bit better than just stuffing everything into the environment defines because (a) it doesn't invalidate the entire build, just the targets which are affected and (b) settings for multiple build variants don't translate well to the flat map of environment defines.
Reland https://github.com/flutter/flutter/pull/141818 with a fix for a special case: If only `background` is specified for `TextButton.styleFrom` or `OutlinedButton.styleFrom` it applies the button's disabled state, i.e. as if the same value had been specified for disabledBackgroundColor.
The change relative to #141818 is the indicated line below:
```dart
final MaterialStateProperty<Color?>? backgroundColorProp = switch ((backgroundColor, disabledBackgroundColor)) {
(null, null) => null,
(_, null) => MaterialStatePropertyAll<Color?>(backgroundColor), // ADDED THIS LINE
(_, _) => _TextButtonDefaultColor(backgroundColor, disabledBackgroundColor),
};
```
This backwards incompatibility cropped up in an internal test, see internal Google issue b/323399158.
This PR is step 5 in the journey to solve issue #136139 and make the entire Flutter repo more readable.
(previous pull requests: #139048, #139882, #141591, #142279)
The current focus is on `packages/flutter/lib/src/material/`.
The previous PR covered files in this directory starting with `a`, `b`, and `c`; this pull request is for `d` through `m`.
When the Dart VM is not found within 10 minutes in CI on CoreDevices (iOS 17+), stop the app and upload the logs from DerivedData. The app has to be stopped first since the logs are not put in DerivedData until it's stopped.
Also, rearranged some logic to have CoreDevice have its own function for Dart VM url discovery.
Debugging for https://github.com/flutter/flutter/issues/142448.
Reverts flutter/flutter#141818
Initiated by: XilaiZhang
This change reverts the following previous change:
Original Description:
Fixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563.
Two new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button's background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme's style parameter.
The new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are:
```dart
typedef ButtonLayerBuilder = Widget Function(
BuildContext context,
Set<MaterialState> states,
Widget? child
);
```
The new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button.
## `backgroundBuilder`
Creates a widget that becomes the child of the button's Material and whose child is the rest of the button, including the button's `child` parameter. By default the returned widget is clipped to the Material's ButtonStyle.shape.
The `backgroundBuilder` can be used to add a gradient to the button's background. Here's an example that creates a yellow/orange gradient background:
![opaque-gradient-bg](https://github.com/flutter/flutter/assets/1377460/80df8368-e7cf-49ef-aee7-2776a573644c)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Because the background widget becomes the child of the button's Material, if it's opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button's Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget. This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.
![ink-gradient-bg](https://github.com/flutter/flutter/assets/1377460/68a49733-f30e-44a1-a948-dc8cc95e1716)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Now the button's overlay highlights are painted on the Ink widget. An Ink widget isn't needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget.
![translucent-graident-bg](https://github.com/flutter/flutter/assets/1377460/3b016e1f-200a-4d07-8111-e20d29f18014)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.orange.withOpacity(0.5),
Colors.yellow.withOpacity(0.5),
]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
One can also decorate the background with an image. In this example, the button's background is an burlap texture image. The foreground color has been changed to black to make the button's text a little clearer relative to the mottled brown backround.
![burlap-bg](https://github.com/flutter/flutter/assets/1377460/f2f61ab1-10d9-43a4-bd63-beecdce33b45)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.black,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(burlapUrl),
fit: BoxFit.cover,
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.
![gradient-flip](https://github.com/flutter/flutter/assets/1377460/c6c6fe26-ae47-445b-b82d-4605d9583bd8)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button's shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there's no `styleFrom` shorthand for this case.
![border-gradient-bg](https://github.com/flutter/flutter/assets/1377460/63cffcd3-0dcf-4eb1-aed5-d14adf1e57f6)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.indigo,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
).copyWith(
side: MaterialStateProperty.resolveWith<BorderSide?>((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return BorderSide(width: 3, color: Colors.yellow);
}
return null; // defer to the default
}),
),
child: Text('Text Button'),
)
```
Although all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton.
## `foregroundBuilder`
Creates a Widget that contains the button's child parameter. The returned widget is clipped by the button's [ButtonStyle.shape] inset by the button's [ButtonStyle.padding] and aligned by the button's [ButtonStyle.alignment].
The `foregroundBuilder` can be used to wrap the button's child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child.
This example adds a border that's just applied to the child. The border only appears when the button is hovered/pressed.
![border-fg](https://github.com/flutter/flutter/assets/1377460/687a3245-fe68-4983-a04e-5fcc77f8aa21)
```dart
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return DecoratedBox(
decoration: BoxDecoration(
border: states.contains(MaterialState.hovered)
? Border(bottom: BorderSide(color: colorScheme.primary))
: Border(), // essentially "no border"
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The foregroundBuilder can be used with `ShaderMask` to change the way the button's child is rendered. In this example the ShaderMask's gradient causes the button's child to fade out on top.
![shader_mask_fg](https://github.com/flutter/flutter/assets/1377460/54010f24-e65d-4551-ae58-712135df3d8d)
```dart
ElevatedButton(
onPressed: () { },
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: <Color>[
colorScheme.primary,
colorScheme.primaryContainer,
],
).createShader(bounds);
},
blendMode: BlendMode.srcATop,
child: child,
);
},
),
child: const Text('Elevated Button'),
)
```
A commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn't use the child it's passed, even though we've provided the required TextButton child parameter.
![image-button](https://github.com/flutter/flutter/assets/1377460/f5b1a22f-43ce-4be3-8e70-06de4c958380)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final String url = states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url;
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
In this example the button's default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:
![image-per-state](https://github.com/flutter/flutter/assets/1377460/7ab9da2f-f661-4374-b395-c2e0c7c4cf13)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.transparent,
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
String url = states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url;
if (states.contains(MaterialState.pressed)) {
url = smiley2Url;
}
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
This PR fixes CupertinoTabView's handling of Android back button with PopScope and nested navigators by calling `NavigatorState.maybePop` instead of `NavigatorState.pop`, so that the Navigator pops only when it should.
Fix#139050
This PR is to add 19 new `ColorScheme` roles following the Material Design 3 specs. This PR doesn't apply the new colors to `ThemeData` or any widgets.
This PR is created to split the big change in #138521, once this is merged, another PR that contains the rest of the changes(apply new color roles to widgets and deprecate 3 more colors) will follow.
**Tone-based surface colors** (7 colors):
* surfaceBright
* surfaceDim
* surfaceContainer
* surfaceContainerLowest
* surfaceContainerLow
* surfaceContainerHigh
* surfaceContainerHighest
**Accent color add-ons** (12 colors):
* primary/secondary/tertiary-Fixed
* primary/secondary/tertiary-FixedDim
* onPrimary/onSecondary/onTertiary-Fixed
* onPrimary/onSecondary/onTertiary-FixedVariant
Please checkout this [design doc](https://docs.google.com/document/d/1ODqivpM_6c490T4j5XIiWCDKo5YqHy78YEFqDm4S8h4/edit?usp=sharing) for more information:)
## Description
This changes the factory constructors for `TextButton.icon`, `ElevatedButton.icon`, `FilledButton.icon`, and `FilledButton.tonalIcon` to take nullable icons. If the icon is null, then the "regular" version of the button is created.
## Tests
- Added tests for all four constructors.
The regular chip and the action chip templates were referencing non existent M3 design tokens.
Fixes https://github.com/flutter/flutter/issues/141288
The `ActionChip` doesn't have any visual difference. Even though the template and file changes, the default `labelStyle` color already uses `onSurface`.
For the reviewer, I've changed the `action_chip_test` to expect a color from the colorScheme so that it is more explicit that the color might not be the same as the labelLarge default in the global textTheme, even if for this case the color is the same.
The regular `Chip` does have visual differences, in particular, the label and trailing icon colors, which were not following the specification. In order to fix this, the regular chip now is based from the `filter-chip` spec as described in the linked issue.
## Before
![image](https://github.com/flutter/flutter/assets/22084723/d602ef42-625a-4b5c-b63b-c46cb2070d80)
## After
![image](https://github.com/flutter/flutter/assets/22084723/dddb754f-fd29-4c4c-96cc-e7f508219f12)
Fixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563.
Two new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button's background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme's style parameter.
The new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are:
```dart
typedef ButtonLayerBuilder = Widget Function(
BuildContext context,
Set<MaterialState> states,
Widget? child
);
```
The new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button.
## `backgroundBuilder`
Creates a widget that becomes the child of the button's Material and whose child is the rest of the button, including the button's `child` parameter. By default the returned widget is clipped to the Material's ButtonStyle.shape.
The `backgroundBuilder` can be used to add a gradient to the button's background. Here's an example that creates a yellow/orange gradient background:
![opaque-gradient-bg](https://github.com/flutter/flutter/assets/1377460/80df8368-e7cf-49ef-aee7-2776a573644c)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Because the background widget becomes the child of the button's Material, if it's opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button's Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget. This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.
![ink-gradient-bg](https://github.com/flutter/flutter/assets/1377460/68a49733-f30e-44a1-a948-dc8cc95e1716)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
Now the button's overlay highlights are painted on the Ink widget. An Ink widget isn't needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget.
![translucent-graident-bg](https://github.com/flutter/flutter/assets/1377460/3b016e1f-200a-4d07-8111-e20d29f18014)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.red,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.orange.withOpacity(0.5),
Colors.yellow.withOpacity(0.5),
]),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
One can also decorate the background with an image. In this example, the button's background is an burlap texture image. The foreground color has been changed to black to make the button's text a little clearer relative to the mottled brown backround.
![burlap-bg](https://github.com/flutter/flutter/assets/1377460/f2f61ab1-10d9-43a4-bd63-beecdce33b45)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.black,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
return Ink(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(burlapUrl),
fit: BoxFit.cover,
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.
![gradient-flip](https://github.com/flutter/flutter/assets/1377460/c6c6fe26-ae47-445b-b82d-4605d9583bd8)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button's shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there's no `styleFrom` shorthand for this case.
![border-gradient-bg](https://github.com/flutter/flutter/assets/1377460/63cffcd3-0dcf-4eb1-aed5-d14adf1e57f6)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundColor: Colors.indigo,
backgroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final Color color1 = Colors.blue.withOpacity(0.5);
final Color color2 = Colors.orange.withOpacity(0.5);
return DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: switch (states.contains(MaterialState.hovered)) {
true => <Color>[color1, color2],
false => <Color>[color2, color1],
},
),
),
child: child,
);
},
).copyWith(
side: MaterialStateProperty.resolveWith<BorderSide?>((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return BorderSide(width: 3, color: Colors.yellow);
}
return null; // defer to the default
}),
),
child: Text('Text Button'),
)
```
Although all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton.
## `foregroundBuilder`
Creates a Widget that contains the button's child parameter. The returned widget is clipped by the button's [ButtonStyle.shape] inset by the button's [ButtonStyle.padding] and aligned by the button's [ButtonStyle.alignment].
The `foregroundBuilder` can be used to wrap the button's child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child.
This example adds a border that's just applied to the child. The border only appears when the button is hovered/pressed.
![border-fg](https://github.com/flutter/flutter/assets/1377460/687a3245-fe68-4983-a04e-5fcc77f8aa21)
```dart
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return DecoratedBox(
decoration: BoxDecoration(
border: states.contains(MaterialState.hovered)
? Border(bottom: BorderSide(color: colorScheme.primary))
: Border(), // essentially "no border"
),
child: child,
);
},
),
child: Text('Text Button'),
)
```
The foregroundBuilder can be used with `ShaderMask` to change the way the button's child is rendered. In this example the ShaderMask's gradient causes the button's child to fade out on top.
![shader_mask_fg](https://github.com/flutter/flutter/assets/1377460/54010f24-e65d-4551-ae58-712135df3d8d)
```dart
ElevatedButton(
onPressed: () { },
style: ElevatedButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final ColorScheme colorScheme = Theme.of(context).colorScheme;
return ShaderMask(
shaderCallback: (Rect bounds) {
return LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: <Color>[
colorScheme.primary,
colorScheme.primaryContainer,
],
).createShader(bounds);
},
blendMode: BlendMode.srcATop,
child: child,
);
},
),
child: const Text('Elevated Button'),
)
```
A commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn't use the child it's passed, even though we've provided the required TextButton child parameter.
![image-button](https://github.com/flutter/flutter/assets/1377460/f5b1a22f-43ce-4be3-8e70-06de4c958380)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
final String url = states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url;
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
In this example the button's default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:
![image-per-state](https://github.com/flutter/flutter/assets/1377460/7ab9da2f-f661-4374-b395-c2e0c7c4cf13)
```dart
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
overlayColor: Colors.transparent,
foregroundBuilder: (BuildContext context, Set<MaterialState> states, Widget? child) {
String url = states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url;
if (states.contains(MaterialState.pressed)) {
url = smiley2Url;
}
return AnimatedContainer(
width: 100,
height: 100,
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(url),
fit: BoxFit.contain,
),
),
);
},
),
child: Text('No Child'),
)
```
## Description
Fixes a paragraph in the `showDialog` docs that had strange placement due to evolution of the docs. Fixed some missing words too.
## Related Issues
- Fixes https://github.com/flutter/flutter/issues/142097
Refactors `ShaderTarget` to make it opaque as to whether it's using Impeller or SkSL and instead has it focus on the target platform it's generating for.
ImpellerC includes SkSL right now whether you ask for it or not.
The tester target also might need SkSL or Vulkan depending on whether `--enable-impeller` is passed.
Fixes https://github.com/flutter/flutter/issues/142480.
This fixes a crash occurring during hot reload when a `ViewAnchor` is used between a `ParentDataWidget` (like `Positioned`) and its closest `RenderObject` descendant. Prior to the fix, the `ParentDataWidget` was accidentally applying its parent data to the render object in the `ViewAnchor.view` slot, which crashed because that render object wasn't (and shouldn't be) setup to accept parent data (after all, it is in a different render tree). Instead, the parent data should only be applied to the render object in the `ViewAnchor.child` slot. Luckily, with `Element.renderObjectAttachingChild` we already have API in place to walk the widget tree such as that only `RenderObjectWidgets` from the same render tree are considered.
Fixes https://github.com/flutter/flutter/issues/142045
The intent of using `??=` was that if the tooltip is already scheduled for showing, rescheduling another show does nothing. But if the tooltip is already scheduled for dismissing, the `??=` won't cancel the dismiss timer and as a result the tooltip won't show. So the `??=` is now replaced by `=` to keep it consistent with the `_scheduleDismissTooltip` implementation.
While looking into resolving https://github.com/flutter/flutter/issues/117903, I found the massive test file `app_bar_test.dart` and found it unwieldy to work with. So before proposing a solution to #117903, which would touch many of these tests, I figured a clean up would be best first.
This splits up `app_bar_test.dart` with a new file `app_bar_sliver_test.dart`, and adds `app_bar_utils.dart` for shared test methods.
It basically moves all SliverAppBar tests into their own file, leaving just AppBar tests in the original file.
Children should be omitted from debugFillProperties (if they really need to be included they should be in debugDescribeChildren, but in general for widgets we don't bother including them since they are eventually included anyway).
toStrings should not contain newlines (or, ideally, should use Diagnosticable).
Also some minor tweaks to match grammar and style guide conventions.
This change uses `CapturedTheme`s to capture the themes from the context the selection handles were built in and wraps the handles with them so they can correctly inherit `Theme`s from local `Theme` widgets.
`CapturedTheme`s only captures `InheritedTheme`s, so this change also makes `_InheritedCupertinoTheme` an `InheritedTheme`. This is so we can capture themes declared under a `CupertinoTheme`, for example `primaryColor` is used as the selection handle color.
Fixes#74890
Fixes https://github.com/flutter/flutter/issues/142183
This fixes a bug in the SliverGeometry of SliverMainAxisGroup. The cacheExtent represents how many pixels the sliver has consumed in the SliverConstraints.remainingCacheExtent. Since it was not set, slivers that came after a SliverMainAxisGroup that filled the whole screen did not properly lay out their own children, in some cases making lazy sliver more eager than they should be.
This PR is adding a flag parameter to the `TextField` widget. This flag controls whether the TextField ignores pointers. The flag takes priority over other TextField behaviors such as enabled, so it can be useful when trying to have a disabled TextField that can be scrolled (behavior observed using TextArea on the web).
Adding a flag parameter to `TextField` helps with more customization and flexibility to the widget which can improve user experience. I am open to other ideas.
Fixes issue #140147
Before:
https://github.com/flutter/flutter/assets/66151079/293e5b4e-3126-4a00-824d-1530aeaa494b
After:
https://github.com/flutter/flutter/assets/66151079/08c1af09-3bf9-4b49-b684-dda4dd920503
Usage:
```dart
child: TextField(
ignorePointer: false,
enabled: false,
),
```
This PR is the fourth step in the journey to solve issue #136139 and make the entire Flutter repo more readable.
(previous pull requests: #139048, #139882, #141591)
This one is covering files in `packages/flutter/lib/src/foundation/` and `packages/flutter/lib/src/material/`.
The `material/` directory is pretty big though, so for now I just did the files that start with `a`, `b`, and `c`.
This PR increases Android's `minSdkVersion` to 21.
There are two changes in this PR aside from simply increasing the number
from 19 to 21 everywhere.
First, tests using `flutter_gallery` fail without updating the
lockfiles. The changes in the PR are the results of running
`dev/tools/bin/generate_gradle_lockfiles.dart` on that app.
Second, from
[here](https://developer.android.com/build/multidex#mdex-pre-l):
> if your minSdkVersion is 21 or higher, multidex is enabled by default
and you don't need the multidex library.
As a result, the `multidex` option everywhere is obsolete. This PR
removes all logic and tests related to that option that I could find.
`Google testing` and `customer_tests` pass on this PR, so it seems like
this won't be too breaking if it is at all. If needed I'll give this
some time to bake in the framework before landing the flutter/engine
PRs.
Context: https://github.com/flutter/flutter/issues/138117,
https://github.com/flutter/flutter/issues/141277, b/319373605
Reverts flutter/flutter#142339
In the original change one of the tests included the same view twice which resulted in a different failure than the expected one. The second commit contains the fix for this. I don't understand how this wasn't caught presubmit on CI.
It fixes assertion failure due to unstable state of children list during reordering in `RenderTwoDimensionalViewport.parentDataOf`. This changes the assertion to check debug orphan list and `keepAlive` bucket in addition to children list to determine whether child belongs to this render object or not.
- Fixes#141101
Reverts flutter/flutter#141484
Initiated by: eliasyishak
This change reverts the following previous change:
Original Description:
The existing `runApp` bootstraps the widget tree and renders the provided widget into the default view (which is currently the implicit View from `PlatformDispatcher.implicitView` and - in the future - may be a default-created window). Apps, that want more control over the View they are rendered in, need a new way to bootstrap the widget tree: `runWidget`. It does not make any assumptions about the View the provided widget is rendered into. Instead, it is up to the caller to include a View widget in the provided widget tree that specifies where content should be rendered. In the future, this may enable developers to create a custom window for their app instead of relying on the default-created one.
The existing `runApp` bootstraps the widget tree and renders the provided widget into the default view (which is currently the implicit View from `PlatformDispatcher.implicitView` and - in the future - may be a default-created window). Apps, that want more control over the View they are rendered in, need a new way to bootstrap the widget tree: `runWidget`. It does not make any assumptions about the View the provided widget is rendered into. Instead, it is up to the caller to include a View widget in the provided widget tree that specifies where content should be rendered. In the future, this may enable developers to create a custom window for their app instead of relying on the default-created one.
This PR fixes 2 small mistakes in `FlutterExtension`:
- all fields must be `public` in order to be used in Gradle Kotlin DSL the same as in Gradle Groovy DSL
- using `logger` instead of `project.logger` throws an error when executed
This PR re-adds a subset of changes from #141541 which broke the tree and has been reverted.
fix https://github.com/flutter/flutter/issues/121493
`SegmentedButton` uses `TextButton` for each segments. When we have `MaterialTapTargetSize.padded` for `TextButton`, we make sure the minimum tap target size is 48.0( this value can be adjusted by visual density), even tough the actual button size is smaller. When `SegmentedButton` paints segments by using `MultiChildRenderObjectWidget`, it also includes the tap target size so the button that it actually draws always has the same height as the height of the tap target size.
To fix it, this PR firstly calculate the actual height of a text button in `SegmentedButton` class, then we can get the height delta if there is. Then the the value of (Segmented button render box height - the delta) would be the actual button size that we should see.
For now, we are not able to customize the min, max, fixed size in [`SegmentedButton` style](https://api.flutter.dev/flutter/material/SegmentedButton/style.html). So the standard button height is always 40 and can only be customized by `style.visualDensity` and `style.tapTargetSize`; `SegmentedButton` only simulates the `TextButton` behavior when `TextButton`'s height is its default value.
![Screenshot 2024-01-25 at 11 45 42â¯AM](https://github.com/flutter/flutter/assets/36861262/7451fa96-6d45-4cd3-a894-ca71e776c8ef)
https://github.com/flutter/flutter/assets/36861262/15ca6034-e6e0-4cc6-8fe3-808b4bd6a920
It's now possible to natively compile a flutter app for windows-arm64. Cross-compilation is not yet implemented.
Uses arm64 artifacts now available for Dart/Flutter. Platform detection is based on Abi class, provided by Dart. Depending if Dart is an arm64 or x64 binary, the Abi is set accordingly. Initial bootstrap of dart artifacts (update_dart_sdk.ps1) is checking PROCESSOR_ARCHITECTURE environment variable, which is the way to detect host architecture on Windows.
This is available only for master channel (on other channels, it fallbacks to windows-x64).
On windows-x64, it produces an x64 app. On windows-arm64, it produces an arm64 app.