Parcourir la source

enhance: ace-jump like

Tienson Qin il y a 1 an
Parent
commit
d3b4d0087b

+ 0 - 3
src/main/frontend/components/container.cljs

@@ -48,7 +48,6 @@
             [frontend.util :as util]
             [frontend.util.cursor :as cursor]
             [frontend.components.window-controls :as window-controls]
-            [frontend.components.jump :as jump]
             [medley.core :as medley]
             [goog.dom :as gdom]
             [goog.object :as gobj]
@@ -921,8 +920,6 @@
         (when (util/electron?)
           (find-in-page/search))
 
-        (jump/jump)
-
         (main {:route-match         route-match
                :margin-less-pages?  margin-less-pages?
                :logged?             logged?

+ 0 - 44
src/main/frontend/components/jump.cljs

@@ -1,44 +0,0 @@
-(ns frontend.components.jump
-  "Jump to"
-  (:require [frontend.state :as state]
-            [rum.core :as rum]
-            [frontend.util :as util]
-            [frontend.handler.jump :as jump-handler]))
-
-(defn- exit!
-  []
-  (state/set-state! :editor/jump-data nil)
-  (jump-handler/clear-jump-hints!))
-
-(rum/defcs input <
-  (rum/local "" ::q)
-  [state {:keys [triggers _mode]}]      ; TODO: jump to block
-  (let [*q (::q state)]
-    [:div.flex.w-full.relative
-     [:input.form-input.block.sm:text-sm.my-2.border-none.outline-none
-      {:auto-focus true
-       :placeholder "Jump to"
-       :aria-label "Jump to"
-       :value @*q
-       :on-change (fn [e] (reset! *q (util/evalue e)))
-       :on-key-down (fn [e]
-                      (util/stop-propagation e)
-                      (case (util/ekey e)
-                        "Enter"
-                        (when-let [idx (util/safe-parse-int @*q)]
-                          (when (> idx 0)
-                            (when-let [elem (nth triggers (dec idx))]
-                              (state/clear-selection!)
-                              (exit!)
-                              (.click elem))))
-                        "Escape"
-                        (exit!)
-                        nil))}]]))
-
-(rum/defc jump < rum/reactive
-  []
-  (let [data (state/sub :editor/jump-data)]
-    (when data
-      [:div#bottom-console.flex.flex-1.flex-row.absolute.top-10.right-2.shadow-lg.px-2.py-1.faster-fade-in.items-center
-
-       (input data)])))

+ 3 - 2
src/main/frontend/components/property.cljs

@@ -660,11 +660,12 @@
                         (:block/page v-block)
                         (contains? #{:default :template} type))
             collapsed? (when block? (property-collapsed? block property))
-            date? (= type :date)]
+            date? (= type :date)
+            checkbox? (= type :checkbox)]
         [:div {:class (cond
                         (and block? (not closed-values?))
                         "flex flex-1 flex-col gap-1 property-block"
-                        date?
+                        (or date? checkbox?)
                         "property-pair items-center"
                         :else
                         "property-pair items-start")}

+ 3 - 3
src/main/frontend/components/property/value.cljs

@@ -92,7 +92,7 @@
      (shui/dropdown-menu
       {:open open?}
       (shui/dropdown-menu-trigger
-       {:class "jtrigger flex"
+       {:class "jtrigger flex flex-row items-center"
         :on-click (fn [e]
                     (if config/publishing?
                       (navigate-to-date-page value)
@@ -593,7 +593,7 @@
      {:open open?}
      (shui/dropdown-menu-trigger
       {:class "jtrigger flex flex-1"
-       :on-pointer-down #(set-open! (not open?))
+       :on-click #(set-open! (not open?))
        :on-key-down (fn [e]
                       (when (= " " (util/ekey e))
                         (set-open! true)))}
@@ -646,7 +646,7 @@
         :checkbox
         (let [add-property! (fn []
                               (<add-property! block (:block/original-name property) (boolean (not value))))]
-          (shui/checkbox {:class "jtrigger"
+          (shui/checkbox {:class "jtrigger flex flex-row items-center"
                           :checked value
                           :auto-focus editing?
                           :on-checked-change add-property!

+ 96 - 13
src/main/frontend/handler/jump.cljs

@@ -1,28 +1,111 @@
 (ns frontend.handler.jump
   "Jump to property key/value"
   (:require [frontend.state :as state]
-            [dommy.core :as d]))
+            [dommy.core :as d]
+            [clojure.string :as string]
+            [frontend.util :as util]))
+
+(defonce *current-keys (atom nil))
+(defonce *jump-data (atom {}))
+
+(def prefix-keys ["j" "k" "l"])
+(def keys
+  ["a"
+   "s"
+   "d"
+   "f"
+   "g"
+   "h"
+   "q"
+   "w"
+   "e"
+   "r"
+   "t"
+   "y"
+   "u"
+   "i"
+   "o"
+   "p"
+   "z"
+   "x"
+   "c"
+   "v"
+   "b"
+   "n"
+   "m"])
+
+(defonce full-start-keys (set (concat prefix-keys keys)))
+
+(defn generate-keys
+  "Notice: at most 92 keys for now"
+  [n]
+  (vec
+   (take n
+         (concat keys
+                 (mapcat
+                  (fn [k]
+                    (map #(str k %) keys))
+                  prefix-keys)))))
 
 (defn clear-jump-hints!
   []
-  (dorun (map d/remove! (d/sel ".jtrigger-id"))))
+  (dorun (map d/remove! (d/sel ".jtrigger-id")))
+  (reset! *current-keys nil))
+
+(defn exit!
+  []
+  (when-let [event-handler (:key-down-handler @*jump-data)]
+    (.removeEventListener js/window "keydown" event-handler))
+  (reset! *current-keys nil)
+  (reset! *jump-data {})
+  (clear-jump-hints!))
+
+(defn get-trigger
+  [triggers key]
+  (when-let [idx (.indexOf @*current-keys key)]
+    (nth triggers idx)))
+
+(defn trigger!
+  [key e]
+  (let [{:keys [triggers _mode]} @*jump-data]
+    (when-let [trigger (get-trigger triggers (string/trim key))]
+      (util/stop e)
+      (state/clear-selection!)
+      (exit!)
+      (.click trigger))))
 
 (defn jump-to
   []
   (let [selected-block (first (state/get-selection-blocks))]
     (cond
       selected-block
-      (let [triggers (d/sel selected-block ".jtrigger")]
-        (when (seq triggers)
-          (state/set-state! :editor/jump-data {:mode :property
-                                        :triggers (d/sel selected-block ".jtrigger")})
-          (doall
-           (map-indexed
-            (fn [id dom]
-              (d/append! dom (-> (d/create-element :span)
-                                 (d/set-attr! :class "jtrigger-id text-sm border rounded ml-2 px-1 shadow-xs")
-                                 (d/set-text! (str (inc id))))))
-            triggers))))
+      (when (empty? (d/sel js/document ".jtrigger-id"))
+        (let [triggers (d/sel selected-block ".jtrigger")]
+          (when (seq triggers)
+            (reset! *jump-data {:mode :property
+                                :triggers (d/sel selected-block ".jtrigger")})
+            (let [keys (generate-keys (count triggers))
+                  key-down-handler (fn [e]
+                                     (let [k (util/ekey e)]
+                                       (if (= k "Escape")
+                                         (exit!)
+                                         (when (and (contains? full-start-keys k) (seq (:triggers @*jump-data)))
+                                           (swap! *jump-data update :chords (fn [s] (str s (util/ekey e))))
+                                           (let [chords (:chords @*jump-data)]
+                                             (trigger! chords e))))))]
+              (swap! *jump-data assoc :key-down-handler key-down-handler)
+              (reset! *current-keys keys)
+              (doall
+               (map-indexed
+                (fn [id dom]
+                  (let [class (if (d/has-class? dom "ui__checkbox")
+                                "jtrigger-id text-sm border rounded ml-4 px-1 shadow-xs"
+                                "jtrigger-id text-sm border rounded ml-2 px-1 shadow-xs")]
+                    (d/append! dom (-> (d/create-element :div)
+                                       (d/set-attr! :class class)
+                                       (d/set-text! (nth keys id))))))
+                triggers))
+              (.addEventListener js/window "keydown" key-down-handler)))))
 
       :else                             ; add block jump support
       nil)))

+ 1 - 1
src/main/frontend/modules/shortcut/config.cljs

@@ -508,7 +508,7 @@
    :command/toggle-favorite                 {:binding "mod+shift+f"
                                              :fn      page-handler/toggle-favorite!}
 
-   :editor/jump                             {:binding "j"
+   :editor/jump                             {:binding "mod+j"
                                              :fn      jump-handler/jump-to}
    :editor/open-file-in-default-app         {:binding  "mod+d mod+a"
                                              :inactive (not (util/electron?))

+ 0 - 1
src/main/frontend/state.cljs

@@ -121,7 +121,6 @@
       :block/component-editing-mode?         false
       :editor/start-pos                      (atom nil)
       :editor/op                             (atom nil)
-      :editor/jump-data                      (atom nil)
       :editor/hidden-editors                 #{} ;; page names
       :editor/draw-mode?                     false
       :editor/action                         (atom nil)