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] (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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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