Przeglądaj źródła

feat: sync theme with system & add settings options

charlie 4 lat temu
rodzic
commit
473c6b0d8b

+ 49 - 0
src/main/frontend/components/settings.css

@@ -58,6 +58,55 @@
         @apply text-sm;
       }
     }
+
+    .theme-modes-options {
+      @apply flex items-center list-none m-0;
+
+      > li {
+        @apply m-0 pr-2 opacity-90 hover:opacity-100;
+
+        &:hover {
+          cursor: pointer;
+        }
+
+        &.active {
+          @apply opacity-100;
+          cursor: inherit;
+
+          > i {
+            border-color: var(--ls-link-text-color);
+            border-width: 2px;
+          }
+        }
+
+        > i {
+          display: block;
+          width: 80px;
+          height: 57px;
+          background-color: #a4b5b6;
+          background: url("../img/theme-modes.png") no-repeat;
+          background-size: 355%;
+          border-radius: 4px;
+          overflow: hidden;
+          border-width: 0;
+          border-style: solid;
+          border-color: transparent;
+
+
+          &.mode-dark {
+            background-position-x: -97px;
+          }
+
+          &.mode-system {
+            background-position-x: -194px;
+          }
+        }
+
+        > strong {
+          @apply block pr-2 pt-1.5 text-center text-xs font-medium;
+        }
+      }
+    }
   }
 
   &-app-updater {

+ 2 - 0
src/main/frontend/components/sidebar.cljs

@@ -288,6 +288,7 @@
         current-repo (state/sub :git/current-repo)
         granted? (state/sub [:nfs/user-granted? (state/get-current-repo)])
         theme (state/sub :ui/theme)
+        system-theme? (state/sub :ui/system-theme?)
         white? (= "white" (state/sub :ui/theme))
         settings-open? (state/sub :ui/settings-open?)
         sidebar-open?  (state/sub :ui/sidebar-open?)
@@ -305,6 +306,7 @@
         :route         route-match
         :nfs-granted?  granted?
         :db-restoring? db-restoring?
+        :system-theme? system-theme?
         :on-click      editor-handler/unhighlight-blocks!}
 
        [:div.theme-inner

+ 7 - 1
src/main/frontend/components/theme.cljs

@@ -1,11 +1,12 @@
 (ns frontend.components.theme
   (:require [rum.core :as rum]
             [frontend.util :as util]
+            [frontend.ui :as ui]
             [frontend.handler.route :as route-handler]
             [frontend.components.svg :as svg]))
 
 (rum/defc container
-  [{:keys [route theme on-click nfs-granted? db-restoring?] :as props} child]
+  [{:keys [route theme on-click nfs-granted? db-restoring? system-theme?] :as props} child]
   (rum/use-effect!
    #(let [doc js/document.documentElement
           cls (.-classList doc)]
@@ -23,6 +24,11 @@
           (route-handler/update-page-title! route))))
    [nfs-granted? db-restoring? route])
 
+  (rum/use-effect!
+   #(when system-theme?
+      (ui/setup-system-theme-effect!))
+   [system-theme?])
+
   [:div
    {:class    (str theme "-theme")
     :on-click on-click}

+ 3 - 3
src/main/frontend/dicts.cljs

@@ -92,7 +92,7 @@
         :strikethrough "Strikethrough"
         :code "Code"
         :right-side-bar/help "Help"
-        :right-side-bar/switch-theme "Switch to {1} theme"
+        :right-side-bar/switch-theme "Theme modes"
         :right-side-bar/theme "{1} theme"
         :right-side-bar/page "Page graph"
         :right-side-bar/recent "Recent"
@@ -756,7 +756,7 @@
            :strikethrough "删除线"
            :code "代码"
            :right-side-bar/help "帮助"
-           :right-side-bar/switch-theme "切换到 {1} 主题"
+           :right-side-bar/switch-theme "主题模式"
            :right-side-bar/theme "{1}主题"
            :right-side-bar/page "页面图谱"
            :right-side-bar/recent "最近"
@@ -1012,7 +1012,7 @@
              :strikethrough "刪除線"
              :code "代碼"
              :right-side-bar/help "幫助"
-             :right-side-bar/switch-theme "切換到 {1} 主題"
+             :right-side-bar/switch-theme "主題模式"
              :right-side-bar/theme "{1}主題"
              :right-side-bar/page "頁面圖譜"
              :right-side-bar/recent "最近"

+ 18 - 2
src/main/frontend/state.cljs

@@ -54,6 +54,7 @@
     :ui/sidebar-open? false
     :ui/left-sidebar-open? false
     :ui/theme (or (storage/get :ui/theme) "dark")
+    :ui/system-theme? (or (storage/get :ui/system-theme?) true)
     :ui/wide-mode? false
     ;; :show-all, :hide-block-body, :hide-block-children
     :ui/cycle-collapse :show-all
@@ -735,8 +736,7 @@
              ;; use set-change-value for now
              ;; until somebody can figure out why set! value doesn't work here
              ;; it seems to me textarea autoresize is completely broken
-             #_
-             (set! (.-value input) (string/trim content)))
+             #_(set! (.-value input) (string/trim content)))
            (when move-cursor?
              (util/move-cursor-to input pos))))))))
 
@@ -761,6 +761,22 @@
   (set-state! :ui/theme theme)
   (storage/set :ui/theme theme))
 
+(defn sync-system-theme!
+  []
+  (let [system-dark? (.-matches (js/window.matchMedia "(prefers-color-scheme: dark)"))]
+    (set-theme! (if system-dark? "dark" "white"))
+    (set-state! :ui/system-theme? true)
+    (storage/set :ui/system-theme? true)))
+
+(defn use-theme-mode!
+  [theme-mode]
+  (if-not (= theme-mode "system")
+    (do
+      (set-theme! (if (= theme-mode "light") "white" "dark"))
+      (set-state! :ui/system-theme? false)
+      (storage/set :ui/system-theme? false))
+    (sync-system-theme!)))
+
 (defn dark?
   []
   (= "dark" (:ui/theme @state)))

+ 7 - 0
src/main/frontend/ui.cljs

@@ -284,6 +284,13 @@
         (.removeEventListener viewport "resize" handler)
         (.removeEventListener viewport "scroll" handler)))))
 
+(defn setup-system-theme-effect!
+  []
+  (let [^js schemaMedia (js/window.matchMedia "(prefers-color-scheme: dark)")]
+    (.addEventListener schemaMedia "change" state/sync-system-theme!)
+    (state/sync-system-theme!)
+    #(.removeEventListener schemaMedia "change" state/sync-system-theme!)))
+
 (defn on-scroll
   [node on-load on-top-reached]
   (let [full-height (gobj/get node "scrollHeight")

+ 15 - 0
src/main/frontend/util.cljc

@@ -1358,3 +1358,18 @@
                         (apply min))
                    (count val))]
        (.setRangeText input "" current (inc idx)))))
+
+(defn classnames
+  "Like react classnames utility:
+
+     ```
+      [:div {:class (classnames [:a :b {:c true}])}
+     ```
+  "
+  [args]
+  (into #{} (mapcat
+              #(if (map? %)
+                 (for [[k v] %]
+                   (when v (name k)))
+                 (name %))
+              args)))