diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs index 2a0f3a129..aeafe56b1 100644 --- a/frontend/src/app/main/ui/shapes/attrs.cljs +++ b/frontend/src/app/main/ui/shapes/attrs.cljs @@ -175,12 +175,12 @@ (obj/set! styles "fill" (str "url(#fill-0-" render-id ")")) ;; imported svgs can have fill and fill-opacity attributes - (obj/contains? svg-styles "fill") + (and (some? svg-styles) (obj/contains? svg-styles "fill")) (-> styles (obj/set! "fill" (obj/get svg-styles "fill")) (obj/set! "fillOpacity" (obj/get svg-styles "fillOpacity"))) - (obj/contains? svg-attrs "fill") + (and (some? svg-attrs) (obj/contains? svg-attrs "fill")) (-> styles (obj/set! "fill" (obj/get svg-attrs "fill")) (obj/set! "fillOpacity" (obj/get svg-attrs "fillOpacity"))) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index 9d08c4cab..28522282a 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -350,7 +350,7 @@ (obj/without ["fill" "fillOpacity"])))] (obj/set! props "fill" (dm/fmt "url(#fill-0-%)" render-id))) - (obj/contains? svg-styles "fill") + (and (some? svg-styles) (obj/contains? svg-styles "fill")) (let [style (-> (obj/get props "style") (obj/clone) @@ -359,7 +359,7 @@ (-> props (obj/set! "style" style))) - (obj/contains? svg-attrs "fill") + (and (some? svg-attrs) (obj/contains? svg-attrs "fill")) (let [style (-> (obj/get props "style") (obj/clone) diff --git a/frontend/src/app/main/ui/shapes/svg_defs.cljs b/frontend/src/app/main/ui/shapes/svg_defs.cljs index 0b875bcfb..a3662e49c 100644 --- a/frontend/src/app/main/ui/shapes/svg_defs.cljs +++ b/frontend/src/app/main/ui/shapes/svg_defs.cljs @@ -43,24 +43,24 @@ transform-mask? (and (= :mask tag) (= "userSpaceOnUse" (get attrs :maskUnits "objectBoundingBox"))) - attrs (-> attrs - (usvg/update-attr-ids prefix-id) - (usvg/clean-attrs) - ;; This clasname will be used to change the transform on the viewport - ;; only necessary for groups because shapes have their own transform - (cond-> (and (or transform-gradient? - transform-pattern? - transform-clippath? - transform-filter? - transform-mask?) - (= :group type)) - (update :className #(if % (dm/str % " svg-def") "svg-def"))) - (cond-> - transform-gradient? (add-matrix :gradientTransform transform) - transform-pattern? (add-matrix :patternTransform transform) - transform-clippath? (add-matrix :transform transform) - (or transform-filter? - transform-mask?) (merge attrs bounds))) + attrs + (-> attrs + (usvg/update-attr-ids prefix-id) + (usvg/clean-attrs) + ;; This clasname will be used to change the transform on the viewport + ;; only necessary for groups because shapes have their own transform + (cond-> (and (or transform-gradient? + transform-pattern? + transform-clippath? + transform-filter? + transform-mask?) + (= :group type)) + (update :className #(if % (dm/str % " svg-def") "svg-def"))) + (cond-> + transform-gradient? (add-matrix :gradientTransform transform) + transform-pattern? (add-matrix :patternTransform transform) + transform-clippath? (add-matrix :transform transform) + (or transform-filter? transform-mask?) (merge bounds))) [wrapper wrapper-props] (if (= tag :mask) ["g" #js {:className "svg-mask-wrapper" diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index e8204b59e..3bb8ad2c9 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -9,9 +9,12 @@ [app.common.data :as d] [app.common.exceptions :as ex] [app.common.geom.point :as gpt] + [app.common.pages.helpers :as cph] + [app.common.text :as txt] [app.main.data.comments :as dcm] [app.main.data.viewer :as dv] [app.main.data.viewer.shortcuts :as sc] + [app.main.fonts :as fonts] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.hooks :as hooks] @@ -75,6 +78,12 @@ (fn [] (get-in data [:pages page-id]))) + text-shapes + (hooks/use-equal-memo + (->> (:objects page) + (vals) + (filter cph/text-shape?))) + zoom (:zoom local) frames (:frames page) frame (get frames index) @@ -219,6 +228,13 @@ nil)))) + (mf/use-effect + (mf/deps text-shapes) + (fn [] + (let [text-nodes (->> text-shapes (mapcat #(txt/node-seq txt/is-text-node? (:content %)))) + fonts (into #{} (keep :font-id) text-nodes)] + (run! fonts/ensure-loaded! fonts)))) + [:div#viewer-layout {:class (dom/classnames :force-visible (:show-thumbnails local) :viewer-layout (not= section :handoff) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 2eba7eeca..900dd304b 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -88,6 +88,7 @@ ;; REFS viewport-ref (mf/use-ref nil) + overlays-ref (mf/use-ref nil) ;; VARS disable-paste (mf/use-var false) @@ -169,7 +170,7 @@ disabled-guides? (or drawing-tool transform)] - (hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?) + (hooks/setup-dom-events viewport-ref overlays-ref zoom disable-paste in-viewport?) (hooks/setup-viewport-size viewport-ref) (hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing?) (hooks/setup-keyboard alt? mod? space?) @@ -179,7 +180,7 @@ (hooks/setup-active-frames base-objects vbox hover active-frames) [:div.viewport - [:div.viewport-overlays + [:div.viewport-overlays {:ref overlays-ref} [:& wtr/frame-renderer {:objects base-objects :background background}] diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 0ad3de7a0..111a0fa91 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -363,21 +363,23 @@ pt (utils/translate-point-to-viewport viewport zoom raw-pt)] (rx/push! move-stream pt))))) -(defn on-mouse-wheel [viewport-ref zoom] +(defn on-mouse-wheel [viewport-ref overlays-ref zoom] (mf/use-callback (mf/deps zoom) (fn [event] (let [viewport (mf/ref-val viewport-ref) + overlays (mf/ref-val overlays-ref) event (.getBrowserEvent ^js event) - target (dom/get-target event)] - (when (.contains ^js viewport target) + target (dom/get-target event) + mod? (kbd/mod? event)] + + (when (or (dom/is-child? viewport target) + (dom/is-child? overlays target)) (dom/prevent-default event) (dom/stop-propagation event) (let [pt (->> (dom/get-client-position event) (utils/translate-point-to-viewport viewport zoom)) - mod? (kbd/mod? event) - delta-mode (.-deltaMode ^js event) unit (cond diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 11e4bc006..d2e70e878 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -27,11 +27,11 @@ [rumext.alpha :as mf]) (:import goog.events.EventType)) -(defn setup-dom-events [viewport-ref zoom disable-paste in-viewport?] +(defn setup-dom-events [viewport-ref overlays-ref zoom disable-paste in-viewport?] (let [on-key-down (actions/on-key-down) on-key-up (actions/on-key-up) on-mouse-move (actions/on-mouse-move viewport-ref zoom) - on-mouse-wheel (actions/on-mouse-wheel viewport-ref zoom) + on-mouse-wheel (actions/on-mouse-wheel viewport-ref overlays-ref zoom) on-paste (actions/on-paste disable-paste in-viewport?)] (mf/use-layout-effect (mf/deps on-key-down on-key-up on-mouse-move on-mouse-wheel on-paste) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 0aba75592..64ba990dc 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -530,3 +530,8 @@ (when onfinish (set! (.-onfinish animation) onfinish))))) +(defn is-child? + [^js node ^js candidate] + (and (some? node) + (some? candidate) + (.contains node candidate)))