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

Commit fe6e3a1

Browse files
committed
Merge changes
1 parent 88d0137 commit fe6e3a1

File tree

4 files changed

+63
-31
lines changed

4 files changed

+63
-31
lines changed

lib/ui/platform_dispatcher.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ class PlatformDispatcher {
255255
///
256256
/// The framework invokes [callback] in the same zone in which this method
257257
/// was called.
258-
void sendPlatformMessage(String name, ByteData data, PlatformMessageResponseCallback callback) {
258+
void sendPlatformMessage(String/*!*/ name, ByteData/*?*/ data, PlatformMessageResponseCallback/*?*/ callback) {
259259
final String error =
260260
_sendPlatformMessage(name, _zonedPlatformMessageResponseCallback(callback), data);
261261
if (error != null) {
@@ -288,13 +288,13 @@ class PlatformDispatcher {
288288
}
289289

290290
/// Called by [_dispatchPlatformMessage].
291-
void _respondToPlatformMessage(int responseId, ByteData data)
291+
void _respondToPlatformMessage(int/*!*/ responseId, ByteData/*?*/ data)
292292
native 'PlatformConfiguration_respondToPlatformMessage';
293293

294294
/// Wraps the given [callback] in another callback that ensures that the
295295
/// original callback is called in the zone it was registered in.
296-
static PlatformMessageResponseCallback _zonedPlatformMessageResponseCallback(
297-
PlatformMessageResponseCallback callback) {
296+
static PlatformMessageResponseCallback/*?*/ _zonedPlatformMessageResponseCallback(
297+
PlatformMessageResponseCallback/*?*/ callback) {
298298
if (callback == null) {
299299
return null;
300300
}
@@ -316,7 +316,7 @@ class PlatformDispatcher {
316316
/// This can be combined with flutter tools `--isolate-filter` flag to debug
317317
/// specific root isolates. For example: `flutter attach --isolate-filter=[name]`.
318318
/// Note that this does not rename any child isolates of the root.
319-
void setIsolateDebugName(String name) native 'PlatformConfiguration_setIsolateDebugName';
319+
void setIsolateDebugName(String/*!*/ name) native 'PlatformConfiguration_setIsolateDebugName';
320320

321321
/// The embedder can specify data that the isolate can request synchronously
322322
/// on launch. This accessor fetches that data.
@@ -327,7 +327,7 @@ class PlatformDispatcher {
327327
///
328328
/// For asynchronous communication between the embedder and isolate, a
329329
/// platform channel may be used.
330-
ByteData getPersistentIsolateData() native 'PlatformConfiguration_getPersistentIsolateData';
330+
ByteData/*?*/ getPersistentIsolateData() native 'PlatformConfiguration_getPersistentIsolateData';
331331

332332
/// Requests that, at the next appropriate opportunity, the [onBeginFrame]
333333
/// and [onDrawFrame] callbacks be invoked.

lib/ui/window.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ class FlutterView {
745745
/// scheduling of frames.
746746
/// * [RendererBinding], the Flutter framework class which manages layout and
747747
/// painting.
748-
void render(Scene scene) => _platformDispatcher.render(scene, this);
748+
void render(Scene/*!*/ scene) => _platformDispatcher.render(scene, this);
749749
}
750750

751751
/// The most basic interface to the host operating system's user interface.

lib/web_ui/lib/src/engine/dom_renderer.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ flt-glass-pane * {
472472
}
473473
_localeSubscription = languageChangeEvent.forTarget(html.window)
474474
.listen(_languageDidChange);
475-
window._updateLocales();
475+
EnginePlatformDispatcher.instance._updateLocales();
476476
}
477477

478478
/// Called immediately after browser window metrics change.
@@ -498,7 +498,7 @@ flt-glass-pane * {
498498

499499
/// Called immediately after browser window language change.
500500
void _languageDidChange(html.Event event) {
501-
window._updateLocales();
501+
EnginePlatformDispatcher.instance._updateLocales();
502502
if (ui.window.onLocaleChanged != null) {
503503
ui.window.onLocaleChanged();
504504
}

lib/web_ui/lib/src/engine/platform_dispatcher.dart

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
2323
/// The current platform configuration.
2424
@override
2525
ui.PlatformConfiguration get configuration => _configuration;
26-
ui.PlatformConfiguration _configuration = const ui.PlatformConfiguration();
26+
ui.PlatformConfiguration _configuration = ui.PlatformConfiguration(locales: parseBrowserLanguages());
2727

2828
/// Receives all events related to platform configuration changes.
2929
@override
@@ -310,9 +310,9 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
310310

311311
@override
312312
void sendPlatformMessage(
313-
String name,
314-
ByteData data,
315-
ui.PlatformMessageResponseCallback callback,
313+
String/*!*/ name,
314+
ByteData/*?*/ data,
315+
ui.PlatformMessageResponseCallback/*?*/ callback,
316316
) {
317317
_sendPlatformMessage(name, data, _zonedPlatformMessageResponseCallback(callback));
318318
}
@@ -354,9 +354,9 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
354354
}
355355

356356
void _sendPlatformMessage(
357-
String name,
358-
ByteData data,
359-
ui.PlatformMessageResponseCallback callback,
357+
String/*?*/ name,
358+
ByteData/*?*/ data,
359+
ui.PlatformMessageResponseCallback/*?*/ callback,
360360
) {
361361
// In widget tests we want to bypass processing of platform messages.
362362
if (assertionsEnabled && ui.debugEmulateFlutterTesterEnvironment) {
@@ -546,7 +546,7 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
546546
/// * [RendererBinding], the Flutter framework class which manages layout and
547547
/// painting.
548548
@override
549-
void render(ui.Scene scene, [ui.FlutterView view]) {
549+
void render(ui.Scene/*!*/ scene, [ui.FlutterView view]) {
550550
if (experimentalUseSkia) {
551551
final LayerScene layerScene = scene;
552552
rasterizer.draw(layerScene.layerTree);
@@ -588,22 +588,15 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
588588
EngineSemanticsOwner.instance.updateSemantics(update);
589589
}
590590

591-
/// The system-reported default locale of the device.
591+
/// We use the first locale in the [locales] list instead of the browser's
592+
/// built-in `navigator.language` because browsers do not agree on the
593+
/// implementation.
592594
///
593-
/// This establishes the language and formatting conventions that application
594-
/// should, if possible, use to render their user interface.
595-
///
596-
/// This is the first locale selected by the user and is the user's
597-
/// primary locale (the locale the device UI is displayed in)
595+
/// See also:
598596
///
599-
/// This is equivalent to `locales.first` and will provide an empty non-null locale
600-
/// if the [locales] list has not been set or is empty.
601-
ui.Locale get locale {
602-
if (configuration?.locales != null && configuration.locales.isNotEmpty) {
603-
return locales.first;
604-
}
605-
return null;
606-
}
597+
/// * https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/languages,
598+
/// which explains browser quirks in the implementation notes.
599+
ui.Locale get locale => locales.first;
607600

608601
/// The full system-reported supported locales of the device.
609602
///
@@ -650,6 +643,45 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
650643
_onLocaleChangedZone = Zone.current;
651644
}
652645

646+
/// The locale used when we fail to get the list from the browser.
647+
static const _defaultLocale = const ui.Locale('en', 'US');
648+
649+
/// Sets locales to an empty list.
650+
///
651+
/// The empty list is not a valid value for locales. This is only used for
652+
/// testing locale update logic.
653+
void debugResetLocales() {
654+
_configuration = _configuration.copyWith(locales: const <ui.Locale>[]);
655+
}
656+
657+
// Called by DomRenderer when browser languages change.
658+
void _updateLocales() {
659+
_configuration = _configuration.copyWith(locales: parseBrowserLanguages());
660+
}
661+
662+
static List<ui.Locale> parseBrowserLanguages() {
663+
// TODO(yjbanov): find a solution for IE
664+
final bool languagesFeatureMissing = !js_util.hasProperty(html.window.navigator, 'languages');
665+
if (languagesFeatureMissing || html.window.navigator.languages.isEmpty) {
666+
// To make it easier for the app code, let's not leave the locales list
667+
// empty. This way there's fewer corner cases for apps to handle.
668+
return const [_defaultLocale];
669+
}
670+
671+
final List<ui.Locale> locales = <ui.Locale>[];
672+
for (final String language in html.window.navigator.languages) {
673+
final List<String> parts = language.split('-');
674+
if (parts.length > 1) {
675+
locales.add(ui.Locale(parts.first, parts.last));
676+
} else {
677+
locales.add(ui.Locale(language));
678+
}
679+
}
680+
681+
assert(locales.isNotEmpty);
682+
return locales;
683+
}
684+
653685
/// Engine code should use this method instead of the callback directly.
654686
/// Otherwise zones won't work properly.
655687
void invokeOnLocaleChanged() {

0 commit comments

Comments
 (0)