mirror of
https://github.com/penpot/penpot.git
synced 2025-01-22 14:39:45 -05:00
✨ Plugins proof of concept
This commit is contained in:
parent
fd92437f7d
commit
3f473ca765
6 changed files with 200 additions and 10 deletions
|
@ -430,15 +430,18 @@
|
|||
|
||||
(defmacro define-properties!
|
||||
[rsym & properties]
|
||||
(let [rsym (with-meta rsym {:tag 'js})]
|
||||
(let [rsym (with-meta rsym {:tag 'js})
|
||||
self-sym (gensym "self-")
|
||||
get-fn-sym (gensym "get-fn-")
|
||||
set-fn-sym (gensym "set-fn-")
|
||||
params-sym (gensym "params-")
|
||||
args-sym (gensym "args-")]
|
||||
`(do
|
||||
~@(for [params properties
|
||||
:let [pname (get params :name)
|
||||
get-fn (get params :get)
|
||||
set-fn (get params :set)]]
|
||||
`(.defineProperty js/Object
|
||||
(.-prototype ~rsym)
|
||||
~pname
|
||||
`(.defineProperty js/Object (.-prototype ~rsym) ~pname
|
||||
(cljs.core/js-obj
|
||||
"enumerable" true
|
||||
"configurable" true
|
||||
|
@ -447,4 +450,3 @@
|
|||
["get" get-fn])
|
||||
(when set-fn
|
||||
["set" set-fn]))))))))
|
||||
|
||||
|
|
16
frontend/resources/public/js/plugins-runtime.mjs
Normal file
16
frontend/resources/public/js/plugins-runtime.mjs
Normal file
|
@ -0,0 +1,16 @@
|
|||
export class PluginsElement extends HTMLElement {
|
||||
connectedCallback() {
|
||||
console.log('PluginsElement.connectedCallback');
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('penpot-plugins', PluginsElement);
|
||||
|
||||
// Alternative to message passing
|
||||
export function initialize(api) {
|
||||
console.log("PluginsRuntime:initialize", api)
|
||||
|
||||
api.addListener("foobar", "page", (page) => {
|
||||
console.log("Page Changed:", page.name);
|
||||
});
|
||||
};
|
|
@ -23,6 +23,11 @@
|
|||
{{/isDebug}}
|
||||
|
||||
<link rel="icon" href="images/favicon.png" />
|
||||
<script type="importmap">
|
||||
{"imports": {"plugins-runtime": "http://localhost:4200/index.mjs"}}
|
||||
</script>
|
||||
|
||||
<script type="module" src="http://localhost:4200/index.mjs"></script>
|
||||
|
||||
<script>
|
||||
window.penpotTranslations = JSON.parse({{& translations}});
|
||||
|
@ -32,8 +37,8 @@
|
|||
|
||||
{{# manifest}}
|
||||
<script>window.penpotWorkerURI="{{& worker}}"</script>
|
||||
<script src="{{& config}}"></script>
|
||||
<script src="{{& polyfills}}"></script>
|
||||
<script defer src="{{& config}}"></script>
|
||||
<script defer src="{{& polyfills}}"></script>
|
||||
{{/manifest}}
|
||||
|
||||
<!--cookie-consent-->
|
||||
|
@ -44,8 +49,19 @@
|
|||
<div id="app"></div>
|
||||
<section id="modal"></section>
|
||||
{{# manifest}}
|
||||
<script src="{{& shared}}"></script>
|
||||
<script src="{{& main}}"></script>
|
||||
|
||||
<script defer src="{{& shared}}"></script>
|
||||
<script defer src="{{& main}}"></script>
|
||||
|
||||
<penpot-plugins />
|
||||
{{/manifest}}
|
||||
|
||||
<script type="module">
|
||||
import * as runtime from "plugins-runtime";
|
||||
|
||||
// console.log(globalThis.app.plugins);
|
||||
runtime.initialize(globalThis.app.plugins);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
{:entries []}
|
||||
|
||||
:main
|
||||
{:entries [app.main]
|
||||
{:entries [app.main app.plugins]
|
||||
:depends-on #{:shared}
|
||||
:init-fn app.main/init}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
[app.main.ui.modal :refer [modal]]
|
||||
[app.main.ui.routes :as rt]
|
||||
[app.main.worker :as worker]
|
||||
[app.plugins]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n]
|
||||
[app.util.theme :as theme]
|
||||
|
|
155
frontend/src/app/plugins.cljs
Normal file
155
frontend/src/app/plugins.cljs
Normal file
|
@ -0,0 +1,155 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.plugins
|
||||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.record :as crc]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[goog.functions :as gf]
|
||||
[app.util.array :as array]
|
||||
[app.util.rxops :as rxops]
|
||||
[app.util.timers :as tm]))
|
||||
|
||||
;; ---- TYPES
|
||||
|
||||
(deftype ShapeProxy [id name type _data])
|
||||
|
||||
(defn data->shape-proxy
|
||||
[data]
|
||||
(->ShapeProxy (str (:id data))
|
||||
(:name data)
|
||||
(name (:type data))
|
||||
data))
|
||||
|
||||
(def ^:private
|
||||
xf-map-shape-proxy
|
||||
(comp
|
||||
(map val)
|
||||
(map data->shape-proxy)))
|
||||
|
||||
(deftype PageProxy [id name _data]
|
||||
Object
|
||||
(getShapes [_]
|
||||
;; Returns a lazy (iterable) of all available shapes
|
||||
(sequence xf-map-shape-proxy (:objects _data))))
|
||||
|
||||
(defn- data->page-proxy
|
||||
[data]
|
||||
(->PageProxy (str (:id data))
|
||||
(:name data)
|
||||
data))
|
||||
|
||||
(def ^:private
|
||||
xf-map-page-proxy
|
||||
(comp
|
||||
(map val)
|
||||
(map data->page-proxy)))
|
||||
|
||||
(deftype FileProxy [id name revn _data]
|
||||
Object
|
||||
(getPages [_]
|
||||
;; Returns a lazy (iterable) of all available pages
|
||||
(sequence xf-map-page-proxy (:pages-index _data))))
|
||||
|
||||
;; ---- PROPERTIES
|
||||
|
||||
(crc/define-properties!
|
||||
FileProxy
|
||||
{:name js/Symbol.toStringTag
|
||||
:get (fn [] (str "FileProxy"))})
|
||||
|
||||
(crc/define-properties!
|
||||
PageProxy
|
||||
{:name js/Symbol.toStringTag
|
||||
:get (fn [] (str "PageProxy"))})
|
||||
|
||||
(crc/define-properties!
|
||||
ShapeProxy
|
||||
{:name js/Symbol.toStringTag
|
||||
:get (fn [] (str "ShapeProxy"))})
|
||||
|
||||
;; ---- PUBLIC API
|
||||
|
||||
(defn ^:export getCurrentFile
|
||||
[]
|
||||
(let [data (:workspace-data @st/state)]
|
||||
(when (some? data)
|
||||
(let [file (:workspace-file @st/state)]
|
||||
(->FileProxy (str (:id file))
|
||||
(:name file)
|
||||
(:revn file)
|
||||
data)))))
|
||||
|
||||
(defn ^:export getCurrentPage
|
||||
[]
|
||||
(when-let [page-id (:current-page-id @st/state)]
|
||||
(when-let [data (get-in @st/state [:workspace-data :pages-index page-id])]
|
||||
(data->page-proxy data))))
|
||||
|
||||
(defn ^:export getCurrentSelection
|
||||
[]
|
||||
(let [selection (get-in @st/state [:workspace-local :selected])]
|
||||
(when (some? selection)
|
||||
selection)))
|
||||
|
||||
(defn ^:export getCurrentTheme
|
||||
[]
|
||||
(get-in @st/state [:profile :theme]))
|
||||
|
||||
(defn ^:export getState
|
||||
[]
|
||||
@st/state)
|
||||
|
||||
;; (defonce listeners
|
||||
;; (atom {}))
|
||||
|
||||
(defn ^:export addListener
|
||||
[key type f]
|
||||
(let [f (gf/debounce f 500)]
|
||||
(case type
|
||||
"file"
|
||||
(add-watch st/state key
|
||||
(fn [_ _ old-val new-val]
|
||||
(let [old-file (:workspace-file old-val)
|
||||
new-file (:workspace-file new-val)
|
||||
old-data (:workspace-data old-val)
|
||||
new-data (:workspace-data new-val)]
|
||||
(when-not (and (identical? old-file new-file)
|
||||
(identical? old-data new-data))
|
||||
(f (->FileProxy (str (:id new-file))
|
||||
(:name new-file)
|
||||
(:revn new-file)
|
||||
new-data))))))
|
||||
"page"
|
||||
(add-watch st/state key
|
||||
(fn [_ _ old-val new-val]
|
||||
(let [old-page-id (:current-page-id old-val)
|
||||
new-page-id (:current-page-id new-val)
|
||||
old-page (dm/get-in old-val [:workspace-data :pages-index old-page-id])
|
||||
new-page (dm/get-in new-val [:workspace-data :pages-index new-page-id])]
|
||||
(when-not (identical? old-page new-page)
|
||||
(f (data->page-proxy new-page))))))
|
||||
"selection"
|
||||
(add-watch st/state key
|
||||
(fn [_ _ old-val new-val]
|
||||
(let [old-selection (get-in old-val [:workspace-local :selected])
|
||||
new-selection (get-in new-val [:workspace-local :selected])]
|
||||
(when-not (identical? old-selection new-selection)
|
||||
(f (clj->js new-selection))))))
|
||||
|
||||
"theme"
|
||||
(add-watch st/state key
|
||||
(fn [_ _ old-val new-val]
|
||||
(let [old-theme (get-in old-val [:profile :theme])
|
||||
new-theme (get-in new-val [:profile :theme])]
|
||||
(when-not (identical? old-theme new-theme)
|
||||
(f new-theme)))))
|
||||
)))
|
||||
|
Loading…
Add table
Reference in a new issue