From 7f079a8b538571e4fbfade99bc1743626328875b Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Wed, 9 Aug 2023 23:33:07 +0800 Subject: [PATCH] UP/DOWN support for multiple values --- src/main/frontend/components/block.cljs | 5 +- src/main/frontend/components/property.cljs | 5 +- .../frontend/components/property/value.cljs | 47 ++++++++++++++----- .../frontend/handler/editor/lifecycle.cljs | 19 +++++--- src/main/frontend/state.cljs | 5 ++ 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index 975a16a14c..d074fc4638 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -96,7 +96,6 @@ ;; TODO: dynamic (defonce max-depth-of-links 5) -(defonce *blocks-container-id (atom 0)) ;; TODO: ;; add `key` @@ -2489,7 +2488,7 @@ block (db/sub-block block-id) blocks-container-id (if @*init-blocks-container-id @*init-blocks-container-id - (let [id' (swap! *blocks-container-id inc)] + (let [id' (state/next-blocks-container-id)] (reset! *init-blocks-container-id id') id')) block-el-id (str "ls-block-" blocks-container-id "-" uuid) @@ -3343,7 +3342,7 @@ (let [*init-blocks-container-id (::init-blocks-container-id state) blocks-container-id (if @*init-blocks-container-id @*init-blocks-container-id - (let [id' (swap! *blocks-container-id inc)] + (let [id' (state/next-blocks-container-id)] (reset! *init-blocks-container-id id') id')) config (assoc config :blocks-container-id blocks-container-id) diff --git a/src/main/frontend/components/property.cljs b/src/main/frontend/components/property.cljs index 46c1baa3ea..6f1bfa7bbb 100644 --- a/src/main/frontend/components/property.cljs +++ b/src/main/frontend/components/property.cljs @@ -292,7 +292,10 @@ (and (:*configure-show? opts) @(:*configure-show? opts) (empty? properties)) - (= edit-input-id (state/sub :ui/new-property-input-id)))] + (= edit-input-id (state/sub :ui/new-property-input-id))) + opts (if (:blocks-container-id opts) + opts + (assoc opts :blocks-container-id (state/next-blocks-container-id)))] (when-not (and (empty? properties) (not new-property?) (not (:page-configure? opts))) diff --git a/src/main/frontend/components/property/value.cljs b/src/main/frontend/components/property/value.cljs index 0780e27f67..9c5b97ad4b 100644 --- a/src/main/frontend/components/property/value.cljs +++ b/src/main/frontend/components/property/value.cljs @@ -159,8 +159,21 @@ (when-let [f (:on-chosen opts)] (f)) nil))})}))) +(defn- move-cursor + [up? opts] + (let [f (if up? dec inc) + id (str (:parent-dom-id opts) "-" (f (:idx opts))) + editor-id (str (:parent-dom-id opts) "-editor" "-" (f (:idx opts))) + sibling (gdom/getElement id) + editor (gdom/getElement editor-id)] + (when sibling + (.click sibling) + (state/set-state! :editor/property-triggered-by-click? {editor-id true})) + (when editor + (.focus editor)))) + (defn- new-text-editor-opts - [repo block property value type editor-id *add-new-item?] + [repo block property value type editor-id *add-new-item? opts] {:on-blur (fn [e] (let [new-value (util/evalue e) @@ -172,7 +185,8 @@ (:block/original-name property) new-value :old-value value)) - (exit-edit-property) + (when (= js/document.activeElement (gdom/getElement editor-id)) + (exit-edit-property)) (when *add-new-item? (reset! *add-new-item? false))))) :on-key-down (fn [e] @@ -181,8 +195,10 @@ enter? (= (util/ekey e) "Enter") esc? (= (util/ekey e) "Escape") meta? (util/meta-key? e) - create-another-one? (and meta? enter?)] - (when (and (or enter? esc? create-another-one?) + create-another-one? (and meta? enter?) + down? (= (util/ekey e) "ArrowDown") + up? (= (util/ekey e) "ArrowUp")] + (when (and (or enter? esc? create-another-one? down? up?) (not (state/get-editor-action))) (util/stop e) (when-not blank? @@ -191,9 +207,16 @@ (:block/original-name property) new-value :old-value value))) + (exit-edit-property) (cond + down? + (move-cursor false opts) + + up? + (move-cursor true opts) + (or esc? blank? @@ -225,7 +248,8 @@ editor-id dom-id row? editor-box editor-args editing? *add-new-item? *configure-show? - blocks-container-id]}] + blocks-container-id] + :as opts}] (let [property (model/sub-block (:db/id property)) multiple-values? (= :many (:cardinality (:block/schema property))) editor-id (or editor-id (str "ls-property-" blocks-container-id "-" (:db/id block) "-" (:db/id property))) @@ -261,7 +285,7 @@ :block [:div.h-6 (select-block block property select-opts)] - (let [config {:editor-opts (new-text-editor-opts repo block property value type editor-id *add-new-item?)}] + (let [config {:editor-opts (new-text-editor-opts repo block property value type editor-id *add-new-item? opts)}] [:div.pl-1 (editor-box editor-args editor-id (cond-> config multiple-values? @@ -351,12 +375,14 @@ (for [[idx item] (medley/indexed items)] (let [dom-id' (str dom-id "-" idx) - editor-id' (str editor-id idx)] + editor-id' (str editor-id "-" idx)] (rum/with-key (multiple-value-item block property item (merge opts - {:dom-id dom-id' + {:parent-dom-id dom-id + :idx idx + :dom-id dom-id' :editor-id editor-id' :editor-args editor-args :row? row? @@ -394,9 +420,8 @@ (rum/defc property-value < rum/reactive [block property v opts] - (let [k (:block/uuid property) - dom-id (str "ls-property-" (:blocks-container-id opts) "-" k) - editor-id (str "ls-property-" (:blocks-container-id opts) "-" (:db/id block) "-" (:db/id property)) + (let [dom-id (str "ls-property-" (:blocks-container-id opts) "-" (:db/id property)) + editor-id (str dom-id "-editor") schema (:block/schema property) multiple-values? (= :many (:cardinality schema)) editor-args {:block property diff --git a/src/main/frontend/handler/editor/lifecycle.cljs b/src/main/frontend/handler/editor/lifecycle.cljs index fc204fc3a1..65fc3c47b5 100644 --- a/src/main/frontend/handler/editor/lifecycle.cljs +++ b/src/main/frontend/handler/editor/lifecycle.cljs @@ -1,12 +1,13 @@ (ns ^:no-doc frontend.handler.editor.lifecycle - (:require [frontend.handler.editor :as editor-handler :refer [get-state]] + (:require [dommy.core :as d] + [frontend.db :as db] + [frontend.handler.editor :as editor-handler :refer [get-state]] [frontend.handler.editor.keyboards :as keyboards-handler] [frontend.handler.property :as property-handler] [frontend.state :as state :refer [sub]] [frontend.util :as util] - [goog.dom :as gdom] - [dommy.core :as d] - [frontend.db :as db])) + [frontend.util.cursor :as cursor] + [goog.dom :as gdom])) (defn did-mount! [state] @@ -14,8 +15,14 @@ content (get @(get @state/state :editor/content) id)] (when block-parent-id (state/set-editing-block-dom-id! block-parent-id)) - (when content - (editor-handler/restore-cursor-pos! id content)) + ;; FIXME: remove ugly :editor/property-triggered-by-click? + (if (get-in @state/state [:editor/property-triggered-by-click? id]) + (do + (when-let [input (gdom/getElement (str id))] + (cursor/move-cursor-to-end input)) + (state/set-state! :editor/property-triggered-by-click? {})) + (when content + (editor-handler/restore-cursor-pos! id content))) ;; Here we delay this listener, otherwise the click to edit event will trigger a outside click event, ;; which will hide the editor so no way for editing. diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index bd85f71c62..84a4eca86c 100644 --- a/src/main/frontend/state.cljs +++ b/src/main/frontend/state.cljs @@ -103,6 +103,7 @@ true) :ui/scrolling? (atom false) :ui/new-property-input-id nil + :ui/blocks-container-id (atom 0) :document/mode? document-mode? :config {} @@ -2189,3 +2190,7 @@ Similar to re-frame subscriptions" (rum/derived-atom [(rum/cursor-in state [repo :restore/unloaded-blocks])] [::block-unloaded repo block-uuid] (fn [s] (contains? s (str block-uuid)))))) + +(defn next-blocks-container-id + [] + (swap! (:ui/blocks-container-id @state) inc))