From efa1818cb4e1b158f8aace87aeddbca335faf29a Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 14 Aug 2019 13:42:55 -0700 Subject: [PATCH] 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??? --- docs/api/native-theme.md | 35 +++++++ docs/api/system-preferences.md | 43 ++++++-- filenames.auto.gni | 7 +- filenames.gni | 2 + lib/browser/api/system-preferences.js | 15 --- lib/browser/api/system-preferences.ts | 42 ++++++++ lib/common/api/deprecate.ts | 16 ++- lib/common/api/module-list.js | 1 + lib/common/api/native-theme.ts | 8 ++ .../api/atom_api_system_preferences.cc | 4 +- shell/common/api/atom_api_native_theme.cc | 97 +++++++++++++++++++ shell/common/api/atom_api_native_theme.h | 45 +++++++++ shell/common/node_bindings.cc | 1 + spec-main/api-native-theme-spec.ts | 22 +++++ spec/api-deprecate-spec.js | 31 ++++++ typings/internal-electron.d.ts | 3 +- 16 files changed, 343 insertions(+), 29 deletions(-) create mode 100644 docs/api/native-theme.md delete mode 100644 lib/browser/api/system-preferences.js create mode 100644 lib/browser/api/system-preferences.ts create mode 100644 lib/common/api/native-theme.ts create mode 100644 shell/common/api/atom_api_native_theme.cc create mode 100644 shell/common/api/atom_api_native_theme.h create mode 100644 spec-main/api-native-theme-spec.ts diff --git a/docs/api/native-theme.md b/docs/api/native-theme.md new file mode 100644 index 000000000000..815143c7a73a --- /dev/null +++ b/docs/api/native-theme.md @@ -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. diff --git a/docs/api/system-preferences.md b/docs/api/system-preferences.md index ffddd331e2b7..b948cb42630a 100644 --- a/docs/api/system-preferences.md +++ b/docs/api/system-preferences.md @@ -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. diff --git a/filenames.auto.gni b/filenames.auto.gni index c5e0b0577cf0..6348cde35837 100644 --- a/filenames.auto.gni +++ b/filenames.auto.gni @@ -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", diff --git a/filenames.gni b/filenames.gni index b3b601f6b69d..231ce1db2633 100644 --- a/filenames.gni +++ b/filenames.gni @@ -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", diff --git a/lib/browser/api/system-preferences.js b/lib/browser/api/system-preferences.js deleted file mode 100644 index 6a42289bf7b8..000000000000 --- a/lib/browser/api/system-preferences.js +++ /dev/null @@ -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 diff --git a/lib/browser/api/system-preferences.ts b/lib/browser/api/system-preferences.ts new file mode 100644 index 000000000000..3de4732de05c --- /dev/null +++ b/lib/browser/api/system-preferences.ts @@ -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 diff --git a/lib/common/api/deprecate.ts b/lib/common/api/deprecate.ts index 3bc6a6e1f3f0..ceeb54cf08c1 100644 --- a/lib/common/api/deprecate.ts +++ b/lib/common/api/deprecate.ts @@ -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 diff --git a/lib/common/api/module-list.js b/lib/common/api/module-list.js index da75e7d36fb2..38b6093970f9 100644 --- a/lib/common/api/module-list.js +++ b/lib/common/api/module-list.js @@ -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 } diff --git a/lib/common/api/native-theme.ts b/lib/common/api/native-theme.ts new file mode 100644 index 000000000000..78d7e9049bf0 --- /dev/null +++ b/lib/common/api/native-theme.ts @@ -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 diff --git a/shell/browser/api/atom_api_system_preferences.cc b/shell/browser/api/atom_api_system_preferences.cc index b5d32871e33f..3e3210c2768c 100644 --- a/shell/browser/api/atom_api_system_preferences.cc +++ b/shell/browser/api/atom_api_system_preferences.cc @@ -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) diff --git a/shell/common/api/atom_api_native_theme.cc b/shell/common/api/atom_api_native_theme.cc new file mode 100644 index 000000000000..385d0daaa05d --- /dev/null +++ b/shell/common/api/atom_api_native_theme.cc @@ -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 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 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 exports, + v8::Local unused, + v8::Local 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) diff --git a/shell/common/api/atom_api_native_theme.h b/shell/common/api/atom_api_native_theme.h new file mode 100644 index 000000000000..8c1405e38e20 --- /dev/null +++ b/shell/common/api/atom_api_native_theme.h @@ -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, + public ui::NativeThemeObserver { + public: + static v8::Local Create(v8::Isolate* isolate); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local 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_ diff --git a/shell/common/node_bindings.cc b/shell/common/node_bindings.cc index c20b33fc3c3b..655fac20ecee 100644 --- a/shell/common/node_bindings.cc +++ b/shell/common/node_bindings.cc @@ -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) \ diff --git a/spec-main/api-native-theme-spec.ts b/spec-main/api-native-theme-spec.ts new file mode 100644 index 000000000000..cee34c83a058 --- /dev/null +++ b/spec-main/api-native-theme-spec.ts @@ -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') + }) + }) +}) diff --git a/spec/api-deprecate-spec.js b/spec/api-deprecate-spec.js index 999080f16bff..75283d7233aa 100644 --- a/spec/api-deprecate-spec.js +++ b/spec/api-deprecate-spec.js @@ -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 diff --git a/typings/internal-electron.d.ts b/typings/internal-electron.d.ts index f2c48a154eae..b39ab2080040 100644 --- a/typings/internal-electron.d.ts +++ b/typings/internal-electron.d.ts @@ -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(object: T, propertyName: K): T; renameProperty(object: T, oldName: string, newName: K): T; + moveAPI(fn: Function, oldUsage: string, newUsage: string): Function; promisify any>(fn: T): T;