mirror of
https://github.com/penpot/penpot.git
synced 2025-02-10 00:58:26 -05:00
Merge branch 'hiru-remove-graphics' into develop
This commit is contained in:
commit
58dbe21544
8 changed files with 405 additions and 164 deletions
|
@ -388,12 +388,14 @@
|
|||
(setup-rect-selrect)))
|
||||
|
||||
(defn- setup-image
|
||||
[{:keys [metadata] :as shape} props]
|
||||
(-> (setup-rect shape props)
|
||||
(assoc
|
||||
:proportion (/ (:width metadata)
|
||||
(:height metadata))
|
||||
:proportion-lock true)))
|
||||
[shape props]
|
||||
(let [metadata (or (:metadata shape) (:metadata props))]
|
||||
(-> (setup-rect shape props)
|
||||
(assoc
|
||||
:metadata metadata
|
||||
:proportion (/ (:width metadata)
|
||||
(:height metadata))
|
||||
:proportion-lock true))))
|
||||
|
||||
(defn setup-shape
|
||||
"A function that initializes the geometric data of
|
||||
|
@ -409,7 +411,9 @@
|
|||
(defn make-shape
|
||||
"Make a non group shape, ready to use."
|
||||
[type geom-props attrs]
|
||||
(-> (make-minimal-shape type)
|
||||
(-> (if-not (= type :group)
|
||||
(make-minimal-shape type)
|
||||
(make-minimal-group uuid/zero geom-props (:name attrs)))
|
||||
(setup-shape geom-props)
|
||||
(merge attrs)))
|
||||
|
||||
|
|
|
@ -1848,6 +1848,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
.remove-graphics-dialog {
|
||||
.close {
|
||||
border: 1px solid $color-gray-30;
|
||||
background: $color-canvas;
|
||||
border-radius: 3px;
|
||||
padding: 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
|
||||
&:hover {
|
||||
background: $color-gray-20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- LOGIN
|
||||
.login-register {
|
||||
background-color: $color-white;
|
||||
|
|
|
@ -13,11 +13,16 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.rect :as gpsr]
|
||||
[app.common.logging :as log]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.text :as txt]
|
||||
[app.common.transit :as t]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
|
@ -25,6 +30,7 @@
|
|||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.messages :as msg]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.data.workspace.bool :as dwb]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
|
@ -49,17 +55,19 @@
|
|||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.svg-upload :as svg]
|
||||
[app.main.data.workspace.thumbnails :as dwth]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.viewport :as dwv]
|
||||
[app.main.data.workspace.zoom :as dwz]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as ug]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :as i18n]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
[app.util.timers :as tm]
|
||||
[app.util.webapi :as wapi]
|
||||
|
@ -78,6 +86,7 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(declare file-initialized)
|
||||
(declare remove-graphics)
|
||||
|
||||
;; --- Initialize Workspace
|
||||
|
||||
|
@ -170,15 +179,20 @@
|
|||
:current-file-comments-users (d/index-by :id file-comments-users)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [file-id (:id file)
|
||||
ignore-until (:ignore-sync-until file)
|
||||
needs-update? (some #(and (> (:modified-at %) (:synced-at %))
|
||||
(or (not ignore-until)
|
||||
(> (:modified-at %) ignore-until)))
|
||||
libraries)]
|
||||
(watch [_ state _]
|
||||
(let [file-id (:id file)
|
||||
ignore-until (:ignore-sync-until file)
|
||||
some-graphics? (some? (-> file :data :media))
|
||||
needs-update? (some #(and (> (:modified-at %) (:synced-at %))
|
||||
(or (not ignore-until)
|
||||
(> (:modified-at %) ignore-until)))
|
||||
libraries)
|
||||
components-v2 (features/active-feature? state :components-v2)]
|
||||
(rx/merge
|
||||
(rx/of (fbc/fix-bool-contents))
|
||||
(if (and some-graphics? components-v2)
|
||||
(rx/of (remove-graphics (:id file) (:name file)))
|
||||
(rx/empty))
|
||||
(if needs-update?
|
||||
(rx/of (dwl/notify-sync-file file-id))
|
||||
(rx/empty)))))))
|
||||
|
@ -1241,7 +1255,7 @@
|
|||
(catch :default e
|
||||
(let [data (ex-data e)]
|
||||
(if (:not-implemented data)
|
||||
(rx/of (msg/warn (i18n/tr "errors.clipboard-not-implemented")))
|
||||
(rx/of (msg/warn (tr "errors.clipboard-not-implemented")))
|
||||
(js/console.error "ERROR" e))))))))
|
||||
|
||||
(defn paste-from-event
|
||||
|
@ -1588,6 +1602,163 @@
|
|||
(dwu/commit-undo-transaction))))))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Remove graphics
|
||||
;; TODO: this should be deprecated and removed together with components-v2
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- initialize-remove-graphics
|
||||
[total]
|
||||
(ptk/reify ::initialize-remove-graphics
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :remove-graphics {:total total
|
||||
:current nil}))))
|
||||
|
||||
(defn- update-remove-graphics
|
||||
[current]
|
||||
(ptk/reify ::update-remove-graphics
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:remove-graphics :current] current))))
|
||||
|
||||
(defn- complete-remove-graphics
|
||||
[]
|
||||
(ptk/reify ::complete-remove-graphics
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(dissoc state :remove-graphics))))
|
||||
|
||||
(defn- create-shapes-svg
|
||||
[file-id objects pos media-obj]
|
||||
(let [path (cfg/resolve-file-media media-obj)
|
||||
|
||||
upload-images
|
||||
(fn [svg-data]
|
||||
(->> (svg/upload-images svg-data file-id)
|
||||
(rx/map #(assoc svg-data :image-data %))))
|
||||
|
||||
process-svg
|
||||
(fn [svg-data]
|
||||
(let [[shape children]
|
||||
(svg/create-svg-shapes svg-data pos objects uuid/zero #{} false)]
|
||||
[shape children]))]
|
||||
|
||||
(->> (http/send! {:method :get :uri path :mode :no-cors})
|
||||
(rx/map :body)
|
||||
(rx/map #(vector (:name media-obj) %))
|
||||
(rx/merge-map dwm/svg->clj)
|
||||
(rx/merge-map upload-images)
|
||||
(rx/map process-svg)
|
||||
(rx/catch ; When error downloading media-obj, skip it and continue with next one
|
||||
#(log/error :hint "error downloading file"
|
||||
:path path
|
||||
:name (:name media-obj)
|
||||
:cause %)))))
|
||||
|
||||
(defn- create-shapes-img
|
||||
[pos {:keys [name width height id mtype] :as media-obj}]
|
||||
(let [group-shape (cts/make-shape :group
|
||||
{:x (:x pos)
|
||||
:y (:y pos)
|
||||
:width width
|
||||
:height height}
|
||||
{:name name
|
||||
:frame-id uuid/zero
|
||||
:parent-id uuid/zero})
|
||||
|
||||
img-shape (cts/make-shape :image
|
||||
{:x (:x pos)
|
||||
:y (:y pos)
|
||||
:width width
|
||||
:height height
|
||||
:metadata {:id id
|
||||
:width width
|
||||
:height height
|
||||
:mtype mtype}}
|
||||
{:name name
|
||||
:frame-id uuid/zero
|
||||
:parent-id (:id group-shape)})]
|
||||
(rx/of [group-shape [img-shape]])))
|
||||
|
||||
(defn- remove-graphic
|
||||
[it file-data page [index [media-obj pos]]]
|
||||
(let [process-shapes
|
||||
(fn [[shape children]]
|
||||
(let [page' (reduce #(ctst/add-shape (:id %2) %2 %1 uuid/zero (:parent-id %2) nil false)
|
||||
page
|
||||
(cons shape children))
|
||||
|
||||
shape' (ctn/get-shape page' (:id shape))
|
||||
|
||||
path (cph/merge-path-item (tr "workspace.assets.graphics") (:path media-obj))
|
||||
|
||||
[component-shape component-shapes updated-shapes]
|
||||
(ctn/make-component-shape shape' (:objects page') (:id file-data) true)
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/set-save-undo? false)
|
||||
(pcb/with-page page')
|
||||
(pcb/with-objects (:objects page'))
|
||||
(pcb/with-library-data file-data)
|
||||
(pcb/delete-media (:id media-obj))
|
||||
(pcb/add-objects (cons shape children))
|
||||
(pcb/add-component (:id component-shape)
|
||||
path
|
||||
(:name media-obj)
|
||||
component-shapes
|
||||
updated-shapes
|
||||
(:id shape)
|
||||
(:id page)))]
|
||||
|
||||
(dch/commit-changes changes)))
|
||||
|
||||
shapes (if (= (:mtype media-obj) "image/svg+xml")
|
||||
(create-shapes-svg (:id file-data) (:objects page) pos media-obj)
|
||||
(create-shapes-img pos media-obj))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (update-remove-graphics index))
|
||||
(rx/map process-shapes shapes))))
|
||||
|
||||
(defn- remove-graphics
|
||||
[file-id file-name]
|
||||
(ptk/reify ::remove-graphics
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-data (wsh/get-file state file-id)
|
||||
|
||||
grid-gap 50
|
||||
|
||||
[file-data' page-id start-pos]
|
||||
(ctf/get-or-add-library-page file-data grid-gap)
|
||||
|
||||
new-page? (nil? (ctpl/get-page file-data page-id))
|
||||
page (ctpl/get-page file-data' page-id)
|
||||
media (vals (:media file-data'))
|
||||
|
||||
media-points
|
||||
(map #(assoc % :points (gpsr/rect->points {:x 0
|
||||
:y 0
|
||||
:width (:width %)
|
||||
:height (:height %)}))
|
||||
media)
|
||||
|
||||
shape-grid
|
||||
(ctst/generate-shape-grid media-points start-pos grid-gap)]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (modal/show {:type :remove-graphics-dialog :file-name file-name})
|
||||
(initialize-remove-graphics (count media)))
|
||||
(when new-page?
|
||||
(rx/of (dch/commit-changes (-> (pcb/empty-changes it)
|
||||
(pcb/set-save-undo? false)
|
||||
(pcb/add-page (:id page) page)))))
|
||||
(rx/mapcat (partial remove-graphic it file-data' page)
|
||||
(rx/from (d/enumerate (d/zip media shape-grid))))
|
||||
(rx/of (modal/hide)
|
||||
(complete-remove-graphics)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Exports
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
[app.main.store :as st]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.svg :as usvg]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
|
@ -35,27 +33,6 @@
|
|||
(catch :default _err
|
||||
(rx/throw {:type :svg-parser}))))
|
||||
|
||||
(defn extract-name [url]
|
||||
(let [query-idx (str/last-index-of url "?")
|
||||
url (if (> query-idx 0) (subs url 0 query-idx) url)
|
||||
filename (->> (str/split url "/") (last))
|
||||
ext-idx (str/last-index-of filename ".")]
|
||||
(if (> ext-idx 0) (subs filename 0 ext-idx) filename)))
|
||||
|
||||
(defn data-uri->blob
|
||||
[data-uri]
|
||||
(let [[mtype b64-data] (str/split data-uri ";base64,")
|
||||
mtype (subs mtype (inc (str/index-of mtype ":")))
|
||||
decoded (.atob js/window b64-data)
|
||||
size (.-length ^js decoded)
|
||||
content (js/Uint8Array. size)]
|
||||
|
||||
(doseq [i (range 0 size)]
|
||||
(aset content i (.charCodeAt decoded i)))
|
||||
|
||||
(wapi/create-blob content mtype)))
|
||||
|
||||
|
||||
;; TODO: rename to bitmap-image-uploaded
|
||||
(defn image-uploaded
|
||||
[image {:keys [x y]}]
|
||||
|
@ -82,26 +59,8 @@
|
|||
;; Once the SVG is uploaded, we need to extract all the bitmap
|
||||
;; images and upload them separately, then proceed to create
|
||||
;; all shapes.
|
||||
(->> (rx/from (usvg/collect-images svg-data))
|
||||
(rx/map (fn [uri]
|
||||
(merge
|
||||
{:file-id file-id
|
||||
:is-local true}
|
||||
(if (str/starts-with? uri "data:")
|
||||
{:name "image"
|
||||
:content (data-uri->blob uri)}
|
||||
{:name (extract-name uri)
|
||||
:url uri}))))
|
||||
(rx/mapcat (fn [uri-data]
|
||||
(->> (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 #(svg/create-svg-shapes (assoc svg-data :image-data %) position))))))
|
||||
(->> (svg/upload-images svg-data file-id)
|
||||
(rx/map #(svg/add-svg-shapes (assoc svg-data :image-data %) position))))))
|
||||
|
||||
(defn- process-uris
|
||||
[{:keys [file-id local? name uris mtype on-image on-svg]}]
|
||||
|
@ -112,13 +71,13 @@
|
|||
(prepare [uri]
|
||||
{:file-id file-id
|
||||
:is-local local?
|
||||
:name (or name (extract-name uri))
|
||||
:name (or name (svg/extract-name uri))
|
||||
:url uri})
|
||||
|
||||
(fetch-svg [name uri]
|
||||
(->> (http/send! {:method :get :uri uri :mode :no-cors})
|
||||
(rx/map #(vector
|
||||
(or name (extract-name uri))
|
||||
(or name (svg/extract-name uri))
|
||||
(:body %)))))]
|
||||
|
||||
(rx/merge
|
||||
|
@ -234,6 +193,7 @@
|
|||
(rx/catch handle-error)
|
||||
(rx/finalize #(st/emit! (dm/hide-tag :media-loading)))))))))
|
||||
|
||||
;; Deprecated in components-v2
|
||||
(defn upload-media-asset
|
||||
[params]
|
||||
(let [params (assoc params
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.color :as uc]
|
||||
[app.util.path.parser :as upp]
|
||||
[app.util.svg :as usvg]
|
||||
[app.util.webapi :as wapi]
|
||||
[beicon.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
|
@ -411,105 +413,170 @@
|
|||
(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)]
|
||||
(if (some? shape)
|
||||
(let [shape-id (:id shape)
|
||||
(defn create-svg-children
|
||||
[objects selected frame-id parent-id svg-data [unames children] [_index svg-element]]
|
||||
(let [[new-shape new-children] (parse-svg-element frame-id svg-data svg-element unames)]
|
||||
(if (some? new-shape)
|
||||
(let [shape-id (:id new-shape)
|
||||
|
||||
new-shape (dwsh/make-new-shape shape objects selected)
|
||||
changes (-> changes
|
||||
(pcb/add-object new-shape)
|
||||
(pcb/change-parent parent-id [new-shape] index))
|
||||
new-shape' (-> (dwsh/make-new-shape new-shape objects selected)
|
||||
(assoc :parent-id parent-id))
|
||||
|
||||
unames (conj unames (:name new-shape))
|
||||
children (conj children new-shape')
|
||||
unames (conj unames (:name new-shape'))
|
||||
|
||||
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data)]
|
||||
(reduce reducer-fn [unames changes] (d/enumerate children)))
|
||||
reducer-fn (partial create-svg-children objects selected frame-id shape-id svg-data)]
|
||||
|
||||
[unames changes])))
|
||||
(reduce reducer-fn [unames children] (d/enumerate new-children)))
|
||||
|
||||
[unames children])))
|
||||
|
||||
(defn data-uri->blob
|
||||
[data-uri]
|
||||
(let [[mtype b64-data] (str/split data-uri ";base64,")
|
||||
mtype (subs mtype (inc (str/index-of mtype ":")))
|
||||
decoded (.atob js/window b64-data)
|
||||
size (.-length ^js decoded)
|
||||
content (js/Uint8Array. size)]
|
||||
|
||||
(doseq [i (range 0 size)]
|
||||
(aset content i (.charCodeAt decoded i)))
|
||||
|
||||
(wapi/create-blob content mtype)))
|
||||
|
||||
(defn extract-name [url]
|
||||
(let [query-idx (str/last-index-of url "?")
|
||||
url (if (> query-idx 0) (subs url 0 query-idx) url)
|
||||
filename (->> (str/split url "/") (last))
|
||||
ext-idx (str/last-index-of filename ".")]
|
||||
(if (> ext-idx 0) (subs filename 0 ext-idx) filename)))
|
||||
|
||||
(defn upload-images
|
||||
"Extract all bitmap images inside the svg data, and upload them, associated to the file.
|
||||
Return a map {<url> <image-data>}."
|
||||
[svg-data file-id]
|
||||
(->> (rx/from (usvg/collect-images svg-data))
|
||||
(rx/map (fn [uri]
|
||||
(merge
|
||||
{:file-id file-id
|
||||
:is-local true}
|
||||
(if (str/starts-with? uri "data:")
|
||||
{:name "image"
|
||||
:content (data-uri->blob uri)}
|
||||
{:name (extract-name uri)
|
||||
:url uri}))))
|
||||
(rx/mapcat (fn [uri-data]
|
||||
(->> (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)) {})))
|
||||
|
||||
(defn create-svg-shapes
|
||||
[svg-data {:keys [x y] :as position}]
|
||||
(ptk/reify ::create-svg-shapes
|
||||
[svg-data {:keys [x y] :as position} objects frame-id selected center?]
|
||||
(try
|
||||
(let [[vb-x vb-y vb-width vb-height] (svg-dimensions svg-data)
|
||||
x (if center?
|
||||
(- x vb-x (/ vb-width 2))
|
||||
x)
|
||||
y (if center?
|
||||
(- y vb-y (/ vb-height 2))
|
||||
y)
|
||||
|
||||
unames (ctst/retrieve-used-names objects)
|
||||
|
||||
svg-name (->> (str/replace (:name svg-data) ".svg" "")
|
||||
(ctst/generate-unique-name unames))
|
||||
|
||||
svg-data (-> svg-data
|
||||
(assoc :x x
|
||||
:y y
|
||||
:offset-x vb-x
|
||||
:offset-y vb-y
|
||||
:width vb-width
|
||||
:height vb-height
|
||||
:name svg-name))
|
||||
|
||||
[def-nodes svg-data] (-> svg-data
|
||||
(usvg/fix-default-values)
|
||||
(usvg/fix-percents)
|
||||
(usvg/extract-defs))
|
||||
|
||||
svg-data (assoc svg-data :defs def-nodes)
|
||||
|
||||
root-shape (create-svg-root frame-id svg-data)
|
||||
root-id (:id root-shape)
|
||||
|
||||
;; In penpot groups have the size of their children. To respect the imported svg size and empty space let's create a transparent shape as background to respect the imported size
|
||||
base-background-shape {:tag :rect
|
||||
:attrs {:x "0"
|
||||
:y "0"
|
||||
:width (str (:width root-shape))
|
||||
:height (str (:height root-shape))
|
||||
:fill "none"
|
||||
:id "base-background"}
|
||||
:hidden true
|
||||
:content []}
|
||||
|
||||
svg-data (-> svg-data
|
||||
(assoc :defs def-nodes)
|
||||
(assoc :content (into [base-background-shape] (:content svg-data))))
|
||||
|
||||
;; Create the root shape
|
||||
new-shape (dwsh/make-new-shape root-shape objects selected)
|
||||
|
||||
root-attrs (-> (:attrs svg-data)
|
||||
(usvg/format-styles))
|
||||
|
||||
[_ new-children]
|
||||
(reduce (partial create-svg-children objects selected frame-id root-id svg-data)
|
||||
[unames []]
|
||||
(d/enumerate (->> (:content svg-data)
|
||||
(mapv #(usvg/inherit-attributes root-attrs %)))))]
|
||||
|
||||
[new-shape new-children])
|
||||
|
||||
(catch :default e
|
||||
(.error js/console "Error SVG" e)
|
||||
(rx/throw {:type :svg-parser
|
||||
:data e}))))
|
||||
|
||||
(defn add-svg-shapes
|
||||
[svg-data position]
|
||||
(ptk/reify ::add-svg-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(try
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
selected (wsh/lookup-selected state)
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (ctst/top-nested-frame objects position)
|
||||
selected (wsh/lookup-selected state)
|
||||
|
||||
[vb-x vb-y vb-width vb-height] (svg-dimensions svg-data)
|
||||
x (- x vb-x (/ vb-width 2))
|
||||
y (- y vb-y (/ vb-height 2))
|
||||
[new-shape new-children]
|
||||
(create-svg-shapes svg-data position objects frame-id selected true)
|
||||
|
||||
unames (ctst/retrieve-used-names objects)
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/add-object new-shape))
|
||||
|
||||
svg-name (->> (str/replace (:name svg-data) ".svg" "")
|
||||
(ctst/generate-unique-name unames))
|
||||
changes
|
||||
(reduce (fn [changes [index new-child]]
|
||||
(-> changes
|
||||
(pcb/add-object new-child)
|
||||
(pcb/change-parent (:parent-id new-child) [new-child] index)))
|
||||
changes
|
||||
(d/enumerate new-children))
|
||||
|
||||
svg-data (-> svg-data
|
||||
(assoc :x x
|
||||
:y y
|
||||
:offset-x vb-x
|
||||
:offset-y vb-y
|
||||
:width vb-width
|
||||
:height vb-height
|
||||
:name svg-name))
|
||||
changes (pcb/resize-parents changes
|
||||
(->> changes
|
||||
:redo-changes
|
||||
(filter #(= :add-obj (:type %)))
|
||||
(map :id)
|
||||
reverse
|
||||
vec))]
|
||||
|
||||
[def-nodes svg-data] (-> svg-data
|
||||
(usvg/fix-default-values)
|
||||
(usvg/fix-percents)
|
||||
(usvg/extract-defs))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dws/select-shapes (d/ordered-set (:id new-shape))))))))
|
||||
|
||||
svg-data (assoc svg-data :defs def-nodes)
|
||||
|
||||
root-shape (create-svg-root frame-id svg-data)
|
||||
root-id (:id root-shape)
|
||||
|
||||
;; In penpot groups have the size of their children. To respect the imported svg size and empty space let's create a transparent shape as background to respect the imported size
|
||||
base-background-shape {:tag :rect
|
||||
:attrs {:x "0"
|
||||
:y "0"
|
||||
:width (str (:width root-shape))
|
||||
:height (str (:height root-shape))
|
||||
:fill "none"
|
||||
:id "base-background"}
|
||||
:hidden true
|
||||
:content []}
|
||||
|
||||
svg-data (-> svg-data
|
||||
(assoc :defs def-nodes)
|
||||
(assoc :content (into [base-background-shape] (:content svg-data))))
|
||||
|
||||
;; Creates the root shape
|
||||
new-shape (dwsh/make-new-shape root-shape objects selected)
|
||||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/add-object new-shape))
|
||||
|
||||
root-attrs (-> (:attrs svg-data)
|
||||
(usvg/format-styles))
|
||||
|
||||
;; Reduce the children to create the changes to add the children shapes
|
||||
[_ changes]
|
||||
(reduce (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data)
|
||||
[unames changes]
|
||||
(d/enumerate (->> (:content svg-data)
|
||||
(mapv #(usvg/inherit-attributes root-attrs %)))))
|
||||
changes (pcb/resize-parents changes
|
||||
(->> changes
|
||||
:redo-changes
|
||||
(filter #(= :add-obj (:type %)))
|
||||
(map :id)
|
||||
reverse
|
||||
vec))]
|
||||
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dws/select-shapes (d/ordered-set root-id))))
|
||||
|
||||
(catch :default e
|
||||
(.error js/console "Error SVG" e)
|
||||
(rx/throw {:type :svg-parser
|
||||
:data e}))))))
|
||||
|
|
|
@ -300,7 +300,6 @@
|
|||
[ids]
|
||||
(l/derived #(select-keys % ids) workspace-modifiers))
|
||||
|
||||
|
||||
(def workspace-modifiers-with-objects
|
||||
(l/derived
|
||||
(fn [state]
|
||||
|
@ -361,6 +360,10 @@
|
|||
(def workspace-focus-selected
|
||||
(l/derived :workspace-focus-selected st/state))
|
||||
|
||||
;; Remove this when deprecating components-v2
|
||||
(def remove-graphics
|
||||
(l/derived :remove-graphics st/state))
|
||||
|
||||
;; ---- Viewer refs
|
||||
|
||||
(defn lookup-viewer-objects-by-id
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.colors :as clr]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.messages :as msg]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.persistence :as dwp]
|
||||
[app.main.features :as features]
|
||||
|
@ -168,3 +169,19 @@
|
|||
:layout layout}]
|
||||
[:& workspace-loader])]]]]]]))
|
||||
|
||||
(mf/defc remove-graphics-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :remove-graphics-dialog}
|
||||
[{:keys [] :as ctx}]
|
||||
(let [remove-state (mf/deref refs/remove-graphics)
|
||||
close #(modal/hide!)]
|
||||
[:div.modal-overlay
|
||||
[:div.modal-container.remove-graphics-dialog
|
||||
[:div.modal-header
|
||||
[:div.modal-header-title
|
||||
[:h2 (str "Updating " (:file-name ctx) "...")]]
|
||||
[:div.modal-close-button
|
||||
{:on-click close} i/close]]
|
||||
[:div.modal-content
|
||||
[:p (str "Converting " (:current remove-state) " / " (:total remove-state))]]]]))
|
||||
|
||||
|
|
|
@ -759,9 +759,7 @@
|
|||
(mf/use-fn
|
||||
(mf/deps object selected-objects item-ref on-drag-start)
|
||||
(fn [event]
|
||||
(on-asset-drag-start event object selected-objects item-ref :graphics on-drag-start)))
|
||||
|
||||
]
|
||||
(on-asset-drag-start event object selected-objects item-ref :graphics on-drag-start)))]
|
||||
|
||||
[:div {:ref item-ref
|
||||
:class-name (dom/classnames
|
||||
|
@ -919,6 +917,8 @@
|
|||
|
||||
groups (group-assets objects reverse-sort?)
|
||||
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
|
||||
add-graphic
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
|
@ -1051,12 +1051,13 @@
|
|||
:open? open?}
|
||||
(when local?
|
||||
[:& asset-section-block {:role :title-button}
|
||||
[:div.assets-button {:on-click add-graphic}
|
||||
i/plus
|
||||
[:& file-uploader {:accept cm/str-image-types
|
||||
:multi true
|
||||
:ref input-ref
|
||||
:on-selected on-file-selected}]]])
|
||||
(when-not components-v2
|
||||
[:div.assets-button {:on-click add-graphic}
|
||||
i/plus
|
||||
[:& file-uploader {:accept cm/str-image-types
|
||||
:multi true
|
||||
:ref input-ref
|
||||
:on-selected on-file-selected}]])])
|
||||
|
||||
[:& asset-section-block {:role :content}
|
||||
[:& graphics-group {:file-id file-id
|
||||
|
@ -1916,10 +1917,12 @@
|
|||
|
||||
selected-assets (mf/deref refs/selected-assets)
|
||||
|
||||
selected-count (+ (count (:components selected-assets))
|
||||
(count (:graphics selected-assets))
|
||||
(count (:colors selected-assets))
|
||||
(count (:typographies selected-assets)))
|
||||
selected-count (+ (count (:components selected-assets))
|
||||
(count (:graphics selected-assets))
|
||||
(count (:colors selected-assets))
|
||||
(count (:typographies selected-assets)))
|
||||
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
|
||||
toggle-open #(st/emit! (dwl/set-assets-box-open (:id file) :library (not open?)))
|
||||
|
||||
|
@ -2053,7 +2056,8 @@
|
|||
show-graphics? (and (or (= (:box filters) :all)
|
||||
(= (:box filters) :graphics))
|
||||
(or (> (count media) 0)
|
||||
(str/empty? (:term filters))))
|
||||
(and (str/empty? (:term filters))
|
||||
(not components-v2))))
|
||||
show-colors? (and (or (= (:box filters) :all)
|
||||
(= (:box filters) :colors))
|
||||
(or (> (count colors) 0)
|
||||
|
|
Loading…
Add table
Reference in a new issue