Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fcde2c8

Browse files
christopherfujinomdebbarchunhtaiPiinks
authored
[flutter_releases] Flutter beta 2.5.0-5.3.pre Engine Cherrypicks (#28415)
* 'Update Dart SDK to aa7d19d' * [web] Don't reset history on hot restart (#27872) * Makes scrollable to use main screen if the flutter view is not attached to a screen (#28110) * Fix regression in system UI colors (#28206) * update licenses golden Co-authored-by: Mouad Debbar <[email protected]> Co-authored-by: chunhtai <[email protected]> Co-authored-by: Kate Lovett <[email protected]>
1 parent 7a4c450 commit fcde2c8

File tree

9 files changed

+221
-47
lines changed

9 files changed

+221
-47
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ vars = {
3535
# Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
3636
# You can use //tools/dart/create_updated_flutter_deps.py to produce
3737
# updated revision list of existing dependencies.
38-
'dart_revision': '9a1827339c8e4e55a9b214d033aeba7d30daa28f',
38+
'dart_revision': 'aa7d19d185583b221093ad7385cf91fca3e8779c',
3939

4040
# WARNING: DO NOT EDIT MANUALLY
4141
# The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py

ci/licenses_golden/licenses_third_party

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Signature: 762dc8deadc282521ea04cfc1f0973e9
1+
Signature: 988f1584a445473114bc2516f591f26b
22

33
UNUSED LICENSES:
44

lib/web_ui/lib/src/engine/navigation/history.dart

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ import '../services/message_codec.dart';
1111
import '../services/message_codecs.dart';
1212
import 'url_strategy.dart';
1313

14+
/// Infers the history mode from the existing browser history state, then
15+
/// creates the appropriate instance of [BrowserHistory] for it.
16+
///
17+
/// If it can't infer, it creates a [MultiEntriesBrowserHistory] by default.
18+
BrowserHistory createHistoryForExistingState(UrlStrategy? urlStrategy) {
19+
if (urlStrategy != null) {
20+
final Object? state = urlStrategy.getState();
21+
if (SingleEntryBrowserHistory._isOriginEntry(state) || SingleEntryBrowserHistory._isFlutterEntry(state)) {
22+
return SingleEntryBrowserHistory(urlStrategy: urlStrategy);
23+
}
24+
}
25+
return MultiEntriesBrowserHistory(urlStrategy: urlStrategy);
26+
}
27+
1428
/// An abstract class that provides the API for [EngineWindow] to delegate its
1529
/// navigating events.
1630
///
@@ -263,14 +277,14 @@ class SingleEntryBrowserHistory extends BrowserHistory {
263277

264278
/// The origin entry is the history entry that the Flutter app landed on. It's
265279
/// created by the browser when the user navigates to the url of the app.
266-
bool _isOriginEntry(Object? state) {
280+
static bool _isOriginEntry(Object? state) {
267281
return state is Map && state[_kOriginTag] == true;
268282
}
269283

270284
/// The flutter entry is a history entry that we maintain on top of the origin
271285
/// entry. It allows us to catch popstate events when the user hits the back
272286
/// button.
273-
bool _isFlutterEntry(Object? state) {
287+
static bool _isFlutterEntry(Object? state) {
274288
return state is Map && state[_kFlutterTag] == true;
275289
}
276290

lib/web_ui/lib/src/engine/window.dart

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import 'package:js/js.dart';
1313
import 'package:meta/meta.dart';
1414
import 'package:ui/ui.dart' as ui;
1515

16-
import '../engine.dart' show registerHotRestartListener;
1716
import 'browser_detection.dart';
1817
import 'navigation/history.dart';
1918
import 'navigation/js_url_strategy.dart';
@@ -49,12 +48,8 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
4948
engineDispatcher.windows[_windowId] = this;
5049
engineDispatcher.windowConfigurations[_windowId] = const ui.ViewConfiguration();
5150
if (_isUrlStrategySet) {
52-
_browserHistory =
53-
MultiEntriesBrowserHistory(urlStrategy: _customUrlStrategy);
51+
_browserHistory = createHistoryForExistingState(_customUrlStrategy);
5452
}
55-
registerHotRestartListener(() {
56-
window.resetHistory();
57-
});
5853
}
5954

6055
final Object _windowId;
@@ -66,7 +61,7 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
6661
/// button, etc.
6762
BrowserHistory get browserHistory {
6863
return _browserHistory ??=
69-
MultiEntriesBrowserHistory(urlStrategy: _urlStrategyForInitialization);
64+
createHistoryForExistingState(_urlStrategyForInitialization);
7065
}
7166

7267
UrlStrategy? get _urlStrategyForInitialization {
@@ -81,32 +76,50 @@ class EngineFlutterWindow extends ui.SingletonFlutterWindow {
8176
_browserHistory; // Must be either SingleEntryBrowserHistory or MultiEntriesBrowserHistory.
8277

8378
Future<void> _useSingleEntryBrowserHistory() async {
79+
// Recreate the browser history mode that's appropriate for the existing
80+
// history state.
81+
//
82+
// If it happens to be a single-entry one, then there's nothing further to do.
83+
//
84+
// But if it's a multi-entry one, it will be torn down below and replaced
85+
// with a single-entry history.
86+
//
87+
// See: https://github.com/flutter/flutter/issues/79241
88+
_browserHistory ??=
89+
createHistoryForExistingState(_urlStrategyForInitialization);
90+
8491
if (_browserHistory is SingleEntryBrowserHistory) {
8592
return;
8693
}
8794

88-
final UrlStrategy? strategy;
89-
if (_browserHistory == null) {
90-
strategy = _urlStrategyForInitialization;
91-
} else {
92-
strategy = _browserHistory?.urlStrategy;
93-
await _browserHistory?.tearDown();
94-
}
95+
// At this point, we know that `_browserHistory` is a non-null
96+
// `MultiEntriesBrowserHistory` instance.
97+
final UrlStrategy? strategy = _browserHistory?.urlStrategy;
98+
await _browserHistory?.tearDown();
9599
_browserHistory = SingleEntryBrowserHistory(urlStrategy: strategy);
96100
}
97101

98102
Future<void> _useMultiEntryBrowserHistory() async {
103+
// Recreate the browser history mode that's appropriate for the existing
104+
// history state.
105+
//
106+
// If it happens to be a multi-entry one, then there's nothing further to do.
107+
//
108+
// But if it's a single-entry one, it will be torn down below and replaced
109+
// with a multi-entry history.
110+
//
111+
// See: https://github.com/flutter/flutter/issues/79241
112+
_browserHistory ??=
113+
createHistoryForExistingState(_urlStrategyForInitialization);
114+
99115
if (_browserHistory is MultiEntriesBrowserHistory) {
100116
return;
101117
}
102118

103-
final UrlStrategy? strategy;
104-
if (_browserHistory == null) {
105-
strategy = _urlStrategyForInitialization;
106-
} else {
107-
strategy = _browserHistory?.urlStrategy;
108-
await _browserHistory?.tearDown();
109-
}
119+
// At this point, we know that `_browserHistory` is a non-null
120+
// `SingleEntryBrowserHistory` instance.
121+
final UrlStrategy? strategy = _browserHistory?.urlStrategy;
122+
await _browserHistory?.tearDown();
110123
_browserHistory = MultiEntriesBrowserHistory(urlStrategy: strategy);
111124
}
112125

lib/web_ui/test/engine/history_test.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,50 @@ void main() {
3939
}
4040

4141
void testMain() {
42+
test('createHistoryForExistingState', () {
43+
TestUrlStrategy strategy;
44+
BrowserHistory history;
45+
46+
// No url strategy.
47+
history = createHistoryForExistingState(null);
48+
expect(history, isA<MultiEntriesBrowserHistory>());
49+
expect(history.urlStrategy, isNull);
50+
51+
// Random history state.
52+
strategy = TestUrlStrategy.fromEntry(
53+
const TestHistoryEntry(<dynamic, dynamic>{'foo': 123}, null, '/'),
54+
);
55+
history = createHistoryForExistingState(strategy);
56+
expect(history, isA<MultiEntriesBrowserHistory>());
57+
expect(history.urlStrategy, strategy);
58+
59+
// Multi-entry history state.
60+
final Map<dynamic, dynamic> state = <dynamic, dynamic>{
61+
'serialCount': 1,
62+
'state': <dynamic, dynamic>{'foo': 123},
63+
};
64+
strategy = TestUrlStrategy.fromEntry(TestHistoryEntry(state, null, '/'));
65+
history = createHistoryForExistingState(strategy);
66+
expect(history, isA<MultiEntriesBrowserHistory>());
67+
expect(history.urlStrategy, strategy);
68+
69+
// Single-entry history "origin" state.
70+
strategy = TestUrlStrategy.fromEntry(
71+
const TestHistoryEntry(<dynamic, dynamic>{'origin': true}, null, '/'),
72+
);
73+
history = createHistoryForExistingState(strategy);
74+
expect(history, isA<SingleEntryBrowserHistory>());
75+
expect(history.urlStrategy, strategy);
76+
77+
// Single-entry history "flutter" state.
78+
strategy = TestUrlStrategy.fromEntry(
79+
const TestHistoryEntry(<dynamic, dynamic>{'flutter': true}, null, '/'),
80+
);
81+
history = createHistoryForExistingState(strategy);
82+
expect(history, isA<SingleEntryBrowserHistory>());
83+
expect(history.urlStrategy, strategy);
84+
});
85+
4286
group('$SingleEntryBrowserHistory', () {
4387
final PlatformMessagesSpy spy = PlatformMessagesSpy();
4488

shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -374,15 +374,17 @@ private void setSystemChromeSystemUIOverlayStyle(
374374
// If transparent, SDK 29 and higher may apply a translucent scrim behind the bar to ensure
375375
// proper contrast. This can be overridden with
376376
// SystemChromeStyle.systemStatusBarContrastEnforced.
377-
if (systemChromeStyle.statusBarIconBrightness != null && Build.VERSION.SDK_INT >= 23) {
378-
switch (systemChromeStyle.statusBarIconBrightness) {
379-
case DARK:
380-
// View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
381-
flags |= 0x2000;
382-
break;
383-
case LIGHT:
384-
flags &= ~0x2000;
385-
break;
377+
if (Build.VERSION.SDK_INT >= 23) {
378+
if (systemChromeStyle.statusBarIconBrightness != null) {
379+
switch (systemChromeStyle.statusBarIconBrightness) {
380+
case DARK:
381+
// View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
382+
flags |= 0x2000;
383+
break;
384+
case LIGHT:
385+
flags &= ~0x2000;
386+
break;
387+
}
386388
}
387389

388390
if (systemChromeStyle.statusBarColor != null) {
@@ -403,16 +405,17 @@ private void setSystemChromeSystemUIOverlayStyle(
403405
// If transparent, SDK 29 and higher may apply a translucent scrim behind 2/3 button navigation
404406
// bars to ensure proper contrast. This can be overridden with
405407
// SystemChromeStyle.systemNavigationBarContrastEnforced.
406-
if (systemChromeStyle.systemNavigationBarIconBrightness != null
407-
&& Build.VERSION.SDK_INT >= 26) {
408-
switch (systemChromeStyle.systemNavigationBarIconBrightness) {
409-
case DARK:
410-
// View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
411-
flags |= 0x10;
412-
break;
413-
case LIGHT:
414-
flags &= ~0x10;
415-
break;
408+
if (Build.VERSION.SDK_INT >= 26) {
409+
if (systemChromeStyle.systemNavigationBarIconBrightness != null) {
410+
switch (systemChromeStyle.systemNavigationBarIconBrightness) {
411+
case DARK:
412+
// View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
413+
flags |= 0x10;
414+
break;
415+
case LIGHT:
416+
flags &= ~0x10;
417+
break;
418+
}
416419
}
417420

418421
if (systemChromeStyle.systemNavigationBarColor != null) {

shell/platform/android/test/io/flutter/plugin/platform/PlatformPluginTest.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,41 @@ public void setNavigationBarDividerColor() {
162162
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
163163
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
164164
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
165+
// Default style test
165166
SystemChromeStyle style =
166-
new SystemChromeStyle(0XFF000000, null, true, 0XFFC70039, null, 0XFF006DB3, true);
167+
new SystemChromeStyle(
168+
0XFF000000, // statusBarColor
169+
null, // statusBarIconBrightness
170+
true, // systemStatusBarContrastEnforced
171+
0XFFC70039, // systemNavigationBarColor
172+
null, // systemNavigationBarIconBrightness
173+
0XFF006DB3, // systemNavigationBarDividerColor
174+
true); // systemNavigationBarContrastEnforced
167175

168176
if (Build.VERSION.SDK_INT >= 28) {
169177
platformPlugin.mPlatformMessageHandler.setSystemUiOverlayStyle(style);
170178

179+
assertEquals(0XFF000000, fakeActivity.getWindow().getStatusBarColor());
180+
assertEquals(0XFFC70039, fakeActivity.getWindow().getNavigationBarColor());
171181
assertEquals(0XFF006DB3, fakeActivity.getWindow().getNavigationBarDividerColor());
182+
183+
// Regression test for https://github.com/flutter/flutter/issues/88431
184+
// A null brightness should not affect changing color settings.
185+
style =
186+
new SystemChromeStyle(
187+
0XFF006DB3, // statusBarColor
188+
null, // statusBarIconBrightness
189+
true, // systemStatusBarContrastEnforced
190+
0XFF000000, // systemNavigationBarColor
191+
null, // systemNavigationBarIconBrightness
192+
0XFF006DB3, // systemNavigationBarDividerColor
193+
true); // systemNavigationBarContrastEnforced
194+
195+
platformPlugin.mPlatformMessageHandler.setSystemUiOverlayStyle(style);
196+
172197
assertEquals(0XFFC70039, fakeActivity.getWindow().getStatusBarColor());
173198
assertEquals(0XFF000000, fakeActivity.getWindow().getNavigationBarColor());
199+
assertEquals(0XFF006DB3, fakeActivity.getWindow().getNavigationBarDividerColor());
174200
}
175201
}
176202

shell/platform/darwin/ios/framework/Source/SemanticsObject.mm

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ CGPoint ConvertPointToGlobal(SemanticsObject* reference, CGPoint local_point) {
5454
// `rect` is in the physical pixel coordinate system. iOS expects the accessibility frame in
5555
// the logical pixel coordinate system. Therefore, we divide by the `scale` (pixel ratio) to
5656
// convert.
57-
CGFloat scale = [[[reference bridge]->view() window] screen].scale;
57+
UIScreen* screen = [[[reference bridge]->view() window] screen];
58+
// Screen can be nil if the FlutterView is covered by another native view.
59+
CGFloat scale = screen == nil ? [UIScreen mainScreen].scale : screen.scale;
5860
auto result = CGPointMake(point.x() / scale, point.y() / scale);
5961
return [[reference bridge]->view() convertPoint:result toView:nil];
6062
}
@@ -80,7 +82,9 @@ CGRect ConvertRectToGlobal(SemanticsObject* reference, CGRect local_rect) {
8082
// `rect` is in the physical pixel coordinate system. iOS expects the accessibility frame in
8183
// the logical pixel coordinate system. Therefore, we divide by the `scale` (pixel ratio) to
8284
// convert.
83-
CGFloat scale = [[[reference bridge]->view() window] screen].scale;
85+
UIScreen* screen = [[[reference bridge]->view() window] screen];
86+
// Screen can be nil if the FlutterView is covered by another native view.
87+
CGFloat scale = screen == nil ? [UIScreen mainScreen].scale : screen.scale;
8488
auto result =
8589
CGRectMake(rect.x() / scale, rect.y() / scale, rect.width() / scale, rect.height() / scale);
8690
return UIAccessibilityConvertFrameToScreenCoordinates(result, [reference bridge]->view());

0 commit comments

Comments
 (0)