Setting WKWebView's inheriting Appearance to InterfaceStyle: .Dark on macOS 10.13 (or iOS 12) and earlier

Viewed 777

I currently have a project that is based around a web-app, embedded in a WKWebView. When triggered by the user, the application's NSApplication.appearance will toggle between .aqua light mode and .darkAqua dark mode (see Apple Docs). Since the web-app is setup to inherit its parent container, the web-app will toggle between its own light and dark mode, obeying whatever the application does.

However, today I started adding support for macOS 10.13 and below (equivalently, in this case, iOS 12 and below). Since Apple only released Dark Mode in macOS 10.14 (iOS 13), I'm running into problems with forcing the web-app to switch to dark mode (as light mode is the only option on those prior versions of macOS). Similarly, Apple only introduced Dark Mode on iOS 13; however, if a web-app already has Dark Mode capability, there must be some way to enforce that on a device running iOS 12, no?

Is there any way that I could go about forcibly telling the content, embedded in a WKWebView, that its parent container is running dark mode? Maybe through a key-value or JavaScript evaluation?

Key-Value

ie. Setting the WKWebView's background to be transparent: webView.setValue(false, forKey: "drawsBackground")

What I'm going for:

webView.setValue(1, forKey: "appearance")            // where 0 is light mode
webView.setValue(currentMode.Dark, forKey: "InterfaceStyle")
webView.setValue("Dark", forKey: "AppleInterfaceStyle")

enum InterfaceStyle: String {
    case Dark, Light
    init() {
        let type = UserDefaults.standard.string(forKey: "AppleInterfaceStyle") ?? "Light"
        self = InterfaceStyle(rawValue: type)!
    }
}
let currentMode = InterfaceStyle()

However, this may also be problematic as the light/dark mode is dynamically changing, based on whenever the user switches their system NSAppearance (or toggles to dark mode, in my app, with the code below).

JavaScript evaluation

Alternatively, maybe there is a way to do this through WKWebView's JavaScript evaluation?

For reference, the web app in question is the Apple Music Web Player. When switching the app's appearance with NSAppearance(named: .darkAqua), the Web Player's entire UI switches to dark mode in real-time.

This is what I have thus far:

let App = NSApplication.shared
func setDarkMode(_ mode: Bool) {
    if #available(OSX 10.14, *) {
        if mode {
            App.appearance = NSAppearance(named: .darkAqua)     // Force Dark Mode UI
        } else {
            App.appearance = NSAppearance(named: .aqua)         // Force Light Mode UI
        }
    } else { print("System running macOS 10.13 or earlier, Dark Mode is disabled") }
}

I'm not entirely sure where to go from here. There must be some way to tell the WKWebView content to run in dark mode without the dedicated NS/UIAppearance properties introduced in macOS 10.14 and iOS 13.

Feel free to also look through the code on GitHub: https://github.com/revblaze/AppleMusicUltra

EDIT: Apple's Safari now includes a Force Dark Mode option in the Elements tab of the Inspector. I wonder how they're going about the functionality for that button.

0 Answers
Related