More performance improvements

This commit is contained in:
alonso.torres 2021-01-26 12:02:00 +01:00
parent 07d552c86b
commit cf77ebde6a
7 changed files with 141 additions and 104 deletions

View file

@ -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

View file

@ -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

View file

@ -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}))]

View file

@ -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

View file

@ -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")

View file

@ -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}]])))

View file

@ -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)]