From f2d1a4190ae1012b3c6ec8e8ad445e92c04de6be Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 21 Mar 2022 22:58:37 +0100 Subject: [PATCH] :sparkles: Don't stop SVG import when an image cannot be imported --- CHANGES.md | 1 + .../app/main/data/workspace/svg_upload.cljs | 97 ++++++++++--------- frontend/src/app/main/ui/shapes/attrs.cljs | 10 +- .../src/app/main/ui/shapes/custom_stroke.cljs | 27 +++++- 4 files changed, 88 insertions(+), 47 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 36c6349e1..53b0bdb97 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,7 @@ - Add the ability to specify the attr for retrieve the email on OIDC integration [#1460](https://github.com/penpot/penpot/issues/1460) - Allow registration with invitation token when registration is disabled - Add the ability to disable standard, password login [Taiga #2999](https://tree.taiga.io/project/penpot/us/2999) +- Don't stop SVG import when an image cannot be imported [#1531](https://github.com/penpot/penpot/issues/1531) ### :bug: Bugs fixed diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index bd6a8d715..6998bce8e 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -70,30 +70,32 @@ :else (str tag)))) (defn setup-fill [shape] - (cond-> shape - ;; Color present as attribute - (uc/color? (str/trim (get-in shape [:svg-attrs :fill]))) - (-> (update :svg-attrs dissoc :fill) - (assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :fill]) - (str/trim) - (uc/parse-color)))) + (if (some? (:fills shape)) + shape + (cond-> shape + ;; Color present as attribute + (uc/color? (str/trim (get-in shape [:svg-attrs :fill]))) + (-> (update :svg-attrs dissoc :fill) + (assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :fill]) + (str/trim) + (uc/parse-color)))) - ;; Color present as style - (uc/color? (str/trim (get-in shape [:svg-attrs :style :fill]))) - (-> (update-in [:svg-attrs :style] dissoc :fill) - (assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :style :fill]) - (str/trim) - (uc/parse-color)))) + ;; Color present as style + (uc/color? (str/trim (get-in shape [:svg-attrs :style :fill]))) + (-> (update-in [:svg-attrs :style] dissoc :fill) + (assoc-in [:fills 0 :fill-color] (-> (get-in shape [:svg-attrs :style :fill]) + (str/trim) + (uc/parse-color)))) - (get-in shape [:svg-attrs :fill-opacity]) - (-> (update :svg-attrs dissoc :fill-opacity) - (assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :fill-opacity]) - (d/parse-double)))) + (get-in shape [:svg-attrs :fill-opacity]) + (-> (update :svg-attrs dissoc :fill-opacity) + (assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :fill-opacity]) + (d/parse-double)))) - (get-in shape [:svg-attrs :style :fill-opacity]) - (-> (update-in [:svg-attrs :style] dissoc :fill-opacity) - (assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :style :fill-opacity]) - (d/parse-double)))))) + (get-in shape [:svg-attrs :style :fill-opacity]) + (-> (update-in [:svg-attrs :style] dissoc :fill-opacity) + (assoc-in [:fills 0 :fill-opacity] (-> (get-in shape [:svg-attrs :style :fill-opacity]) + (d/parse-double))))))) (defn setup-stroke [shape] (let [stroke-linecap (-> (or (get-in shape [:svg-attrs :stroke-linecap]) @@ -337,18 +339,20 @@ (update :y - (:y origin))) rect-metadata (calculate-rect-metadata rect-data transform)] - (-> {:id (uuid/next) - :type :image - :name name - :frame-id frame-id - :metadata {:width (:width image-data) - :height (:height image-data) - :mtype (:mtype image-data) - :id (:id image-data)}} - (merge rect-metadata) - (assoc :svg-viewbox (select-keys rect [:x :y :width :height])) - (assoc :svg-attrs (dissoc attrs :x :y :width :height :xlink:href))))) + (when (some? image-data) + (-> {:id (uuid/next) + :type :image + :name name + :frame-id frame-id + :metadata {:width (:width image-data) + :height (:height image-data) + :mtype (:mtype image-data) + :id (:id image-data)}} + + (merge rect-metadata) + (assoc :svg-viewbox (select-keys rect [:x :y :width :height])) + (assoc :svg-attrs (dissoc attrs :x :y :width :height :xlink:href)))))) (defn parse-svg-element [frame-id svg-data element-data unames] (let [{:keys [tag attrs]} element-data @@ -389,21 +393,21 @@ :polygon (create-path-shape name frame-id svg-data (-> element-data usvg/polygon->path)) :line (create-path-shape name frame-id svg-data (-> element-data usvg/line->path)) :image (create-image-shape name frame-id svg-data element-data) - #_other (create-raw-svg name frame-id svg-data element-data))) + #_other (create-raw-svg name frame-id svg-data element-data)))] + (when (some? shape) + (let [shape (assoc shape :fills []) + shape (assoc shape :strokes []) - shape (assoc shape :fills []) - shape (assoc shape :strokes []) + shape (when (some? shape) + (-> shape + (assoc :svg-defs (select-keys (:defs svg-data) references)) + (setup-fill) + (setup-stroke))) - shape (when (some? shape) - (-> shape - (assoc :svg-defs (select-keys (:defs svg-data) references)) - (setup-fill) - (setup-stroke))) - - children (cond->> (:content element-data) - (or (= tag :g) (= tag :svg)) - (mapv #(usvg/inherit-attributes attrs %)))] - [shape children])))) + children (cond->> (:content element-data) + (or (= tag :g) (= tag :svg)) + (mapv #(usvg/inherit-attributes attrs %)))] + [shape children])))))) (defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames changes] [index data]] (let [[shape children] (parse-svg-element frame-id svg-data data unames)] @@ -448,6 +452,9 @@ (->> (rp/mutation! (if (contains? uri-data :content) :upload-file-media-object :create-file-media-object-from-url) uri-data) + ;; When the image uploaded fail we skip the shape + ;; returning `nil` will afterward not create the shape. + (rx/catch #(rx/of nil)) (rx/map #(vector (:url uri-data) %))))) (rx/reduce (fn [acc [url image]] (assoc acc url image)) {}) (rx/map #(create-svg-shapes (assoc svg-data :image-data %) position)))))) diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs index dd76b8a6a..2a0f3a129 100644 --- a/frontend/src/app/main/ui/shapes/attrs.cljs +++ b/frontend/src/app/main/ui/shapes/attrs.cljs @@ -180,6 +180,11 @@ (obj/set! "fill" (obj/get svg-styles "fill")) (obj/set! "fillOpacity" (obj/get svg-styles "fillOpacity"))) + (obj/contains? svg-attrs "fill") + (-> styles + (obj/set! "fill" (obj/get svg-attrs "fill")) + (obj/set! "fillOpacity" (obj/get svg-attrs "fillOpacity"))) + ;; If contains svg-attrs the origin is svg. If it's not svg origin ;; we setup the default fill as transparent (instead of black) (and (contains? shape :svg-attrs) @@ -187,8 +192,11 @@ (empty? (:fills shape))) styles + (d/not-empty? (:fills shape)) + (add-fill styles (d/without-nils (get-in shape [:fills 0])) render-id 0) + :else - (add-fill styles (d/without-nils (get-in shape [:fills 0])) render-id 0))] + styles)] (-> props (obj/merge! svg-attrs) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index fa99695b8..c9f8d1f70 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -328,7 +328,13 @@ props (cond-> props (d/not-empty? (:shadow shape)) - (obj/set! "filter" (dm/fmt "url(#filter_%)" render-id)))] + (obj/set! "filter" (dm/fmt "url(#filter_%)" render-id))) + + svg-defs (:svg-defs shape {}) + svg-attrs (:svg-attrs shape {}) + + [svg-attrs svg-styles] + (attrs/extract-svg-attrs render-id svg-defs svg-attrs)] (cond url-fill? @@ -339,6 +345,25 @@ (obj/without ["fill" "fillOpacity"])))] (obj/set! props "fill" (dm/fmt "url(#fill-0-%)" render-id))) + (obj/contains? svg-styles "fill") + (let [style + (-> (obj/get props "style") + (obj/clone) + (obj/set! "fill" (obj/get svg-styles "fill")) + (obj/set! "fillOpacity" (obj/get svg-styles "fillOpacity")))] + (-> props + (obj/set! "style" style))) + + (obj/contains? svg-attrs "fill") + (let [style + (-> (obj/get props "style") + (obj/clone) + (obj/set! "fill" (obj/get svg-attrs "fill")) + (obj/set! "fillOpacity" (obj/get svg-attrs "fillOpacity")))] + (-> props + (obj/set! "style" style))) + + (d/not-empty? (:fills shape)) (let [fill-props (attrs/extract-fill-attrs (get-in shape [:fills 0]) render-id 0)