0
Fork 0
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:
Andrey Antukh 2020-04-18 20:34:34 +02:00 committed by Alonso Torres
parent 45bf06733f
commit d6d38283e7
8 changed files with 122 additions and 60 deletions

View file

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

View file

@ -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" : {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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