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"}
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/rumext {:mvn/version "2022.03.28-131"}
funcool/rumext {:mvn/version "2022.03.31-133"}
funcool/tubax {:mvn/version "2021.05.20-0"}
instaparse/instaparse {:mvn/version "1.4.10"}

View file

@ -20,39 +20,45 @@
([state]
(lookup-page-objects state (:current-page-id state)))
([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
([state]
(lookup-page-options state (:current-page-id state)))
([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
([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
([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
([state]
(lookup-selected state nil))
([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)
selected (->> (dm/get-in state [:workspace-local :selected])
(cph/clean-loops objects))
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))))
selected (dm/get-in state [:workspace-local :selected])]
(process-selected-shapes objects selected options))))
(defn lookup-shapes
([state ids]
@ -79,7 +85,7 @@
[state file-id]
(if (= file-id (:current-file-id state))
(get state :workspace-data)
(get-in state [:workspace-libraries file-id :data])))
(dm/get-in state [:workspace-libraries file-id :data])))
(defn get-libraries
"Retrieve all libraries, including the local file."

View file

@ -102,8 +102,22 @@
(l/derived :workspace-drawing st/state))
;; 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
(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
[id]
@ -258,7 +272,7 @@
(defn objects-by-id
[ids]
(l/derived #(wsh/lookup-shapes % ids) st/state =))
(l/derived #(into [] (keep (d/getf %)) ids) workspace-page-objects))
(defn- set-content-modifiers [state]
(fn [id shape]

View file

@ -18,7 +18,6 @@
[app.main.ui.shapes.rect :as rect]
[app.main.ui.shapes.text.fontfaces :as ff]
[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.frame :as frame]
[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.text :as text]
[app.util.object :as obj]
[debug :refer [debug?]]
[rumext.alpha :as mf]))
(declare shape-wrapper)
@ -87,10 +85,7 @@
;; Only used when drawing a new frame.
:frame [:> frame-wrapper opts]
nil)
(when (debug? :bounding-boxes)
[:> bounding-box opts])])))
nil)])))
(def group-wrapper (group/group-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
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.point :as gpt]
[app.common.logging :as log]
@ -231,20 +232,20 @@
(.-innerText el)))
(defn query
([^string query]
(query globals/document query))
([^string selector]
(query globals/document selector))
([^js el ^string query]
([^js el ^string selector]
(when (some? el)
(.querySelector el query))))
(.querySelector el selector))))
(defn query-all
([^string query]
(query-all globals/document query))
([^string selector]
(query-all globals/document selector))
([^js el ^string query]
([^js el ^string selector]
(when (some? el)
(.querySelectorAll el query))))
(.querySelectorAll el selector))))
(defn get-client-position
[^js event]
@ -535,3 +536,13 @@
(and (some? node)
(some? 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.shortcuts]
[app.main.store :as st]
[app.util.dom :as dom]
[app.util.object :as obj]
[app.util.timers :as timers]
[beicon.core :as rx]
@ -340,3 +341,9 @@
(.log js/console "%c Viewer" style)
(print-shortcuts app.main.data.viewer.shortcuts/shortcuts)))
nil)
(defn ^:export nodeStats
[]
(let [root-node (dom/query ".viewport .render-shapes")
num-nodes (->> (dom/seq-nodes root-node) count)]
#js {:number num-nodes}))