mirror of
https://github.com/penpot/penpot.git
synced 2025-05-05 00:05:53 +02:00
✨ Add to plugin api: upload media, group and ungroup
This commit is contained in:
parent
75d8965365
commit
21d38a058b
6 changed files with 148 additions and 51 deletions
|
@ -15,6 +15,7 @@
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
|
@ -68,7 +69,7 @@
|
||||||
result)))))))
|
result)))))))
|
||||||
|
|
||||||
(defn prepare-create-group
|
(defn prepare-create-group
|
||||||
[changes objects page-id shapes base-name keep-name?]
|
[changes id objects page-id shapes base-name keep-name?]
|
||||||
(let [frame-id (:frame-id (first shapes))
|
(let [frame-id (:frame-id (first shapes))
|
||||||
parent-id (:parent-id (first shapes))
|
parent-id (:parent-id (first shapes))
|
||||||
gname (if (and keep-name?
|
gname (if (and keep-name?
|
||||||
|
@ -84,7 +85,8 @@
|
||||||
(cfh/get-position-on-parent objects)
|
(cfh/get-position-on-parent objects)
|
||||||
inc)
|
inc)
|
||||||
|
|
||||||
group (cts/setup-shape {:type :group
|
group (cts/setup-shape {:id id
|
||||||
|
:type :group
|
||||||
:name gname
|
:name gname
|
||||||
:shapes (mapv :id shapes)
|
:shapes (mapv :id shapes)
|
||||||
:selrect selrect
|
:selrect selrect
|
||||||
|
@ -173,30 +175,43 @@
|
||||||
;; GROUPS
|
;; GROUPS
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def group-selected
|
(defn group-shapes
|
||||||
(ptk/reify ::group-selected
|
[id ids & {:keys [change-selection?] :or {change-selection? false}}]
|
||||||
|
(ptk/reify ::group-shapes
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [id (d/nilv id (uuid/next))
|
||||||
|
page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
selected (->> (wsh/lookup-selected state)
|
|
||||||
(cfh/clean-loops objects)
|
shapes
|
||||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
(->> ids
|
||||||
shapes (shapes-for-grouping objects selected)
|
(cfh/clean-loops objects)
|
||||||
|
(remove #(ctn/has-any-copy-parent? objects (get objects %)))
|
||||||
|
(shapes-for-grouping objects))
|
||||||
parents (into #{} (map :parent-id) shapes)]
|
parents (into #{} (map :parent-id) shapes)]
|
||||||
(when-not (empty? shapes)
|
(when-not (empty? shapes)
|
||||||
(let [[group changes]
|
(let [[group changes]
|
||||||
(prepare-create-group (pcb/empty-changes it) objects page-id shapes "Group" false)]
|
(prepare-create-group (pcb/empty-changes it) id objects page-id shapes "Group" false)]
|
||||||
(rx/of (dch/commit-changes changes)
|
(rx/of (dch/commit-changes changes)
|
||||||
(dws/select-shapes (d/ordered-set (:id group)))
|
(when change-selection?
|
||||||
|
(dws/select-shapes (d/ordered-set (:id group))))
|
||||||
(ptk/data-event :layout/update {:ids parents}))))))))
|
(ptk/data-event :layout/update {:ids parents}))))))))
|
||||||
|
|
||||||
(def ungroup-selected
|
(def group-selected
|
||||||
(ptk/reify ::ungroup-selected
|
(ptk/reify ::group-selected
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [selected (wsh/lookup-selected state)]
|
||||||
|
(rx/of group-shapes nil selected)))))
|
||||||
|
|
||||||
|
(defn ungroup-shapes
|
||||||
|
[ids & {:keys [change-selection?] :or {change-selection? false}}]
|
||||||
|
(ptk/reify ::ungroup-shapes
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
|
|
||||||
prepare
|
prepare
|
||||||
(fn [shape-id]
|
(fn [shape-id]
|
||||||
|
@ -213,35 +228,42 @@
|
||||||
(ctl/grid-layout? objects (:parent-id shape))
|
(ctl/grid-layout? objects (:parent-id shape))
|
||||||
(pcb/update-shapes [(:parent-id shape)] ctl/assign-cells {:with-objects? true}))))
|
(pcb/update-shapes [(:parent-id shape)] ctl/assign-cells {:with-objects? true}))))
|
||||||
|
|
||||||
selected (->> (wsh/lookup-selected state)
|
ids (->> ids
|
||||||
(remove #(ctn/has-any-copy-parent? objects (get objects %)))
|
(remove #(ctn/has-any-copy-parent? objects (get objects %)))
|
||||||
;; components can't be ungrouped
|
;; components can't be ungrouped
|
||||||
(remove #(ctk/instance-head? (get objects %))))
|
(remove #(ctk/instance-head? (get objects %))))
|
||||||
changes-list (sequence
|
|
||||||
(keep prepare)
|
changes-list (sequence (keep prepare) ids)
|
||||||
selected)
|
|
||||||
|
|
||||||
parents (into #{}
|
parents (into #{}
|
||||||
(comp (map #(cfh/get-parent objects %))
|
(comp (map #(cfh/get-parent objects %))
|
||||||
(keep :id))
|
(keep :id))
|
||||||
selected)
|
ids)
|
||||||
|
|
||||||
child-ids
|
child-ids
|
||||||
(into (d/ordered-set)
|
(into (d/ordered-set)
|
||||||
(mapcat #(dm/get-in objects [% :shapes]))
|
(mapcat #(dm/get-in objects [% :shapes]))
|
||||||
selected)
|
ids)
|
||||||
|
|
||||||
changes {:redo-changes (vec (mapcat :redo-changes changes-list))
|
changes {:redo-changes (vec (mapcat :redo-changes changes-list))
|
||||||
:undo-changes (vec (mapcat :undo-changes changes-list))
|
:undo-changes (vec (mapcat :undo-changes changes-list))
|
||||||
:origin it}
|
:origin it}
|
||||||
undo-id (js/Symbol)]
|
undo-id (js/Symbol)]
|
||||||
|
|
||||||
(when-not (empty? selected)
|
(when-not (empty? ids)
|
||||||
(rx/of (dwu/start-undo-transaction undo-id)
|
(rx/of (dwu/start-undo-transaction undo-id)
|
||||||
(dch/commit-changes changes)
|
(dch/commit-changes changes)
|
||||||
(ptk/data-event :layout/update {:ids parents})
|
(ptk/data-event :layout/update {:ids parents})
|
||||||
(dwu/commit-undo-transaction undo-id)
|
(dwu/commit-undo-transaction undo-id)
|
||||||
(dws/select-shapes child-ids)))))))
|
(when change-selection?
|
||||||
|
(dws/select-shapes child-ids))))))))
|
||||||
|
|
||||||
|
(def ungroup-selected
|
||||||
|
(ptk/reify ::ungroup-selected
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [selected (wsh/lookup-selected state)]
|
||||||
|
(rx/of (ungroup-shapes selected :change-selection? true))))))
|
||||||
|
|
||||||
(def mask-group
|
(def mask-group
|
||||||
(ptk/reify ::mask-group
|
(ptk/reify ::mask-group
|
||||||
|
@ -262,7 +284,7 @@
|
||||||
(= (:type (first shapes)) :group))
|
(= (:type (first shapes)) :group))
|
||||||
[first-shape (-> (pcb/empty-changes it page-id)
|
[first-shape (-> (pcb/empty-changes it page-id)
|
||||||
(pcb/with-objects objects))]
|
(pcb/with-objects objects))]
|
||||||
(prepare-create-group (pcb/empty-changes it) objects page-id shapes "Mask" true))
|
(prepare-create-group (pcb/empty-changes it) (uuid/next) objects page-id shapes "Mask" true))
|
||||||
|
|
||||||
changes (-> changes
|
changes (-> changes
|
||||||
(pcb/update-shapes (:shapes group)
|
(pcb/update-shapes (:shapes group)
|
||||||
|
|
|
@ -87,7 +87,17 @@
|
||||||
(->> (svg/upload-images svg-data file-id)
|
(->> (svg/upload-images svg-data file-id)
|
||||||
(rx/map #(svg/add-svg-shapes (assoc svg-data :image-data %) position))))))
|
(rx/map #(svg/add-svg-shapes (assoc svg-data :image-data %) position))))))
|
||||||
|
|
||||||
(defn- process-uris
|
|
||||||
|
(defn upload-media-url
|
||||||
|
[name file-id url]
|
||||||
|
(rp/cmd!
|
||||||
|
:create-file-media-object-from-url
|
||||||
|
{:name name
|
||||||
|
:file-id file-id
|
||||||
|
:url url
|
||||||
|
:is-local true}))
|
||||||
|
|
||||||
|
(defn process-uris
|
||||||
[{:keys [file-id local? name uris mtype on-image on-svg]}]
|
[{:keys [file-id local? name uris mtype on-image on-svg]}]
|
||||||
(letfn [(svg-url? [url]
|
(letfn [(svg-url? [url]
|
||||||
(or (and mtype (= mtype "image/svg+xml"))
|
(or (and mtype (= mtype "image/svg+xml"))
|
||||||
|
|
|
@ -13,12 +13,18 @@
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.changes :as ch]
|
[app.main.data.workspace.changes :as ch]
|
||||||
|
[app.main.data.workspace.groups :as dwg]
|
||||||
|
[app.main.data.workspace.media :as dwm]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.events :as events]
|
[app.plugins.events :as events]
|
||||||
[app.plugins.file :as file]
|
[app.plugins.file :as file]
|
||||||
[app.plugins.page :as page]
|
[app.plugins.page :as page]
|
||||||
[app.plugins.shape :as shape]
|
[app.plugins.shape :as shape]
|
||||||
[app.plugins.viewport :as viewport]))
|
[app.plugins.utils :as utils]
|
||||||
|
[app.plugins.viewport :as viewport]
|
||||||
|
[app.util.object :as obj]
|
||||||
|
[beicon.v2.core :as rx]
|
||||||
|
[promesa.core :as p]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; PLUGINS PUBLIC API - The plugins will able to access this functions
|
;; PLUGINS PUBLIC API - The plugins will able to access this functions
|
||||||
|
@ -33,7 +39,7 @@
|
||||||
[type]
|
[type]
|
||||||
(let [page-id (:current-page-id @st/state)
|
(let [page-id (:current-page-id @st/state)
|
||||||
page (dm/get-in @st/state [:workspace-data :pages-index page-id])
|
page (dm/get-in @st/state [:workspace-data :pages-index page-id])
|
||||||
shape (cts/setup-shape {:type :type
|
shape (cts/setup-shape {:type type
|
||||||
:x 0 :y 0 :width 100 :height 100})
|
:x 0 :y 0 :width 100 :height 100})
|
||||||
changes
|
changes
|
||||||
(-> (cb/empty-changes)
|
(-> (cb/empty-changes)
|
||||||
|
@ -89,13 +95,39 @@
|
||||||
"dark"
|
"dark"
|
||||||
(get-in @st/state [:profile :theme]))))
|
(get-in @st/state [:profile :theme]))))
|
||||||
|
|
||||||
|
(uploadMediaUrl
|
||||||
|
[_ name url]
|
||||||
|
(let [file-id (get-in @st/state [:workspace-file :id])]
|
||||||
|
(p/create
|
||||||
|
(fn [resolve reject]
|
||||||
|
(->> (dwm/upload-media-url name file-id url)
|
||||||
|
(rx/map utils/to-js)
|
||||||
|
(rx/take 1)
|
||||||
|
(rx/subs! resolve reject))))))
|
||||||
|
|
||||||
|
(group
|
||||||
|
[_ shapes]
|
||||||
|
(let [page-id (:current-page-id @st/state)
|
||||||
|
id (uuid/next)
|
||||||
|
ids (into #{} (map #(get (obj/get % "_data") :id)) shapes)]
|
||||||
|
(st/emit! (dwg/group-shapes id ids))
|
||||||
|
(shape/data->shape-proxy
|
||||||
|
(dm/get-in @st/state [:workspace-data :pages-index page-id :objects id]))))
|
||||||
|
|
||||||
|
(ungroup
|
||||||
|
[_ group & rest]
|
||||||
|
(let [shapes (concat [group] rest)
|
||||||
|
ids (into #{} (map #(get (obj/get % "_data") :id)) shapes)]
|
||||||
|
(st/emit! (dwg/ungroup-shapes ids))))
|
||||||
|
|
||||||
(createFrame
|
(createFrame
|
||||||
[_]
|
[_]
|
||||||
(create-shape :frame))
|
(create-shape :frame))
|
||||||
|
|
||||||
(createRectangle
|
(createRectangle
|
||||||
[_]
|
[_]
|
||||||
(create-shape :rect)))
|
(create-shape :rect))
|
||||||
|
)
|
||||||
|
|
||||||
(defn create-context
|
(defn create-context
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -16,9 +16,8 @@
|
||||||
[app.main.data.workspace :as udw]
|
[app.main.data.workspace :as udw]
|
||||||
[app.main.data.workspace.changes :as dwc]
|
[app.main.data.workspace.changes :as dwc]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.utils :refer [get-data get-data-fn]]
|
[app.plugins.utils :as utils :refer [get-data get-data-fn]]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]))
|
||||||
[cuerdas.core :as str]))
|
|
||||||
|
|
||||||
(declare data->shape-proxy)
|
(declare data->shape-proxy)
|
||||||
|
|
||||||
|
@ -26,19 +25,13 @@
|
||||||
[fills]
|
[fills]
|
||||||
(.freeze
|
(.freeze
|
||||||
js/Object
|
js/Object
|
||||||
(apply array
|
(apply array (->> fills (map utils/to-js)))))
|
||||||
(->> fills
|
|
||||||
;; TODO: Transform explicitly instead of cljs->js?
|
|
||||||
(map #(clj->js % {:keyword-fn (fn [k] (str/camel (name k)))}))))))
|
|
||||||
|
|
||||||
(defn- make-strokes
|
(defn- make-strokes
|
||||||
[strokes]
|
[strokes]
|
||||||
(.freeze
|
(.freeze
|
||||||
js/Object
|
js/Object
|
||||||
(apply array
|
(apply array (->> strokes (map utils/to-js)))))
|
||||||
(->> strokes
|
|
||||||
;; TODO: Transform explicitly instead of cljs->js?
|
|
||||||
(map #(clj->js % {:keyword-fn (fn [k] (str/camel (name k)))}))))))
|
|
||||||
|
|
||||||
(defn- locate-shape
|
(defn- locate-shape
|
||||||
[shape-id]
|
[shape-id]
|
||||||
|
@ -64,7 +57,6 @@
|
||||||
|
|
||||||
(resize
|
(resize
|
||||||
[self width height]
|
[self width height]
|
||||||
|
|
||||||
(let [id (get-data self :id)]
|
(let [id (get-data self :id)]
|
||||||
(st/emit! (udw/update-dimensions [id] :width width)
|
(st/emit! (udw/update-dimensions [id] :width width)
|
||||||
(udw/update-dimensions [id] :height height))))
|
(udw/update-dimensions [id] :height height))))
|
||||||
|
@ -99,7 +91,7 @@
|
||||||
:get (get-data-fn :id str)}
|
:get (get-data-fn :id str)}
|
||||||
|
|
||||||
{:name "type"
|
{:name "type"
|
||||||
:get (get-data-fn :type)}
|
:get (get-data-fn :type name)}
|
||||||
|
|
||||||
{:name "x"
|
{:name "x"
|
||||||
:get #(get-state % :x)
|
:get #(get-state % :x)
|
||||||
|
@ -129,12 +121,18 @@
|
||||||
|
|
||||||
{:name "fills"
|
{:name "fills"
|
||||||
:get #(get-state % :fills make-fills)
|
:get #(get-state % :fills make-fills)
|
||||||
;;:set (fn [self value] (.log js/console self value))
|
:set (fn [self value]
|
||||||
|
(let [id (get-data self :id)
|
||||||
|
value (mapv #(utils/from-js %) value)]
|
||||||
|
(st/emit! (dwc/update-shapes [id] #(assoc % :fills value)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
{:name "strokes"
|
{:name "strokes"
|
||||||
:get #(get-state % :strokes make-strokes)
|
:get #(get-state % :strokes make-strokes)
|
||||||
;;:set (fn [self value] (.log js/console self value))
|
:set (fn [self value]
|
||||||
|
(let [id (get-data self :id)
|
||||||
|
value (mapv #(utils/from-js %) value)]
|
||||||
|
(st/emit! (dwc/update-shapes [id] #(assoc % :strokes value)))))
|
||||||
})
|
})
|
||||||
|
|
||||||
(cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data))
|
(cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data))
|
||||||
|
|
|
@ -7,7 +7,13 @@
|
||||||
(ns app.plugins.utils
|
(ns app.plugins.utils
|
||||||
"RPC for plugins runtime."
|
"RPC for plugins runtime."
|
||||||
(:require
|
(:require
|
||||||
[app.util.object :as obj]))
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[app.util.object :as obj]
|
||||||
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
|
(def uuid-regex
|
||||||
|
#"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}")
|
||||||
|
|
||||||
(defn get-data
|
(defn get-data
|
||||||
([self attr]
|
([self attr]
|
||||||
|
@ -27,4 +33,37 @@
|
||||||
(fn [self]
|
(fn [self]
|
||||||
(get-data self attr transform-fn))))
|
(get-data self attr transform-fn))))
|
||||||
|
|
||||||
|
(defn from-js
|
||||||
|
"Converts the object back to js"
|
||||||
|
[obj]
|
||||||
|
(let [ret (js->clj obj {:keyword-fn (fn [k] (str/camel (name k)))})]
|
||||||
|
(reduce-kv
|
||||||
|
(fn [m k v]
|
||||||
|
(let [v (cond (map? v)
|
||||||
|
(from-js v)
|
||||||
|
|
||||||
|
(and (string? v) (re-matches uuid-regex v))
|
||||||
|
(uuid/uuid v)
|
||||||
|
|
||||||
|
:else v)]
|
||||||
|
(assoc m (keyword (str/kebab k)) v)))
|
||||||
|
{}
|
||||||
|
ret)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn to-js
|
||||||
|
"Converts to javascript an camelize the keys"
|
||||||
|
[obj]
|
||||||
|
(let [result
|
||||||
|
(reduce-kv
|
||||||
|
(fn [m k v]
|
||||||
|
(let [v (cond (object? v) (to-js v)
|
||||||
|
(uuid? v) (dm/str v)
|
||||||
|
:else v)]
|
||||||
|
(assoc m (str/camel (name k)) v)))
|
||||||
|
{}
|
||||||
|
obj)]
|
||||||
|
(clj->js result)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,11 @@
|
||||||
"RPC for plugins runtime."
|
"RPC for plugins runtime."
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.point :as gpt]
|
|
||||||
[app.common.record :as crc]
|
|
||||||
[app.common.record :as crc]
|
[app.common.record :as crc]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.viewport :as dwv]
|
[app.main.data.workspace.viewport :as dwv]
|
||||||
[app.main.data.workspace.zoom :as dwz]
|
[app.main.data.workspace.zoom :as dwz]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.page :as page]
|
|
||||||
[app.plugins.utils :refer [get-data-fn]]
|
|
||||||
[app.util.object :as obj]))
|
[app.util.object :as obj]))
|
||||||
|
|
||||||
(deftype ViewportProxy []
|
(deftype ViewportProxy []
|
||||||
|
|
Loading…
Add table
Reference in a new issue