diff --git a/common/src/app/common/types/shape.cljc b/common/src/app/common/types/shape.cljc index c994f3c34..9249ac560 100644 --- a/common/src/app/common/types/shape.cljc +++ b/common/src/app/common/types/shape.cljc @@ -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))) diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss index a9420d84c..cbfc24e1b 100644 --- a/frontend/resources/styles/main/partials/modal.scss +++ b/frontend/resources/styles/main/partials/modal.scss @@ -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; diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f4ffb8671..81fa94eeb 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -13,11 +13,15 @@ [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.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 +29,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 +54,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 +85,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (declare file-initialized) +(declare remove-graphics) ;; --- Initialize Workspace @@ -170,15 +178,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 +1254,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 +1601,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 #(js/console.error ; When error downloading media-obj, skip it and continue with next one + (str "Error downloading " (:name media-obj) " " path ":") + (clj->js %)))))) + +(defn- create-shapes-img + [pos media-obj] + (let [{:keys [name width height id mtype]} media-obj + + 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/media.cljs b/frontend/src/app/main/data/workspace/media.cljs index e08c75c8e..3ff712de5 100644 --- a/frontend/src/app/main/data/workspace/media.cljs +++ b/frontend/src/app/main/data/workspace/media.cljs @@ -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 diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 4424f6ba0..2d6aa420a 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -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 { }." + [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})))))) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index de39b2c04..5c2e6eea1 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -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 diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index cbb8ba694..bfcca5b48 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -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))]]]])) + diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index f1b909d7f..3a341175e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -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)