mirror of
https://github.com/penpot/penpot.git
synced 2025-05-18 20:06:11 +02:00
Merge pull request #5895 from penpot/niwinz-bugfix-comments
🐛 Fix unexpected exception on clicking empty area on creating comment
This commit is contained in:
commit
4ac52c138c
2 changed files with 121 additions and 114 deletions
|
@ -90,22 +90,29 @@
|
||||||
(dom/set-data! "fullname" fullname)
|
(dom/set-data! "fullname" fullname)
|
||||||
(obj/set! "textContent" fullname)))
|
(obj/set! "textContent" fullname)))
|
||||||
|
|
||||||
(defn- current-text-node
|
(defn- current-text-node*
|
||||||
"Retrieves the text node and the offset that the cursor is positioned on"
|
"Retrieves the text node and the offset that the cursor is positioned on"
|
||||||
[node]
|
[node anchor-node]
|
||||||
|
(when (.contains node anchor-node)
|
||||||
(let [selection (wapi/get-selection)
|
(let [span-node (if (instance? js/Text anchor-node)
|
||||||
range (wapi/get-range selection 0)
|
|
||||||
anchor-node (wapi/range-start-container range)
|
|
||||||
anchor-offset (wapi/range-start-offset range)]
|
|
||||||
(when (and node (.contains node anchor-node))
|
|
||||||
(let [span-node
|
|
||||||
(if (instance? js/Text anchor-node)
|
|
||||||
(dom/get-parent anchor-node)
|
(dom/get-parent anchor-node)
|
||||||
anchor-node)
|
anchor-node)
|
||||||
container (dom/get-parent span-node)]
|
container (dom/get-parent span-node)]
|
||||||
(when (= node container)
|
(when (= node container)
|
||||||
[span-node anchor-offset])))))
|
span-node))))
|
||||||
|
|
||||||
|
(defn- current-text-node
|
||||||
|
"Retrieves the text node and the offset that the cursor is positioned on"
|
||||||
|
[node]
|
||||||
|
(assert (some? node) "expected valid node")
|
||||||
|
|
||||||
|
(when-let [selection (wapi/get-selection)]
|
||||||
|
(let [range (wapi/get-range selection 0)
|
||||||
|
anchor-node (wapi/range-start-container range)
|
||||||
|
offset (wapi/range-start-offset range)
|
||||||
|
span-node (current-text-node* node anchor-node)]
|
||||||
|
(when span-node
|
||||||
|
[span-node offset]))))
|
||||||
|
|
||||||
(defn- absolute-offset
|
(defn- absolute-offset
|
||||||
[node child offset]
|
[node child offset]
|
||||||
|
@ -156,7 +163,8 @@
|
||||||
mentions-s (mf/use-ctx mentions-context)
|
mentions-s (mf/use-ctx mentions-context)
|
||||||
cur-mention (mf/use-var nil)
|
cur-mention (mf/use-var nil)
|
||||||
|
|
||||||
prev-selection (mf/use-var nil)
|
prev-selection-ref
|
||||||
|
(mf/use-ref)
|
||||||
|
|
||||||
init-input
|
init-input
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -203,36 +211,21 @@
|
||||||
handle-select
|
handle-select
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(let [node (mf/ref-val local-ref)
|
(when-let [node (mf/ref-val local-ref)]
|
||||||
selection (wapi/get-selection)
|
(when-let [selection (wapi/get-selection)]
|
||||||
range (wapi/get-range selection 0)
|
(let [range (wapi/get-range selection 0)
|
||||||
anchor-node (wapi/range-start-container range)]
|
anchor-node (wapi/range-start-container range)
|
||||||
(when (and (= node anchor-node) (.-collapsed range))
|
offset (wapi/range-start-offset range)]
|
||||||
(wapi/set-cursor-after! anchor-node)))
|
|
||||||
|
|
||||||
(let [node (mf/ref-val local-ref)
|
(when (and (= node anchor-node) (.-collapsed ^js range))
|
||||||
[span-node offset] (current-text-node node)
|
(wapi/set-cursor-after! anchor-node))
|
||||||
[prev-span prev-offset] @prev-selection]
|
|
||||||
|
|
||||||
(reset! prev-selection #js [span-node offset])
|
(when-let [span-node (current-text-node* node anchor-node)]
|
||||||
|
(let [[prev-span prev-offset]
|
||||||
|
(mf/ref-val prev-selection-ref)
|
||||||
|
|
||||||
(when (= (dom/get-data span-node "type") "mention")
|
node-text
|
||||||
(let [from-offset (absolute-offset node prev-span prev-offset)
|
(subs (dom/get-text span-node) 0 offset)
|
||||||
to-offset (absolute-offset node span-node offset)
|
|
||||||
|
|
||||||
[_ prev next]
|
|
||||||
(->> node
|
|
||||||
(dom/seq-nodes)
|
|
||||||
(d/with-prev-next)
|
|
||||||
(filter (fn [[elem _ _]] (= elem span-node)))
|
|
||||||
(first))]
|
|
||||||
|
|
||||||
(if (> from-offset to-offset)
|
|
||||||
(wapi/set-cursor-after! prev)
|
|
||||||
(wapi/set-cursor-before! next))))
|
|
||||||
|
|
||||||
(when span-node
|
|
||||||
(let [node-text (subs (dom/get-text span-node) 0 offset)
|
|
||||||
|
|
||||||
current-at-symbol
|
current-at-symbol
|
||||||
(str/last-index-of (subs node-text 0 offset) "@")
|
(str/last-index-of (subs node-text 0 offset) "@")
|
||||||
|
@ -244,6 +237,22 @@
|
||||||
(and (> current-at-symbol 0)
|
(and (> current-at-symbol 0)
|
||||||
(str/word? (str/slice node-text (- current-at-symbol 1) current-at-symbol)))]
|
(str/word? (str/slice node-text (- current-at-symbol 1) current-at-symbol)))]
|
||||||
|
|
||||||
|
(mf/set-ref-val! prev-selection-ref #js [span-node offset])
|
||||||
|
|
||||||
|
(when (= (dom/get-data span-node "type") "mention")
|
||||||
|
(let [from-offset (absolute-offset node prev-span prev-offset)
|
||||||
|
to-offset (absolute-offset node span-node offset)
|
||||||
|
|
||||||
|
[_ prev next]
|
||||||
|
(->> node
|
||||||
|
(dom/seq-nodes)
|
||||||
|
(d/with-prev-next)
|
||||||
|
(filter (fn [[elem _ _]] (= elem span-node)))
|
||||||
|
(first))]
|
||||||
|
(if (> from-offset to-offset)
|
||||||
|
(wapi/set-cursor-after! prev)
|
||||||
|
(wapi/set-cursor-before! next))))
|
||||||
|
|
||||||
(if (and (not at-symbol-inside-word?)
|
(if (and (not at-symbol-inside-word?)
|
||||||
(re-matches #"@\w*" mention-text))
|
(re-matches #"@\w*" mention-text))
|
||||||
(do
|
(do
|
||||||
|
@ -254,7 +263,7 @@
|
||||||
(rx/push! mentions-s {:type :filter-mentions :data mention}))))
|
(rx/push! mentions-s {:type :filter-mentions :data mention}))))
|
||||||
(do
|
(do
|
||||||
(reset! cur-mention nil)
|
(reset! cur-mention nil)
|
||||||
(rx/push! mentions-s {:type :hide-mentions}))))))))
|
(rx/push! mentions-s {:type :hide-mentions}))))))))))
|
||||||
|
|
||||||
handle-focus
|
handle-focus
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -279,9 +288,8 @@
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps on-change)
|
(mf/deps on-change)
|
||||||
(fn [data]
|
(fn [data]
|
||||||
(let [node (mf/ref-val local-ref)
|
(when-let [node (mf/ref-val local-ref)]
|
||||||
[span-node offset] (current-text-node node)]
|
(when-let [[span-node offset] (current-text-node node)]
|
||||||
(when span-node
|
|
||||||
(let [node-text
|
(let [node-text
|
||||||
(dom/get-text span-node)
|
(dom/get-text span-node)
|
||||||
|
|
||||||
|
@ -314,8 +322,8 @@
|
||||||
handle-insert-at-symbol
|
handle-insert-at-symbol
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(let [node (mf/ref-val local-ref) [span-node] (current-text-node node)]
|
(when-let [node (mf/ref-val local-ref)]
|
||||||
(when span-node
|
(when-let [[span-node] (current-text-node node)]
|
||||||
(let [node-text (dom/get-text span-node)
|
(let [node-text (dom/get-text span-node)
|
||||||
at-symbol (if (blank-content? node-text) "@" " @")]
|
at-symbol (if (blank-content? node-text) "@" " @")]
|
||||||
|
|
||||||
|
@ -327,10 +335,8 @@
|
||||||
(mf/deps on-esc on-ctrl-enter handle-select handle-input)
|
(mf/deps on-esc on-ctrl-enter handle-select handle-input)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(handle-select event)
|
(handle-select event)
|
||||||
|
(when-let [node (mf/ref-val local-ref)]
|
||||||
(let [node (mf/ref-val local-ref)
|
(when-let [[span-node offset] (current-text-node node)]
|
||||||
[span-node offset] (current-text-node node)]
|
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(and @cur-mention (kbd/enter? event))
|
(and @cur-mention (kbd/enter? event))
|
||||||
(do (dom/prevent-default event)
|
(do (dom/prevent-default event)
|
||||||
|
@ -380,13 +386,11 @@
|
||||||
(= offset 1))
|
(= offset 1))
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(.remove prev-node)))))))]
|
(.remove prev-node))))))))]
|
||||||
|
|
||||||
(mf/use-layout-effect
|
(mf/with-layout-effect [autofocus]
|
||||||
(mf/deps autofocus)
|
(when ^boolean autofocus
|
||||||
(fn []
|
(dom/focus! (mf/ref-val local-ref))))
|
||||||
(when autofocus
|
|
||||||
(dom/focus! (mf/ref-val local-ref)))))
|
|
||||||
|
|
||||||
;; Creates the handlers for selection
|
;; Creates the handlers for selection
|
||||||
(mf/with-effect [handle-select]
|
(mf/with-effect [handle-select]
|
||||||
|
@ -410,12 +414,12 @@
|
||||||
|
|
||||||
;; Auto resize input to display the comment
|
;; Auto resize input to display the comment
|
||||||
(mf/with-layout-effect nil
|
(mf/with-layout-effect nil
|
||||||
(let [^js node (mf/ref-val local-ref)]
|
(when-let [^js node (mf/ref-val local-ref)]
|
||||||
(set! (.-height (.-style node)) "0")
|
(set! (.-height (.-style node)) "0")
|
||||||
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))
|
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))
|
||||||
|
|
||||||
(mf/with-effect [value prev-value]
|
(mf/with-effect [value prev-value]
|
||||||
(let [node (mf/ref-val local-ref)]
|
(when-let [node (mf/ref-val local-ref)]
|
||||||
(cond
|
(cond
|
||||||
(and (d/not-empty? prev-value) (empty? value))
|
(and (d/not-empty? prev-value) (empty? value))
|
||||||
(do (dom/set-html! node "")
|
(do (dom/set-html! node "")
|
||||||
|
|
|
@ -282,9 +282,12 @@
|
||||||
(.selectAllChildren selection node))
|
(.selectAllChildren selection node))
|
||||||
|
|
||||||
(defn get-selection
|
(defn get-selection
|
||||||
|
"Only returns valid selection"
|
||||||
[]
|
[]
|
||||||
(when-let [document globals/document]
|
(when-let [document globals/document]
|
||||||
(.getSelection document)))
|
(let [selection (.getSelection document)]
|
||||||
|
(when (not= (.-type selection) "None")
|
||||||
|
selection))))
|
||||||
|
|
||||||
(defn get-anchor-node
|
(defn get-anchor-node
|
||||||
[^js selection]
|
[^js selection]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue