From c910d8d58d3a32b5316a538f121b0039f856cb29 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 06:09:09 -0400 Subject: [PATCH 01/83] Roll Engine from 586c90c1336f to 4228b72286ff (4 revisions) (#102290) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index f8a6975cadca4..84146a74fee68 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -586c90c1336f9bba303a4ce6147c212ffffdd5d8 +4228b72286ff76303ae632d6db5a047f86ee6e69 From 1065ca000b3ce16573d88c37d022d5d416699610 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 12:04:07 -0400 Subject: [PATCH 02/83] Roll Plugins from 6e18c7195678 to 5c3c1b8aac06 (7 revisions) (#102306) --- bin/internal/flutter_plugins.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/flutter_plugins.version b/bin/internal/flutter_plugins.version index 03bde7b570745..a083a54bc9ded 100644 --- a/bin/internal/flutter_plugins.version +++ b/bin/internal/flutter_plugins.version @@ -1 +1 @@ -6e18c7195678f5f2ff12e79a5fe738280a66fe26 +5c3c1b8aac065aa1988f114d0c66ecec758e9cbb From a9eaee55eaa4d6ad5e3ac6f584ef169435173ece Mon Sep 17 00:00:00 2001 From: yusuf-goog <91688203+yusuf-goog@users.noreply.github.com> Date: Thu, 21 Apr 2022 09:35:24 -0700 Subject: [PATCH 03/83] Switch ci.yaml Linux builders to Debian. (#102253) In preparation for upgrading linux VMs to Ubuntu, specify builders to use 'os: Debian' instead of 'os: Linux'. There should be no functional changes to current builders with this change. Bug:102252 --- .ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci.yaml b/.ci.yaml index dcf183eff6baa..d54143a5d21f2 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -26,7 +26,7 @@ platform_properties: [ {"dependency": "curl"} ] - os: Linux + os: Debian device_type: none linux_android: properties: From e4edcbceb388c79fc2002a1b84159dab5f41c5e5 Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Thu, 21 Apr 2022 20:39:09 +0300 Subject: [PATCH 04/83] Improve 'NestedScrollView and internal scrolling' test to account for all the inner children layers (#102309) --- .../test/widgets/nested_scroll_view_test.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/flutter/test/widgets/nested_scroll_view_test.dart b/packages/flutter/test/widgets/nested_scroll_view_test.dart index 212e86428e3af..62a257e38d59a 100644 --- a/packages/flutter/test/widgets/nested_scroll_view_test.dart +++ b/packages/flutter/test/widgets/nested_scroll_view_test.dart @@ -599,9 +599,15 @@ void main() { return child; } if (child is ContainerLayer) { - final PhysicalModelLayer? candidate = _dfsFindPhysicalLayer(child); - if (candidate != null) { - return candidate; + Layer? innerChild = child.firstChild; + while (innerChild != null) { + if (innerChild is ContainerLayer) { + final PhysicalModelLayer? candidate = _dfsFindPhysicalLayer(innerChild); + if (candidate != null) { + return candidate; + } + } + innerChild = innerChild.nextSibling; } } child = child.nextSibling; From 49e043a2c006ef334682b2feb6e9b9f423e3e2db Mon Sep 17 00:00:00 2001 From: Flutter GitHub Bot Date: Thu, 21 Apr 2022 10:49:09 -0700 Subject: [PATCH 05/83] Marks Linux_android gradient_dynamic_perf__e2e_summary to be unflaky (#101832) --- .ci.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.ci.yaml b/.ci.yaml index d54143a5d21f2..ede503f7e59a8 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -2376,7 +2376,6 @@ targets: scheduler: luci - name: Linux_android gradient_dynamic_perf__e2e_summary - bringup: true recipe: devicelab/devicelab_drone presubmit: false timeout: 60 From d3ce6d6eb1788cd274f6b1a1e333e31dcc512a8e Mon Sep 17 00:00:00 2001 From: Flutter GitHub Bot Date: Thu, 21 Apr 2022 11:09:10 -0700 Subject: [PATCH 06/83] Marks Mac_ios cubic_bezier_perf_ios_sksl_warmup__timeline_summary to be flaky (#102231) --- .ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci.yaml b/.ci.yaml index ede503f7e59a8..13fdac329be53 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -3276,6 +3276,7 @@ targets: scheduler: luci - name: Mac_ios cubic_bezier_perf_ios_sksl_warmup__timeline_summary + bringup: true # Flaky https://github.com/flutter/flutter/issues/102230 recipe: devicelab/devicelab_drone presubmit: false timeout: 60 From 73b4a7cb9ed73e7b92fa02cc46813e76b0e62c6e Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 15:04:07 -0400 Subject: [PATCH 07/83] Roll Engine from 4228b72286ff to 701e5e8f44ac (4 revisions) (#102316) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 84146a74fee68..6b14862e5a17e 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -4228b72286ff76303ae632d6db5a047f86ee6e69 +701e5e8f44acea0c556adda5c84d1b877096c0b4 From ec6481bed84613ada10d52a39fd123ba88280952 Mon Sep 17 00:00:00 2001 From: drewroengoogle <102626803+drewroengoogle@users.noreply.github.com> Date: Thu, 21 Apr 2022 19:12:38 +0000 Subject: [PATCH 08/83] Change dependency from ios_signing to apple_signing (#102259) * Change dependency name to apple_signing for a better understanding of it's use * Updated Mac_ios test to run if .ci.yaml is updated --- .ci.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci.yaml b/.ci.yaml index 13fdac329be53..eaee1eb4d8915 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -125,7 +125,7 @@ platform_properties: [ {"dependency": "xcode"}, {"dependency": "gems"}, - {"dependency": "ios_signing"} + {"dependency": "apple_signing"} ] os: Mac-12 cpu: x86 @@ -3365,6 +3365,7 @@ targets: task_name: hot_mode_dev_cycle_macos_target__benchmark runIf: - dev/** + - .ci.yaml scheduler: luci - name: Mac_ios integration_test_test_ios From 2ebc7bee9ca1ef992d2111902b4134d5896741ad Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Thu, 21 Apr 2022 12:14:09 -0700 Subject: [PATCH 09/83] Adds tooltip to semantics node (#87684) --- .../flutter/lib/src/material/tooltip.dart | 2 +- .../flutter/lib/src/rendering/proxy_box.dart | 16 ++++++ .../flutter/lib/src/semantics/semantics.dart | 51 ++++++++++++++++++- packages/flutter/lib/src/widgets/basic.dart | 7 ++- .../lib/src/widgets/semantics_debugger.dart | 20 +++++--- .../test/material/back_button_test.dart | 2 +- .../material/calendar_date_picker_test.dart | 4 +- packages/flutter/test/material/chip_test.dart | 2 +- .../test/material/date_picker_test.dart | 4 +- .../material/floating_action_button_test.dart | 4 +- .../flutter/test/material/search_test.dart | 2 +- .../flutter/test/material/tooltip_test.dart | 5 +- .../test/material/tooltip_theme_test.dart | 6 ++- .../test/semantics/semantics_test.dart | 2 + .../test/semantics/semantics_update_test.dart | 3 +- .../flutter/test/widgets/semantics_test.dart | 28 ++++++++++ .../test/widgets/semantics_tester.dart | 10 ++++ .../flutter_test/lib/src/accessibility.dart | 2 +- packages/flutter_test/lib/src/matchers.dart | 8 +++ packages/flutter_test/test/matchers_test.dart | 1 + 20 files changed, 154 insertions(+), 25 deletions(-) diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart index 7b49f81eb15e9..fd70a6b5eec2d 100644 --- a/packages/flutter/lib/src/material/tooltip.dart +++ b/packages/flutter/lib/src/material/tooltip.dart @@ -698,7 +698,7 @@ class TooltipState extends State with SingleTickerProviderStateMixin { _enableFeedback = widget.enableFeedback ?? tooltipTheme.enableFeedback ?? _defaultEnableFeedback; Widget result = Semantics( - label: _excludeFromSemantics + tooltip: _excludeFromSemantics ? null : _tooltipMessage, child: widget.child, diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 7d204b807671b..32fb58e9433ba 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -3859,6 +3859,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox { AttributedString? attributedIncreasedValue, AttributedString? attributedDecreasedValue, AttributedString? attributedHint, + String? tooltip, SemanticsHintOverrides? hintOverrides, TextDirection? textDirection, SemanticsSortKey? sortKey, @@ -3917,6 +3918,7 @@ class RenderSemanticsAnnotations extends RenderProxyBox { _attributedIncreasedValue = attributedIncreasedValue, _attributedDecreasedValue = attributedDecreasedValue, _attributedHint = attributedHint, + _tooltip = tooltip, _hintOverrides = hintOverrides, _textDirection = textDirection, _sortKey = sortKey, @@ -4311,6 +4313,18 @@ class RenderSemanticsAnnotations extends RenderProxyBox { markNeedsSemanticsUpdate(); } + /// If non-null, sets the [SemanticsNode.tooltip] semantic to the given value. + /// + /// The reading direction is given by [textDirection]. + String? get tooltip => _tooltip; + String? _tooltip; + set tooltip(String? value) { + if (_tooltip == value) + return; + _tooltip = value; + markNeedsSemanticsUpdate(); + } + /// If non-null, sets the [SemanticsConfiguration.hintOverrides] to the given value. SemanticsHintOverrides? get hintOverrides => _hintOverrides; SemanticsHintOverrides? _hintOverrides; @@ -4843,6 +4857,8 @@ class RenderSemanticsAnnotations extends RenderProxyBox { config.attributedDecreasedValue = attributedDecreasedValue!; if (attributedHint != null) config.attributedHint = attributedHint!; + if (tooltip != null) + config.tooltip = tooltip!; if (hintOverrides != null && hintOverrides!.isNotEmpty) config.hintOverrides = hintOverrides; if (scopesRoute != null) diff --git a/packages/flutter/lib/src/semantics/semantics.dart b/packages/flutter/lib/src/semantics/semantics.dart index 851cd5e8819f9..a7373e589d195 100644 --- a/packages/flutter/lib/src/semantics/semantics.dart +++ b/packages/flutter/lib/src/semantics/semantics.dart @@ -316,6 +316,7 @@ class SemanticsData with Diagnosticable { required this.attributedIncreasedValue, required this.attributedDecreasedValue, required this.attributedHint, + required this.tooltip, required this.textDirection, required this.rect, required this.elevation, @@ -339,6 +340,7 @@ class SemanticsData with Diagnosticable { assert(attributedDecreasedValue != null), assert(attributedIncreasedValue != null), assert(attributedHint != null), + assert(tooltip == '' || textDirection != null, 'A SemanticsData object with tooltip "$tooltip" had a null textDirection.'), assert(attributedLabel.string == '' || textDirection != null, 'A SemanticsData object with label "${attributedLabel.string}" had a null textDirection.'), assert(attributedValue.string == '' || textDirection != null, 'A SemanticsData object with value "${attributedValue.string}" had a null textDirection.'), assert(attributedDecreasedValue.string == '' || textDirection != null, 'A SemanticsData object with decreasedValue "${attributedDecreasedValue.string}" had a null textDirection.'), @@ -429,6 +431,11 @@ class SemanticsData with Diagnosticable { /// See also [hint], which exposes just the raw text. final AttributedString attributedHint; + /// A textual description of the widget's tooltip. + /// + /// The reading direction is given by [textDirection]. + final String tooltip; + /// The reading direction for the text in [label], [value], /// [increasedValue], [decreasedValue], and [hint]. final TextDirection? textDirection; @@ -587,6 +594,7 @@ class SemanticsData with Diagnosticable { properties.add(AttributedStringProperty('increasedValue', attributedIncreasedValue)); properties.add(AttributedStringProperty('decreasedValue', attributedDecreasedValue)); properties.add(AttributedStringProperty('hint', attributedHint)); + properties.add(StringProperty('tooltip', tooltip, defaultValue: '')); properties.add(EnumProperty('textDirection', textDirection, defaultValue: null)); if (textSelection?.isValid ?? false) properties.add(MessageProperty('textSelection', '[${textSelection!.start}, ${textSelection!.end}]')); @@ -610,6 +618,7 @@ class SemanticsData with Diagnosticable { && other.attributedIncreasedValue == attributedIncreasedValue && other.attributedDecreasedValue == attributedDecreasedValue && other.attributedHint == attributedHint + && other.tooltip == tooltip && other.textDirection == textDirection && other.rect == rect && setEquals(other.tags, tags) @@ -637,6 +646,7 @@ class SemanticsData with Diagnosticable { attributedIncreasedValue, attributedDecreasedValue, attributedHint, + tooltip, textDirection, rect, tags, @@ -648,8 +658,8 @@ class SemanticsData with Diagnosticable { scrollExtentMin, platformViewId, maxValueLength, - currentValueLength, Object.hash( + currentValueLength, transform, elevation, thickness, @@ -785,6 +795,7 @@ class SemanticsProperties extends DiagnosticableTree { this.decreasedValue, this.attributedDecreasedValue, this.hint, + this.tooltip, this.attributedHint, this.hintOverrides, this.textDirection, @@ -1178,6 +1189,16 @@ class SemanticsProperties extends DiagnosticableTree { /// * [hint] for a plain string version of this property. final AttributedString? attributedHint; + /// Provides a textual description of the widget's tooltip. + /// + /// In Android, this property sets the `AccessibilityNodeInfo.setTooltipText`. + /// In iOS, this property is appended to the end of the + /// `UIAccessibilityElement.accessibilityLabel`. + /// + /// If a [tooltip] is provided, there must either by an ambient + /// [Directionality] or an explicit [textDirection] should be provided. + final String? tooltip; + /// Provides hint values which override the default hints on supported /// platforms. /// @@ -1469,6 +1490,7 @@ class SemanticsProperties extends DiagnosticableTree { properties.add(AttributedStringProperty('attributedDecreasedValue', attributedDecreasedValue, defaultValue: null)); properties.add(StringProperty('hint', hint, defaultValue: null)); properties.add(AttributedStringProperty('attributedHint', attributedHint, defaultValue: null)); + properties.add(StringProperty('tooltip', tooltip)); properties.add(EnumProperty('textDirection', textDirection, defaultValue: null)); properties.add(DiagnosticsProperty('sortKey', sortKey, defaultValue: null)); properties.add(DiagnosticsProperty('hintOverrides', hintOverrides, defaultValue: null)); @@ -1898,6 +1920,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { || _attributedValue != config.attributedValue || _attributedIncreasedValue != config.attributedIncreasedValue || _attributedDecreasedValue != config.attributedDecreasedValue + || _tooltip != config.tooltip || _flags != config._flags || _textDirection != config.textDirection || _sortKey != config._sortKey @@ -2027,6 +2050,12 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { AttributedString get attributedHint => _attributedHint; AttributedString _attributedHint = _kEmptyConfig.attributedHint; + /// A textual description of the widget's tooltip. + /// + /// The reading direction is given by [textDirection]. + String get tooltip => _tooltip; + String _tooltip = _kEmptyConfig.tooltip; + /// The elevation along the z-axis at which the [rect] of this [SemanticsNode] /// is located above its parent. /// @@ -2235,6 +2264,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { _attributedIncreasedValue = config.attributedIncreasedValue; _attributedDecreasedValue = config.attributedDecreasedValue; _attributedHint = config.attributedHint; + _tooltip = config.tooltip; _hintOverrides = config.hintOverrides; _elevation = config.elevation; _thickness = config.thickness; @@ -2282,6 +2312,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { AttributedString attributedIncreasedValue = _attributedIncreasedValue; AttributedString attributedDecreasedValue = _attributedDecreasedValue; AttributedString attributedHint = _attributedHint; + String tooltip = _tooltip; TextDirection? textDirection = _textDirection; Set? mergedTags = tags == null ? null : Set.of(tags!); TextSelection? textSelection = _textSelection; @@ -2336,6 +2367,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { attributedIncreasedValue = node._attributedIncreasedValue; if (attributedDecreasedValue == null || attributedDecreasedValue.string == '') attributedDecreasedValue = node._attributedDecreasedValue; + if (tooltip == '') + tooltip = node._tooltip; if (node.tags != null) { mergedTags ??= {}; mergedTags!.addAll(node.tags!); @@ -2385,6 +2418,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { attributedIncreasedValue: attributedIncreasedValue, attributedDecreasedValue: attributedDecreasedValue, attributedHint: attributedHint, + tooltip: tooltip, textDirection: textDirection, rect: rect, transform: transform, @@ -2457,6 +2491,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { decreasedValueAttributes: data.attributedDecreasedValue.attributes, hint: data.attributedHint.string, hintAttributes: data.attributedHint.attributes, + tooltip: data.tooltip, textDirection: data.textDirection, textSelectionBase: data.textSelection != null ? data.textSelection!.baseOffset : -1, textSelectionExtent: data.textSelection != null ? data.textSelection!.extentOffset : -1, @@ -2595,6 +2630,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { properties.add(AttributedStringProperty('increasedValue', _attributedIncreasedValue)); properties.add(AttributedStringProperty('decreasedValue', _attributedDecreasedValue)); properties.add(AttributedStringProperty('hint', _attributedHint)); + properties.add(StringProperty('tooltip', _tooltip, defaultValue: '')); properties.add(EnumProperty('textDirection', _textDirection, defaultValue: null)); properties.add(DiagnosticsProperty('sortKey', sortKey, defaultValue: null)); if (_textSelection?.isValid ?? false) @@ -3955,6 +3991,16 @@ class SemanticsConfiguration { _hasBeenAnnotated = true; } + /// A textual description of the widget's tooltip. + /// + /// The reading direction is given by [textDirection]. + String get tooltip => _tooltip; + String _tooltip = ''; + set tooltip(String tooltip) { + _tooltip = tooltip; + _hasBeenAnnotated = true; + } + /// Provides hint values which override the default hints on supported /// platforms. SemanticsHintOverrides? get hintOverrides => _hintOverrides; @@ -4420,6 +4466,8 @@ class SemanticsConfiguration { otherAttributedString: child._attributedHint, otherTextDirection: child.textDirection, ); + if (_tooltip == '') + _tooltip = child._tooltip; _thickness = math.max(_thickness, child._thickness + child._elevation); @@ -4442,6 +4490,7 @@ class SemanticsConfiguration { .._attributedDecreasedValue = _attributedDecreasedValue .._attributedHint = _attributedHint .._hintOverrides = _hintOverrides + .._tooltip = _tooltip .._elevation = _elevation .._thickness = _thickness .._flags = _flags diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 417f09f2a18ea..f565db3598e2e 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -6695,6 +6695,7 @@ class Semantics extends SingleChildRenderObjectWidget { AttributedString? attributedDecreasedValue, String? hint, AttributedString? attributedHint, + String? tooltip, String? onTapHint, String? onLongPressHint, TextDirection? textDirection, @@ -6759,6 +6760,7 @@ class Semantics extends SingleChildRenderObjectWidget { attributedDecreasedValue: attributedDecreasedValue, hint: hint, attributedHint: attributedHint, + tooltip: tooltip, textDirection: textDirection, sortKey: sortKey, tagForChildren: tagForChildren, @@ -6901,6 +6903,7 @@ class Semantics extends SingleChildRenderObjectWidget { attributedIncreasedValue: _effectiveAttributedIncreasedValue, attributedDecreasedValue: _effectiveAttributedDecreasedValue, attributedHint: _effectiveAttributedHint, + tooltip: properties.tooltip, hintOverrides: properties.hintOverrides, textDirection: _getTextDirection(context), sortKey: properties.sortKey, @@ -6936,7 +6939,8 @@ class Semantics extends SingleChildRenderObjectWidget { final bool containsText = properties.attributedLabel != null || properties.label != null || properties.value != null || - properties.hint != null; + properties.hint != null || + properties.tooltip != null; if (!containsText) return null; @@ -6977,6 +6981,7 @@ class Semantics extends SingleChildRenderObjectWidget { ..attributedIncreasedValue = _effectiveAttributedIncreasedValue ..attributedDecreasedValue = _effectiveAttributedDecreasedValue ..attributedHint = _effectiveAttributedHint + ..tooltip = properties.tooltip ..hintOverrides = properties.hintOverrides ..namesRoute = properties.namesRoute ..textDirection = _getTextDirection(context) diff --git a/packages/flutter/lib/src/widgets/semantics_debugger.dart b/packages/flutter/lib/src/widgets/semantics_debugger.dart index b7796248921dd..062659186cd3e 100644 --- a/packages/flutter/lib/src/widgets/semantics_debugger.dart +++ b/packages/flutter/lib/src/widgets/semantics_debugger.dart @@ -281,27 +281,33 @@ class _SemanticsDebuggerPainter extends CustomPainter { assert(data.attributedLabel != null); final String message; - if (data.attributedLabel.string.isEmpty) { + final String tooltipAndLabel = [ + if (data.tooltip.isNotEmpty) + data.tooltip, + if (data.attributedLabel.string.isNotEmpty) + data.attributedLabel.string, + ].join('\n'); + if (tooltipAndLabel.isEmpty) { message = annotations.join('; '); } else { - final String label; + final String effectivelabel; if (data.textDirection == null) { - label = '${Unicode.FSI}${data.attributedLabel.string}${Unicode.PDI}'; + effectivelabel = '${Unicode.FSI}$tooltipAndLabel${Unicode.PDI}'; annotations.insert(0, 'MISSING TEXT DIRECTION'); } else { switch (data.textDirection!) { case TextDirection.rtl: - label = '${Unicode.RLI}${data.attributedLabel.string}${Unicode.PDF}'; + effectivelabel = '${Unicode.RLI}$tooltipAndLabel${Unicode.PDF}'; break; case TextDirection.ltr: - label = data.attributedLabel.string; + effectivelabel = tooltipAndLabel; break; } } if (annotations.isEmpty) { - message = label; + message = effectivelabel; } else { - message = '$label (${annotations.join('; ')})'; + message = '$effectivelabel (${annotations.join('; ')})'; } } diff --git a/packages/flutter/test/material/back_button_test.dart b/packages/flutter/test/material/back_button_test.dart index eb4db41a6bab1..d4ff9a92ffab1 100644 --- a/packages/flutter/test/material/back_button_test.dart +++ b/packages/flutter/test/material/back_button_test.dart @@ -154,7 +154,7 @@ void main() { await tester.pumpAndSettle(); expect(tester.getSemantics(find.byType(BackButton)), matchesSemantics( - label: 'Back', + tooltip: 'Back', isButton: true, hasEnabledState: true, isEnabled: true, diff --git a/packages/flutter/test/material/calendar_date_picker_test.dart b/packages/flutter/test/material/calendar_date_picker_test.dart index bf1add0ef3b3b..f21300a043847 100644 --- a/packages/flutter/test/material/calendar_date_picker_test.dart +++ b/packages/flutter/test/material/calendar_date_picker_test.dart @@ -649,7 +649,7 @@ void main() { // Prev/Next month buttons. expect(tester.getSemantics(previousMonthIcon), matchesSemantics( - label: 'Previous month', + tooltip: 'Previous month', isButton: true, hasTapAction: true, isEnabled: true, @@ -657,7 +657,7 @@ void main() { isFocusable: true, )); expect(tester.getSemantics(nextMonthIcon), matchesSemantics( - label: 'Next month', + tooltip: 'Next month', isButton: true, hasTapAction: true, isEnabled: true, diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 80cb5ccec09fe..ea4c7947a20a4 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -1964,7 +1964,7 @@ void main() { ], children: [ TestSemantics( - label: 'Delete', + tooltip: 'Delete', actions: [SemanticsAction.tap], textDirection: TextDirection.ltr, flags: [ diff --git a/packages/flutter/test/material/date_picker_test.dart b/packages/flutter/test/material/date_picker_test.dart index 45ab8b05ccb97..525148fb82cf7 100644 --- a/packages/flutter/test/material/date_picker_test.dart +++ b/packages/flutter/test/material/date_picker_test.dart @@ -817,7 +817,7 @@ void main() { // Input mode toggle button expect(tester.getSemantics(switchToInputIcon), matchesSemantics( - label: 'Switch to input', + tooltip: 'Switch to input', isButton: true, hasTapAction: true, isEnabled: true, @@ -860,7 +860,7 @@ void main() { // Input mode toggle button expect(tester.getSemantics(switchToCalendarIcon), matchesSemantics( - label: 'Switch to calendar', + tooltip: 'Switch to calendar', isButton: true, hasTapAction: true, isEnabled: true, diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart index 3b41bc336d01e..987e8a9905005 100644 --- a/packages/flutter/test/material/floating_action_button_test.dart +++ b/packages/flutter/test/material/floating_action_button_test.dart @@ -670,7 +670,7 @@ void main() { semantics.dispose(); }); - testWidgets('Tooltip is used as semantics label', (WidgetTester tester) async { + testWidgets('Tooltip is used as semantics tooltip', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); await tester.pumpWidget( @@ -697,7 +697,7 @@ void main() { ], children: [ TestSemantics( - label: 'Add Photo', + tooltip: 'Add Photo', actions: [ SemanticsAction.tap, ], diff --git a/packages/flutter/test/material/search_test.dart b/packages/flutter/test/material/search_test.dart index 9d7ccb30daca4..9a6c24e1529d8 100644 --- a/packages/flutter/test/material/search_test.dart +++ b/packages/flutter/test/material/search_test.dart @@ -616,7 +616,7 @@ void main() { SemanticsFlag.isFocusable, ], actions: [SemanticsAction.tap], - label: 'Back', + tooltip: 'Back', textDirection: TextDirection.ltr, ), TestSemantics( diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart index 842cf8b0c112c..2d25385bc6dc9 100644 --- a/packages/flutter/test/material/tooltip_test.dart +++ b/packages/flutter/test/material/tooltip_test.dart @@ -1263,7 +1263,7 @@ void main() { children: [ TestSemantics.rootChild( id: 1, - label: 'TIP', + tooltip: 'TIP', textDirection: TextDirection.ltr, ), ], @@ -1462,7 +1462,8 @@ void main() { flags: [SemanticsFlag.scopesRoute], children: [ TestSemantics( - label: 'Foo\nBar', + tooltip: 'Foo', + label: 'Bar', textDirection: TextDirection.ltr, ), ], diff --git a/packages/flutter/test/material/tooltip_theme_test.dart b/packages/flutter/test/material/tooltip_theme_test.dart index 999c335115b6a..2fedbf3a5e6f1 100644 --- a/packages/flutter/test/material/tooltip_theme_test.dart +++ b/packages/flutter/test/material/tooltip_theme_test.dart @@ -1066,7 +1066,8 @@ void main() { flags: [SemanticsFlag.scopesRoute], children: [ TestSemantics( - label: 'Foo\nBar', + tooltip: 'Foo', + label: 'Bar', textDirection: TextDirection.ltr, ), ], @@ -1108,7 +1109,8 @@ void main() { flags: [SemanticsFlag.scopesRoute], children: [ TestSemantics( - label: 'Foo\nBar', + tooltip: 'Foo', + label: 'Bar', textDirection: TextDirection.ltr, ), ], diff --git a/packages/flutter/test/semantics/semantics_test.dart b/packages/flutter/test/semantics/semantics_test.dart index ebc240b3436d4..4f2be0e967e11 100644 --- a/packages/flutter/test/semantics/semantics_test.dart +++ b/packages/flutter/test/semantics/semantics_test.dart @@ -561,6 +561,7 @@ void main() { ' increasedValue: ""\n' ' decreasedValue: ""\n' ' hint: ""\n' + ' tooltip: ""\n' ' textDirection: null\n' ' sortKey: null\n' ' platformViewId: null\n' @@ -659,6 +660,7 @@ void main() { ' increasedValue: ""\n' ' decreasedValue: ""\n' ' hint: ""\n' + ' tooltip: ""\n' ' textDirection: null\n' ' sortKey: null\n' ' platformViewId: null\n' diff --git a/packages/flutter/test/semantics/semantics_update_test.dart b/packages/flutter/test/semantics/semantics_update_test.dart index 78b0926dee053..0026e50674306 100644 --- a/packages/flutter/test/semantics/semantics_update_test.dart +++ b/packages/flutter/test/semantics/semantics_update_test.dart @@ -158,7 +158,8 @@ void main() { 'properties: SemanticsProperties, ' 'attributedLabel: "label" [SpellOutStringAttribute(TextRange(start: 0, end: 5))], ' 'attributedValue: "value" [LocaleStringAttribute(TextRange(start: 0, end: 5), en-MX)], ' - 'attributedHint: "hint" [SpellOutStringAttribute(TextRange(start: 1, end: 2))]' // ignore: missing_whitespace_between_adjacent_strings + 'attributedHint: "hint" [SpellOutStringAttribute(TextRange(start: 1, end: 2))], ' + 'tooltip: null'// ignore: missing_whitespace_between_adjacent_strings ')', ); diff --git a/packages/flutter/test/widgets/semantics_test.dart b/packages/flutter/test/widgets/semantics_test.dart index d8e6fc636d9da..5586aa83860a6 100644 --- a/packages/flutter/test/widgets/semantics_test.dart +++ b/packages/flutter/test/widgets/semantics_test.dart @@ -61,6 +61,34 @@ void main() { semantics.dispose(); }, semanticsEnabled: false); + testWidgets('Semantics tooltip', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + + final TestSemantics expectedSemantics = TestSemantics.root( + children: [ + TestSemantics.rootChild( + tooltip: 'test1', + textDirection: TextDirection.ltr, + ), + ], + ); + + await tester.pumpWidget( + Semantics( + tooltip: 'test1', + textDirection: TextDirection.ltr, + ), + ); + + expect(semantics, hasSemantics( + expectedSemantics, + ignoreTransform: true, + ignoreRect: true, + ignoreId: true, + )); + semantics.dispose(); + }); + testWidgets('Detach and reattach assert', (WidgetTester tester) async { final SemanticsTester semantics = SemanticsTester(tester); final GlobalKey key = GlobalKey(); diff --git a/packages/flutter/test/widgets/semantics_tester.dart b/packages/flutter/test/widgets/semantics_tester.dart index 3c4cc90ac8112..e15332dfc7d31 100644 --- a/packages/flutter/test/widgets/semantics_tester.dart +++ b/packages/flutter/test/widgets/semantics_tester.dart @@ -39,6 +39,7 @@ class TestSemantics { this.actions = 0, this.label = '', this.value = '', + this.tooltip = '', this.increasedValue = '', this.decreasedValue = '', this.hint = '', @@ -72,6 +73,7 @@ class TestSemantics { this.increasedValue = '', this.decreasedValue = '', this.hint = '', + this.tooltip = '', this.textDirection, this.transform, this.textSelection, @@ -110,6 +112,7 @@ class TestSemantics { this.label = '', this.hint = '', this.value = '', + this.tooltip = '', this.increasedValue = '', this.decreasedValue = '', this.textDirection, @@ -176,6 +179,9 @@ class TestSemantics { /// performed on this node. final String hint; + /// A textual tooltip of this node. + final String tooltip; + /// The reading direction of the [label]. /// /// Even if this is not set, the [hasSemantics] matcher will verify that if a @@ -292,6 +298,8 @@ class TestSemantics { return fail('expected node id $id to have decreasedValue "$decreasedValue" but found value "${nodeData.decreasedValue}".'); if (hint != nodeData.hint) return fail('expected node id $id to have hint "$hint" but found hint "${nodeData.hint}".'); + if (tooltip != nodeData.tooltip) + return fail('expected node id $id to have tooltip "$tooltip" but found hint "${nodeData.tooltip}".'); if (textDirection != null && textDirection != nodeData.textDirection) return fail('expected node id $id to have textDirection "$textDirection" but found "${nodeData.textDirection}".'); if ((nodeData.label != '' || nodeData.value != '' || nodeData.hint != '' || node.increasedValue != '' || node.decreasedValue != '') && nodeData.textDirection == null) @@ -365,6 +373,8 @@ class TestSemantics { buf.writeln("$indent decreasedValue: '$decreasedValue',"); if (hint != null && hint != '') buf.writeln("$indent hint: '$hint',"); + if (tooltip != null && tooltip != '') + buf.writeln("$indent tooltip: '$tooltip',"); if (textDirection != null) buf.writeln('$indent textDirection: $textDirection,'); if (textSelection?.isValid ?? false) diff --git a/packages/flutter_test/lib/src/accessibility.dart b/packages/flutter_test/lib/src/accessibility.dart index 5bb9262a91745..f23c589b81de5 100644 --- a/packages/flutter_test/lib/src/accessibility.dart +++ b/packages/flutter_test/lib/src/accessibility.dart @@ -228,7 +228,7 @@ class LabeledTapTargetGuideline extends AccessibilityGuideline { !data.hasAction(ui.SemanticsAction.tap)) { return result; } - if (data.label == null || data.label.isEmpty) { + if ((data.label == null || data.label.isEmpty) && (data.tooltip == null || data.tooltip.isEmpty)) { result += Evaluation.fail( '$node: expected tappable node to have semantic label, ' 'but none was found.\n', diff --git a/packages/flutter_test/lib/src/matchers.dart b/packages/flutter_test/lib/src/matchers.dart index bad708fe4f7b8..338e5bcaf1860 100644 --- a/packages/flutter_test/lib/src/matchers.dart +++ b/packages/flutter_test/lib/src/matchers.dart @@ -494,6 +494,7 @@ Matcher matchesSemantics({ String? increasedValue, AttributedString? attributedIncreasedValue, String? decreasedValue, + String? tooltip, AttributedString? attributedDecreasedValue, TextDirection? textDirection, Rect? rect, @@ -625,6 +626,7 @@ Matcher matchesSemantics({ value: value, attributedValue: attributedValue, increasedValue: increasedValue, + tooltip: tooltip, attributedIncreasedValue: attributedIncreasedValue, decreasedValue: decreasedValue, attributedDecreasedValue: attributedDecreasedValue, @@ -1783,6 +1785,7 @@ class _MatchesSemanticsData extends Matcher { this.attributedIncreasedValue, this.decreasedValue, this.attributedDecreasedValue, + this.tooltip, this.flags, this.actions, this.textDirection, @@ -1808,6 +1811,7 @@ class _MatchesSemanticsData extends Matcher { final AttributedString? attributedIncreasedValue; final String? decreasedValue; final AttributedString? attributedDecreasedValue; + final String? tooltip; final SemanticsHintOverrides? hintOverrides; final List? actions; final List? customActions; @@ -1845,6 +1849,8 @@ class _MatchesSemanticsData extends Matcher { description.add(' with decreasedValue: $decreasedValue '); if (attributedDecreasedValue != null) description.add(' with attributedDecreasedValue: $attributedDecreasedValue'); + if (tooltip != null) + description.add(' with tooltip: $tooltip'); if (actions != null) description.add(' with actions: ').addDescriptionOf(actions); if (flags != null) @@ -1942,6 +1948,8 @@ class _MatchesSemanticsData extends Matcher { return failWithDescription( matchState, 'attributedDecreasedValue was: ${data.attributedDecreasedValue}'); } + if (tooltip != null && tooltip != data.tooltip) + return failWithDescription(matchState, 'tooltip was: ${data.tooltip}'); if (textDirection != null && textDirection != data.textDirection) return failWithDescription(matchState, 'textDirection was: $textDirection'); if (rect != null && rect != data.rect) diff --git a/packages/flutter_test/test/matchers_test.dart b/packages/flutter_test/test/matchers_test.dart index 48a9d781035b6..4632aba6fc4ea 100644 --- a/packages/flutter_test/test/matchers_test.dart +++ b/packages/flutter_test/test/matchers_test.dart @@ -566,6 +566,7 @@ void main() { attributedValue: AttributedString('c'), attributedDecreasedValue: AttributedString('d'), attributedHint: AttributedString('e'), + tooltip: 'f', textDirection: TextDirection.ltr, rect: const Rect.fromLTRB(0.0, 0.0, 10.0, 10.0), elevation: 3.0, From ab889ab976fbe69ff9d54afbf1ba41a696c32b2c Mon Sep 17 00:00:00 2001 From: Abhishek Ghaskata Date: Fri, 22 Apr 2022 01:04:07 +0530 Subject: [PATCH 10/83] macos support for image_list (#84899) --- examples/image_list/macos/.gitignore | 6 + .../macos/Flutter/Flutter-Debug.xcconfig | 1 + .../macos/Flutter/Flutter-Release.xcconfig | 1 + .../macos/Runner.xcodeproj/project.pbxproj | 572 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 89 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../image_list/macos/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 68 +++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 46993 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 3276 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 1429 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 5933 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1243 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 14800 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 1874 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 339 +++++++++++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + examples/image_list/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 19 + .../macos/Runner/Release.entitlements | 8 + 26 files changed, 1214 insertions(+) create mode 100644 examples/image_list/macos/.gitignore create mode 100644 examples/image_list/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 examples/image_list/macos/Flutter/Flutter-Release.xcconfig create mode 100644 examples/image_list/macos/Runner.xcodeproj/project.pbxproj create mode 100644 examples/image_list/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/image_list/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 examples/image_list/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 examples/image_list/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 examples/image_list/macos/Runner/AppDelegate.swift create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 examples/image_list/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 examples/image_list/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 examples/image_list/macos/Runner/Configs/Debug.xcconfig create mode 100644 examples/image_list/macos/Runner/Configs/Release.xcconfig create mode 100644 examples/image_list/macos/Runner/Configs/Warnings.xcconfig create mode 100644 examples/image_list/macos/Runner/DebugProfile.entitlements create mode 100644 examples/image_list/macos/Runner/Info.plist create mode 100644 examples/image_list/macos/Runner/MainFlutterWindow.swift create mode 100644 examples/image_list/macos/Runner/Release.entitlements diff --git a/examples/image_list/macos/.gitignore b/examples/image_list/macos/.gitignore new file mode 100644 index 0000000000000..d2fd3772308cc --- /dev/null +++ b/examples/image_list/macos/.gitignore @@ -0,0 +1,6 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/xcuserdata/ diff --git a/examples/image_list/macos/Flutter/Flutter-Debug.xcconfig b/examples/image_list/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000000000..c2efd0b608ba8 --- /dev/null +++ b/examples/image_list/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/examples/image_list/macos/Flutter/Flutter-Release.xcconfig b/examples/image_list/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000000000..c2efd0b608ba8 --- /dev/null +++ b/examples/image_list/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/examples/image_list/macos/Runner.xcodeproj/project.pbxproj b/examples/image_list/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000000000..65e1baa895ba6 --- /dev/null +++ b/examples/image_list/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,572 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* image_list.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "image_list.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* image_list.app */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* image_list.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/examples/image_list/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/image_list/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000..18d981003d68d --- /dev/null +++ b/examples/image_list/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/image_list/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/examples/image_list/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000000000..8d8f1dd636d6d --- /dev/null +++ b/examples/image_list/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/image_list/macos/Runner.xcworkspace/contents.xcworkspacedata b/examples/image_list/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000000..1d526a16ed0f1 --- /dev/null +++ b/examples/image_list/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/examples/image_list/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/image_list/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000000..18d981003d68d --- /dev/null +++ b/examples/image_list/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/examples/image_list/macos/Runner/AppDelegate.swift b/examples/image_list/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000000000..d080d41951d35 --- /dev/null +++ b/examples/image_list/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000000..a2ec33f19f110 --- /dev/null +++ b/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4935a7ca84f0976aca34b7f2895d65fb94d1ea GIT binary patch literal 46993 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 literal 0 HcmV?d00001 diff --git a/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4cc16421680a50164ba74381b4b35ceaa0ccfc GIT binary patch literal 3276 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 N;OXk;vd$@?2>?>Ex^Vyi literal 0 HcmV?d00001 diff --git a/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbf36df2f2aaaa0a63c7dabc94e600184229d0d GIT binary patch literal 5933 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 f$KZHO*s&vt|9^w-6P?|#0pRK8NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!ItFh?!xdN1Q+aGJ{c&& zS>O>_%)r1c48n{Iv*t(u1=&kHeO=ifbFy+6aSK)V_AxLppYn8Z42d|rc6w}vOsL55 z`t&mC&y2@JTEyg!eDiFX^k#CC!jq%>erB=yHqUP0XcDOTw6ko}L zX;EmMrq(fKk*eygEuA616;0)>@A{TK|55PV@70 z$OfzS*(VJxQev3J?yY?O=ul(v`fp}?u9z`JK3ugibK>)DyCwImZOF4d{xK%%Ks1*} zv$oa)9anR%lXIBUqYnhLmT>VOzHfNP?ZwJNZ!5$s9M08RynIvaXw>@G^T9@r9^KH1 zVy??F&uuk)bH9Y4pQY!hP58i_H6 znl-NcuCpLV6ZWU;4C zu@9exF&OZi`Bovq_m%T+WhU2kvkz@^_LpycBvqm3bMpLw8X-Or5sL>0AKE1$(k_L=_Zc=CUq#=x1-QZf)G7nHu@fmsQ1eN_N3+nTEz`4HI4Z6uVlE zJH+X&det8JU?tO?upcM4Z=cV!JV;yF>FfL5Q$M|W_2Z!P`S=}Wzp|_1^#d%e?_H`> zV@%vA$+bFVqhw9`U;TfP|5|PD{||OiYdor8P*i??|NJcb%kzT_73*7WE?Ua5hAnR2 z=7WE=PhTlJ#ZeRznjTUb;`E(wkMZrj4e|Hilz-mK>9cZHQY**5TUPw~u}k;u73KI}xAx!0m-)GVia|x^d3p~s_9gh83jA&Ra<8rM%`>U3x69t&NzbwWY}7Ar?)FK#IZ0z|d0H0EkRO w3{9;}4Xg|ebq&m|3=9_N6z8I7$jwj5OsmAL;bP(Gi$Dzwp00i_>zopr02+f8CIA2c literal 0 HcmV?d00001 diff --git a/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/examples/image_list/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000000000000000000000000000000000000..e71a726136a47ed24125c7efc79d68a4a01961b4 GIT binary patch literal 14800 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/image_list/macos/Runner/Configs/AppInfo.xcconfig b/examples/image_list/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000000000..55939c7dca21e --- /dev/null +++ b/examples/image_list/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = image_list + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.imageList + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved. diff --git a/examples/image_list/macos/Runner/Configs/Debug.xcconfig b/examples/image_list/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000000000..36b0fd9464f45 --- /dev/null +++ b/examples/image_list/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/examples/image_list/macos/Runner/Configs/Release.xcconfig b/examples/image_list/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000000000..dff4f49561c81 --- /dev/null +++ b/examples/image_list/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/examples/image_list/macos/Runner/Configs/Warnings.xcconfig b/examples/image_list/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000000000..42bcbf4780b18 --- /dev/null +++ b/examples/image_list/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/examples/image_list/macos/Runner/DebugProfile.entitlements b/examples/image_list/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000000000..dddb8a30c851e --- /dev/null +++ b/examples/image_list/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/examples/image_list/macos/Runner/Info.plist b/examples/image_list/macos/Runner/Info.plist new file mode 100644 index 0000000000000..4789daa6a443e --- /dev/null +++ b/examples/image_list/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/image_list/macos/Runner/MainFlutterWindow.swift b/examples/image_list/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000000000..a97a96274ee93 --- /dev/null +++ b/examples/image_list/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,19 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController.init() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/examples/image_list/macos/Runner/Release.entitlements b/examples/image_list/macos/Runner/Release.entitlements new file mode 100644 index 0000000000000..852fa1a4728ae --- /dev/null +++ b/examples/image_list/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + From 4a72c5345eca5540d1420019caf6217e638eeca5 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Thu, 21 Apr 2022 12:49:08 -0700 Subject: [PATCH 11/83] [ci.yaml] Migrate bringup targets to cocoon scheduler (#102249) --- .ci.yaml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.ci.yaml b/.ci.yaml index eaee1eb4d8915..c8946b32847b9 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -1425,7 +1425,6 @@ targets: tags: > ["devicelab","android","linux"] task_name: android_semantics_integration_test - scheduler: luci - name: Linux_android android_stack_size_test recipe: devicelab/devicelab_drone @@ -2302,7 +2301,6 @@ targets: ] tags: > ["framework","hostonly"] - scheduler: luci timeout: 60 - name: Linux_android opacity_peephole_one_rect_perf__e2e_summary @@ -2383,7 +2381,6 @@ targets: tags: > ["devicelab","android","linux"] task_name: gradient_dynamic_perf__e2e_summary - scheduler: luci - name: Linux_android gradient_consistent_perf__e2e_summary bringup: true @@ -2394,7 +2391,6 @@ targets: tags: > ["devicelab","android","linux"] task_name: gradient_consistent_perf__e2e_summary - scheduler: luci - name: Linux_android gradient_static_perf__e2e_summary bringup: true @@ -2405,7 +2401,6 @@ targets: tags: > ["devicelab","android","linux"] task_name: gradient_static_perf__e2e_summary - scheduler: luci - name: Linux_android android_choreographer_do_frame_test recipe: devicelab/devicelab_drone @@ -2426,7 +2421,6 @@ targets: tags: > ["devicelab","android","linux"] task_name: android_lifecycles_test - scheduler: luci - name: Mac build_aar_module_test recipe: devicelab/devicelab_drone @@ -2908,7 +2902,6 @@ targets: tags: > ["framework","hostonly","shard"] test_timeout_secs: "2700" - scheduler: luci runIf: - dev/** - packages/flutter_tools/** @@ -3103,7 +3096,6 @@ targets: tags: > ["devicelab","android","mac"] task_name: entrypoint_dart_registrant - scheduler: luci runIf: - dev/** - packages/flutter_tools/** @@ -3344,7 +3336,6 @@ targets: tags: > ["devicelab","ios","mac"] task_name: flutter_view_ios__start_up - scheduler: luci - name: Mac_ios hello_world_ios__compile recipe: devicelab/devicelab_drone @@ -3477,7 +3468,6 @@ targets: tags: > ["devicelab","ios","mac"] task_name: large_image_changer_perf_ios - scheduler: luci - name: Mac_ios macos_chrome_dev_mode recipe: devicelab/devicelab_drone @@ -3508,7 +3498,6 @@ targets: tags: > ["devicelab","ios","mac"] task_name: new_gallery_ios__transition_perf - scheduler: luci - name: Mac_ios new_gallery_impeller_ios__transition_perf bringup: true # Flaky https://github.com/flutter/flutter/issues/96401 @@ -3519,7 +3508,6 @@ targets: tags: > ["devicelab","ios","mac"] task_name: new_gallery_impeller_ios__transition_perf - scheduler: luci - name: Mac_ios ios_picture_cache_complexity_scoring_perf__timeline_summary recipe: devicelab/devicelab_drone @@ -3620,7 +3608,6 @@ targets: tags: > ["devicelab","ios","mac"] task_name: hot_mode_dev_cycle_ios__benchmark - scheduler: luci - name: Mac_ios tiles_scroll_perf_ios__timeline_summary recipe: devicelab/devicelab_drone @@ -3640,7 +3627,6 @@ targets: tags: > ["devicelab","ios","mac"] task_name: native_ui_tests_ios - scheduler: luci - name: Mac native_ui_tests_macos recipe: devicelab/devicelab_drone From 900e5405c223e9983f644d237467e18cda0a51f5 Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Thu, 21 Apr 2022 22:59:07 +0300 Subject: [PATCH 12/83] Replace `ListTile` with `Chip` in the `debugCheckHasMaterial control test` (#102311) --- packages/flutter/test/material/debug_test.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/flutter/test/material/debug_test.dart b/packages/flutter/test/material/debug_test.dart index 37628bb8c17a7..46f9e61b37fd9 100644 --- a/packages/flutter/test/material/debug_test.dart +++ b/packages/flutter/test/material/debug_test.dart @@ -8,7 +8,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('debugCheckHasMaterial control test', (WidgetTester tester) async { - await tester.pumpWidget(const ListTile()); + await tester.pumpWidget(const Chip(label: Text('label'))); final dynamic exception = tester.takeException(); expect(exception, isFlutterError); final FlutterError error = exception as FlutterError; @@ -28,7 +28,7 @@ void main() { error.toStringDeep(), 'FlutterError\n' ' No Material widget found.\n' - ' ListTile widgets require a Material widget ancestor.\n' + ' Chip widgets require a Material widget ancestor.\n' ' In material design, most widgets are conceptually "printed" on a\n' " sheet of material. In Flutter's material library, that material\n" ' is represented by the Material widget. It is the Material widget\n' @@ -39,7 +39,7 @@ void main() { ' one, or use a widget that contains Material itself, such as a\n' ' Card, Dialog, Drawer, or Scaffold.\n' ' The specific widget that could not find a Material ancestor was:\n' - ' ListTile\n' + ' Chip\n' ' The ancestors of this widget were:\n' ' [root]\n', ); From b63689de691a77679687dc419346a88b12536b38 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 16:09:07 -0400 Subject: [PATCH 13/83] Roll Engine from 701e5e8f44ac to 1cb7af579661 (1 revision) (#102322) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 6b14862e5a17e..05562aaa5ad50 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -701e5e8f44acea0c556adda5c84d1b877096c0b4 +1cb7af579661d2910ee5423ae2091e36836a7b84 diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index 00c4bf56d3a74..2f79426f55bb4 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -p0aZoDAqDDEeIK9bKWRhrH1nXxArDPLqvfGHm4vMVFkC +zjqxHaj1c_wYG8bqwUhNinmx-_aZ-_dL7nyLd8SGKGcC From 06314a073dfdd844e42471259dfaaecad998e97e Mon Sep 17 00:00:00 2001 From: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com> Date: Thu, 21 Apr 2022 13:14:10 -0700 Subject: [PATCH 14/83] Put `waitFor` back in keyboard_textfield_test integration test (#102315) --- .../ui/lib/keyboard_textfield.dart | 7 +++---- .../test_driver/keyboard_textfield_test.dart | 21 ++++--------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/dev/integration_tests/ui/lib/keyboard_textfield.dart b/dev/integration_tests/ui/lib/keyboard_textfield.dart index 4917657c6036a..0f9268a6fe289 100644 --- a/dev/integration_tests/ui/lib/keyboard_textfield.dart +++ b/dev/integration_tests/ui/lib/keyboard_textfield.dart @@ -62,11 +62,10 @@ class _MyHomePageState extends State { Text('$offset', key: const ValueKey(keys.kOffsetText), ), - Text( - isSoftKeyboardVisible ? 'keyboard visible' : 'keyboard hidden', - key: const ValueKey(keys.kKeyboardVisibleView), + if (isSoftKeyboardVisible) const Text( + 'keyboard visible', + key: ValueKey(keys.kKeyboardVisibleView), ), - const ElevatedButton(onPressed: debugDumpApp, child: Text('dump app')), Expanded( child: ListView( key: const ValueKey(keys.kListView), diff --git a/dev/integration_tests/ui/test_driver/keyboard_textfield_test.dart b/dev/integration_tests/ui/test_driver/keyboard_textfield_test.dart index d8353873cc18e..286fc396b1d50 100644 --- a/dev/integration_tests/ui/test_driver/keyboard_textfield_test.dart +++ b/dev/integration_tests/ui/test_driver/keyboard_textfield_test.dart @@ -40,23 +40,10 @@ void main() { // Bring up keyboard await driver.tap(textFieldFinder); - const int keyboardTimeout = 3; - bool keyboardVisible = false; - for (int i = 0; i < keyboardTimeout; i++) { - await Future.delayed(const Duration(seconds: 1)); - final String keyboardVisibilityText = await driver.getText(keyboardVisibilityIndicatorFinder); - keyboardVisible = keyboardVisibilityText == 'keyboard visible'; - if (keyboardVisible) { - break; - } - } - - if (!keyboardVisible) { - await driver.tap(find.text('dump app')); - } - - // TODO(jmagman): Remove timeout once flake has been diagnosed. https://github.com/flutter/flutter/issues/96787 - expect(keyboardVisible, isTrue); + // The blinking cursor may have animation. Do not wait for it to finish. + await driver.runUnsynchronized(() async { + await driver.waitFor(keyboardVisibilityIndicatorFinder); + }); // Ensure that TextField is visible again await driver.waitFor(textFieldFinder); From 242ad0f730dc35eded0bc106daabbbeebd53420d Mon Sep 17 00:00:00 2001 From: keyonghan <54558023+keyonghan@users.noreply.github.com> Date: Thu, 21 Apr 2022 13:24:07 -0700 Subject: [PATCH 15/83] Enable DeviceLab arm64 ios tests as `bringup: true` (#102089) --- .ci.yaml | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/.ci.yaml b/.ci.yaml index c8946b32847b9..4a22bf4e12304 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -131,6 +131,29 @@ platform_properties: cpu: x86 device_os: iOS-15.1 xcode: 13a233 + mac_arm64_ios: + properties: + caches: >- + [ + {"name":"builder_mac_devicelab","path":"builder"}, + {"name":"chrome_and_driver_96","path":"chrome"}, + {"name":"flutter_sdk","path":"flutter sdk"}, + {"name":"gradle","path":"gradle"}, + {"name":"openjdk","path":"java11"}, + {"name":"pub_cache","path":".pub-cache"}, + {"name":"xcode_binary","path":"xcode_binary"}, + {"name":"osx_sdk_13a233","path":"osx_sdk"} + ] + dependencies: >- + [ + {"dependency": "xcode"}, + {"dependency": "gems"}, + {"dependency": "apple_signing"} + ] + os: Mac-12 + cpu: arm64 + device_os: iOS-15.1 + xcode: 13a233 windows: properties: caches: >- @@ -2472,6 +2495,22 @@ targets: - bin/** - .ci.yaml + - name: Mac_arm64_ios build_ios_framework_module_test + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: build_ios_framework_module_test + runIf: + - dev/** + - packages/flutter_tools/** + - bin/** + - .ci.yaml + scheduler: luci + - name: Mac build_tests_1_4 recipe: flutter/flutter_drone timeout: 60 @@ -3318,6 +3357,17 @@ targets: task_name: flutter_gallery_ios__compile scheduler: luci + - name: Mac_arm64_ios flutter_gallery_ios__compile + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: flutter_gallery_ios__compile + scheduler: luci + - name: Mac_ios flutter_gallery_ios__start_up recipe: devicelab/devicelab_drone presubmit: false @@ -3347,6 +3397,17 @@ targets: task_name: hello_world_ios__compile scheduler: luci + - name: Mac_arm64_ios hello_world_ios__compile + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: hello_world_ios__compile + scheduler: luci + - name: Mac_ios hot_mode_dev_cycle_macos_target__benchmark recipe: devicelab/devicelab_drone timeout: 60 @@ -3359,6 +3420,19 @@ targets: - .ci.yaml scheduler: luci + - name: Mac_arm64_ios hot_mode_dev_cycle_macos_target__benchmark + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: hot_mode_dev_cycle_macos_target__benchmark + runIf: + - dev/** + scheduler: luci + - name: Mac_ios integration_test_test_ios recipe: devicelab/devicelab_drone presubmit: false @@ -3429,6 +3503,17 @@ targets: task_name: ios_app_with_extensions_test scheduler: luci + - name: Mac_arm64_ios ios_app_with_extensions_test + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: ios_app_with_extensions_test + scheduler: luci + - name: Mac_ios ios_content_validation_test recipe: devicelab/devicelab_drone presubmit: false @@ -3439,6 +3524,17 @@ targets: task_name: ios_content_validation_test scheduler: luci + - name: Mac_arm64_ios ios_content_validation_test + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: ios_content_validation_test + scheduler: luci + - name: Mac_ios ios_defines_test recipe: devicelab/devicelab_drone presubmit: false @@ -3479,6 +3575,17 @@ targets: task_name: macos_chrome_dev_mode scheduler: luci + - name: Mac_arm64_ios macos_chrome_dev_mode + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: macos_chrome_dev_mode + scheduler: luci + - name: Mac_ios microbenchmarks_ios recipe: devicelab/devicelab_drone presubmit: false @@ -3628,6 +3735,17 @@ targets: ["devicelab","ios","mac"] task_name: native_ui_tests_ios + - name: Mac_arm64_ios native_ui_tests_ios + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: native_ui_tests_ios + scheduler: luci + - name: Mac native_ui_tests_macos recipe: devicelab/devicelab_drone timeout: 60 @@ -3666,6 +3784,22 @@ targets: - .ci.yaml scheduler: luci + - name: Mac_arm64_ios run_release_test_macos + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true # https://github.com/flutter/flutter/issues/87508 + timeout: 60 + properties: + tags: > + ["devicelab","ios","mac","arm64"] + task_name: run_release_test_macos + runIf: + - dev/** + - packages/flutter_tools/** + - bin/** + - .ci.yaml + scheduler: luci + - name: Windows build_aar_module_test bringup: true # Flaky https://github.com/flutter/flutter/issues/102226 recipe: devicelab/devicelab_drone From 0cbd6231e4e5411ac7c021cf685a1025ec507a17 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 17:14:06 -0400 Subject: [PATCH 16/83] Roll Engine from 1cb7af579661 to 4f05631a710a (1 revision) (#102326) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 05562aaa5ad50..63e2cfb1eed9a 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -1cb7af579661d2910ee5423ae2091e36836a7b84 +4f05631a710ab707ab252b34695446bd2a2ad244 From 4ca94ab2fcd04012ef9e64463270bcfb69b3ce3f Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Thu, 21 Apr 2022 15:24:09 -0700 Subject: [PATCH 17/83] Remove build_aar_module_test from devicelab tests (#102329) --- .ci.yaml | 78 -------------------------------------------------------- 1 file changed, 78 deletions(-) diff --git a/.ci.yaml b/.ci.yaml index 4a22bf4e12304..41ec45cd947fa 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -205,32 +205,6 @@ targets: validation_name: Analyze scheduler: luci - - name: Linux build_aar_module_test - recipe: devicelab/devicelab_drone - timeout: 60 - properties: - add_recipes_cq: "true" - caches: >- - [ - {"name":"gradle","path":"gradle"}, - {"name": "openjdk_11", "path": "java"} - ] - dependencies: >- - [ - {"dependency": "android_sdk", "version": "version:31v8"}, - {"dependency": "chrome_and_driver", "version": "version:96.2"}, - {"dependency": "open_jdk", "version": "11"} - ] - tags: > - ["devicelab","hostonly"] - task_name: build_aar_module_test - scheduler: luci - runIf: - - dev/** - - packages/flutter_tools/** - - bin/** - - .ci.yaml - - name: Linux build_tests_1_2 recipe: flutter/flutter_drone timeout: 60 @@ -2445,31 +2419,6 @@ targets: ["devicelab","android","linux"] task_name: android_lifecycles_test - - name: Mac build_aar_module_test - recipe: devicelab/devicelab_drone - timeout: 60 - properties: - add_recipes_cq: "true" - caches: >- - [ - {"name":"gradle", "path":"gradle"}, - {"name": "openjdk_11", "path": "java"} - ] - dependencies: >- - [ - {"dependency": "android_sdk", "version": "version:31v8"}, - {"dependency": "open_jdk", "version": "11"} - ] - tags: > - ["devicelab","hostonly"] - task_name: build_aar_module_test - runIf: - - dev/** - - packages/flutter_tools/** - - bin/** - - .ci.yaml - scheduler: luci - - name: Mac build_ios_framework_module_test recipe: devicelab/devicelab_drone timeout: 60 @@ -3800,33 +3749,6 @@ targets: - .ci.yaml scheduler: luci - - name: Windows build_aar_module_test - bringup: true # Flaky https://github.com/flutter/flutter/issues/102226 - recipe: devicelab/devicelab_drone - timeout: 60 - properties: - add_recipes_cq: "true" - caches: >- - [ - {"name":"gradle","path":"gradle"}, - {"name": "openjdk_11", "path": "java"} - ] - dependencies: >- - [ - {"dependency": "android_sdk", "version": "version:31v8"}, - {"dependency": "chrome_and_driver", "version": "version:96.2"}, - {"dependency": "open_jdk", "version": "11"} - ] - tags: > - ["devicelab","hostonly"] - task_name: build_aar_module_test - scheduler: luci - runIf: - - dev/** - - packages/flutter_tools/** - - bin/** - - .ci.yaml - - name: Windows build_tests_1_3 recipe: flutter/flutter_drone timeout: 60 From c73100bfaec52f48eaa4662c5fa60adfb2fb9cbf Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Thu, 21 Apr 2022 15:39:07 -0700 Subject: [PATCH 18/83] Fix the code point for CupertinoIcons.location (#101923) --- packages/flutter/lib/src/cupertino/icons.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/cupertino/icons.dart b/packages/flutter/lib/src/cupertino/icons.dart index d214511b3a382..fd02f2350fcf9 100644 --- a/packages/flutter/lib/src/cupertino/icons.dart +++ b/packages/flutter/lib/src/cupertino/icons.dart @@ -912,7 +912,7 @@ class CupertinoIcons { static const IconData mail_solid = IconData(0xf423, fontFamily: iconFont, fontPackage: iconFontPackage); /// location — Cupertino icon for a location pin. - static const IconData location = IconData(0xf455, fontFamily: iconFont, fontPackage: iconFontPackage); + static const IconData location = IconData(0xf6ee, fontFamily: iconFont, fontPackage: iconFontPackage); /// placemark_fill — Cupertino icon for a location pin. This icon is filled in. /// This is the same icon as [placemark_fill] in cupertino_icons 1.0.0+. From c9825d24dd8a624c9720d24a4af4753e5d468b79 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 21 Apr 2022 15:49:08 -0700 Subject: [PATCH 19/83] Handle CocoaPods ffi stderr (#102327) --- packages/flutter_tools/lib/src/macos/cocoapods.dart | 7 ++++--- .../test/general.shard/macos/cocoapods_test.dart | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/flutter_tools/lib/src/macos/cocoapods.dart b/packages/flutter_tools/lib/src/macos/cocoapods.dart index a471e36b1fbf3..26365b6a46425 100644 --- a/packages/flutter_tools/lib/src/macos/cocoapods.dart +++ b/packages/flutter_tools/lib/src/macos/cocoapods.dart @@ -349,10 +349,11 @@ class CocoaPods { } void _diagnosePodInstallFailure(ProcessResult result) { - if (result.stdout is! String) { + final Object? stdout = result.stdout; + final Object? stderr = result.stderr; + if (stdout is! String || stderr is! String) { return; } - final String stdout = result.stdout as String; if (stdout.contains('out-of-date source repos')) { _logger.printError( "Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.\n" @@ -360,7 +361,7 @@ class CocoaPods { ' pod repo update\n', emphasis: true, ); - } else if ((stdout.contains('ffi_c.bundle') || stdout.contains('/ffi/')) && + } else if ((stderr.contains('ffi_c.bundle') || stderr.contains('/ffi/')) && _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm) { // https://github.com/flutter/flutter/issues/70796 UsageEvent( diff --git a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart index e5554ba2466eb..81139a64730c0 100644 --- a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart +++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart @@ -514,7 +514,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by 'LANG': 'en_US.UTF-8', }, exitCode: 1, - stdout: cocoaPodsError, + stderr: cocoaPodsError, ), const FakeCommand( command: ['which', 'sysctl'], From 512cbdb9da883cc59013ef3363a62beb7d2a6e3c Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Thu, 21 Apr 2022 18:54:13 -0400 Subject: [PATCH 20/83] Enable jank metric collection in profile mode (#102334) --- packages/flutter_tools/lib/src/resident_runner.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 419c1953a0c79..d303e639a60db 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -682,7 +682,7 @@ abstract class ResidentHandlers { /// use case is to look at the various layers in proportion to see what /// contributes the most towards raster performance. Future debugFrameJankMetrics() async { - if (!supportsServiceProtocol || !isRunningDebug) { + if (!supportsServiceProtocol) { return false; } for (final FlutterDevice device in flutterDevices) { From 570e23e94944fcc90d60e95ffbc10b2fe45b4a3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Apr 2022 15:59:07 -0700 Subject: [PATCH 21/83] Bump actions/checkout from 3.0.1 to 3.0.2 (#102337) --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a00102e3287e6..e4a0f5407ebb7 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -21,7 +21,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@dcd71f646680f2efd8db4afa5ad64fdcba30e748 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b with: persist-credentials: false From b7abece9cd44b45aafb32dc9442ae022ff06f9f7 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 19:24:09 -0400 Subject: [PATCH 22/83] Roll Engine from 4f05631a710a to 238eb9d7f55f (5 revisions) (#102340) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 63e2cfb1eed9a..a5a46c41584e6 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -4f05631a710ab707ab252b34695446bd2a2ad244 +238eb9d7f55f0ca24d2a1e706b02109ef76844cf From b8dfe0d80c4c16f605f08015ee39c769f1c57e6c Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 20:29:06 -0400 Subject: [PATCH 23/83] Roll Engine from 238eb9d7f55f to 1b10b146cf7c (2 revisions) (#102344) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index a5a46c41584e6..8c2f99063d593 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -238eb9d7f55f0ca24d2a1e706b02109ef76844cf +1b10b146cf7c73cf4e543e6762e479eb1b023f1e diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index 75b80067c63bd..979c9a5d493ed 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -9g8p_giFbkP4781dwqfOd3BTojVaMQTirYYfd07wLLEC +CQEP7X2HznO3K8CVIYx6C3TYvcIcymV0QfthRNJ01zMC From 9a3806bd0877b2a9fdcfa2c8b869f8631244a98f Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 21:44:03 -0400 Subject: [PATCH 24/83] Roll Engine from 1b10b146cf7c to bcd35000ed99 (1 revision) (#102345) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 8c2f99063d593..ac6ccf83deb75 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -1b10b146cf7c73cf4e543e6762e479eb1b023f1e +bcd35000ed997ad7fa52f5f45b525567f880b755 From 0d9c51c7329fb7aefdae55b6d054053329b8aa3a Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Thu, 21 Apr 2022 22:49:07 -0400 Subject: [PATCH 25/83] Roll Engine from bcd35000ed99 to c6ea046c2cda (3 revisions) (#102347) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index ac6ccf83deb75..0529b874e6588 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -bcd35000ed997ad7fa52f5f45b525567f880b755 +c6ea046c2cdaf3fb2428b31108eae3c3b1174e6e From a91ad0052f5ee88e788bac094856b772c754484f Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 00:34:06 -0400 Subject: [PATCH 26/83] Roll Engine from c6ea046c2cda to d4158760408d (1 revision) (#102349) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 0529b874e6588..f8a7b3b3715bb 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -c6ea046c2cdaf3fb2428b31108eae3c3b1174e6e +d4158760408d01db8d0b5f924bd8b8c3411f822a From 0a36b53551c49b2fb302f20e3424b9d68c50ed17 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 05:09:07 -0400 Subject: [PATCH 27/83] Roll Engine from d4158760408d to e96c75676ee5 (2 revisions) (#102354) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index f8a7b3b3715bb..e15fe8a7abab2 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -d4158760408d01db8d0b5f924bd8b8c3411f822a +e96c75676ee56c039ea136c9f70328e14fd08b9d diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index 2f79426f55bb4..b730a98fb7298 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -zjqxHaj1c_wYG8bqwUhNinmx-_aZ-_dL7nyLd8SGKGcC +sTvRmqTst61TllIcWosYZZBa5b7Qa9aFlu65kBU-FSkC From fde7622f7e0ab915ce19bd49a8ead5707141df6a Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 06:14:07 -0400 Subject: [PATCH 28/83] Roll Engine from e96c75676ee5 to 2d7fcf4e36eb (1 revision) (#102359) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index e15fe8a7abab2..39a05e18da3c3 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -e96c75676ee56c039ea136c9f70328e14fd08b9d +2d7fcf4e36ebaea10bd9c471644389e69c423b12 From ad652a665900e7b45037b1e525845e862853700c Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 09:14:07 -0400 Subject: [PATCH 29/83] Roll Engine from 2d7fcf4e36eb to 0a88671c35f6 (2 revisions) (#102371) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 39a05e18da3c3..3586d7224104f 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -2d7fcf4e36ebaea10bd9c471644389e69c423b12 +0a88671c35f6974db605d3a9cae9422d21fb0290 diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index 979c9a5d493ed..e061e1f5d8a25 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -CQEP7X2HznO3K8CVIYx6C3TYvcIcymV0QfthRNJ01zMC +2URwvdZiLGMKsnYKqGCtPo6Vw4fiUnRuEp4OayAc0PQC From e2f4e80ce5cc5143d6455e727163d0b8e6117993 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 11:04:07 -0400 Subject: [PATCH 30/83] Roll Engine from 0a88671c35f6 to d9b3a550a75a (1 revision) (#102375) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 3586d7224104f..61092f8a2d77c 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -0a88671c35f6974db605d3a9cae9422d21fb0290 +d9b3a550a75a4db522c06324a8c5a61a18d49f30 From 03c93640b4ed82a984cbbfcf959918d35b68ed11 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 12:04:08 -0400 Subject: [PATCH 31/83] Roll Plugins from 5c3c1b8aac06 to ca63d964d9fd (10 revisions) (#102379) --- bin/internal/flutter_plugins.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/flutter_plugins.version b/bin/internal/flutter_plugins.version index a083a54bc9ded..8915d67171ac0 100644 --- a/bin/internal/flutter_plugins.version +++ b/bin/internal/flutter_plugins.version @@ -1 +1 @@ -5c3c1b8aac065aa1988f114d0c66ecec758e9cbb +ca63d964d9fdfff9be36533ea4248d0d0ca28fd0 From e2dc2c821ff82a75e7da339ab981062fe48d46b4 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 12:49:07 -0400 Subject: [PATCH 32/83] Roll Engine from d9b3a550a75a to 587bca0454bc (1 revision) (#102380) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 61092f8a2d77c..6a6d1270bb87c 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -d9b3a550a75a4db522c06324a8c5a61a18d49f30 +587bca0454bcc9858cff709e31a2392d4b6aa3b7 From f4de048ff88bf227f8857bb9b5c899712344e220 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 14:19:07 -0400 Subject: [PATCH 33/83] Roll Engine from 587bca0454bc to 4350d117406d (1 revision) (#102386) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 6a6d1270bb87c..4392f29bf9dcc 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -587bca0454bcc9858cff709e31a2392d4b6aa3b7 +4350d117406dbb1dc1dcfcd117292176de3169de From ca3b406c44138b547b0e7ee7ac516722a66a5135 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 15:39:06 -0400 Subject: [PATCH 34/83] Roll Engine from 4350d117406d to ad6976c4d1db (1 revision) (#102394) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 4392f29bf9dcc..4a3a032579e91 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -4350d117406dbb1dc1dcfcd117292176de3169de +ad6976c4d1db068d6462733516c89837a4958042 From 5414ef4c86ba014568bafd721a30cb3e5cfb9b96 Mon Sep 17 00:00:00 2001 From: "Elliott Brooks (she/her)" <21270878+elliette@users.noreply.github.com> Date: Fri, 22 Apr 2022 12:43:39 -0700 Subject: [PATCH 35/83] Hide unresolved DartUri log messages (#102338) --- .../flutter_tools/lib/src/isolated/devfs_web.dart | 10 ++++++++++ .../test/web.shard/output_web_test.dart | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/flutter_tools/lib/src/isolated/devfs_web.dart b/packages/flutter_tools/lib/src/isolated/devfs_web.dart index 8b6f22b78703d..8a833129bba9e 100644 --- a/packages/flutter_tools/lib/src/isolated/devfs_web.dart +++ b/packages/flutter_tools/lib/src/isolated/devfs_web.dart @@ -1009,6 +1009,16 @@ void _log(logging.LogRecord event) { if (event.level >= logging.Level.SEVERE) { globals.printError('${event.loggerName}: ${event.message}$error', stackTrace: event.stackTrace); } else if (event.level == logging.Level.WARNING) { + // TODO(elliette): Remove the following message suppressions after DWDS is + // >13.1.0, https://github.com/flutter/flutter/issues/101639 + const String dartUri = 'DartUri'; + if (event.loggerName == dartUri) { + const String webSqlWarning = 'Unresolved uri: dart:web_sql'; + const String uiWarning = 'Unresolved uri: dart:ui'; + if (event.message == webSqlWarning || event.message == uiWarning) { + return; + } + } globals.printWarning('${event.loggerName}: ${event.message}$error'); } else { globals.printTrace('${event.loggerName}: ${event.message}$error'); diff --git a/packages/flutter_tools/test/web.shard/output_web_test.dart b/packages/flutter_tools/test/web.shard/output_web_test.dart index a689088ab0dcf..bcb4b7473a703 100644 --- a/packages/flutter_tools/test/web.shard/output_web_test.dart +++ b/packages/flutter_tools/test/web.shard/output_web_test.dart @@ -78,4 +78,18 @@ void main() { await sendEvent({'type': 'DevtoolsEvent'}); await warning; }, skip: true); // Skipping for 'https://github.com/dart-lang/webdev/issues/1562' + + testWithoutContext( + 'flutter run output skips DartUri warning messages from dwds', () async { + bool containsDartUriWarning = false; + flutter.stderr.listen((String msg) { + if (msg.contains('DartUri')) { + containsDartUriWarning = true; + } + }); + await start(); + await flutter.stop(); + expect(containsDartUriWarning, isFalse); + // TODO(elliette): Enable for DWDS >13.1.0, https://github.com/flutter/flutter/issues/101639 + }, skip: true); // [intended] enable for DWDS >13.1.0 } From dc51dfe61ebb6e0f7f96e7fca0e7c2cf0719706f Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 16:44:07 -0400 Subject: [PATCH 36/83] Roll Engine from ad6976c4d1db to 061fb1d74a9f (1 revision) (#102397) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 4a3a032579e91..38295d2cb2ed7 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -ad6976c4d1db068d6462733516c89837a4958042 +061fb1d74a9fd0d738de02442f4a9c4d94e00a6b From 1ba573b758dc384a2738384c7f83853bc11308ad Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 17:49:06 -0400 Subject: [PATCH 37/83] Roll Engine from 061fb1d74a9f to 0da451d25cf8 (1 revision) (#102400) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 38295d2cb2ed7..0d7243973c386 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -061fb1d74a9fd0d738de02442f4a9c4d94e00a6b +0da451d25cf84a1336ad32028427873bc3e87c70 From 6ea4aef827cefff2f088dae8abd4f762271d2ff0 Mon Sep 17 00:00:00 2001 From: rgevrek Date: Sat, 23 Apr 2022 00:19:06 +0200 Subject: [PATCH 38/83] Fix jumping when doing long press for selecting text (#102270) --- .../lib/src/widgets/editable_text.dart | 5 ++ .../test/widgets/editable_text_test.dart | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 8e477b4032cb7..be622d5ba3bda 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -2514,6 +2514,11 @@ class EditableTextState extends State with AutomaticKeepAliveClien _showCaretOnScreenScheduled = true; SchedulerBinding.instance.addPostFrameCallback((Duration _) { _showCaretOnScreenScheduled = false; + + // if cursor is inactive, e.g. while selecting text, do not jump away + if (!_cursorActive) { + return; + } if (_currentCaretRect == null || !_scrollController.hasClients) { return; } diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index c13aecb79da75..4b0226ebb82fe 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5183,6 +5183,53 @@ void main() { // toolbar. Until we change that, this test should remain skipped. }, skip: kIsWeb); // [intended] + + testWidgets('text selection handle visibility for long text', (WidgetTester tester) async { + // long text which is scrollable based on given box size + const String testText = + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.'; + final TextEditingController controller = + TextEditingController(text: testText); + final ScrollController scrollController = ScrollController(); + + await tester.pumpWidget(MaterialApp( + home: Align( + alignment: Alignment.topLeft, + child: SizedBox( + width: 100, + height: 100, + child: SingleChildScrollView( + controller: scrollController, + child: EditableText( + controller: controller, + showSelectionHandles: true, + focusNode: FocusNode(), + style: Typography.material2018().black.subtitle1!, + cursorColor: Colors.blue, + backgroundCursorColor: Colors.grey, + selectionControls: materialTextSelectionControls, + keyboardType: TextInputType.multiline, + maxLines: null, + ), + ), + ), + ), + )); + + // scroll to a text that is outside of the inital visible rect + scrollController.jumpTo(151); + await tester.pump(); + + // long press on a word to trigger a select + await tester.longPressAt(const Offset(20, 15)); + // wait for adjustments of scroll area + await tester.pump(); + await tester.pumpAndSettle(); + + // assert not jumped to top + expect(scrollController.offset, equals(151)); + }); + const String testText = 'Now is the time for\n' // 20 'all good people\n' // 20 + 16 => 36 'to come to the aid\n' // 36 + 19 => 55 From a3a9a23e46f32f8ec0b2191cd969188a70a5af5f Mon Sep 17 00:00:00 2001 From: Daniel Cardona Rojas Date: Fri, 22 Apr 2022 17:24:10 -0500 Subject: [PATCH 39/83] Add matcher to find at least a given number of widgets (#102081) (#102342) --- packages/flutter_test/lib/src/matchers.dart | 20 +++++++++++ packages/flutter_test/test/matchers_test.dart | 36 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/packages/flutter_test/lib/src/matchers.dart b/packages/flutter_test/lib/src/matchers.dart index 338e5bcaf1860..5434b0be538fe 100644 --- a/packages/flutter_test/lib/src/matchers.dart +++ b/packages/flutter_test/lib/src/matchers.dart @@ -37,6 +37,7 @@ import 'widget_tester.dart' show WidgetTester; /// * [findsWidgets], when you want the finder to find one or more widgets. /// * [findsOneWidget], when you want the finder to find exactly one widget. /// * [findsNWidgets], when you want the finder to find a specific number of widgets. +/// * [findsAtLeastNWidgets], when you want the finder to find at least a specific number of widgets. const Matcher findsNothing = _FindsWidgetMatcher(null, 0); /// Asserts that the [Finder] locates at least one widget in the widget tree. @@ -52,6 +53,7 @@ const Matcher findsNothing = _FindsWidgetMatcher(null, 0); /// * [findsNothing], when you want the finder to not find anything. /// * [findsOneWidget], when you want the finder to find exactly one widget. /// * [findsNWidgets], when you want the finder to find a specific number of widgets. +/// * [findsAtLeastNWidgets], when you want the finder to find at least a specific number of widgets. const Matcher findsWidgets = _FindsWidgetMatcher(1, null); /// Asserts that the [Finder] locates at exactly one widget in the widget tree. @@ -67,6 +69,7 @@ const Matcher findsWidgets = _FindsWidgetMatcher(1, null); /// * [findsNothing], when you want the finder to not find anything. /// * [findsWidgets], when you want the finder to find one or more widgets. /// * [findsNWidgets], when you want the finder to find a specific number of widgets. +/// * [findsAtLeastNWidgets], when you want the finder to find at least a specific number of widgets. const Matcher findsOneWidget = _FindsWidgetMatcher(1, 1); /// Asserts that the [Finder] locates the specified number of widgets in the widget tree. @@ -82,8 +85,25 @@ const Matcher findsOneWidget = _FindsWidgetMatcher(1, 1); /// * [findsNothing], when you want the finder to not find anything. /// * [findsWidgets], when you want the finder to find one or more widgets. /// * [findsOneWidget], when you want the finder to find exactly one widget. +/// * [findsAtLeastNWidgets], when you want the finder to find at least a specific number of widgets. Matcher findsNWidgets(int n) => _FindsWidgetMatcher(n, n); +/// Asserts that the [Finder] locates at least a number of widgets in the widget tree. +/// +/// ## Sample code +/// +/// ```dart +/// expect(find.text('Save'), findsAtLeastNWidgets(2)); +/// ``` +/// +/// See also: +/// +/// * [findsNothing], when you want the finder to not find anything. +/// * [findsWidgets], when you want the finder to find one or more widgets. +/// * [findsOneWidget], when you want the finder to find exactly one widget. +/// * [findsNWidgets], when you want the finder to find a specific number of widgets. +Matcher findsAtLeastNWidgets(int n) => _FindsWidgetMatcher(n, null); + /// Asserts that the [Finder] locates a single widget that has at /// least one [Offstage] widget ancestor. /// diff --git a/packages/flutter_test/test/matchers_test.dart b/packages/flutter_test/test/matchers_test.dart index 4632aba6fc4ea..2477313a06484 100644 --- a/packages/flutter_test/test/matchers_test.dart +++ b/packages/flutter_test/test/matchers_test.dart @@ -674,6 +674,42 @@ void main() { handle.dispose(); }); }); + + group('findsAtLeastNWidgets', () { + Widget boilerplate(Widget child) { + return Directionality( + textDirection: TextDirection.ltr, + child: child, + ); + } + + testWidgets('succeeds when finds more then the specified count', + (WidgetTester tester) async { + await tester.pumpWidget(boilerplate(Column( + children: const [Text('1'), Text('2'), Text('3')], + ))); + + expect(find.byType(Text), findsAtLeastNWidgets(2)); + }); + + testWidgets('succeeds when finds the exact specified count', + (WidgetTester tester) async { + await tester.pumpWidget(boilerplate(Column( + children: const [Text('1'), Text('2')], + ))); + + expect(find.byType(Text), findsAtLeastNWidgets(2)); + }); + + testWidgets('fails when finds less then specified count', + (WidgetTester tester) async { + await tester.pumpWidget(boilerplate(Column( + children: const [Text('1'), Text('2')], + ))); + + expect(find.byType(Text), isNot(findsAtLeastNWidgets(3))); + }); + }); } enum _ComparatorBehavior { From 5a3e10047f841d910cd078d75040b16a44cf4fa1 Mon Sep 17 00:00:00 2001 From: Christopher Fujino Date: Fri, 22 Apr 2022 15:29:07 -0700 Subject: [PATCH 40/83] [flutter_tools] Add test that "Unresolve URI" warnings from DWDS are filtered from logs (#102399) --- .../lib/src/isolated/devfs_web.dart | 5 ++-- .../general.shard/web/devfs_web_test.dart | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/flutter_tools/lib/src/isolated/devfs_web.dart b/packages/flutter_tools/lib/src/isolated/devfs_web.dart index 8a833129bba9e..7539977abd3ed 100644 --- a/packages/flutter_tools/lib/src/isolated/devfs_web.dart +++ b/packages/flutter_tools/lib/src/isolated/devfs_web.dart @@ -275,7 +275,7 @@ class WebAssetServer implements AssetReader { } logging.Logger.root.level = logging.Level.ALL; - logging.Logger.root.onRecord.listen(_log); + logging.Logger.root.onRecord.listen(log); // In debug builds, spin up DWDS and the full asset server. final Dwds dwds = await dwdsLauncher( @@ -1004,7 +1004,8 @@ class ReleaseAssetServer { } } -void _log(logging.LogRecord event) { +@visibleForTesting +void log(logging.LogRecord event) { final String error = event.error == null? '': 'Error: ${event.error}'; if (event.level >= logging.Level.SEVERE) { globals.printError('${event.loggerName}: ${event.message}$error', stackTrace: event.stackTrace); diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart index 909258801c6ae..cc0f158caecc7 100644 --- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart +++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart @@ -8,6 +8,7 @@ import 'dart:io' hide Directory, File; import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/targets/web.dart'; @@ -16,6 +17,7 @@ import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/isolated/devfs_web.dart'; import 'package:flutter_tools/src/web/compile.dart'; +import 'package:logging/logging.dart' as logging; import 'package:package_config/package_config.dart'; import 'package:shelf/shelf.dart'; import 'package:test/fake.dart'; @@ -39,6 +41,7 @@ void main() { PackageConfig packages; Platform windows; FakeHttpServer httpServer; + BufferLogger logger; setUpAll(() async { packages = PackageConfig([ @@ -50,6 +53,7 @@ void main() { httpServer = FakeHttpServer(); linux = FakePlatform(environment: {}); windows = FakePlatform(operatingSystem: 'windows', environment: {}); + logger = BufferLogger.test(); testbed = Testbed(setup: () { webAssetServer = WebAssetServer( httpServer, @@ -67,9 +71,35 @@ void main() { webBuildDirectory: null, basePath: null, ); + }, overrides: { + Logger: () => logger, }); }); + test('.log() filters events', () => testbed.run(() { + // harmless warning that should be filtered out + const String harmlessMessage = 'Unresolved uri: dart:ui'; + // serious warning + const String seriousMessage = 'Something bad happened'; + + final List events = [ + logging.LogRecord( + logging.Level.WARNING, + harmlessMessage, + 'DartUri', + ), + logging.LogRecord( + logging.Level.WARNING, + seriousMessage, + 'DartUri', + ), + ]; + + events.forEach(log); + expect(logger.warningText, contains(seriousMessage)); + expect(logger.warningText, isNot(contains(harmlessMessage))); + })); + test('Handles against malformed manifest', () => testbed.run(() async { final File source = globals.fs.file('source') ..writeAsStringSync('main() {}'); From 2c60d2c9152d6a64ff0383bf97e31d6e8b8e6a37 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 18:54:08 -0400 Subject: [PATCH 41/83] Roll Engine from 0da451d25cf8 to 7cb80a7964ef (2 revisions) (#102409) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 0d7243973c386..87e01678018ee 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -0da451d25cf84a1336ad32028427873bc3e87c70 +7cb80a7964ef5653330117ac1d78a2966833f5b3 diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index b730a98fb7298..cf04203131f41 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -sTvRmqTst61TllIcWosYZZBa5b7Qa9aFlu65kBU-FSkC +yRFArCwDi-2UHUxwQl6rk0ISTua4FobB84XwaUZFC7cC From e32dbbab43001166a05ab4fe65a939b9cbf205d0 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 19:59:04 -0400 Subject: [PATCH 42/83] Roll Engine from 7cb80a7964ef to 819ca4ec8cd5 (3 revisions) (#102411) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 87e01678018ee..91df8e962c837 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -7cb80a7964ef5653330117ac1d78a2966833f5b3 +819ca4ec8cd5cd4ad491f99b11418139a554ed5d From d25116921eb7fbccea74937abae0096fb92bfd04 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Fri, 22 Apr 2022 23:14:07 -0400 Subject: [PATCH 43/83] Roll Engine from 819ca4ec8cd5 to e9ebbb5575fb (4 revisions) (#102425) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 91df8e962c837..c8f88b72424b8 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -819ca4ec8cd5cd4ad491f99b11418139a554ed5d +e9ebbb5575fbd051835d3b5aaa1cb3017061bbc5 diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index e061e1f5d8a25..da77eae70092d 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -2URwvdZiLGMKsnYKqGCtPo6Vw4fiUnRuEp4OayAc0PQC +OOBEL73yb3wgbPPtZ_n599QLfJdr2snywov8_9Z39xUC From 751d9041fdb9973ab70db5e4c3668bb05d2475b6 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sat, 23 Apr 2022 01:04:05 -0400 Subject: [PATCH 44/83] Roll Engine from e9ebbb5575fb to 49fe29e373d6 (2 revisions) (#102428) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index c8f88b72424b8..628c24cdd4ce1 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -e9ebbb5575fbd051835d3b5aaa1cb3017061bbc5 +49fe29e373d60e88e0931a96a3c0d307b007dcab From e3ec5a4843f2a6920b32aaa0c8d22da9cc801932 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sat, 23 Apr 2022 07:09:06 -0400 Subject: [PATCH 45/83] Roll Engine from 49fe29e373d6 to f6725544f45e (1 revision) (#102437) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 628c24cdd4ce1..989df848d9c38 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -49fe29e373d60e88e0931a96a3c0d307b007dcab +f6725544f45eaacd9afc6893e1a6131f933ef17e diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index cf04203131f41..af4e48006f4c2 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -yRFArCwDi-2UHUxwQl6rk0ISTua4FobB84XwaUZFC7cC +uetob3LZ0XpTHKVP2YC9_9qv7AGxeV4vzHZS97O3HuwC From b3584f58fdeec971be9762d3dfe892ddb373a577 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sat, 23 Apr 2022 08:14:04 -0400 Subject: [PATCH 46/83] Roll Engine from f6725544f45e to b4cc382cb26b (1 revision) (#102438) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 989df848d9c38..9a6a0868af8a7 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -f6725544f45eaacd9afc6893e1a6131f933ef17e +b4cc382cb26b3cf045a9b65e1c1e4178c47c77c1 From 02f081a708b74d94cd55ba2d9dc480256a8b0cc2 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sat, 23 Apr 2022 14:14:03 -0400 Subject: [PATCH 47/83] Roll Engine from b4cc382cb26b to dbe5a764d952 (1 revision) (#102444) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 9a6a0868af8a7..56da0a4f2035a 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -b4cc382cb26b3cf045a9b65e1c1e4178c47c77c1 +dbe5a764d952269f3cb6fa417df8ddcde5371b4b From 6e3016952e0bb6a404848967fb0e27340360c920 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sat, 23 Apr 2022 20:19:05 -0400 Subject: [PATCH 48/83] Roll Engine from dbe5a764d952 to cf3445791f6d (1 revision) (#102448) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 56da0a4f2035a..ab09f4d7dd92b 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -dbe5a764d952269f3cb6fa417df8ddcde5371b4b +cf3445791f6dfe933de80dcd9b1a0f84507fa479 diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index af4e48006f4c2..d96abea865cb7 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -uetob3LZ0XpTHKVP2YC9_9qv7AGxeV4vzHZS97O3HuwC +evOcilNU5vxsBmRd76GJmsc242eCvpreR2laiQqcyWEC From 32ddd039a19d4170b9e12448d865c350f0d8bbe7 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sun, 24 Apr 2022 03:09:06 -0400 Subject: [PATCH 49/83] Roll Engine from cf3445791f6d to f23d31c4755e (1 revision) (#102456) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index ab09f4d7dd92b..9a022aeafe5b7 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -cf3445791f6dfe933de80dcd9b1a0f84507fa479 +f23d31c4755e011f09fbf10f9dfe36659177b405 diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index da77eae70092d..e28798ca88b3e 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -OOBEL73yb3wgbPPtZ_n599QLfJdr2snywov8_9Z39xUC +O69VeGryOb6EViFsMEkeU7N55-TySLesPbOiWxqYvt8C From 641d6cd0b7665fd06b4fe8da02716c9f077fb56c Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sun, 24 Apr 2022 07:44:06 -0400 Subject: [PATCH 50/83] Roll Engine from f23d31c4755e to 0a924011e2f0 (1 revision) (#102461) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 9a022aeafe5b7..080210ca44f48 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -f23d31c4755e011f09fbf10f9dfe36659177b405 +0a924011e2f0e164ee09c3cc788869f3ece56493 From c654d04f119f9ff742170967c773c180b63a8d5f Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sun, 24 Apr 2022 09:19:05 -0400 Subject: [PATCH 51/83] Roll Engine from 0a924011e2f0 to 984b5b332bb2 (1 revision) (#102463) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 080210ca44f48..4c37debd0ca07 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -0a924011e2f0e164ee09c3cc788869f3ece56493 +984b5b332bb2afe50bd9654fc5b2a444e1c40771 diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index d96abea865cb7..c746e0630cd3b 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -evOcilNU5vxsBmRd76GJmsc242eCvpreR2laiQqcyWEC +UrnPgfhOYsXIu2DdQqzbUvLhk4ndYXYWo5rC63CLH3sC From dca58a289b0e8d1e8d118a55123329fd2e9d04ff Mon Sep 17 00:00:00 2001 From: Alex Li Date: Mon, 25 Apr 2022 02:04:06 +0800 Subject: [PATCH 52/83] [gen_l10n] Throw a specified exception when the language code is invalid (#102431) --- .../localizations/localizations_utils.dart | 12 +++++-- .../generate_localizations_test.dart | 33 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/packages/flutter_tools/lib/src/localizations/localizations_utils.dart b/packages/flutter_tools/lib/src/localizations/localizations_utils.dart index 3f482cf69c955..a8e413526670e 100644 --- a/packages/flutter_tools/lib/src/localizations/localizations_utils.dart +++ b/packages/flutter_tools/lib/src/localizations/localizations_utils.dart @@ -7,6 +7,7 @@ import 'package:yaml/yaml.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; +import 'gen_l10n_types.dart'; import 'language_subtag_registry.dart'; typedef HeaderGenerator = String Function(String regenerateInstructions); @@ -215,8 +216,15 @@ void precacheLanguageAndRegionTags() { String describeLocale(String tag) { final List subtags = tag.split('_'); assert(subtags.isNotEmpty); - assert(_languages.containsKey(subtags[0])); - final String language = _languages[subtags[0]]!; + final String languageCode = subtags[0]; + if (!_languages.containsKey(languageCode)) { + throw L10nException( + '"$languageCode" is not a supported language code.\n' + 'See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry ' + 'for the supported list.', + ); + } + final String language = _languages[languageCode]!; String output = language; String? region; String? script; diff --git a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart index e850ca3fb4630..286c051d0f206 100644 --- a/packages/flutter_tools/test/general.shard/generate_localizations_test.dart +++ b/packages/flutter_tools/test/general.shard/generate_localizations_test.dart @@ -2595,6 +2595,39 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ); }); }); + + testWithoutContext('throws when the language code is not supported', () { + const String arbFileWithInvalidCode = ''' +{ + "@@locale": "invalid", + "title": "invalid" +}'''; + + final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') + ..createSync(recursive: true); + l10nDirectory.childFile('app_invalid.arb') + .writeAsStringSync(arbFileWithInvalidCode); + + expect( + () { + LocalizationsGenerator( + fileSystem: fs, + inputPathString: defaultL10nPathString, + outputPathString: defaultL10nPathString, + templateArbFileName: 'app_invalid.arb', + outputFileString: defaultOutputFileString, + classNameString: defaultClassNameString, + ) + ..loadResources() + ..writeOutputFiles(BufferLogger.test()); + }, + throwsA(isA().having( + (L10nException e) => e.message, + 'message', + contains('"invalid" is not a supported language code.'), + )), + ); + }); }); testWithoutContext('should generate a valid pubspec.yaml file when using synthetic package if it does not already exist', () { From 2a9aa79843b45af01e3bc852ed7641177e3d7f8e Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sun, 24 Apr 2022 16:29:06 -0400 Subject: [PATCH 53/83] Roll Engine from 984b5b332bb2 to e31251e55fd9 (1 revision) (#102470) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 4c37debd0ca07..be409a3a17c64 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -984b5b332bb2afe50bd9654fc5b2a444e1c40771 +e31251e55fd95607bd636dfced066ad74f22175d diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index e28798ca88b3e..b39c5f1d6d3e3 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -O69VeGryOb6EViFsMEkeU7N55-TySLesPbOiWxqYvt8C +u23mb8xy8Dxs6J3Quw5UvYpn2l2ixuKRmifIGYDg9acC From 399b866431c833374d0d6b2223a17cb02b784d76 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sun, 24 Apr 2022 22:24:06 -0400 Subject: [PATCH 54/83] Roll Engine from e31251e55fd9 to 3200b99d99f3 (1 revision) (#102475) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index be409a3a17c64..3a260f9ff8c79 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -e31251e55fd95607bd636dfced066ad74f22175d +3200b99d99f366f9b0b7805de61702622916dd30 diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index c746e0630cd3b..29d43f1b8b2df 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -UrnPgfhOYsXIu2DdQqzbUvLhk4ndYXYWo5rC63CLH3sC +ZRKEPPWM6cOHhhmKT45cICE7QDKDiSy7g6ieguBmk6sC From 4fec2ee0ed9849ad94bf89d7c560d188f3d01763 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Sun, 24 Apr 2022 23:29:06 -0400 Subject: [PATCH 55/83] Roll Engine from 3200b99d99f3 to 20b5b8604c3e (1 revision) (#102477) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 3a260f9ff8c79..1c2d56e0a3c29 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -3200b99d99f366f9b0b7805de61702622916dd30 +20b5b8604c3e3b860f89c320991f5bb7eabacd0a From ce3d1af64723a910c5d4f670235b4b20fa3e3e51 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 02:29:07 -0400 Subject: [PATCH 56/83] Roll Engine from 20b5b8604c3e to 93de17f347fe (1 revision) (#102480) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 1c2d56e0a3c29..e27338485f760 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -20b5b8604c3e3b860f89c320991f5bb7eabacd0a +93de17f347fec7ea92c6d410e5d6ce65e0de7903 From 8c22f5648a07b9e22230fce1183c9579e6674f17 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 05:34:07 -0400 Subject: [PATCH 57/83] Roll Engine from 93de17f347fe to 10efa195bf1c (2 revisions) (#102488) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index e27338485f760..6f888ca74c616 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -93de17f347fec7ea92c6d410e5d6ce65e0de7903 +10efa195bf1ceea25d2a5a377bbe54234787fdda From d69cff97cdbcceb7339be91e55e9123c9dea13ff Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 06:39:06 -0400 Subject: [PATCH 58/83] Roll Engine from 10efa195bf1c to c901936d4f6c (1 revision) (#102493) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 6f888ca74c616..5b24f0a4ff103 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -10efa195bf1ceea25d2a5a377bbe54234787fdda +c901936d4f6c882891cbb3b965aa4027269e7760 diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index b39c5f1d6d3e3..0d44851a49b42 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -u23mb8xy8Dxs6J3Quw5UvYpn2l2ixuKRmifIGYDg9acC +MbA1RtjV4CJorJFQIR2Ueo6zQWyA00GExqKIWj3bYcEC From e1ec377321e8043aa7c41505fcdc4fc05c2f239f Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 11:29:04 -0400 Subject: [PATCH 59/83] Roll Engine from c901936d4f6c to 5451e88a09c0 (1 revision) (#102509) --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 5b24f0a4ff103..0973af4a0d473 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -c901936d4f6c882891cbb3b965aa4027269e7760 +5451e88a09c006b3f4d33facc9e7daa99402a6ea diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index 29d43f1b8b2df..d4df5be730842 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -ZRKEPPWM6cOHhhmKT45cICE7QDKDiSy7g6ieguBmk6sC +JVNKiIJWP2nsg080g4dtv3nbXCEU_BKeBv23bgWC9IUC From e3e75ff909fb237282b0a4ee0d97e5c118fdad99 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 12:04:07 -0400 Subject: [PATCH 60/83] Roll Plugins from ca63d964d9fd to 4ff0157340ea (3 revisions) (#102511) --- bin/internal/flutter_plugins.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/flutter_plugins.version b/bin/internal/flutter_plugins.version index 8915d67171ac0..8fcea5085fea7 100644 --- a/bin/internal/flutter_plugins.version +++ b/bin/internal/flutter_plugins.version @@ -1 +1 @@ -ca63d964d9fdfff9be36533ea4248d0d0ca28fd0 +4ff0157340ea1874ca753bf921807e62c1943099 From f6feb8f8b6dc3e2771acda5fc38a4ef434d3af87 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 12:34:06 -0400 Subject: [PATCH 61/83] Roll Engine from 5451e88a09c0 to 966812846313 (2 revisions) (#102513) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 0973af4a0d473..e7fa1fb3e3b3f 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -5451e88a09c006b3f4d33facc9e7daa99402a6ea +966812846313c06b5371f777c7a53a38ed47f793 From 899548c48ae68eacadab3749ab9a0c46a1ffef93 Mon Sep 17 00:00:00 2001 From: wangying Date: Tue, 26 Apr 2022 01:04:07 +0800 Subject: [PATCH 62/83] Assign debugCreator for more layers (#101899) --- .../flutter/lib/src/rendering/proxy_box.dart | 29 +++++++- .../lib/src/rendering/proxy_sliver.dart | 4 + .../flutter/lib/src/widgets/color_filter.dart | 4 + .../flutter/lib/src/widgets/image_filter.dart | 5 +- packages/flutter/test/widgets/debug_test.dart | 74 ++++++++++++++++++- 5 files changed, 113 insertions(+), 3 deletions(-) diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index 32fb58e9433ba..2b62dafa78d2c 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -899,6 +899,10 @@ class RenderOpacity extends RenderProxyBox { } assert(needsCompositing); layer = context.pushOpacity(offset, _alpha, super.paint, oldLayer: layer as OpacityLayer?); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } } @@ -1006,6 +1010,10 @@ mixin RenderAnimatedOpacityMixin on RenderObjectWithChil } assert(needsCompositing); layer = context.pushOpacity(offset, _alpha!, super.paint, oldLayer: layer as OpacityLayer?); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } } @@ -1115,6 +1123,10 @@ class RenderShaderMask extends RenderProxyBox { ..maskRect = offset & size ..blendMode = _blendMode; context.pushLayer(layer!, super.paint, offset); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } else { layer = null; } @@ -1181,6 +1193,10 @@ class RenderBackdropFilter extends RenderProxyBox { layer!.filter = _filter; layer!.blendMode = _blendMode; context.pushLayer(layer!, super.paint, offset); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } else { layer = null; } @@ -2426,6 +2442,10 @@ class RenderTransform extends RenderProxyBox { layer = ImageFilterLayer(imageFilter: filter); } context.pushLayer(layer!, super.paint, offset); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } } } @@ -5212,7 +5232,10 @@ class RenderLeaderLayer extends RenderProxyBox { ..offset = offset; } context.pushLayer(layer!, super.paint, Offset.zero); - assert(layer != null); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } @override @@ -5424,6 +5447,10 @@ class RenderFollowerLayer extends RenderProxyBox { double.infinity, ), ); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } @override diff --git a/packages/flutter/lib/src/rendering/proxy_sliver.dart b/packages/flutter/lib/src/rendering/proxy_sliver.dart index 520e0d1bba2bc..3328aac677862 100644 --- a/packages/flutter/lib/src/rendering/proxy_sliver.dart +++ b/packages/flutter/lib/src/rendering/proxy_sliver.dart @@ -173,6 +173,10 @@ class RenderSliverOpacity extends RenderProxySliver { super.paint, oldLayer: layer as OpacityLayer?, ); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } } diff --git a/packages/flutter/lib/src/widgets/color_filter.dart b/packages/flutter/lib/src/widgets/color_filter.dart index b8d5c27367e1b..b604a908bf3ea 100644 --- a/packages/flutter/lib/src/widgets/color_filter.dart +++ b/packages/flutter/lib/src/widgets/color_filter.dart @@ -74,5 +74,9 @@ class _ColorFilterRenderObject extends RenderProxyBox { @override void paint(PaintingContext context, Offset offset) { layer = context.pushColorFilter(offset, colorFilter, super.paint, oldLayer: layer as ColorFilterLayer?); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } } diff --git a/packages/flutter/lib/src/widgets/image_filter.dart b/packages/flutter/lib/src/widgets/image_filter.dart index 8546ea969f015..935d401789ac1 100644 --- a/packages/flutter/lib/src/widgets/image_filter.dart +++ b/packages/flutter/lib/src/widgets/image_filter.dart @@ -73,6 +73,9 @@ class _ImageFilterRenderObject extends RenderProxyBox { filterLayer.imageFilter = imageFilter; } context.pushLayer(layer!, super.paint, offset); - assert(layer != null); + assert(() { + layer!.debugCreator = debugCreator; + return true; + }()); } } diff --git a/packages/flutter/test/widgets/debug_test.dart b/packages/flutter/test/widgets/debug_test.dart index 47e3cffabc95e..ce1eabb770fb9 100644 --- a/packages/flutter/test/widgets/debug_test.dart +++ b/packages/flutter/test/widgets/debug_test.dart @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:ui'; + import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -269,4 +271,74 @@ void main() { } debugHighlightDeprecatedWidgets = false; }); + + testWidgets('debugCreator of layers should not be null', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Stack( + children: [ + const ColorFiltered( + colorFilter: ColorFilter.mode(Color(0xFFFF0000), BlendMode.color), + child: Placeholder(), + ), + const Opacity( + opacity: 1.0, + child: Placeholder(), + ), + ImageFiltered( + imageFilter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), + child: const Placeholder(), + ), + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), + child: const Placeholder(), + ), + ShaderMask( + shaderCallback: (Rect bounds) => const RadialGradient( + radius: 0.05, + colors: [Color(0xFFFF0000), Color(0xFF00FF00)], + tileMode: TileMode.mirror, + ).createShader(bounds), + child: const Placeholder(), + ), + RangeSlider( + values: const RangeValues(0.3, 0.7), + onChanged: (RangeValues newValues) {}, + ), + CompositedTransformFollower( + link: LayerLink(), + ), + ], + ), + ), + ), + ), + ); + + RenderObject renderObject; + + renderObject = tester.firstRenderObject(find.byType(Opacity)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + + renderObject = tester.firstRenderObject(find.byType(ColorFiltered)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + + renderObject = tester.firstRenderObject(find.byType(ImageFiltered)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + + renderObject = tester.firstRenderObject(find.byType(BackdropFilter)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + + renderObject = tester.firstRenderObject(find.byType(ShaderMask)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + + renderObject = tester.firstRenderObject(find.byType(RangeSlider)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + + renderObject = tester.firstRenderObject(find.byType(CompositedTransformFollower)); + expect(renderObject.debugLayer?.debugCreator, isNotNull); + }); } From 46cb9ede2f02f03e2151fda38f2e47805f503590 Mon Sep 17 00:00:00 2001 From: Emmanuel Garcia Date: Mon, 25 Apr 2022 10:30:40 -0700 Subject: [PATCH 63/83] Reduce Gradle log level in verbose output (#102422) --- packages/flutter_tools/lib/src/android/gradle.dart | 4 ++-- .../general.shard/android/android_gradle_builder_test.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart index 19948c57b6384..d5caca41af480 100644 --- a/packages/flutter_tools/lib/src/android/gradle.dart +++ b/packages/flutter_tools/lib/src/android/gradle.dart @@ -269,7 +269,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ]; if (_logger.isVerbose) { command.add('--full-stacktrace'); - command.add('--debug'); + command.add('--info'); command.add('-Pverbose=true'); } else { command.add('-q'); @@ -593,7 +593,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ]; if (_logger.isVerbose) { command.add('--full-stacktrace'); - command.add('--debug'); + command.add('--info'); command.add('-Pverbose=true'); } else { command.add('-q'); diff --git a/packages/flutter_tools/test/general.shard/android/android_gradle_builder_test.dart b/packages/flutter_tools/test/general.shard/android/android_gradle_builder_test.dart index b0d0636bed699..bd90fa1730346 100644 --- a/packages/flutter_tools/test/general.shard/android/android_gradle_builder_test.dart +++ b/packages/flutter_tools/test/general.shard/android/android_gradle_builder_test.dart @@ -142,7 +142,7 @@ void main() { command: [ 'gradlew', '--full-stacktrace', - '--debug', + '--info', '-Pverbose=true', '-Ptarget-platform=android-arm,android-arm64,android-x64', '-Ptarget=lib/main.dart', @@ -782,7 +782,7 @@ void main() { '-Pis-plugin=false', '-PbuildNumber=1.0', '--full-stacktrace', - '--debug', + '--info', '-Pverbose=true', '-Pdart-obfuscation=false', '-Ptrack-widget-creation=false', From 7b580fd5df9442bd37e7327e35060a1efa6b2c68 Mon Sep 17 00:00:00 2001 From: Sai Sandeep Mutyala Date: Mon, 25 Apr 2022 23:14:07 +0530 Subject: [PATCH 64/83] Enable TestDefaultBinaryMessenger to intercept all platform channels. (#100049) --- .../src/test_default_binary_messenger.dart | 13 ++++++- .../test_default_binary_messenger_test.dart | 39 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/packages/flutter_test/lib/src/test_default_binary_messenger.dart b/packages/flutter_test/lib/src/test_default_binary_messenger.dart index ba227d6e40f71..0907209e7e616 100644 --- a/packages/flutter_test/lib/src/test_default_binary_messenger.dart +++ b/packages/flutter_test/lib/src/test_default_binary_messenger.dart @@ -8,6 +8,11 @@ import 'dart:ui' as ui; import 'package:fake_async/fake_async.dart'; import 'package:flutter/services.dart'; +/// A function which takes the name of the method channel, it's handler, +/// platform message and asynchronously returns an encoded response. +typedef AllMessagesHandler = Future? Function( + String channel, MessageHandler? handler, ByteData? message); + /// A [BinaryMessenger] subclass that is used as the default binary messenger /// under testing environment. /// @@ -116,11 +121,17 @@ class TestDefaultBinaryMessenger extends BinaryMessenger { // can implement the [checkMockMessageHandler] method. final Map _outboundHandlerIdentities = {}; + /// Handler that intercepts and responds to outgoing messages, pretending + /// to be the platform, for all channels. + AllMessagesHandler? allMessagesHandler; + @override Future? send(String channel, ByteData? message) { final Future? resultFuture; final MessageHandler? handler = _outboundHandlers[channel]; - if (handler != null) { + if (allMessagesHandler != null) { + resultFuture = allMessagesHandler!(channel, handler, message); + } else if (handler != null) { resultFuture = handler(message); } else { resultFuture = delegate.send(channel, message); diff --git a/packages/flutter_test/test/test_default_binary_messenger_test.dart b/packages/flutter_test/test/test_default_binary_messenger_test.dart index 5052882682f52..30ed9e686bd46 100644 --- a/packages/flutter_test/test/test_default_binary_messenger_test.dart +++ b/packages/flutter_test/test/test_default_binary_messenger_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:typed_data'; import 'dart:ui' as ui; import 'package:flutter/services.dart'; @@ -26,6 +27,19 @@ class TestDelegate extends BinaryMessenger { void setMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError(); } +class WorkingTestDelegate extends BinaryMessenger { + @override + Future? send(String channel, ByteData? message) async { + return ByteData.sublistView(Uint8List.fromList([1, 2, 3])); + } + + // Rest of the API isn't needed for this test. + @override + Future handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback) => throw UnimplementedError(); + @override + void setMessageHandler(String channel, MessageHandler? handler) => throw UnimplementedError(); +} + void main() { testWidgets('Caught exceptions are caught by the test framework', (WidgetTester tester) async { final BinaryMessenger delegate = TestDelegate(); @@ -39,4 +53,29 @@ void main() { expect(error, const RecognizableTestException()); } }); + + testWidgets('Mock MessageHandler is set correctly', + (WidgetTester tester) async { + final TestDefaultBinaryMessenger binaryMessenger = + TestDefaultBinaryMessenger(WorkingTestDelegate()); + binaryMessenger.setMockMessageHandler( + '', + (ByteData? message) async => + ByteData.sublistView(Uint8List.fromList([2, 3, 4]))); + + final ByteData? result = await binaryMessenger.send('', null); + expect(result?.buffer.asUint8List(), Uint8List.fromList([2, 3, 4])); + }); + + testWidgets('Mock AllMessagesHandler is set correctly', + (WidgetTester tester) async { + final TestDefaultBinaryMessenger binaryMessenger = + TestDefaultBinaryMessenger(WorkingTestDelegate()); + binaryMessenger.allMessagesHandler = + (String channel, MessageHandler? handler, ByteData? message) async => + ByteData.sublistView(Uint8List.fromList([2, 3, 4])); + + final ByteData? result = await binaryMessenger.send('', null); + expect(result?.buffer.asUint8List(), Uint8List.fromList([2, 3, 4])); + }); } From 0095feeadee672f8bf68cd75ad557921ae090ffe Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 13:49:07 -0400 Subject: [PATCH 65/83] Roll Engine from 966812846313 to c4184728a9ad (1 revision) (#102515) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index e7fa1fb3e3b3f..d76c58decd2a7 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -966812846313c06b5371f777c7a53a38ed47f793 +c4184728a9ad486ed900a705800db3f7d1e61215 From d46979648693f41a84b5e3011b9b81d519e8581b Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 14:54:06 -0400 Subject: [PATCH 66/83] Roll Engine from c4184728a9ad to f1bb8f421135 (1 revision) (#102519) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index d76c58decd2a7..ef891fb884d84 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -c4184728a9ad486ed900a705800db3f7d1e61215 +f1bb8f4211351cfdeb267cf4aba2bb57abdd3d77 From 3bd19f22970d7800ffc0ae0da2a8d7cc3877bc68 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 16:34:07 -0400 Subject: [PATCH 67/83] Roll Engine from f1bb8f421135 to 0f47c7a68811 (1 revision) (#102523) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index ef891fb884d84..8ff7d5ba428f2 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -f1bb8f4211351cfdeb267cf4aba2bb57abdd3d77 +0f47c7a68811f0436adf942fefb64a6e379a8371 From 558016455afea6613fd467fe4e50df45c063e852 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 25 Apr 2022 15:54:05 -0500 Subject: [PATCH 68/83] Re-land reverse case for AppBar scrolled under (#102343) --- .../flutter/lib/src/material/app_bar.dart | 34 +- .../widgets/scroll_notification_observer.dart | 32 +- .../flutter/test/material/app_bar_test.dart | 706 +++++++++++------- .../flutter/test/material/debug_test.dart | 1 + .../flutter/test/material/scaffold_test.dart | 1 + 5 files changed, 479 insertions(+), 295 deletions(-) diff --git a/packages/flutter/lib/src/material/app_bar.dart b/packages/flutter/lib/src/material/app_bar.dart index 39c7bd39c339c..045d9d8325ac4 100644 --- a/packages/flutter/lib/src/material/app_bar.dart +++ b/packages/flutter/lib/src/material/app_bar.dart @@ -767,17 +767,33 @@ class _AppBarState extends State { } void _handleScrollNotification(ScrollNotification notification) { - if (notification is ScrollUpdateNotification) { - final bool oldScrolledUnder = _scrolledUnder; - _scrolledUnder = notification.depth == 0 - && notification.metrics.extentBefore > 0 - && notification.metrics.axis == Axis.vertical; - if (_scrolledUnder != oldScrolledUnder) { - setState(() { - // React to a change in MaterialState.scrolledUnder - }); + final bool oldScrolledUnder = _scrolledUnder; + final ScrollMetrics metrics = notification.metrics; + + if (notification.depth != 0) { + _scrolledUnder = false; + } else { + switch (metrics.axisDirection) { + case AxisDirection.up: + // Scroll view is reversed + _scrolledUnder = metrics.extentAfter > 0; + break; + case AxisDirection.down: + _scrolledUnder = metrics.extentBefore > 0; + break; + case AxisDirection.right: + case AxisDirection.left: + // Scrolled under is only supported in the vertical axis. + _scrolledUnder = false; + break; } } + + if (_scrolledUnder != oldScrolledUnder) { + setState(() { + // React to a change in MaterialState.scrolledUnder + }); + } } Color _resolveColor(Set states, Color? widgetColor, Color? themeColor, Color defaultColor) { diff --git a/packages/flutter/lib/src/widgets/scroll_notification_observer.dart b/packages/flutter/lib/src/widgets/scroll_notification_observer.dart index bc151190f1d5d..6fa7ffaa15b7c 100644 --- a/packages/flutter/lib/src/widgets/scroll_notification_observer.dart +++ b/packages/flutter/lib/src/widgets/scroll_notification_observer.dart @@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart'; import 'framework.dart'; import 'notification_listener.dart'; import 'scroll_notification.dart'; +import 'scroll_position.dart'; /// A [ScrollNotification] listener for [ScrollNotificationObserver]. /// @@ -151,14 +152,26 @@ class ScrollNotificationObserverState extends State @override Widget build(BuildContext context) { - return NotificationListener( - onNotification: (ScrollNotification notification) { - _notifyListeners(notification); + // A ScrollMetricsNotification allows listeners to be notified for an + // initial state, as well as if the content dimensions change without + // scrolling. + return NotificationListener( + onNotification: (ScrollMetricsNotification notification) { + _notifyListeners(_ConvertedScrollMetricsNotification( + metrics: notification.metrics, + context: notification.context, + )); return false; }, - child: _ScrollNotificationObserverScope( - scrollNotificationObserverState: this, - child: widget.child, + child: NotificationListener( + onNotification: (ScrollNotification notification) { + _notifyListeners(notification); + return false; + }, + child: _ScrollNotificationObserverScope( + scrollNotificationObserverState: this, + child: widget.child, + ), ), ); } @@ -170,3 +183,10 @@ class ScrollNotificationObserverState extends State super.dispose(); } } + +class _ConvertedScrollMetricsNotification extends ScrollNotification { + _ConvertedScrollMetricsNotification({ + required super.metrics, + required super.context, + }); +} diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart index 88b6963f68aab..1b08520ea620f 100644 --- a/packages/flutter/test/material/app_bar_test.dart +++ b/packages/flutter/test/material/app_bar_test.dart @@ -2567,311 +2567,457 @@ void main() { expect(actionIconTheme.color, foregroundColor); }); - testWidgets('SliverAppBar.backgroundColor MaterialStateColor scrolledUnder', (WidgetTester tester) async { + group('MaterialStateColor scrolledUnder', () { const double collapsedHeight = kToolbarHeight; const double expandedHeight = 200.0; const Color scrolledColor = Color(0xff00ff00); const Color defaultColor = Color(0xff0000ff); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: CustomScrollView( - slivers: [ - SliverAppBar( - elevation: 0, - backgroundColor: MaterialStateColor.resolveWith((Set states) { - return states.contains(MaterialState.scrolledUnder) ? scrolledColor : defaultColor; - }), - expandedHeight: expandedHeight, - pinned: true, - ), - SliverList( - delegate: SliverChildListDelegate( - [ - Container(height: 1200.0, color: Colors.teal), - ], - ), - ), - ], - ), - ), - ), - ); - Finder findAppBarMaterial() { - return find.descendant(of: find.byType(AppBar), matching: find.byType(Material)); + return find.descendant(of: find.byType(AppBar), matching: find.byType(Material)).first; } - Color? getAppBarBackgroundColor() { + Color? getAppBarBackgroundColor(WidgetTester tester) { return tester.widget(findAppBarMaterial()).color; } - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); - - TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); - await gesture.moveBy(const Offset(0.0, -expandedHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), scrolledColor); - expect(tester.getSize(findAppBarMaterial()).height, collapsedHeight); - - gesture = await tester.startGesture(const Offset(50.0, 300.0)); - await gesture.moveBy(const Offset(0.0, expandedHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); - }); - - testWidgets('SliverAppBar.backgroundColor with FlexibleSpace MaterialStateColor scrolledUnder', (WidgetTester tester) async { - const double collapsedHeight = kToolbarHeight; - const double expandedHeight = 200.0; - const Color scrolledColor = Color(0xff00ff00); - const Color defaultColor = Color(0xff0000ff); - - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: CustomScrollView( - slivers: [ - SliverAppBar( - elevation: 0, - backgroundColor: MaterialStateColor.resolveWith((Set states) { - return states.contains(MaterialState.scrolledUnder) ? scrolledColor : defaultColor; - }), - expandedHeight: expandedHeight, - pinned: true, - flexibleSpace: const FlexibleSpaceBar( - title: Text('SliverAppBar'), + group('SliverAppBar', () { + Widget _buildSliverApp({ + required double contentHeight, + bool reverse = false, + bool includeFlexibleSpace = false, + }) { + return MaterialApp( + home: Scaffold( + body: CustomScrollView( + reverse: reverse, + slivers: [ + SliverAppBar( + elevation: 0, + backgroundColor: MaterialStateColor.resolveWith((Set states) { + return states.contains(MaterialState.scrolledUnder) + ? scrolledColor + : defaultColor; + }), + expandedHeight: expandedHeight, + pinned: true, + flexibleSpace: includeFlexibleSpace + ? const FlexibleSpaceBar(title: Text('SliverAppBar')) + : null, ), - ), - SliverList( - delegate: SliverChildListDelegate( + SliverList( + delegate: SliverChildListDelegate( [ - Container(height: 1200.0, color: Colors.teal), + Container(height: contentHeight, color: Colors.teal), ], + ), ), - ), - ], - ), - ), - ), - ); - - Finder findAppBarMaterial() { - // There are 2 Material widgets below AppBar. The second is only added if - // flexibleSpace is non-null. - return find.descendant(of: find.byType(AppBar), matching: find.byType(Material)).first; - } - - Color? getAppBarBackgroundColor() { - return tester.widget(findAppBarMaterial()).color; - } - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); - - TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); - await gesture.moveBy(const Offset(0.0, -expandedHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), scrolledColor); - expect(tester.getSize(findAppBarMaterial()).height, collapsedHeight); - - gesture = await tester.startGesture(const Offset(50.0, 300.0)); - await gesture.moveBy(const Offset(0.0, expandedHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); - }); - - testWidgets('AppBar.backgroundColor MaterialStateColor scrolledUnder', (WidgetTester tester) async { - const Color scrolledColor = Color(0xff00ff00); - const Color defaultColor = Color(0xff0000ff); - - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: MaterialStateColor.resolveWith((Set states) { - return states.contains(MaterialState.scrolledUnder) ? scrolledColor : defaultColor; - }), - title: const Text('AppBar'), - ), - body: ListView( - children: [ - Container(height: 1200.0, color: Colors.teal), - ], - ), - ), - ), - ); - - Finder findAppBarMaterial() { - return find.descendant(of: find.byType(AppBar), matching: find.byType(Material)); - } - - Color? getAppBarBackgroundColor() { - return tester.widget(findAppBarMaterial()).color; - } - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); - - TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); - await gesture.moveBy(const Offset(0.0, -kToolbarHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), scrolledColor); - expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); - - gesture = await tester.startGesture(const Offset(50.0, 300.0)); - await gesture.moveBy(const Offset(0.0, kToolbarHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); - }); - - testWidgets('AppBar.backgroundColor with FlexibleSpace MaterialStateColor scrolledUnder', (WidgetTester tester) async { - const Color scrolledColor = Color(0xff00ff00); - const Color defaultColor = Color(0xff0000ff); - - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: MaterialStateColor.resolveWith((Set states) { - return states.contains(MaterialState.scrolledUnder) ? scrolledColor : defaultColor; - }), - title: const Text('AppBar'), - flexibleSpace: const FlexibleSpaceBar( - title: Text('FlexibleSpace'), + ], ), ), - body: ListView( - children: [ - Container(height: 1200.0, color: Colors.teal), - ], - ), - ), - ), - ); - - Finder findAppBarMaterial() { - // There are 2 Material widgets below AppBar. The second is only added if - // flexibleSpace is non-null. - return find.descendant(of: find.byType(AppBar), matching: find.byType(Material)).first; - } - - Color? getAppBarBackgroundColor() { - return tester.widget(findAppBarMaterial()).color; - } - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); - - TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); - await gesture.moveBy(const Offset(0.0, -kToolbarHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), scrolledColor); - expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); - - gesture = await tester.startGesture(const Offset(50.0, 300.0)); - await gesture.moveBy(const Offset(0.0, kToolbarHeight)); - await gesture.up(); - await tester.pumpAndSettle(); - - expect(getAppBarBackgroundColor(), defaultColor); - expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); - }); + ); + } + + testWidgets('backgroundColor', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverApp(contentHeight: 1200.0) + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, -expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, collapsedHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + }); + + testWidgets('backgroundColor with FlexibleSpace', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverApp(contentHeight: 1200.0, includeFlexibleSpace: true) + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, -expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, collapsedHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + }); + + testWidgets('backgroundColor - reverse', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverApp(contentHeight: 1200.0, reverse: true) + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, collapsedHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, -expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + }); + + testWidgets('backgroundColor with FlexibleSpace - reverse', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverApp( + contentHeight: 1200.0, + reverse: true, + includeFlexibleSpace: true, + ) + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, collapsedHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, -expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + }); + + testWidgets('backgroundColor - not triggered in reverse for short content', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverApp(contentHeight: 200, reverse: true) + ); + + // In reverse, the content here is not long enough to scroll under the app + // bar. + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + + final TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + }); + + testWidgets('backgroundColor with FlexibleSpace - not triggered in reverse for short content', (WidgetTester tester) async { + await tester.pumpWidget( + _buildSliverApp( + contentHeight: 200, + reverse: true, + includeFlexibleSpace: true, + ) + ); + + // In reverse, the content here is not long enough to scroll under the app + // bar. + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + + final TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, expandedHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, expandedHeight); + }); + }); - testWidgets('AppBar._handleScrollNotification safely calls setState()', (WidgetTester tester) async { - // Regression test for failures found in Google internal issue b/185192049. - final ScrollController controller = ScrollController(initialScrollOffset: 400); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('AppBar'), - ), - body: Scrollbar( - isAlwaysShown: true, - controller: controller, - child: ListView( - controller: controller, + group('AppBar', () { + Widget _buildAppBar({ + required double contentHeight, + bool reverse = false, + bool includeFlexibleSpace = false + }) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + elevation: 0, + backgroundColor: MaterialStateColor.resolveWith((Set states) { + return states.contains(MaterialState.scrolledUnder) + ? scrolledColor + : defaultColor; + }), + title: const Text('AppBar'), + flexibleSpace: includeFlexibleSpace + ? const FlexibleSpaceBar(title: Text('FlexibleSpace')) + : null, + ), + body: ListView( + reverse: reverse, children: [ - Container(height: 1200.0, color: Colors.teal), + Container(height: contentHeight, color: Colors.teal), ], ), ), - ), - ), - ); - - expect(tester.takeException(), isNull); - }); - - testWidgets('AppBar scrolledUnder does not trigger on horizontal scroll', (WidgetTester tester) async { - const Color scrolledColor = Color(0xff00ff00); - const Color defaultColor = Color(0xff0000ff); - - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: MaterialStateColor.resolveWith((Set states) { - return states.contains(MaterialState.scrolledUnder) ? scrolledColor : defaultColor; - }), - title: const Text('AppBar'), - ), - body: ListView( - scrollDirection: Axis.horizontal, - children: [ - Container(height: 600.0, width: 1200.0, color: Colors.teal), - ], + ); + } + + testWidgets('backgroundColor', (WidgetTester tester) async { + await tester.pumpWidget( + _buildAppBar(contentHeight: 1200.0) + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, -kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + }); + + testWidgets('backgroundColor with FlexibleSpace', (WidgetTester tester) async { + await tester.pumpWidget( + _buildAppBar(contentHeight: 1200.0, includeFlexibleSpace: true) + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, -kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + }); + + testWidgets('backgroundColor - reverse', (WidgetTester tester) async { + await tester.pumpWidget( + _buildAppBar(contentHeight: 1200.0, reverse: true) + ); + await tester.pump(); + + // In this test case, the content always extends under the AppBar, so it + // should always be the scrolledColor. + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, -kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + }); + + testWidgets('backgroundColor with FlexibleSpace - reverse', (WidgetTester tester) async { + await tester.pumpWidget( + _buildAppBar( + contentHeight: 1200.0, + reverse: true, + includeFlexibleSpace: true, + ) + ); + await tester.pump(); + + // In this test case, the content always extends under the AppBar, so it + // should always be the scrolledColor. + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + gesture = await tester.startGesture(const Offset(50.0, 300.0)); + await gesture.moveBy(const Offset(0.0, -kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), scrolledColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + }); + + testWidgets('_handleScrollNotification safely calls setState()', (WidgetTester tester) async { + // Regression test for failures found in Google internal issue b/185192049. + final ScrollController controller = ScrollController(initialScrollOffset: 400); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('AppBar'), + ), + body: Scrollbar( + isAlwaysShown: true, + controller: controller, + child: ListView( + controller: controller, + children: [ + Container(height: 1200.0, color: Colors.teal), + ], + ), + ), + ), ), - ), - ), - ); - - Finder findAppBarMaterial() { - return find.descendant(of: find.byType(AppBar), matching: find.byType(Material)); - } - - Color? getAppBarBackgroundColor() { - return tester.widget(findAppBarMaterial()).color; - } - - expect(getAppBarBackgroundColor(), defaultColor); - - TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); - await gesture.moveBy(const Offset(-100.0, 0.0)); - await gesture.up(); - await tester.pumpAndSettle(); + ); - expect(getAppBarBackgroundColor(), defaultColor); - - gesture = await tester.startGesture(const Offset(50.0, 400.0)); - await gesture.moveBy(const Offset(100.0, 0.0)); - await gesture.up(); - await tester.pumpAndSettle(); + expect(tester.takeException(), isNull); + }); - expect(getAppBarBackgroundColor(), defaultColor); + testWidgets('does not trigger on horizontal scroll', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + appBar: AppBar( + elevation: 0, + backgroundColor: MaterialStateColor.resolveWith((Set states) { + return states.contains(MaterialState.scrolledUnder) + ? scrolledColor + : defaultColor; + }), + title: const Text('AppBar'), + ), + body: ListView( + scrollDirection: Axis.horizontal, + children: [ + Container(height: 600.0, width: 1200.0, color: Colors.teal), + ], + ), + ), + ), + ); + + expect(getAppBarBackgroundColor(tester), defaultColor); + + TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(-100.0, 0.0)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + + gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(100.0, 0.0)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + }); + + testWidgets('backgroundColor - not triggered in reverse for short content', (WidgetTester tester) async { + await tester.pumpWidget( + _buildAppBar( + contentHeight: 200.0, + reverse: true, + ) + ); + await tester.pump(); + + // In reverse, the content here is not long enough to scroll under the app + // bar. + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + final TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + }); + + testWidgets('backgroundColor with FlexibleSpace - not triggered in reverse for short content', (WidgetTester tester) async { + await tester.pumpWidget( + _buildAppBar( + contentHeight: 200.0, + reverse: true, + includeFlexibleSpace: true, + ) + ); + await tester.pump(); + + // In reverse, the content here is not long enough to scroll under the app + // bar. + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + + final TestGesture gesture = await tester.startGesture(const Offset(50.0, 400.0)); + await gesture.moveBy(const Offset(0.0, kToolbarHeight)); + await gesture.up(); + await tester.pumpAndSettle(); + + expect(getAppBarBackgroundColor(tester), defaultColor); + expect(tester.getSize(findAppBarMaterial()).height, kToolbarHeight); + }); + }); }); testWidgets('AppBar.preferredHeightFor', (WidgetTester tester) async { diff --git a/packages/flutter/test/material/debug_test.dart b/packages/flutter/test/material/debug_test.dart index 46f9e61b37fd9..21492e972bc01 100644 --- a/packages/flutter/test/material/debug_test.dart +++ b/packages/flutter/test/material/debug_test.dart @@ -349,6 +349,7 @@ void main() { ' Material\n' ' _ScrollNotificationObserverScope\n' ' NotificationListener\n' + ' NotificationListener\n' ' ScrollNotificationObserver\n' ' _ScaffoldScope\n' ' Scaffold-[LabeledGlobalKey#00000]\n' diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart index 3a10ba8c08fb3..7aeee33dc42ec 100644 --- a/packages/flutter/test/material/scaffold_test.dart +++ b/packages/flutter/test/material/scaffold_test.dart @@ -2339,6 +2339,7 @@ void main() { ' Material\n' ' _ScrollNotificationObserverScope\n' ' NotificationListener\n' + ' NotificationListener\n' ' ScrollNotificationObserver\n' ' _ScaffoldScope\n' ' Scaffold\n' From 4537391ac2b1c5d219d2a65580c716fbe8ccf7bb Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 17:44:07 -0400 Subject: [PATCH 69/83] Roll Engine from 0f47c7a68811 to 5fdfbe3010bb (1 revision) (#102526) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 8ff7d5ba428f2..ab406e980e26b 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -0f47c7a68811f0436adf942fefb64a6e379a8371 +5fdfbe3010bb55f163fc2f2d27f0ca914663e367 From 1c80e29b8e0a793ae582e8f4ccf7099c7f316d85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 15:29:08 -0700 Subject: [PATCH 70/83] Bump debian from bullseye-20220328-slim to bullseye-20220418-slim in /dev/ci/docker_linux (#102528) --- dev/ci/docker_linux/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/ci/docker_linux/Dockerfile b/dev/ci/docker_linux/Dockerfile index 9263abdbacc7c..d6a930ab5e00b 100644 --- a/dev/ci/docker_linux/Dockerfile +++ b/dev/ci/docker_linux/Dockerfile @@ -12,7 +12,7 @@ # Last manual update 2021-09-24 (changing this comment will re-build image) -FROM debian@sha256:78fd65998de7a59a001d792fe2d3a6d2ea25b6f3f068e5c84881250373577414 +FROM debian@sha256:f75d8a3ac10acdaa9be6052ea5f28bcfa56015ff02298831994bd3e6d66f7e57 MAINTAINER Flutter Developers RUN apt-get update -y && \ From 18713e0c5d44ed2e991e94595e1ff2900f97a7ef Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Mon, 25 Apr 2022 15:39:05 -0700 Subject: [PATCH 71/83] Made Directionality forego dependency tracking for better performance. (#102336) --- packages/flutter/lib/src/widgets/basic.dart | 59 ++++++++++++++++++- .../flutter/lib/src/widgets/framework.dart | 5 ++ .../flutter/test/widgets/framework_test.dart | 24 ++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index f565db3598e2e..0d6b956a6f962 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -80,12 +80,69 @@ export 'package:flutter/services.dart' show // BIDIRECTIONAL TEXT SUPPORT +/// An [InheritedElement] that has hundreds of dependencies but will +/// infrequently change. This provides a performance tradeoff where building +/// the [Widget]s is faster but performing updates is slower. +/// +/// | | _UbiquitiousInheritedElement | InheritedElement | +/// |---------------------|------------------------------|------------------| +/// | insert (best case) | O(1) | O(1) | +/// | insert (worst case) | O(1) | O(n) | +/// | search (best case) | O(n) | O(1) | +/// | search (worst case) | O(n) | O(n) | +/// +/// Insert happens when building the [Widget] tree, search happens when updating +/// [Widget]s. +class _UbiquitousInheritedElement extends InheritedElement { + /// Creates an element that uses the given widget as its configuration. + _UbiquitousInheritedElement(super.widget); + + @override + void setDependencies(Element dependent, Object? value) { + // This is where the cost of [InheritedElement] is incurred during build + // time of the widget tree. Omitting this bookkeeping is where the + // performance savings come from. + assert(value == null); + } + + @override + Object? getDependencies(Element dependent) { + return null; + } + + @override + void notifyClients(InheritedWidget oldWidget) { + _recurseChildren(this, (Element element) { + if (element.doesDependOnInheritedElement(this)) { + notifyDependent(oldWidget, element); + } + }); + } + + static void _recurseChildren(Element element, ElementVisitor visitor) { + element.visitChildren((Element child) { + _recurseChildren(child, visitor); + }); + visitor(element); + } +} + +/// See also: +/// +/// * [_UbiquitousInheritedElement], the [Element] for [_UbiquitousInheritedWidget]. +abstract class _UbiquitousInheritedWidget extends InheritedWidget { + const _UbiquitousInheritedWidget({super.key, required super.child}); + + @override + InheritedElement createElement() => _UbiquitousInheritedElement(this); +} + /// A widget that determines the ambient directionality of text and /// text-direction-sensitive render objects. /// /// For example, [Padding] depends on the [Directionality] to resolve /// [EdgeInsetsDirectional] objects into absolute [EdgeInsets] objects. -class Directionality extends InheritedWidget { +class Directionality extends _UbiquitousInheritedWidget { /// Creates a widget that determines the directionality of text and /// text-direction-sensitive render objects. /// diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 654c83f6a1181..cc42fc59f63df 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -4197,6 +4197,11 @@ abstract class Element extends DiagnosticableTree implements BuildContext { return true; } + /// Returns `true` if [dependOnInheritedElement] was previously called with [ancestor]. + @protected + bool doesDependOnInheritedElement(InheritedElement ancestor) => + _dependencies != null && _dependencies!.contains(ancestor); + @override InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect }) { assert(ancestor != null); diff --git a/packages/flutter/test/widgets/framework_test.dart b/packages/flutter/test/widgets/framework_test.dart index ca2a57fba2c25..b754a442863f6 100644 --- a/packages/flutter/test/widgets/framework_test.dart +++ b/packages/flutter/test/widgets/framework_test.dart @@ -1694,6 +1694,30 @@ The findRenderObject() method was called for the following element: expect(inheritedElement.hashCode, identityHashCode(inheritedElement)); }); + + testWidgets('doesDependOnInheritedElement', (WidgetTester tester) async { + final _TestInheritedElement ancestor = + _TestInheritedElement(const Directionality( + textDirection: TextDirection.ltr, + child: Placeholder(), + )); + final _TestInheritedElement child = + _TestInheritedElement(const Directionality( + textDirection: TextDirection.ltr, + child: Placeholder(), + )); + expect(child.doesDependOnInheritedElement(ancestor), isFalse); + child.dependOnInheritedElement(ancestor); + expect(child.doesDependOnInheritedElement(ancestor), isTrue); + }); +} + +class _TestInheritedElement extends InheritedElement { + _TestInheritedElement(super.widget); + @override + bool doesDependOnInheritedElement(InheritedElement element) { + return super.doesDependOnInheritedElement(element); + } } class _WidgetWithNoVisitChildren extends StatelessWidget { From 92bc78371beee9a788491ed5dfaf252e4635f186 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Mon, 25 Apr 2022 18:49:06 -0400 Subject: [PATCH 72/83] Roll Engine from 5fdfbe3010bb to 4df9cf27052b (1 revision) (#102529) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index ab406e980e26b..3648a52ab4f87 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -5fdfbe3010bb55f163fc2f2d27f0ca914663e367 +4df9cf27052bbb6c6acdeab17db1bac0bf79a372 From 0411a6f8a3bb6c44aaa69555984cc6e7112374a5 Mon Sep 17 00:00:00 2001 From: keyonghan <54558023+keyonghan@users.noreply.github.com> Date: Mon, 25 Apr 2022 16:14:03 -0700 Subject: [PATCH 73/83] Enable M1 mac/ios tests in prod as bringup: false (#102530) --- .ci.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.ci.yaml b/.ci.yaml index 41ec45cd947fa..47ecaac5d6fea 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -2447,7 +2447,6 @@ targets: - name: Mac_arm64_ios build_ios_framework_module_test recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3309,7 +3308,6 @@ targets: - name: Mac_arm64_ios flutter_gallery_ios__compile recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3349,7 +3347,6 @@ targets: - name: Mac_arm64_ios hello_world_ios__compile recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3372,7 +3369,6 @@ targets: - name: Mac_arm64_ios hot_mode_dev_cycle_macos_target__benchmark recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3455,7 +3451,6 @@ targets: - name: Mac_arm64_ios ios_app_with_extensions_test recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3476,7 +3471,6 @@ targets: - name: Mac_arm64_ios ios_content_validation_test recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3527,7 +3521,6 @@ targets: - name: Mac_arm64_ios macos_chrome_dev_mode recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3687,7 +3680,6 @@ targets: - name: Mac_arm64_ios native_ui_tests_ios recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > @@ -3736,7 +3728,6 @@ targets: - name: Mac_arm64_ios run_release_test_macos recipe: devicelab/devicelab_drone presubmit: false - bringup: true # https://github.com/flutter/flutter/issues/87508 timeout: 60 properties: tags: > From f15295cc91dfa1b9705d318edca27cf9605e1f73 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 25 Apr 2022 17:44:07 -0700 Subject: [PATCH 74/83] [framework] allow disabling image filter layer (#102085) --- .../flutter/lib/src/widgets/image_filter.dart | 46 +++++++++++++++++-- .../test/widgets/image_filter_test.dart | 21 +++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/packages/flutter/lib/src/widgets/image_filter.dart b/packages/flutter/lib/src/widgets/image_filter.dart index 935d401789ac1..67f9ae459fecc 100644 --- a/packages/flutter/lib/src/widgets/image_filter.dart +++ b/packages/flutter/lib/src/widgets/image_filter.dart @@ -11,6 +11,19 @@ import 'framework.dart'; /// Applies an [ImageFilter] to its child. /// +/// An image filter will always apply its filter operation to the child widget, +/// even if said filter is conceptually a "no-op", such as an ImageFilter.blur +/// with a radius of 0 or an ImageFilter.matrix with an identity matrix. Setting +/// [ImageFiltered.enabled] to `false` is a more efficient manner of disabling +/// an image filter. +/// +/// The framework does not attempt to optimize out "no-op" filters because it +/// cannot tell the difference between an intentional no-op and a filter that is +/// only incidentally a no-op. Consider an ImageFilter.matrix that is animated +/// and happens to pass through the identity matrix. If the framework identified it +/// as a no-op it would drop and then recreate the layer during the animation which +/// would be more expensive than keeping it around. +/// /// {@youtube 560 315 https://www.youtube.com/watch?v=7Lftorq4i2o} /// /// See also: @@ -27,17 +40,27 @@ class ImageFiltered extends SingleChildRenderObjectWidget { super.key, required this.imageFilter, super.child, + this.enabled = true, }) : assert(imageFilter != null); /// The image filter to apply to the child of this widget. final ImageFilter imageFilter; + /// Whether or not to apply the image filter opation to the child of this + /// widget. + /// + /// Prefer setting enabled to `false` instead of creating a "no-op" filter + /// type for performance reasons. + final bool enabled; + @override - RenderObject createRenderObject(BuildContext context) => _ImageFilterRenderObject(imageFilter); + RenderObject createRenderObject(BuildContext context) => _ImageFilterRenderObject(imageFilter, enabled); @override void updateRenderObject(BuildContext context, RenderObject renderObject) { - (renderObject as _ImageFilterRenderObject).imageFilter = imageFilter; + (renderObject as _ImageFilterRenderObject) + ..enabled = enabled + ..imageFilter = imageFilter; } @override @@ -48,7 +71,17 @@ class ImageFiltered extends SingleChildRenderObjectWidget { } class _ImageFilterRenderObject extends RenderProxyBox { - _ImageFilterRenderObject(this._imageFilter); + _ImageFilterRenderObject(this._imageFilter, this._enabled); + + bool get enabled => _enabled; + bool _enabled; + set enabled(bool value) { + if (enabled == value) { + return; + } + _enabled = value; + markNeedsPaint(); + } ImageFilter get imageFilter => _imageFilter; ImageFilter _imageFilter; @@ -61,11 +94,16 @@ class _ImageFilterRenderObject extends RenderProxyBox { } @override - bool get alwaysNeedsCompositing => child != null; + bool get alwaysNeedsCompositing => child != null && enabled; @override void paint(PaintingContext context, Offset offset) { assert(imageFilter != null); + if (!enabled) { + layer = null; + return super.paint(context, offset); + } + if (layer == null) { layer = ImageFilterLayer(imageFilter: imageFilter); } else { diff --git a/packages/flutter/test/widgets/image_filter_test.dart b/packages/flutter/test/widgets/image_filter_test.dart index 38d949860baa1..6395cb044edca 100644 --- a/packages/flutter/test/widgets/image_filter_test.dart +++ b/packages/flutter/test/widgets/image_filter_test.dart @@ -86,4 +86,25 @@ void main() { await pumpWithSigma(10.0); expect(renderObject.debugLayer, same(originalLayer)); }); + + testWidgets('Image filter - enabled and disabled', (WidgetTester tester) async { + Future pumpWithEnabledStaet(bool enabled) async { + await tester.pumpWidget( + RepaintBoundary( + child: ImageFiltered( + enabled: enabled, + imageFilter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: const Placeholder(), + ), + ), + ); + } + + await pumpWithEnabledStaet(false); + expect(tester.layers, isNot(contains(isA()))); + + + await pumpWithEnabledStaet(true); + expect(tester.layers, contains(isA())); + }); } From 63574cf76ab021877d14be5c39fb77ea8116bab4 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 25 Apr 2022 18:14:06 -0700 Subject: [PATCH 75/83] add benchmark for animated complex opacity (#102532) --- .ci.yaml | 11 ++++ TESTOWNERS | 1 + .../android/app/src/main/AndroidManifest.xml | 1 + .../macrobenchmarks/lib/common.dart | 1 + dev/benchmarks/macrobenchmarks/lib/main.dart | 9 +++ .../lib/src/animated_complex_opacity.dart | 59 +++++++++++++++++++ ...ted_complex_opacity_perf__e2e_summary.dart | 14 +++++ dev/devicelab/lib/tasks/perf_tests.dart | 7 +++ 8 files changed, 103 insertions(+) create mode 100644 dev/benchmarks/macrobenchmarks/lib/src/animated_complex_opacity.dart create mode 100644 dev/devicelab/bin/tasks/animated_complex_opacity_perf__e2e_summary.dart diff --git a/.ci.yaml b/.ci.yaml index 47ecaac5d6fea..8322c8c8b45d2 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -1453,6 +1453,17 @@ targets: task_name: animated_image_gc_perf scheduler: luci + - name: Linux_android animated_complex_opacity_perf__e2e_summary + recipe: devicelab/devicelab_drone + presubmit: false + bringup: true + timeout: 60 + properties: + tags: > + ["devicelab","android","linux"] + task_name: animated_complex_opacity_perf__e2e_summary + scheduler: luci + - name: Linux_android animated_placeholder_perf__e2e_summary recipe: devicelab/devicelab_drone presubmit: false diff --git a/TESTOWNERS b/TESTOWNERS index d48ef1a5494c3..9706dde1c5154 100644 --- a/TESTOWNERS +++ b/TESTOWNERS @@ -78,6 +78,7 @@ /dev/devicelab/bin/tasks/gradient_consistent_perf__e2e_summary.dart @flar @flutter/engine /dev/devicelab/bin/tasks/gradient_dynamic_perf__e2e_summary.dart @flar @flutter/engine /dev/devicelab/bin/tasks/gradient_static_perf__e2e_summary.dart @flar @flutter/engine +/dev/devicelab/bin/tasks/animated_complex_opacity_perf__e2e_summary.dart @jonahwilliams @flutter/engine ## Windows Android DeviceLab tests /dev/devicelab/bin/tasks/basic_material_app_win__compile.dart @zanderso @flutter/tool diff --git a/dev/benchmarks/macrobenchmarks/android/app/src/main/AndroidManifest.xml b/dev/benchmarks/macrobenchmarks/android/app/src/main/AndroidManifest.xml index c0f2c6be78295..6453a039057a8 100644 --- a/dev/benchmarks/macrobenchmarks/android/app/src/main/AndroidManifest.xml +++ b/dev/benchmarks/macrobenchmarks/android/app/src/main/AndroidManifest.xml @@ -21,6 +21,7 @@ found in the LICENSE file. --> android:label="macrobenchmarks" android:icon="@mipmap/ic_launcher"> const GradientPerfHomePage(), ...gradientPerfRoutes, + kAnimatedComplexOpacityPerfRouteName: (BuildContext context) => const AnimatedComplexOpacity(), }, ); } @@ -257,6 +259,13 @@ class HomePage extends StatelessWidget { Navigator.pushNamed(context, kGradientPerfRouteName); }, ), + ElevatedButton( + key: const Key(kAnimatedComplexOpacityPerfRouteName), + child: const Text('Animated complex opacity perf'), + onPressed: () { + Navigator.pushNamed(context, kAnimatedComplexOpacityPerfRouteName); + }, + ), ], ), ); diff --git a/dev/benchmarks/macrobenchmarks/lib/src/animated_complex_opacity.dart b/dev/benchmarks/macrobenchmarks/lib/src/animated_complex_opacity.dart new file mode 100644 index 0000000000000..90b2276e343bc --- /dev/null +++ b/dev/benchmarks/macrobenchmarks/lib/src/animated_complex_opacity.dart @@ -0,0 +1,59 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +// Various tests to verify that Aniamted opacity layers (i.e. FadeTransition) do not +// dirty children even without explicit repaint boundaries. These intentionally use +// text to ensure we don't measure the opacity peephole case. +class AnimatedComplexOpacity extends StatefulWidget { + const AnimatedComplexOpacity({ super.key }); + + @override + State createState() => _AnimatedComplexOpacityState(); +} + +class _AnimatedComplexOpacityState extends State with SingleTickerProviderStateMixin { + late final AnimationController controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 5000)); + late final Animation animation = controller.drive(Tween(begin: 0.0, end: 1.0)); + + @override + void initState() { + super.initState(); + controller.forward(from: 0.0); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + body: ListView( + children: [ + for (int i = 0; i < 20; i++) + FadeTransition(opacity: animation, child: Center( + child: Transform.scale(scale: 1.01, child: const ModeratelyComplexWidget()), + )) + ], + ), + ), + ); + } +} + +class ModeratelyComplexWidget extends StatelessWidget { + const ModeratelyComplexWidget({ super.key }); + + @override + Widget build(BuildContext context) { + return const Material( + elevation: 10, + clipBehavior: Clip.hardEdge, + child: ListTile( + leading: Icon(Icons.abc, size: 24), + title: DecoratedBox(decoration: BoxDecoration(color: Colors.red), child: Text('Hello World')), + trailing: FlutterLogo(), + ), + ); + } +} diff --git a/dev/devicelab/bin/tasks/animated_complex_opacity_perf__e2e_summary.dart b/dev/devicelab/bin/tasks/animated_complex_opacity_perf__e2e_summary.dart new file mode 100644 index 0000000000000..64f073714bde0 --- /dev/null +++ b/dev/devicelab/bin/tasks/animated_complex_opacity_perf__e2e_summary.dart @@ -0,0 +1,14 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter_devicelab/framework/devices.dart'; +import 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/tasks/perf_tests.dart'; + +Future main() async { + deviceOperatingSystem = DeviceOperatingSystem.android; + await task(createAnimatedComplexOpacityPerfE2ETest()); +} diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart index a004d8580d8d5..5618cc84613a7 100644 --- a/dev/devicelab/lib/tasks/perf_tests.dart +++ b/dev/devicelab/lib/tasks/perf_tests.dart @@ -577,6 +577,13 @@ TaskFunction createGradientStaticPerfE2ETest() { ).run; } +TaskFunction createAnimatedComplexOpacityPerfE2ETest() { + return PerfTest.e2e( + '${flutterDirectory.path}/dev/benchmarks/macrobenchmarks', + 'test/animated_complex_opacity_perf_e2e.dart', + ).run; +} + Map _average(List> results, int iterations) { final Map tally = {}; for (final Map item in results) { From 2381657394ae95d56bebf121759694d9a0ae258c Mon Sep 17 00:00:00 2001 From: xubaolin Date: Tue, 26 Apr 2022 09:24:07 +0800 Subject: [PATCH 76/83] Fix a `Slider` widget accessibility bug (#102129) --- .../lib/src/material/range_slider.dart | 9 ++- packages/flutter/lib/src/material/slider.dart | 5 +- .../test/material/range_slider_test.dart | 59 ++++++++++++++++++ .../flutter/test/material/slider_test.dart | 60 +++++++++++++++++++ 4 files changed, 126 insertions(+), 7 deletions(-) diff --git a/packages/flutter/lib/src/material/range_slider.dart b/packages/flutter/lib/src/material/range_slider.dart index eff3119b3e87b..bb86fde4859cf 100644 --- a/packages/flutter/lib/src/material/range_slider.dart +++ b/packages/flutter/lib/src/material/range_slider.dart @@ -285,7 +285,9 @@ class RangeSlider extends StatefulWidget { /// If null, the slider is continuous. final int? divisions; - /// Labels to show as text in the [SliderThemeData.rangeValueIndicatorShape]. + /// Labels to show as text in the [SliderThemeData.rangeValueIndicatorShape] + /// when the slider is active and [SliderThemeData.showValueIndicator] + /// is satisfied. /// /// There are two labels: one for the start thumb and one for the end thumb. /// @@ -1491,7 +1493,6 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix double value, double increasedValue, double decreasedValue, - String? label, VoidCallback increaseAction, VoidCallback decreaseAction, ) { @@ -1503,7 +1504,7 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix config.onIncrease = increaseAction; config.onDecrease = decreaseAction; } - config.label = label ?? ''; + if (semanticFormatterCallback != null) { config.value = semanticFormatterCallback!(_state._lerp(value)); config.increasedValue = semanticFormatterCallback!(_state._lerp(increasedValue)); @@ -1529,7 +1530,6 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix values.start, _increasedStartValue, _decreasedStartValue, - labels?.start, _increaseStartAction, _decreaseStartAction, ); @@ -1537,7 +1537,6 @@ class _RenderRangeSlider extends RenderBox with RelayoutWhenSystemFontsChangeMix values.end, _increasedEndValue, _decreasedEndValue, - labels?.end, _increaseEndAction, _decreaseEndAction, ); diff --git a/packages/flutter/lib/src/material/slider.dart b/packages/flutter/lib/src/material/slider.dart index 3110d05c3f5b6..5cb0ee675dc42 100644 --- a/packages/flutter/lib/src/material/slider.dart +++ b/packages/flutter/lib/src/material/slider.dart @@ -317,7 +317,8 @@ class Slider extends StatefulWidget { /// If null, the slider is continuous. final int? divisions; - /// A label to show above the slider when the slider is active. + /// A label to show above the slider when the slider is active and + /// [SliderThemeData.showValueIndicator] is satisfied. /// /// It is used to display the value of a discrete slider, and it is displayed /// as part of the value indicator shape. @@ -1506,7 +1507,7 @@ class _RenderSlider extends RenderBox with RelayoutWhenSystemFontsChangeMixin { config.onIncrease = increaseAction; config.onDecrease = decreaseAction; } - config.label = _label ?? ''; + if (semanticFormatterCallback != null) { config.value = semanticFormatterCallback!(_state._lerp(value)); config.increasedValue = semanticFormatterCallback!(_state._lerp((value + _semanticActionUnit).clamp(0.0, 1.0))); diff --git a/packages/flutter/test/material/range_slider_test.dart b/packages/flutter/test/material/range_slider_test.dart index 621c3da740c7c..6e8595bf0d87e 100644 --- a/packages/flutter/test/material/range_slider_test.dart +++ b/packages/flutter/test/material/range_slider_test.dart @@ -1681,6 +1681,65 @@ void main() { ); }); + // Regression test for https://github.com/flutter/flutter/issues/101868 + testWidgets('RangeSlider.label info should not write to semantic node', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + home: Theme( + data: ThemeData.light(), + child: Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: RangeSlider( + values: const RangeValues(10.0, 12.0), + max: 100.0, + onChanged: (RangeValues v) { }, + labels: const RangeLabels('Begin', 'End'), + ), + ), + ), + ), + ), + ); + + await tester.pumpAndSettle(); + + expect( + tester.getSemantics(find.byType(RangeSlider)), + matchesSemantics( + scopesRoute: true, + children:[ + matchesSemantics( + children: [ + matchesSemantics( + isEnabled: true, + isSlider: true, + hasEnabledState: true, + hasIncreaseAction: true, + hasDecreaseAction: true, + value: '10%', + increasedValue: '10%', + decreasedValue: '5%', + label: '' + ), + matchesSemantics( + isEnabled: true, + isSlider: true, + hasEnabledState: true, + hasIncreaseAction: true, + hasDecreaseAction: true, + value: '12%', + increasedValue: '17%', + decreasedValue: '12%', + label: '' + ), + ], + ), + ], + ), + ); + }); + testWidgets('Range Slider Semantics', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp( diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart index 354ddde960265..543831055c32f 100644 --- a/packages/flutter/test/material/slider_test.dart +++ b/packages/flutter/test/material/slider_test.dart @@ -1816,6 +1816,66 @@ void main() { semantics.dispose(); }); + // Regression test for https://github.com/flutter/flutter/issues/101868 + testWidgets('Slider.label info should not write to semantic node', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + + await tester.pumpWidget(MaterialApp( + home: Directionality( + textDirection: TextDirection.ltr, + child: Material( + child: Slider( + value: 40.0, + max: 200.0, + divisions: 10, + semanticFormatterCallback: (double value) => value.round().toString(), + onChanged: (double v) { }, + label: 'Bingo', + ), + ), + ), + )); + + expect( + semantics, + hasSemantics( + TestSemantics.root( + children: [ + TestSemantics( + id: 1, + textDirection: TextDirection.ltr, + children: [ + TestSemantics( + id: 2, + children: [ + TestSemantics( + id: 3, + flags: [SemanticsFlag.scopesRoute], + children: [ + TestSemantics( + id: 4, + flags: [SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider], + actions: [SemanticsAction.increase, SemanticsAction.decrease], + value: '40', + increasedValue: '60', + decreasedValue: '20', + textDirection: TextDirection.ltr, + ), + ], + ), + ], + ), + ], + ), + ], + ), + ignoreRect: true, + ignoreTransform: true, + ), + ); + semantics.dispose(); + }); + testWidgets('Slider is focusable and has correct focus color', (WidgetTester tester) async { final FocusNode focusNode = FocusNode(debugLabel: 'Slider'); tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional; From fa96ddd42789cf42ea1aa9c2f3635e32b505fd78 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 25 Apr 2022 21:39:07 -0700 Subject: [PATCH 77/83] add missing benchmark test file fromhttps://github.com/flutter/flutter/pull/102532 (#102544) --- .../test/animated_complex_opacity_perf_e2e.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 dev/benchmarks/macrobenchmarks/test/animated_complex_opacity_perf_e2e.dart diff --git a/dev/benchmarks/macrobenchmarks/test/animated_complex_opacity_perf_e2e.dart b/dev/benchmarks/macrobenchmarks/test/animated_complex_opacity_perf_e2e.dart new file mode 100644 index 0000000000000..cd6e4f92f5c77 --- /dev/null +++ b/dev/benchmarks/macrobenchmarks/test/animated_complex_opacity_perf_e2e.dart @@ -0,0 +1,16 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:macrobenchmarks/common.dart'; + +import 'util.dart'; + +void main() { + macroPerfTestE2E( + 'animated_complex_opacity_perf', + kAnimatedComplexOpacityPerfRouteName, + pageDelay: const Duration(seconds: 1), + duration: const Duration(seconds: 5), + ); +} From de6689aaa32ec32d738884850d0df6caab1290cf Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Tue, 26 Apr 2022 01:02:38 -0400 Subject: [PATCH 78/83] Roll Engine from 4df9cf27052b to 79152137a94c (8 revisions) (#102551) * b2ca1ce53 [web] Migrate Flutter Web to JS static interop - 14. (flutter/engine#32683) * d3886d6c5 Roll Fuchsia Linux SDK from MbA1RtjV4... to YyokSAVV4... (flutter/engine#32907) * 0aca7c0a1 Roll Skia from 4f33f5bef8eb to f8e52b27aa70 (4 revisions) (flutter/engine#32911) * ccf075470 Roll Skia from f8e52b27aa70 to 74742130b08d (2 revisions) (flutter/engine#32913) * a2d8df99e Roll Skia from 74742130b08d to 82146a7fcde2 (1 revision) (flutter/engine#32914) * 1e19613db Roll Fuchsia Mac SDK from JVNKiIJWP... to Jki3kG8_P... (flutter/engine#32916) * 65bc7e348 Roll Dart SDK from 865c2ff0940e to e89b629ed91d (1 revision) (flutter/engine#32917) * 79152137a Revert "[web] Migrate Flutter Web to JS static interop - 14. (#32683)" (flutter/engine#32919) * Add impellerc to conductor codesigning list * Update coductor codesigning for libtessellator.dylib Co-authored-by: Zachary Anderson --- bin/internal/engine.version | 2 +- bin/internal/fuchsia-linux.version | 2 +- bin/internal/fuchsia-mac.version | 2 +- dev/conductor/core/lib/src/codesign.dart | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 3648a52ab4f87..648830f1b1802 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -4df9cf27052bbb6c6acdeab17db1bac0bf79a372 +79152137a94cf2c0efd84d783531c8b3839593c3 diff --git a/bin/internal/fuchsia-linux.version b/bin/internal/fuchsia-linux.version index 0d44851a49b42..8fe2d423b387a 100644 --- a/bin/internal/fuchsia-linux.version +++ b/bin/internal/fuchsia-linux.version @@ -1 +1 @@ -MbA1RtjV4CJorJFQIR2Ueo6zQWyA00GExqKIWj3bYcEC +YyokSAVV4CDbCsZkAKj1Qiony-m4sjI-Pvwb1wX18ZkC diff --git a/bin/internal/fuchsia-mac.version b/bin/internal/fuchsia-mac.version index d4df5be730842..1bcedb32f599e 100644 --- a/bin/internal/fuchsia-mac.version +++ b/bin/internal/fuchsia-mac.version @@ -1 +1 @@ -JVNKiIJWP2nsg080g4dtv3nbXCEU_BKeBv23bgWC9IUC +Jki3kG8_PI7MxcaiJMq3S_hlIs_wVuqBMOWOnuEHaw0C diff --git a/dev/conductor/core/lib/src/codesign.dart b/dev/conductor/core/lib/src/codesign.dart index 271a5bcd1823c..32b3b7f0efe36 100644 --- a/dev/conductor/core/lib/src/codesign.dart +++ b/dev/conductor/core/lib/src/codesign.dart @@ -189,6 +189,8 @@ class CodesignCommand extends Command { 'artifacts/engine/darwin-x64-release/FlutterMacOS.framework/Versions/A/FlutterMacOS', 'artifacts/engine/darwin-x64/FlutterMacOS.framework/Versions/A/FlutterMacOS', 'artifacts/engine/darwin-x64/font-subset', + 'artifacts/engine/darwin-x64/impellerc', + 'artifacts/engine/darwin-x64/libtessellator.dylib', 'artifacts/engine/ios-profile/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter', 'artifacts/engine/ios-profile/Flutter.xcframework/ios-arm64_x86_64-simulator/Flutter.framework/Flutter', 'artifacts/engine/ios-release/Flutter.xcframework/ios-arm64/Flutter.framework/Flutter', From 719a3816b172adf3304878ecd14df0f38c03b4a8 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Tue, 26 Apr 2022 02:09:07 -0400 Subject: [PATCH 79/83] Roll Engine from 79152137a94c to df21738974e3 (1 revision) (#102553) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 648830f1b1802..5ebbd77102d6b 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -79152137a94cf2c0efd84d783531c8b3839593c3 +df21738974e335897a23a764b992b14a1fc13766 From c593903eee813d57d2a6138043d83dd6238d1244 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Tue, 26 Apr 2022 03:14:06 -0400 Subject: [PATCH 80/83] Roll Engine from df21738974e3 to 8aace64d19fc (1 revision) (#102555) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index 5ebbd77102d6b..b9b5db1343a2c 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -df21738974e335897a23a764b992b14a1fc13766 +8aace64d19fcf6330ceccdc6f4a2a2726064c47a From 646b910c9cefa394dd1e906444ed1cbb75255b08 Mon Sep 17 00:00:00 2001 From: engine-flutter-autoroll Date: Tue, 26 Apr 2022 05:14:04 -0400 Subject: [PATCH 81/83] Roll Engine from 8aace64d19fc to cd78221a88ae (1 revision) (#102562) --- bin/internal/engine.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/internal/engine.version b/bin/internal/engine.version index b9b5db1343a2c..d13baebf32373 100644 --- a/bin/internal/engine.version +++ b/bin/internal/engine.version @@ -1 +1 @@ -8aace64d19fcf6330ceccdc6f4a2a2726064c47a +cd78221a88ae704ae94323344cc793d6ecc20e9c From bc7d3bbc65b3786800d1a8ad137d80e1bd7e3fd7 Mon Sep 17 00:00:00 2001 From: Bruno Leroux Date: Tue, 26 Apr 2022 11:24:05 +0200 Subject: [PATCH 82/83] Fix DraggableScrollableController.animateTo leaks Ticker (#102504) --- .../src/widgets/draggable_scrollable_sheet.dart | 17 +++++++++++++++++ .../draggable_scrollable_sheet_test.dart | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart b/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart index 0ccae36798f3d..a53437444a3ca 100644 --- a/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart +++ b/packages/flutter/lib/src/widgets/draggable_scrollable_sheet.dart @@ -52,6 +52,7 @@ typedef ScrollableWidgetBuilder = Widget Function( /// constraints provided to an attached sheet change. class DraggableScrollableController extends ChangeNotifier { _DraggableScrollableSheetScrollController? _attachedController; + final Set _animationControllers = {}; /// Get the current size (as a fraction of the parent height) of the attached sheet. double get size { @@ -115,6 +116,7 @@ class DraggableScrollableController extends ChangeNotifier { vsync: _attachedController!.position.context.vsync, value: _attachedController!.extent.currentSize, ); + _animationControllers.add(animationController); _attachedController!.position.goIdle(); // This disables any snapping until the next user interaction with the sheet. _attachedController!.extent.hasDragged = false; @@ -175,6 +177,7 @@ class DraggableScrollableController extends ChangeNotifier { assert(_attachedController == null, 'Draggable scrollable controller is already attached to a sheet.'); _attachedController = scrollController; _attachedController!.extent._currentSize.addListener(notifyListeners); + _attachedController!.onPositionDetached = _disposeAnimationControllers; } void _onExtentReplaced(_DraggableSheetExtent previousExtent) { @@ -193,6 +196,13 @@ class DraggableScrollableController extends ChangeNotifier { _attachedController?.extent._currentSize.removeListener(notifyListeners); _attachedController = null; } + + void _disposeAnimationControllers() { + for (final AnimationController animationController in _animationControllers) { + animationController.dispose(); + } + _animationControllers.clear(); + } } /// A container for a [Scrollable] that responds to drag gestures by resizing @@ -724,6 +734,7 @@ class _DraggableScrollableSheetScrollController extends ScrollController { }) : assert(extent != null); _DraggableSheetExtent extent; + VoidCallback? onPositionDetached; @override _DraggableScrollableSheetScrollPosition createScrollPosition( @@ -764,6 +775,12 @@ class _DraggableScrollableSheetScrollController extends ScrollController { } extent.updateSize(extent.initialSize, position.context.notificationContext!); } + + @override + void detach(ScrollPosition position) { + onPositionDetached?.call(); + super.detach(position); + } } /// A scroll position that manages scroll activities for diff --git a/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart b/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart index bfd65190b9dc9..28375d25328c2 100644 --- a/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart +++ b/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart @@ -1209,4 +1209,19 @@ void main() { expect(controller.isAttached, true); expect(controller.size, isNotNull); }); + + testWidgets('DraggableScrollableController.animateTo should not leak Ticker', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/102483 + final DraggableScrollableController controller = DraggableScrollableController(); + await tester.pumpWidget(_boilerplate(() {}, controller: controller)); + + controller.animateTo(0.0, curve: Curves.linear, duration: const Duration(milliseconds: 200)); + await tester.pump(); + + // Dispose the DraggableScrollableSheet + await tester.pumpWidget(const SizedBox.shrink()); + // Controller should be detached and no exception should be thrown + expect(controller.isAttached, false); + expect(tester.takeException(), isNull); + }); } From 34d84209cf7ece5fb82ac6a114f86a2291754824 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Tue, 26 Apr 2022 08:44:09 -0700 Subject: [PATCH 83/83] Avoid scheduling a forced frame when there is no child to the renderView (#102556) --- .../flutter/lib/src/rendering/binding.dart | 5 ++++- .../flutter/test/rendering/binding_test.dart | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 packages/flutter/test/rendering/binding_test.dart diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart index 2e59a4055faf2..ed1a0e28f5dd0 100644 --- a/packages/flutter/lib/src/rendering/binding.dart +++ b/packages/flutter/lib/src/rendering/binding.dart @@ -235,10 +235,13 @@ mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, Gesture /// /// See [dart:ui.PlatformDispatcher.onMetricsChanged]. @protected + @visibleForTesting void handleMetricsChanged() { assert(renderView != null); renderView.configuration = createViewConfiguration(); - scheduleForcedFrame(); + if (renderView.child != null) { + scheduleForcedFrame(); + } } /// Called when the platform text scale factor changes. diff --git a/packages/flutter/test/rendering/binding_test.dart b/packages/flutter/test/rendering/binding_test.dart new file mode 100644 index 0000000000000..c10df12b05f41 --- /dev/null +++ b/packages/flutter/test/rendering/binding_test.dart @@ -0,0 +1,22 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/rendering.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + + test('handleMetricsChanged does not scheduleForcedFrame unless there is a child to the renderView', () async { + expect(SchedulerBinding.instance.hasScheduledFrame, false); + RendererBinding.instance.handleMetricsChanged(); + expect(SchedulerBinding.instance.hasScheduledFrame, false); + + RendererBinding.instance.renderView.child = RenderLimitedBox(); + RendererBinding.instance.handleMetricsChanged(); + expect(SchedulerBinding.instance.hasScheduledFrame, true); + }); +}