From 5233654da2e750c758a04034a0c67f3033815888 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 10 Jun 2024 11:32:35 +0200 Subject: [PATCH] :sparkles: Add support for plugin data into penpot objects --- common/src/app/common/files/changes.cljc | 42 +++ .../src/app/common/files/changes_builder.cljc | 31 ++ common/src/app/common/schema.cljc | 3 + common/src/app/common/types/color.cljc | 4 +- common/src/app/common/types/container.cljc | 4 +- common/src/app/common/types/file.cljc | 4 +- common/src/app/common/types/page.cljc | 4 +- common/src/app/common/types/shape.cljc | 4 +- common/src/app/common/types/typography.cljc | 4 +- frontend/src/app/main/data/workspace.cljs | 29 ++ .../src/app/main/ui/workspace/plugins.cljs | 16 +- frontend/src/app/plugins.cljs | 3 +- frontend/src/app/plugins/api.cljs | 45 +-- frontend/src/app/plugins/events.cljs | 20 +- frontend/src/app/plugins/file.cljs | 84 ++++- frontend/src/app/plugins/flex.cljs | 14 +- frontend/src/app/plugins/grid.cljs | 15 +- frontend/src/app/plugins/library.cljs | 343 ++++++++++++++++-- frontend/src/app/plugins/page.cljs | 80 +++- frontend/src/app/plugins/shape.cljs | 129 +++++-- frontend/src/app/plugins/user.cljs | 18 +- frontend/src/app/plugins/viewport.cljs | 6 +- 22 files changed, 764 insertions(+), 138 deletions(-) diff --git a/common/src/app/common/files/changes.cljc b/common/src/app/common/files/changes.cljc index a82ab947c0..3df8b9d895 100644 --- a/common/src/app/common/files/changes.cljc +++ b/common/src/app/common/files/changes.cljc @@ -133,6 +133,18 @@ [:id ::sm/uuid] [:name :string]]] + [:mod-plugin-data + [:map {:title "ModPagePluginData"} + [:type [:= :mod-plugin-data]] + [:object-type [::sm/one-of #{:file :page :shape :color :typography :component}]] + ;; It's optional because files don't need the id for type :file + [:object-id {:optional true} [:maybe ::sm/uuid]] + ;; Only needed in type shape + [:page-id {:optional true} [:maybe ::sm/uuid]] + [:namespace :keyword] + [:key :string] + [:value [:maybe :string]]]] + [:del-page [:map {:title "DelPageChange"} [:type [:= :del-page]] @@ -586,6 +598,36 @@ [data {:keys [id name]}] (d/update-in-when data [:pages-index id] assoc :name name)) +(defmethod process-change :mod-plugin-data + [data {:keys [object-type object-id page-id namespace key value]}] + + (when (and (= object-type :shape) (nil? page-id)) + (ex/raise :type :internal :hint "update for shapes needs a page-id")) + + (letfn [(update-fn + [data] + (if (some? value) + (assoc-in data [:plugin-data namespace key] value) + (update-in data [:plugin-data namespace] (fnil dissoc {}) key)))] + (case object-type + :file + (update-fn data) + + :page + (d/update-in-when data [:pages-index object-id :options] update-fn) + + :shape + (d/update-in-when data [:pages-index page-id :objects object-id] update-fn) + + :color + (d/update-in-when data [:colors object-id] update-fn) + + :typography + (d/update-in-when data [:typographies object-id] update-fn) + + :component + (d/update-in-when data [:components object-id] update-fn)))) + (defmethod process-change :del-page [data {:keys [id]}] (ctpl/delete-page data id)) diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc index 865ed2fa73..0540cfcdfd 100644 --- a/common/src/app/common/files/changes_builder.cljc +++ b/common/src/app/common/files/changes_builder.cljc @@ -201,6 +201,37 @@ (update :undo-changes conj {:type :mod-page :id (:id page) :name (:name page)}) (apply-changes-local))) +(defn mod-plugin-data + ([changes namespace key value] + (mod-plugin-data changes :file nil nil namespace key value)) + ([changes type id namespace key value] + (mod-plugin-data changes type id nil namespace key value)) + ([changes type id page-id namespace key value] + (let [data (::file-data (meta changes)) + old-val + (case type + :file + (get-in data [:plugin-data namespace key]) + + :page + (get-in data [:pages-index id :options :plugin-data namespace key]) + + :shape + (get-in data [:pages-index page-id :objects id :plugin-data namespace key]) + + :color + (get-in data [:colors id :plugin-data namespace key]) + + :typography + (get-in data [:typographies id :plugin-data namespace key]) + + :component + (get-in data [:components id :plugin-data namespace key]))] + (-> changes + (update :redo-changes conj {:type :mod-plugin-data :object-type type :object-id id :page-id page-id :namespace namespace :key key :value value}) + (update :undo-changes conj {:type :mod-plugin-data :object-type type :object-id id :page-id page-id :namespace namespace :key key :value old-val}) + (apply-changes-local))))) + (defn del-page [changes page] (-> changes diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index b1e743f643..a74b88f1f0 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -658,6 +658,9 @@ ::oapi/format "uri" ::oapi/decode (comp u/uri str/trim)}}) +(def! ::plugin-data + [:map-of {:gen/max 5} :string :string]) + ;; ---- PREDICATES (def valid-safe-number? diff --git a/common/src/app/common/types/color.cljc b/common/src/app/common/types/color.cljc index 111343d58d..c8a1ef67bd 100644 --- a/common/src/app/common/types/color.cljc +++ b/common/src/app/common/types/color.cljc @@ -84,7 +84,9 @@ [:ref-id {:optional true} ::sm/uuid] [:ref-file {:optional true} ::sm/uuid] [:gradient {:optional true} [:maybe ::gradient]] - [:image {:optional true} [:maybe ::image-color]]] + [:image {:optional true} [:maybe ::image-color]] + [:plugin-data {:optional true} + [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]] [::sm/contains-any {:strict true} [:color :gradient :image]]]) (sm/define! ::recent-color diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index c4166508ad..0313870b66 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -35,7 +35,9 @@ [:path {:optional true} [:maybe :string]] [:modified-at {:optional true} ::sm/inst] [:objects {:optional true} - [:map-of {:gen/max 10} ::sm/uuid :map]]]) + [:map-of {:gen/max 10} ::sm/uuid :map]] + [:plugin-data {:optional true} + [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]) (def check-container! (sm/check-fn ::container)) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index d12b759dfd..c8c7fbe432 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -57,7 +57,9 @@ [:typographies {:optional true} [:map-of {:gen/max 2} ::sm/uuid ::cty/typography]] [:media {:optional true} - [:map-of {:gen/max 5} ::sm/uuid ::media-object]]]) + [:map-of {:gen/max 5} ::sm/uuid ::media-object]] + [:plugin-data {:optional true} + [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]) (def check-file-data! (sm/check-fn ::data)) diff --git a/common/src/app/common/types/page.cljc b/common/src/app/common/types/page.cljc index 0b20389288..3e31540dbc 100644 --- a/common/src/app/common/types/page.cljc +++ b/common/src/app/common/types/page.cljc @@ -43,7 +43,9 @@ [:flows {:optional true} [:vector {:gen/max 2} ::flow]] [:guides {:optional true} - [:map-of {:gen/max 2} ::sm/uuid ::guide]]]]]) + [:map-of {:gen/max 2} ::sm/uuid ::guide]] + [:plugin-data {:optional true} + [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]]]) (def check-page-guide! (sm/check-fn ::guide)) diff --git a/common/src/app/common/types/shape.cljc b/common/src/app/common/types/shape.cljc index a489133293..1a4ed092a8 100644 --- a/common/src/app/common/types/shape.cljc +++ b/common/src/app/common/types/shape.cljc @@ -186,7 +186,9 @@ [:vector {:gen/max 1} ::ctss/shadow]] [:blur {:optional true} ::ctsb/blur] [:grow-type {:optional true} - [::sm/one-of #{:auto-width :auto-height :fixed}]]]) + [::sm/one-of #{:auto-width :auto-height :fixed}]] + [:plugin-data {:optional true} + [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]) (sm/define! ::group-attrs [:map {:title "GroupAttrs"} diff --git a/common/src/app/common/types/typography.cljc b/common/src/app/common/types/typography.cljc index 6e216020a8..2e5a08b93a 100644 --- a/common/src/app/common/types/typography.cljc +++ b/common/src/app/common/types/typography.cljc @@ -29,7 +29,9 @@ [:letter-spacing :string] [:text-transform :string] [:modified-at {:optional true} ::sm/inst] - [:path {:optional true} [:maybe :string]]]) + [:path {:optional true} [:maybe :string]] + [:plugin-data {:optional true} + [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]) (def check-typography! (sm/check-fn ::typography)) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index c2ce35228c..fd4fa64c99 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -568,6 +568,35 @@ (rx/of (dch/commit-changes changes)))))) +(defn set-plugin-data + ([file-id type namespace key value] + (set-plugin-data file-id type nil nil namespace key value)) + ([file-id type id namespace key value] + (set-plugin-data file-id type id nil namespace key value)) + ([file-id type id page-id namespace key value] + (dm/assert! (contains? #{:file :page :shape :color :typography :component} type)) + (dm/assert! (or (nil? id) (uuid? id))) + (dm/assert! (or (nil? page-id) (uuid? page-id))) + (dm/assert! (uuid? file-id)) + (dm/assert! (keyword? namespace)) + (dm/assert! (string? key)) + (dm/assert! (or (nil? value) (string? value))) + + (ptk/reify ::set-file-plugin-data + ptk/WatchEvent + (watch [it state _] + (let [file-data + (if (= file-id (:current-file-id state)) + (:workspace-data state) + (get-in state [:workspace-libraries file-id :data])) + + changes + (-> (pcb/empty-changes it) + (pcb/with-file-data file-data) + (assoc :file-id file-id) + (pcb/mod-plugin-data type id page-id namespace key value))] + (rx/of (dch/commit-changes changes))))))) + (declare purge-page) (declare go-to-file) diff --git a/frontend/src/app/main/ui/workspace/plugins.cljs b/frontend/src/app/main/ui/workspace/plugins.cljs index a6eca7efd3..7cca4d86c4 100644 --- a/frontend/src/app/main/ui/workspace/plugins.cljs +++ b/frontend/src/app/main/ui/workspace/plugins.cljs @@ -73,14 +73,14 @@ (defn open-plugin! [{:keys [plugin-id name description host code icon permissions]}] (.ɵloadPlugin - js/window #js - {:pluginId plugin-id - :name name - :description description - :host host - :code code - :icon icon - :permissions (apply array permissions)})) + js/window + #js {:pluginId plugin-id + :name name + :description description + :host host + :code code + :icon icon + :permissions (apply array permissions)})) (mf/defc plugin-management-dialog {::mf/register modal/components diff --git a/frontend/src/app/plugins.cljs b/frontend/src/app/plugins.cljs index 8bd6d5ebbe..ac48f5c080 100644 --- a/frontend/src/app/plugins.cljs +++ b/frontend/src/app/plugins.cljs @@ -26,5 +26,4 @@ (fn [] (when (features/active-feature? @st/state "plugins/runtime") (when-let [init-runtime (obj/get global "initPluginsRuntime")] - (let [context (api/create-context)] - (init-runtime context)))))))) + (init-runtime (fn [plugin-id] (api/create-context plugin-id))))))))) diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index 66bd6ee750..4d682593cc 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -35,7 +35,7 @@ ;; PLUGINS PUBLIC API - The plugins will able to access this functions ;; (defn create-shape - [type] + [plugin-id type] (let [page-id (:current-page-id @st/state) page (dm/get-in @st/state [:workspace-data :pages-index page-id]) shape (cts/setup-shape {:type type @@ -46,13 +46,13 @@ (cb/with-objects (:objects page)) (cb/add-object shape))] (st/emit! (ch/commit-changes changes)) - (shape/shape-proxy (:id shape)))) + (shape/shape-proxy plugin-id (:id shape)))) -(deftype PenpotContext [] +(deftype PenpotContext [$plugin] Object (addListener [_ type callback] - (events/add-listener type callback)) + (events/add-listener type $plugin callback)) (removeListener [_ listener-id] @@ -60,17 +60,17 @@ (getViewport [_] - (viewport/create-proxy)) + (viewport/create-proxy $plugin)) (getFile [_] - (file/file-proxy (:current-file-id @st/state))) + (file/file-proxy $plugin (:current-file-id @st/state))) (getPage [_] (let [file-id (:current-file-id @st/state) page-id (:current-page-id @st/state)] - (page/page-proxy file-id page-id))) + (page/page-proxy $plugin file-id page-id))) (getSelected [_] @@ -80,11 +80,11 @@ (getSelectedShapes [_] (let [selection (get-in @st/state [:workspace-local :selected])] - (apply array (sequence (map shape/shape-proxy) selection)))) + (apply array (sequence (map (partial shape/shape-proxy $plugin)) selection)))) (getRoot [_] - (shape/shape-proxy uuid/zero)) + (shape/shape-proxy $plugin uuid/zero)) (getTheme [_] @@ -95,7 +95,7 @@ (getCurrentUser [_] - (user/current-user-proxy (:session-id @st/state))) + (user/current-user-proxy $plugin (:session-id @st/state))) (getActiveUsers [_] @@ -103,7 +103,7 @@ (->> (:workspace-presence @st/state) (vals) (remove #(= (:id %) (:session-id @st/state))) - (map #(user/active-user-proxy (:id %)))))) + (map #(user/active-user-proxy $plugin (:id %)))))) (uploadMediaUrl [_ name url] @@ -122,7 +122,7 @@ id (uuid/next) ids (into #{} (map #(obj/get % "$id")) shapes)] (st/emit! (dwg/group-shapes id ids)) - (shape/shape-proxy file-id page-id id))) + (shape/shape-proxy $plugin file-id page-id id))) (ungroup [_ group & rest] @@ -132,15 +132,15 @@ (createFrame [_] - (create-shape :frame)) + (create-shape $plugin :frame)) (createRectangle [_] - (create-shape :rect)) + (create-shape $plugin :rect)) (createEllipse [_] - (create-shape :circle)) + (create-shape $plugin :circle)) (createPath [_] @@ -156,7 +156,7 @@ (cb/with-objects (:objects page)) (cb/add-object shape))] (st/emit! (ch/commit-changes changes)) - (shape/shape-proxy (:id shape)))) + (shape/shape-proxy $plugin (:id shape)))) (createText [_ text] @@ -172,7 +172,7 @@ (cb/with-objects (:objects page)) (cb/add-object shape))] (st/emit! (ch/commit-changes changes)) - (shape/shape-proxy file-id page-id (:id shape)))) + (shape/shape-proxy $plugin file-id page-id (:id shape)))) (createShapeFromSvg [_ svg-string] @@ -181,7 +181,7 @@ file-id (:current-file-id @st/state) page-id (:current-page-id @st/state)] (st/emit! (dwm/create-svg-shape id "svg" svg-string (gpt/point 0 0))) - (shape/shape-proxy file-id page-id id)))) + (shape/shape-proxy $plugin file-id page-id id)))) (createBoolean [_ bool-type shapes] (let [ids (into #{} (map #(obj/get % "$id")) shapes) @@ -190,14 +190,15 @@ (if (contains? cts/bool-types bool-type) (let [id-ret (atom nil)] (st/emit! (dwb/create-bool bool-type ids {:id-ret id-ret})) - (shape/shape-proxy @id-ret)) + (shape/shape-proxy $plugin @id-ret)) (utils/display-not-valid :bool-shape bool-type))))) (defn create-context - [] + [plugin-id] (cr/add-properties! - (PenpotContext.) + (PenpotContext. plugin-id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "root" :get #(.getRoot ^js %)} {:name "currentFile" :get #(.getFile ^js %)} {:name "currentPage" :get #(.getPage ^js %)} @@ -205,4 +206,4 @@ {:name "viewport" :get #(.getViewport ^js %)} {:name "currentUser" :get #(.getCurrentUser ^js %)} {:name "activeUsers" :get #(.getActiveUsers ^js %)} - {:name "library" :get (fn [_] (library/library-subcontext))})) + {:name "library" :get (fn [_] (library/library-subcontext plugin-id))})) diff --git a/frontend/src/app/plugins/events.cljs b/frontend/src/app/plugins/events.cljs index 6405c8a7b8..eada65d67c 100644 --- a/frontend/src/app/plugins/events.cljs +++ b/frontend/src/app/plugins/events.cljs @@ -15,7 +15,7 @@ (defmulti handle-state-change (fn [type _] type)) (defmethod handle-state-change "finish" - [_ old-val new-val] + [_ _ old-val new-val] (let [old-file-id (:current-file-id old-val) new-file-id (:current-file-id new-val)] (if (and (some? old-file-id) (nil? new-file-id)) @@ -23,7 +23,7 @@ ::not-changed))) (defmethod handle-state-change "filechange" - [_ old-val new-val] + [_ plugin-id old-val new-val] (let [old-file (:workspace-file old-val) new-file (:workspace-file new-val) old-data (:workspace-data old-val) @@ -31,10 +31,10 @@ (if (and (identical? old-file new-file) (identical? old-data new-data)) ::not-changed - (file/file-proxy (:id new-file))))) + (file/file-proxy plugin-id (:id new-file))))) (defmethod handle-state-change "pagechange" - [_ old-val new-val] + [_ plugin-id old-val new-val] (let [file-id (:current-file-id new-val) old-page-id (:current-page-id old-val) new-page-id (:current-page-id new-val) @@ -42,10 +42,10 @@ new-page (dm/get-in new-val [:workspace-data :pages-index new-page-id])] (if (identical? old-page new-page) ::not-changed - (page/page-proxy file-id new-page-id)))) + (page/page-proxy plugin-id file-id new-page-id)))) (defmethod handle-state-change "selectionchange" - [_ old-val new-val] + [_ _ old-val new-val] (let [old-selection (get-in old-val [:workspace-local :selected]) new-selection (get-in new-val [:workspace-local :selected])] (if (identical? old-selection new-selection) @@ -53,7 +53,7 @@ (apply array (map str new-selection))))) (defmethod handle-state-change "themechange" - [_ old-val new-val] + [_ _ old-val new-val] (let [old-theme (get-in old-val [:profile :theme]) new-theme (get-in new-val [:profile :theme])] (if (identical? old-theme new-theme) @@ -63,17 +63,17 @@ new-theme)))) (defmethod handle-state-change :default - [_ _ _] + [_ _ _ _] ::not-changed) (defn add-listener - [type callback] + [type plugin-id callback] (let [key (js/Symbol) callback (gf/debounce callback 10)] (add-watch st/state key (fn [_ _ old-val new-val] - (let [result (handle-state-change type old-val new-val)] + (let [result (handle-state-change type plugin-id old-val new-val)] (when (not= ::not-changed result) (callback result))))) diff --git a/frontend/src/app/plugins/file.cljs b/frontend/src/app/plugins/file.cljs index ec9b843bfc..1fd74e29ee 100644 --- a/frontend/src/app/plugins/file.cljs +++ b/frontend/src/app/plugins/file.cljs @@ -9,15 +9,84 @@ (:require [app.common.data.macros :as dm] [app.common.record :as crc] + [app.main.data.workspace :as dw] + [app.main.store :as st] [app.plugins.page :as page] - [app.plugins.utils :refer [locate-file proxy->file]] + [app.plugins.utils :as u] [app.util.object :as obj])) -(deftype FileProxy [$id] +(deftype FileProxy [$plugin $id] Object (getPages [_] - (let [file (locate-file $id)] - (apply array (sequence (map #(page/page-proxy $id %)) (dm/get-in file [:data :pages])))))) + (let [file (u/locate-file $id)] + (apply array (sequence (map #(page/page-proxy $plugin $id %)) (dm/get-in file [:data :pages]))))) + + ;; Plugin data + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + :else + (let [file (u/proxy->file self)] + (dm/get-in file [:data :plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :file-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $id :file (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [file (u/proxy->file self)] + (apply array (keys (dm/get-in file [:data :plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :file-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + :else + (let [file (u/proxy->file self)] + (dm/get-in file [:data :plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + + (cond + (not (string? namespace)) + (u/display-not-valid :file-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :file-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $id :file (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :file-plugin-data-namespace namespace) + + :else + (let [file (u/proxy->file self)] + (apply array (keys (dm/get-in file [:data :plugin-data (keyword "shared" namespace)]))))))) (crc/define-properties! FileProxy @@ -25,16 +94,17 @@ :get (fn [] (str "FileProxy"))}) (defn file-proxy - [id] + [plugin-id id] (crc/add-properties! - (FileProxy. id) + (FileProxy. plugin-id id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "id" :get #(dm/str (obj/get % "$id"))} {:name "name" - :get #(-> % proxy->file :name)} + :get #(-> % u/proxy->file :name)} {:name "pages" :get #(.getPages ^js %)})) diff --git a/frontend/src/app/plugins/flex.cljs b/frontend/src/app/plugins/flex.cljs index cf47cd7f87..e379fcba4a 100644 --- a/frontend/src/app/plugins/flex.cljs +++ b/frontend/src/app/plugins/flex.cljs @@ -17,7 +17,7 @@ [app.util.object :as obj] [potok.v2.core :as ptk])) -(deftype FlexLayout [$file $page $id] +(deftype FlexLayout [$plugin $file $page $id] Object (remove [_] @@ -30,9 +30,10 @@ (ptk/data-event :layout/update {:ids [$id]}))))) (defn flex-layout-proxy - [file-id page-id id] - (-> (FlexLayout. file-id page-id id) + [plugin-id file-id page-id id] + (-> (FlexLayout. plugin-id file-id page-id id) (crc/add-properties! + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "$page" :enumerable false :get (constantly page-id)} @@ -148,12 +149,13 @@ (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) -(deftype LayoutChildProxy [$file $page $id]) +(deftype LayoutChildProxy [$plugin $file $page $id]) (defn layout-child-proxy - [file-id page-id id] - (-> (LayoutChildProxy. file-id page-id id) + [plugin-id file-id page-id id] + (-> (LayoutChildProxy. plugin-id file-id page-id id) (crc/add-properties! + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "$page" :enumerable false :get (constantly page-id)} diff --git a/frontend/src/app/plugins/grid.cljs b/frontend/src/app/plugins/grid.cljs index e254e815ea..8b0f49ab9f 100644 --- a/frontend/src/app/plugins/grid.cljs +++ b/frontend/src/app/plugins/grid.cljs @@ -23,7 +23,7 @@ js/Object (apply array (->> tracks (map utils/to-js))))) -(deftype GridLayout [$file $page $id] +(deftype GridLayout [$plugin $file $page $id] Object (addRow @@ -75,9 +75,10 @@ (ptk/data-event :layout/update {:ids [$id]}))))) (defn grid-layout-proxy - [file-id page-id id] - (-> (GridLayout. file-id page-id id) + [plugin-id file-id page-id id] + (-> (GridLayout. plugin-id file-id page-id id) (crc/add-properties! + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "$page" :enumerable false :get (constantly page-id)} @@ -164,7 +165,6 @@ (when (us/safe-int? value) (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))} - {:name "topPadding" :get #(-> % proxy->shape :layout-padding :p1) :set @@ -197,17 +197,18 @@ (when (us/safe-int? value) (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) -(deftype GridCellProxy [$file $page $id]) +(deftype GridCellProxy [$plugin $file $page $id]) (defn layout-cell-proxy - [file-id page-id id] + [plugin-id file-id page-id id] (letfn [(locate-cell [_] (let [shape (locate-shape file-id page-id id) parent (locate-shape file-id page-id (:parent-id shape))] (ctl/get-cell-by-shape-id parent id)))] - (-> (GridCellProxy. file-id page-id id) + (-> (GridCellProxy. plugin-id file-id page-id id) (crc/add-properties! + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "$page" :enumerable false :get (constantly page-id)} diff --git a/frontend/src/app/plugins/library.cljs b/frontend/src/app/plugins/library.cljs index b588e61a24..6f6f87ed38 100644 --- a/frontend/src/app/plugins/library.cljs +++ b/frontend/src/app/plugins/library.cljs @@ -16,6 +16,7 @@ [app.common.types.color :as ctc] [app.common.types.typography :as ctt] [app.common.uuid :as uuid] + [app.main.data.workspace :as dw] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.texts :as dwt] [app.main.store :as st] @@ -26,7 +27,7 @@ (declare lib-color-proxy) (declare lib-typography-proxy) -(deftype LibraryColorProxy [$file $id] +(deftype LibraryColorProxy [$plugin $file $id] Object (remove @@ -39,7 +40,7 @@ color (-> (u/locate-library-color $file $id) (assoc :id color-id))] (st/emit! (dwl/add-color color {:rename? false})) - (lib-color-proxy $id color-id))) + (lib-color-proxy $plugin $id color-id))) (asFill [_] (let [color (u/locate-library-color $file $id)] @@ -63,15 +64,87 @@ :stroke-color-ref-id $id :stroke-image (:image color) :stroke-style :solid - :stroke-alignment :inner}))))) + :stroke-alignment :inner})))) + + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :color-plugin-data-key key) + + :else + (let [color (u/proxy->library-color self)] + (dm/get-in color [:plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not= $file (:current-file-id @st/state)) + (u/display-not-valid :color-edit-non-local-library $file) + + (not (string? key)) + (u/display-not-valid :color-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :color-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :color $id (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [color (u/proxy->library-color self)] + (apply array (keys (dm/get-in color [:plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :color-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :color-plugin-data-key key) + + :else + (let [color (u/proxy->library-color self)] + (dm/get-in color [:plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + (cond + (not= $file (:current-file-id @st/state)) + (u/display-not-valid :color-edit-non-local-library $file) + + (not (string? namespace)) + (u/display-not-valid :color-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :color-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :color-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :color $id (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :color-plugin-data-namespace namespace) + + :else + (let [color (u/proxy->library-color self)] + (apply array (keys (dm/get-in color [:plugin-data (keyword "shared" namespace)]))))))) (defn lib-color-proxy - [file-id id] + [plugin-id file-id id] (assert (uuid? file-id)) (assert (uuid? id)) (cr/add-properties! - (LibraryColorProxy. file-id id) + (LibraryColorProxy. plugin-id file-id id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} @@ -139,7 +212,7 @@ (st/emit! (dwl/update-color color file-id))) (u/display-not-valid :library-color-image value))))})) -(deftype LibraryTypographyProxy [$file $id] +(deftype LibraryTypographyProxy [$plugin $file $id] Object (remove [_] @@ -151,7 +224,7 @@ typo (-> (u/locate-library-typography $file $id) (assoc :id typo-id))] (st/emit! (dwl/add-typography typo false)) - (lib-typography-proxy $id typo-id))) + (lib-typography-proxy $plugin $id typo-id))) (applyToText [_ shape] @@ -162,15 +235,88 @@ (applyToTextRange [_ _shape _from _to] ;; TODO - )) + ) + + ;; PLUGIN DATA + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :typography-plugin-data-key key) + + :else + (let [typography (u/proxy->library-typography self)] + (dm/get-in typography [:plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not= $file (:current-file-id @st/state)) + (u/display-not-valid :typography-edit-non-local-library $file) + + (not (string? key)) + (u/display-not-valid :typography-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :typography-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :typography $id (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [typography (u/proxy->library-typography self)] + (apply array (keys (dm/get-in typography [:plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :typography-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :typography-plugin-data-key key) + + :else + (let [typography (u/proxy->library-typography self)] + (dm/get-in typography [:plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + (cond + (not= $file (:current-file-id @st/state)) + (u/display-not-valid :typography-edit-non-local-library $file) + + (not (string? namespace)) + (u/display-not-valid :typography-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :typography-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :typography-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :typography $id (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :typography-plugin-data-namespace namespace) + + :else + (let [typography (u/proxy->library-typography self)] + (apply array (keys (dm/get-in typography [:plugin-data (keyword "shared" namespace)]))))))) (defn lib-typography-proxy - [file-id id] + [plugin-id file-id id] (assert (uuid? file-id)) (assert (uuid? id)) (cr/add-properties! - (LibraryTypographyProxy. file-id id) + (LibraryTypographyProxy. plugin-id file-id id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "id" :get (fn [_] (dm/str id))} @@ -285,7 +431,7 @@ (st/emit! (dwl/update-typography typo file-id))) (u/display-not-valid :library-typography-text-transform value)))})) -(deftype LibraryComponentProxy [$file $id] +(deftype LibraryComponentProxy [$plugin $file $id] Object (remove @@ -296,15 +442,87 @@ [_] (let [id-ref (atom nil)] (st/emit! (dwl/instantiate-component $file $id (gpt/point 0 0) {:id-ref id-ref})) - (shapes/shape-proxy @id-ref)))) + (shapes/shape-proxy $plugin @id-ref))) + + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :component-plugin-data-key key) + + :else + (let [component (u/proxy->library-component self)] + (dm/get-in component [:plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not= $file (:current-file-id @st/state)) + (u/display-not-valid :component-edit-non-local-library $file) + + (not (string? key)) + (u/display-not-valid :component-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :component-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :component $id (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [component (u/proxy->library-component self)] + (apply array (keys (dm/get-in component [:plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :component-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :component-plugin-data-key key) + + :else + (let [component (u/proxy->library-component self)] + (dm/get-in component [:plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + (cond + (not= $file (:current-file-id @st/state)) + (u/display-not-valid :component-edit-non-local-library $file) + + (not (string? namespace)) + (u/display-not-valid :component-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :component-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :component-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :component $id (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :component-plugin-data-namespace namespace) + + :else + (let [component (u/proxy->library-component self)] + (apply array (keys (dm/get-in component [:plugin-data (keyword "shared" namespace)]))))))) (defn lib-component-proxy - [file-id id] + [plugin-id file-id id] (assert (uuid? file-id)) (assert (uuid? id)) (cr/add-properties! - (LibraryComponentProxy. file-id id) + (LibraryComponentProxy. plugin-id file-id id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "id" :get (fn [_] (dm/str id))} @@ -329,34 +547,102 @@ (st/emit! (dwl/rename-component id value))) (u/display-not-valid :library-component-path value)))})) -(deftype Library [$id] +(deftype Library [$plugin $id] Object (createColor [_] (let [color-id (uuid/next)] (st/emit! (dwl/add-color {:id color-id :name "Color" :color "#000000" :opacity 1} {:rename? false})) - (lib-color-proxy $id color-id))) + (lib-color-proxy $plugin $id color-id))) (createTypography [_] (let [typography-id (uuid/next)] (st/emit! (dwl/add-typography (ctt/make-typography {:id typography-id :name "Typography"}) false)) - (lib-typography-proxy $id typography-id))) + (lib-typography-proxy $plugin $id typography-id))) (createComponent [_ shapes] (let [id-ref (atom nil) ids (into #{} (map #(obj/get % "$id")) shapes)] (st/emit! (dwl/add-component id-ref ids)) - (lib-component-proxy $id @id-ref)))) + (lib-component-proxy $plugin $id @id-ref))) + + ;; Plugin data + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + :else + (let [file (u/proxy->file self)] + (dm/get-in file [:data :plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :file-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $id :file (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [file (u/proxy->file self)] + (apply array (keys (dm/get-in file [:data :plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :file-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + :else + (let [file (u/proxy->file self)] + (dm/get-in file [:data :plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + + (cond + (not (string? namespace)) + (u/display-not-valid :file-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :file-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :file-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $id :file (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :file-plugin-data-namespace namespace) + + :else + (let [file (u/proxy->file self)] + (apply array (keys (dm/get-in file [:data :plugin-data (keyword "shared" namespace)]))))))) (defn library-proxy - [file-id] + [plugin-id file-id] (assert (uuid? file-id) "File id not valid") (cr/add-properties! - (Library. file-id) + (Library. plugin-id file-id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "id" @@ -369,14 +655,14 @@ :get (fn [_] (let [file (u/locate-file file-id) - colors (->> file :data :colors keys (map #(lib-color-proxy file-id %)))] + colors (->> file :data :colors keys (map #(lib-color-proxy plugin-id file-id %)))] (apply array colors)))} {:name "typographies" :get (fn [_] (let [file (u/locate-file file-id) - typographies (->> file :data :typographies keys (map #(lib-typography-proxy file-id %)))] + typographies (->> file :data :typographies keys (map #(lib-typography-proxy plugin-id file-id %)))] (apply array typographies)))} {:name "components" @@ -388,10 +674,10 @@ :components (remove (comp :deleted second)) (map first) - (map #(lib-component-proxy file-id %)))] + (map #(lib-component-proxy plugin-id file-id %)))] (apply array components)))})) -(deftype PenpotLibrarySubcontext [] +(deftype PenpotLibrarySubcontext [$plugin] Object (find [_ _name]) @@ -399,14 +685,15 @@ (find [_])) (defn library-subcontext - [] + [plugin-id] (cr/add-properties! - (PenpotLibrarySubcontext.) + (PenpotLibrarySubcontext. plugin-id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "local" :get (fn [_] - (library-proxy (:current-file-id @st/state)))} + (library-proxy plugin-id (:current-file-id @st/state)))} {:name "connected" :get (fn [_] (let [libraries (get @st/state :workspace-libraries)] - (apply array (->> libraries vals (map library-proxy)))))})) + (apply array (->> libraries keys (map (partial library-proxy plugin-id))))))})) diff --git a/frontend/src/app/plugins/page.cljs b/frontend/src/app/plugins/page.cljs index 4e3140264d..35c1a9dd59 100644 --- a/frontend/src/app/plugins/page.cljs +++ b/frontend/src/app/plugins/page.cljs @@ -17,23 +17,90 @@ [app.plugins.utils :as u] [app.util.object :as obj])) -(deftype PageProxy [$file $id] +(deftype PageProxy [$plugin $file $id] Object (getShapeById [_ shape-id] (let [shape-id (uuid/uuid shape-id)] - (shape/shape-proxy $file $id shape-id))) + (shape/shape-proxy $plugin $file $id shape-id))) (getRoot [_] - (shape/shape-proxy $file $id uuid/zero)) + (shape/shape-proxy $plugin $file $id uuid/zero)) (findShapes [_] ;; Returns a lazy (iterable) of all available shapes (when (and (some? $file) (some? $id)) (let [page (u/locate-page $file $id)] - (apply array (sequence (map shape/shape-proxy) (keys (:objects page)))))))) + (apply array (sequence (map (partial shape/shape-proxy $plugin)) (keys (:objects page))))))) + + ;; Plugin data + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :page-plugin-data-key key) + + :else + (let [page (u/proxy->page self)] + (dm/get-in page [:options :plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not (string? key)) + (u/display-not-valid :page-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :page-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :page $id (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [page (u/proxy->page self)] + (apply array (keys (dm/get-in page [:options :plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :page-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :page-plugin-data-key key) + + :else + (let [page (u/proxy->page self)] + (dm/get-in page [:options :plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + + (cond + (not (string? namespace)) + (u/display-not-valid :page-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :page-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :page-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :page $id (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :page-plugin-data-namespace namespace) + + :else + (let [page (u/proxy->page self)] + (apply array (keys (dm/get-in page [:options :plugin-data (keyword "shared" namespace)]))))))) (crc/define-properties! PageProxy @@ -41,9 +108,10 @@ :get (fn [] (str "PageProxy"))}) (defn page-proxy - [file-id id] + [plugin-id file-id id] (crc/add-properties! - (PageProxy. file-id id) + (PageProxy. plugin-id file-id id) + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index a22bbab69c..81ad46bbb2 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -9,6 +9,7 @@ (:require [app.common.colors :as clr] [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.files.helpers :as cfh] [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] @@ -20,7 +21,7 @@ [app.common.types.shape.layout :as ctl] [app.common.types.shape.radius :as ctsr] [app.common.uuid :as uuid] - [app.main.data.workspace :as udw] + [app.main.data.workspace :as dw] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.selection :as dws] [app.main.data.workspace.shape-layout :as dwsl] @@ -61,23 +62,90 @@ (dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs}) (dwt/current-text-values {:shape shape :attrs txt/text-node-attrs}))) -(deftype ShapeProxy [$file $page $id] +(deftype ShapeProxy [$plugin $file $page $id] Object (resize [_ width height] - (st/emit! (udw/update-dimensions [$id] :width width) - (udw/update-dimensions [$id] :height height))) + (st/emit! (dw/update-dimensions [$id] :width width) + (dw/update-dimensions [$id] :height height))) (clone [_] (let [ret-v (atom nil)] (st/emit! (dws/duplicate-shapes #{$id} :change-selection? false :return-ref ret-v)) - (shape-proxy (deref ret-v)))) + (shape-proxy $plugin (deref ret-v)))) (remove [_] (st/emit! (dwsh/delete-shapes #{$id}))) + ;; Plugin data + (getPluginData + [self key] + (cond + (not (string? key)) + (u/display-not-valid :shape-plugin-data-key key) + + :else + (let [shape (u/proxy->shape self)] + (dm/get-in shape [:plugin-data (keyword "plugin" (str $plugin)) key])))) + + (setPluginData + [_ key value] + (cond + (not (string? key)) + (u/display-not-valid :shape-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :shape-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :shape $id $page (keyword "plugin" (str $plugin)) key value)))) + + (getPluginDataKeys + [self] + (let [shape (u/proxy->shape self)] + (apply array (keys (dm/get-in shape [:plugin-data (keyword "plugin" (str $plugin))]))))) + + (getSharedPluginData + [self namespace key] + (cond + (not (string? namespace)) + (u/display-not-valid :shape-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :shape-plugin-data-key key) + + :else + (let [shape (u/proxy->shape self)] + (dm/get-in shape [:plugin-data (keyword "shared" namespace) key])))) + + (setSharedPluginData + [_ namespace key value] + + (cond + (not (string? namespace)) + (u/display-not-valid :shape-plugin-data-namespace namespace) + + (not (string? key)) + (u/display-not-valid :shape-plugin-data-key key) + + (and (some? value) (not (string? value))) + (u/display-not-valid :shape-plugin-data value) + + :else + (st/emit! (dw/set-plugin-data $file :shape $id $page (keyword "shared" namespace) key value)))) + + (getSharedPluginDataKeys + [self namespace] + (cond + (not (string? namespace)) + (u/display-not-valid :shape-plugin-data-namespace namespace) + + :else + (let [shape (u/proxy->shape self)] + (apply array (keys (dm/get-in shape [:plugin-data (keyword "shared" namespace)])))))) + ;; Only for frames + groups + booleans (getChildren [_] @@ -85,7 +153,7 @@ (if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) (apply array (->> (u/locate-shape $file $page $id) :shapes - (map #(shape-proxy $file $page %)))) + (map #(shape-proxy $plugin $file $page %)))) (u/display-not-valid :getChildren (:type shape))))) (appendChild @@ -93,7 +161,7 @@ (let [shape (u/locate-shape $file $page $id)] (if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) (let [child-id (obj/get child "$id")] - (st/emit! (udw/relocate-shapes #{child-id} $id 0))) + (st/emit! (dw/relocate-shapes #{child-id} $id 0))) (u/display-not-valid :appendChild (:type shape))))) (insertChild @@ -101,7 +169,7 @@ (let [shape (u/locate-shape $file $page $id)] (if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) (let [child-id (obj/get child "$id")] - (st/emit! (udw/relocate-shapes #{child-id} $id index))) + (st/emit! (dw/relocate-shapes #{child-id} $id index))) (u/display-not-valid :insertChild (:type shape))))) ;; Only for frames @@ -110,7 +178,7 @@ (let [shape (u/locate-shape $file $page $id)] (if (cfh/frame-shape? shape) (do (st/emit! (dwsl/create-layout-from-id $id :flex :from-frame? true :calculate-params? false)) - (grid/grid-layout-proxy $file $page $id)) + (grid/grid-layout-proxy $plugin $file $page $id)) (u/display-not-valid :addFlexLayout (:type shape))))) (addGridLayout @@ -118,7 +186,7 @@ (let [shape (u/locate-shape $file $page $id)] (if (cfh/frame-shape? shape) (do (st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false)) - (grid/grid-layout-proxy $file $page $id)) + (grid/grid-layout-proxy $plugin $file $page $id)) (u/display-not-valid :addGridLayout (:type shape))))) ;; Make masks for groups @@ -142,6 +210,14 @@ (let [shape (u/locate-shape $file $page $id)] (if (cfh/path-shape? shape) (upf/format-path (:content shape)) + (u/display-not-valid :makeMask (:type shape))))) + + ;; Text shapes + (getRange + [_ _from _to] + (let [shape (u/locate-shape $file $page $id)] + (if (cfh/text-shape? shape) + nil ;; TODO (u/display-not-valid :makeMask (:type shape)))))) (crc/define-properties! @@ -150,20 +226,21 @@ :get (fn [] (str "ShapeProxy"))}) (defn shape-proxy - ([id] - (shape-proxy (:current-file-id @st/state) (:current-page-id @st/state) id)) + ([plugin-id id] + (shape-proxy plugin-id (:current-file-id @st/state) (:current-page-id @st/state) id)) - ([page-id id] - (shape-proxy (:current-file-id @st/state) page-id id)) + ([plugin-id page-id id] + (shape-proxy plugin-id (:current-file-id @st/state) page-id id)) - ([file-id page-id id] + ([plugin-id file-id page-id id] (assert (uuid? file-id)) (assert (uuid? page-id)) (assert (uuid? id)) (let [data (u/locate-shape file-id page-id id)] - (-> (ShapeProxy. file-id page-id id) + (-> (ShapeProxy. plugin-id file-id page-id id) (crc/add-properties! + {:name "$plugin" :enumerable false :get (constantly plugin-id)} {:name "$id" :enumerable false :get (constantly id)} {:name "$file" :enumerable false :get (constantly file-id)} {:name "$page" :enumerable false :get (constantly page-id)} @@ -332,14 +409,14 @@ :set (fn [self value] (let [id (obj/get self "$id")] - (st/emit! (udw/update-position id {:x value}))))} + (st/emit! (dw/update-position id {:x value}))))} {:name "y" :get #(-> % u/proxy->shape :y) :set (fn [self value] (let [id (obj/get self "$id")] - (st/emit! (udw/update-position id {:y value}))))} + (st/emit! (dw/update-position id {:y value}))))} {:name "parentX" :get (fn [self] @@ -353,7 +430,7 @@ parent-id (-> self u/proxy->shape :parent-id) parent (u/locate-shape (obj/get self "$file") (obj/get self "$page") parent-id) parent-x (:x parent)] - (st/emit! (udw/update-position id {:x (+ parent-x value)}))))} + (st/emit! (dw/update-position id {:x (+ parent-x value)}))))} {:name "parentY" :get (fn [self] @@ -368,7 +445,7 @@ parent-id (-> self u/proxy->shape :parent-id) parent (u/locate-shape (obj/get self "$file") (obj/get self "$page") parent-id) parent-y (:y parent)] - (st/emit! (udw/update-position id {:y (+ parent-y value)}))))} + (st/emit! (dw/update-position id {:y (+ parent-y value)}))))} {:name "frameX" :get (fn [self] @@ -383,7 +460,7 @@ frame-id (-> self u/proxy->shape :frame-id) frame (u/locate-shape (obj/get self "$file") (obj/get self "$page") frame-id) frame-x (:x frame)] - (st/emit! (udw/update-position id {:x (+ frame-x value)}))))} + (st/emit! (dw/update-position id {:x (+ frame-x value)}))))} {:name "frameY" :get (fn [self] @@ -398,7 +475,7 @@ frame-id (-> self u/proxy->shape :frame-id) frame (u/locate-shape (obj/get self "$file") (obj/get self "$page") frame-id) frame-y (:y frame)] - (st/emit! (udw/update-position id {:y (+ frame-y value)}))))} + (st/emit! (dw/update-position id {:y (+ frame-y value)}))))} {:name "width" :get #(-> % u/proxy->shape :width)} @@ -437,7 +514,7 @@ id (obj/get self "$id") objects (u/locate-objects file-id page-id)] (when (ctl/any-layout-immediate-child-id? objects id) - (flex/layout-child-proxy file-id page-id id))))} + (flex/layout-child-proxy plugin-id file-id page-id id))))} {:name "layoutCell" :get @@ -447,7 +524,7 @@ id (obj/get self "$id") objects (u/locate-objects file-id page-id)] (when (ctl/grid-layout-immediate-child-id? objects id) - (grid/layout-cell-proxy file-id page-id id))))}) + (grid/layout-cell-proxy plugin-id file-id page-id id))))}) (cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data)) (crc/add-properties! @@ -465,7 +542,7 @@ page-id (obj/get self "$page") id (obj/get self "$id")] (when (= :grid layout) - (grid/grid-layout-proxy file-id page-id id))))} + (grid/grid-layout-proxy plugin-id file-id page-id id))))} {:name "flex" :get @@ -475,7 +552,7 @@ page-id (obj/get self "$page") id (obj/get self "$id")] (when (= :flex layout) - (flex/flex-layout-proxy file-id page-id id))))} + (flex/flex-layout-proxy plugin-id file-id page-id id))))} {:name "guides" :get #(-> % u/proxy->shape :grids u/array-to-js) diff --git a/frontend/src/app/plugins/user.cljs b/frontend/src/app/plugins/user.cljs index b7556ecbf8..eb199f5a6b 100644 --- a/frontend/src/app/plugins/user.cljs +++ b/frontend/src/app/plugins/user.cljs @@ -11,14 +11,18 @@ [app.plugins.utils :as u] [app.util.object :as obj])) -(deftype CurrentUserProxy [$session]) -(deftype ActiveUserProxy [$session]) +(deftype CurrentUserProxy [$plugin $session]) +(deftype ActiveUserProxy [$plugin $session]) (defn add-user-properties [user-proxy] - (let [session-id (obj/get user-proxy "$session")] + (let [plugin-id (obj/get user-proxy "$plugin") + session-id (obj/get user-proxy "$session")] (crc/add-properties! user-proxy + {:name "$plugin" :enumerable false :get (constantly plugin-id)} + {:name "$session" :enumerable false :get (constantly session-id)} + {:name "id" :get (fn [_] (-> (u/locate-profile session-id) :id str))} @@ -35,13 +39,13 @@ :get (fn [_] (str session-id))}))) (defn current-user-proxy - [session-id] - (-> (CurrentUserProxy. session-id) + [plugin-id session-id] + (-> (CurrentUserProxy. plugin-id session-id) (add-user-properties))) (defn active-user-proxy - [session-id] - (-> (ActiveUserProxy. session-id) + [plugin-id session-id] + (-> (ActiveUserProxy. plugin-id session-id) (add-user-properties) (crc/add-properties! {:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point u/to-js))} diff --git a/frontend/src/app/plugins/viewport.cljs b/frontend/src/app/plugins/viewport.cljs index 656a65674c..8859f6197a 100644 --- a/frontend/src/app/plugins/viewport.cljs +++ b/frontend/src/app/plugins/viewport.cljs @@ -16,7 +16,7 @@ [app.main.store :as st] [app.util.object :as obj])) -(deftype ViewportProxy [] +(deftype ViewportProxy [$plugin] Object (zoomIntoView [_ shapes] (let [ids @@ -33,9 +33,9 @@ :get (fn [] (str "ViewportProxy"))}) (defn create-proxy - [] + [plugin-id] (crc/add-properties! - (ViewportProxy.) + (ViewportProxy. plugin-id) {:name "center" :get (fn [_]