From a71a7d6951222c3251fa50d599013fd45edd1973 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 3 Dec 2020 22:29:47 +0100 Subject: [PATCH] :bug: Fixed problems with resize texts --- frontend/src/app/main/data/workspace.cljs | 20 +---- .../src/app/main/data/workspace/common.cljs | 6 +- .../main/data/workspace/drawing/common.cljs | 2 +- .../src/app/main/data/workspace/texts.cljs | 42 +++++++++ .../app/main/data/workspace/transforms.cljs | 23 ++++- frontend/src/app/main/ui/shapes/group.cljs | 11 +-- frontend/src/app/main/ui/shapes/shape.cljs | 2 +- frontend/src/app/main/ui/shapes/text.cljs | 3 +- .../app/main/ui/workspace/context_menu.cljs | 4 +- .../app/main/ui/workspace/shapes/group.cljs | 41 ++++++--- .../app/main/ui/workspace/shapes/text.cljs | 87 ++++++++----------- .../main/ui/workspace/shapes/text/editor.cljs | 4 +- .../workspace/sidebar/options/component.cljs | 4 +- .../ui/workspace/sidebar/options/fill.cljs | 4 +- .../ui/workspace/sidebar/options/page.cljs | 4 +- .../ui/workspace/sidebar/options/shadow.cljs | 4 +- .../ui/workspace/sidebar/options/stroke.cljs | 4 +- 17 files changed, 149 insertions(+), 116 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 817afccaa..99fbecd7d 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1003,21 +1003,6 @@ :operations ops2 :id (:id curr)}))))))))) -;; --- Update Dimensions - -;; Event mainly used for handling user modification of the size of the -;; object from workspace sidebar options inputs. - -(defn update-dimensions - [ids attr value] - (us/verify (s/coll-of ::us/uuid) ids) - (us/verify #{:width :height} attr) - (us/verify ::us/number value) - (ptk/reify ::update-dimensions - ptk/WatchEvent - (watch [_ state stream] - (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) - ;; --- Shape Proportions (defn set-shape-proportion-lock @@ -1348,10 +1333,10 @@ :height height :grow-type (if (> (count text) 100) :auto-height :auto-width) :content (as-content text)})] - (rx/of dwc/start-undo-transaction + (rx/of (dwc/start-undo-transaction) (dws/deselect-all) (dwc/add-shape shape) - dwc/commit-undo-transaction))))) + (dwc/commit-undo-transaction)))))) (defn- image-uploaded [image] @@ -1610,6 +1595,7 @@ (d/export dwt/set-rotation) (d/export dwt/set-modifiers) (d/export dwt/apply-modifiers) +(d/export dwt/update-dimensions) ;; Persistence diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 0cdd80018..663e037c7 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -288,7 +288,7 @@ (defonce empty-tx {:undo-changes [] :redo-changes []}) -(def start-undo-transaction +(defn start-undo-transaction [] (ptk/reify ::start-undo-transaction ptk/UpdateEvent (update [_ state] @@ -297,13 +297,13 @@ (cond-> state (nil? current-tx) (assoc-in [:workspace-undo :transaction] empty-tx)))))) -(def discard-undo-transaction +(defn discard-undo-transaction [] (ptk/reify ::discard-undo-transaction ptk/UpdateEvent (update [_ state] (update state :workspace-undo dissoc :transaction)))) -(def commit-undo-transaction +(defn commit-undo-transaction [] (ptk/reify ::commit-undo-transaction ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/workspace/drawing/common.cljs b/frontend/src/app/main/data/workspace/drawing/common.cljs index 424287b3f..c5a19c32c 100644 --- a/frontend/src/app/main/data/workspace/drawing/common.cljs +++ b/frontend/src/app/main/data/workspace/drawing/common.cljs @@ -55,7 +55,7 @@ ;; Add & select the created shape to the workspace (rx/concat (if (= :text (:type shape)) - (rx/of dwc/start-undo-transaction) + (rx/of (dwc/start-undo-transaction)) (rx/empty)) (rx/of (dws/deselect-all) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index c13a6dda2..ed9b2dc82 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -19,6 +19,7 @@ [app.common.geom.shapes :as geom] [app.common.attrs :as attrs] [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.transforms :as dwt] [app.main.fonts :as fonts] [app.util.object :as obj] [app.util.text :as ut])) @@ -210,3 +211,44 @@ (and (= 1 (count selected)) (= (-> selected first :type) :text)) (assoc-in [:workspace-local :edition] (-> selected first :id))))))) + +(defn resize-text [id new-width new-height] + (ptk/reify ::resize-text + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + shape (get-in state [:workspace-data :pages-index page-id :objects id]) + {:keys [selrect grow-type overflow-text]} shape + {shape-width :width shape-height :height} selrect + undo-transaction (get-in state [:workspace-undo :transaction]) + + events (when (and (> new-width 0) (> new-height 0)) + (cond + (and overflow-text (not= :fixed grow-type)) + [(update-overflow-text id false)] + + (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) + [(update-overflow-text id true)] + + (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) + [(update-overflow-text id false)] + + (and (or (not= shape-width new-width) + (not= shape-height new-height)) + (= grow-type :auto-width)) + (when (and (pos? shape-width) + (pos? shape-height)) + [(dwt/update-dimensions [id] :width new-width) + (dwt/update-dimensions [id] :height new-height)]) + + (and (not= shape-height new-height) (= grow-type :auto-height)) + (when (pos? shape-height) + [(dwt/update-dimensions [id] :height new-height)])))] + + (if (not (empty? events)) + (rx/concat + (when (not undo-transaction) + (rx/of (dwc/start-undo-transaction))) + (rx/from events) + (when (not undo-transaction) + (rx/of (dwc/discard-undo-transaction))))))))) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index c74221e31..44d7658a0 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -18,7 +18,6 @@ [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.common :as dwc] - [app.main.data.workspace.texts :as dwt] [app.main.data.workspace.selection :as dws] [app.main.refs :as refs] [app.main.snap :as snap] @@ -266,7 +265,7 @@ (when-not (empty? rch) (rx/of dwc/pop-undo-into-transaction (dwc/commit-changes rch uch {:commit-local? true}) - dwc/commit-undo-transaction + (dwc/commit-undo-transaction) (dwc/expand-collapse frame-id))))))) (defn start-move @@ -472,6 +471,22 @@ rchanges (conj (dwc/generate-changes page-id objects1 objects2) regchg) uchanges (conj (dwc/generate-changes page-id objects2 objects0) regchg)] - (rx/of dwc/start-undo-transaction + (rx/of (dwc/start-undo-transaction) (dwc/commit-changes rchanges uchanges {:commit-local? true}) - dwc/commit-undo-transaction))))) + (dwc/commit-undo-transaction)))))) + +;; --- Update Dimensions + +;; Event mainly used for handling user modification of the size of the +;; object from workspace sidebar options inputs. + +(defn update-dimensions + [ids attr value] + (us/verify (s/coll-of ::us/uuid) ids) + (us/verify #{:width :height} attr) + (us/verify ::us/number value) + (ptk/reify ::update-dimensions + ptk/WatchEvent + (watch [_ state stream] + #_(prn "??? update-dimensions" ids attr value) + (rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true}))))) diff --git a/frontend/src/app/main/ui/shapes/group.cljs b/frontend/src/app/main/ui/shapes/group.cljs index 03bea3db6..98c36bd0a 100644 --- a/frontend/src/app/main/ui/shapes/group.cljs +++ b/frontend/src/app/main/ui/shapes/group.cljs @@ -12,7 +12,6 @@ [rumext.alpha :as mf] [cuerdas.core :as str] [app.main.ui.shapes.attrs :as attrs] - [app.util.debug :refer [debug?]] [app.common.geom.shapes :as geom])) (def mask-id-ctx (mf/create-context nil)) @@ -32,7 +31,6 @@ childs (if (and (:masked-group? shape) (not expand-mask)) (rest childs) childs) - is-child-selected? (unchecked-get props "is-child-selected?") {:keys [id x y width height]} shape transform (geom/transform-matrix shape)] [:g @@ -48,13 +46,6 @@ [:& shape-wrapper {:frame frame :shape item :key (:id item)}])] - (when (not is-child-selected?) - [:rect {:transform transform - :x x - :y y - :fill (if (debug? :group) "red" "transparent") - :opacity 0.5 - :width width - :height height}])]))) + ]))) diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 56af59aad..cfe637c69 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -28,7 +28,7 @@ group-props (-> (obj/clone props) (obj/without ["shape" "children"]) (obj/set! "id" (str "shape-" (:id shape))) - (obj/set! "className" "shape") + (obj/set! "className" (str "shape " (:type shape))) (obj/set! "filter" (filters/filter-str filter-id shape)))] [:& (mf/provider muc/render-ctx) {:value render-id} [:> :g group-props diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index 4578692b2..c420f9421 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -100,6 +100,7 @@ :width (if (#{:auto-width} grow-type) 10000 width) :height (if (#{:auto-height :auto-width} grow-type) 10000 height) :mask mask-id - :ref ref} + :ref ref + :pointer-events "none"} [:& text-content {:shape shape :content (:content shape)}]])) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 7f1a4bbf6..de5180966 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -71,10 +71,10 @@ do-detach-component #(st/emit! (dwl/detach-component id)) do-reset-component #(st/emit! (dwl/reset-component id)) do-update-component #(do - (st/emit! dwc/start-undo-transaction) + (st/emit! (dwc/start-undo-transaction)) (st/emit! (dwl/update-component id)) (st/emit! (dwl/sync-file nil)) - (st/emit! dwc/commit-undo-transaction)) + (st/emit! (dwc/commit-undo-transaction))) do-show-component #(st/emit! (dw/go-to-layout :assets)) do-navigate-component-file #(st/emit! (dwl/nav-to-component-file (:component-file shape)))] diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index 3e265d25c..e9d502032 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -17,7 +17,9 @@ [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.workspace.effects :as we] [app.util.dom :as dom] - [rumext.alpha :as mf])) + [rumext.alpha :as mf] + [app.common.geom.shapes :as gsh] + [app.util.debug :refer [debug?]])) (defn- group-wrapper-factory-equals? [np op] @@ -46,6 +48,9 @@ (let [shape (unchecked-get props "shape") frame (unchecked-get props "frame") + {:keys [id x y width height]} shape + transform (gsh/transform-matrix shape) + childs-ref (mf/use-memo (mf/deps shape) #(refs/objects-by-id (:shapes shape))) childs (mf/deref childs-ref) @@ -69,16 +74,26 @@ handle-pointer-leave (we/use-pointer-leave shape) handle-double-click (use-double-click shape)] - [:> shape-container {:shape shape - :on-mouse-down handle-mouse-down - :on-context-menu handle-context-menu - :on-pointer-enter handle-pointer-enter - :on-pointer-leave handle-pointer-leave - :on-double-click handle-double-click} - [:& group-shape - {:frame frame - :shape shape - :childs childs - :is-child-selected? is-child-selected? - :expand-mask is-mask-selected?}]])))) + [:> shape-container {:shape shape} + [:g.group-shape + [:& group-shape + {:frame frame + :shape shape + :childs childs + :expand-mask is-mask-selected?}] + + (when-not is-child-selected? + [:rect.group-actions + {:x x + :y y + :fill (if (debug? :group) "red" "transparent") + :opacity 0.5 + :transform transform + :width width + :height height + :on-mouse-down handle-mouse-down + :on-context-menu handle-context-menu + :on-pointer-enter handle-pointer-enter + :on-pointer-leave handle-pointer-leave + :on-double-click handle-double-click}])]])))) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index ea30d0282..46121983a 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -41,52 +41,6 @@ ;; --- Text Wrapper for workspace -(defn handle-shape-resize - [{:keys [id selrect grow-type overflow-text]} new-width new-height] - (let [{shape-width :width shape-height :height} selrect - undo-transaction (get-in @st/state [:workspace-undo :transaction])] - (when (not undo-transaction) (st/emit! dwc/start-undo-transaction)) - (when (and (> new-width 0) (> new-height 0)) - (cond - (and overflow-text (not= :fixed grow-type)) - (st/emit! (dwt/update-overflow-text id false)) - - (and (= :fixed grow-type) (not overflow-text) (> new-height shape-height)) - (st/emit! (dwt/update-overflow-text id true)) - - (and (= :fixed grow-type) overflow-text (<= new-height shape-height)) - (st/emit! (dwt/update-overflow-text id false)) - - (and (or (not= shape-width new-width) - (not= shape-height new-height)) - (= grow-type :auto-width)) - (when (and (pos? shape-width) - (pos? shape-height)) - (st/emit! (dw/update-dimensions [id] :width new-width) - (dw/update-dimensions [id] :height new-height))) - - (and (not= shape-height new-height) (= grow-type :auto-height)) - (when (pos? shape-height) - (st/emit! (dw/update-dimensions [id] :height new-height))))) - (when (not undo-transaction) (st/emit! dwc/discard-undo-transaction)))) - -(defn resize-observer [{:keys [id selrect grow-type overflow-text] :as shape} root query] - (mf/use-effect - (mf/deps id selrect grow-type overflow-text root query) - (fn [] - (let [on-change (fn [entries] - (when (seq entries) - ;; RequestAnimationFrame so the "loop limit error" error is not thrown - ;; https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded - (timers/raf - #(let [width (obj/get-in entries [0 "contentRect" "width"]) - height (obj/get-in entries [0 "contentRect" "height"])] - (handle-shape-resize shape (mth/ceil width) (mth/ceil height)))))) - observer (js/ResizeObserver. on-change) - node (when root (dom/query root query))] - (when node (.observe observer node)) - #(.disconnect observer))))) - (mf/defc text-wrapper {::mf/wrap-props false} [props] @@ -109,21 +63,50 @@ handle-pointer-leave (we/use-pointer-leave shape) handle-double-click (use-double-click shape selected?) - text-ref (mf/use-ref nil) - text-node (mf/ref-val text-ref)] + paragraph-ref (mf/use-var nil) - (resize-observer shape text-node ".paragraph-set") + handle-resize-text + (mf/use-callback + (mf/deps id) + (fn [entries] + (when (seq entries) + ;; RequestAnimationFrame so the "loop limit error" error is not thrown + ;; https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded + (timers/raf + #(let [width (obj/get-in entries [0 "contentRect" "width"]) + height (obj/get-in entries [0 "contentRect" "height"])] + (st/emit! (dwt/resize-text id (mth/ceil width) (mth/ceil height)))))))) + + text-ref-cb + (mf/use-callback + (mf/deps handle-resize-text) + (fn [node] + (when node + (let [obs-ref (atom nil)] + (timers/schedule + (fn [] + (when-let [ps-node (dom/query node ".paragraph-set")] + (reset! paragraph-ref ps-node))))))))] + + (mf/use-effect + (mf/deps @paragraph-ref handle-resize-text) + (fn [] + (when-let [paragraph-node @paragraph-ref] + (let [observer (js/ResizeObserver. handle-resize-text)] + (.observe observer paragraph-node) + #(.disconnect observer))) + )) [:> shape-container {:shape shape} ;; We keep hidden the shape when we're editing so it keeps track of the size ;; and updates the selrect acordingly [:g.text-shape {:opacity (when edition? 0)} - [:& text/text-shape {:key "text-shape" - :ref text-ref + [:& text/text-shape {:key (str "text-shape" (:id shape)) + :ref text-ref-cb :shape shape :selected? selected?}]] (when edition? - [:& editor/text-shape-edit {:key "editor" + [:& editor/text-shape-edit {:key (str "editor" (:id shape)) :shape shape}]) (when-not edition? diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 0e55d242c..f54187a68 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -204,11 +204,11 @@ (let [lkey1 (events/listen (dom/get-root) EventType.CLICK on-click-outside) lkey2 (events/listen (dom/get-root) EventType.KEYUP on-key-up)] (st/emit! (dwt/assign-editor id editor) - dwc/start-undo-transaction) + (dwc/start-undo-transaction)) #(do (st/emit! (dwt/assign-editor id nil) - dwc/commit-undo-transaction) + (dwc/commit-undo-transaction)) (events/unlistenByKey lkey1) (events/unlistenByKey lkey2)))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs index a88062f38..41fe6bd19 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/component.cljs @@ -49,10 +49,10 @@ do-detach-component #(st/emit! (dwl/detach-component id)) do-reset-component #(st/emit! (dwl/reset-component id)) do-update-component #(do - (st/emit! dwc/start-undo-transaction) + (st/emit! (dwc/start-undo-transaction)) (st/emit! (dwl/update-component id)) (st/emit! (dwl/sync-file nil)) - (st/emit! dwc/commit-undo-transaction)) + (st/emit! (dwc/commit-undo-transaction))) do-show-component #(st/emit! (dw/go-to-layout :assets)) do-navigate-component-file #(st/emit! (dwl/nav-to-component-file (:component-file values)))] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs index d469acee2..016dc9652 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs @@ -81,13 +81,13 @@ (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/start-undo-transaction))) + (st/emit! (dwc/start-undo-transaction)))) on-close-picker (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/commit-undo-transaction)))] + (st/emit! (dwc/commit-undo-transaction))))] (if show? [:div.element-set diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs index 31381c3a0..e0a0289ef 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/page.cljs @@ -34,12 +34,12 @@ on-open (mf/use-callback (mf/deps page-id) - #(st/emit! dwc/start-undo-transaction)) + #(st/emit! (dwc/start-undo-transaction))) on-close (mf/use-callback (mf/deps page-id) - #(st/emit! dwc/commit-undo-transaction))] + #(st/emit! (dwc/commit-undo-transaction)))] [:div.element-set [:div.element-set-title (t locale "workspace.options.canvas-background")] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs index 0db47133a..6bf6ae899 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs @@ -172,8 +172,8 @@ (:color value)) :disable-gradient true :on-change (update-color index) - :on-open #(st/emit! dwc/start-undo-transaction) - :on-close #(st/emit! dwc/commit-undo-transaction)}]]]])) + :on-open #(st/emit! (dwc/start-undo-transaction)) + :on-close #(st/emit! (dwc/commit-undo-transaction))}]]]])) (mf/defc shadow-menu [{:keys [ids values] :as props}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs index 6419805d2..12903f28f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/stroke.cljs @@ -116,13 +116,13 @@ (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/start-undo-transaction))) + (st/emit! (dwc/start-undo-transaction)))) on-close-picker (mf/use-callback (mf/deps ids) (fn [value opacity id file-id] - (st/emit! dwc/commit-undo-transaction)))] + (st/emit! (dwc/commit-undo-transaction))))] (if show-options [:div.element-set