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:
parent
e62f0603b5
commit
0bb20197f1
7 changed files with 67 additions and 124 deletions
|
@ -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"}
|
||||||
|
|
|
@ -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."
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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}]]]))
|
|
|
@ -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))))
|
||||||
|
|
|
@ -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}))
|
||||||
|
|
Loading…
Reference in a new issue