Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[web] change status bar color based on SystemUiOverlayStyle #40599

Merged
merged 12 commits into from
Apr 20, 2023
8 changes: 6 additions & 2 deletions lib/web_ui/lib/src/engine/platform_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -518,9 +518,13 @@ class EnginePlatformDispatcher extends ui.PlatformDispatcher {
final Map<String, dynamic> arguments = decoded.arguments as Map<String, dynamic>;
// TODO(ferhat): Find more appropriate defaults? Or noop when values are null?
final String label = arguments['label'] as String? ?? '';
final int primaryColor = arguments['primaryColor'] as int? ?? 0xFF000000;
maRci002 marked this conversation as resolved.
Show resolved Hide resolved
domDocument.title = label;
setThemeColor(ui.Color(primaryColor));
replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
ditman marked this conversation as resolved.
Show resolved Hide resolved
return;
case 'SystemChrome.setSystemUIOverlayStyle':
maRci002 marked this conversation as resolved.
Show resolved Hide resolved
final Map<String, dynamic> arguments = decoded.arguments as Map<String, dynamic>;
maRci002 marked this conversation as resolved.
Show resolved Hide resolved
final int? statusBarColor = arguments['statusBarColor'] as int?;
setThemeColor(statusBarColor == null ? null : ui.Color(statusBarColor));
replyToPlatformMessage(callback, codec.encodeSuccessEnvelope(true));
return;
case 'SystemChrome.setPreferredOrientations':
Expand Down
19 changes: 12 additions & 7 deletions lib/web_ui/lib/src/engine/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -678,16 +678,21 @@ void setClipPath(DomElement element, String? value) {
}
}

void setThemeColor(ui.Color color) {
void setThemeColor(ui.Color? color) {
DomHTMLMetaElement? theme =
domDocument.querySelector('#flutterweb-theme') as DomHTMLMetaElement?;
if (theme == null) {
theme = createDomHTMLMetaElement()
..id = 'flutterweb-theme'
..name = 'theme-color';
domDocument.head!.append(theme);

if (color != null) {
if (theme == null) {
theme = createDomHTMLMetaElement()
..id = 'flutterweb-theme'
..name = 'theme-color';
domDocument.head!.append(theme);
}
theme.content = colorToCssString(color)!;
} else if (theme != null) {
theme.remove();
}
maRci002 marked this conversation as resolved.
Show resolved Hide resolved
theme.content = colorToCssString(color)!;
}

bool? _ellipseFeatureDetected;
Expand Down
31 changes: 27 additions & 4 deletions lib/web_ui/test/engine/platform_dispatcher_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,27 @@ void testMain() {
);
});

test('responds to flutter/platform SystemChrome.setSystemUIOverlayStyle',
() async {
const MethodCodec codec = JSONMethodCodec();
final Completer<ByteData?> completer = Completer<ByteData?>();
ui.PlatformDispatcher.instance.sendPlatformMessage(
'flutter/platform',
codec.encodeMethodCall(const MethodCall(
'SystemChrome.setSystemUIOverlayStyle',
<String, dynamic>{},
)),
completer.complete,
);

final ByteData? response = await completer.future;
expect(response, isNotNull);
expect(
codec.decodeEnvelope(response!),
true,
);
});

test('responds to flutter/contextmenu enable', () async {
const MethodCodec codec = JSONMethodCodec();
final Completer<ByteData?> completer = Completer<ByteData?>();
Expand Down Expand Up @@ -144,7 +165,8 @@ void testMain() {
() async {
final DomElement root = domDocument.documentElement!;
final String oldFontSize = root.style.fontSize;
final ui.VoidCallback? oldCallback = ui.PlatformDispatcher.instance.onTextScaleFactorChanged;
final ui.VoidCallback? oldCallback =
ui.PlatformDispatcher.instance.onTextScaleFactorChanged;

addTearDown(() {
root.style.fontSize = oldFontSize;
Expand All @@ -162,15 +184,17 @@ void testMain() {
await Future<void>.delayed(Duration.zero);
expect(root.style.fontSize, '20px');
expect(isCalled, isTrue);
expect(ui.PlatformDispatcher.instance.textScaleFactor, findBrowserTextScaleFactor());
expect(ui.PlatformDispatcher.instance.textScaleFactor,
findBrowserTextScaleFactor());

isCalled = false;

root.style.fontSize = '16px';
await Future<void>.delayed(Duration.zero);
expect(root.style.fontSize, '16px');
expect(isCalled, isTrue);
expect(ui.PlatformDispatcher.instance.textScaleFactor, findBrowserTextScaleFactor());
expect(ui.PlatformDispatcher.instance.textScaleFactor,
findBrowserTextScaleFactor());
});
});
}
Expand All @@ -183,7 +207,6 @@ class MockHighContrastSupport implements HighContrastSupport {
@override
bool get isHighContrastEnabled => isEnabled;


void invokeListeners(bool val) {
for (final HighContrastListener listener in _listeners) {
listener(val);
Expand Down
53 changes: 53 additions & 0 deletions lib/web_ui/test/ui/system_ui_overlay_style_test.dart
ditman marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2013 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:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' as ui;

import 'utils.dart';

void main() {
internalBootstrapBrowserTest(() => testMain);
}

void testMain() {
setUpUiTest();

const MethodCodec codec = JSONMethodCodec();

void sendSetSystemUIOverlayStyle({ui.Color? statusBarColor}) {
ui.window.sendPlatformMessage(
'flutter/platform',
codec.encodeMethodCall(
MethodCall('SystemChrome.setSystemUIOverlayStyle', <String, dynamic>{
'statusBarColor': statusBarColor?.value,
})),
null,
);
}

String? getCssThemeColor() {
final DomHTMLMetaElement? theme =
domDocument.querySelector('#flutterweb-theme') as DomHTMLMetaElement?;
return theme?.content;
}

group('SystemUIOverlayStyle', () {
test('theme color is set / removed by platform message', () {
// Run the unit test without emulating Flutter tester environment.
ui.debugEmulateFlutterTesterEnvironment = false;

expect(getCssThemeColor(), null);

const ui.Color statusBarColor = ui.Color(0xFFF44336);
sendSetSystemUIOverlayStyle(statusBarColor: statusBarColor);
expect(getCssThemeColor(), colorToCssString(statusBarColor));

sendSetSystemUIOverlayStyle();
expect(getCssThemeColor(), null);
});
});
}