0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-08 07:50:43 -05:00

Improved performance of refs

This commit is contained in:
alonso.torres 2022-04-01 11:21:50 +02:00
parent e62f0603b5
commit 0bb20197f1
7 changed files with 67 additions and 124 deletions

View file

@ -8,9 +8,9 @@
metosin/reitit-core {:mvn/version "0.5.17"} metosin/reitit-core {:mvn/version "0.5.17"}
funcool/beicon {:mvn/version "2021.07.05-1"} funcool/beicon {:mvn/version "2021.07.05-1"}
funcool/okulary {:mvn/version "2020.04.14-0"} funcool/okulary {:mvn/version "2022.04.01-10"}
funcool/potok {:mvn/version "2021.09.20-0"} funcool/potok {:mvn/version "2021.09.20-0"}
funcool/rumext {:mvn/version "2022.03.28-131"} funcool/rumext {:mvn/version "2022.03.31-133"}
funcool/tubax {:mvn/version "2021.05.20-0"} funcool/tubax {:mvn/version "2021.05.20-0"}
instaparse/instaparse {:mvn/version "1.4.10"} instaparse/instaparse {:mvn/version "1.4.10"}

View file

@ -20,39 +20,45 @@
([state] ([state]
(lookup-page-objects state (:current-page-id state))) (lookup-page-objects state (:current-page-id state)))
([state page-id] ([state page-id]
(get-in state [:workspace-data :pages-index page-id :objects]))) (dm/get-in state [:workspace-data :pages-index page-id :objects])))
(defn lookup-page-options (defn lookup-page-options
([state] ([state]
(lookup-page-options state (:current-page-id state))) (lookup-page-options state (:current-page-id state)))
([state page-id] ([state page-id]
(get-in state [:workspace-data :pages-index page-id :options]))) (dm/get-in state [:workspace-data :pages-index page-id :options])))
(defn lookup-component-objects (defn lookup-component-objects
([state component-id] ([state component-id]
(get-in state [:workspace-data :components component-id :objects]))) (dm/get-in state [:workspace-data :components component-id :objects])))
(defn lookup-local-components (defn lookup-local-components
([state] ([state]
(get-in state [:workspace-data :components]))) (dm/get-in state [:workspace-data :components])))
(defn process-selected-shapes
([objects selected]
(process-selected-shapes objects selected nil))
([objects selected {:keys [omit-blocked?] :or {omit-blocked? false}}]
(letfn [(selectable? [id]
(and (contains? objects id)
(or (not omit-blocked?)
(not (get-in objects [id :blocked] false)))))]
(let [selected (->> selected (cph/clean-loops objects))]
(into (d/ordered-set)
(filter selectable?)
selected)))))
;; TODO: improve performance of this
(defn lookup-selected (defn lookup-selected
([state] ([state]
(lookup-selected state nil)) (lookup-selected state nil))
([state options] ([state options]
(lookup-selected state (:current-page-id state) options)) (lookup-selected state (:current-page-id state) options))
([state page-id {:keys [omit-blocked?] :or {omit-blocked? false}}] ([state page-id options]
(let [objects (lookup-page-objects state page-id) (let [objects (lookup-page-objects state page-id)
selected (->> (dm/get-in state [:workspace-local :selected]) selected (dm/get-in state [:workspace-local :selected])]
(cph/clean-loops objects)) (process-selected-shapes objects selected options))))
selectable? (fn [id]
(and (contains? objects id)
(or (not omit-blocked?)
(not (get-in objects [id :blocked] false)))))]
(into (d/ordered-set)
(filter selectable?)
selected))))
(defn lookup-shapes (defn lookup-shapes
([state ids] ([state ids]
@ -79,7 +85,7 @@
[state file-id] [state file-id]
(if (= file-id (:current-file-id state)) (if (= file-id (:current-file-id state))
(get state :workspace-data) (get state :workspace-data)
(get-in state [:workspace-libraries file-id :data]))) (dm/get-in state [:workspace-libraries file-id :data])))
(defn get-libraries (defn get-libraries
"Retrieve all libraries, including the local file." "Retrieve all libraries, including the local file."

View file

@ -102,8 +102,22 @@
(l/derived :workspace-drawing st/state)) (l/derived :workspace-drawing st/state))
;; TODO: rename to workspace-selected (?) ;; TODO: rename to workspace-selected (?)
;; Don't use directly from components, this is a proxy to improve performance of selected-shapes
(def ^:private selected-shapes-data
(l/derived
(fn [state]
(let [objects (wsh/lookup-page-objects state)
selected (dm/get-in state [:workspace-local :selected])]
{:objects objects :selected selected}))
st/state (fn [v1 v2]
(and (identical? (:objects v1) (:objects v2))
(= (:selected v1) (:selected v2))))))
(def selected-shapes (def selected-shapes
(l/derived wsh/lookup-selected st/state =)) (l/derived
(fn [{:keys [objects selected]}]
(wsh/process-selected-shapes objects selected))
selected-shapes-data))
(defn make-selected-ref (defn make-selected-ref
[id] [id]
@ -258,7 +272,7 @@
(defn objects-by-id (defn objects-by-id
[ids] [ids]
(l/derived #(wsh/lookup-shapes % ids) st/state =)) (l/derived #(into [] (keep (d/getf %)) ids) workspace-page-objects))
(defn- set-content-modifiers [state] (defn- set-content-modifiers [state]
(fn [id shape] (fn [id shape]

View file

@ -18,7 +18,6 @@
[app.main.ui.shapes.rect :as rect] [app.main.ui.shapes.rect :as rect]
[app.main.ui.shapes.text.fontfaces :as ff] [app.main.ui.shapes.text.fontfaces :as ff]
[app.main.ui.workspace.shapes.bool :as bool] [app.main.ui.workspace.shapes.bool :as bool]
[app.main.ui.workspace.shapes.bounding-box :refer [bounding-box]]
[app.main.ui.workspace.shapes.common :as common] [app.main.ui.workspace.shapes.common :as common]
[app.main.ui.workspace.shapes.frame :as frame] [app.main.ui.workspace.shapes.frame :as frame]
[app.main.ui.workspace.shapes.group :as group] [app.main.ui.workspace.shapes.group :as group]
@ -26,7 +25,6 @@
[app.main.ui.workspace.shapes.svg-raw :as svg-raw] [app.main.ui.workspace.shapes.svg-raw :as svg-raw]
[app.main.ui.workspace.shapes.text :as text] [app.main.ui.workspace.shapes.text :as text]
[app.util.object :as obj] [app.util.object :as obj]
[debug :refer [debug?]]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(declare shape-wrapper) (declare shape-wrapper)
@ -87,10 +85,7 @@
;; Only used when drawing a new frame. ;; Only used when drawing a new frame.
:frame [:> frame-wrapper opts] :frame [:> frame-wrapper opts]
nil) nil)])))
(when (debug? :bounding-boxes)
[:> bounding-box opts])])))
(def group-wrapper (group/group-wrapper-factory shape-wrapper)) (def group-wrapper (group/group-wrapper-factory shape-wrapper))
(def svg-raw-wrapper (svg-raw/svg-raw-wrapper-factory shape-wrapper)) (def svg-raw-wrapper (svg-raw/svg-raw-wrapper-factory shape-wrapper))

View file

@ -1,90 +0,0 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.main.ui.workspace.shapes.bounding-box
(:require
["randomcolor" :as rdcolor]
[app.common.geom.shapes :as gsh]
[app.main.refs :as refs]
[cuerdas.core :as str]
[rumext.alpha :as mf]))
(defn fixed
[num]
(when num (.toFixed num 2)))
(mf/defc cross-point [{:keys [point zoom color]}]
(let [width (/ 5 zoom)]
[:g.point
[:line {:x1 (- (:x point) width) :y1 (- (:y point) width)
:x2 (+ (:x point) width) :y2 (+ (:y point) width)
:stroke color
:stroke-width "1px"
:stroke-opacity 0.5}]
[:line {:x1 (+ (:x point) width) :y1 (- (:y point) width)
:x2 (- (:x point) width) :y2 (+ (:y point) width)
:stroke color
:stroke-width "1px"
:stroke-opacity 0.5}]]))
(mf/defc render-rect [{{:keys [x y width height]} :rect :keys [color transform]}]
[:rect {:x x
:y y
:width width
:height height
:transform (or transform "none")
:style {:stroke color
:fill "none"
:stroke-width "1px"
:pointer-events "none"}}])
(mf/defc render-rect-points [{:keys [points color]}]
(for [[p1 p2] (map vector points (concat (rest points) [(first points)]))]
[:line {:x1 (:x p1)
:y1 (:y p1)
:x2 (:x p2)
:y2 (:y p2)
:style {:stroke color
:stroke-width "1px"}}]))
(mf/defc bounding-box
{::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
bounding-box (gsh/points->selrect (-> shape :points))
shape-center (gsh/center-shape shape)
line-color (rdcolor #js {:seed (str (:id shape))})
zoom (mf/deref refs/selected-zoom)]
[:g.bounding-box
[:text {:x (:x bounding-box)
:y (- (:y bounding-box) 5)
:font-size 10
:fill line-color
:stroke "var(--color-white)"
:stroke-width 0.1}
(str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x bounding-box)) (fixed (:y bounding-box)))]
[:g.center
[:& cross-point {:point shape-center
:zoom zoom
:color line-color}]]
[:g.points
(for [point (:points shape)]
[:& cross-point {:point point
:zoom zoom
:color line-color}])
#_[:& render-rect-points {:points (:points shape)
:color line-color}]]
[:g.selrect
[:& render-rect {:rect (:selrect shape)
;; :transform (gsh/transform-matrix shape)
:color line-color}]
#_[:& render-rect {:rect bounding-box
:color line-color}]]]))

View file

@ -6,6 +6,7 @@
(ns app.util.dom (ns app.util.dom
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.logging :as log] [app.common.logging :as log]
@ -231,20 +232,20 @@
(.-innerText el))) (.-innerText el)))
(defn query (defn query
([^string query] ([^string selector]
(query globals/document query)) (query globals/document selector))
([^js el ^string query] ([^js el ^string selector]
(when (some? el) (when (some? el)
(.querySelector el query)))) (.querySelector el selector))))
(defn query-all (defn query-all
([^string query] ([^string selector]
(query-all globals/document query)) (query-all globals/document selector))
([^js el ^string query] ([^js el ^string selector]
(when (some? el) (when (some? el)
(.querySelectorAll el query)))) (.querySelectorAll el selector))))
(defn get-client-position (defn get-client-position
[^js event] [^js event]
@ -535,3 +536,13 @@
(and (some? node) (and (some? node)
(some? candidate) (some? candidate)
(.contains node candidate))) (.contains node candidate)))
(defn seq-nodes
[root-node]
(letfn [(branch? [node]
(d/not-empty? (get-children node)))
(get-children [node]
(seq (.-children node)))]
(->> root-node
(tree-seq branch? get-children))))

View file

@ -18,6 +18,7 @@
[app.main.data.workspace.path.shortcuts] [app.main.data.workspace.path.shortcuts]
[app.main.data.workspace.shortcuts] [app.main.data.workspace.shortcuts]
[app.main.store :as st] [app.main.store :as st]
[app.util.dom :as dom]
[app.util.object :as obj] [app.util.object :as obj]
[app.util.timers :as timers] [app.util.timers :as timers]
[beicon.core :as rx] [beicon.core :as rx]
@ -340,3 +341,9 @@
(.log js/console "%c Viewer" style) (.log js/console "%c Viewer" style)
(print-shortcuts app.main.data.viewer.shortcuts/shortcuts))) (print-shortcuts app.main.data.viewer.shortcuts/shortcuts)))
nil) nil)
(defn ^:export nodeStats
[]
(let [root-node (dom/query ".viewport .render-shapes")
num-nodes (->> (dom/seq-nodes root-node) count)]
#js {:number num-nodes}))