mirror of
https://github.com/penpot/penpot.git
synced 2026-10-30 22:40:33 +00:00
74 lines
2.3 KiB
Clojure
74 lines
2.3 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS SUBSIDIARY SL
|
|
|
|
(ns app.util.theme
|
|
(:require
|
|
[app.common.data :as d]
|
|
[app.util.globals :as globals]
|
|
[beicon.v2.core :as rx]
|
|
[rumext.v2 :as mf]))
|
|
|
|
(defonce ^:private color-scheme-media-query
|
|
(.matchMedia globals/window "(prefers-color-scheme: dark)"))
|
|
|
|
(defonce ^:private color-scheme-listeners*
|
|
(atom #{}))
|
|
|
|
(def ^:const default "dark")
|
|
|
|
(defn get-system-theme
|
|
[]
|
|
(if ^boolean (.-matches color-scheme-media-query)
|
|
"dark"
|
|
"light"))
|
|
|
|
(defn- notify-color-scheme-listeners!
|
|
[]
|
|
(doseq [f @color-scheme-listeners*]
|
|
(f)))
|
|
|
|
(defn add-color-scheme-listener!
|
|
"Registers `f` to run after each `body` color-scheme update in
|
|
`use-initialize` (profile theme or OS preference). Returns a dispose fn."
|
|
[f]
|
|
(swap! color-scheme-listeners* conj f)
|
|
(fn [] (swap! color-scheme-listeners* disj f)))
|
|
|
|
(defn- set-color-scheme
|
|
[^string color]
|
|
|
|
(let [node (.querySelector js/document "body")
|
|
class (if (= color "dark") "default" "light")]
|
|
(.removeAttribute node "class")
|
|
(.add ^js (.-classList ^js node) class)))
|
|
|
|
(defn resolve-theme
|
|
"Resolves the profile's theme setting to the effective UI theme ('dark' or
|
|
'light'): 'system' follows the given system theme, 'default' and an unset
|
|
theme mean dark, and any other value is taken as-is. Single source of truth
|
|
for the app's own theme and the theme reported to plugins."
|
|
[profile-theme system-theme]
|
|
(cond
|
|
(= profile-theme "system") system-theme
|
|
(= profile-theme "default") "dark"
|
|
:else (d/nilv profile-theme "dark")))
|
|
|
|
(defn use-initialize
|
|
[{profile-theme :theme}]
|
|
(let [system-theme* (mf/use-state get-system-theme)
|
|
system-theme (deref system-theme*)]
|
|
|
|
(mf/with-effect []
|
|
(let [s (->> (rx/from-event color-scheme-media-query "change")
|
|
(rx/map #(if (.-matches %) "dark" "light"))
|
|
(rx/subs! #(reset! system-theme* %)))]
|
|
(fn []
|
|
(rx/dispose! s))))
|
|
|
|
(mf/with-effect [system-theme profile-theme]
|
|
(set-color-scheme (resolve-theme profile-theme system-theme))
|
|
(notify-color-scheme-listeners!))))
|