From 71bb34efc51ac59ab279ec5c4327535fea6a6f4a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 26 Apr 2022 18:26:33 +0200 Subject: [PATCH] :zap: Improved first load time --- common/src/app/common/pages/helpers.cljc | 2 +- common/src/app/common/pages/indices.cljc | 33 ++++++++++------- frontend/src/app/main/data/workspace.cljs | 27 ++++++++------ .../src/app/main/data/workspace/common.cljs | 5 ++- .../app/main/data/workspace/persistence.cljs | 4 +-- frontend/src/app/main/repo.cljs | 27 +++++++++----- frontend/src/app/util/worker.cljs | 13 ++++--- frontend/src/app/worker.cljs | 10 +++--- frontend/src/app/worker/impl.cljs | 16 +++++---- frontend/src/app/worker/messages.cljs | 36 +++++++++++++++++++ frontend/src/app/worker/selection.cljs | 20 ++++++----- 11 files changed, 128 insertions(+), 65 deletions(-) create mode 100644 frontend/src/app/worker/messages.cljs diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 63f693195..1059d1435 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -92,7 +92,7 @@ "Returns a vector of parents of the specified shape." [objects shape-id] (loop [result [] id shape-id] - (if-let [parent-id (->> id (get objects) :parent-id)] + (if-let [parent-id (get-in objects [id :parent-id])] (recur (conj result parent-id) parent-id) result))) diff --git a/common/src/app/common/pages/indices.cljc b/common/src/app/common/pages/indices.cljc index 2ec512478..3a5a852ee 100644 --- a/common/src/app/common/pages/indices.cljc +++ b/common/src/app/common/pages/indices.cljc @@ -11,16 +11,17 @@ [app.common.uuid :as uuid] [clojure.set :as set])) -(defn calculate-frame-z-index [z-index frame-id objects] +(defn calculate-frame-z-index + [z-index frame-id base-idx objects] + (let [is-frame? (fn [id] (= :frame (get-in objects [id :type]))) - frame-shapes (->> objects (vals) (filterv #(= (:frame-id %) frame-id))) children (or (get-in objects [frame-id :shapes]) [])] (if (empty? children) z-index (loop [current (peek children) pending (pop children) - current-idx (count frame-shapes) + current-idx base-idx z-index z-index] (let [children (get-in objects [current :shapes]) @@ -46,10 +47,15 @@ [objects] (let [frames (cph/get-frames objects) - z-index (calculate-frame-z-index {} uuid/zero objects)] + + by-frame (cph/objects-by-frame objects) + frame-base-idx (d/update-vals by-frame count) + + z-index (calculate-frame-z-index {} uuid/zero (get frame-base-idx uuid/zero) objects)] (->> frames - (map :id) - (reduce #(calculate-frame-z-index %1 %2 objects) z-index)))) + (reduce + (fn [z-index {:keys [id]}] + (calculate-frame-z-index z-index id (get frame-base-idx id) objects)) z-index)))) (defn update-z-index "Updates the z-index given a set of ids to change and the old and new objects @@ -65,10 +71,13 @@ (map :id) (filter #(contains? changed-frames %))) - z-index (calculate-frame-z-index z-index uuid/zero new-objects)] + by-frame (cph/objects-by-frame new-objects) + frame-base-idx (d/update-vals by-frame count) + z-index (calculate-frame-z-index z-index uuid/zero (get frame-base-idx uuid/zero) new-objects)] (->> frames - (reduce #(calculate-frame-z-index %1 %2 new-objects) z-index)))) + (reduce (fn [z-index id] + (calculate-frame-z-index z-index id (get frame-base-idx id) new-objects)) z-index)))) (defn generate-child-parent-index [objects] @@ -84,10 +93,10 @@ (generate-child-all-parents-index objects (vals objects))) ([objects shapes] - (let [xf-parents (comp - (map :id) - (map #(vector % (cph/get-parent-ids objects %))))] - (into {} xf-parents shapes)))) + (let [shape->entry + (fn [shape] + [(:id shape) (cph/get-parent-ids objects (:id shape))])] + (into {} (map shape->entry) shapes)))) (defn create-clip-index "Retrieves the mask information for an object" diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index daabc9e74..768ca5b2b 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -115,17 +115,24 @@ (rx/filter (ptk/type? ::dwp/bundle-fetched)) (rx/take 1) (rx/map deref) - (rx/mapcat (fn [bundle] - (let [team-id (-> bundle :project :team-id)] - (rx/merge - (rx/of (dwn/initialize team-id file-id) - (dwp/initialize-file-persistence file-id) - (dwc/initialize-indices bundle)) + (rx/mapcat + (fn [bundle] + (rx/merge + (rx/of (dwc/initialize-indices bundle)) - (->> stream - (rx/filter #(= ::dwc/index-initialized %)) - (rx/take 1) - (rx/map #(file-initialized bundle)))))))))) + (->> (rx/of bundle) + (rx/mapcat + (fn [bundle] + (let [bundle (assoc bundle :file (t/decode-str (:file-raw bundle))) + team-id (dm/get-in bundle [:project :team-id])] + (rx/merge + (rx/of (dwn/initialize team-id file-id) + (dwp/initialize-file-persistence file-id)) + + (->> stream + (rx/filter #(= ::dwc/index-initialized %)) + (rx/take 1) + (rx/map #(file-initialized bundle)))))))))))))) ptk/EffectEvent (effect [_ _ _] diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 3b7a99355..d50b29c2d 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -48,13 +48,12 @@ ;; --- Selection Index Handling (defn initialize-indices - [{:keys [file] :as bundle}] + [{:keys [file-raw] :as bundle}] (ptk/reify ::setup-selection-index ptk/WatchEvent (watch [_ _ _] (let [msg {:cmd :initialize-indices - :file-id (:id file) - :data (:data file)}] + :file-raw file-raw}] (->> (uw/ask! msg) (rx/map (constantly ::index-initialized))))))) diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index c27766a08..8bf0f2db4 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -251,8 +251,8 @@ (rp/query :project {:id project-id}) (rp/query :file-libraries {:file-id file-id})) (rx/take 1) - (rx/map (fn [[file users project libraries]] - {:file file + (rx/map (fn [[file-raw users project libraries]] + {:file-raw file-raw :users users :project project :libraries libraries})) diff --git a/frontend/src/app/main/repo.cljs b/frontend/src/app/main/repo.cljs index 2e3ffb9fa..907020c7a 100644 --- a/frontend/src/app/main/repo.cljs +++ b/frontend/src/app/main/repo.cljs @@ -35,8 +35,7 @@ (rx/throw {:type :validation :code :request-body-too-large}) - (and (>= status 400) - (map? body)) + (and (>= status 400) (map? body)) (rx/throw body) :else @@ -49,13 +48,19 @@ (defn- send-query! "A simple helper for send and receive transit data on the penpot query api." - [id params] - (->> (http/send! {:method :get - :uri (u/join base-uri "api/rpc/query/" (name id)) - :credentials "include" - :query params}) - (rx/map http/conditional-decode-transit) - (rx/mapcat handle-response))) + ([id params] + (send-query! id params nil)) + + ([id params {:keys [raw-transit?]}] + (let [decode-transit (if raw-transit? + identity + (partial rx/map http/conditional-decode-transit))] + (->> (http/send! {:method :get + :uri (u/join base-uri "api/rpc/query/" (name id)) + :credentials "include" + :query params}) + (decode-transit) + (rx/mapcat handle-response))))) (defn- send-mutation! "A simple helper for a common case of sending and receiving transit @@ -77,6 +82,10 @@ [id params] (send-query! id params)) +(defmethod query :file + [id params] + (send-query! id params {:raw-transit? true})) + (defmethod mutation :default [id params] (send-mutation! id params)) diff --git a/frontend/src/app/util/worker.cljs b/frontend/src/app/util/worker.cljs index 0ffa78d54..59d98f5b5 100644 --- a/frontend/src/app/util/worker.cljs +++ b/frontend/src/app/util/worker.cljs @@ -7,10 +7,10 @@ (ns app.util.worker "A lightweight layer on top of webworkers api." (:require - [app.common.transit :as t] [app.common.uuid :as uuid] [app.util.globals :refer [global]] [app.util.object :as obj] + [app.worker.messages :as wm] [beicon.core :as rx])) (declare handle-response) @@ -27,7 +27,7 @@ (rx/take-while #(not (:completed %)) ob) (rx/take 1 ob))) - data (t/encode-str message) + data (wm/encode message) instance (:instance worker)] (if (some? instance) @@ -71,11 +71,10 @@ handle-message (fn [event] - (let [data (.-data event) - data (t/decode-str data)] - (if (:error data) - (on-error (:error data)) - (rx/push! bus data)))) + (let [message (wm/decode (.-data event))] + (if (:error message) + (on-error (:error message)) + (rx/push! bus message)))) handle-error (fn [error] diff --git a/frontend/src/app/worker.cljs b/frontend/src/app/worker.cljs index 5889a8cd9..bb5ef3ff0 100644 --- a/frontend/src/app/worker.cljs +++ b/frontend/src/app/worker.cljs @@ -8,10 +8,10 @@ (:require [app.common.logging :as log] [app.common.spec :as us] - [app.common.transit :as t] [app.worker.export] [app.worker.impl :as impl] [app.worker.import] + [app.worker.messages :as wm] [app.worker.selection] [app.worker.snaps] [app.worker.thumbnails] @@ -46,7 +46,7 @@ [{:keys [sender-id payload] :as message}] (us/assert ::message message) (letfn [(post [msg] - (let [msg (-> msg (assoc :reply-to sender-id) (t/encode-str))] + (let [msg (-> msg (assoc :reply-to sender-id) (wm/encode))] (.postMessage js/self msg))) (reply [result] @@ -91,8 +91,8 @@ "Sends to the client a notification that its messages have been dropped" [{:keys [sender-id] :as message}] (us/assert ::message message) - (.postMessage js/self (t/encode-str {:reply-to sender-id - :dropped true}))) + (.postMessage js/self (wm/encode {:reply-to sender-id + :dropped true}))) (defn subscribe-buffer-messages "Creates a subscription to process the buffer messages" @@ -150,7 +150,7 @@ [event] (when (nil? (.-source event)) (let [message (.-data event) - message (t/decode-str message)] + message (wm/decode message)] (if (:buffer? message) (rx/push! buffer message) (handle-message message))))) diff --git a/frontend/src/app/worker/impl.cljs b/frontend/src/app/worker/impl.cljs index 977c8d85e..cfef2e3e2 100644 --- a/frontend/src/app/worker/impl.cljs +++ b/frontend/src/app/worker/impl.cljs @@ -7,6 +7,7 @@ (ns app.worker.impl (:require [app.common.pages.changes :as ch] + [app.common.transit :as t] [app.util.globals :refer [global]] [app.util.object :as obj] [okulary.core :as l])) @@ -28,14 +29,15 @@ message) (defmethod handler :initialize-indices - [{:keys [data] :as message}] + [{:keys [file-raw] :as message}] - (reset! state data) - - (handler (-> message - (assoc :cmd :selection/initialize-index))) - (handler (-> message - (assoc :cmd :snaps/initialize-index)))) + (let [data (-> (t/decode-str file-raw) :data) + message (assoc message :data data)] + (reset! state data) + (handler (-> message + (assoc :cmd :selection/initialize-index))) + (handler (-> message + (assoc :cmd :snaps/initialize-index))))) (defmethod handler :update-page-indices [{:keys [page-id changes] :as message}] diff --git a/frontend/src/app/worker/messages.cljs b/frontend/src/app/worker/messages.cljs new file mode 100644 index 000000000..87dc3b6c9 --- /dev/null +++ b/frontend/src/app/worker/messages.cljs @@ -0,0 +1,36 @@ +;; 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.worker.messages + "A lightweight layer on top of webworkers api." + (:require + [app.common.data :as d] + [app.common.transit :as t] + [app.util.object :as obj])) + +(defn encode [{:keys [sender-id reply-to payload buffer?] :as message}] + #js {:cmd (d/name (:cmd payload)) + :senderId (when sender-id (str sender-id)) + :replyTo (when reply-to (str reply-to)) + :payload (if (= :initialize-indices (:cmd payload)) + (:file-raw payload) + (when (some? payload) (t/encode-str payload))) + :buffer (when (some? buffer?) buffer?)}) + +(defn decode [^js data] + (let [cmd (obj/get data "cmd") + sender-id (obj/get data "senderId") + reply-to (obj/get data "replyTo") + payload (obj/get data "payload") + buffer (obj/get data "buffer")] + (d/without-nils + {:sender-id (when sender-id (uuid sender-id)) + :reply-to (when reply-to (uuid reply-to)) + :payload (if (= cmd "initialize-indices") + {:cmd :initialize-indices + :file-raw payload} + (when (some? payload) (t/decode-str payload))) + :buffer? buffer}))) diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index 74abc06dc..138c79b06 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -21,7 +21,7 @@ (defonce state (l/atom {})) -(defn index-shape +(defn make-index-shape [objects parents-index clip-parents-index] (fn [index shape] (let [{:keys [x y width height]} @@ -77,13 +77,16 @@ (let [shapes (-> objects (dissoc uuid/zero) vals) parents-index (cp/generate-child-all-parents-index objects) clip-parents-index (cp/create-clip-index objects parents-index) - bounds (-> objects objects-bounds add-padding-bounds) - index (reduce (index-shape objects parents-index clip-parents-index) - (qdt/create (clj->js bounds)) - shapes) + root-shapes (cph/get-immediate-children objects uuid/zero) + bounds (-> root-shapes gsh/selection-rect add-padding-bounds) - z-index (cp/calculate-z-index objects)] + index-shape (make-index-shape objects parents-index clip-parents-index) + initial-quadtree (qdt/create (clj->js bounds)) + + index (reduce index-shape initial-quadtree shapes) + + z-index (cp/calculate-z-index objects)] {:index index :z-index z-index :bounds bounds})) @@ -106,9 +109,8 @@ new-index (qdt/remove-all index changed-ids) - index (reduce (index-shape new-objects parents-index clip-parents-index) - new-index - shapes) + index-shape (make-index-shape new-objects parents-index clip-parents-index) + index (reduce index-shape new-index shapes) z-index (cp/update-z-index z-index changed-ids old-objects new-objects)]