mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
feat(dark-mode): add system appearance property, event and CSS classes (#7887)
This commit is contained in:
committed by
Manol Donev
parent
d7d7ebf5de
commit
5c9a217bc5
@@ -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
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user