mirror of
https://github.com/penpot/penpot.git
synced 2025-01-22 14:39:45 -05:00
✨ Improve layers performance.
This commit is contained in:
parent
45bf06733f
commit
d6d38283e7
8 changed files with 122 additions and 60 deletions
|
@ -93,7 +93,7 @@ function readLocales() {
|
|||
return JSON.stringify(result);
|
||||
}
|
||||
|
||||
function readConfig() {
|
||||
function readConfig(data) {
|
||||
const publicURL = process.env.UXBOX_PUBLIC_URL;
|
||||
const demoWarn = process.env.UXBOX_DEMO_WARNING;
|
||||
const deployDate = process.env.UXBOX_DEPLOY_DATE;
|
||||
|
@ -115,6 +115,8 @@ function readConfig() {
|
|||
cfg.deployCommit = deployCommit;
|
||||
}
|
||||
|
||||
Object.assign(cfg, data);
|
||||
|
||||
return JSON.stringify(cfg);
|
||||
}
|
||||
|
||||
|
@ -128,7 +130,7 @@ function templatePipeline(options) {
|
|||
const themes = ["default"];
|
||||
|
||||
const locales = readLocales();
|
||||
const config = readConfig();
|
||||
const config = readConfig({themes});
|
||||
|
||||
const tmpl = mustache({
|
||||
ts: ts,
|
||||
|
@ -174,22 +176,21 @@ gulp.task("templates", gulp.series("template:main"));
|
|||
* Development
|
||||
***********************************************/
|
||||
|
||||
gulp.task("dev:clean", function(next) {
|
||||
gulp.task("clean", function(next) {
|
||||
rimraf(paths.output, next);
|
||||
});
|
||||
|
||||
gulp.task("dev:copy:images", function() {
|
||||
gulp.task("copy:assets:images", function() {
|
||||
return gulp.src(paths.resources + "images/**/*")
|
||||
.pipe(gulp.dest(paths.output + "images/"));
|
||||
});
|
||||
|
||||
gulp.task("dev:copy:fonts", function() {
|
||||
gulp.task("copy:assets:fonts", function() {
|
||||
return gulp.src(paths.resources + "fonts/**/*")
|
||||
.pipe(gulp.dest(paths.output + "fonts/"));
|
||||
});
|
||||
|
||||
gulp.task("dev:copy", gulp.parallel("dev:copy:images",
|
||||
"dev:copy:fonts"));
|
||||
gulp.task("copy:assets", gulp.parallel("copy:assets:images", "copy:assets:fonts"));
|
||||
|
||||
gulp.task("dev:dirs", function(next) {
|
||||
mkdirp("./resources/public/css/").then(() => next())
|
||||
|
@ -198,18 +199,18 @@ gulp.task("dev:dirs", function(next) {
|
|||
gulp.task("watch:main", function() {
|
||||
gulp.watch(paths.scss, gulp.series("scss"));
|
||||
gulp.watch(paths.resources + "images/**/*",
|
||||
gulp.series("svg:sprite",
|
||||
"dev:copy:images"));
|
||||
gulp.series("svg:sprite", "copy:assets:images"));
|
||||
|
||||
gulp.watch([paths.resources + "templates/*.mustache",
|
||||
paths.resources + "locales.json"],
|
||||
gulp.series("templates"));
|
||||
});
|
||||
|
||||
gulp.task("build", gulp.parallel("scss", "svg:sprite", "templates", "copy:assets"));
|
||||
|
||||
gulp.task("watch", gulp.series(
|
||||
"dev:dirs",
|
||||
gulp.parallel("scss", "templates", "svg:sprite"),
|
||||
"dev:copy",
|
||||
"build",
|
||||
"watch:main"
|
||||
));
|
||||
|
||||
|
@ -231,10 +232,3 @@ gulp.task("dist:gzip", function() {
|
|||
.pipe(gzip({gzipOptions: {level: 9}}))
|
||||
.pipe(gulp.dest(paths.dist));
|
||||
});
|
||||
|
||||
gulp.task("dist", gulp.series(
|
||||
"dev:clean",
|
||||
"dist:clean",
|
||||
gulp.parallel("scss", "templates", "svg:sprite", "dev:copy"),
|
||||
"dist:copy"
|
||||
));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
|
||||
"dashboard.grid.delete" : {
|
||||
"used-in" : [ "src/uxbox/main/ui/dashboard/project.cljs:61", "src/uxbox/main/ui/dashboard/grid.cljs:92" ],
|
||||
"translations" : {
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
window.uxboxTranslations = JSON.parse({{& translations }});
|
||||
window.uxboxThemes = {{& themes }};
|
||||
</script>
|
||||
<script src="/js/shared.js?ts={{& ts}}"></script>
|
||||
<script src="/js/main.js?ts={{& ts}}"></script>
|
||||
<script>uxbox.main.init()</script>
|
||||
<script src="/js/shared.js?ts={{& ts }}"></script>
|
||||
<script src="/js/main.js?ts={{& ts }}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,9 +7,11 @@ npm ci
|
|||
|
||||
export NODE_ENV=production;
|
||||
|
||||
npx gulp dist:clean || exit 1;
|
||||
npx gulp dist || exit 1;
|
||||
# Clean the output directory
|
||||
npx gulp clean || exit 1;
|
||||
|
||||
shadow-cljs release main
|
||||
|
||||
npx gulp build || exit 1;
|
||||
npx gulp dist:clean || exit 1;
|
||||
npx gulp dist:copy || exit 1;
|
||||
npx gulp dist:gzip || exit 1;
|
||||
|
|
|
@ -13,16 +13,17 @@
|
|||
:modules
|
||||
{:shared {:entries []}
|
||||
:main {:entries [uxbox.main]
|
||||
:depends-on #{:shared}}
|
||||
:depends-on #{:shared}
|
||||
:init-fn uxbox.main/init}
|
||||
:worker {:entries [uxbox.worker]
|
||||
:web-worker true
|
||||
:depends-on #{:shared}}}
|
||||
:compiler-options
|
||||
{:output-feature-set :es8
|
||||
;; :optimizations :simple
|
||||
:output-wrapper false}
|
||||
:release
|
||||
{:output-dir "target/dist/js"
|
||||
:compiler-options
|
||||
{:compiler-options
|
||||
{:fn-invoke-direct true
|
||||
:source-map true
|
||||
:anon-fn-naming-policy :off
|
||||
|
|
|
@ -1907,6 +1907,20 @@
|
|||
(let [page-id (::page-id state)]
|
||||
(assoc-in state [:workspace-data page-id :objects id :hidden] hidden?)))
|
||||
|
||||
|
||||
(defn toggle-collapse
|
||||
[id]
|
||||
(ptk/reify ::toggle-collapse
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:workspace-local :expanded id] not))))
|
||||
|
||||
(def collapse-all
|
||||
(ptk/reify ::collapse-all
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-local dissoc :expanded))))
|
||||
|
||||
;; --- Shape Blocking
|
||||
|
||||
(declare impl-update-shape-blocked)
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
(ns uxbox.main.ui.workspace.sidebar.layers
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[okulary.core :as l]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.data.helpers :as dh]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.hooks :as hooks]
|
||||
|
@ -74,33 +76,27 @@
|
|||
{:on-double-click on-click}
|
||||
(:name shape "")])))
|
||||
|
||||
(defn- layer-item-memo-equals?
|
||||
[nprops oprops]
|
||||
(let [n-item (unchecked-get nprops "item")
|
||||
o-item (unchecked-get oprops "item")
|
||||
n-selc (unchecked-get nprops "selected")
|
||||
o-selc (unchecked-get oprops "selected")
|
||||
n-indx (unchecked-get nprops "index")
|
||||
o-indx (unchecked-get oprops "index")]
|
||||
;; (js/console.log "FOR" (:name n-item)
|
||||
;; "NEW SEL" n-selc
|
||||
;; "OLD SEL" o-selc)6
|
||||
(and (identical? n-item o-item)
|
||||
(identical? n-indx o-indx)
|
||||
(identical? n-selc o-selc))))
|
||||
|
||||
(declare layer-item)
|
||||
(defn- make-collapsed-iref
|
||||
[id]
|
||||
#(-> (l/in [:expanded id])
|
||||
(l/derived refs/workspace-local)))
|
||||
|
||||
(mf/defc layer-item
|
||||
;; {::mf/wrap [#(mf/memo' % layer-item-memo-equals?)]}
|
||||
[{:keys [index item selected objects] :as props}]
|
||||
(let [selected? (contains? selected (:id item))
|
||||
collapsed? (mf/use-state false)
|
||||
|
||||
expanded-iref (mf/use-memo
|
||||
(mf/deps (:id item))
|
||||
(make-collapsed-iref (:id item)))
|
||||
|
||||
expanded? (mf/deref expanded-iref)
|
||||
|
||||
toggle-collapse
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! collapsed? not))
|
||||
(if (and expanded? (kbd/shift? event))
|
||||
(st/emit! dw/collapse-all)
|
||||
(st/emit! (dw/toggle-collapse (:id item)))))
|
||||
|
||||
toggle-blocking
|
||||
(fn [event]
|
||||
|
@ -163,7 +159,6 @@
|
|||
:index index
|
||||
:name (:name item)})
|
||||
]
|
||||
;; (prn "layer-item" (:name item) index)
|
||||
[:li {:on-context-menu on-context-menu
|
||||
:ref dref
|
||||
:data-index index
|
||||
|
@ -190,36 +185,91 @@
|
|||
(when (:shapes item)
|
||||
[:span.toggle-content
|
||||
{:on-click toggle-collapse
|
||||
:class (when-not @collapsed? "inverse")}
|
||||
:class (when expanded? "inverse")}
|
||||
i/arrow-slide])]
|
||||
(when (and (:shapes item) (not @collapsed?))
|
||||
(when (and (:shapes item) expanded?)
|
||||
[:ul.element-children
|
||||
(for [[index id] (reverse (d/enumerate (:shapes item)))]
|
||||
(when-let [item (get objects id)]
|
||||
[:& uxbox.main.ui.workspace.sidebar.layers/layer-item
|
||||
[:& layer-item
|
||||
{:item item
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key (:id item)}]))])]))
|
||||
|
||||
(defn frame-wrapper-memo-equals?
|
||||
[oprops nprops]
|
||||
(let [new-sel (unchecked-get nprops "selected")
|
||||
old-sel (unchecked-get oprops "selected")
|
||||
new-itm (unchecked-get nprops "item")
|
||||
old-itm (unchecked-get oprops "item")
|
||||
new-idx (unchecked-get nprops "index")
|
||||
old-idx (unchecked-get oprops "index")
|
||||
new-obs (unchecked-get nprops "objects")
|
||||
old-obs (unchecked-get oprops "objects")]
|
||||
(and (= new-itm old-itm)
|
||||
(identical? new-idx old-idx)
|
||||
(let [childs (dh/get-children (:id new-itm) new-obs)
|
||||
childs' (conj childs (:id new-itm))]
|
||||
(and (or (= new-sel old-sel)
|
||||
(not (or (boolean (some new-sel childs'))
|
||||
(boolean (some old-sel childs')))))
|
||||
(loop [ids (rest childs)
|
||||
id (first childs)]
|
||||
(if (nil? id)
|
||||
true
|
||||
(if (= (get new-obs id)
|
||||
(get old-obs id))
|
||||
(recur (rest ids)
|
||||
(first ids))
|
||||
false))))))))
|
||||
|
||||
;; This components is a piece for sharding equality check between top
|
||||
;; level frames and try to avoid rerender frames that are does not
|
||||
;; affected by the selected set.
|
||||
|
||||
(mf/defc frame-wrapper
|
||||
{::mf/wrap-props false
|
||||
::mf/wrap [#(mf/memo' % frame-wrapper-memo-equals?)]}
|
||||
[props]
|
||||
[:> layer-item props])
|
||||
|
||||
(def ^:private layers-objects
|
||||
(letfn [(strip-data [obj]
|
||||
(select-keys obj [:id :name :blocked :hidden :shapes :type]))
|
||||
(selector [{:keys [objects] :as data}]
|
||||
(persistent!
|
||||
(reduce-kv (fn [res id obj]
|
||||
(assoc! res id (strip-data obj)))
|
||||
(transient {})
|
||||
objects)))]
|
||||
(l/derived selector refs/workspace-data =)))
|
||||
|
||||
(mf/defc layers-tree
|
||||
{::mf/wrap [mf/memo]}
|
||||
[props]
|
||||
[]
|
||||
(let [selected (mf/deref refs/selected-shapes)
|
||||
data (mf/deref refs/workspace-data)
|
||||
objects (:objects data)
|
||||
objects (mf/deref layers-objects)
|
||||
root (get objects uuid/zero)]
|
||||
|
||||
;; [:& perf/profiler {:label "layers-tree" :enabled false}
|
||||
[:ul.element-list
|
||||
(for [[index id] (reverse (d/enumerate (:shapes root)))]
|
||||
[:& layer-item
|
||||
{:item (get objects id)
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key id}])]))
|
||||
(let [obj (get objects id)]
|
||||
(if (= :frame (:type obj))
|
||||
[:& frame-wrapper
|
||||
{:item (get objects id)
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key id}]
|
||||
[:& layer-item
|
||||
{:item (get objects id)
|
||||
:selected selected
|
||||
:index index
|
||||
:objects objects
|
||||
:key id}])))]))
|
||||
|
||||
|
||||
;; --- Layers Toolbox
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
(ns uxbox.main.worker
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[uxbox.config :as cfg]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.util.worker :as uw]))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue