Add support for plugin data into penpot objects

This commit is contained in:
alonso.torres 2024-06-10 11:32:35 +02:00 committed by Andrey Antukh
parent 4d4a3a512d
commit 5233654da2
22 changed files with 764 additions and 138 deletions

View file

@ -133,6 +133,18 @@
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string]]] [: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 [:del-page
[:map {:title "DelPageChange"} [:map {:title "DelPageChange"}
[:type [:= :del-page]] [:type [:= :del-page]]
@ -586,6 +598,36 @@
[data {:keys [id name]}] [data {:keys [id name]}]
(d/update-in-when data [:pages-index id] assoc :name 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 (defmethod process-change :del-page
[data {:keys [id]}] [data {:keys [id]}]
(ctpl/delete-page data id)) (ctpl/delete-page data id))

View file

@ -201,6 +201,37 @@
(update :undo-changes conj {:type :mod-page :id (:id page) :name (:name page)}) (update :undo-changes conj {:type :mod-page :id (:id page) :name (:name page)})
(apply-changes-local))) (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 (defn del-page
[changes page] [changes page]
(-> changes (-> changes

View file

@ -658,6 +658,9 @@
::oapi/format "uri" ::oapi/format "uri"
::oapi/decode (comp u/uri str/trim)}}) ::oapi/decode (comp u/uri str/trim)}})
(def! ::plugin-data
[:map-of {:gen/max 5} :string :string])
;; ---- PREDICATES ;; ---- PREDICATES
(def valid-safe-number? (def valid-safe-number?

View file

@ -84,7 +84,9 @@
[:ref-id {:optional true} ::sm/uuid] [:ref-id {:optional true} ::sm/uuid]
[:ref-file {:optional true} ::sm/uuid] [:ref-file {:optional true} ::sm/uuid]
[:gradient {:optional true} [:maybe ::gradient]] [: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/contains-any {:strict true} [:color :gradient :image]]])
(sm/define! ::recent-color (sm/define! ::recent-color

View file

@ -35,7 +35,9 @@
[:path {:optional true} [:maybe :string]] [:path {:optional true} [:maybe :string]]
[:modified-at {:optional true} ::sm/inst] [:modified-at {:optional true} ::sm/inst]
[:objects {:optional true} [: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! (def check-container!
(sm/check-fn ::container)) (sm/check-fn ::container))

View file

@ -57,7 +57,9 @@
[:typographies {:optional true} [:typographies {:optional true}
[:map-of {:gen/max 2} ::sm/uuid ::cty/typography]] [:map-of {:gen/max 2} ::sm/uuid ::cty/typography]]
[:media {:optional true} [: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! (def check-file-data!
(sm/check-fn ::data)) (sm/check-fn ::data))

View file

@ -43,7 +43,9 @@
[:flows {:optional true} [:flows {:optional true}
[:vector {:gen/max 2} ::flow]] [:vector {:gen/max 2} ::flow]]
[:guides {:optional true} [: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! (def check-page-guide!
(sm/check-fn ::guide)) (sm/check-fn ::guide))

View file

@ -186,7 +186,9 @@
[:vector {:gen/max 1} ::ctss/shadow]] [:vector {:gen/max 1} ::ctss/shadow]]
[:blur {:optional true} ::ctsb/blur] [:blur {:optional true} ::ctsb/blur]
[:grow-type {:optional true} [: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 (sm/define! ::group-attrs
[:map {:title "GroupAttrs"} [:map {:title "GroupAttrs"}

View file

@ -29,7 +29,9 @@
[:letter-spacing :string] [:letter-spacing :string]
[:text-transform :string] [:text-transform :string]
[:modified-at {:optional true} ::sm/inst] [: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! (def check-typography!
(sm/check-fn ::typography)) (sm/check-fn ::typography))

View file

@ -568,6 +568,35 @@
(rx/of (dch/commit-changes changes)))))) (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 purge-page)
(declare go-to-file) (declare go-to-file)

View file

@ -73,8 +73,8 @@
(defn open-plugin! (defn open-plugin!
[{:keys [plugin-id name description host code icon permissions]}] [{:keys [plugin-id name description host code icon permissions]}]
(.ɵloadPlugin (.ɵloadPlugin
js/window #js js/window
{:pluginId plugin-id #js {:pluginId plugin-id
:name name :name name
:description description :description description
:host host :host host

View file

@ -26,5 +26,4 @@
(fn [] (fn []
(when (features/active-feature? @st/state "plugins/runtime") (when (features/active-feature? @st/state "plugins/runtime")
(when-let [init-runtime (obj/get global "initPluginsRuntime")] (when-let [init-runtime (obj/get global "initPluginsRuntime")]
(let [context (api/create-context)] (init-runtime (fn [plugin-id] (api/create-context plugin-id)))))))))
(init-runtime context))))))))

View file

@ -35,7 +35,7 @@
;; PLUGINS PUBLIC API - The plugins will able to access this functions ;; PLUGINS PUBLIC API - The plugins will able to access this functions
;; ;;
(defn create-shape (defn create-shape
[type] [plugin-id 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
@ -46,13 +46,13 @@
(cb/with-objects (:objects page)) (cb/with-objects (:objects page))
(cb/add-object shape))] (cb/add-object shape))]
(st/emit! (ch/commit-changes changes)) (st/emit! (ch/commit-changes changes))
(shape/shape-proxy (:id shape)))) (shape/shape-proxy plugin-id (:id shape))))
(deftype PenpotContext [] (deftype PenpotContext [$plugin]
Object Object
(addListener (addListener
[_ type callback] [_ type callback]
(events/add-listener type callback)) (events/add-listener type $plugin callback))
(removeListener (removeListener
[_ listener-id] [_ listener-id]
@ -60,17 +60,17 @@
(getViewport (getViewport
[_] [_]
(viewport/create-proxy)) (viewport/create-proxy $plugin))
(getFile (getFile
[_] [_]
(file/file-proxy (:current-file-id @st/state))) (file/file-proxy $plugin (:current-file-id @st/state)))
(getPage (getPage
[_] [_]
(let [file-id (:current-file-id @st/state) (let [file-id (:current-file-id @st/state)
page-id (:current-page-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 (getSelected
[_] [_]
@ -80,11 +80,11 @@
(getSelectedShapes (getSelectedShapes
[_] [_]
(let [selection (get-in @st/state [:workspace-local :selected])] (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 (getRoot
[_] [_]
(shape/shape-proxy uuid/zero)) (shape/shape-proxy $plugin uuid/zero))
(getTheme (getTheme
[_] [_]
@ -95,7 +95,7 @@
(getCurrentUser (getCurrentUser
[_] [_]
(user/current-user-proxy (:session-id @st/state))) (user/current-user-proxy $plugin (:session-id @st/state)))
(getActiveUsers (getActiveUsers
[_] [_]
@ -103,7 +103,7 @@
(->> (:workspace-presence @st/state) (->> (:workspace-presence @st/state)
(vals) (vals)
(remove #(= (:id %) (:session-id @st/state))) (remove #(= (:id %) (:session-id @st/state)))
(map #(user/active-user-proxy (:id %)))))) (map #(user/active-user-proxy $plugin (:id %))))))
(uploadMediaUrl (uploadMediaUrl
[_ name url] [_ name url]
@ -122,7 +122,7 @@
id (uuid/next) id (uuid/next)
ids (into #{} (map #(obj/get % "$id")) shapes)] ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dwg/group-shapes id ids)) (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 (ungroup
[_ group & rest] [_ group & rest]
@ -132,15 +132,15 @@
(createFrame (createFrame
[_] [_]
(create-shape :frame)) (create-shape $plugin :frame))
(createRectangle (createRectangle
[_] [_]
(create-shape :rect)) (create-shape $plugin :rect))
(createEllipse (createEllipse
[_] [_]
(create-shape :circle)) (create-shape $plugin :circle))
(createPath (createPath
[_] [_]
@ -156,7 +156,7 @@
(cb/with-objects (:objects page)) (cb/with-objects (:objects page))
(cb/add-object shape))] (cb/add-object shape))]
(st/emit! (ch/commit-changes changes)) (st/emit! (ch/commit-changes changes))
(shape/shape-proxy (:id shape)))) (shape/shape-proxy $plugin (:id shape))))
(createText (createText
[_ text] [_ text]
@ -172,7 +172,7 @@
(cb/with-objects (:objects page)) (cb/with-objects (:objects page))
(cb/add-object shape))] (cb/add-object shape))]
(st/emit! (ch/commit-changes changes)) (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 (createShapeFromSvg
[_ svg-string] [_ svg-string]
@ -181,7 +181,7 @@
file-id (:current-file-id @st/state) file-id (:current-file-id @st/state)
page-id (:current-page-id @st/state)] page-id (:current-page-id @st/state)]
(st/emit! (dwm/create-svg-shape id "svg" svg-string (gpt/point 0 0))) (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] (createBoolean [_ bool-type shapes]
(let [ids (into #{} (map #(obj/get % "$id")) shapes) (let [ids (into #{} (map #(obj/get % "$id")) shapes)
@ -190,14 +190,15 @@
(if (contains? cts/bool-types bool-type) (if (contains? cts/bool-types bool-type)
(let [id-ret (atom nil)] (let [id-ret (atom nil)]
(st/emit! (dwb/create-bool bool-type ids {:id-ret id-ret})) (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))))) (utils/display-not-valid :bool-shape bool-type)))))
(defn create-context (defn create-context
[] [plugin-id]
(cr/add-properties! (cr/add-properties!
(PenpotContext.) (PenpotContext. plugin-id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "root" :get #(.getRoot ^js %)} {:name "root" :get #(.getRoot ^js %)}
{:name "currentFile" :get #(.getFile ^js %)} {:name "currentFile" :get #(.getFile ^js %)}
{:name "currentPage" :get #(.getPage ^js %)} {:name "currentPage" :get #(.getPage ^js %)}
@ -205,4 +206,4 @@
{:name "viewport" :get #(.getViewport ^js %)} {:name "viewport" :get #(.getViewport ^js %)}
{:name "currentUser" :get #(.getCurrentUser ^js %)} {:name "currentUser" :get #(.getCurrentUser ^js %)}
{:name "activeUsers" :get #(.getActiveUsers ^js %)} {:name "activeUsers" :get #(.getActiveUsers ^js %)}
{:name "library" :get (fn [_] (library/library-subcontext))})) {:name "library" :get (fn [_] (library/library-subcontext plugin-id))}))

View file

@ -15,7 +15,7 @@
(defmulti handle-state-change (fn [type _] type)) (defmulti handle-state-change (fn [type _] type))
(defmethod handle-state-change "finish" (defmethod handle-state-change "finish"
[_ old-val new-val] [_ _ old-val new-val]
(let [old-file-id (:current-file-id old-val) (let [old-file-id (:current-file-id old-val)
new-file-id (:current-file-id new-val)] new-file-id (:current-file-id new-val)]
(if (and (some? old-file-id) (nil? new-file-id)) (if (and (some? old-file-id) (nil? new-file-id))
@ -23,7 +23,7 @@
::not-changed))) ::not-changed)))
(defmethod handle-state-change "filechange" (defmethod handle-state-change "filechange"
[_ old-val new-val] [_ plugin-id old-val new-val]
(let [old-file (:workspace-file old-val) (let [old-file (:workspace-file old-val)
new-file (:workspace-file new-val) new-file (:workspace-file new-val)
old-data (:workspace-data old-val) old-data (:workspace-data old-val)
@ -31,10 +31,10 @@
(if (and (identical? old-file new-file) (if (and (identical? old-file new-file)
(identical? old-data new-data)) (identical? old-data new-data))
::not-changed ::not-changed
(file/file-proxy (:id new-file))))) (file/file-proxy plugin-id (:id new-file)))))
(defmethod handle-state-change "pagechange" (defmethod handle-state-change "pagechange"
[_ old-val new-val] [_ plugin-id old-val new-val]
(let [file-id (:current-file-id new-val) (let [file-id (:current-file-id new-val)
old-page-id (:current-page-id old-val) old-page-id (:current-page-id old-val)
new-page-id (:current-page-id new-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])] new-page (dm/get-in new-val [:workspace-data :pages-index new-page-id])]
(if (identical? old-page new-page) (if (identical? old-page new-page)
::not-changed ::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" (defmethod handle-state-change "selectionchange"
[_ old-val new-val] [_ _ old-val new-val]
(let [old-selection (get-in old-val [:workspace-local :selected]) (let [old-selection (get-in old-val [:workspace-local :selected])
new-selection (get-in new-val [:workspace-local :selected])] new-selection (get-in new-val [:workspace-local :selected])]
(if (identical? old-selection new-selection) (if (identical? old-selection new-selection)
@ -53,7 +53,7 @@
(apply array (map str new-selection))))) (apply array (map str new-selection)))))
(defmethod handle-state-change "themechange" (defmethod handle-state-change "themechange"
[_ old-val new-val] [_ _ old-val new-val]
(let [old-theme (get-in old-val [:profile :theme]) (let [old-theme (get-in old-val [:profile :theme])
new-theme (get-in new-val [:profile :theme])] new-theme (get-in new-val [:profile :theme])]
(if (identical? old-theme new-theme) (if (identical? old-theme new-theme)
@ -63,17 +63,17 @@
new-theme)))) new-theme))))
(defmethod handle-state-change :default (defmethod handle-state-change :default
[_ _ _] [_ _ _ _]
::not-changed) ::not-changed)
(defn add-listener (defn add-listener
[type callback] [type plugin-id callback]
(let [key (js/Symbol) (let [key (js/Symbol)
callback (gf/debounce callback 10)] callback (gf/debounce callback 10)]
(add-watch (add-watch
st/state key st/state key
(fn [_ _ old-val new-val] (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) (when (not= ::not-changed result)
(callback result))))) (callback result)))))

View file

@ -9,15 +9,84 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.record :as crc] [app.common.record :as crc]
[app.main.data.workspace :as dw]
[app.main.store :as st]
[app.plugins.page :as page] [app.plugins.page :as page]
[app.plugins.utils :refer [locate-file proxy->file]] [app.plugins.utils :as u]
[app.util.object :as obj])) [app.util.object :as obj]))
(deftype FileProxy [$id] (deftype FileProxy [$plugin $id]
Object Object
(getPages [_] (getPages [_]
(let [file (locate-file $id)] (let [file (u/locate-file $id)]
(apply array (sequence (map #(page/page-proxy $id %)) (dm/get-in file [:data :pages])))))) (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! (crc/define-properties!
FileProxy FileProxy
@ -25,16 +94,17 @@
:get (fn [] (str "FileProxy"))}) :get (fn [] (str "FileProxy"))})
(defn file-proxy (defn file-proxy
[id] [plugin-id id]
(crc/add-properties! (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" :enumerable false :get (constantly id)}
{:name "id" {:name "id"
:get #(dm/str (obj/get % "$id"))} :get #(dm/str (obj/get % "$id"))}
{:name "name" {:name "name"
:get #(-> % proxy->file :name)} :get #(-> % u/proxy->file :name)}
{:name "pages" {:name "pages"
:get #(.getPages ^js %)})) :get #(.getPages ^js %)}))

View file

@ -17,7 +17,7 @@
[app.util.object :as obj] [app.util.object :as obj]
[potok.v2.core :as ptk])) [potok.v2.core :as ptk]))
(deftype FlexLayout [$file $page $id] (deftype FlexLayout [$plugin $file $page $id]
Object Object
(remove (remove
[_] [_]
@ -30,9 +30,10 @@
(ptk/data-event :layout/update {:ids [$id]}))))) (ptk/data-event :layout/update {:ids [$id]})))))
(defn flex-layout-proxy (defn flex-layout-proxy
[file-id page-id id] [plugin-id file-id page-id id]
(-> (FlexLayout. file-id page-id id) (-> (FlexLayout. plugin-id file-id page-id id)
(crc/add-properties! (crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)} {:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)} {:name "$page" :enumerable false :get (constantly page-id)}
@ -148,12 +149,13 @@
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))}))) (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 (defn layout-child-proxy
[file-id page-id id] [plugin-id file-id page-id id]
(-> (LayoutChildProxy. file-id page-id id) (-> (LayoutChildProxy. plugin-id file-id page-id id)
(crc/add-properties! (crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)} {:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)} {:name "$page" :enumerable false :get (constantly page-id)}

View file

@ -23,7 +23,7 @@
js/Object js/Object
(apply array (->> tracks (map utils/to-js))))) (apply array (->> tracks (map utils/to-js)))))
(deftype GridLayout [$file $page $id] (deftype GridLayout [$plugin $file $page $id]
Object Object
(addRow (addRow
@ -75,9 +75,10 @@
(ptk/data-event :layout/update {:ids [$id]}))))) (ptk/data-event :layout/update {:ids [$id]})))))
(defn grid-layout-proxy (defn grid-layout-proxy
[file-id page-id id] [plugin-id file-id page-id id]
(-> (GridLayout. file-id page-id id) (-> (GridLayout. plugin-id file-id page-id id)
(crc/add-properties! (crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)} {:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)} {:name "$page" :enumerable false :get (constantly page-id)}
@ -164,7 +165,6 @@
(when (us/safe-int? value) (when (us/safe-int? value)
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))} (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))}
{:name "topPadding" {:name "topPadding"
:get #(-> % proxy->shape :layout-padding :p1) :get #(-> % proxy->shape :layout-padding :p1)
:set :set
@ -197,17 +197,18 @@
(when (us/safe-int? value) (when (us/safe-int? value)
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 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 (defn layout-cell-proxy
[file-id page-id id] [plugin-id file-id page-id id]
(letfn [(locate-cell [_] (letfn [(locate-cell [_]
(let [shape (locate-shape file-id page-id id) (let [shape (locate-shape file-id page-id id)
parent (locate-shape file-id page-id (:parent-id shape))] parent (locate-shape file-id page-id (:parent-id shape))]
(ctl/get-cell-by-shape-id parent id)))] (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! (crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)} {:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)} {:name "$page" :enumerable false :get (constantly page-id)}

View file

@ -16,6 +16,7 @@
[app.common.types.color :as ctc] [app.common.types.color :as ctc]
[app.common.types.typography :as ctt] [app.common.types.typography :as ctt]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.workspace :as dw]
[app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.texts :as dwt] [app.main.data.workspace.texts :as dwt]
[app.main.store :as st] [app.main.store :as st]
@ -26,7 +27,7 @@
(declare lib-color-proxy) (declare lib-color-proxy)
(declare lib-typography-proxy) (declare lib-typography-proxy)
(deftype LibraryColorProxy [$file $id] (deftype LibraryColorProxy [$plugin $file $id]
Object Object
(remove (remove
@ -39,7 +40,7 @@
color (-> (u/locate-library-color $file $id) color (-> (u/locate-library-color $file $id)
(assoc :id color-id))] (assoc :id color-id))]
(st/emit! (dwl/add-color color {:rename? false})) (st/emit! (dwl/add-color color {:rename? false}))
(lib-color-proxy $id color-id))) (lib-color-proxy $plugin $id color-id)))
(asFill [_] (asFill [_]
(let [color (u/locate-library-color $file $id)] (let [color (u/locate-library-color $file $id)]
@ -63,15 +64,87 @@
:stroke-color-ref-id $id :stroke-color-ref-id $id
:stroke-image (:image color) :stroke-image (:image color)
:stroke-style :solid :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 (defn lib-color-proxy
[file-id id] [plugin-id file-id id]
(assert (uuid? file-id)) (assert (uuid? file-id))
(assert (uuid? id)) (assert (uuid? id))
(cr/add-properties! (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 "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
@ -139,7 +212,7 @@
(st/emit! (dwl/update-color color file-id))) (st/emit! (dwl/update-color color file-id)))
(u/display-not-valid :library-color-image value))))})) (u/display-not-valid :library-color-image value))))}))
(deftype LibraryTypographyProxy [$file $id] (deftype LibraryTypographyProxy [$plugin $file $id]
Object Object
(remove (remove
[_] [_]
@ -151,7 +224,7 @@
typo (-> (u/locate-library-typography $file $id) typo (-> (u/locate-library-typography $file $id)
(assoc :id typo-id))] (assoc :id typo-id))]
(st/emit! (dwl/add-typography typo false)) (st/emit! (dwl/add-typography typo false))
(lib-typography-proxy $id typo-id))) (lib-typography-proxy $plugin $id typo-id)))
(applyToText (applyToText
[_ shape] [_ shape]
@ -162,15 +235,88 @@
(applyToTextRange (applyToTextRange
[_ _shape _from _to] [_ _shape _from _to]
;; TODO ;; 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 (defn lib-typography-proxy
[file-id id] [plugin-id file-id id]
(assert (uuid? file-id)) (assert (uuid? file-id))
(assert (uuid? id)) (assert (uuid? id))
(cr/add-properties! (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 "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "id" :get (fn [_] (dm/str id))} {:name "id" :get (fn [_] (dm/str id))}
@ -285,7 +431,7 @@
(st/emit! (dwl/update-typography typo file-id))) (st/emit! (dwl/update-typography typo file-id)))
(u/display-not-valid :library-typography-text-transform value)))})) (u/display-not-valid :library-typography-text-transform value)))}))
(deftype LibraryComponentProxy [$file $id] (deftype LibraryComponentProxy [$plugin $file $id]
Object Object
(remove (remove
@ -296,15 +442,87 @@
[_] [_]
(let [id-ref (atom nil)] (let [id-ref (atom nil)]
(st/emit! (dwl/instantiate-component $file $id (gpt/point 0 0) {:id-ref id-ref})) (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 (defn lib-component-proxy
[file-id id] [plugin-id file-id id]
(assert (uuid? file-id)) (assert (uuid? file-id))
(assert (uuid? id)) (assert (uuid? id))
(cr/add-properties! (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 "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "id" :get (fn [_] (dm/str id))} {:name "id" :get (fn [_] (dm/str id))}
@ -329,34 +547,102 @@
(st/emit! (dwl/rename-component id value))) (st/emit! (dwl/rename-component id value)))
(u/display-not-valid :library-component-path value)))})) (u/display-not-valid :library-component-path value)))}))
(deftype Library [$id] (deftype Library [$plugin $id]
Object Object
(createColor (createColor
[_] [_]
(let [color-id (uuid/next)] (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}))
(lib-color-proxy $id color-id))) (lib-color-proxy $plugin $id color-id)))
(createTypography (createTypography
[_] [_]
(let [typography-id (uuid/next)] (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))
(lib-typography-proxy $id typography-id))) (lib-typography-proxy $plugin $id typography-id)))
(createComponent (createComponent
[_ shapes] [_ shapes]
(let [id-ref (atom nil) (let [id-ref (atom nil)
ids (into #{} (map #(obj/get % "$id")) shapes)] ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dwl/add-component id-ref ids)) (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 (defn library-proxy
[file-id] [plugin-id file-id]
(assert (uuid? file-id) "File id not valid") (assert (uuid? file-id) "File id not valid")
(cr/add-properties! (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 "$file" :enumerable false :get (constantly file-id)}
{:name "id" {:name "id"
@ -369,14 +655,14 @@
:get :get
(fn [_] (fn [_]
(let [file (u/locate-file file-id) (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)))} (apply array colors)))}
{:name "typographies" {:name "typographies"
:get :get
(fn [_] (fn [_]
(let [file (u/locate-file file-id) (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)))} (apply array typographies)))}
{:name "components" {:name "components"
@ -388,10 +674,10 @@
:components :components
(remove (comp :deleted second)) (remove (comp :deleted second))
(map first) (map first)
(map #(lib-component-proxy file-id %)))] (map #(lib-component-proxy plugin-id file-id %)))]
(apply array components)))})) (apply array components)))}))
(deftype PenpotLibrarySubcontext [] (deftype PenpotLibrarySubcontext [$plugin]
Object Object
(find (find
[_ _name]) [_ _name])
@ -399,14 +685,15 @@
(find [_])) (find [_]))
(defn library-subcontext (defn library-subcontext
[] [plugin-id]
(cr/add-properties! (cr/add-properties!
(PenpotLibrarySubcontext.) (PenpotLibrarySubcontext. plugin-id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "local" :get {:name "local" :get
(fn [_] (fn [_]
(library-proxy (:current-file-id @st/state)))} (library-proxy plugin-id (:current-file-id @st/state)))}
{:name "connected" :get {:name "connected" :get
(fn [_] (fn [_]
(let [libraries (get @st/state :workspace-libraries)] (let [libraries (get @st/state :workspace-libraries)]
(apply array (->> libraries vals (map library-proxy)))))})) (apply array (->> libraries keys (map (partial library-proxy plugin-id))))))}))

View file

@ -17,23 +17,90 @@
[app.plugins.utils :as u] [app.plugins.utils :as u]
[app.util.object :as obj])) [app.util.object :as obj]))
(deftype PageProxy [$file $id] (deftype PageProxy [$plugin $file $id]
Object Object
(getShapeById (getShapeById
[_ shape-id] [_ shape-id]
(let [shape-id (uuid/uuid 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 (getRoot
[_] [_]
(shape/shape-proxy $file $id uuid/zero)) (shape/shape-proxy $plugin $file $id uuid/zero))
(findShapes (findShapes
[_] [_]
;; Returns a lazy (iterable) of all available shapes ;; Returns a lazy (iterable) of all available shapes
(when (and (some? $file) (some? $id)) (when (and (some? $file) (some? $id))
(let [page (u/locate-page $file $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! (crc/define-properties!
PageProxy PageProxy
@ -41,9 +108,10 @@
:get (fn [] (str "PageProxy"))}) :get (fn [] (str "PageProxy"))})
(defn page-proxy (defn page-proxy
[file-id id] [plugin-id file-id id]
(crc/add-properties! (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 "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}

View file

@ -9,6 +9,7 @@
(:require (:require
[app.common.colors :as clr] [app.common.colors :as clr]
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.geom.rect :as grc] [app.common.geom.rect :as grc]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
@ -20,7 +21,7 @@
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.common.types.shape.radius :as ctsr] [app.common.types.shape.radius :as ctsr]
[app.common.uuid :as uuid] [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.groups :as dwg]
[app.main.data.workspace.selection :as dws] [app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shape-layout :as dwsl]
@ -61,23 +62,90 @@
(dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs}) (dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs})
(dwt/current-text-values {:shape shape :attrs txt/text-node-attrs}))) (dwt/current-text-values {:shape shape :attrs txt/text-node-attrs})))
(deftype ShapeProxy [$file $page $id] (deftype ShapeProxy [$plugin $file $page $id]
Object Object
(resize (resize
[_ width height] [_ width height]
(st/emit! (udw/update-dimensions [$id] :width width) (st/emit! (dw/update-dimensions [$id] :width width)
(udw/update-dimensions [$id] :height height))) (dw/update-dimensions [$id] :height height)))
(clone (clone
[_] [_]
(let [ret-v (atom nil)] (let [ret-v (atom nil)]
(st/emit! (dws/duplicate-shapes #{$id} :change-selection? false :return-ref ret-v)) (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 (remove
[_] [_]
(st/emit! (dwsh/delete-shapes #{$id}))) (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 ;; Only for frames + groups + booleans
(getChildren (getChildren
[_] [_]
@ -85,7 +153,7 @@
(if (or (cfh/frame-shape? shape) (cfh/group-shape? shape) (cfh/svg-raw-shape? shape) (cfh/bool-shape? shape)) (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) (apply array (->> (u/locate-shape $file $page $id)
:shapes :shapes
(map #(shape-proxy $file $page %)))) (map #(shape-proxy $plugin $file $page %))))
(u/display-not-valid :getChildren (:type shape))))) (u/display-not-valid :getChildren (:type shape)))))
(appendChild (appendChild
@ -93,7 +161,7 @@
(let [shape (u/locate-shape $file $page $id)] (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)) (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")] (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))))) (u/display-not-valid :appendChild (:type shape)))))
(insertChild (insertChild
@ -101,7 +169,7 @@
(let [shape (u/locate-shape $file $page $id)] (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)) (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")] (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))))) (u/display-not-valid :insertChild (:type shape)))))
;; Only for frames ;; Only for frames
@ -110,7 +178,7 @@
(let [shape (u/locate-shape $file $page $id)] (let [shape (u/locate-shape $file $page $id)]
(if (cfh/frame-shape? shape) (if (cfh/frame-shape? shape)
(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))
(grid/grid-layout-proxy $file $page $id)) (grid/grid-layout-proxy $plugin $file $page $id))
(u/display-not-valid :addFlexLayout (:type shape))))) (u/display-not-valid :addFlexLayout (:type shape)))))
(addGridLayout (addGridLayout
@ -118,7 +186,7 @@
(let [shape (u/locate-shape $file $page $id)] (let [shape (u/locate-shape $file $page $id)]
(if (cfh/frame-shape? shape) (if (cfh/frame-shape? shape)
(do (st/emit! (dwsl/create-layout-from-id $id :grid :from-frame? true :calculate-params? false)) (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))))) (u/display-not-valid :addGridLayout (:type shape)))))
;; Make masks for groups ;; Make masks for groups
@ -142,6 +210,14 @@
(let [shape (u/locate-shape $file $page $id)] (let [shape (u/locate-shape $file $page $id)]
(if (cfh/path-shape? shape) (if (cfh/path-shape? shape)
(upf/format-path (:content 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)))))) (u/display-not-valid :makeMask (:type shape))))))
(crc/define-properties! (crc/define-properties!
@ -150,20 +226,21 @@
:get (fn [] (str "ShapeProxy"))}) :get (fn [] (str "ShapeProxy"))})
(defn shape-proxy (defn shape-proxy
([id] ([plugin-id id]
(shape-proxy (:current-file-id @st/state) (:current-page-id @st/state) id)) (shape-proxy plugin-id (:current-file-id @st/state) (:current-page-id @st/state) id))
([page-id id] ([plugin-id page-id id]
(shape-proxy (:current-file-id @st/state) 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? file-id))
(assert (uuid? page-id)) (assert (uuid? page-id))
(assert (uuid? id)) (assert (uuid? id))
(let [data (u/locate-shape file-id page-id 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! (crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)} {:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)} {:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)} {:name "$page" :enumerable false :get (constantly page-id)}
@ -332,14 +409,14 @@
:set :set
(fn [self value] (fn [self value]
(let [id (obj/get self "$id")] (let [id (obj/get self "$id")]
(st/emit! (udw/update-position id {:x value}))))} (st/emit! (dw/update-position id {:x value}))))}
{:name "y" {:name "y"
:get #(-> % u/proxy->shape :y) :get #(-> % u/proxy->shape :y)
:set :set
(fn [self value] (fn [self value]
(let [id (obj/get self "$id")] (let [id (obj/get self "$id")]
(st/emit! (udw/update-position id {:y value}))))} (st/emit! (dw/update-position id {:y value}))))}
{:name "parentX" {:name "parentX"
:get (fn [self] :get (fn [self]
@ -353,7 +430,7 @@
parent-id (-> self u/proxy->shape :parent-id) parent-id (-> self u/proxy->shape :parent-id)
parent (u/locate-shape (obj/get self "$file") (obj/get self "$page") parent-id) parent (u/locate-shape (obj/get self "$file") (obj/get self "$page") parent-id)
parent-x (:x parent)] 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" {:name "parentY"
:get (fn [self] :get (fn [self]
@ -368,7 +445,7 @@
parent-id (-> self u/proxy->shape :parent-id) parent-id (-> self u/proxy->shape :parent-id)
parent (u/locate-shape (obj/get self "$file") (obj/get self "$page") parent-id) parent (u/locate-shape (obj/get self "$file") (obj/get self "$page") parent-id)
parent-y (:y parent)] 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" {:name "frameX"
:get (fn [self] :get (fn [self]
@ -383,7 +460,7 @@
frame-id (-> self u/proxy->shape :frame-id) frame-id (-> self u/proxy->shape :frame-id)
frame (u/locate-shape (obj/get self "$file") (obj/get self "$page") frame-id) frame (u/locate-shape (obj/get self "$file") (obj/get self "$page") frame-id)
frame-x (:x frame)] 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" {:name "frameY"
:get (fn [self] :get (fn [self]
@ -398,7 +475,7 @@
frame-id (-> self u/proxy->shape :frame-id) frame-id (-> self u/proxy->shape :frame-id)
frame (u/locate-shape (obj/get self "$file") (obj/get self "$page") frame-id) frame (u/locate-shape (obj/get self "$file") (obj/get self "$page") frame-id)
frame-y (:y frame)] 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" {:name "width"
:get #(-> % u/proxy->shape :width)} :get #(-> % u/proxy->shape :width)}
@ -437,7 +514,7 @@
id (obj/get self "$id") id (obj/get self "$id")
objects (u/locate-objects file-id page-id)] objects (u/locate-objects file-id page-id)]
(when (ctl/any-layout-immediate-child-id? objects 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" {:name "layoutCell"
:get :get
@ -447,7 +524,7 @@
id (obj/get self "$id") id (obj/get self "$id")
objects (u/locate-objects file-id page-id)] objects (u/locate-objects file-id page-id)]
(when (ctl/grid-layout-immediate-child-id? objects 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)) (cond-> (or (cfh/frame-shape? data) (cfh/group-shape? data) (cfh/svg-raw-shape? data) (cfh/bool-shape? data))
(crc/add-properties! (crc/add-properties!
@ -465,7 +542,7 @@
page-id (obj/get self "$page") page-id (obj/get self "$page")
id (obj/get self "$id")] id (obj/get self "$id")]
(when (= :grid layout) (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" {:name "flex"
:get :get
@ -475,7 +552,7 @@
page-id (obj/get self "$page") page-id (obj/get self "$page")
id (obj/get self "$id")] id (obj/get self "$id")]
(when (= :flex layout) (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" {:name "guides"
:get #(-> % u/proxy->shape :grids u/array-to-js) :get #(-> % u/proxy->shape :grids u/array-to-js)

View file

@ -11,14 +11,18 @@
[app.plugins.utils :as u] [app.plugins.utils :as u]
[app.util.object :as obj])) [app.util.object :as obj]))
(deftype CurrentUserProxy [$session]) (deftype CurrentUserProxy [$plugin $session])
(deftype ActiveUserProxy [$session]) (deftype ActiveUserProxy [$plugin $session])
(defn add-user-properties (defn add-user-properties
[user-proxy] [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! (crc/add-properties!
user-proxy user-proxy
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$session" :enumerable false :get (constantly session-id)}
{:name "id" {:name "id"
:get (fn [_] (-> (u/locate-profile session-id) :id str))} :get (fn [_] (-> (u/locate-profile session-id) :id str))}
@ -35,13 +39,13 @@
:get (fn [_] (str session-id))}))) :get (fn [_] (str session-id))})))
(defn current-user-proxy (defn current-user-proxy
[session-id] [plugin-id session-id]
(-> (CurrentUserProxy. session-id) (-> (CurrentUserProxy. plugin-id session-id)
(add-user-properties))) (add-user-properties)))
(defn active-user-proxy (defn active-user-proxy
[session-id] [plugin-id session-id]
(-> (ActiveUserProxy. session-id) (-> (ActiveUserProxy. plugin-id session-id)
(add-user-properties) (add-user-properties)
(crc/add-properties! (crc/add-properties!
{:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point u/to-js))} {:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point u/to-js))}

View file

@ -16,7 +16,7 @@
[app.main.store :as st] [app.main.store :as st]
[app.util.object :as obj])) [app.util.object :as obj]))
(deftype ViewportProxy [] (deftype ViewportProxy [$plugin]
Object Object
(zoomIntoView [_ shapes] (zoomIntoView [_ shapes]
(let [ids (let [ids
@ -33,9 +33,9 @@
:get (fn [] (str "ViewportProxy"))}) :get (fn [] (str "ViewportProxy"))})
(defn create-proxy (defn create-proxy
[] [plugin-id]
(crc/add-properties! (crc/add-properties!
(ViewportProxy.) (ViewportProxy. plugin-id)
{:name "center" {:name "center"
:get :get
(fn [_] (fn [_]