From 6c1955c0d922eb94fb9cde5eaa3348d0c0b6dbde Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 31 Jan 2017 17:02:33 +0100 Subject: [PATCH] Many performance improvements on workspace. --- frontend/src/uxbox/main/data/workspace.cljs | 2 + .../uxbox/main/data/workspace/drawing.cljs | 19 ++-- frontend/src/uxbox/main/exports.cljs | 9 +- frontend/src/uxbox/main/refs.cljs | 8 ++ frontend/src/uxbox/main/ui.cljs | 1 + frontend/src/uxbox/main/ui/shapes/common.cljs | 9 +- frontend/src/uxbox/main/ui/workspace.cljs | 18 ++-- .../src/uxbox/main/ui/workspace/canvas.cljs | 26 +++-- .../src/uxbox/main/ui/workspace/rules.cljs | 95 +++++++------------ .../main/ui/workspace/sidebar/drawtools.cljs | 25 +++-- .../main/ui/workspace/sidebar/history.cljs | 25 ++--- .../main/ui/workspace/sidebar/layers.cljs | 10 +- 12 files changed, 120 insertions(+), 127 deletions(-) diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index 6d68320fe..837b937c2 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -53,6 +53,7 @@ :page page :selected #{} :drawing nil + :drawing-tool nil :tooltip nil}) (assoc state :workspace {:project project @@ -61,6 +62,7 @@ :flags #{:sitemap :drawtools :layers :element-options} :selected #{} :drawing nil + :drawing-tool nil :tooltip nil}))) ptk/WatchEvent diff --git a/frontend/src/uxbox/main/data/workspace/drawing.cljs b/frontend/src/uxbox/main/data/workspace/drawing.cljs index df4d95ce5..04e470ffd 100644 --- a/frontend/src/uxbox/main/data/workspace/drawing.cljs +++ b/frontend/src/uxbox/main/data/workspace/drawing.cljs @@ -33,8 +33,10 @@ (let [current (l/focus ul/selected-drawing state)] (if (or (nil? shape) (= shape current)) - (update state :workspace dissoc :drawing) - (assoc-in state [:workspace :drawing] shape))))) + (update state :workspace dissoc :drawing :drawing-tool) + (update state :workspace assoc + :drawing shape + :drawing-tool shape))))) (defn select-for-drawing [shape] @@ -105,9 +107,8 @@ (deftype FinishDrawing [] ptk/WatchEvent (watch [_ state stream] - (println "finish-drawing" (get-in state [:workspace :drawing])) (if-let [shape (get-in state [:workspace :drawing])] - (rx/of #(update % :workspace dissoc :drawing) + (rx/of #(update % :workspace dissoc :drawing :drawing-tool) (uds/add-shape shape) (uds/select-first-shape) ::uev/interrupt) @@ -197,11 +198,9 @@ (defn- translate-to-canvas [point] - (let [zoom @refs/selected-zoom - ccords (gpt/multiply canvas-coords zoom)] - (-> point - (gpt/subtract ccords) - (gpt/divide zoom)))) + (-> point + (gpt/subtract (gpt/multiply canvas-coords @refs/selected-zoom)) + (gpt/divide @refs/selected-zoom))) (declare on-init-draw-icon) (declare on-init-draw-path) @@ -302,7 +301,7 @@ (defn- on-init-draw-free-path [shape stoper] (let [stoper (get-path-stoper-stream stoper true) - mouse (->> (rx/sample 10 streams/viewport-mouse-position) + mouse (->> streams/viewport-mouse-position (rx/mapcat conditional-align) (rx/map translate-to-canvas)) diff --git a/frontend/src/uxbox/main/exports.cljs b/frontend/src/uxbox/main/exports.cljs index adaafa373..f646dc91a 100644 --- a/frontend/src/uxbox/main/exports.cljs +++ b/frontend/src/uxbox/main/exports.cljs @@ -64,6 +64,9 @@ (defn render-page [id] - (let [page (get-in @*state* [:pages id])] - (when (:shapes page) - (mx/render-static-html (page-svg page))))) + (try + (let [page (get-in @*state* [:pages id])] + (when (:shapes page) + (mx/render-static-html (page-svg page)))) + (catch :default e + nil))) diff --git a/frontend/src/uxbox/main/refs.cljs b/frontend/src/uxbox/main/refs.cljs index e069e9102..0008c1b77 100644 --- a/frontend/src/uxbox/main/refs.cljs +++ b/frontend/src/uxbox/main/refs.cljs @@ -62,6 +62,14 @@ (-> (l/key :zoom) (l/derive workspace))) +(def selected-tooltip + (-> (l/key :tooltip) + (l/derive workspace))) + +(def selected-drawing-tool + (-> (l/key :drawing-tool) + (l/derive workspace))) + (defn alignment-activated? [state] (let [flags (l/focus ul/workspace-flags state)] diff --git a/frontend/src/uxbox/main/ui.cljs b/frontend/src/uxbox/main/ui.cljs index 14d7dcad8..e2f3857d4 100644 --- a/frontend/src/uxbox/main/ui.cljs +++ b/frontend/src/uxbox/main/ui.cljs @@ -52,6 +52,7 @@ "A default error handler." [{:keys [status] :as error}] (js/console.log "on-error:" (pr-str error)) + (js/console.log "stack:" (.-stack error)) (reset! st/loader false) (cond ;; Unauthorized or Auth timeout diff --git a/frontend/src/uxbox/main/ui/shapes/common.cljs b/frontend/src/uxbox/main/ui/shapes/common.cljs index 980b783e0..8efc519f4 100644 --- a/frontend/src/uxbox/main/ui/shapes/common.cljs +++ b/frontend/src/uxbox/main/ui/shapes/common.cljs @@ -21,12 +21,13 @@ ;; --- Refs (def edition-ref - (-> (l/in [:workspace :edition]) - (l/derive st/state))) + (-> (l/in [:edition]) + (l/derive refs/workspace))) +;; TODO: replace with refs/selected-drawing-tool (def drawing-state-ref - (-> (l/in [:workspace :drawing]) - (l/derive st/state))) + (-> (l/key :drawing-tool) + (l/derive refs/workspace))) (def selected-ref (-> (l/in [:selected]) diff --git a/frontend/src/uxbox/main/ui/workspace.cljs b/frontend/src/uxbox/main/ui/workspace.cljs index 133c7d307..1127a6bd0 100644 --- a/frontend/src/uxbox/main/ui/workspace.cljs +++ b/frontend/src/uxbox/main/ui/workspace.cljs @@ -8,6 +8,7 @@ (ns uxbox.main.ui.workspace (:require [beicon.core :as rx] [potok.core :as ptk] + [lentes.core :as l] [uxbox.main.store :as st] [uxbox.main.constants :as c] [uxbox.main.refs :as refs] @@ -97,6 +98,10 @@ (st/emit! (dw/decrease-zoom))) (scroll/scroll-to-point dom mouse-point scroll-position)))) +(def ^:private workspace-page-ref + (-> (l/key :page) + (l/derive refs/workspace))) + (mx/defcs workspace {:did-remount workspace-did-remount :will-mount workspace-will-mount @@ -104,15 +109,15 @@ :did-mount workspace-did-mount :mixins [mx/static mx/reactive - shortcuts-mixin - (mx/local)]} + shortcuts-mixin]} [own] - (let [{:keys [flags zoom page] :as workspace} (mx/react refs/workspace) + (let [flags (mx/react refs/flags) + page (mx/react workspace-page-ref) + left-sidebar? (not (empty? (keep flags [:layers :sitemap :document-history]))) right-sidebar? (not (empty? (keep flags [:icons :drawtools :element-options]))) - local (:rum/local own) classes (classnames :no-tool-bar-right (not right-sidebar?) :no-tool-bar-left (not left-sidebar?) @@ -123,7 +128,6 @@ (colorpalette) [:main.main-content - [:section.workspace-content {:class classes :on-scroll on-scroll @@ -133,8 +137,8 @@ (history-dialog page) ;; Rules - (horizontal-rule zoom) - (vertical-rule zoom) + (horizontal-rule) + (vertical-rule) ;; Canvas [:section.workspace-canvas diff --git a/frontend/src/uxbox/main/ui/workspace/canvas.cljs b/frontend/src/uxbox/main/ui/workspace/canvas.cljs index d4ec79317..62a72c3ca 100644 --- a/frontend/src/uxbox/main/ui/workspace/canvas.cljs +++ b/frontend/src/uxbox/main/ui/workspace/canvas.cljs @@ -103,11 +103,9 @@ ;; --- Canvas (mx/defc canvas - {:mixins [mx/reactive]} + {:mixins [mx/static mx/reactive]} [{:keys [metadata id] :as page}] - (let [workspace (mx/react refs/workspace) - flags (:flags workspace) - width (:width metadata) + (let [width (:width metadata) height (:height metadata)] [:svg.page-canvas {:x c/canvas-start-x :y c/canvas-start-y @@ -201,14 +199,12 @@ :will-unmount viewport-will-unmount :mixins [mx/reactive]} [] - (let [workspace (mx/react refs/workspace) - page (mx/react refs/selected-page) - flags (:flags workspace) - drawing? (:drawing workspace) - tooltip (if (:tooltip workspace) - (:tooltip workspace) - (get-shape-tooltip drawing?)) - zoom (or (:zoom workspace) 1)] + (let [page (mx/react refs/selected-page) + flags (mx/react refs/flags) + drawing (mx/react refs/selected-drawing-tool) + tooltip (or (mx/react refs/selected-tooltip) + (get-shape-tooltip drawing)) + zoom (or (mx/react refs/selected-zoom) 1)] (letfn [(on-mouse-down [event] (dom/stop-propagation event) (let [ctrl? (kbd/ctrl? event) @@ -216,8 +212,8 @@ opts {:shift? shift? :ctrl? ctrl?}] (st/emit! (uev/mouse-event :down ctrl? shift?))) - (if-let [object (:drawing workspace)] - (st/emit! (udw/start-drawing object)) + (if drawing + (st/emit! (udw/start-drawing drawing)) (st/emit! (udw/start-selrect)))) (on-context-menu [event] (dom/prevent-default event) @@ -255,7 +251,7 @@ [:svg.viewport {:width (* c/viewport-width zoom) :height (* c/viewport-height zoom) :ref "viewport" - :class (when drawing? "drawing") + :class (when drawing "drawing") :on-context-menu on-context-menu :on-click on-click :on-double-click on-double-click diff --git a/frontend/src/uxbox/main/ui/workspace/rules.cljs b/frontend/src/uxbox/main/ui/workspace/rules.cljs index e3b36b5cf..d526c304d 100644 --- a/frontend/src/uxbox/main/ui/workspace/rules.cljs +++ b/frontend/src/uxbox/main/ui/workspace/rules.cljs @@ -6,8 +6,7 @@ ;; Copyright (c) 2015-2017 Juan de la Cruz (ns uxbox.main.ui.workspace.rules - (:require [sablono.core :as html :refer-macros [html]] - [rum.core :as rum] + (:require [sablono.core :refer-macros [html]] [cuerdas.core :as str] [beicon.core :as rx] [uxbox.main.store :as s] @@ -104,84 +103,62 @@ ;; --- Horizontal Rule Ticks (Component) -(defn- horizontal-rule-ticks-render - [own zoom] +(mx/defc horizontal-rule-ticks + {:mixins [mx/static]} + [zoom] (let [zoom (or zoom 1) path (reduce (partial make-vertical-tick zoom) [] +ticks+) labels (->> (map (partial horizontal-text-label zoom) +ticks+) (filterv identity))] - (html - [:g - [:path {:d (str/join " " path) :stroke "#9da2a6"}] - labels]))) - -(def ^:private horizontal-rule-ticks - (mx/component - {:render horizontal-rule-ticks-render - :name "horizontal-rule-ticks" - :mixins [mx/static]})) + [:g + [:path {:d (str/join " " path) :stroke "#9da2a6"}] + labels])) ;; --- Vertical Rule Ticks (Component) -(defn- vertical-rule-ticks-render - [own zoom] +(mx/defc vertical-rule-ticks + {:mixins [mx/static]} + [zoom] (let [zoom (or zoom 1) path (reduce (partial make-horizontal-tick zoom) [] +ticks+) labels (->> (map (partial vertical-text-label zoom) +ticks+) (filterv identity))] - (html - [:g - [:path {:d (str/join " " path) :stroke "#9da2a6"}] - labels]))) - -(def ^:private vertical-rule-ticks - (mx/component - {:render vertical-rule-ticks-render - :name "vertical-rule-ticks" - :mixins [mx/static]})) + [:g + [:path {:d (str/join " " path) :stroke "#9da2a6"}] + labels])) ;; --- Horizontal Rule (Component) -(defn horizontal-rule-render - [own zoom] +(mx/defc horizontal-rule + {:mixins [mx/static mx/reactive]} + [] (let [scroll (mx/react refs/workspace-scroll) + zoom (mx/react refs/selected-zoom) scroll-x (:x scroll) translate-x (- (- c/canvas-scroll-padding) (:x scroll))] - (html - [:svg.horizontal-rule - {:width c/viewport-width - :height 20} - [:g {:transform (str "translate(" translate-x ", 0)")} - (horizontal-rule-ticks zoom)]]))) - -(def horizontal-rule - (mx/component - {:render horizontal-rule-render - :name "horizontal-rule" - :mixins [mx/static mx/reactive]})) + [:svg.horizontal-rule + {:width c/viewport-width + :height 20} + [:g {:transform (str "translate(" translate-x ", 0)")} + (horizontal-rule-ticks zoom)]])) ;; --- Vertical Rule (Component) -(defn vertical-rule-render - [own zoom] +(mx/defc vertical-rule + {:mixins [mx/static mx/reactive]} + [] (let [scroll (mx/react refs/workspace-scroll) + zoom (mx/react refs/selected-zoom) scroll-y (:y scroll) translate-y (- (- c/canvas-scroll-padding) (:y scroll))] - (html - [:svg.vertical-rule - {:width 20 - :height c/viewport-height} + [:svg.vertical-rule + {:width 20 + :height c/viewport-height} - [:g {:transform (str "translate(0, " translate-y ")")} - (vertical-rule-ticks zoom)] - [:rect {:x 0 - :y 0 - :height 20 - :width 20 - :fill "rgb(233, 234, 235)"}]]))) - -(def vertical-rule - (mx/component - {:render vertical-rule-render - :name "vertical-rule" - :mixins [mx/static mx/reactive]})) + [:g {:transform (str "translate(0, " translate-y ")")} + (vertical-rule-ticks zoom)] + [:rect {:x 0 + :y 0 + :height 20 + :width 20 + :fill "rgb(233, 234, 235)"}]])) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/drawtools.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/drawtools.cljs index d1b65f599..416b45637 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/drawtools.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/drawtools.cljs @@ -14,6 +14,7 @@ [uxbox.main.data.workspace :as dw] [uxbox.main.user-events :as uev] [uxbox.builtins.icons :as i] + [uxbox.util.uuid :as uuid] [uxbox.util.i18n :refer (tr)] [uxbox.util.router :as r] [uxbox.util.data :refer (read-string)] @@ -22,27 +23,30 @@ ;; --- Refs -(def ^:private drawing-shape +(def ^:private drawing-shape-id-ref "A focused vision of the drawing property of the workspace status. This avoids rerender the whole toolbox on each workspace change." - (-> (l/in [:workspace :drawing]) - (l/derive st/state))) + (-> (l/key :drawing-tool) + (l/derive refs/workspace))) ;; --- Constants (def +draw-tool-rect+ {:type :rect + :id (uuid/random) :name "Rect" :stroke-color "#000000"}) (def +draw-tool-circle+ {:type :circle + :id (uuid/random) :name "Circle"}) (def +draw-tool-path+ {:type :path + :id (uuid/random) :name "Path" :stroke-style :solid :stroke-color "#000000" @@ -52,8 +56,14 @@ ;; :close? true :points []}) +(def +draw-tool-curve+ + (assoc +draw-tool-path+ + :id (uuid/random) + :free true)) + (def +draw-tool-text+ {:type :text + :id (uuid/random) :name "Text" :content "Hello world"}) @@ -76,7 +86,7 @@ :priority 5} {:icon i/pencil :help (tr "ds.help.path") - :shape (assoc +draw-tool-path+ :free true) + :shape +draw-tool-curve+ :priority 6}]) ;; --- Draw Toolbox (Component) @@ -88,9 +98,8 @@ (mx/defc draw-toolbox {:mixins [mx/static mx/reactive]} - [own] - (let [workspace (mx/react refs/workspace) - drawing (mx/react drawing-shape) + [] + (let [drawing-tool (mx/react refs/selected-drawing-tool) close #(st/emit! (dw/toggle-flag :drawtools)) tools (->> (into [] +draw-tools+) (sort-by (comp :priority second)))] @@ -101,7 +110,7 @@ [:div.tool-window-close {:on-click close} i/close]] [:div.tool-window-content (for [[i props] (map-indexed vector tools) - :let [selected? (= drawing (:shape props))]] + :let [selected? (= drawing-tool (:shape props))]] [:div.tool-btn.tooltip.tooltip-hover {:alt (:help props) :class (when selected? "selected") diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/history.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/history.cljs index 3565d6304..c82a26a12 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/history.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/history.cljs @@ -151,24 +151,17 @@ ;; --- History Dialog -(defn history-dialog-render - [own page] +(mx/defc history-dialog + {:mixins [mx/static mx/reactive]} + [page] (let [history (mx/react history-ref) version (:selected history) on-accept #(st/emit! (udh/apply-selected-history page)) on-cancel #(st/emit! (udh/deselect-page-history page))] (when (or version (:deselecting history)) - (html - [:div.message-version - {:class (when (:deselecting history) "hide-message")} - [:span (tr "history.alert-message" (or version "00")) - [:div.message-action - [:a.btn-transparent {:on-click on-accept} "Accept"] - [:a.btn-transparent {:on-click on-cancel} "Cancel"]]]])))) - -(def history-dialog - (mx/component - {:render history-dialog-render - :name "history-dialog" - :mixins [mx/static mx/reactive]})) - + [:div.message-version + {:class (when (:deselecting history) "hide-message")} + [:span (tr "history.alert-message" (or version "00")) + [:div.message-action + [:a.btn-transparent {:on-click on-accept} "Accept"] + [:a.btn-transparent {:on-click on-cancel} "Cancel"]]]]))) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index e136dbca2..a0012a4b4 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -288,13 +288,13 @@ ;; --- Layers Toolbox (Component) (mx/defc layers-toolbox - {:mixins [mx/reactive]} + {:mixins [mx/static mx/reactive]} [] - (let [workspace (mx/react refs/workspace) - selected (:selected workspace) - ;; TODO: dont react to the while shapes-by-id + (let [selected (mx/react refs/selected-shapes) + page (mx/react refs/selected-page) + + ;; TODO: dont react to the whole shapes-by-id shapes-map (mx/react refs/shapes-by-id) - page (mx/react (focus-page (:page workspace))) close #(st/emit! (udw/toggle-flag :layers)) duplicate #(st/emit! (uds/duplicate-selected)) group #(st/emit! (uds/group-selected))