diff --git a/backend/src/app/rpc/mutations/files.clj b/backend/src/app/rpc/mutations/files.clj index 1093e9dc3..822c39d3d 100644 --- a/backend/src/app/rpc/mutations/files.clj +++ b/backend/src/app/rpc/mutations/files.clj @@ -274,8 +274,7 @@ [{:keys [pool] :as cfg} {:keys [id profile-id] :as params}] (db/with-atomic [conn pool] (db/xact-lock! conn id) - (let [{:keys [id] :as file} (db/get-by-id conn :file id {:for-key-share true - :uncheked true})] + (let [{:keys [id] :as file} (db/get-by-id conn :file id {:for-key-share true})] (files/check-edition-permissions! conn profile-id id) (update-file (assoc cfg :conn conn) (assoc params :file file))))) @@ -399,10 +398,10 @@ (proj/check-edition-permissions! conn profile-id project-id) (create-file conn (assoc params :deleted-at (dt/in-future {:days 1}))))) -(s/def ::make-permanent +(s/def ::persist-temp-file (s/keys :req-un [::id ::profile-id])) -(sv/defmethod ::make-permanent +(sv/defmethod ::persist-temp-file [{:keys [pool] :as cfg} {:keys [id profile-id] :as params}] (db/with-atomic [conn pool] (files/check-edition-permissions! conn profile-id id) diff --git a/common/src/app/common/data.cljc b/common/src/app/common/data.cljc index e034f00e8..acc7bc063 100644 --- a/common/src/app/common/data.cljc +++ b/common/src/app/common/data.cljc @@ -503,3 +503,51 @@ (->> keys (reduce diff-attr {})))) + +(defn- extract-numeric-suffix + [basename] + (if-let [[match p1 p2] (re-find #"(.*)-([0-9]+)$" basename)] + [p1 (+ 1 (parse-integer p2))] + [basename 1])) + +(defn unique-name + "A unique name generator" + ([basename used] + (unique-name basename used false)) + + ([basename used prefix-first?] + (assert (string? basename)) + (assert (set? used)) + + (let [[prefix initial] (extract-numeric-suffix basename)] + (if (and (not prefix-first?) + (not (contains? used basename))) + basename + (loop [counter initial] + (let [candidate (if (and (= 1 counter) prefix-first?) + (str prefix) + (str prefix "-" counter))] + (if (contains? used candidate) + (recur (inc counter)) + candidate))))))) + +(defn deep-mapm + "Applies a map function to an associative map and recurses over its children + when it's a vector or a map" + [mfn m] + (let [do-map + (fn [[k v]] + (cond + (or (vector? v) (map? v)) + [k (deep-mapm mfn v)] + :else + (mfn [k v])))] + (cond + (map? m) + (into {} (map do-map) m) + + (vector? m) + (into [] (map (partial deep-mapm mfn)) m) + + :else + m))) diff --git a/common/src/app/common/file_builder.cljc b/common/src/app/common/file_builder.cljc index b83653b11..64ae5dff4 100644 --- a/common/src/app/common/file_builder.cljc +++ b/common/src/app/common/file_builder.cljc @@ -13,7 +13,8 @@ [app.common.pages.init :as init] [app.common.pages.spec :as spec] [app.common.spec :as us] - [app.common.uuid :as uuid])) + [app.common.uuid :as uuid] + [cuerdas.core :as str])) (def root-frame uuid/zero) @@ -51,6 +52,27 @@ :parent-id parent-id :obj obj})))) +(defn generate-name + [type data] + (if (= type :svg-raw) + (let [tag (get-in data [:content :tag])] + (str "svg-" (cond (string? tag) tag + (keyword? tag) (d/name tag) + (nil? tag) "node" + :else (str tag)))) + (str/capital (d/name type)))) + +(defn check-name + "Given a tag returns its layer name" + [data file type] + + (cond-> data + (nil? (:name data)) + (assoc :name (generate-name type data)) + + :always + (update :name d/unique-name (:unames file)))) + ;; PUBLIC API (defn create-file @@ -82,14 +104,31 @@ (assoc :current-frame-id root-frame) ;; Current parent stack we'll be nesting - (assoc :parent-stack [root-frame])))) + (assoc :parent-stack [root-frame]) + + ;; Last object id added + (assoc :last-id nil) + + ;; Current used names + (assoc :unames #{})))) + +(defn close-page [file] + (-> file + (dissoc :current-page-id) + (dissoc :parent-stack) + (dissoc :last-id) + (dissoc :unames))) (defn add-artboard [file data] (let [obj (-> (init/make-minimal-shape :frame) - (merge data))] + (merge data) + (check-name file :frame) + (d/without-nils))] (-> file (commit-shape obj) (assoc :current-frame-id (:id obj)) + (assoc :last-id (:id obj)) + (update :unames conj (:name obj)) (update :parent-stack conj (:id obj))))) (defn close-artboard [file] @@ -102,9 +141,13 @@ selrect init/empty-selrect name (:name data) obj (-> (init/make-minimal-group frame-id selrect name) - (merge data))] + (merge data) + (check-name file :group) + (d/without-nils))] (-> file (commit-shape obj) + (assoc :last-id (:id obj)) + (update :unames conj (:name obj)) (update :parent-stack conj (:id obj))))) (defn close-group [file] @@ -115,13 +158,14 @@ points (gsh/rect->points selrect)] (-> file - (commit-change - {:type :mod-obj - :page-id (:current-page-id file) - :id group-id - :operations - [{:type :set :attr :selrect :val selrect} - {:type :set :attr :points :val points}]}) + (cond-> (not (empty? shapes)) + (commit-change + {:type :mod-obj + :page-id (:current-page-id file) + :id group-id + :operations + [{:type :set :attr :selrect :val selrect} + {:type :set :attr :points :val points}]})) (update :parent-stack pop)))) (defn create-shape [file type data] @@ -130,10 +174,14 @@ (lookup-shape file frame-id)) obj (-> (init/make-minimal-shape type) (merge data) - (d/without-nils) - (cond-> frame - (gsh/translate-from-frame frame)))] - (commit-shape file obj))) + (check-name file :type) + (d/without-nils)) + obj (cond-> obj + frame (gsh/translate-from-frame frame))] + (-> file + (commit-shape obj) + (assoc :last-id (:id obj)) + (update :unames conj (:name obj))))) (defn create-rect [file data] (create-shape file :rect data)) @@ -150,10 +198,27 @@ (defn create-image [file data] (create-shape file :image data)) -(defn close-page [file] +(declare close-svg-raw) + +(defn create-svg-raw [file data] + (let [file (as-> file $ + (create-shape $ :svg-raw data) + (update $ :parent-stack conj (:last-id $))) + + create-child + (fn [file child] + (-> file + (create-svg-raw (assoc data :content child)) + (close-svg-raw)))] + + ;; First :content is the the shape attribute, the other content is the + ;; XML children + (reduce create-child file (get-in data [:content :content])))) + +(defn close-svg-raw [file] (-> file - (dissoc :current-page-id) - (dissoc :parent-stack))) + (update :parent-stack pop))) + (defn generate-changes [file] diff --git a/frontend/src/app/main/exports.cljs b/frontend/src/app/main/exports.cljs index 760f2b5d4..2ee9d6db7 100644 --- a/frontend/src/app/main/exports.cljs +++ b/frontend/src/app/main/exports.cljs @@ -85,9 +85,15 @@ (mf/fnc svg-raw-wrapper [{:keys [shape frame] :as props}] (let [childs (mapv #(get objects %) (:shapes shape))] - [:& svg-raw-shape {:frame frame - :shape shape - :childs childs}])))) + (if (and (contains? shape :svg-attrs) (map? (:content shape))) + [:> shape-container {:shape shape} + [:& svg-raw-shape {:frame frame + :shape shape + :childs childs}]] + + [:& svg-raw-shape {:frame frame + :shape shape + :childs childs}]))))) (defn shape-wrapper-factory [objects] diff --git a/frontend/src/app/main/ui/shapes/export.cljs b/frontend/src/app/main/ui/shapes/export.cljs index 924ddc7eb..196061efb 100644 --- a/frontend/src/app/main/ui/shapes/export.cljs +++ b/frontend/src/app/main/ui/shapes/export.cljs @@ -10,8 +10,25 @@ [app.common.geom.matrix :as gmt] [app.util.json :as json] [app.util.object :as obj] + [app.util.svg :as usvg] + [cuerdas.core :as str] [rumext.alpha :as mf])) +(mf/defc render-xml + [{{:keys [tag attrs content] :as node} :xml}] + + (cond + (map? node) + [:> (d/name tag) (clj->js (usvg/clean-attrs attrs)) + (for [child content] + [:& render-xml {:xml child}])] + + (string? node) + node + + :else + nil)) + (defn add-data "Adds as metadata properties that we cannot deduce from the exported SVG" [props shape] @@ -22,7 +39,7 @@ (obj/set! ns-attr val)))) frame? (= :frame (:type shape)) group? (= :group (:type shape)) - rect? (= :text (:type shape)) + rect? (= :rect (:type shape)) text? (= :text (:type shape)) mask? (and group? (:masked-group? shape))] (-> props @@ -74,5 +91,33 @@ (for [{:keys [scale suffix type]} (:exports shape)] [:> "penpot:export" #js {:penpot:type (d/name type) :penpot:suffix suffix - :penpot:scale (str scale)}])])) + :penpot:scale (str scale)}]) + + (when (contains? shape :svg-attrs) + (let [svg-transform (get shape :svg-transform) + svg-attrs (->> shape :svg-attrs keys (mapv d/name) (str/join ",") ) + svg-defs (->> shape :svg-defs keys (mapv d/name) (str/join ","))] + [:> "penpot:svg-import" #js {:penpot:svg-attrs (when-not (empty? svg-attrs) svg-attrs) + :penpot:svg-defs (when-not (empty? svg-defs) svg-defs) + :penpot:svg-transform (when svg-transform (str svg-transform)) + :penpot:svg-viewbox-x (get-in shape [:svg-viewbox :x]) + :penpot:svg-viewbox-y (get-in shape [:svg-viewbox :y]) + :penpot:svg-viewbox-width (get-in shape [:svg-viewbox :width]) + :penpot:svg-viewbox-height (get-in shape [:svg-viewbox :height])} + (for [[def-id def-xml] (:svg-defs shape)] + [:> "penpot:svg-def" #js {:def-id def-id} + [:& render-xml {:xml def-xml}]])])) + + (when (= (:type shape) :svg-raw) + (let [props (-> (obj/new) + (obj/set! "penpot:x" (:x shape)) + (obj/set! "penpot:y" (:y shape)) + (obj/set! "penpot:width" (:width shape)) + (obj/set! "penpot:height" (:height shape)) + (obj/set! "penpot:tag" (-> (get-in shape [:content :tag]) d/name)) + (obj/merge! (-> (get-in shape [:content :attrs]) + (clj->js))))] + [:> "penpot:svg-content" props + (for [leaf (->> shape :content :content (filter string?))] + [:> "penpot:svg-child" {} leaf])]))])) diff --git a/frontend/src/app/main/ui/shapes/gradients.cljs b/frontend/src/app/main/ui/shapes/gradients.cljs index a6e091cbc..4cee1d330 100644 --- a/frontend/src/app/main/ui/shapes/gradients.cljs +++ b/frontend/src/app/main/ui/shapes/gradients.cljs @@ -18,12 +18,13 @@ (mf/defc linear-gradient [{:keys [id gradient shape]}] (let [{:keys [x y width height]} (:selrect shape) transform (when (= :path (:type shape)) (gsh/transform-matrix shape nil (gpt/point 0.5 0.5)))] - [:linearGradient {:id id - :x1 (:start-x gradient) - :y1 (:start-y gradient) - :x2 (:end-x gradient) - :y2 (:end-y gradient) - :gradientTransform transform} + [:> :linearGradient #js {:id id + :x1 (:start-x gradient) + :y1 (:start-y gradient) + :x2 (:end-x gradient) + :y2 (:end-y gradient) + :gradientTransform transform + :penpot:gradient "true"} (for [{:keys [offset color opacity]} (:stops gradient)] [:stop {:key (str id "-stop-" offset) :offset (or offset 0) @@ -32,6 +33,7 @@ (defn add-metadata [props gradient] (-> props + (obj/set! "penpot:gradient" "true") (obj/set! "penpot:start-x" (:start-x gradient)) (obj/set! "penpot:start-x" (:start-x gradient)) (obj/set! "penpot:start-y" (:start-y gradient)) diff --git a/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs b/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs index a07307048..d2a34d316 100644 --- a/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs @@ -35,23 +35,13 @@ def-ctx? (mf/use-ctx muc/def-ctx)] - (cond - (and (svg-raw/graphic-element? tag) (not def-ctx?)) - [:> shape-container { :shape shape } - [:& svg-raw-shape - {:frame frame - :shape shape - :childs childs}]] - - ;; We cannot wrap inside groups the shapes that go inside the defs tag - ;; we use the context so we know when we should not render the container - (= tag :defs) - [:& (mf/provider muc/def-ctx) {:value true} + (if (or (= (get-in shape [:content :tag]) :svg) + (and (contains? shape :svg-attrs) (map? (:content shape)))) + [:> shape-container {:shape shape} [:& svg-raw-shape {:frame frame :shape shape :childs childs}]] - :else [:& svg-raw-shape {:frame frame :shape shape :childs childs}]))))) diff --git a/frontend/src/app/util/import/parser.cljc b/frontend/src/app/util/import/parser.cljc index fed82c64b..e207ecdeb 100644 --- a/frontend/src/app/util/import/parser.cljc +++ b/frontend/src/app/util/import/parser.cljc @@ -29,8 +29,13 @@ (and (vector? node) (= ::close (first node)))) -(defn get-data [node] - (->> node :content (d/seek #(= :penpot:shape (:tag %))))) +(defn get-data + ([node] + (->> node :content (d/seek #(= :penpot:shape (:tag %))))) + ([node tag] + (->> (get-data node) + :content + (d/seek #(= tag (:tag %)))))) (defn get-type [node] @@ -65,9 +70,6 @@ [content] (->> content (tree-seq branch? get-children))) -(defn get-transform - [type node]) - (defn parse-style "Transform style list into a map" [style-str] @@ -97,13 +99,19 @@ [type node] (let [node-attrs (add-attrs {} (:attrs node))] - (if (search-data-node? type) + (cond + (search-data-node? type) (let [data-tags #{:ellipse :rect :path :text :foreignObject :image}] (->> node (node-seq) (filter #(contains? data-tags (:tag %))) (map #(:attrs %)) (reduce add-attrs node-attrs))) + + (= type :svg-raw) + (->> node :content last) + + :else node-attrs))) (def has-position? #{:frame :rect :image :text}) @@ -153,26 +161,42 @@ (defn parse-gradient [node ref-url] - (let [[_ url] (re-matches url-regex ref-url) + (let [[_ url] (re-find url-regex ref-url) gradient-node (->> node (node-seq) (seek-node url)) stops (parse-stops gradient-node)] - (cond-> {:stops stops} - (= :linearGradient (:tag gradient-node)) - (assoc :type :linear - :start-x (-> gradient-node :attrs :x1 d/parse-double) - :start-y (-> gradient-node :attrs :y1 d/parse-double) - :end-x (-> gradient-node :attrs :x2 d/parse-double) - :end-y (-> gradient-node :attrs :y2 d/parse-double) - :width 1) + (when (contains? (:attrs gradient-node) :penpot:gradient) + (cond-> {:stops stops} + (= :linearGradient (:tag gradient-node)) + (assoc :type :linear + :start-x (-> gradient-node :attrs :x1 d/parse-double) + :start-y (-> gradient-node :attrs :y1 d/parse-double) + :end-x (-> gradient-node :attrs :x2 d/parse-double) + :end-y (-> gradient-node :attrs :y2 d/parse-double) + :width 1) - (= :radialGradient (:tag gradient-node)) - (assoc :type :radial - :start-x (get-meta gradient-node :start-x d/parse-double) - :start-y (get-meta gradient-node :start-y d/parse-double) - :end-x (get-meta gradient-node :end-x d/parse-double) - :end-y (get-meta gradient-node :end-y d/parse-double) - :width (get-meta gradient-node :width d/parse-double))))) + (= :radialGradient (:tag gradient-node)) + (assoc :type :radial + :start-x (get-meta gradient-node :start-x d/parse-double) + :start-y (get-meta gradient-node :start-y d/parse-double) + :end-x (get-meta gradient-node :end-x d/parse-double) + :end-y (get-meta gradient-node :end-y d/parse-double) + :width (get-meta gradient-node :width d/parse-double)))))) + +(defn add-svg-position [props node] + (let [svg-content (get-data node :penpot:svg-content)] + (cond-> props + (contains? (:attrs svg-content) :penpot:x) + (assoc :x (-> svg-content :attrs :penpot:x d/parse-double)) + + (contains? (:attrs svg-content) :penpot:y) + (assoc :y (-> svg-content :attrs :penpot:y d/parse-double)) + + (contains? (:attrs svg-content) :penpot:width) + (assoc :width (-> svg-content :attrs :penpot:width d/parse-double)) + + (contains? (:attrs svg-content) :penpot:height) + (assoc :height (-> svg-content :attrs :penpot:height d/parse-double))))) (defn add-position [props type node svg-data] @@ -181,6 +205,10 @@ (-> (parse-position svg-data) (gsh/setup-selrect)) + (= type :svg-raw) + (-> (add-svg-position node) + (gsh/setup-selrect)) + (= type :circle) (-> (parse-circle svg-data) (gsh/setup-selrect)) @@ -191,14 +219,16 @@ (defn add-fill [props node svg-data] - (let [fill (:fill svg-data)] + (let [fill (:fill svg-data) + gradient (when (str/starts-with? fill "url") + (parse-gradient node fill))] (cond-> props - (= fill "none") + :always (assoc :fill-color nil :fill-opacity nil) - (str/starts-with? fill "url") - (assoc :fill-color-gradient (parse-gradient node fill) + (some? gradient) + (assoc :fill-color-gradient gradient :fill-color nil :fill-opacity nil) @@ -211,24 +241,44 @@ (let [stroke-style (get-meta node :stroke-style keyword) stroke-alignment (get-meta node :stroke-alignment keyword) - stroke (:stroke svg-data)] + stroke (:stroke svg-data) + gradient (when (str/starts-with? stroke "url") + (parse-gradient node stroke))] (cond-> props :always (assoc :stroke-alignment stroke-alignment :stroke-style stroke-style - :stroke-color (-> svg-data (:stroke "#000000")) - :stroke-opacity (-> svg-data (:stroke-opacity "1") d/parse-double) - :stroke-width (-> svg-data (:stroke-width "0") d/parse-double)) + :stroke-color (-> svg-data :stroke) + :stroke-opacity (-> svg-data :stroke-opacity d/parse-double) + :stroke-width (-> svg-data :stroke-width d/parse-double)) - (str/starts-with? stroke "url") - (assoc :stroke-color-gradient (parse-gradient node stroke) + (some? gradient) + (assoc :stroke-color-gradient gradient :stroke-color nil :stroke-opacity nil) (= stroke-alignment :inner) (update :stroke-width / 2)))) +(defn add-rect-data + [props node svg-data] + (let [r1 (get-meta node :r1 d/parse-double) + r2 (get-meta node :r2 d/parse-double) + r3 (get-meta node :r3 d/parse-double) + r4 (get-meta node :r4 d/parse-double) + + rx (-> (get svg-data :rx) d/parse-double) + ry (-> (get svg-data :ry) d/parse-double)] + + (cond-> props + (some? r1) + (assoc :r1 r1 :r2 r2 :r3 r3 :r4 r4 + :rx nil :ry nil) + + (and (nil? r1) (some? rx)) + (assoc :rx rx :ry ry)))) + (defn add-image-data [props node] (-> props @@ -276,12 +326,16 @@ :suffix (get-meta node :suffix) :scale (get-meta node :scale d/parse-double)}) -(defn extract-from-data [node tag parse-fn] - (let [shape-data (get-data node)] - (->> shape-data - (node-seq) - (filter #(= (:tag %) tag)) - (mapv parse-fn)))) +(defn extract-from-data + ([node tag] + (extract-from-data node tag identity)) + + ([node tag parse-fn] + (let [shape-data (get-data node)] + (->> shape-data + (node-seq) + (filter #(= (:tag %) tag)) + (mapv parse-fn))))) (defn add-shadows [props node] @@ -313,8 +367,111 @@ (some? blend-mode) (assoc :blend-mode (keyword blend-mode)) - (some? opacity) - (assoc :opacity opacity)))) + (some? opacity) + (assoc :opacity opacity)))) + +(defn remove-prefix [s] + (cond-> s + (string? s) + (str/replace #"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-" ""))) + +(defn get-svg-attrs + [svg-data svg-attrs] + (let [assoc-key + (fn [acc prop] + (let [key (keyword prop)] + (if-let [v (or (get svg-data key) + (get-in svg-data [:attrs key]))] + (assoc acc key (remove-prefix v)) + acc)))] + + (->> (str/split svg-attrs ",") + (reduce assoc-key {})))) + +(defn get-svg-defs + [node svg-defs] + + (let [svg-import (get-data node :penpot:svg-import)] + (->> svg-import + :content + (filter #(= (:tag %) :penpot:svg-def)) + (map #(vector (-> % :attrs :def-id) + (-> % :content first))) + (into {})))) + +(defn add-svg-attrs + [props node svg-data] + + (let [svg-import (get-data node :penpot:svg-import)] + (if (some? svg-import) + (let [svg-attrs (get-in svg-import [:attrs :penpot:svg-attrs]) + svg-defs (get-in svg-import [:attrs :penpot:svg-defs]) + svg-transform (get-in svg-import [:attrs :penpot:svg-transform]) + viewbox-x (get-in svg-import [:attrs :penpot:svg-viewbox-x]) + viewbox-y (get-in svg-import [:attrs :penpot:svg-viewbox-y]) + viewbox-width (get-in svg-import [:attrs :penpot:svg-viewbox-width]) + viewbox-height (get-in svg-import [:attrs :penpot:svg-viewbox-height])] + + (cond-> props + :true + (assoc :svg-attrs (get-svg-attrs svg-data svg-attrs)) + + (some? viewbox-x) + (assoc :svg-viewbox {:x (d/parse-double viewbox-x) + :y (d/parse-double viewbox-y) + :width (d/parse-double viewbox-width) + :height (d/parse-double viewbox-height)}) + + (some? svg-transform) + (assoc :svg-transform (gmt/str->matrix svg-transform)) + + + (some? svg-defs) + (assoc :svg-defs (get-svg-defs node svg-defs)))) + + props))) + +(defn without-penpot-prefix + [m] + (let [no-penpot-prefix? + (fn [[k v]] + (not (str/starts-with? (d/name k) "penpot:")))] + (into {} (filter no-penpot-prefix?) m))) + +(defn camelize [[k v]] + [(-> k d/name str/camel keyword) v]) + +(defn camelize-keys + [m] + (assert (map? m) (str m)) + + (into {} (map camelize) m)) + +(defn fix-style-attr + [m] + (let [fix-style + (fn [[k v]] + (if (= k :style) + [k (-> v parse-style camelize-keys)] + [k v]))] + + (d/deep-mapm (comp camelize fix-style) m))) + +(defn add-svg-content + [props node] + (let [svg-content (get-data node :penpot:svg-content) + attrs (-> (:attrs svg-content) (without-penpot-prefix)) + tag (-> svg-content :attrs :penpot:tag keyword) + content {:attrs attrs + :tag tag + :content (cond + (= tag :svg) + (->> node :content last :content last :content fix-style-attr) + + (= tag :text) + (-> node :content last :content))}] + (-> props + (assoc :content content)))) (defn get-image-name [node] @@ -337,6 +494,9 @@ svg-data (get-svg-data type node)] (-> {} + (assoc :name name) + (assoc :blocked blocked) + (assoc :hidden hidden) (add-position type node svg-data) (add-fill node svg-data) (add-stroke node svg-data) @@ -344,13 +504,17 @@ (add-shadows node) (add-blur node) (add-exports node) - (assoc :name name) - (assoc :blocked blocked) - (assoc :hidden hidden) + (add-svg-attrs node svg-data) + + (cond-> (= :svg-raw type) + (add-svg-content node)) (cond-> (= :group type) (add-group-data node)) + (cond-> (= :rect type) + (add-rect-data node svg-data)) + (cond-> (= :image type) (add-image-data node)) diff --git a/frontend/src/app/worker/import.cljs b/frontend/src/app/worker/import.cljs index e2f1cd785..6a1c338a9 100644 --- a/frontend/src/app/worker/import.cljs +++ b/frontend/src/app/worker/import.cljs @@ -48,17 +48,16 @@ (rx/concat (->> (rx/from changes-batches) (rx/mapcat - (fn [cur-changes-batch] - (rp/mutation - :update-file - {:id file-id - :session-id session-id - :revn @revn - :changes cur-changes-batch}))) - + #(rp/mutation + :update-file + {:id file-id + :session-id session-id + :revn @revn + :changes %})) + (rx/map first) (rx/tap #(reset! revn (:revn %)))) - (rp/mutation :make-permanent {:id (:id file)})))) + (rp/mutation :persist-temp-file {:id (:id file)})))) (defn upload-media-files "Upload a image to the backend and returns its id" @@ -91,6 +90,9 @@ :group (fb/close-group file) + :svg-raw + (fb/close-svg-raw file) + ;; default file) @@ -102,6 +104,7 @@ :path (fb/create-path file data) :text (fb/create-text file data) :image (fb/create-image file data) + :svg-raw (fb/create-svg-raw file data) ;; default file)))) @@ -127,7 +130,8 @@ (assoc-in [:attrs :penpot:media-mtype] (:mtype media))))))) ;; If the node is not an image just return the node - (rx/of node))) + (->> (rx/of node) + (rx/observe-on :async)))) (defn import-page [file [page-name content]]