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

feat: add APIs to support mojave dark modes #14755

Merged
merged 2 commits into from Sep 27, 2018
Merged

feat: add APIs to support mojave dark modes #14755

merged 2 commits into from Sep 27, 2018

Conversation

MarshallOfSound
Copy link
Member

Closes #13387

This PR implements the following APIs:
### `systemPreferences.getEffectiveAppearance()` _macOS_

Returns `String` - Can be `dark`, `light` or `unknown`.

Gets the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiverAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)

Please note that because Electron is not built targetting the 10.14 SDK your applications
`effectiveAppearance` will always default to "light" and never automatically inherit the OS
level setting.  We have provided a helper method `startAppLevelAppearanceTrackingOS()` which
will emulate this behavior until we start targetting the 10.14 SDK.

### `systemPreferences.getAppLevelAppearance()` _macOS_

Returns `String` | `null` - Can be `dark`, `light` or `unknown`.

Gets the macOS appearance setting that is you have declared you want for
your application, maps to [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc).
You can use the `setAppLevelAppearance` API to set this value.

### `systemPreferences.setAppLevelAppearance(appearance)` _macOS_

* `appearance` String | null - Can be `dark` or `light`

Sets the appearance setting for your application, this should override the
system default and override the value of `getEffectiveAppearance`.

### `systemPreferences.startAppLevelAppearanceTrackingOS()` _macOS_

This is a helper method to make your applications "appearance" setting track the
users OS level appearance setting.  I.e. Your app will have dark mode enabled if
the users system has dark mode enabled.

You can track this automatic change with the `appearance-changed` event.

### `systemPreferences.stopAppLevelAppearanceTrackingOS()` _macOS_

This is a helper method to stop your application tracking the OS level appearance
setting.  It is a no-op if you have not called `startAppLevelAppearanceTrackingOS()`

Please note the lack of tests is currently delibrate due to our tests not running on mojave machines (so these APIs are all noops)

Notes: Added systemPreferences APIs to help apps respect mojave dark mode settings


Returns `String` | `null` - Can be `dark`, `light` or `unknown`.

Gets the macOS appearance setting that is you have declared you want for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/is //


### `systemPreferences.startAppLevelAppearanceTrackingOS()` _macOS_

This is a helper method to make your applications "appearance" setting track the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

application's


This is a helper method to make your applications "appearance" setting track the
users OS level appearance setting. I.e. Your app will have dark mode enabled if
the users system has dark mode enabled.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user's

@@ -141,7 +141,7 @@ BrowserWindow.fromId = (id) => {
}

BrowserWindow.getAllWindows = () => {
return TopLevelWindow.getAllWindows().filter(isBrowserWindow)
return TopLevelWindow.getAllWindows()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems significant.

semver/minor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is a mis-commit, will remove

: 'light'

systemPreferences.emit('appearance-changed', newAppearance)
systemPreferences.setAppLevelAppearance(newAppearance)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should appearance-changed emit after the appearance has been changed?

### `systemPreferences.startAppLevelAppearanceTrackingOS()` _macOS_

This is a helper method to make your applications "appearance" setting track the
users OS level appearance setting. I.e. Your app will have dark mode enabled if
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • s/users/user's/

  • s/Your/your/


if (val.name == NSAppearanceNameAqua) {
return mate::ConvertToV8(isolate, "light");
} else if (val.name == NSAppearanceNameDarkAqua) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent_ use of else if after a return clause.

This is a style thing that I would let slide but there's a conditional return just above this paragraph and another return immediately following, making the inconsistency more jarring.

This would be good:

if (val == nil) {
  return v8::Null(isolate);
}
if (val.name == NSAppearanceNameAqua) {
  return mate::ConvertToV8(isolate, "light");
}
if (val.name == NSAppearanceNameDarkAqua) {
  return mate::ConvertToV8(isolate, "dark");
}
return mate::ConvertToV8(isolate, "unknown")

This would also be OK:

if (val == nil) {
  return v8::Null(isolate);
} else if (val.name == NSAppearanceNameAqua) {
  return mate::ConvertToV8(isolate, "light");
} else if (val.name == NSAppearanceNameDarkAqua) {
  return mate::ConvertToV8(isolate, "dark");
} else {
  return mate::ConvertToV8(isolate, "unknown")
}

Gets the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiverAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)

Please note that because Electron is not built targetting the 10.14 SDK your applications
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • s/not built/not yet built/
  • targeting
  • s/SDK/SDK,/
  • application's

maps to [NSApplication.effectiverAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)

Please note that because Electron is not built targetting the 10.14 SDK your applications
`effectiveAppearance` will always default to "light" and never automatically inherit the OS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confusing use of 'never' here since we're implying that it will work correctly once Electron is built targeting the 10.14 SDK.

Possibly better:

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 we have provided a helper method startAppLevelAppearanceTrackingOS() which emulates this behavior.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually -- rather than make this a public API that people will have to opt-in on and which we'll have to deprecate after moving to 10.14 SDK -- why not make this run automatically so that the color scheme will Just Work both before and after the SDK switch?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not make this run automatically so that the color scheme will Just Work both before and after the SDK switch?

This is a good question, I personally wouldn't want this to be forced upon apps because enabling dark mode in your app is more complex than just the native macOS UI looking dark mode. For instance if we forced this on all app's context menus would become dark themed, which may not look too good with a light themed app.

In my mind, this would be opt-in for apps that have a dark theme, and once we move to 10.14's SDK the auto-move can be opt-out through a field in the Info.plist which we can document once we make that move. (There is a built-in field macOS respects to not auto-switch that Chrome uses at the moment)

I'll add a note to this API though that it is exempt from the standard deprecation cycle, it will be removed in a single major bump at some point in the future because as soon as we reach 10.14 this API will be pointless and probably not work correctly.

@MarshallOfSound
Copy link
Member Author

@ckerr Updated 👍

Returns `String` - Can be `dark`, `light` or `unknown`.

Gets the macOS appearance setting that is currently applied to your application,
maps to [NSApplication.effectiverAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NSApplication.effectiveAppearance]?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't objective c, it's intended to indicate a property style value to JS devs that they can click on to learn more

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding an r into "effectiveAppearance" so it's "effectiverAppearance" does that?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more effective that way

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*more effectiver

@MarshallOfSound MarshallOfSound changed the title feat: add APIs to support mojave dark mode feat: add APIs to support mojave dark modes Sep 27, 2018
@ckerr ckerr merged commit 0d2a0c7 into master Sep 27, 2018
@ckerr ckerr deleted the majove-dark-mode branch September 27, 2018 15:33
@release-clerk
Copy link

release-clerk bot commented Sep 27, 2018

Release Notes Persisted

Added systemPreferences APIs to help apps respect mojave dark mode settings

codebytere pushed a commit that referenced this pull request Sep 27, 2018
* feat: add APIs to support mojave dark mode

Closes #13387

* docs: fix system-prefs typo
@vanejung
Copy link

vanejung commented Oct 6, 2018

@MarshallOfSound Perhaps this is going to be a dumb question..

I've added the code below in the main process in order to dynamically set a theme status state in my app.

const { ..., systemPreferences } = require('electron')
systemPreferences.startAppLevelAppearanceTrackingOS()
systemPreferences.on('appearance-changed', (newAppearance) => {
    mainWindow.send('theme-mode', newAppearance)
})

But I'm getting TypeError: systemPreferences.startAppLevelAppearanceTrackingOS is not a function ....

What did I do wrong here? :(

@vanejung
Copy link

vanejung commented Oct 7, 2018

@MarshallOfSound Don't mind me... Fixed own problem by doing this instead,

systemPreferences.subscribeNotification('AppleInterfaceThemeChangedNotification', () => {
    mainWindow.send('theme-mode', systemPreferences.isDarkMode())
})

Got the idea from here. - sindresorhus/caprine#510

@markozxuu
Copy link

@MarshallOfSound In what version is this change available? ^-^

@ckerr
Copy link
Member

ckerr commented Oct 11, 2018

@mapeso I believe this is in 4.0.0-beta.1

@RyanZim
Copy link

RyanZim commented Oct 17, 2018

Are there plans to backport this to 3.x or 2.x release lines?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/minor backwards-compatible functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants