mirror of
https://github.com/penpot/penpot.git
synced 2025-03-28 15:41:25 -05:00
✨ Refactor to the context api
This commit is contained in:
parent
7b508f2803
commit
0ffd82299f
7 changed files with 187 additions and 82 deletions
|
@ -429,8 +429,9 @@
|
|||
`(update ~ssym ~ksym ~f ~@params)))
|
||||
|
||||
(defmacro define-properties!
|
||||
"Define properties in the prototype with `.defineProperty`"
|
||||
[rsym & properties]
|
||||
(let [rsym (with-meta rsym {:tag 'js})]
|
||||
(let [rsym (with-meta rsym {:tag 'js})]
|
||||
`(do
|
||||
~@(for [params properties
|
||||
:let [pname (get params :name)
|
||||
|
@ -458,3 +459,50 @@
|
|||
|
||||
(when set-fn
|
||||
["set" set-fn]))))))))
|
||||
|
||||
(defmacro add-properties!
|
||||
"Adds properties to an object using `.defineProperty`"
|
||||
[rsym & properties]
|
||||
(let [rsym (with-meta rsym {:tag 'js})
|
||||
getf-sym (with-meta (gensym "get-fn") {:tag 'js})
|
||||
setf-sym (with-meta (gensym "set-fn") {:tag 'js})
|
||||
this-sym (with-meta (gensym "this") {:tag 'js})
|
||||
target-sym (with-meta (gensym "target") {:tag 'js})]
|
||||
`(let [~target-sym ~rsym]
|
||||
;; Creates the `.defineProperty` per property
|
||||
~@(for [params properties
|
||||
:let [pname (get params :name)
|
||||
get-fn (get params :get)
|
||||
set-fn (get params :set)
|
||||
enum-p (get params :enumerable)
|
||||
conf-p (get params :configurable)
|
||||
writ-p (get params :writable)]]
|
||||
`(let [~getf-sym ~get-fn
|
||||
~setf-sym ~set-fn]
|
||||
(.defineProperty
|
||||
js/Object
|
||||
~target-sym
|
||||
~pname
|
||||
(cljs.core/js-obj
|
||||
~@(concat
|
||||
(if (some? enum-p)
|
||||
["enumerable" enum-p]
|
||||
;; Default in JS is false. We default to true
|
||||
["enumerable" true])
|
||||
|
||||
(when (some? conf-p)
|
||||
["configurable" conf-p])
|
||||
|
||||
(when (some? writ-p)
|
||||
["writable" writ-p])
|
||||
|
||||
(when get-fn
|
||||
["get" `(fn []
|
||||
(cljs.core/this-as ~this-sym
|
||||
(~getf-sym ~this-sym)))])
|
||||
(when set-fn
|
||||
["set" `(fn [value#]
|
||||
(cljs.core/this-as ~this-sym
|
||||
(~setf-sym ~this-sym value#)))]))))))
|
||||
;; Returns the object
|
||||
~target-sym)))
|
||||
|
|
|
@ -18,6 +18,4 @@
|
|||
(when (features/active-feature? @st/state "plugins/runtime")
|
||||
(when-let [init-runtime (obj/get global "initPluginsRuntime")]
|
||||
(let [context (api/create-context)]
|
||||
(when *assert*
|
||||
(js/console.log "Plugins context" context))
|
||||
(init-runtime context)))))
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.record :as cr]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.events :as events]
|
||||
[app.plugins.file :as file]
|
||||
|
@ -23,35 +25,50 @@
|
|||
(map val)
|
||||
(map shape/data->shape-proxy)))
|
||||
|
||||
(defn ^:export addListener
|
||||
[type callback]
|
||||
(events/add-listener type callback))
|
||||
(deftype PenpotContext []
|
||||
Object
|
||||
(addListener
|
||||
[_ type callback]
|
||||
(events/add-listener type callback))
|
||||
|
||||
(defn ^:export getFile
|
||||
[]
|
||||
(file/data->file-proxy (:workspace-file @st/state) (:workspace-data @st/state)))
|
||||
(getFile
|
||||
[_]
|
||||
(file/data->file-proxy (:workspace-file @st/state) (:workspace-data @st/state)))
|
||||
|
||||
(defn ^:export getPage
|
||||
[]
|
||||
(let [page-id (:current-page-id @st/state)]
|
||||
(page/data->page-proxy (dm/get-in @st/state [:workspace-data :pages-index page-id]))))
|
||||
(getPage
|
||||
[_]
|
||||
(let [page-id (:current-page-id @st/state)]
|
||||
(page/data->page-proxy (dm/get-in @st/state [:workspace-data :pages-index page-id]))))
|
||||
|
||||
(defn ^:export getSelected
|
||||
[]
|
||||
(let [selection (get-in @st/state [:workspace-local :selected])]
|
||||
(apply array (map str selection))))
|
||||
(getSelected
|
||||
[_]
|
||||
(let [selection (get-in @st/state [:workspace-local :selected])]
|
||||
(apply array (map str selection))))
|
||||
|
||||
(defn ^:export getSelectedShapes
|
||||
[]
|
||||
(let [page-id (:current-page-id @st/state)
|
||||
selection (get-in @st/state [:workspace-local :selected])
|
||||
objects (dm/get-in @st/state [:workspace-data :pages-index page-id :objects])
|
||||
shapes (select-keys objects selection)]
|
||||
(apply array (sequence xf-map-shape-proxy shapes))))
|
||||
(getSelectedShapes
|
||||
[_]
|
||||
(let [page-id (:current-page-id @st/state)
|
||||
selection (get-in @st/state [:workspace-local :selected])
|
||||
objects (dm/get-in @st/state [:workspace-data :pages-index page-id :objects])
|
||||
shapes (select-keys objects selection)]
|
||||
(apply array (sequence xf-map-shape-proxy shapes))))
|
||||
|
||||
(defn ^:export getTheme
|
||||
(getRoot
|
||||
[_]
|
||||
(let [page-id (:current-page-id @st/state)
|
||||
root (dm/get-in @st/state [:workspace-data :pages-index page-id :objects uuid/zero])]
|
||||
(shape/data->shape-proxy root)))
|
||||
|
||||
(getTheme
|
||||
[_]
|
||||
(let [theme (get-in @st/state [:profile :theme])]
|
||||
(if (or (not theme) (= theme "default"))
|
||||
"dark"
|
||||
(get-in @st/state [:profile :theme])))))
|
||||
|
||||
(defn create-context
|
||||
[]
|
||||
(let [theme (get-in @st/state [:profile :theme])]
|
||||
(if (or (not theme) (= theme "default"))
|
||||
"dark"
|
||||
(get-in @st/state [:profile :theme]))))
|
||||
(cr/add-properties!
|
||||
(PenpotContext.)
|
||||
{:name "root" :get #(.getRoot ^js %)}
|
||||
{:name "currentPage" :get #(.getPage ^js %)}))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
(:require
|
||||
[app.common.record :as crc]
|
||||
[app.plugins.page :as page]
|
||||
[app.plugins.utils :as utils]))
|
||||
[app.plugins.utils :refer [get-data-fn]]))
|
||||
|
||||
(def ^:private
|
||||
xf-map-page-proxy
|
||||
|
@ -17,8 +17,7 @@
|
|||
(map val)
|
||||
(map page/data->page-proxy)))
|
||||
|
||||
(deftype FileProxy [id name revn
|
||||
#_:clj-kondo/ignore _data]
|
||||
(deftype FileProxy [#_:clj-kondo/ignore _data]
|
||||
Object
|
||||
(getPages [_]
|
||||
;; Returns a lazy (iterable) of all available pages
|
||||
|
@ -27,16 +26,21 @@
|
|||
(crc/define-properties!
|
||||
FileProxy
|
||||
{:name js/Symbol.toStringTag
|
||||
:get (fn [] (str "FileProxy"))}
|
||||
{:name "pages"
|
||||
:get (fn [] (this-as this (.getPages ^js this)))})
|
||||
:get (fn [] (str "FileProxy"))})
|
||||
|
||||
(defn data->file-proxy
|
||||
[file data]
|
||||
(utils/hide-data!
|
||||
(->FileProxy (str (:id file))
|
||||
(:name file)
|
||||
(:revn file)
|
||||
data)))
|
||||
(crc/add-properties!
|
||||
(FileProxy. (merge file data))
|
||||
{:name "_data" :enumerable false}
|
||||
|
||||
{:name "id"
|
||||
:get (get-data-fn :id str)}
|
||||
|
||||
{:name "name"
|
||||
:get (get-data-fn :name)}
|
||||
|
||||
{:name "pages"
|
||||
:get #(.getPages ^js %)}))
|
||||
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.record :as crc]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.plugins.shape :as shape]
|
||||
[app.plugins.utils :as utils]))
|
||||
[app.plugins.utils :refer [get-data-fn]]))
|
||||
|
||||
(def ^:private
|
||||
xf-map-shape-proxy
|
||||
|
@ -17,9 +18,14 @@
|
|||
(map val)
|
||||
(map shape/data->shape-proxy)))
|
||||
|
||||
(deftype PageProxy [id name
|
||||
#_:clj-kondo/ignore _data]
|
||||
(deftype PageProxy [#_:clj-kondo/ignore _data]
|
||||
Object
|
||||
(getShapeById [_ id]
|
||||
(shape/data->shape-proxy (get (:objects _data) (uuid/uuid id))))
|
||||
|
||||
(getRoot [_]
|
||||
(shape/data->shape-proxy (get (:objects _data) uuid/zero)))
|
||||
|
||||
(findShapes [_]
|
||||
;; Returns a lazy (iterable) of all available shapes
|
||||
(apply array (sequence xf-map-shape-proxy (:objects _data)))))
|
||||
|
@ -31,8 +37,16 @@
|
|||
|
||||
(defn data->page-proxy
|
||||
[data]
|
||||
(utils/hide-data!
|
||||
(->PageProxy
|
||||
(str (:id data))
|
||||
(:name data)
|
||||
data)))
|
||||
|
||||
(crc/add-properties!
|
||||
(PageProxy. data)
|
||||
{:name "_data" :enumerable false}
|
||||
|
||||
{:name "id"
|
||||
:get (get-data-fn :id str)}
|
||||
|
||||
{:name "name"
|
||||
:get (get-data-fn :name)}
|
||||
|
||||
{:name "root"
|
||||
:get #(.getRoot ^js %)}))
|
||||
|
|
|
@ -7,12 +7,15 @@
|
|||
(ns app.plugins.shape
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.record :as crc]
|
||||
[app.plugins.utils :as utils]
|
||||
[app.util.object :as obj]
|
||||
[app.main.data.workspace.changes :as dwc]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.utils :refer [get-data get-data-fn]]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(declare data->shape-proxy)
|
||||
|
||||
(defn- make-fills
|
||||
[fills]
|
||||
;; TODO: Transform explicitly?
|
||||
|
@ -20,8 +23,19 @@
|
|||
(->> fills
|
||||
(map #(clj->js % {:keyword-fn (fn [k] (str/camel (name k)))})))))
|
||||
|
||||
(deftype ShapeProxy [_data]
|
||||
(defn- locate-shape
|
||||
[shape-id]
|
||||
(let [page-id (:current-page-id @st/state)]
|
||||
(dm/get-in @st/state [:workspace-data :pages-index page-id :objects shape-id])))
|
||||
|
||||
(deftype ShapeProxy [#_:clj-kondo/ignore _data]
|
||||
Object
|
||||
(getChildren
|
||||
[self]
|
||||
(apply array (->> (get-data self :shapes)
|
||||
(map locate-shape)
|
||||
(map data->shape-proxy))))
|
||||
|
||||
(clone [_] (.log js/console (clj->js _data)))
|
||||
(delete [_] (.log js/console (clj->js _data)))
|
||||
(appendChild [_] (.log js/console (clj->js _data))))
|
||||
|
@ -31,36 +45,28 @@
|
|||
{:name js/Symbol.toStringTag
|
||||
:get (fn [] (str "ShapeProxy"))})
|
||||
|
||||
|
||||
(defn get-data
|
||||
([this attr]
|
||||
(-> this
|
||||
(obj/get "_data")
|
||||
(get attr)))
|
||||
([this attr transform-fn]
|
||||
(-> this
|
||||
(get-data attr)
|
||||
(transform-fn))))
|
||||
|
||||
(defn data->shape-proxy
|
||||
[data]
|
||||
|
||||
(-> (->ShapeProxy data)
|
||||
(js/Object.defineProperties
|
||||
#js {"_data" #js {:enumerable false}
|
||||
(crc/add-properties!
|
||||
(ShapeProxy. data)
|
||||
{:name "_data"
|
||||
:enumerable false}
|
||||
|
||||
:id
|
||||
#js {:get #(get-data (js* "this") :id str)
|
||||
:enumerable true}
|
||||
{:name "id"
|
||||
:get (get-data-fn :id str)}
|
||||
|
||||
:name
|
||||
#js {:get #(get-data (js* "this") :name)
|
||||
;;:set (fn [] (prn "SET NAME"))
|
||||
:enumerable true}
|
||||
{:name "name"
|
||||
:get (get-data-fn :name)
|
||||
:set (fn [self value]
|
||||
(let [id (get-data self :id)]
|
||||
(st/emit! (dwc/update-shapes [id] #(assoc % :name value)))))}
|
||||
|
||||
:fills
|
||||
#js {:get #(get-data (js* "this") :fills make-fills)
|
||||
;;:set (fn [] (prn "SET FILLS"))
|
||||
:enumerable true}}
|
||||
)))
|
||||
{:name "children"
|
||||
:get #(.getChildren ^js %)}
|
||||
|
||||
{:name "fills"
|
||||
:get (get-data-fn :fills make-fills)
|
||||
;;:set (fn [self value] (.log js/console self value))
|
||||
}))
|
||||
|
||||
|
|
|
@ -5,8 +5,26 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.plugins.utils
|
||||
"RPC for plugins runtime.")
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.util.object :as obj]))
|
||||
|
||||
(defn get-data
|
||||
([self attr]
|
||||
(-> (obj/get self "_data")
|
||||
(get attr)))
|
||||
|
||||
([self attr transform-fn]
|
||||
(-> (get-data self attr)
|
||||
(transform-fn))))
|
||||
|
||||
(defn get-data-fn
|
||||
([attr]
|
||||
(fn [self]
|
||||
(get-data self attr)))
|
||||
|
||||
([attr transform-fn]
|
||||
(fn [self]
|
||||
(get-data self attr transform-fn))))
|
||||
|
||||
|
||||
(defn hide-data!
|
||||
[proxy]
|
||||
(.defineProperty js/Object proxy "_data" #js {:enumerable false}))
|
||||
|
|
Loading…
Add table
Reference in a new issue