0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 15:51:37 -05:00

🐛 Fix problem with texts randomly moving

This commit is contained in:
alonso.torres 2023-01-10 10:59:28 +01:00
parent 4aa8baa129
commit b5c1199f4d
6 changed files with 66 additions and 20 deletions

View file

@ -43,14 +43,16 @@
(mapv #(gpt/add % move-vec)))) (mapv #(gpt/add % move-vec))))
(defn move-position-data (defn move-position-data
[position-data dx dy] ([position-data {:keys [x y]}]
(move-position-data position-data x y))
([position-data dx dy]
(when (some? position-data) (when (some? position-data)
(cond->> position-data (cond->> position-data
(d/num? dx dy) (d/num? dx dy)
(mapv #(-> % (mapv #(-> %
(update :x + dx) (update :x + dx)
(update :y + dy)))))) (update :y + dy)))))))
(defn move (defn move
"Move the shape relatively to its current "Move the shape relatively to its current

View file

@ -114,6 +114,18 @@
(reduce set-child ignore-tree children)))) (reduce set-child ignore-tree children))))
(defn assoc-position-data
[shape position-data old-shape]
(let [deltav (gpt/to-vec (gpt/point (:selrect old-shape))
(gpt/point (:selrect shape)))
position-data
(-> position-data
(gsh/move-position-data deltav))]
(cond-> shape
(d/not-empty? position-data)
(assoc :position-data position-data))))
(defn update-grow-type (defn update-grow-type
[shape old-shape] [shape old-shape]
(let [auto-width? (= :auto-width (:grow-type shape)) (let [auto-width? (= :auto-width (:grow-type shape))
@ -319,7 +331,8 @@
(ptk/reify ::apply-modifiers (ptk/reify ::apply-modifiers
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (wsh/lookup-page-objects state) (let [text-modifiers (get state :workspace-text-modifier)
objects (wsh/lookup-page-objects state)
object-modifiers (if modifiers object-modifiers (if modifiers
(calculate-modifiers state modifiers) (calculate-modifiers state modifiers)
(get state :workspace-modifiers)) (get state :workspace-modifiers))
@ -342,9 +355,13 @@
ids ids
(fn [shape] (fn [shape]
(let [modif (get-in object-modifiers [(:id shape) :modifiers]) (let [modif (get-in object-modifiers [(:id shape) :modifiers])
text-shape? (cph/text-shape? shape)] text-shape? (cph/text-shape? shape)
position-data (when text-shape?
(dm/get-in text-modifiers [(:id shape) :position-data]))]
(-> shape (-> shape
(gsh/transform-shape modif) (gsh/transform-shape modif)
(cond-> (d/not-empty? position-data)
(assoc-position-data position-data shape))
(cond-> text-shape? (cond-> text-shape?
(update-grow-type shape))))) (update-grow-type shape)))))
{:reg-objects? true {:reg-objects? true
@ -366,7 +383,11 @@
:grow-type :grow-type
:layout-item-h-sizing :layout-item-h-sizing
:layout-item-v-sizing :layout-item-v-sizing
:position-data
]}) ]})
;; We've applied the text-modifier so we can dissoc the temporary data
(fn [state]
(update state :workspace-text-modifier #(apply dissoc % ids)))
(clear-local-transform)) (clear-local-transform))
(if undo-transation? (if undo-transation?
(rx/of (dwu/commit-undo-transaction undo-id)) (rx/of (dwu/commit-undo-transaction undo-id))

View file

@ -344,7 +344,7 @@
(when (or (and (not-changed? (:width shape) new-width) (= (:grow-type shape) :auto-width)) (when (or (and (not-changed? (:width shape) new-width) (= (:grow-type shape) :auto-width))
(and (not-changed? (:height shape) new-height) (and (not-changed? (:height shape) new-height)
(or (= (:grow-type shape) :auto-height) (= (:grow-type shape) :auto-width)))) (or (= (:grow-type shape) :auto-height) (= (:grow-type shape) :auto-width))))
(rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? false}) (rx/of (dch/update-shapes [id] update-fn {:reg-objects? true :save-undo? true})
(ptk/data-event :layout/update [id])))))))) (ptk/data-event :layout/update [id]))))))))
@ -377,7 +377,7 @@
(gpt/point (:selrect shape))) (gpt/point (:selrect shape)))
new-shape new-shape
(update new-shape :position-data gsh/move-position-data (:x delta-move) (:y delta-move))] (update new-shape :position-data gsh/move-position-data delta-move)]
new-shape)) new-shape))

View file

@ -140,6 +140,10 @@
(let [text-shapes (obj/get props "text-shapes") (let [text-shapes (obj/get props "text-shapes")
prev-text-shapes (hooks/use-previous text-shapes) prev-text-shapes (hooks/use-previous text-shapes)
;; We store in the state the texts still pending to be calculated so we can
;; get its position
pending-update (mf/use-state {})
text-change? text-change?
(fn [id] (fn [id]
(let [new-shape (get text-shapes id) (let [new-shape (get text-shapes id)
@ -153,12 +157,23 @@
changed-texts changed-texts
(mf/use-memo (mf/use-memo
(mf/deps text-shapes) (mf/deps text-shapes @pending-update)
#(->> (keys text-shapes) #(let [pending-shapes (into #{} (vals @pending-update))]
(filter text-change?) (->> (keys text-shapes)
(map (d/getf text-shapes)))) (filter (fn [id]
(or (contains? pending-shapes id)
(text-change? id))))
(map (d/getf text-shapes)))))
handle-update-shape (mf/use-callback update-text-shape)] handle-update-shape
(mf/use-callback
(fn [shape node]
;; Unique to indentify the pending state
(let [uid (js/Symbol)]
(swap! pending-update assoc uid (:id shape))
(p/then
(update-text-shape shape node)
#(swap! pending-update dissoc uid)))))]
[:.text-changes-renderer [:.text-changes-renderer
(for [{:keys [id] :as shape} changed-texts] (for [{:keys [id] :as shape} changed-texts]

View file

@ -12,6 +12,7 @@
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.texts :as dwt] [app.main.data.workspace.texts :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.main.fonts :as fonts] [app.main.fonts :as fonts]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
@ -20,7 +21,7 @@
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]] [app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.timers :as tm] [app.util.timers :as ts]
[cuerdas.core :as str] [cuerdas.core :as str]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -164,7 +165,12 @@
(let [grow-type (:grow-type values) (let [grow-type (:grow-type values)
handle-change-grow handle-change-grow
(fn [_ grow-type] (fn [_ grow-type]
(st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type))) (let [uid (js/Symbol)]
(st/emit!
(dwu/start-undo-transaction uid)
(dch/update-shapes ids #(assoc % :grow-type grow-type)))
;; We asynchronously commit so every sychronous event is resolved first and inside the transaction
(ts/schedule #(st/emit! (dwu/commit-undo-transaction uid))))
(when (some? on-blur) (on-blur)))] (when (some? on-blur) (on-blur)))]
[:div.align-icons [:div.align-icons
@ -304,7 +310,7 @@
:show-recent true :show-recent true
:on-blur :on-blur
(fn [] (fn []
(tm/schedule (ts/schedule
100 100
(fn [] (fn []
(when (not= "INPUT" (-> (dom/get-active) (dom/get-tag-name))) (when (not= "INPUT" (-> (dom/get-active) (dom/get-tag-name)))

View file

@ -225,7 +225,9 @@
;; inside a foreign object "dummy" so this awkward behaviour is take into account ;; inside a foreign object "dummy" so this awkward behaviour is take into account
[:svg {:style {:top 0 :left 0 :position "fixed" :width "100%" :height "100%" :opacity (when-not (debug? :html-text) 0)}} [:svg {:style {:top 0 :left 0 :position "fixed" :width "100%" :height "100%" :opacity (when-not (debug? :html-text) 0)}}
[:foreignObject {:x 0 :y 0 :width "100%" :height "100%"} [:foreignObject {:x 0 :y 0 :width "100%" :height "100%"}
[:div {:style {:pointer-events (when-not (debug? :html-text) "none")}} [:div {:style {:pointer-events (when-not (debug? :html-text) "none")
;; some opacity because to debug auto-width events will fill the screen
:opacity 0.6}}
[:& stvh/viewport-texts [:& stvh/viewport-texts
{:key (dm/str "texts-" page-id) {:key (dm/str "texts-" page-id)
:page-id page-id :page-id page-id