feat: add new nativeTheme API (#19656)
* feat: add new nativeTheme API * chore: deprecate and clean up old systemPreferences theme APIs in favor of new nativeTheme module * chore: clean up and deprecate things per feedback * chore: add tests for deprecate and clean up invert impl * build: when is a boolean not a boolean???
This commit is contained in:
parent
246187a20f
commit
efa1818cb4
16 changed files with 343 additions and 29 deletions
35
docs/api/native-theme.md
Normal file
35
docs/api/native-theme.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# nativeTheme
|
||||
|
||||
> Read and respond to changes in Chromium's native color theme.
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
## Events
|
||||
|
||||
The `nativeTheme` module emits the following events:
|
||||
|
||||
### Event: 'updated'
|
||||
|
||||
Emitted when something in the underlying NativeTheme has changed. This normally
|
||||
means that either the value of `shouldUseDarkColors`,
|
||||
`shouldUseHighContrastColors` or `shouldUseInvertedColorScheme` has changed.
|
||||
You will have to check them to determine which one has changed.
|
||||
|
||||
## Properties
|
||||
|
||||
The `nativeTheme` module has the following properties:
|
||||
|
||||
### `nativeTheme.shouldUseDarkColors` _Readonly_
|
||||
|
||||
A `Boolean` for if the OS / Chromium currently has a dark mode enabled or is
|
||||
being instructed to show a dark-style UI.
|
||||
|
||||
### `nativeTheme.shouldUseHighContrastColors` _macOS_ _Windows_ _Readonly_
|
||||
|
||||
A `Boolean` for if the OS / Chromium currently has high-contrast mode enabled
|
||||
or is being instructed to show a high-constrast UI.
|
||||
|
||||
### `nativeTheme.shouldUseInvertedColorScheme` _macOS_ _Windows_ _Readonly_
|
||||
|
||||
A `Boolean` for if the OS / Chromium currently has an inverted color scheme
|
||||
or is being instructed to use an inverted color scheme.
|
|
@ -27,28 +27,34 @@ Returns:
|
|||
|
||||
* `event` Event
|
||||
|
||||
### Event: 'inverted-color-scheme-changed' _Windows_
|
||||
### Event: 'inverted-color-scheme-changed' _Windows_ _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `invertedColorScheme` Boolean - `true` if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is being used, `false` otherwise.
|
||||
|
||||
### Event: 'high-contrast-color-scheme-changed' _Windows_
|
||||
**Deprecated:** Should use the new [`updated`](native-theme.md#event-updated) event on the `nativeTheme` module.
|
||||
|
||||
### Event: 'high-contrast-color-scheme-changed' _Windows_ _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `highContrastColorScheme` Boolean - `true` if a high contrast theme is being used, `false` otherwise.
|
||||
|
||||
**Deprecated:** Should use the new [`updated`](native-theme.md#event-updated) event on the `nativeTheme` module.
|
||||
|
||||
## Methods
|
||||
|
||||
### `systemPreferences.isDarkMode()` _macOS_ _Windows_
|
||||
### `systemPreferences.isDarkMode()` _macOS_ _Windows_ _Deprecated_
|
||||
|
||||
Returns `Boolean` - Whether the system is in Dark Mode.
|
||||
|
||||
**Note:** On macOS 10.15 Catalina in order for this API to return the correct value when in the "automatic" dark mode setting you must either have `NSRequiresAquaSystemAppearance=false` in your `Info.plist` or be on Electron `>=7.0.0`. See the [dark mode guide](../tutorial/mojave-dark-mode-guide.md) for more information.
|
||||
|
||||
**Deprecated:** Should use the new [`nativeTheme.shouldUseDarkColors`](native-theme.md#nativethemeshouldusedarkcolors-readonly) API.
|
||||
|
||||
### `systemPreferences.isSwipeTrackingFromScrollEventsEnabled()` _macOS_
|
||||
|
||||
Returns `Boolean` - Whether the Swipe between pages setting is on.
|
||||
|
@ -342,14 +348,18 @@ Returns `String` - The standard system color formatted as `#RRGGBBAA`.
|
|||
|
||||
Returns one of several standard system colors that automatically adapt to vibrancy and changes in accessibility settings like 'Increase contrast' and 'Reduce transparency'. See [Apple Documentation](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color#system-colors) for more details.
|
||||
|
||||
### `systemPreferences.isInvertedColorScheme()` _Windows_
|
||||
### `systemPreferences.isInvertedColorScheme()` _Windows_ _Deprecated_
|
||||
|
||||
Returns `Boolean` - `true` if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is active, `false` otherwise.
|
||||
|
||||
### `systemPreferences.isHighContrastColorScheme()` _macOS_ _Windows_
|
||||
**Deprecated:** Should use the new [`nativeTheme.shouldUseInvertedColorScheme`](native-theme.md#nativethemeshoulduseinvertedcolorscheme-macos-windows-readonly) API.
|
||||
|
||||
### `systemPreferences.isHighContrastColorScheme()` _macOS_ _Windows_ _Deprecated_
|
||||
|
||||
Returns `Boolean` - `true` if a high contrast theme is active, `false` otherwise.
|
||||
|
||||
**Depreacted:** Should use the new [`nativeTheme.shouldUseHighContrastColors`](native-theme.md#nativethemeshouldusehighcontrastcolors-macos-windows-readonly) API.
|
||||
|
||||
### `systemPreferences.getEffectiveAppearance()` _macOS_
|
||||
|
||||
Returns `String` - Can be `dark`, `light` or `unknown`.
|
||||
|
@ -365,7 +375,9 @@ using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode
|
|||
packager option to `true`. See the [Electron Packager API](https://github.com/electron/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
|
||||
for more details.
|
||||
|
||||
### `systemPreferences.getAppLevelAppearance()` _macOS_
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `systemPreferences.getAppLevelAppearance()` _macOS_ _Deprecated_
|
||||
|
||||
Returns `String` | `null` - Can be `dark`, `light` or `unknown`.
|
||||
|
||||
|
@ -375,7 +387,7 @@ You can use the `setAppLevelAppearance` API to set this value.
|
|||
|
||||
**[Deprecated](modernization/property-updates.md)**
|
||||
|
||||
### `systemPreferences.setAppLevelAppearance(appearance)` _macOS_
|
||||
### `systemPreferences.setAppLevelAppearance(appearance)` _macOS_ _Deprecated_
|
||||
|
||||
* `appearance` String | null - Can be `dark` or `light`
|
||||
|
||||
|
@ -450,10 +462,25 @@ Returns an object with system animation settings.
|
|||
|
||||
### `systemPreferences.appLevelAppearance` _macOS_
|
||||
|
||||
A `String` property that determines the macOS appearance setting for
|
||||
A `String` property that can be `dark`, `light` or `unknown`. It determines the macOS appearance setting for
|
||||
your application. This maps to values in: [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc). Setting this will override the
|
||||
system default as well as the value of `getEffectiveAppearance`.
|
||||
|
||||
Possible values that can be set are `dark` and `light`, and possible return values are `dark`, `light`, and `unknown`.
|
||||
|
||||
This property is only available on macOS 10.14 Mojave or newer.
|
||||
|
||||
### `systemPreferences.effectiveAppearance` _macOS_ _Readonly_
|
||||
|
||||
A `String` property that can be `dark`, `light` or `unknown`.
|
||||
|
||||
Returns the macOS appearance setting that is currently applied to your application,
|
||||
maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)
|
||||
|
||||
Please note that until Electron is built targeting the 10.14 SDK, your application's
|
||||
`effectiveAppearance` will default to 'light' and won't inherit the OS preference. In
|
||||
the interim in order for your application to inherit the OS preference you must set the
|
||||
`NSRequiresAquaSystemAppearance` key in your apps `Info.plist` to `false`. If you are
|
||||
using `electron-packager` or `electron-forge` just set the `enableDarwinDarkMode`
|
||||
packager option to `true`. See the [Electron Packager API](https://github.com/electron/electron-packager/blob/master/docs/api.md#darwindarkmodesupport)
|
||||
for more details.
|
||||
|
|
|
@ -34,6 +34,7 @@ auto_filenames = {
|
|||
"docs/api/menu.md",
|
||||
"docs/api/modernization",
|
||||
"docs/api/native-image.md",
|
||||
"docs/api/native-theme.md",
|
||||
"docs/api/net-log.md",
|
||||
"docs/api/net.md",
|
||||
"docs/api/notification.md",
|
||||
|
@ -131,6 +132,7 @@ auto_filenames = {
|
|||
"lib/common/api/deprecate.ts",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/native-theme.ts",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
|
@ -229,7 +231,7 @@ auto_filenames = {
|
|||
"lib/browser/api/protocol.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/session.js",
|
||||
"lib/browser/api/system-preferences.js",
|
||||
"lib/browser/api/system-preferences.ts",
|
||||
"lib/browser/api/top-level-window.js",
|
||||
"lib/browser/api/touch-bar.js",
|
||||
"lib/browser/api/tray.js",
|
||||
|
@ -262,6 +264,7 @@ auto_filenames = {
|
|||
"lib/common/api/exports/electron.js",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/native-theme.ts",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
|
@ -287,6 +290,7 @@ auto_filenames = {
|
|||
"lib/common/api/exports/electron.js",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/native-theme.ts",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
|
@ -337,6 +341,7 @@ auto_filenames = {
|
|||
"lib/common/api/exports/electron.js",
|
||||
"lib/common/api/module-list.js",
|
||||
"lib/common/api/native-image.js",
|
||||
"lib/common/api/native-theme.ts",
|
||||
"lib/common/api/shell.js",
|
||||
"lib/common/buffer-utils.ts",
|
||||
"lib/common/clipboard-utils.ts",
|
||||
|
|
|
@ -419,6 +419,8 @@ filenames = {
|
|||
"shell/common/api/atom_api_native_image.cc",
|
||||
"shell/common/api/atom_api_native_image.h",
|
||||
"shell/common/api/atom_api_native_image_mac.mm",
|
||||
"shell/common/api/atom_api_native_theme.cc",
|
||||
"shell/common/api/atom_api_native_theme.h",
|
||||
"shell/common/api/atom_api_shell.cc",
|
||||
"shell/common/api/atom_api_v8_util.cc",
|
||||
"shell/common/api/electron_bindings.cc",
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
const { EventEmitter } = require('events')
|
||||
const { deprecate } = require('electron')
|
||||
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences')
|
||||
|
||||
// SystemPreferences is an EventEmitter.
|
||||
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype)
|
||||
EventEmitter.call(systemPreferences)
|
||||
|
||||
if ('appLevelAppearance' in systemPreferences) {
|
||||
deprecate.fnToProperty(SystemPreferences.prototype, 'appLevelAppearance', '_getAppLevelAppearance', '_setAppLevelAppearance')
|
||||
}
|
||||
|
||||
module.exports = systemPreferences
|
42
lib/browser/api/system-preferences.ts
Normal file
42
lib/browser/api/system-preferences.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { EventEmitter } from 'events'
|
||||
import { deprecate } from 'electron'
|
||||
const { systemPreferences, SystemPreferences } = process.electronBinding('system_preferences')
|
||||
|
||||
// SystemPreferences is an EventEmitter.
|
||||
Object.setPrototypeOf(SystemPreferences.prototype, EventEmitter.prototype)
|
||||
EventEmitter.call(systemPreferences)
|
||||
|
||||
if ('appLevelAppearance' in systemPreferences) {
|
||||
deprecate.fnToProperty(
|
||||
SystemPreferences.prototype,
|
||||
'appLevelAppearance',
|
||||
'_getAppLevelAppearance',
|
||||
'_setAppLevelAppearance'
|
||||
)
|
||||
}
|
||||
|
||||
if ('effectiveAppearance' in systemPreferences) {
|
||||
deprecate.fnToProperty(
|
||||
SystemPreferences.prototype,
|
||||
'effectiveAppearance',
|
||||
'_getEffectiveAppearance'
|
||||
)
|
||||
}
|
||||
|
||||
SystemPreferences.prototype.isDarkMode = deprecate.moveAPI(
|
||||
SystemPreferences.prototype.isDarkMode,
|
||||
'systemPreferences.isDarkMode()',
|
||||
'nativeTheme.shouldUseDarkColors'
|
||||
)
|
||||
SystemPreferences.prototype.isInvertedColorScheme = deprecate.moveAPI(
|
||||
SystemPreferences.prototype.isInvertedColorScheme,
|
||||
'systemPreferences.isInvertedColorScheme()',
|
||||
'nativeTheme.shouldUseInvertedColorScheme'
|
||||
)
|
||||
SystemPreferences.prototype.isHighContrastColorScheme = deprecate.moveAPI(
|
||||
SystemPreferences.prototype.isHighContrastColorScheme,
|
||||
'systemPreferences.isHighContrastColorScheme()',
|
||||
'nativeTheme.shouldUseHighContrastColors'
|
||||
)
|
||||
|
||||
module.exports = systemPreferences
|
|
@ -51,7 +51,15 @@ const deprecate: ElectronInternal.DeprecationUtil = {
|
|||
const warn = warnOnce(`${fn.name} function`, `${newName} function`)
|
||||
return function (this: any) {
|
||||
warn()
|
||||
fn.apply(this, arguments)
|
||||
return fn.apply(this, arguments)
|
||||
}
|
||||
},
|
||||
|
||||
moveAPI: (fn: Function, oldUsage: string, newUsage: string) => {
|
||||
const warn = warnOnce(oldUsage, newUsage)
|
||||
return function (this: any) {
|
||||
warn()
|
||||
return fn.apply(this, arguments)
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -69,7 +77,7 @@ const deprecate: ElectronInternal.DeprecationUtil = {
|
|||
},
|
||||
|
||||
// deprecate a getter/setter function pair in favor of a property
|
||||
fnToProperty: (prototype: any, prop: string, getter: string, setter: string) => {
|
||||
fnToProperty: (prototype: any, prop: string, getter: string, setter?: string) => {
|
||||
const withWarnOnce = function (obj: any, key: any, oldName: string, newName: string) {
|
||||
const warn = warnOnce(oldName, newName)
|
||||
const method = obj[key]
|
||||
|
@ -80,7 +88,9 @@ const deprecate: ElectronInternal.DeprecationUtil = {
|
|||
}
|
||||
|
||||
prototype[getter.substr(1)] = withWarnOnce(prototype, getter, `${getter.substr(1)} function`, `${prop} property`)
|
||||
prototype[setter.substr(1)] = withWarnOnce(prototype, setter, `${setter.substr(1)} function`, `${prop} property`)
|
||||
if (setter) {
|
||||
prototype[setter.substr(1)] = withWarnOnce(prototype, setter, `${setter.substr(1)} function`, `${prop} property`)
|
||||
}
|
||||
},
|
||||
|
||||
// remove a property with no replacement
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
module.exports = [
|
||||
{ name: 'clipboard', loader: () => require('./clipboard') },
|
||||
{ name: 'nativeImage', loader: () => require('./native-image') },
|
||||
{ name: 'nativeTheme', loader: () => require('./native-theme') },
|
||||
{ name: 'shell', loader: () => require('./shell') },
|
||||
// The internal modules, invisible unless you know their names.
|
||||
{ name: 'deprecate', loader: () => require('./deprecate'), private: true }
|
||||
|
|
8
lib/common/api/native-theme.ts
Normal file
8
lib/common/api/native-theme.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { EventEmitter } from 'events'
|
||||
|
||||
const { NativeTheme, nativeTheme } = process.electronBinding('native_theme')
|
||||
|
||||
Object.setPrototypeOf(NativeTheme.prototype, EventEmitter.prototype)
|
||||
EventEmitter.call(nativeTheme as any)
|
||||
|
||||
module.exports = nativeTheme
|
|
@ -99,7 +99,7 @@ void SystemPreferences::BuildPrototype(
|
|||
.SetMethod("removeUserDefault", &SystemPreferences::RemoveUserDefault)
|
||||
.SetMethod("isSwipeTrackingFromScrollEventsEnabled",
|
||||
&SystemPreferences::IsSwipeTrackingFromScrollEventsEnabled)
|
||||
.SetMethod("getEffectiveAppearance",
|
||||
.SetMethod("_getEffectiveAppearance",
|
||||
&SystemPreferences::GetEffectiveAppearance)
|
||||
.SetMethod("_getAppLevelAppearance",
|
||||
&SystemPreferences::GetAppLevelAppearance)
|
||||
|
@ -108,6 +108,8 @@ void SystemPreferences::BuildPrototype(
|
|||
.SetProperty("appLevelAppearance",
|
||||
&SystemPreferences::GetAppLevelAppearance,
|
||||
&SystemPreferences::SetAppLevelAppearance)
|
||||
.SetProperty("effectiveAppearance",
|
||||
&SystemPreferences::GetEffectiveAppearance)
|
||||
.SetMethod("getSystemColor", &SystemPreferences::GetSystemColor)
|
||||
.SetMethod("canPromptTouchID", &SystemPreferences::CanPromptTouchID)
|
||||
.SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
|
||||
|
|
97
shell/common/api/atom_api_native_theme.cc
Normal file
97
shell/common/api/atom_api_native_theme.cc
Normal file
|
@ -0,0 +1,97 @@
|
|||
// Copyright (c) 2019 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/common/api/atom_api_native_theme.h"
|
||||
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#include "ui/native_theme/native_theme.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace api {
|
||||
|
||||
NativeTheme::NativeTheme(v8::Isolate* isolate, ui::NativeTheme* theme)
|
||||
: theme_(theme) {
|
||||
theme_->AddObserver(this);
|
||||
Init(isolate);
|
||||
}
|
||||
|
||||
NativeTheme::~NativeTheme() {
|
||||
theme_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void NativeTheme::OnNativeThemeUpdated(ui::NativeTheme* theme) {
|
||||
Emit("updated");
|
||||
}
|
||||
|
||||
bool NativeTheme::ShouldUseDarkColors() {
|
||||
return theme_->SystemDarkModeEnabled();
|
||||
}
|
||||
|
||||
bool NativeTheme::ShouldUseHighContrastColors() {
|
||||
return theme_->UsesHighContrastColors();
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
const CFStringRef WhiteOnBlack = CFSTR("whiteOnBlack");
|
||||
const CFStringRef UniversalAccessDomain = CFSTR("com.apple.universalaccess");
|
||||
#endif
|
||||
|
||||
// TODO(MarshallOfSound): Implement for Linux
|
||||
bool NativeTheme::ShouldUseInvertedColorScheme() {
|
||||
#if defined(OS_MACOSX)
|
||||
CFPreferencesAppSynchronize(UniversalAccessDomain);
|
||||
Boolean keyExistsAndHasValidFormat = false;
|
||||
Boolean is_inverted = CFPreferencesGetAppBooleanValue(
|
||||
WhiteOnBlack, UniversalAccessDomain, &keyExistsAndHasValidFormat);
|
||||
if (!keyExistsAndHasValidFormat)
|
||||
return false;
|
||||
return is_inverted;
|
||||
#else
|
||||
return color_utils::IsInvertedColorScheme();
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> NativeTheme::Create(v8::Isolate* isolate) {
|
||||
ui::NativeTheme* theme = ui::NativeTheme::GetInstanceForNativeUi();
|
||||
return mate::CreateHandle(isolate, new NativeTheme(isolate, theme)).ToV8();
|
||||
}
|
||||
|
||||
// static
|
||||
void NativeTheme::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(mate::StringToV8(isolate, "NativeTheme"));
|
||||
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetProperty("shouldUseDarkColors", &NativeTheme::ShouldUseDarkColors)
|
||||
.SetProperty("shouldUseHighContrastColors",
|
||||
&NativeTheme::ShouldUseHighContrastColors)
|
||||
.SetProperty("shouldUseInvertedColorScheme",
|
||||
&NativeTheme::ShouldUseInvertedColorScheme);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace electron
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("nativeTheme", electron::api::NativeTheme::Create(isolate));
|
||||
dict.Set("NativeTheme", electron::api::NativeTheme::GetConstructor(isolate)
|
||||
->GetFunction(context)
|
||||
.ToLocalChecked());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(atom_common_native_theme, Initialize)
|
45
shell/common/api/atom_api_native_theme.h
Normal file
45
shell/common/api/atom_api_native_theme.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2019 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_COMMON_API_ATOM_API_NATIVE_THEME_H_
|
||||
#define SHELL_COMMON_API_ATOM_API_NATIVE_THEME_H_
|
||||
|
||||
#include "native_mate/handle.h"
|
||||
#include "shell/browser/api/event_emitter.h"
|
||||
#include "ui/native_theme/native_theme_observer.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace api {
|
||||
|
||||
class NativeTheme : public mate::EventEmitter<NativeTheme>,
|
||||
public ui::NativeThemeObserver {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
protected:
|
||||
NativeTheme(v8::Isolate* isolate, ui::NativeTheme* theme);
|
||||
~NativeTheme() override;
|
||||
|
||||
bool ShouldUseDarkColors();
|
||||
bool ShouldUseHighContrastColors();
|
||||
bool ShouldUseInvertedColorScheme();
|
||||
|
||||
// ui::NativeThemeObserver:
|
||||
void OnNativeThemeUpdated(ui::NativeTheme* theme) override;
|
||||
|
||||
private:
|
||||
ui::NativeTheme* theme_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(NativeTheme);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // SHELL_COMMON_API_ATOM_API_NATIVE_THEME_H_
|
|
@ -61,6 +61,7 @@
|
|||
V(atom_common_crash_reporter) \
|
||||
V(atom_common_features) \
|
||||
V(atom_common_native_image) \
|
||||
V(atom_common_native_theme) \
|
||||
V(atom_common_notification) \
|
||||
V(atom_common_screen) \
|
||||
V(atom_common_shell) \
|
||||
|
|
22
spec-main/api-native-theme-spec.ts
Normal file
22
spec-main/api-native-theme-spec.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { expect } from 'chai'
|
||||
import { nativeTheme } from 'electron'
|
||||
|
||||
describe('nativeTheme module', () => {
|
||||
describe('nativeTheme.shouldUseDarkColors', () => {
|
||||
it('returns a boolean', () => {
|
||||
expect(nativeTheme.shouldUseDarkColors).to.be.a('boolean')
|
||||
})
|
||||
})
|
||||
|
||||
describe('nativeTheme.shouldUseInvertedColorScheme', () => {
|
||||
it('returns a boolean', () => {
|
||||
expect(nativeTheme.shouldUseInvertedColorScheme).to.be.a('boolean')
|
||||
})
|
||||
})
|
||||
|
||||
describe('nativeTheme.shouldUseHighContrastColors', () => {
|
||||
it('returns a boolean', () => {
|
||||
expect(nativeTheme.shouldUseHighContrastColors).to.be.a('boolean')
|
||||
})
|
||||
})
|
||||
})
|
|
@ -168,6 +168,37 @@ describe('deprecate', () => {
|
|||
expect(warnings[1]).to.include(newProp)
|
||||
})
|
||||
|
||||
describe('moveAPI', () => {
|
||||
beforeEach(() => {
|
||||
deprecate.setHandler(null)
|
||||
})
|
||||
|
||||
it('should call the original method', () => {
|
||||
const warnings = []
|
||||
deprecate.setHandler(warning => warnings.push(warning))
|
||||
|
||||
let called = false
|
||||
const fn = () => {
|
||||
called = true
|
||||
}
|
||||
const deprecated = deprecate.moveAPI(fn, 'old', 'new')
|
||||
deprecated()
|
||||
expect(called).to.equal(true)
|
||||
})
|
||||
|
||||
it('should log the deprecation warning once', () => {
|
||||
const warnings = []
|
||||
deprecate.setHandler(warning => warnings.push(warning))
|
||||
|
||||
const deprecated = deprecate.moveAPI(() => null, 'old', 'new')
|
||||
deprecated()
|
||||
expect(warnings).to.have.lengthOf(1)
|
||||
deprecated()
|
||||
expect(warnings).to.have.lengthOf(1)
|
||||
expect(warnings[0]).to.equal('\'old\' is deprecated and will be removed. Please use \'new\' instead.')
|
||||
})
|
||||
})
|
||||
|
||||
describe('promisify', () => {
|
||||
const expected = 'Hello, world!'
|
||||
let promiseFunc
|
||||
|
|
3
typings/internal-electron.d.ts
vendored
3
typings/internal-electron.d.ts
vendored
|
@ -89,9 +89,10 @@ declare namespace ElectronInternal {
|
|||
removeFunction(fn: Function, removedName: string): Function;
|
||||
renameFunction(fn: Function, newName: string): Function;
|
||||
event(emitter: NodeJS.EventEmitter, oldName: string, newName: string): void;
|
||||
fnToProperty(module: any, prop: string, getter: string, setter: string): void;
|
||||
fnToProperty(module: any, prop: string, getter: string, setter?: string): void;
|
||||
removeProperty<T, K extends (keyof T & string)>(object: T, propertyName: K): T;
|
||||
renameProperty<T, K extends (keyof T & string)>(object: T, oldName: string, newName: K): T;
|
||||
moveAPI(fn: Function, oldUsage: string, newUsage: string): Function;
|
||||
|
||||
promisify<T extends (...args: any[]) => any>(fn: T): T;
|
||||
|
||||
|
|
Loading…
Reference in a new issue