From cff08804d3cd97ed5a7a4b70cf0391a4ad1b8deb Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Fri, 6 May 2022 21:10:40 +0100 Subject: [PATCH] feat: add reference at --- src/cljc/athens/common_events/bfs.cljc | 11 ++++-- src/cljs/athens/events.cljs | 4 +- .../views/blocks/autocomplete_search.cljs | 3 +- src/cljs/athens/views/blocks/core.cljs | 2 +- .../athens/views/blocks/textarea_keydown.cljs | 38 ++++++++++++++++++- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/cljc/athens/common_events/bfs.cljc b/src/cljc/athens/common_events/bfs.cljc index 0cd34139d1..63d9e0e1f2 100644 --- a/src/cljc/athens/common_events/bfs.cljc +++ b/src/cljc/athens/common_events/bfs.cljc @@ -117,8 +117,10 @@ ;; - else the parent is the current block's parent current-block-parent? (and children open) + is-page? (common-db/get-page-title db uid) empty-block? (and (string/blank? local-str) - (empty? children)) + (empty? children) + (not is-page?)) new-block-str? (not= local-str string) ;; If block has a new local-str, write that block-save-op (when new-block-str? @@ -135,8 +137,11 @@ empty-block? current-block-parent-uid current-block-parent? uid :else current-block-parent-uid) - default-position (common-db/compat-position db {:block/uid block-position - :relation new-block-order}) + default-position (common-db/compat-position db (if is-page? + {:page/title (common-db/get-page-title db uid) + :relation :last} + {:block/uid block-position + :relation new-block-order})) ir-ops (internal-representation->atomic-ops db internal-representation default-position) remove-op (when empty-block? (graph-ops/build-block-remove-op db uid))] diff --git a/src/cljs/athens/events.cljs b/src/cljs/athens/events.cljs index 69999f7b85..542ad6b9c7 100644 --- a/src/cljs/athens/events.cljs +++ b/src/cljs/athens/events.cljs @@ -1625,11 +1625,11 @@ (reg-event-fx :paste-internal [(interceptors/sentry-span-no-new-tx "paste-internal")] - (fn [_ [_ uid local-str internal-representation]] + (fn [_ [_ uid local-str internal-representation target-uid]] (when (seq internal-representation) (let [[uid] (db/uid-and-embed-id uid) op (bfs/build-paste-op @db/dsdb - uid + (or target-uid uid) local-str internal-representation) new-titles (graph-ops/ops->new-page-titles op) diff --git a/src/cljs/athens/views/blocks/autocomplete_search.cljs b/src/cljs/athens/views/blocks/autocomplete_search.cljs index ee2a445ba9..a16a9736bf 100644 --- a/src/cljs/athens/views/blocks/autocomplete_search.cljs +++ b/src/cljs/athens/views/blocks/autocomplete_search.cljs @@ -13,6 +13,7 @@ f (case (:search/type @state) :hashtag textarea-keydown/auto-complete-hashtag :template textarea-keydown/auto-complete-template + :at textarea-keydown/auto-complete-at textarea-keydown/auto-complete-inline)] (f state target expansion))) @@ -22,7 +23,7 @@ (fn [block state] (let [{:keys [last-e]} @state {:search/keys [index results type query]} @state - is-open (some #(= % type) [:page :block :hashtag :template])] + is-open (some #(= % type) [:page :block :hashtag :template :at])] [:> Autocomplete {:event last-e :isOpen is-open :onClose #(swap! state assoc :search/type false)} diff --git a/src/cljs/athens/views/blocks/core.cljs b/src/cljs/athens/views/blocks/core.cljs index 1516e7f5f5..935eb024cd 100644 --- a/src/cljs/athens/views/blocks/core.cljs +++ b/src/cljs/athens/views/blocks/core.cljs @@ -290,7 +290,7 @@ {:block/keys [uid original-uid]} block state (r/atom {:string/local nil :string/previous nil - ;; one of #{:page :block :slash :hashtag :template} + ;; one of #{:page :block :slash :hashtag :template :at} :search/type nil :search/results nil :search/query nil diff --git a/src/cljs/athens/views/blocks/textarea_keydown.cljs b/src/cljs/athens/views/blocks/textarea_keydown.cljs index e8d6a3eb90..66cc09cb0d 100644 --- a/src/cljs/athens/views/blocks/textarea_keydown.cljs +++ b/src/cljs/athens/views/blocks/textarea_keydown.cljs @@ -133,12 +133,14 @@ :page db/search-in-node-title :hashtag db/search-in-node-title :template db/search-in-block-content + :at db/search-in-node-title :slash filter-slash-options) regex (case type :block #"(?s).*\(\(" :page #"(?s).*\[\[" :hashtag #"(?s).*#" :template #"(?s).*;;" + :at #"(?s).*@" :slash #"(?s).*/") find (re-find regex head) query-start-idx (count find) @@ -302,6 +304,32 @@ (swap! state assoc :search/type nil)))))) +;; see `auto-complete-slash` for how this arity-overloaded +;; function is used. +(defn auto-complete-at + ([state e] + (let [{:search/keys [index results]} @state + target (.. e -target) + {:keys [node/title]} (nth results index nil) + expansion title] + (auto-complete-at state target expansion))) + + ([state target expansion] + (let [{:keys [start head]} (destruct-target target) + start-idx (count (re-find #"(?s).*@" head)) + uid (:block/uid @state) + page-uid (common-db/get-page-uid @db/dsdb expansion) + ref-ir [{:block/uid (common.utils/gen-block-uid) + :block/string (str "((" uid "))")}]] + (if (nil? expansion) + (swap! state assoc :search/type nil) + (do + (set-selection target start-idx start) + (replace-selection-with (str "[[" expansion "]]")) + (swap! state assoc :search/type nil) + (dispatch [:paste-internal uid (:string/local @state) ref-ir page-uid])))))) + + ;; Arrow Keys @@ -492,7 +520,8 @@ :page (auto-complete-inline state e) :block (auto-complete-inline state e) :hashtag (auto-complete-hashtag state e) - :template (auto-complete-template state e)) + :template (auto-complete-template state e) + :at (auto-complete-at state e)) ;; shift-enter: add line break to textarea and move cursor to the next line. shift (replace-selection-with "\n") ;; cmd-enter: cycle todo states, then move cursor to the end of the line. @@ -760,6 +789,8 @@ (and (= "#" look-behind-char) (= type :hashtag)) (swap! state assoc :search/type nil) ;; semicolon: close dropdown (and (= ";" look-behind-char) (= type :template)) (swap! state assoc :search/type nil) + ;; at symbol: close dropdown + (and (= "@" look-behind-char) (= type :at)) (swap! state assoc :search/type nil) ;; dropdown is open: update query type (update-query state head "" type)))) @@ -801,6 +832,11 @@ :search/query "" :search/type :template :search/results []) + (and (= key "@") (nil? type)) (swap! state assoc + :search/index 0 + :search/query "" + :search/type :at + :search/results []) type (update-query state head key type))))