Browse Source

enhance(capacitor): direction keys management for the block editor

charlie 5 months ago
parent
commit
1ef089b3eb

+ 34 - 0
src/main/capacitor/components/blocks.cljs

@@ -3,6 +3,7 @@
             [clojure.string :as string]
             [frontend.db.model :as db-model]
             [frontend.util.cursor :as cursor]
+            [dommy.core :as dom]
             [promesa.core :as p]
             [rum.core :as rum]
             [frontend.db.async :as db-async]
@@ -93,6 +94,29 @@
                 opts {:edit-block? false})]
     (editor-handler/api-insert-new-block! content opts')))
 
+(defn dom-prev-block
+  [^js current-block-node]
+  (when-let [prev-node (loop [node current-block-node]
+                         (when-let [node (some-> node (.-previousSibling))]
+                           (when node
+                             (if (dom/has-class? node "block-item")
+                               node
+                               (recur node)))))]
+    (let [uuid' (.-blockid (.-dataset prev-node))]
+      (db-model/get-block-by-uuid (uuid uuid')))))
+
+(defn dom-next-block
+  [^js current-block-node]
+  (when-let [next-node (loop [node current-block-node]
+                         (when-let [node (some-> node (.-nextSibling))]
+                           (when node
+                             (if (dom/has-class? node "block-item")
+                               node
+                               (recur node)))))]
+    (prn :debug next-node)
+    (let [uuid' (.-blockid (.-dataset next-node))]
+      (db-model/get-block-by-uuid (uuid uuid')))))
+
 ;; components
 (rum/defc block-editor
   [block]
@@ -108,6 +132,16 @@
              (cursor/move-cursor-to input cursor-at)
              (cursor/move-cursor-to-end input))))
 
+       :on-bounded!
+       (fn [dir ^js input]
+         (case dir
+           :up (when-let [prev-block (dom-prev-block (.closest input ".block-item"))]
+                 (state/edit-block! prev-block {}))
+           :down (when-let [next-block (dom-next-block (.closest input ".block-item"))]
+                   (js/console.log next-block)
+                   (state/edit-block! next-block {}))
+           :dune))
+
        :on-outside!
        (fn [^js e]
          (let [edit-target? (some-> e (.-target) (cc-common/get-dom-block-uuid))]

+ 16 - 5
src/main/capacitor/components/editor.cljs

@@ -1,13 +1,14 @@
 (ns capacitor.components.editor
   (:require [rum.core :as rum]
             [capacitor.components.ui :as ui]
+            [cljs-bean.core :as bean]
             [capacitor.ionic :as ionic]
             [frontend.util.cursor :as cursor]
             [frontend.util :as util]
             [frontend.handler.notification :as notification]))
 
 (rum/defc editor-aux
-  [content {:keys [on-outside! on-save! on-delete! on-focused! on-keydown! on-keyup!]}]
+  [content {:keys [on-outside! on-save! on-delete! on-focused! on-keydown! on-keyup! on-bounded!]}]
 
   (let [*input (rum/use-ref nil)]
 
@@ -48,25 +49,35 @@
       (ui/textarea
         {:class "editor-aux-input bg-gray-200 border-none"
          :ref *input
+         :on-change (fn [] (debounce-save-handle!))
          :on-key-down (fn [^js e]
                         (let [ekey (.-key e)
                               target (.-target e)
                               enter? (= ekey "Enter")
                               esc? (= ekey "Escape")
-                              backspace? (= ekey "Backspace")]
+                              backspace? (= ekey "Backspace")
+                              arrow-up? (= ekey "ArrowUp")
+                              arrow-down? (= ekey "ArrowDown")]
 
                           (when (or (nil? on-keydown!)
                                   (not (false? (on-keydown! e))))
                             (cond
+                              (or arrow-up? arrow-down?)
+                              (when-let [{:keys [isFirstLine isLastLine]} (some-> (.checkCursorLine js/window.externalsjs target) (bean/->clj))]
+                                (when (and on-bounded! (or (and arrow-up? isFirstLine)
+                                                         (and arrow-down? isLastLine)))
+                                  (on-bounded! (if arrow-up? :up :down) target)
+                                  (util/stop e)))
+
                               (or (and enter? (cursor/end? target)) esc?)
                               (do (save-handle! {:enter? enter? :esc? esc?})
                                 (util/stop e))
 
-                              (and backspace? (cursor/start? target))
+                              (and backspace?
+                                (cursor/start? target)
+                                (not (util/input-text-selected? target)))
                               (do (delete-handle! {})
                                 (util/stop e))
-
-                              :else (debounce-save-handle!)
                               ))))
          :on-key-up (fn [^js e]
                       (when on-keyup!

+ 16 - 0
src/main/capacitor/externals.js

@@ -55,7 +55,23 @@ const settleStatusBar = async () => {
   }
 }
 
+function checkCursorLine (textarea) {
+  const { value, selectionStart } = textarea
+
+  const lines = value.split('\n')
+  const totalLines = lines.length
+
+  const textBeforeCursor = value.substring(0, selectionStart)
+  const currentLine = textBeforeCursor.split('\n').length
+
+  const isFirstLine = currentLine === 1
+  const isLastLine = currentLine === totalLines
+
+  return { isFirstLine, isLastLine, currentLine, totalLines }
+}
+
 window.externalsjs = {
   initGlobalListeners,
   settleStatusBar,
+  checkCursorLine,
 }