feat(dark-mode): add system appearance property, event and CSS classes (#7887)

This commit is contained in:
Vasil Chimev
2019-10-08 13:07:15 +03:00
committed by Manol Donev
parent d7d7ebf5de
commit 5c9a217bc5
16 changed files with 336 additions and 53 deletions

View File

@@ -9,12 +9,14 @@ import {
AndroidApplication as AndroidApplicationDefinition,
ApplicationEventData,
CssChangedEventData,
OrientationChangedEventData
OrientationChangedEventData,
SystemAppearanceChangedEventData
} from ".";
import {
displayedEvent, hasListeners, livesync, lowMemoryEvent, notify, Observable, on,
orientationChanged, orientationChangedEvent, setApplication, suspendEvent
orientationChanged, orientationChangedEvent, setApplication, suspendEvent,
systemAppearanceChanged, systemAppearanceChangedEvent
} from "./application-common";
import { profile } from "../profiling";
@@ -51,6 +53,7 @@ export class AndroidApplication extends Observable implements AndroidApplication
public static activityRequestPermissionsEvent = ActivityRequestPermissions;
private _orientation: "portrait" | "landscape" | "unknown";
private _systemAppearance: "light" | "dark";
public paused: boolean;
public nativeApp: android.app.Application;
public context: android.content.Context;
@@ -93,9 +96,8 @@ export class AndroidApplication extends Observable implements AndroidApplication
if (!this._orientation) {
const resources = this.context.getResources();
const configuration = <android.content.res.Configuration>resources.getConfiguration();
const orientation = configuration.orientation;
this._orientation = getOrientationValue(orientation);
this._orientation = getOrientationValue(configuration);
}
return this._orientation;
@@ -105,6 +107,21 @@ export class AndroidApplication extends Observable implements AndroidApplication
this._orientation = value;
}
get systemAppearance(): "light" | "dark" {
if (!this._systemAppearance) {
const resources = this.context.getResources();
const configuration = <android.content.res.Configuration>resources.getConfiguration();
this._systemAppearance = getSystemAppearanceValue(configuration);
}
return this._systemAppearance;
}
set systemAppearance(value: "light" | "dark") {
this._systemAppearance = value;
}
public registerBroadcastReceiver(intentFilter: string, onReceiveCallback: (context: android.content.Context, intent: android.content.Intent) => void) {
ensureBroadCastReceiverClass();
const that = this;
@@ -131,6 +148,7 @@ export class AndroidApplication extends Observable implements AndroidApplication
}
}
}
export interface AndroidApplication {
on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any);
on(event: "activityCreated", callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any);
@@ -252,12 +270,9 @@ export function orientation(): "portrait" | "landscape" | "unknown" {
return androidApp.orientation;
}
on(orientationChangedEvent, (args: OrientationChangedEventData) => {
const rootView = getRootView();
if (rootView) {
orientationChanged(rootView, args.newValue);
}
});
export function systemAppearance(): "dark" | "light" {
return androidApp.systemAppearance;
}
global.__onLiveSync = function __onLiveSync(context?: ModuleContext) {
if (androidApp && androidApp.paused) {
@@ -268,7 +283,9 @@ global.__onLiveSync = function __onLiveSync(context?: ModuleContext) {
livesync(rootView, context);
};
function getOrientationValue(orientation: number): "portrait" | "landscape" | "unknown" {
function getOrientationValue(configuration: android.content.res.Configuration): "portrait" | "landscape" | "unknown" {
const orientation = configuration.orientation;
switch (orientation) {
case android.content.res.Configuration.ORIENTATION_LANDSCAPE:
return "landscape";
@@ -279,6 +296,19 @@ function getOrientationValue(orientation: number): "portrait" | "landscape" | "u
}
}
// https://developer.android.com/guide/topics/ui/look-and-feel/darktheme#configuration_changes
function getSystemAppearanceValue(configuration: android.content.res.Configuration): "dark" | "light" {
const systemAppearance = configuration.uiMode & android.content.res.Configuration.UI_MODE_NIGHT_MASK;
switch (systemAppearance) {
case android.content.res.Configuration.UI_MODE_NIGHT_YES:
return "dark";
case android.content.res.Configuration.UI_MODE_NIGHT_NO:
case android.content.res.Configuration.UI_MODE_NIGHT_UNDEFINED:
return "light";
}
}
function initLifecycleCallbacks() {
const setThemeOnLaunch = profile("setThemeOnLaunch", (activity: androidx.appcompat.app.AppCompatActivity) => {
// Set app theme after launch screen was used during startup
@@ -380,12 +410,12 @@ function initComponentCallbacks() {
// TODO: This is skipped for now, test carefully for OutOfMemory exceptions
}),
onConfigurationChanged: profile("onConfigurationChanged", function (newConfig: android.content.res.Configuration) {
const newConfigOrientation = newConfig.orientation;
const newOrientation = getOrientationValue(newConfigOrientation);
onConfigurationChanged: profile("onConfigurationChanged", function (newConfiguration: android.content.res.Configuration) {
const newOrientation = getOrientationValue(newConfiguration);
if (androidApp.orientation !== newOrientation) {
androidApp.orientation = newOrientation;
orientationChanged(getRootView(), newOrientation);
notify(<OrientationChangedEventData>{
eventName: orientationChangedEvent,
@@ -393,6 +423,22 @@ function initComponentCallbacks() {
newValue: androidApp.orientation,
object: androidApp
});
return;
}
const newSystemAppearance = getSystemAppearanceValue(newConfiguration);
if (androidApp.systemAppearance !== newSystemAppearance) {
androidApp.systemAppearance = newSystemAppearance;
systemAppearanceChanged(getRootView(), newSystemAppearance);
notify(<SystemAppearanceChangedEventData>{
eventName: systemAppearanceChangedEvent,
android: androidApp.nativeApp,
newValue: androidApp.systemAppearance,
object: androidApp
});
}
})
});