From ff43df682267dbc0a9fdb91be063300f4fb55b10 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 19 Feb 2020 19:20:13 +0100 Subject: [PATCH] :bug: Many bugfixes. --- frontend/src/uxbox/main/data/workspace.cljs | 34 ++++++++- frontend/src/uxbox/main/geom.cljs | 9 ++- frontend/src/uxbox/main/refs.cljs | 5 ++ frontend/src/uxbox/main/ui/shapes/canvas.cljs | 44 +++++------ frontend/src/uxbox/main/ui/shapes/circle.cljs | 3 +- frontend/src/uxbox/main/ui/shapes/common.cljs | 75 ++----------------- frontend/src/uxbox/main/ui/shapes/rect.cljs | 9 ++- .../uxbox/main/ui/workspace/shortcuts.cljs | 1 + .../main/ui/workspace/sidebar/layers.cljs | 10 ++- .../src/uxbox/main/ui/workspace/viewport.cljs | 19 ++--- 10 files changed, 97 insertions(+), 112 deletions(-) diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index 4247aa010..603572e25 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -12,6 +12,7 @@ [uxbox.common.data :as d] [uxbox.common.pages :as cp] [uxbox.common.spec :as us] + [uxbox.common.exceptions :as ex] [uxbox.config :as cfg] [uxbox.main.constants :as c] [uxbox.main.data.icons :as udi] @@ -242,6 +243,11 @@ (rx/of (materialize-undo changes (inc index)) (commit-changes changes [] false)))))))) +(def reinitialize-undo + (ptk/reify ::reset-undo + ptk/UpdateEvent + (update [_ state] + (update state :workspace-local dissoc :undo-index :undo)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1200,7 +1206,6 @@ (ptk/reify ::delete-canvas ptk/WatchEvent (watch [_ state stream] - (prn "delete-shapes" ids) (let [shapes-map (get-in state [:workspace-data :shapes-by-id]) session-id (:session-id state) @@ -1235,7 +1240,6 @@ (ptk/reify ::delete-shapes ptk/WatchEvent (watch [_ state stream] - (prn "delete-canvas" id) (let [shapes-map (get-in state [:workspace-data :shapes-by-id]) session-id (:session-id state) @@ -1576,6 +1580,25 @@ (->> (rp/mutation :update-page params) (rx/map shapes-changes-commited)))))))) + +(defn- check-page-integrity + [data] + (let [items (d/concat (:shapes data) + (:canvas data))] + (loop [id (first items) + ids (rest items)] + (let [content (get-in data [:shapes-by-id id])] + (cond + (nil? id) + nil + (nil? content) + (ex/raise :type :validation + :code :shape-integrity + :context {:id id}) + + :else + (recur (first ids) (rest ids))))))) + (s/def ::shapes-changes-commited (s/keys :req-un [::page-id ::revn ::cp/changes])) @@ -1589,7 +1612,12 @@ (assoc-in [:workspace-page :revn] revn) (assoc-in [:pages page-id :revn] revn) (update-in [:pages-data page-id] cp/process-changes changes) - (update :workspace-data cp/process-changes changes))))) + (update :workspace-data cp/process-changes changes))) + + ptk/EffectEvent + (effect [_ state stream] + (when *assert* + (check-page-integrity (:workspace-data state)))))) ;; --- Start shape "edition mode" diff --git a/frontend/src/uxbox/main/geom.cljs b/frontend/src/uxbox/main/geom.cljs index 8fe9c2496..f838e7ba5 100644 --- a/frontend/src/uxbox/main/geom.cljs +++ b/frontend/src/uxbox/main/geom.cljs @@ -560,10 +560,13 @@ (transform shape (rotation-matrix shape))) (defn resolve-modifier - [{:keys [modifier-mtx] :as shape}] + [{:keys [resize-modifier displacement-modifier] :as shape}] (cond-> shape - (gmt/matrix? modifier-mtx) - (transform modifier-mtx))) + (gmt/matrix? resize-modifier) + (transform resize-modifier) + + (gmt/matrix? displacement-modifier) + (transform displacement-modifier))) ;; NOTE: we need applu `shape->rect-shape` 3 times because we need to ;; update the x1 x2 y1 y2 attributes on each step; this is because diff --git a/frontend/src/uxbox/main/refs.cljs b/frontend/src/uxbox/main/refs.cljs index 10664b66f..d2b4bf892 100644 --- a/frontend/src/uxbox/main/refs.cljs +++ b/frontend/src/uxbox/main/refs.cljs @@ -54,6 +54,11 @@ (-> (l/key :selected) (l/derive workspace-local))) +(defn make-selected + [id] + (-> (l/lens #(contains? % id)) + (l/derive selected-shapes))) + (def selected-canvas (-> (l/key :selected-canvas) (l/derive workspace-local))) diff --git a/frontend/src/uxbox/main/ui/shapes/canvas.cljs b/frontend/src/uxbox/main/ui/shapes/canvas.cljs index 1b5198259..f6c384f01 100644 --- a/frontend/src/uxbox/main/ui/shapes/canvas.cljs +++ b/frontend/src/uxbox/main/ui/shapes/canvas.cljs @@ -33,7 +33,7 @@ (declare canvas-wrapper) (mf/defc shape-wrapper - {:wrap [mf/wrap-memo]} + {:wrap [#(mf/wrap-memo % =)]} [{:keys [shape] :as props}] (when (and shape (not (:hidden shape))) (case (:type shape) @@ -50,13 +50,17 @@ {:fill-color "#ffffff"}) (declare canvas-shape) +(declare translate-to-canvas) (mf/defc canvas-wrapper + {:wrap [#(mf/wrap-memo % =)]} [{:keys [shape childs] :as props}] (when (and shape (not (:hidden shape))) - (let [selected (mf/deref refs/selected-shapes) - selected? (contains? selected (:id shape)) - on-mouse-down #(common/on-mouse-down % shape selected) + (let [selected-iref (mf/use-memo + {:fn #(refs/make-selected (:id shape)) + :deps (mf/deps (:id shape))}) + selected? (mf/deref selected-iref) + on-mouse-down #(common/on-mouse-down % shape) shape (merge canvas-default-props shape) on-double-click @@ -69,23 +73,11 @@ :on-mouse-down on-mouse-down} [:& canvas-shape {:shape shape :childs childs}]]))) -(defn- translate-to-canvas - [shape canvas-ds-modifier pt] - (let [rz-modifier (:resize-modifier shape) - shape (cond-> shape - (gmt/matrix? canvas-ds-modifier) - (geom/transform canvas-ds-modifier) - - (gmt/matrix? rz-modifier) - (-> (geom/transform rz-modifier) - (dissoc :resize-modifier)))] - (geom/move shape pt))) - (mf/defc canvas-shape [{:keys [shape childs] :as props}] (let [rotation (:rotation shape) ds-modifier (:displacement-modifier shape) - rz-modifier (:modifier-mtx shape) + rz-modifier (:resize-modifier shape) shape (cond-> shape (gmt/matrix? rz-modifier) (geom/transform rz-modifier) @@ -101,12 +93,22 @@ :height height )) - translate #(translate-to-canvas % ds-modifier (gpt/point (- x) (- y)))] + translate #(translate-to-canvas % ds-modifier (gpt/point (- x) (- y))) + ] [:svg {:x x :y y :width width :height height} [:& "rect" props] - (for [item (map translate childs)] - [:& shape-wrapper {:shape item :key (:id item)}])])) - + (for [item childs] + [:& shape-wrapper {:shape (translate item) :key (:id item)}])])) +(defn- translate-to-canvas + [shape canvas-ds-modifier pt] + (let [rz-modifier (:resize-modifier shape) + shape (cond-> shape + (gmt/matrix? canvas-ds-modifier) + (geom/transform canvas-ds-modifier) + (gmt/matrix? rz-modifier) + (-> (geom/transform rz-modifier) + (dissoc :resize-modifier)))] + (geom/move shape pt))) diff --git a/frontend/src/uxbox/main/ui/shapes/circle.cljs b/frontend/src/uxbox/main/ui/shapes/circle.cljs index fa2299890..4ff3a31c3 100644 --- a/frontend/src/uxbox/main/ui/shapes/circle.cljs +++ b/frontend/src/uxbox/main/ui/shapes/circle.cljs @@ -32,7 +32,6 @@ (mf/defc circle-shape [{:keys [shape] :as props}] - (let [ds-modifier (:displacement-modifier shape) rz-modifier (:resize-modifier shape) @@ -56,4 +55,4 @@ :transform transform :id (str "shape-" id) ))] - [:& "elipse" props])) + [:& "ellipse" props])) diff --git a/frontend/src/uxbox/main/ui/shapes/common.cljs b/frontend/src/uxbox/main/ui/shapes/common.cljs index e23191995..d9254fce5 100644 --- a/frontend/src/uxbox/main/ui/shapes/common.cljs +++ b/frontend/src/uxbox/main/ui/shapes/common.cljs @@ -43,71 +43,6 @@ (rx/of (dw/materialize-displacement-in-bulk selected) ::dw/page-data-update)))))) -;; (defn apply-canvas-displacement -;; "Apply the same displacement delta to all shapes identified by the -;; set if ids." -;; [id delta] -;; (us/verify ::us/uuid id) -;; (us/verify gpt/point? delta) -;; (ptk/reify ::apply-temporal-displacement-in-bulk -;; ptk/UpdateEvent -;; (update [_ state] -;; (let [shape (get-in state [:workspace-data :shapes-by-id id]) -;; prev-xfmt (:displacement-modifier shape (gmt/matrix)) -;; xfmt (gmt/translate prev-xfmt delta)] -;; (->> (assoc shape :displacement-modifier xfmt) -;; (assoc-in state [:workspace-data :shapes-by-id id])))))) - -;; (defn materialize-canvas-displacement -;; [id] -;; (us/verify ::us/uuid id) -;; (ptk/reify ::materialize-temporal-modifier -;; dw/IBatchedChange -;; ptk/UpdateEvent -;; (update [_ state] -;; (let [data (:workspace-data state) -;; shapes-map (:shapes-by-id data) - -;; canvas (get shapes-map id) - -;; xfmt (or (:displacement-modifier canvas) (gmt/matrix)) - -;; canvas (-> canvas -;; (dissoc :displacement-modifier) -;; (geom/transform xfmt)) - -;; shapes (->> (:shapes data []) -;; (map #(get shapes-map %)) -;; (filter #(= (:canvas %) id)) -;; (map #(geom/transform % xfmt))) - -;; shapes (d/index-by :id shapes) -;; shapes (assoc shapes (:id canvas) canvas)] - -;; (update-in state [:workspace-data :shapes-by-id] merge shapes))))) - -;; (defn- move-canvas -;; [id delta] -;; (ptk/reify ::move-canvas -;; ptk/UpdateEvent -;; (update [_ state] -;; (let [data (:workspace-data state) -;; shapes-map (:shapes-by-id data) - -;; canvas (-> (get shapes-map id) -;; (geom/move delta)) - -;; shapes (->> (:shapes data []) -;; (map #(get shapes-map %)) -;; (filter #(= (:canvas %) id)) -;; (map #(geom/move % delta))) - -;; shapes (d/index-by :id shapes) -;; shapes (assoc shapes (:id canvas) canvas)] - -;; (update-in state [:workspace-data :shapes-by-id] merge shapes))))) - - (def start-move-canvas (ptk/reify ::start-move-selected ptk/WatchEvent @@ -125,9 +60,11 @@ (rx/of (dw/materialize-canvas-displacement canvas-id))))))) (defn on-mouse-down - [event {:keys [id type] :as shape} selected] - (let [selected? (contains? selected id) - drawing? @refs/selected-drawing-tool] + ([event shape] (on-mouse-down event shape nil)) + ([event {:keys [id type] :as shape} kk-tmp] + (let [selected @refs/selected-shapes + selected? (contains? selected id) + drawing? @refs/selected-drawing-tool] (when-not (:blocked shape) (cond drawing? @@ -156,4 +93,4 @@ :else (do (dom/stop-propagation event) - (st/emit! start-move-selected)))))) + (st/emit! start-move-selected))))))) diff --git a/frontend/src/uxbox/main/ui/shapes/rect.cljs b/frontend/src/uxbox/main/ui/shapes/rect.cljs index 9e379bbfa..6aa881149 100644 --- a/frontend/src/uxbox/main/ui/shapes/rect.cljs +++ b/frontend/src/uxbox/main/ui/shapes/rect.cljs @@ -22,10 +22,13 @@ (declare rect-shape) (mf/defc rect-wrapper + {:wrap [#(mf/wrap-memo % =)]} [{:keys [shape] :as props}] - (let [selected (mf/deref refs/selected-shapes) - selected? (contains? selected (:id shape)) - on-mouse-down #(common/on-mouse-down % shape selected)] + (let [selected-iref (mf/use-memo + {:fn #(refs/make-selected (:id shape)) + :deps (mf/deps (:id shape))}) + selected? (mf/deref selected-iref) + on-mouse-down #(common/on-mouse-down % shape)] [:g.shape {:class (when selected? "selected") :on-mouse-down on-mouse-down} [:& rect-shape {:shape shape}]])) diff --git a/frontend/src/uxbox/main/ui/workspace/shortcuts.cljs b/frontend/src/uxbox/main/ui/workspace/shortcuts.cljs index 19f4cdfe2..6af5f72b4 100644 --- a/frontend/src/uxbox/main/ui/workspace/shortcuts.cljs +++ b/frontend/src/uxbox/main/ui/workspace/shortcuts.cljs @@ -34,6 +34,7 @@ :ctrl+z #(st/emit! dw/undo) :ctrl+shift+z #(st/emit! dw/redo) :ctrl+y #(st/emit! dw/redo) + :ctrl+q #(st/emit! dw/reinitialize-undo) :ctrl+b #(st/emit! (dw/select-for-drawing :rect)) :ctrl+e #(st/emit! (dw/select-for-drawing :circle)) :ctrl+t #(st/emit! (dw/select-for-drawing :text)) diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs index 58e24b113..43d70c1bd 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/layers.cljs @@ -79,6 +79,7 @@ ;; --- Layer Item (mf/defc layer-item + {:wrap [#(mf/wrap-memo % =)]} [{:keys [shape selected index] :as props}] (let [selected? (contains? selected (:id shape)) @@ -148,6 +149,7 @@ [:& layer-name {:shape shape}]]])) (mf/defc canvas-item + {:wrap [#(mf/wrap-memo % =)]} [{:keys [canvas shapes selected index] :as props}] (let [selected? (contains? selected (:id canvas)) local (mf/use-state {:collapsed false}) @@ -240,6 +242,7 @@ ;; --- Layers List (mf/defc layers-list + {:wrap [#(mf/wrap-memo % =)]} [{:keys [shapes selected] :as props}] [:ul.element-list (for [[index shape] shapes] @@ -249,6 +252,7 @@ :key (:id shape)}])]) (mf/defc canvas-list + {:wrap [#(mf/wrap-memo % =)]} [{:keys [shapes canvas selected] :as props}] [:ul.element-list (for [[index item] canvas] @@ -261,6 +265,7 @@ ;; --- Layers Toolbox (mf/defc layers-toolbox + {:wrap [mf/wrap-memo]} [{:keys [page] :as props}] (let [locale (i18n/use-locale) on-click #(st/emit! (dw/toggle-layout-flag :layers)) @@ -269,15 +274,16 @@ data (mf/deref refs/workspace-data) shapes-map (:shapes-by-id data) + strip #(select-keys % [:id :canvas :name :type]) canvas (->> (:canvas data) (map #(get shapes-map %)) - #_(remove nil?) + (map strip) (d/enumerate)) shapes (->> (:shapes data) (map #(get shapes-map %)) - #_(remove nil?)) + (map strip)) all-shapes (d/enumerate shapes) unc-shapes (->> shapes diff --git a/frontend/src/uxbox/main/ui/workspace/viewport.cljs b/frontend/src/uxbox/main/ui/workspace/viewport.cljs index e3426fb7c..f8a76a047 100644 --- a/frontend/src/uxbox/main/ui/workspace/viewport.cljs +++ b/frontend/src/uxbox/main/ui/workspace/viewport.cljs @@ -147,17 +147,18 @@ {:wrap [mf/wrap-memo]} [props] (let [data (mf/deref refs/workspace-data) - shapes-by-id (:shapes-by-id data) - shapes (map #(get shapes-by-id %) (:shapes data [])) - canvas (map #(get shapes-by-id %) (:canvas data [])) - unassinged (filter #(nil? (:canvas %)) shapes)] + shapes-map (:shapes-by-id data) + shapes (->> (map #(get shapes-map %) (:shapes data [])) + (group-by :canvas)) + canvas (map #(get shapes-map %) (:canvas data []))] [:g.shapes (for [item canvas] - (let [shapes (filter #(= (:canvas %) (:id item)) shapes)] - [:& canvas-wrapper {:shape item :key (:id item) - :childs shapes}])) - (for [item unassinged] - [:& shape-wrapper {:shape item :key (:id item)}])])) + [:& canvas-wrapper {:shape item + :key (:id item) + :childs (get shapes (:id item))}]) + (for [item (get shapes nil)] + [:& shape-wrapper {:shape item + :key (:id item)}])])) (mf/defc viewport [{:keys [page] :as props}]