Add plugins and mcp event data

This commit is contained in:
alonso.torres 2026-04-29 14:22:55 +02:00
parent 8b29ca61c6
commit 8ac0508d4d
17 changed files with 292 additions and 161 deletions

View File

@ -96,12 +96,13 @@
(update-in [:comments id] assoc (:id comment) comment))))
ptk/WatchEvent
(watch [_ _ _]
(watch [it _ _]
(rx/of (ptk/data-event ::ev/event
{::ev/name "create-comment-thread"
::ev/origin "workspace"
:id id
:content-size (count (:content comment))}))))))
(merge {::ev/name "create-comment-thread"
::ev/origin "workspace"
:id id
:content-size (count (:content comment))}
(meta it))))))))
(def ^:private
schema:create-thread-on-workspace
@ -119,7 +120,7 @@
(ptk/reify ::create-thread-on-workspace
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
(let [page-id (:current-page-id state)
objects (dsh/lookup-page-objects state page-id)
frame-id (ctst/get-frame-id-by-position objects (:position params))
@ -129,7 +130,10 @@
(->> (rp/cmd! :create-comment-thread params)
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)}))
(rx/tap on-thread-created)
(rx/map #(created-thread-on-workspace % open?))
(rx/map
(fn [data]
(-> (created-thread-on-workspace data open?)
(with-meta (meta it)))))
(rx/catch (fn [{:keys [type code] :as cause}]
(if (and (= type :restriction)
(= code :max-quote-reached))
@ -216,11 +220,14 @@
(d/update-in-when state [:comment-threads id] assoc :is-resolved is-resolved))
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
(let [share-id (-> state :viewer-local :share-id)]
(rx/concat
(when is-resolved (rx/of
(ptk/event ::ev/event {::ev/name "resolve-comment-thread" :thread-id id})))
(when is-resolved
(rx/of (ptk/event
::ev/event
(-> {::ev/name "resolve-comment-thread" :thread-id id}
(merge (meta it))))))
(->> (rp/cmd! :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id})
(rx/catch (fn [{:keys [type code] :as cause}]
(if (and (= type :restriction)
@ -309,16 +316,18 @@
(update :comment-threads dissoc id)))
ptk/WatchEvent
(watch [_ _ _]
(watch [it _ _]
(rx/concat
(->> (rp/cmd! :delete-comment-thread {:id id})
(rx/catch #(rx/throw {:type :comment-error}))
(rx/tap on-delete)
(rx/ignore))
(rx/of (ptk/data-event ::ev/event
{::ev/name "delete-comment-thread"
::ev/origin "workspace"
:id id})))))))
(merge
{::ev/name "delete-comment-thread"
::ev/origin "workspace"
:id id}
(meta it)))))))))
(defn delete-comment-thread-on-viewer
[{:keys [id] :as thread}]

View File

@ -433,7 +433,7 @@
([id-ref ids]
(ptk/reify ::add-component
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
(let [objects (dsh/lookup-page-objects state)
selected (->> (d/nilv ids (dsh/lookup-selected state))
(cfh/clean-loops objects))
@ -442,7 +442,8 @@
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))]
(when can-make-component
(rx/of (add-component2 id-ref selected))))))))
(rx/of (-> (add-component2 id-ref selected)
(with-meta (meta it))))))))))
(defn add-multiple-components
"Add several new components to current file library, from the currently selected shapes."
@ -645,10 +646,11 @@
(reset! id-ref (:id new-shape)))
(rx/of (ptk/event ::ev/event
{::ev/name "use-library-component"
::ev/origin origin
:external-library (not= file-id current-file-id)
:is-variant (ctk/is-variant? component)})
(-> {::ev/name "use-library-component"
::ev/origin origin
:external-library (not= file-id current-file-id)
:is-variant (ctk/is-variant? component)}
(merge (meta it))))
(dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update {:ids [(:id new-shape)]})

View File

@ -658,7 +658,7 @@
[{:keys [attributes attributes-to-remove token shape-ids on-update-shape]}]
(ptk/reify ::apply-token
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
;; We do not allow to apply tokens while text editor is open.
;; The classic text editor sets :workspace-editor-state; the WASM text editor
;; does not, so we also check :workspace-local :edition for text shapes.
@ -704,10 +704,12 @@
type (:type token)]
(rx/concat
(rx/of
(st/emit! (ev/event {::ev/name "apply-tokens"
:type type
:applied-to attributes
:applied-to-variant any-variant?}))
(st/emit! (ev/event
(-> {::ev/name "apply-tokens"
:type type
:applied-to attributes
:applied-to-variant any-variant?}
(merge (meta it)))))
(dwu/start-undo-transaction undo-id)
(dwsh/update-shapes shape-ids (fn [shape]
(cond-> shape
@ -736,7 +738,7 @@
[{:keys [token shapes attr]}]
(ptk/reify ::apply-spacing-token-separated
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
(let [objects (dsh/lookup-page-objects state)
{:keys [attributes on-update-shape]}
@ -746,14 +748,17 @@
(group-by #(if (ctsl/any-layout-immediate-child? objects %) :frame-children :other) shapes)]
(rx/of
(apply-token {:attributes (or attr attributes)
:token token
:shape-ids (map :id other)
:on-update-shape on-update-shape})
(apply-token {:attributes ctt/spacing-margin-keys
:token token
:shape-ids (map :id frame-children)
:on-update-shape update-layout-item-margin}))))))
(-> (apply-token {:attributes (or attr attributes)
:token token
:shape-ids (map :id other)
:on-update-shape on-update-shape})
(with-meta (meta it)))
(-> (apply-token {:attributes ctt/spacing-margin-keys
:token token
:shape-ids (map :id frame-children)
:on-update-shape update-layout-item-margin})
(with-meta (meta it))))))))
(defn unapply-token
"Removes `attributes` that match `token` for `shape-ids`.
@ -775,7 +780,7 @@
[{:keys [token attrs shape-ids expand-with-children]}]
(ptk/reify ::on-toggle-token
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
(let [objects (dsh/lookup-page-objects state)
shapes (into [] (keep (d/getf objects)) shape-ids)
@ -812,15 +817,17 @@
(cond
(and (= (:type token) :spacing)
(nil? attrs))
(apply-spacing-token-separated {:token token
:attr attrs
:shapes shapes})
(-> (apply-spacing-token-separated {:token token
:attr attrs
:shapes shapes})
(with-meta (meta it)))
:else
(apply-token {:attributes (if (empty? attrs) attributes attrs)
:token token
:shape-ids shape-ids
:on-update-shape on-update-shape}))))))))
(-> (apply-token {:attributes (if (empty? attrs) attributes attrs)
:token token
:shape-ids shape-ids
:on-update-shape on-update-shape})
(with-meta (meta it))))))))))
(defn apply-token-on-selected
[color-operations token]

View File

@ -426,7 +426,8 @@
token))]
(rx/of (dch/commit-changes changes)
(ptk/data-event ::ev/event {::ev/name "create-token" :type token-type})))
(ptk/data-event ::ev/event (-> {::ev/name "create-token" :type token-type}
(merge (meta it))))))
(rx/of (create-token-with-set token)))))))
@ -454,7 +455,8 @@
id
token'))]
(rx/of (dch/commit-changes changes)
(ptk/data-event ::ev/event {::ev/name "edit-token" :type token-type})))))))
(ptk/data-event ::ev/event (-> {::ev/name "edit-token" :type token-type}
(merge (meta it))))))))))
(defn delete-token
[set-id token-id]
@ -475,7 +477,8 @@
(pcb/with-library-data data)
(pcb/set-token set-id token-id nil))]
(rx/of (dch/commit-changes changes)
(ptk/data-event ::ev/event {::ev/name "delete-token" :type token-type}))))))
(ptk/data-event ::ev/event (-> {::ev/name "delete-token" :type token-type}
(merge (meta it)))))))))
(defn bulk-delete-tokens
[set-id token-ids]

View File

@ -616,7 +616,7 @@
[ids {:keys [page-id trigger variant-id]}]
(ptk/reify ::combine-as-variants
ptk/WatchEvent
(watch [_ state stream]
(watch [it state stream]
(let [current-page (:current-page-id state)
combine
@ -665,7 +665,8 @@
(dwsh/relocate-shapes #{variant-id} common-parent index)
(dwt/update-dimensions [variant-id] :width (+ (:width rect) 60))
(dwt/update-dimensions [variant-id] :height (+ (:height rect) 60))
(ev/event {::ev/name "combine-as-variants" ::ev/origin trigger :number-of-combined (count ids)}))
(ev/event (-> {::ev/name "combine-as-variants" ::ev/origin trigger :number-of-combined (count ids)}
(merge (meta it)))))
;; NOTE: we need to schedule a commit into a
;; microtask for ensure that all the scheduled
@ -701,7 +702,7 @@
[shape {:keys [pos val] :as params}]
(ptk/reify ::variant-switch
ptk/WatchEvent
(watch [_ state _]
(watch [it state _]
(let [libraries (dsh/lookup-libraries state)
component-id (:component-id shape)
component (ctf/get-component libraries (:component-file shape) component-id :include-deleted? false)]
@ -735,20 +736,23 @@
(rx/empty))
(rx/of
(dwl/component-swap shape (:component-file shape) (:id nearest-comp) true)
(ev/event {::ev/name "variant-switch" ::ev/origin "workspace:design-tab"}))))))))))
(ev/event (-> {::ev/name "variant-switch" ::ev/origin "workspace:design-tab"}
(merge (meta it)))))))))))))
(defn variants-switch
"Switch each shape (that must be a variant copy head) for the closest one with the property value passed as parameter"
[{:keys [shapes] :as params}]
(ptk/reify ::variants-switch
ptk/WatchEvent
(watch [_ _ _]
(watch [it _ _]
(let [ids (into (d/ordered-set) d/xf:map-id shapes)
undo-id (js/Symbol)]
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(->> (rx/from shapes)
(rx/map #(variant-switch % params)))
(rx/map (fn [data]
(-> (variant-switch data params)
(with-meta (meta it))))))
(rx/of (dwu/commit-undo-transaction undo-id)
(dws/select-shapes ids)))))))

View File

@ -215,9 +215,6 @@
(let [current-file-id (:current-file-id state)]
;; Force persist before creating snapshot, otherwise we could loss changes
(->> (rx/concat
(rx/of (ptk/event ::ev/event {::ev/origin "plugins"
::ev/name "create-version"}))
(when (= file-id current-file-id)
(rx/of ::dwp/force-persist))
@ -246,20 +243,15 @@
(ptk/reify ::restore-version-from-plugins
ptk/WatchEvent
(watch [_ state _]
(let [team-id (:current-team-id state)]
(rx/concat
(rx/of (ev/event {::ev/name "restore-version-plugin"
:file-id file-id
:team-id team-id})
::dwp/force-persist)
(watch [_ _ _]
(rx/concat
(rx/of ::dwp/force-persist)
(->> (wait-for-persistence file-id id)
(rx/map #(initialize-version)))
(->> (wait-for-persistence file-id id)
(rx/map #(initialize-version)))
(->> (rx/of 1)
(rx/tap resolve)
(rx/ignore)))))))
(->> (rx/of 1)
(rx/tap resolve)
(rx/ignore))))))

View File

@ -273,6 +273,7 @@
(->> (dwm/upload-media-url name file-id url)
(rx/take 1)
(rx/map format/format-image)
(rx/tap #(st/emit! (se/event plugin-id "add-media")))
(rx/subs! resolve reject)))))))
:uploadMediaData
@ -289,6 +290,7 @@
:on-svg identity})
(rx/take 1)
(rx/map format/format-image)
(rx/tap #(st/emit! (se/event plugin-id "add-media")))
(rx/subs! resolve reject))))))
:group
@ -462,6 +464,7 @@
(conj acc (cg/generate-formatted-markup-code objects type resolved-shapes))))
[]))]
(st/emit! (se/event plugin-id "copy-inspect-code"))
(->> resolved-code (str/join "\n"))))))
:generateStyle
@ -508,6 +511,7 @@
(cg/generate-style-code
objects type shapes resolved-shapes {:with-prelude? prelude?}))))
[]))]
(st/emit! (se/event plugin-id "copy-inspect-style"))
(dm/str
(if prelude? (cg/prelude type) "")
(->> resolved-styles
@ -542,7 +546,8 @@
(fn []
(let [file-id (:current-file-id @st/state)
id (uuid/next)]
(st/emit! (dw/create-page {:page-id id :file-id file-id}))
(st/emit! (-> (dw/create-page {:page-id id :file-id file-id})
(se/add-event plugin-id)))
(page/page-proxy plugin-id file-id id)))
:openPage
@ -648,9 +653,10 @@
ids)]
(if valid?
(let [variant-id (uuid/next)]
(st/emit! (dwv/combine-as-variants
ids
{:trigger "plugin:combine-as-variants" :variant-id variant-id}))
(st/emit! (-> (dwv/combine-as-variants
ids
{:trigger "plugin:combine-as-variants" :variant-id variant-id})
(se/add-event plugin-id)))
(shape/shape-proxy plugin-id variant-id))
(u/not-valid plugin-id :shapes "One of the components is not on the same page or is already a variant")))))))

View File

@ -17,6 +17,7 @@
[app.plugins.parser :as parser]
[app.plugins.register :as r]
[app.plugins.shape :as shape]
[app.plugins.system-events :as se]
[app.plugins.user :as user]
[app.plugins.utils :as u]
[app.util.object :as obj]
@ -71,7 +72,13 @@
:else
(->> (rp/cmd! :update-comment {:id (:id data) :content content})
(rx/tap #(st/emit! (dc/retrieve-comment-threads file-id)))
(rx/subs! #(swap! data* assoc :content content))))))}
(rx/subs!
(fn []
(st/emit! (se/event plugin-id "update-comment"
:thread-id thread-id
:id (:id data)
:content-size (count content)))
(swap! data* assoc :content content)))))))}
;; Public methods
:remove
@ -87,7 +94,11 @@
:else
(->> (rp/cmd! :delete-comment {:id (:id data)})
(rx/tap #(st/emit! (dc/retrieve-comment-threads file-id)))
(rx/subs! #(resolve) reject)))))))))
(rx/subs!
(fn []
(st/emit! (se/event plugin-id "update-comment" :thread-id thread-id))
(resolve))
reject)))))))))
(defn comment-thread-proxy? [p]
(obj/type-of? p "CommentThreadProxy"))
@ -143,7 +154,8 @@
(u/not-valid plugin-id :resolved "Plugin doesn't have 'comment:write' permission")
:else
(do (st/emit! (dc/update-comment-thread (assoc @data* :is-resolved is-resolved)))
(do (st/emit! (-> (dc/update-comment-thread (assoc @data* :is-resolved is-resolved))
(se/add-event plugin-id)))
(swap! data* assoc :is-resolved is-resolved))))}
:findComments
@ -178,7 +190,13 @@
(js/Promise.
(fn [resolve reject]
(->> (rp/cmd! :create-comment {:thread-id (:id data) :content content})
(rx/subs! #(resolve (comment-proxy plugin-id file-id page-id (:id data) %)) reject))))))
(rx/subs!
(fn [result]
(st/emit! (se/event plugin-id "create-comment"
:thread-id (:id data)
:file-id file-id
:content-size (count content)))
(resolve (comment-proxy plugin-id file-id page-id (:id data) result))) reject))))))
:remove
(fn []
@ -194,4 +212,5 @@
:else
(js/Promise.
(fn [resolve]
(st/emit! (dc/delete-comment-thread-on-workspace {:id (:id data)} #(resolve)))))))))))
(st/emit! (-> (dc/delete-comment-thread-on-workspace {:id (:id data)} #(resolve))
(se/add-event plugin-id)))))))))))

View File

@ -22,6 +22,7 @@
[app.plugins.page :as page]
[app.plugins.parser :as parser]
[app.plugins.register :as r]
[app.plugins.system-events :as se]
[app.plugins.user :as user]
[app.plugins.utils :as u]
[app.util.http :as http]
@ -54,6 +55,7 @@
(do (swap! data assoc :label value :created-by "user")
(->> (rp/cmd! :update-file-snapshot {:id (:id @data) :label value})
(rx/take 1)
(rx/take #(st/emit! (se/event "rename-version" :file-id file-id)))
(rx/subs! identity)))))}
:createdBy
@ -78,7 +80,9 @@
:else
(let [version-id (get @data :id)]
(st/emit! (dwv/restore-version-from-plugin file-id version-id resolve reject)))))))
(st/emit!
(dwv/restore-version-from-plugin file-id version-id resolve reject)
(se/event plugin-id "restore-version" :file-id file-id)))))))
:remove
(fn []
@ -110,10 +114,12 @@
:label (ct/format-inst (:created-at @data) :localized-date)}]
(->> (rx/zip (rp/cmd! :get-team-users {:file-id file-id})
(rp/cmd! :update-file-snapshot params))
(rx/subs! (fn [[users data]]
(let [users (d/index-by :id users)]
(resolve (file-version-proxy plugin-id file-id users @data))))
reject))))))))))
(rx/subs!
(fn [[users data]]
(let [users (d/index-by :id users)]
(st/emit! (se/event plugin-id "pin-version" :file-id file-id))
(resolve (file-version-proxy plugin-id file-id users @data))))
reject))))))))))
(defn file-proxy? [p]
(obj/type-of? p "FileProxy"))
@ -220,7 +226,8 @@
:else
(let [page-id (uuid/next)]
(st/emit! (dw/create-page {:page-id page-id :file-id id}))
(st/emit! (-> (dw/create-page {:page-id page-id :file-id id})
(se/add-event plugin-id)))
(page/page-proxy plugin-id id page-id))))
:export
@ -269,6 +276,7 @@
:response-type :buffer}))))
(rx/take 1)
(rx/map #(js/Uint8Array. (:body %)))
(rx/tap #(st/emit! (se/event plugin-id "export-binary-files" :format format :type type)))
(rx/subs! resolve reject))))))))
:findVersions
(fn [criteria]
@ -315,7 +323,9 @@
(u/reject-not-valid reject :findVersions "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwv/create-version-from-plugins id label resolve reject)))))]
(st/emit!
(dwv/create-version-from-plugins id label resolve reject)
(se/event plugin-id "create-version" :file-id id)))))]
(-> (js/Promise.all #js [users-promise create-version-promise])
(.then
(fn [[users data]]

View File

@ -13,6 +13,7 @@
[app.main.data.workspace.shapes :as dwsh]
[app.main.store :as st]
[app.plugins.register :as r]
[app.plugins.system-events :as se]
[app.plugins.utils :as u]
[app.util.object :as obj]))
@ -186,7 +187,6 @@
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}}))))}
:topPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
@ -260,11 +260,16 @@
:else
(let [child-id (obj/get child "$id")
shape (u/locate-shape file-id page-id id)
child-shape (u/locate-shape file-id page-id child-id)
index
(if (and (u/natural-child-ordering? plugin-id) (not (ctl/reverse? shape)))
0
(count (:shapes shape)))]
(st/emit! (dwsh/relocate-shapes #{child-id} id index)))))
(st/emit!
(dwsh/relocate-shapes #{child-id} id index)
(se/event plugin-id "add-layout-element"
:type (:type child-shape)
:parent-type (:type shape))))))
:horizontalSizing
{:this true

View File

@ -16,7 +16,6 @@
[app.common.types.file :as ctf]
[app.common.types.typography :as ctt]
[app.common.uuid :as uuid]
[app.main.data.event :as ev]
[app.main.data.plugins :as dp]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.texts :as dwt]
@ -27,6 +26,7 @@
[app.plugins.parser :as parser]
[app.plugins.register :as r]
[app.plugins.shape :as shape]
[app.plugins.system-events :as se]
[app.plugins.text :as text]
[app.plugins.tokens :as tokens]
[app.plugins.utils :as u]
@ -164,7 +164,8 @@
(u/not-valid plugin-id :remove "Plugin doesn't have 'library:write' permission")
:else
(st/emit! (dwl/delete-color {:id id}))))
(st/emit! (-> (dwl/delete-color {:id id})
(se/add-event plugin-id)))))
:clone
(fn []
@ -176,7 +177,8 @@
(let [color-id (uuid/next)
color (-> (u/locate-library-color file-id id)
(assoc :id color-id))]
(st/emit! (dwl/add-color color {:rename? false}))
(st/emit! (-> (dwl/add-color color {:rename? false})
(se/add-event plugin-id)))
(lib-color-proxy plugin-id id color-id))))
:asFill
@ -309,7 +311,8 @@
:else
(let [typo (u/proxy->library-typography self)
value (dm/str (d/nilv (:path typo) "") " / " value)]
(st/emit! (dwl/rename-typography file-id id value)))))}
(st/emit! (-> (dwl/rename-typography file-id id value)
(se/add-event plugin-id))))))}
:path
{:this true
@ -488,7 +491,8 @@
(u/not-valid plugin-id :remove "Plugin doesn't have 'library:write' permission")
:else
(st/emit! (dwl/delete-typography {:id id}))))
(st/emit! (-> (dwl/delete-typography {:id id})
(se/add-event plugin-id)))))
:clone
(fn []
@ -500,7 +504,8 @@
(let [typo-id (uuid/next)
typo (-> (u/locate-library-typography file-id id)
(assoc :id typo-id))]
(st/emit! (dwl/add-typography typo false))
(st/emit! (-> (dwl/add-typography typo false)
(se/add-event plugin-id)))
(lib-typography-proxy plugin-id id typo-id))))
:applyToText
@ -662,13 +667,13 @@
:addVariant
(fn []
(st/emit!
(ev/event {::ev/name "add-new-variant" ::ev/origin "plugin:add-variant"})
(se/event plugin-id "add-new-variant")
(dwv/add-new-variant id)))
:addProperty
(fn []
(st/emit!
(ev/event {::ev/name "add-new-property" ::ev/origin "plugin:add-property"})
(se/event plugin-id "add-new-property")
(dwv/add-new-property id {:property-value "Value 1"})))
:removeProperty
@ -676,7 +681,7 @@
(if (not (nat-int? pos))
(u/not-valid plugin-id :pos pos)
(st/emit!
(ev/event {::ev/name "remove-property" ::ev/origin "plugin:remove-property"})
(se/event plugin-id "remove-property")
(dwv/remove-property id pos))))
:renameProperty
@ -759,7 +764,8 @@
:else
(let [id-ref (atom nil)]
(st/emit! (dwl/instantiate-component file-id id (gpt/point 0 0) {:id-ref id-ref :origin "plugin"}))
(st/emit! (-> (dwl/instantiate-component file-id id (gpt/point 0 0) {:id-ref id-ref :origin "plugin"})
(se/add-event plugin-id)))
(shape/shape-proxy plugin-id @id-ref))))
:getPluginData
@ -885,7 +891,7 @@
(when (and component
(not (ctk/is-variant? component)))
(st/emit!
(ev/event {::ev/name "transform-in-variant" ::ev/origin "plugin:transform-in-variant"})
(se/event plugin-id "transform-in-variant")
(dwv/transform-in-variant (:main-instance-id component))))))
:addVariant
@ -894,7 +900,7 @@
(when (and component
(ctk/is-variant? component))
(st/emit!
(ev/event {::ev/name "add-new-variant" ::ev/origin "plugin:add-variant-from-component"})
(se/event plugin-id "add-new-variant")
(dwv/add-new-variant (:main-instance-id component))))))
:setVariantProperty
@ -908,7 +914,7 @@
:else
(st/emit!
(ev/event {::ev/name "variant-edit-property-value" ::ev/origin "plugin:edit-property-value"})
(se/event plugin-id "variant-edit-property-value")
(dwv/update-property-value id pos value))))))
(defn library-proxy? [p]
@ -974,7 +980,8 @@
:else
(let [color-id (uuid/next)]
(st/emit! (dwl/add-color {:id color-id :name "Color" :color "#000000" :opacity 1} {:rename? false}))
(st/emit! (-> (dwl/add-color {:id color-id :name "Color" :color "#000000" :opacity 1} {:rename? false})
(se/add-event plugin-id)))
(lib-color-proxy plugin-id file-id color-id))))
:createTypography
@ -985,7 +992,8 @@
:else
(let [typography-id (uuid/next)]
(st/emit! (dwl/add-typography (ctt/make-typography {:id typography-id :name "Typography"}) false))
(st/emit! (-> (dwl/add-typography (ctt/make-typography {:id typography-id :name "Typography"}) false)
(se/add-event plugin-id)))
(lib-typography-proxy plugin-id file-id typography-id))))
:createComponent
@ -997,7 +1005,8 @@
:else
(let [id-ref (atom nil)
ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dwl/add-component id-ref ids))
(st/emit! (-> (dwl/add-component id-ref ids)
(se/add-event plugin-id)))
(lib-component-proxy plugin-id file-id @id-ref))))
;; Plugin data
@ -1127,4 +1136,5 @@
(rx/filter (ptk/type? ::dwl/attach-library-finished))
(rx/take 1)
(rx/subs! #(resolve (library-proxy plugin-id library-id)) reject))
(st/emit! (dwl/link-file-to-library file-id library-id))))))))))
(st/emit! (-> (dwl/link-file-to-library file-id library-id)
(se/add-event plugin-id)))))))))))

View File

@ -28,6 +28,7 @@
[app.plugins.register :as r]
[app.plugins.ruler-guides :as rg]
[app.plugins.shape :as shape]
[app.plugins.system-events :as se]
[app.plugins.utils :as u]
[app.util.object :as obj]
[beicon.v2.core :as rx]
@ -283,7 +284,9 @@
:else
(let [flow-id (uuid/next)]
(st/emit! (dwi/add-flow flow-id id name (obj/get frame "$id")))
(st/emit!
(dwi/add-flow flow-id id name (obj/get frame "$id"))
(se/event plugin-id "add-flow"))
(flow-proxy plugin-id file-id id flow-id))))
:removeFlow
@ -293,7 +296,9 @@
(u/not-valid plugin-id :removeFlow-flow flow)
:else
(st/emit! (dwi/remove-flow id (obj/get flow "$id")))))
(st/emit!
(dwi/remove-flow id (obj/get flow "$id"))
(se/event plugin-id "remove-flow"))))
:addRulerGuide
(fn [orientation value board]
@ -316,12 +321,13 @@
:else
(let [ruler-id (uuid/next)]
(st/emit!
(dwgu/update-guides
(d/without-nils
{:id ruler-id
:axis (parser/orientation->axis orientation)
:position value
:frame-id (when board (obj/get board "$id"))})))
(-> (dwgu/update-guides
(d/without-nils
{:id ruler-id
:axis (parser/orientation->axis orientation)
:position value
:frame-id (when board (obj/get board "$id"))}))
(se/add-event plugin-id)))
(rg/ruler-guide-proxy plugin-id file-id id ruler-id)))))
:removeRulerGuide
@ -335,7 +341,8 @@
:else
(let [guide (u/proxy->ruler-guide value)]
(st/emit! (dwgu/remove-guide guide)))))
(st/emit! (-> (dwgu/remove-guide guide)
(se/add-event plugin-id))))))
:addCommentThread
(fn [content position board]
@ -364,15 +371,15 @@
(js/Promise.
(fn [resolve]
(st/emit!
(dc/create-thread-on-workspace
{:file-id file-id
:page-id id
:position (gpt/point position)
:content content}
(fn [data]
(resolve (pc/comment-thread-proxy plugin-id file-id id data)))
false))))))))
(-> (dc/create-thread-on-workspace
{:file-id file-id
:page-id id
:position (gpt/point position)
:content content}
(fn [data]
(resolve (pc/comment-thread-proxy plugin-id file-id id data)))
false)
(se/add-event plugin-id)))))))))
:removeCommentThread
(fn [thread]

View File

@ -135,3 +135,7 @@
(= plugin-id mcp-plugin-id)
(let [{:keys [permissions]} (dm/get-in @registry [:data plugin-id])]
(contains? permissions permission))))
(defn get-plugin-data
[state plugin-id]
(get-in state [:profile :props :plugins :data plugin-id]))

View File

@ -13,6 +13,7 @@
[app.main.store :as st]
[app.plugins.format :as format]
[app.plugins.register :as r]
[app.plugins.system-events :as se]
[app.plugins.utils :as u]
[app.util.object :as obj]))
@ -55,7 +56,8 @@
:else
(let [board-id (when value (obj/get value "$id"))
guide (-> self u/proxy->ruler-guide)]
(st/emit! (dwgu/update-guides (assoc guide :frame-id board-id)))))))}
(st/emit! (-> (dwgu/update-guides (assoc guide :frame-id board-id))
(se/add-event plugin-id)))))))}
:orientation
{:this true
@ -92,9 +94,11 @@
(+ board-pos value))
value)]
(st/emit! (dwgu/update-guides (assoc guide :position position))))))}
(st/emit! (-> (dwgu/update-guides (assoc guide :position position))
(se/add-event plugin-id))))))}
:remove
(fn []
(let [guide (u/locate-ruler-guide file-id page-id id)]
(st/emit! (dwgu/remove-guide guide))))))
(st/emit! (-> (dwgu/remove-guide guide)
(se/add-event plugin-id)))))))

View File

@ -54,6 +54,7 @@
[app.plugins.parser :as parser]
[app.plugins.register :as r]
[app.plugins.ruler-guides :as rg]
[app.plugins.system-events :as se]
[app.plugins.text :as text]
[app.plugins.tokens :refer [applied-tokens-plugin->applied-tokens token-attr-plugin->token-attr token-attr?]]
[app.plugins.utils :as u]
@ -786,10 +787,8 @@
(when (ctl/grid-layout-immediate-child-id? objects id)
(grid/layout-cell-proxy plugin-id file-id page-id id))))}
;; Interactions
:interactions
{:this true
:get
@ -963,12 +962,17 @@
:else
(let [child-id (obj/get child "$id")
child-shape (u/locate-shape file-id page-id child-id)
is-reversed? (ctl/flex-layout? shape)
index
(if (or (not (u/natural-child-ordering? plugin-id)) is-reversed?)
0
(count (:shapes shape)))]
(st/emit! (dwsh/relocate-shapes #{child-id} id index))))))
(st/emit!
(dwsh/relocate-shapes #{child-id} id index)
(se/event plugin-id (if (ctl/any-layout? shape) "add-layout-element" "add-element")
:type (:type child-shape)
:parent-type (:type shape)))))))
:insertChild
(fn [index child]
@ -988,12 +992,17 @@
:else
(let [child-id (obj/get child "$id")
child-shape (u/locate-shape file-id page-id child-id)
is-reversed? (ctl/flex-layout? shape)
index
(if (or (not (u/natural-child-ordering? plugin-id)) is-reversed?)
(- (count (:shapes shape)) index)
index)]
(st/emit! (dwsh/relocate-shapes #{child-id} id index))))))
(st/emit!
(dwsh/relocate-shapes #{child-id} id index)
(se/event plugin-id (if (ctl/any-layout? shape) "add-layout-element" "add-element")
:type (:type child-shape)
:parent-type (:type shape)))))))
;; Only for frames
:addFlexLayout
@ -1007,7 +1016,9 @@
(u/not-valid plugin-id :addFlexLayout "Plugin doesn't have 'content:write' permission")
:else
(do (st/emit! (dwsl/create-layout-from-id id :flex :from-frame? true :calculate-params? false))
(do (st/emit!
(dwsl/create-layout-from-id id :flex :from-frame? true :calculate-params? false)
(se/event plugin-id "create-layout" :layout "flex"))
(flex/flex-layout-proxy plugin-id file-id page-id id)))))
:addGridLayout
@ -1022,6 +1033,7 @@
:else
(do (st/emit! (dwsl/create-layout-from-id id :grid :from-frame? true :calculate-params? false))
(se/event plugin-id "create-layout" :layout "grid")
(grid/grid-layout-proxy plugin-id file-id page-id id)))))
;; Make masks for groups
@ -1036,7 +1048,9 @@
(u/not-valid plugin-id :makeMask "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwg/mask-group #{id})))))
(st/emit!
(dwg/mask-group #{id})
(se/event plugin-id "create-shape" :type "mask")))))
:removeMask
(fn []
@ -1221,6 +1235,7 @@
(rx/map :body)
(rx/mapcat #(.arrayBuffer %))
(rx/map #(js/Uint8Array. %))
(rx/tap #(st/emit! (se/event plugin-id "export-shapes")))
(rx/subs! resolve reject)))))
@ -1249,6 +1264,7 @@
(rx/map :body))))
(rx/mapcat #(.arrayBuffer %))
(rx/map #(js/Uint8Array. %))
(rx/tap #(st/emit! (se/event plugin-id "export-shapes")))
(rx/subs! resolve reject)))))))))
;; Interactions
@ -1263,7 +1279,9 @@
:else
(let [index (-> (u/locate-shape file-id page-id id) (:interactions []) count)]
(st/emit! (dwi/add-interaction page-id id interaction))
(st/emit!
(dwi/add-interaction page-id id interaction)
(se/event plugin-id "add-interaction"))
(interaction-proxy plugin-id file-id page-id id index)))))
:removeInteraction
@ -1273,7 +1291,9 @@
(u/not-valid plugin-id :removeInteraction interaction)
:else
(st/emit! (dwi/remove-interaction {:id id} (obj/get interaction "$index")))))
(st/emit!
(dwi/remove-interaction {:id id} (obj/get interaction "$index"))
(se/event plugin-id "remove-interaction"))))
;; Ruler guides
:addRulerGuide
@ -1300,11 +1320,12 @@
board-pos (get frame axis)
position (+ board-pos value)]
(st/emit!
(dwgu/update-guides
{:id id
:axis axis
:position position
:frame-id id}))
(-> (dwgu/update-guides
{:id id
:axis axis
:position position
:frame-id id})
(se/add-event plugin-id)))
(rg/ruler-guide-proxy plugin-id file-id page-id id)))))
:removeRulerGuide
@ -1318,7 +1339,8 @@
:else
(let [guide (u/proxy->ruler-guide value)]
(st/emit! (dwgu/remove-guide guide)))))
(st/emit! (-> (dwgu/remove-guide guide)
(se/add-event plugin-id))))))
:tokens
{:this true
@ -1345,10 +1367,11 @@
(if (some #(not (token-attr? %)) kw-attrs)
(u/not-valid plugin-id :applyToken attrs)
(st/emit!
(dwta/toggle-token {:token token
:attrs kw-attrs
:shape-ids [id]
:expand-with-children false})))))}
(-> (dwta/toggle-token {:token token
:attrs kw-attrs
:shape-ids [id]
:expand-with-children false})
(se/add-event plugin-id))))))}
:isVariantHead
(fn []
@ -1374,7 +1397,8 @@
(let [shape (u/locate-shape file-id page-id id)
component (u/locate-library-component file-id (:component-id shape))]
(when (and component (ctk/is-variant? component))
(st/emit! (dwv/variants-switch {:shapes [shape] :pos pos :val value}))))))
(st/emit! (-> (dwv/variants-switch {:shapes [shape] :pos pos :val value})
(se/add-event plugin-id)))))))
:combineAsVariants
(fn [ids]
@ -1396,9 +1420,10 @@
(if valid?
(let [variant-id (uuid/next)]
(st/emit! (dwv/combine-as-variants
ids
{:trigger "plugin:combine-as-variants" :variant-id variant-id}))
(st/emit! (-> (dwv/combine-as-variants
ids
{:trigger "plugin:combine-as-variants" :variant-id variant-id})
(se/add-event plugin-id)))
(shape-proxy plugin-id variant-id))
(u/not-valid plugin-id :ids "One of the components is not on the same page or is already a variant"))))))

View File

@ -7,17 +7,34 @@
(ns app.plugins.system-events
(:require
[app.main.data.event :as ev]
[app.main.store :as st]))
[app.main.store :as st]
[app.plugins.register :as r]))
;; Formats an event from the plugin system
(defn event
[plugin-id name & {:as props}]
(let [plugin-data (get-in @st/state [:profile :props :plugins :data plugin-id])]
(if (= plugin-id r/mcp-plugin-id)
(-> props
(assoc ::ev/name name)
(assoc ::ev/origin "plugin")
(assoc ::ev/context
{:plugin-name (:name plugin-data)
:plugin-url (:url plugin-data)})
(ev/event))))
(assoc ::ev/origin "mcp")
(ev/event))
(let [plugin-data (r/get-plugin-data @st/state plugin-id)]
(-> props
(assoc ::ev/name name)
(assoc ::ev/origin "plugin")
(assoc ::ev/context
{:plugin-name (:name plugin-data)
:plugin-url (:url plugin-data)})
(ev/event)))))
(defn add-event
[event plugin-id]
(let [plugin-data (r/get-plugin-data @st/state plugin-id)]
(with-meta
event
(if (= plugin-id r/mcp-plugin-id)
{::ev/origin "mcp"}
{::ev/origin "plugin"
::ev/context {:plugin-name (:name plugin-data)
:plugin-url (:url plugin-data)}}))))

View File

@ -17,6 +17,7 @@
[app.main.data.workspace.tokens.application :as dwta]
[app.main.data.workspace.tokens.library-edit :as dwtl]
[app.main.store :as st]
[app.plugins.system-events :as se]
[app.plugins.utils :as u]
[app.util.object :as obj]
[clojure.datafy :refer [datafy]]
@ -80,10 +81,11 @@
(if (some #(not (token-attr? %)) attrs)
(u/not-valid plugin-id :applyToSelected attrs)
(st/emit!
(dwta/toggle-token {:token token
:attrs (into #{} (map token-attr-plugin->token-attr) attrs)
:shape-ids shape-ids
:expand-with-children false})))))
(-> (dwta/toggle-token {:token token
:attrs (into #{} (map token-attr-plugin->token-attr) attrs)
:shape-ids shape-ids
:expand-with-children false})
(se/add-event plugin-id))))))
(defn- get-resolved-value
[token tokens-tree]
@ -123,7 +125,8 @@
(ctob/get-tokens set-id)))
:set
(fn [_ value]
(st/emit! (dwtl/update-token set-id id {:name value})))}
(st/emit! (-> (dwtl/update-token set-id id {:name value})
(se/add-event plugin-id))))}
:type
{:this true
@ -173,7 +176,8 @@
:schema cfo/schema:token-description
:set
(fn [_ value]
(st/emit! (dwtl/update-token set-id id {:description value})))}
(st/emit! (-> (dwtl/update-token set-id id {:description value})
(se/add-event :plugin-id))))}
:duplicate
(fn []
@ -186,12 +190,14 @@
token' (ctob/make-token (-> (datafy token)
(dissoc :id
:modified-at)))]
(st/emit! (dwtl/create-token set-id token'))
(st/emit! (-> (dwtl/create-token set-id token')
(se/add-event plugin-id)))
(token-proxy plugin-id file-id set-id (:id token'))))
:remove
(fn []
(st/emit! (dwtl/delete-token set-id id)))
(st/emit! (-> (dwtl/delete-token set-id id)
(se/add-event plugin-id))))
:applyToShapes
{:enumerable false
@ -323,7 +329,8 @@
(get resolved-tokens (:name token))]
(if resolved-value
(do (st/emit! (dwtl/create-token id token))
(do (st/emit! (-> (dwtl/create-token id token)
(se/add-event plugin-id)))
(token-proxy plugin-id file-id id (:id token)))
(do (u/not-valid plugin-id :addToken (str errors))
nil))))}