mirror of
https://github.com/penpot/penpot.git
synced 2025-05-19 09:06:12 +02:00
✨ More performance improvements
This commit is contained in:
parent
07d552c86b
commit
cf77ebde6a
7 changed files with 141 additions and 104 deletions
|
@ -221,48 +221,62 @@
|
||||||
(defn not-changed? [old-dim new-dim]
|
(defn not-changed? [old-dim new-dim]
|
||||||
(> (mth/abs (- old-dim new-dim)) 0.1))
|
(> (mth/abs (- old-dim new-dim)) 0.1))
|
||||||
|
|
||||||
|
|
||||||
(defn resize-text-batch [changes]
|
(defn resize-text-batch [changes]
|
||||||
(ptk/reify ::resize-text-batch
|
(ptk/reify ::resize-text-batch
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [objects (dwc/lookup-page-objects state)
|
(let [page-id (:current-page-id state)
|
||||||
|
|
||||||
|
objects0 (get-in state [:workspace-file :data :pages-index page-id :objects])
|
||||||
|
objects1 (get-in state [:workspace-data :pages-index page-id :objects])
|
||||||
|
|
||||||
change-text-shape
|
change-text-shape
|
||||||
(fn [events [id [new-width new-height]]]
|
(fn [objects [id [new-width new-height]]]
|
||||||
|
|
||||||
(let [shape (get objects id)
|
(let [shape (get objects id)
|
||||||
{:keys [selrect grow-type overflow-text]} (gsh/transform-shape shape)
|
{:keys [selrect grow-type overflow-text]} (gsh/transform-shape shape)
|
||||||
{shape-width :width shape-height :height} selrect]
|
{shape-width :width shape-height :height} selrect
|
||||||
|
|
||||||
(cond-> events
|
modifier-width (gsh/resize-modifiers shape :width new-width)
|
||||||
(and overflow-text (not= :fixed grow-type))
|
modifier-height (gsh/resize-modifiers shape :height new-height)
|
||||||
(conj (update-overflow-text id false))
|
|
||||||
|
|
||||||
(and (= :fixed grow-type) (not overflow-text) (> new-height shape-height))
|
shape (cond-> shape
|
||||||
(conj (update-overflow-text id true))
|
(and overflow-text (not= :fixed grow-type))
|
||||||
|
(assoc :overflow-text false)
|
||||||
|
|
||||||
(and (= :fixed grow-type) overflow-text (<= new-height shape-height))
|
(and (= :fixed grow-type) (not overflow-text) (> new-height shape-height))
|
||||||
(conj (update-overflow-text id false))
|
(assoc :overflow-text true)
|
||||||
|
|
||||||
(and (or (not-changed? shape-width new-width) (not-changed? shape-height new-height))
|
(and (= :fixed grow-type) overflow-text (<= new-height shape-height))
|
||||||
(= grow-type :auto-width))
|
(assoc :overflow-text true)
|
||||||
(conj (dwt/update-dimensions [id] :width new-width)
|
|
||||||
(dwt/update-dimensions [id] :height new-height))
|
|
||||||
|
|
||||||
(and (not-changed? shape-height new-height)
|
(and (not-changed? shape-width new-width) (= grow-type :auto-width))
|
||||||
(= grow-type :auto-height))
|
(-> (assoc :modifiers modifier-width)
|
||||||
(conj (dwt/update-dimensions [id] :height new-height)))))
|
(gsh/transform-shape))
|
||||||
|
|
||||||
|
(and (not-changed? shape-height new-height)
|
||||||
|
(or (= grow-type :auto-height) (= grow-type :auto-width)))
|
||||||
|
(-> (assoc :modifiers modifier-height)
|
||||||
|
(gsh/transform-shape)))]
|
||||||
|
(assoc objects id shape)))
|
||||||
|
|
||||||
undo-transaction (get-in state [:workspace-undo :transaction])
|
undo-transaction (get-in state [:workspace-undo :transaction])
|
||||||
events (->> changes (reduce change-text-shape []))]
|
objects2 (->> changes (reduce change-text-shape objects1))
|
||||||
|
|
||||||
(if (seq events)
|
regchg {:type :reg-objects
|
||||||
|
:page-id page-id
|
||||||
|
:shapes (vec (keys changes))}
|
||||||
|
|
||||||
|
rchanges (dwc/generate-changes page-id objects1 objects2)
|
||||||
|
uchanges (dwc/generate-changes page-id objects2 objects0)]
|
||||||
|
|
||||||
|
(if (seq rchanges)
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(when (not undo-transaction)
|
(when-not undo-transaction
|
||||||
(rx/of (dwc/start-undo-transaction)))
|
(rx/of (dwc/start-undo-transaction)))
|
||||||
(rx/from events)
|
(rx/of (dwc/commit-changes (conj rchanges regchg) (conj uchanges regchg) {:commit-local? true}))
|
||||||
(when (not undo-transaction)
|
(when-not undo-transaction
|
||||||
(rx/of (dwc/discard-undo-transaction))))
|
(rx/of (dwc/discard-undo-transaction)))))))))
|
||||||
(rx/empty))))))
|
|
||||||
|
|
||||||
;; When a resize-event arrives we start "buffering" for a time
|
;; When a resize-event arrives we start "buffering" for a time
|
||||||
;; after that time we invoke `resize-text-batch` with all the changes
|
;; after that time we invoke `resize-text-batch` with all the changes
|
||||||
|
|
|
@ -159,51 +159,45 @@
|
||||||
ids))
|
ids))
|
||||||
workspace-page-objects =))
|
workspace-page-objects =))
|
||||||
|
|
||||||
|
(def selected-data
|
||||||
|
(l/derived #(let [selected (get-in % [:workspace-local :selected])
|
||||||
|
page-id (:current-page-id %)
|
||||||
|
objects (get-in % [:workspace-data :pages-index page-id :objects])]
|
||||||
|
(hash-map :selected selected
|
||||||
|
:page-id page-id
|
||||||
|
:objects objects))
|
||||||
|
st/state =))
|
||||||
|
|
||||||
(defn is-child-selected?
|
(defn is-child-selected?
|
||||||
[id]
|
[id]
|
||||||
(letfn [(selector [state]
|
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||||
(let [page-id (:current-page-id state)
|
(let [children (cp/get-children id objects)]
|
||||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
|
||||||
selected (get-in state [:workspace-local :selected])
|
|
||||||
children (cp/get-children id objects)]
|
|
||||||
(some #(contains? selected %) children)))]
|
(some #(contains? selected %) children)))]
|
||||||
(l/derived selector st/state)))
|
(l/derived selector selected-data =)))
|
||||||
|
|
||||||
|
|
||||||
;; TODO: can be replaced by objects-by-id
|
|
||||||
(def selected-objects
|
(def selected-objects
|
||||||
(letfn [(selector [state]
|
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||||
(let [selected (get-in state [:workspace-local :selected])
|
(->> selected
|
||||||
page-id (:current-page-id state)
|
(map #(get objects %))
|
||||||
objects (get-in state [:workspace-data :pages-index page-id :objects])]
|
(filterv (comp not nil?))))]
|
||||||
(->> selected
|
(l/derived selector selected-data =)))
|
||||||
(map #(get objects %))
|
|
||||||
(filterv (comp not nil?)))))]
|
|
||||||
(l/derived selector st/state =)))
|
|
||||||
|
|
||||||
(def selected-shapes-with-children
|
(def selected-shapes-with-children
|
||||||
(letfn [(selector [state]
|
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||||
(let [selected (get-in state [:workspace-local :selected])
|
(let [children (->> selected
|
||||||
page-id (:current-page-id state)
|
|
||||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
|
||||||
children (->> selected
|
|
||||||
(mapcat #(cp/get-children % objects))
|
(mapcat #(cp/get-children % objects))
|
||||||
(filterv (comp not nil?)))]
|
(filterv (comp not nil?)))]
|
||||||
(into selected children)))]
|
(into selected children)))]
|
||||||
(l/derived selector st/state =)))
|
(l/derived selector selected-data =)))
|
||||||
|
|
||||||
|
|
||||||
(def selected-objects-with-children
|
(def selected-objects-with-children
|
||||||
(letfn [(selector [state]
|
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||||
(let [selected (get-in state [:workspace-local :selected])
|
(let [children (->> selected
|
||||||
page-id (:current-page-id state)
|
|
||||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
|
||||||
children (->> selected
|
|
||||||
(mapcat #(cp/get-children % objects))
|
(mapcat #(cp/get-children % objects))
|
||||||
(filterv (comp not nil?)))
|
(filterv (comp not nil?)))
|
||||||
shapes (into selected children)]
|
shapes (into selected children)]
|
||||||
(mapv #(get objects %) shapes)))]
|
(mapv #(get objects %) shapes)))]
|
||||||
(l/derived selector st/state =)))
|
(l/derived selector selected-data =)))
|
||||||
|
|
||||||
;; ---- Viewer refs
|
;; ---- Viewer refs
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@
|
||||||
(let [shape (unchecked-get props "shape")
|
(let [shape (unchecked-get props "shape")
|
||||||
background? (unchecked-get props "background?")
|
background? (unchecked-get props "background?")
|
||||||
{:keys [id x y width height]} (:selrect shape)
|
{:keys [id x y width height]} (:selrect shape)
|
||||||
pdata (ugp/content->path (:content shape))
|
content (:content shape)
|
||||||
|
pdata (mf/use-memo (mf/deps content) #(ugp/content->path content))
|
||||||
props (-> (attrs/extract-style-attrs shape)
|
props (-> (attrs/extract-style-attrs shape)
|
||||||
(obj/merge!
|
(obj/merge!
|
||||||
#js {:d pdata}))]
|
#js {:d pdata}))]
|
||||||
|
|
|
@ -359,6 +359,7 @@
|
||||||
:zoom zoom}])]))
|
:zoom zoom}])]))
|
||||||
|
|
||||||
(mf/defc selection-handlers
|
(mf/defc selection-handlers
|
||||||
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [selected edition zoom show-distances] :as props}]
|
[{:keys [selected edition zoom show-distances] :as props}]
|
||||||
(let [;; We need remove posible nil values because on shape
|
(let [;; We need remove posible nil values because on shape
|
||||||
;; deletion many shape will reamin selected and deleted
|
;; deletion many shape will reamin selected and deleted
|
||||||
|
|
|
@ -153,8 +153,15 @@
|
||||||
result))]
|
result))]
|
||||||
(reduce extract-attrs [] shapes)))
|
(reduce extract-attrs [] shapes)))
|
||||||
|
|
||||||
|
;; TODO: Remove when added to rumext
|
||||||
|
(defn check-props
|
||||||
|
([props] (check-props props =))
|
||||||
|
([props eqfn?]
|
||||||
|
(fn [np op]
|
||||||
|
(every? #(eqfn? (unchecked-get np %) (unchecked-get op %)) props))))
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [#(mf/memo' % (check-props ["shape" "shapes-with-children"]))]
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [shapes (unchecked-get props "shapes")
|
(let [shapes (unchecked-get props "shapes")
|
||||||
|
|
|
@ -267,11 +267,9 @@
|
||||||
(mf/defc snap-distances
|
(mf/defc snap-distances
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [layout (unchecked-get props "layout")
|
(let [page-id (unchecked-get props "page-id")
|
||||||
page-id (unchecked-get props "page-id")
|
|
||||||
zoom (unchecked-get props "zoom")
|
zoom (unchecked-get props "zoom")
|
||||||
selected (unchecked-get props "selected")
|
selected (unchecked-get props "selected")
|
||||||
transform (unchecked-get props "transform")
|
|
||||||
selected-shapes (mf/deref (refs/objects-by-id selected))
|
selected-shapes (mf/deref (refs/objects-by-id selected))
|
||||||
frame-id (-> selected-shapes first :frame-id)
|
frame-id (-> selected-shapes first :frame-id)
|
||||||
frame (mf/deref (refs/object-by-id frame-id))
|
frame (mf/deref (refs/object-by-id frame-id))
|
||||||
|
@ -280,23 +278,20 @@
|
||||||
update-shape (fn [shape] (-> shape
|
update-shape (fn [shape] (-> shape
|
||||||
(update :modifiers merge (:modifiers local))
|
(update :modifiers merge (:modifiers local))
|
||||||
gsh/transform-shape))]
|
gsh/transform-shape))]
|
||||||
(when (and (contains? layout :dynamic-alignment)
|
(let [selrect (->> selected-shapes (map update-shape) gsh/selection-rect)
|
||||||
(= transform :move)
|
key (->> selected (map str) (str/join "-"))]
|
||||||
(not (empty? selected)))
|
[:g.distance
|
||||||
(let [selrect (->> selected-shapes (map update-shape) gsh/selection-rect)
|
[:& shape-distance
|
||||||
key (->> selected (map str) (str/join "-"))]
|
{:selrect selrect
|
||||||
[:g.distance
|
:page-id page-id
|
||||||
[:& shape-distance
|
:frame frame
|
||||||
{:selrect selrect
|
:zoom zoom
|
||||||
:page-id page-id
|
:coord :x
|
||||||
:frame frame
|
:selected selected}]
|
||||||
:zoom zoom
|
[:& shape-distance
|
||||||
:coord :x
|
{:selrect selrect
|
||||||
:selected selected}]
|
:page-id page-id
|
||||||
[:& shape-distance
|
:frame frame
|
||||||
{:selrect selrect
|
:zoom zoom
|
||||||
:page-id page-id
|
:coord :y
|
||||||
:frame frame
|
:selected selected}]])))
|
||||||
:zoom zoom
|
|
||||||
:coord :y
|
|
||||||
:selected selected}]]))))
|
|
||||||
|
|
|
@ -188,7 +188,8 @@
|
||||||
:edition edition}]]))
|
:edition edition}]]))
|
||||||
|
|
||||||
(mf/defc ghost-frames
|
(mf/defc ghost-frames
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap [mf/memo]
|
||||||
|
::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [modifiers (obj/get props "modifiers")
|
(let [modifiers (obj/get props "modifiers")
|
||||||
selected (obj/get props "selected")
|
selected (obj/get props "selected")
|
||||||
|
@ -249,6 +250,7 @@
|
||||||
(gsh/selection-rect))
|
(gsh/selection-rect))
|
||||||
|
|
||||||
alt? (mf/use-state false)
|
alt? (mf/use-state false)
|
||||||
|
cursor (mf/use-state cur/pointer-inner)
|
||||||
viewport-ref (mf/use-ref nil)
|
viewport-ref (mf/use-ref nil)
|
||||||
zoom-view-ref (mf/use-ref nil)
|
zoom-view-ref (mf/use-ref nil)
|
||||||
last-position (mf/use-var nil)
|
last-position (mf/use-var nil)
|
||||||
|
@ -260,6 +262,13 @@
|
||||||
drawing-path? (and edition (= :draw (get-in edit-path [edition :edit-mode])))
|
drawing-path? (and edition (= :draw (get-in edit-path [edition :edit-mode])))
|
||||||
zoom (or zoom 1)
|
zoom (or zoom 1)
|
||||||
|
|
||||||
|
show-grids? (contains? layout :display-grid)
|
||||||
|
show-snap-points? (and (contains? layout :dynamic-alignment)
|
||||||
|
(or drawing-obj (:transform local)))
|
||||||
|
show-snap-distance? (and (contains? layout :dynamic-alignment)
|
||||||
|
(= (:transform local) :move)
|
||||||
|
(not (empty? selected)))
|
||||||
|
|
||||||
on-mouse-down
|
on-mouse-down
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps drawing-tool edition)
|
(mf/deps drawing-tool edition)
|
||||||
|
@ -590,6 +599,27 @@
|
||||||
;; We schedule the event so it fires after `initialize-page` event
|
;; We schedule the event so it fires after `initialize-page` event
|
||||||
(timers/schedule #(st/emit! (dw/initialize-viewport size))))))
|
(timers/schedule #(st/emit! (dw/initialize-viewport size))))))
|
||||||
|
|
||||||
|
;; This change is in an effect to minimize the sideffects of the cursor chaning
|
||||||
|
;; Changing a cursor will produce a "reflow" so we defer it until the component is rendered
|
||||||
|
(mf/use-layout-effect
|
||||||
|
(mf/deps @cursor panning drawing-tool drawing-path?)
|
||||||
|
(fn []
|
||||||
|
(let [new-cursor
|
||||||
|
(cond
|
||||||
|
panning cur/hand
|
||||||
|
(= drawing-tool :comments) cur/comments
|
||||||
|
(= drawing-tool :frame) cur/create-artboard
|
||||||
|
(= drawing-tool :rect) cur/create-rectangle
|
||||||
|
(= drawing-tool :circle) cur/create-ellipse
|
||||||
|
(or (= drawing-tool :path) drawing-path?) cur/pen
|
||||||
|
(= drawing-tool :curve) cur/pencil
|
||||||
|
drawing-tool cur/create-shape
|
||||||
|
:else cur/pointer-inner)]
|
||||||
|
|
||||||
|
(when (not= @cursor new-cursor)
|
||||||
|
(timers/raf
|
||||||
|
#(reset! cursor new-cursor))))))
|
||||||
|
|
||||||
(mf/use-layout-effect (mf/deps layout) on-resize)
|
(mf/use-layout-effect (mf/deps layout) on-resize)
|
||||||
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||||
|
|
||||||
|
@ -619,16 +649,7 @@
|
||||||
:view-box (format-viewbox vbox)
|
:view-box (format-viewbox vbox)
|
||||||
:ref viewport-ref
|
:ref viewport-ref
|
||||||
:class (when drawing-tool "drawing")
|
:class (when drawing-tool "drawing")
|
||||||
:style {:cursor (cond
|
:style {:cursor @cursor
|
||||||
panning cur/hand
|
|
||||||
(= drawing-tool :comments) cur/comments
|
|
||||||
(= drawing-tool :frame) cur/create-artboard
|
|
||||||
(= drawing-tool :rect) cur/create-rectangle
|
|
||||||
(= drawing-tool :circle) cur/create-ellipse
|
|
||||||
(or (= drawing-tool :path) drawing-path?) cur/pen
|
|
||||||
(= drawing-tool :curve) cur/pencil
|
|
||||||
drawing-tool cur/create-shape
|
|
||||||
:else cur/pointer-inner)
|
|
||||||
:background-color (get options :background "#E8E9EA")}
|
:background-color (get options :background "#E8E9EA")}
|
||||||
:on-context-menu on-context-menu
|
:on-context-menu on-context-menu
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
|
@ -671,22 +692,24 @@
|
||||||
:tool drawing-tool
|
:tool drawing-tool
|
||||||
:modifiers (:modifiers local)}])
|
:modifiers (:modifiers local)}])
|
||||||
|
|
||||||
(when (contains? layout :display-grid)
|
(when show-grids?
|
||||||
[:& frame-grid {:zoom zoom}])
|
[:& frame-grid {:zoom zoom}])
|
||||||
|
|
||||||
[:& snap-points {:layout layout
|
(when show-snap-points?
|
||||||
:transform (:transform local)
|
[:& snap-points {:layout layout
|
||||||
:drawing drawing-obj
|
:transform (:transform local)
|
||||||
:zoom zoom
|
:drawing drawing-obj
|
||||||
:page-id page-id
|
:zoom zoom
|
||||||
:selected selected
|
:page-id page-id
|
||||||
:local local}]
|
:selected selected
|
||||||
|
:local local}])
|
||||||
|
|
||||||
[:& snap-distances {:layout layout
|
(when show-snap-distance?
|
||||||
:zoom zoom
|
[:& snap-distances {:layout layout
|
||||||
:transform (:transform local)
|
:zoom zoom
|
||||||
:selected selected
|
:transform (:transform local)
|
||||||
:page-id page-id}]
|
:selected selected
|
||||||
|
:page-id page-id}])
|
||||||
|
|
||||||
(when tooltip
|
(when tooltip
|
||||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])]
|
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])]
|
||||||
|
@ -697,7 +720,9 @@
|
||||||
[:& interactions {:selected selected}])]]))
|
[:& interactions {:selected selected}])]]))
|
||||||
|
|
||||||
|
|
||||||
(mf/defc viewport-actions []
|
(mf/defc viewport-actions
|
||||||
|
{::mf/wrap [mf/memo]}
|
||||||
|
[]
|
||||||
(let [edition (mf/deref refs/selected-edition)
|
(let [edition (mf/deref refs/selected-edition)
|
||||||
selected (mf/deref refs/selected-objects)
|
selected (mf/deref refs/selected-objects)
|
||||||
shape (-> selected first)]
|
shape (-> selected first)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue