mirror of
https://github.com/penpot/penpot.git
synced 2025-05-19 00:06:14 +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]
|
||||
(> (mth/abs (- old-dim new-dim)) 0.1))
|
||||
|
||||
|
||||
(defn resize-text-batch [changes]
|
||||
(ptk/reify ::resize-text-batch
|
||||
ptk/WatchEvent
|
||||
(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
|
||||
(fn [events [id [new-width new-height]]]
|
||||
(fn [objects [id [new-width new-height]]]
|
||||
|
||||
(let [shape (get objects id)
|
||||
{: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
|
||||
(and overflow-text (not= :fixed grow-type))
|
||||
(conj (update-overflow-text id false))
|
||||
modifier-width (gsh/resize-modifiers shape :width new-width)
|
||||
modifier-height (gsh/resize-modifiers shape :height new-height)
|
||||
|
||||
(and (= :fixed grow-type) (not overflow-text) (> new-height shape-height))
|
||||
(conj (update-overflow-text id true))
|
||||
shape (cond-> shape
|
||||
(and overflow-text (not= :fixed grow-type))
|
||||
(assoc :overflow-text false)
|
||||
|
||||
(and (= :fixed grow-type) overflow-text (<= new-height shape-height))
|
||||
(conj (update-overflow-text id false))
|
||||
(and (= :fixed grow-type) (not overflow-text) (> new-height shape-height))
|
||||
(assoc :overflow-text true)
|
||||
|
||||
(and (or (not-changed? shape-width new-width) (not-changed? shape-height new-height))
|
||||
(= grow-type :auto-width))
|
||||
(conj (dwt/update-dimensions [id] :width new-width)
|
||||
(dwt/update-dimensions [id] :height new-height))
|
||||
(and (= :fixed grow-type) overflow-text (<= new-height shape-height))
|
||||
(assoc :overflow-text true)
|
||||
|
||||
(and (not-changed? shape-height new-height)
|
||||
(= grow-type :auto-height))
|
||||
(conj (dwt/update-dimensions [id] :height new-height)))))
|
||||
(and (not-changed? shape-width new-width) (= grow-type :auto-width))
|
||||
(-> (assoc :modifiers modifier-width)
|
||||
(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])
|
||||
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
|
||||
(when (not undo-transaction)
|
||||
(when-not undo-transaction
|
||||
(rx/of (dwc/start-undo-transaction)))
|
||||
(rx/from events)
|
||||
(when (not undo-transaction)
|
||||
(rx/of (dwc/discard-undo-transaction))))
|
||||
(rx/empty))))))
|
||||
(rx/of (dwc/commit-changes (conj rchanges regchg) (conj uchanges regchg) {:commit-local? true}))
|
||||
(when-not undo-transaction
|
||||
(rx/of (dwc/discard-undo-transaction)))))))))
|
||||
|
||||
;; When a resize-event arrives we start "buffering" for a time
|
||||
;; after that time we invoke `resize-text-batch` with all the changes
|
||||
|
|
|
@ -159,51 +159,45 @@
|
|||
ids))
|
||||
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?
|
||||
[id]
|
||||
(letfn [(selector [state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
children (cp/get-children id objects)]
|
||||
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||
(let [children (cp/get-children id objects)]
|
||||
(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
|
||||
(letfn [(selector [state]
|
||||
(let [selected (get-in state [:workspace-local :selected])
|
||||
page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])]
|
||||
(->> selected
|
||||
(map #(get objects %))
|
||||
(filterv (comp not nil?)))))]
|
||||
(l/derived selector st/state =)))
|
||||
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||
(->> selected
|
||||
(map #(get objects %))
|
||||
(filterv (comp not nil?))))]
|
||||
(l/derived selector selected-data =)))
|
||||
|
||||
(def selected-shapes-with-children
|
||||
(letfn [(selector [state]
|
||||
(let [selected (get-in state [:workspace-local :selected])
|
||||
page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
children (->> selected
|
||||
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||
(let [children (->> selected
|
||||
(mapcat #(cp/get-children % objects))
|
||||
(filterv (comp not nil?)))]
|
||||
(into selected children)))]
|
||||
(l/derived selector st/state =)))
|
||||
|
||||
(l/derived selector selected-data =)))
|
||||
|
||||
(def selected-objects-with-children
|
||||
(letfn [(selector [state]
|
||||
(let [selected (get-in state [:workspace-local :selected])
|
||||
page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
children (->> selected
|
||||
(letfn [(selector [{:keys [selected page-id objects]}]
|
||||
(let [children (->> selected
|
||||
(mapcat #(cp/get-children % objects))
|
||||
(filterv (comp not nil?)))
|
||||
shapes (into selected children)]
|
||||
(mapv #(get objects %) shapes)))]
|
||||
(l/derived selector st/state =)))
|
||||
(l/derived selector selected-data =)))
|
||||
|
||||
;; ---- Viewer refs
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
(let [shape (unchecked-get props "shape")
|
||||
background? (unchecked-get props "background?")
|
||||
{: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)
|
||||
(obj/merge!
|
||||
#js {:d pdata}))]
|
||||
|
|
|
@ -359,6 +359,7 @@
|
|||
:zoom zoom}])]))
|
||||
|
||||
(mf/defc selection-handlers
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [selected edition zoom show-distances] :as props}]
|
||||
(let [;; We need remove posible nil values because on shape
|
||||
;; deletion many shape will reamin selected and deleted
|
||||
|
|
|
@ -153,8 +153,15 @@
|
|||
result))]
|
||||
(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/wrap [mf/memo]
|
||||
{::mf/wrap [#(mf/memo' % (check-props ["shape" "shapes-with-children"]))]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shapes (unchecked-get props "shapes")
|
||||
|
|
|
@ -267,11 +267,9 @@
|
|||
(mf/defc snap-distances
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [layout (unchecked-get props "layout")
|
||||
page-id (unchecked-get props "page-id")
|
||||
(let [page-id (unchecked-get props "page-id")
|
||||
zoom (unchecked-get props "zoom")
|
||||
selected (unchecked-get props "selected")
|
||||
transform (unchecked-get props "transform")
|
||||
selected-shapes (mf/deref (refs/objects-by-id selected))
|
||||
frame-id (-> selected-shapes first :frame-id)
|
||||
frame (mf/deref (refs/object-by-id frame-id))
|
||||
|
@ -280,23 +278,20 @@
|
|||
update-shape (fn [shape] (-> shape
|
||||
(update :modifiers merge (:modifiers local))
|
||||
gsh/transform-shape))]
|
||||
(when (and (contains? layout :dynamic-alignment)
|
||||
(= transform :move)
|
||||
(not (empty? selected)))
|
||||
(let [selrect (->> selected-shapes (map update-shape) gsh/selection-rect)
|
||||
key (->> selected (map str) (str/join "-"))]
|
||||
[:g.distance
|
||||
[:& shape-distance
|
||||
{:selrect selrect
|
||||
:page-id page-id
|
||||
:frame frame
|
||||
:zoom zoom
|
||||
:coord :x
|
||||
:selected selected}]
|
||||
[:& shape-distance
|
||||
{:selrect selrect
|
||||
:page-id page-id
|
||||
:frame frame
|
||||
:zoom zoom
|
||||
:coord :y
|
||||
:selected selected}]]))))
|
||||
(let [selrect (->> selected-shapes (map update-shape) gsh/selection-rect)
|
||||
key (->> selected (map str) (str/join "-"))]
|
||||
[:g.distance
|
||||
[:& shape-distance
|
||||
{:selrect selrect
|
||||
:page-id page-id
|
||||
:frame frame
|
||||
:zoom zoom
|
||||
:coord :x
|
||||
:selected selected}]
|
||||
[:& shape-distance
|
||||
{:selrect selrect
|
||||
:page-id page-id
|
||||
:frame frame
|
||||
:zoom zoom
|
||||
:coord :y
|
||||
:selected selected}]])))
|
||||
|
|
|
@ -188,7 +188,8 @@
|
|||
:edition edition}]]))
|
||||
|
||||
(mf/defc ghost-frames
|
||||
{::mf/wrap-props false}
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [modifiers (obj/get props "modifiers")
|
||||
selected (obj/get props "selected")
|
||||
|
@ -249,6 +250,7 @@
|
|||
(gsh/selection-rect))
|
||||
|
||||
alt? (mf/use-state false)
|
||||
cursor (mf/use-state cur/pointer-inner)
|
||||
viewport-ref (mf/use-ref nil)
|
||||
zoom-view-ref (mf/use-ref nil)
|
||||
last-position (mf/use-var nil)
|
||||
|
@ -260,6 +262,13 @@
|
|||
drawing-path? (and edition (= :draw (get-in edit-path [edition :edit-mode])))
|
||||
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
|
||||
(mf/use-callback
|
||||
(mf/deps drawing-tool edition)
|
||||
|
@ -590,6 +599,27 @@
|
|||
;; We schedule the event so it fires after `initialize-page` event
|
||||
(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)
|
||||
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||
|
||||
|
@ -619,16 +649,7 @@
|
|||
:view-box (format-viewbox vbox)
|
||||
:ref viewport-ref
|
||||
:class (when drawing-tool "drawing")
|
||||
:style {: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)
|
||||
:style {:cursor @cursor
|
||||
:background-color (get options :background "#E8E9EA")}
|
||||
:on-context-menu on-context-menu
|
||||
:on-click on-click
|
||||
|
@ -671,22 +692,24 @@
|
|||
:tool drawing-tool
|
||||
:modifiers (:modifiers local)}])
|
||||
|
||||
(when (contains? layout :display-grid)
|
||||
(when show-grids?
|
||||
[:& frame-grid {:zoom zoom}])
|
||||
|
||||
[:& snap-points {:layout layout
|
||||
:transform (:transform local)
|
||||
:drawing drawing-obj
|
||||
:zoom zoom
|
||||
:page-id page-id
|
||||
:selected selected
|
||||
:local local}]
|
||||
(when show-snap-points?
|
||||
[:& snap-points {:layout layout
|
||||
:transform (:transform local)
|
||||
:drawing drawing-obj
|
||||
:zoom zoom
|
||||
:page-id page-id
|
||||
:selected selected
|
||||
:local local}])
|
||||
|
||||
[:& snap-distances {:layout layout
|
||||
:zoom zoom
|
||||
:transform (:transform local)
|
||||
:selected selected
|
||||
:page-id page-id}]
|
||||
(when show-snap-distance?
|
||||
[:& snap-distances {:layout layout
|
||||
:zoom zoom
|
||||
:transform (:transform local)
|
||||
:selected selected
|
||||
:page-id page-id}])
|
||||
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:zoom zoom :tooltip tooltip}])]
|
||||
|
@ -697,7 +720,9 @@
|
|||
[:& interactions {:selected selected}])]]))
|
||||
|
||||
|
||||
(mf/defc viewport-actions []
|
||||
(mf/defc viewport-actions
|
||||
{::mf/wrap [mf/memo]}
|
||||
[]
|
||||
(let [edition (mf/deref refs/selected-edition)
|
||||
selected (mf/deref refs/selected-objects)
|
||||
shape (-> selected first)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue