mirror of
https://github.com/penpot/penpot.git
synced 2025-05-02 01:46:22 +02:00
Merge remote-tracking branch 'upstream/develop' into develop
This commit is contained in:
commit
4f845b5c4d
22 changed files with 380 additions and 110 deletions
|
@ -9,6 +9,7 @@
|
||||||
(:refer-clojure :exclude [tap])
|
(:refer-clojure :exclude [tap])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.exceptions :as ex]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
[app.http.errors :as errors]
|
[app.http.errors :as errors]
|
||||||
|
@ -60,13 +61,10 @@
|
||||||
(try
|
(try
|
||||||
(let [result (handler)]
|
(let [result (handler)]
|
||||||
(events/tap :end result))
|
(events/tap :end result))
|
||||||
|
|
||||||
(catch java.io.EOFException cause
|
|
||||||
(events/tap :error (errors/handle' cause request)))
|
|
||||||
(catch Throwable cause
|
(catch Throwable cause
|
||||||
(l/err :hint "unexpected error on processing sse response"
|
(events/tap :error (errors/handle' cause request))
|
||||||
:cause cause)
|
(when-not (ex/instance? java.io.EOFException cause)
|
||||||
(events/tap :error (errors/handle' cause request)))
|
(l/err :hint "unexpected error on processing sse response" :cause cause)))
|
||||||
(finally
|
(finally
|
||||||
(sp/close! events/*channel*)
|
(sp/close! events/*channel*)
|
||||||
(px/await! listener)))))))}))
|
(px/await! listener)))))))}))
|
||||||
|
|
|
@ -326,7 +326,7 @@
|
||||||
(def ^:private
|
(def ^:private
|
||||||
schema:move-files
|
schema:move-files
|
||||||
[:map {:title "move-files"}
|
[:map {:title "move-files"}
|
||||||
[:ids ::sm/set-of-uuid]
|
[:ids [::sm/set {:min 1} ::sm/uuid]]
|
||||||
[:project-id ::sm/uuid]])
|
[:project-id ::sm/uuid]])
|
||||||
|
|
||||||
(sv/defmethod ::move-files
|
(sv/defmethod ::move-files
|
||||||
|
@ -335,7 +335,7 @@
|
||||||
::webhooks/event? true
|
::webhooks/event? true
|
||||||
::sm/params schema:move-files}
|
::sm/params schema:move-files}
|
||||||
[cfg {:keys [::rpc/profile-id] :as params}]
|
[cfg {:keys [::rpc/profile-id] :as params}]
|
||||||
(db/tx-run! cfg #(move-files % (assoc params :profile-id profile-id))))
|
(db/tx-run! cfg move-files (assoc params :profile-id profile-id)))
|
||||||
|
|
||||||
;; --- COMMAND: Move project
|
;; --- COMMAND: Move project
|
||||||
|
|
||||||
|
|
|
@ -275,7 +275,7 @@
|
||||||
(= :set (:type s))
|
(= :set (:type s))
|
||||||
(m/-collection-schema s)
|
(m/-collection-schema s)
|
||||||
|
|
||||||
(= :vec (:type s))
|
(= :vector (:type s))
|
||||||
(m/-collection-schema s)
|
(m/-collection-schema s)
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
@ -449,24 +449,12 @@
|
||||||
(fn [value]
|
(fn [value]
|
||||||
(every? pred value)))
|
(every? pred value)))
|
||||||
|
|
||||||
|
decode
|
||||||
decode-string-child
|
|
||||||
(decoder kind string-transformer)
|
|
||||||
|
|
||||||
decode-string
|
|
||||||
(fn [v]
|
(fn [v]
|
||||||
(let [v (if (string? v) (str/split v #"[\s,]+") v)
|
(if (string? v)
|
||||||
x (comp xf:filter-word-strings (map decode-string-child))]
|
(let [v (str/split v #"[\s,]+")]
|
||||||
(into #{} x v)))
|
(into #{} xf:filter-word-strings v))
|
||||||
|
v))
|
||||||
decode-json-child
|
|
||||||
(decoder kind json-transformer)
|
|
||||||
|
|
||||||
decode-json
|
|
||||||
(fn [v]
|
|
||||||
(let [v (if (string? v) (str/split v #"[\s,]+") v)
|
|
||||||
x (comp xf:filter-word-strings (map decode-json-child))]
|
|
||||||
(into #{} x v)))
|
|
||||||
|
|
||||||
encode-string-child
|
encode-string-child
|
||||||
(encoder kind string-transformer)
|
(encoder kind string-transformer)
|
||||||
|
@ -475,15 +463,8 @@
|
||||||
(fn [o]
|
(fn [o]
|
||||||
(if (set? o)
|
(if (set? o)
|
||||||
(str/join ", " (map encode-string-child o))
|
(str/join ", " (map encode-string-child o))
|
||||||
o))
|
|
||||||
|
|
||||||
encode-json
|
|
||||||
(fn [o]
|
|
||||||
(if (set? o)
|
|
||||||
(vec o)
|
|
||||||
o))]
|
o))]
|
||||||
|
|
||||||
|
|
||||||
{:pred pred
|
{:pred pred
|
||||||
:empty #{}
|
:empty #{}
|
||||||
:type-properties
|
:type-properties
|
||||||
|
@ -491,10 +472,10 @@
|
||||||
:description "Set of Strings"
|
:description "Set of Strings"
|
||||||
:error/message "should be a set of strings"
|
:error/message "should be a set of strings"
|
||||||
:gen/gen (-> kind sg/generator sg/set)
|
:gen/gen (-> kind sg/generator sg/set)
|
||||||
:decode/string decode-string
|
:decode/string decode
|
||||||
:decode/json decode-json
|
:decode/json decode
|
||||||
:encode/string encode-string
|
:encode/string encode-string
|
||||||
:encode/json encode-json
|
:encode/json identity
|
||||||
::oapi/type "array"
|
::oapi/type "array"
|
||||||
::oapi/format "set"
|
::oapi/format "set"
|
||||||
::oapi/items {:type "string"}
|
::oapi/items {:type "string"}
|
||||||
|
@ -542,23 +523,12 @@
|
||||||
(fn [value]
|
(fn [value]
|
||||||
(every? pred value)))
|
(every? pred value)))
|
||||||
|
|
||||||
decode-string-child
|
decode
|
||||||
(decoder kind string-transformer)
|
|
||||||
|
|
||||||
decode-json-child
|
|
||||||
(decoder kind json-transformer)
|
|
||||||
|
|
||||||
decode-string
|
|
||||||
(fn [v]
|
(fn [v]
|
||||||
(let [v (if (string? v) (str/split v #"[\s,]+") v)
|
(if (string? v)
|
||||||
x (comp xf:filter-word-strings (map decode-string-child))]
|
(let [v (str/split v #"[\s,]+")]
|
||||||
(into #{} x v)))
|
(into #{} xf:filter-word-strings v))
|
||||||
|
v))
|
||||||
decode-json
|
|
||||||
(fn [v]
|
|
||||||
(let [v (if (string? v) (str/split v #"[\s,]+") v)
|
|
||||||
x (comp xf:filter-word-strings (map decode-json-child))]
|
|
||||||
(into #{} x v)))
|
|
||||||
|
|
||||||
encode-string-child
|
encode-string-child
|
||||||
(encoder kind string-transformer)
|
(encoder kind string-transformer)
|
||||||
|
@ -575,9 +545,10 @@
|
||||||
:description "Set of Strings"
|
:description "Set of Strings"
|
||||||
:error/message "should be a set of strings"
|
:error/message "should be a set of strings"
|
||||||
:gen/gen (-> kind sg/generator sg/set)
|
:gen/gen (-> kind sg/generator sg/set)
|
||||||
:decode/string decode-string
|
:decode/string decode
|
||||||
:decode/json decode-json
|
:decode/json decode
|
||||||
:encode/string encode-string
|
:encode/string encode-string
|
||||||
|
:encode/json identity
|
||||||
::oapi/type "array"
|
::oapi/type "array"
|
||||||
::oapi/format "set"
|
::oapi/format "set"
|
||||||
::oapi/items {:type "string"}
|
::oapi/items {:type "string"}
|
||||||
|
|
|
@ -39,3 +39,63 @@
|
||||||
(let [schema [::sm/set ::sm/email]
|
(let [schema [::sm/set ::sm/email]
|
||||||
value (sg/generate schema)]
|
value (sg/generate schema)]
|
||||||
(t/is (true? (sm/validate schema (sg/generate schema)))))))
|
(t/is (true? (sm/validate schema (sg/generate schema)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest test-set-1
|
||||||
|
(let [candidate-1 "cff4b058-ca31-8197-8005-32aeb2377d83, cff4b058-ca31-8197-8005-32aeb2377d82"
|
||||||
|
candidate-2 ["cff4b058-ca31-8197-8005-32aeb2377d82",
|
||||||
|
"cff4b058-ca31-8197-8005-32aeb2377d83"]
|
||||||
|
candidate-3 #{"cff4b058-ca31-8197-8005-32aeb2377d82", "cff4b058-ca31-8197-8005-32aeb2377d83"}
|
||||||
|
candidate-4 [#uuid "cff4b058-ca31-8197-8005-32aeb2377d82"
|
||||||
|
#uuid "cff4b058-ca31-8197-8005-32aeb2377d83"]
|
||||||
|
candidate-5 #{#uuid "cff4b058-ca31-8197-8005-32aeb2377d82"
|
||||||
|
#uuid "cff4b058-ca31-8197-8005-32aeb2377d83"}
|
||||||
|
|
||||||
|
expected candidate-5
|
||||||
|
|
||||||
|
schema [::sm/set ::sm/uuid]
|
||||||
|
decode-s (sm/decoder schema sm/string-transformer)
|
||||||
|
decode-j (sm/decoder schema sm/json-transformer)
|
||||||
|
encode-s (sm/encoder schema sm/string-transformer)
|
||||||
|
encode-j (sm/encoder schema sm/json-transformer)]
|
||||||
|
|
||||||
|
|
||||||
|
(t/is (= expected (decode-s candidate-1)))
|
||||||
|
(t/is (= expected (decode-s candidate-2)))
|
||||||
|
(t/is (= expected (decode-s candidate-3)))
|
||||||
|
(t/is (= expected (decode-s candidate-4)))
|
||||||
|
(t/is (= expected (decode-s candidate-5)))
|
||||||
|
|
||||||
|
(t/is (= candidate-1 (encode-s expected)))
|
||||||
|
(t/is (= candidate-3 (encode-j expected)))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest test-vec-1
|
||||||
|
(let [candidate-1 "cff4b058-ca31-8197-8005-32aeb2377d83, cff4b058-ca31-8197-8005-32aeb2377d82"
|
||||||
|
candidate-2 ["cff4b058-ca31-8197-8005-32aeb2377d83",
|
||||||
|
"cff4b058-ca31-8197-8005-32aeb2377d82"]
|
||||||
|
candidate-3 #{"cff4b058-ca31-8197-8005-32aeb2377d82", "cff4b058-ca31-8197-8005-32aeb2377d83"}
|
||||||
|
candidate-4 [#uuid "cff4b058-ca31-8197-8005-32aeb2377d83"
|
||||||
|
#uuid "cff4b058-ca31-8197-8005-32aeb2377d82"]
|
||||||
|
candidate-5 #{#uuid "cff4b058-ca31-8197-8005-32aeb2377d82"
|
||||||
|
#uuid "cff4b058-ca31-8197-8005-32aeb2377d83"}
|
||||||
|
|
||||||
|
expected candidate-4
|
||||||
|
|
||||||
|
schema [::sm/vec ::sm/uuid]
|
||||||
|
decode-s (sm/decoder schema sm/string-transformer)
|
||||||
|
decode-j (sm/decoder schema sm/json-transformer)
|
||||||
|
encode-s (sm/encoder schema sm/string-transformer)
|
||||||
|
encode-j (sm/encoder schema sm/json-transformer)]
|
||||||
|
|
||||||
|
|
||||||
|
(t/is (= expected (decode-s candidate-1)))
|
||||||
|
(t/is (= expected (decode-s candidate-2)))
|
||||||
|
(t/is (= expected (decode-s candidate-3)))
|
||||||
|
(t/is (= expected (decode-s candidate-4)))
|
||||||
|
(t/is (= expected (decode-s candidate-5)))
|
||||||
|
|
||||||
|
(t/is (= candidate-1 (encode-s expected)))
|
||||||
|
(t/is (= candidate-2 (encode-j expected)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,23 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.plugins.register :as preg]
|
[app.plugins.register :as preg]
|
||||||
[app.util.globals :as ug]
|
[app.util.globals :as ug]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[app.util.time :as dt]
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
(defn save-plugin-permissions-peek
|
||||||
|
[id permissions]
|
||||||
|
(ptk/reify ::save-plugin-permissions-peek
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:plugins-permissions-peek :data id] permissions))))
|
||||||
|
|
||||||
(defn fetch-manifest
|
(defn fetch-manifest
|
||||||
[plugin-url]
|
[plugin-url]
|
||||||
(->> (http/send! {:method :get
|
(->> (http/send! {:method :get
|
||||||
|
@ -59,15 +69,21 @@
|
||||||
(.error js/console "Error" e))))
|
(.error js/console "Error" e))))
|
||||||
|
|
||||||
(defn open-plugin!
|
(defn open-plugin!
|
||||||
[{:keys [url] :as manifest}]
|
[{:keys [url] :as manifest} user-can-edit?]
|
||||||
(if url
|
(if url
|
||||||
;; If the saved manifest has a URL we fetch the manifest to check
|
;; If the saved manifest has a URL we fetch the manifest to check
|
||||||
;; for updates
|
;; for updates
|
||||||
(->> (fetch-manifest url)
|
(->> (fetch-manifest url)
|
||||||
(rx/subs!
|
(rx/subs!
|
||||||
(fn [new-manifest]
|
(fn [new-manifest]
|
||||||
(let [new-manifest (merge new-manifest (select-keys manifest [:plugin-id]))]
|
(let [new-manifest (merge new-manifest (select-keys manifest [:plugin-id]))
|
||||||
|
permissions (:permissions new-manifest)
|
||||||
|
is-edition-plugin? (or (contains? permissions "content:write")
|
||||||
|
(contains? permissions "library:write"))]
|
||||||
|
(st/emit! (save-plugin-permissions-peek (:plugin-id new-manifest) permissions))
|
||||||
(cond
|
(cond
|
||||||
|
(and is-edition-plugin? (not user-can-edit?))
|
||||||
|
(st/emit! (ntf/warn (tr "workspace.plugins.error.need-editor")))
|
||||||
(not= (:permissions new-manifest) (:permissions manifest))
|
(not= (:permissions new-manifest) (:permissions manifest))
|
||||||
(modal/show!
|
(modal/show!
|
||||||
:plugin-permissions-update
|
:plugin-permissions-update
|
||||||
|
@ -96,13 +112,21 @@
|
||||||
(.error js/console "Error" e))))
|
(.error js/console "Error" e))))
|
||||||
|
|
||||||
(defn close-current-plugin
|
(defn close-current-plugin
|
||||||
[]
|
[& {:keys [close-only-edition-plugins?]}]
|
||||||
(ptk/reify ::close-current-plugin
|
(ptk/reify ::close-current-plugin
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ state _]
|
(effect [_ state _]
|
||||||
(let [ids (dm/get-in state [:workspace-local :open-plugins])]
|
(let [ids (dm/get-in state [:workspace-local :open-plugins])]
|
||||||
(doseq [id ids]
|
(doseq [id ids]
|
||||||
(close-plugin! (preg/get-plugin id)))))))
|
(let [plugin (preg/get-plugin id)
|
||||||
|
permissions (or (dm/get-in state [:plugins-permissions-peek :data id])
|
||||||
|
(:permissions plugin))
|
||||||
|
is-edition-plugin? (or (contains? permissions "content:write")
|
||||||
|
(contains? permissions "library:write"))]
|
||||||
|
|
||||||
|
(when (or (not close-only-edition-plugins?)
|
||||||
|
is-edition-plugin?)
|
||||||
|
(close-plugin! plugin))))))))
|
||||||
|
|
||||||
(defn delay-open-plugin
|
(defn delay-open-plugin
|
||||||
[plugin]
|
[plugin]
|
||||||
|
@ -116,6 +140,38 @@
|
||||||
(ptk/reify ::check-open-plugin
|
(ptk/reify ::check-open-plugin
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
|
(let [user-can-edit? (dm/get-in state [:permissions :can-edit])]
|
||||||
(when-let [pid (::open-plugin state)]
|
(when-let [pid (::open-plugin state)]
|
||||||
(open-plugin! (preg/get-plugin pid))
|
(open-plugin! (preg/get-plugin pid) user-can-edit?)
|
||||||
(rx/of #(dissoc % ::open-plugin))))))
|
(rx/of #(dissoc % ::open-plugin)))))))
|
||||||
|
|
||||||
|
(defn- update-plugin-permissions-peek
|
||||||
|
[{:keys [plugin-id url]}]
|
||||||
|
(when url
|
||||||
|
;; If the saved manifest has a URL we fetch the manifest to check
|
||||||
|
;; for updates
|
||||||
|
(->> (fetch-manifest url)
|
||||||
|
(rx/subs!
|
||||||
|
(fn [new-manifest]
|
||||||
|
(let [permissions (:permissions new-manifest)]
|
||||||
|
(when permissions
|
||||||
|
(st/emit! (save-plugin-permissions-peek plugin-id permissions)))))))))
|
||||||
|
|
||||||
|
(defn update-plugins-permissions-peek
|
||||||
|
[]
|
||||||
|
(ptk/reify ::update-plugins-permissions-peek
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [now (dt/now)
|
||||||
|
expiration (dt/minus now (dt/duration {:days 1}))
|
||||||
|
updated-at (dm/get-in state [:plugins-permissions-peek :updated-at] 0)
|
||||||
|
expired? (> expiration updated-at)]
|
||||||
|
|
||||||
|
(if expired?
|
||||||
|
(let [plugins (preg/plugins-list)]
|
||||||
|
(doseq [plugin plugins]
|
||||||
|
(update-plugin-permissions-peek plugin))
|
||||||
|
(-> state
|
||||||
|
(assoc-in [:plugins-permissions-peek :updated-at] now)))
|
||||||
|
|
||||||
|
state)))))
|
||||||
|
|
17
frontend/src/app/main/data/render_wasm.cljs
Normal file
17
frontend/src/app/main/data/render_wasm.cljs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
(ns app.main.data.render-wasm
|
||||||
|
(:require
|
||||||
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
|
(defn context-lost
|
||||||
|
[]
|
||||||
|
(ptk/reify ::context-lost
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :render-state #(assoc % :lost true)))))
|
||||||
|
|
||||||
|
(defn context-restored
|
||||||
|
[]
|
||||||
|
(ptk/reify ::context-restored
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :render-state #(dissoc % :lost)))))
|
|
@ -14,6 +14,7 @@
|
||||||
[app.main.data.changes :as dch]
|
[app.main.data.changes :as dch]
|
||||||
[app.main.data.common :as dc]
|
[app.main.data.common :as dc]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.plugins :as dpl]
|
||||||
[app.main.data.websocket :as dws]
|
[app.main.data.websocket :as dws]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.edition :as dwe]
|
[app.main.data.workspace.edition :as dwe]
|
||||||
|
@ -117,7 +118,8 @@
|
||||||
(rx/delay 100))
|
(rx/delay 100))
|
||||||
(if (= :viewer role)
|
(if (= :viewer role)
|
||||||
(rx/of (modal/hide)
|
(rx/of (modal/hide)
|
||||||
(dwly/set-options-mode :inspect))
|
(dwly/set-options-mode :inspect)
|
||||||
|
(dpl/close-current-plugin {:close-only-edition-plugins? true}))
|
||||||
(rx/of (dwly/set-options-mode :design)))))))
|
(rx/of (dwly/set-options-mode :design)))))))
|
||||||
|
|
||||||
(defn- process-message
|
(defn- process-message
|
||||||
|
|
|
@ -116,6 +116,12 @@
|
||||||
|
|
||||||
;; ---- Workspace refs
|
;; ---- Workspace refs
|
||||||
|
|
||||||
|
(def render-state
|
||||||
|
(l/derived :render-state st/state))
|
||||||
|
|
||||||
|
(def render-context-lost?
|
||||||
|
(l/derived :lost render-state))
|
||||||
|
|
||||||
(def workspace-local
|
(def workspace-local
|
||||||
(l/derived :workspace-local st/state))
|
(l/derived :workspace-local st/state))
|
||||||
|
|
||||||
|
@ -512,6 +518,11 @@
|
||||||
(def workspace-selected-token-set-tokens
|
(def workspace-selected-token-set-tokens
|
||||||
(l/derived #(or (wtts/get-selected-token-set-tokens %) {}) st/state))
|
(l/derived #(or (wtts/get-selected-token-set-tokens %) {}) st/state))
|
||||||
|
|
||||||
|
(def plugins-permissions-peek
|
||||||
|
(l/derived (fn [state]
|
||||||
|
(dm/get-in state [:plugins-permissions-peek :data]))
|
||||||
|
st/state))
|
||||||
|
|
||||||
;; ---- Viewer refs
|
;; ---- Viewer refs
|
||||||
|
|
||||||
(defn lookup-viewer-objects-by-id
|
(defn lookup-viewer-objects-by-id
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.notifications :as ntf]
|
[app.main.data.notifications :as ntf]
|
||||||
[app.main.data.persistence :as dps]
|
[app.main.data.persistence :as dps]
|
||||||
|
[app.main.data.plugins :as dpl]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.colors :as dc]
|
[app.main.data.workspace.colors :as dc]
|
||||||
[app.main.features :as features]
|
[app.main.features :as features]
|
||||||
|
@ -185,7 +186,8 @@
|
||||||
background-color (:background-color wglobal)]
|
background-color (:background-color wglobal)]
|
||||||
|
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(st/emit! (dps/initialize-persistence)))
|
(st/emit! (dps/initialize-persistence)
|
||||||
|
(dpl/update-plugins-permissions-peek)))
|
||||||
|
|
||||||
;; Setting the layout preset by its name
|
;; Setting the layout preset by its name
|
||||||
(mf/with-effect [layout-name]
|
(mf/with-effect [layout-name]
|
||||||
|
|
|
@ -632,7 +632,9 @@
|
||||||
::mf/wrap [mf/memo]}
|
::mf/wrap [mf/memo]}
|
||||||
[{:keys [open-plugins on-close]}]
|
[{:keys [open-plugins on-close]}]
|
||||||
(when (features/active-feature? @st/state "plugins/runtime")
|
(when (features/active-feature? @st/state "plugins/runtime")
|
||||||
(let [plugins (preg/plugins-list)]
|
(let [plugins (preg/plugins-list)
|
||||||
|
user-can-edit? (:can-edit (deref refs/permissions))
|
||||||
|
permissions-peek (deref refs/plugins-permissions-peek)]
|
||||||
[:& dropdown-menu {:show true
|
[:& dropdown-menu {:show true
|
||||||
:list-class (stl/css-case :sub-menu true :plugins true)
|
:list-class (stl/css-case :sub-menu true :plugins true)
|
||||||
:on-close on-close}
|
:on-close on-close}
|
||||||
|
@ -653,24 +655,41 @@
|
||||||
(when (d/not-empty? plugins)
|
(when (d/not-empty? plugins)
|
||||||
[:div {:class (stl/css :separator)}])
|
[:div {:class (stl/css :separator)}])
|
||||||
|
|
||||||
(for [[idx {:keys [name host] :as manifest}] (d/enumerate plugins)]
|
(for [[idx {:keys [plugin-id name host permissions] :as manifest}] (d/enumerate plugins)]
|
||||||
[:> dropdown-menu-item* {:key (dm/str "plugins-menu-" idx)
|
(let [permissions (or (get permissions-peek plugin-id) permissions)
|
||||||
:on-click #(do
|
is-edition-plugin? (or (contains? permissions "content:write")
|
||||||
|
(contains? permissions "library:write"))
|
||||||
|
can-open? (or user-can-edit?
|
||||||
|
(not is-edition-plugin?))
|
||||||
|
on-click
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps can-open? name host manifest user-can-edit?)
|
||||||
|
(fn [event]
|
||||||
|
(if can-open?
|
||||||
|
(do
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "start-plugin"
|
(st/emit! (ptk/event ::ev/event {::ev/name "start-plugin"
|
||||||
::ev/origin "workspace:menu"
|
::ev/origin "workspace:menu"
|
||||||
:name name
|
:name name
|
||||||
:host host}))
|
:host host}))
|
||||||
(dp/open-plugin! manifest))
|
(dp/open-plugin! manifest user-can-edit?))
|
||||||
:class (stl/css :submenu-item)
|
(dom/stop-propagation event))))
|
||||||
:on-key-down (fn [event]
|
on-key-down
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps can-open? name host manifest user-can-edit?)
|
||||||
|
(fn [event]
|
||||||
|
(when can-open?
|
||||||
(when (kbd/enter? event)
|
(when (kbd/enter? event)
|
||||||
#(do
|
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "start-plugin"
|
(st/emit! (ptk/event ::ev/event {::ev/name "start-plugin"
|
||||||
::ev/origin "workspace:menu"
|
::ev/origin "workspace:menu"
|
||||||
:name name
|
:name name
|
||||||
:host host}))
|
:host host}))
|
||||||
(dp/open-plugin! manifest))))}
|
(dp/open-plugin! manifest user-can-edit?)))))]
|
||||||
[:span {:class (stl/css :item-name)} name]])])))
|
[:> dropdown-menu-item* {:key (dm/str "plugins-menu-" idx)
|
||||||
|
:on-click on-click
|
||||||
|
:title (when-not can-open? (tr "workspace.plugins.error.need-editor"))
|
||||||
|
:class (stl/css-case :submenu-item true :menu-disabled (not can-open?))
|
||||||
|
:on-key-down on-key-down}
|
||||||
|
[:span {:class (stl/css :item-name)} name]]))])))
|
||||||
|
|
||||||
(mf/defc menu
|
(mf/defc menu
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
|
|
|
@ -17,20 +17,25 @@
|
||||||
.menu-item {
|
.menu-item {
|
||||||
@extend .menu-item-base;
|
@extend .menu-item-base;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
.open-arrow {
|
.open-arrow {
|
||||||
@include flexCenter;
|
@include flexCenter;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
@extend .button-icon;
|
@extend .button-icon;
|
||||||
stroke: var(--icon-foreground);
|
stroke: var(--icon-foreground);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--menu-foreground-color-hover);
|
color: var(--menu-foreground-color-hover);
|
||||||
|
|
||||||
.open-arrow {
|
.open-arrow {
|
||||||
svg {
|
svg {
|
||||||
stroke: var(--menu-foreground-color-hover);
|
stroke: var(--menu-foreground-color-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-key {
|
.shortcut-key {
|
||||||
color: var(--menu-shortcut-foreground-color-hover);
|
color: var(--menu-shortcut-foreground-color-hover);
|
||||||
}
|
}
|
||||||
|
@ -46,6 +51,7 @@
|
||||||
.shortcut {
|
.shortcut {
|
||||||
@extend .shortcut-base;
|
@extend .shortcut-base;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-key {
|
.shortcut-key {
|
||||||
@extend .shortcut-key-base;
|
@extend .shortcut-key-base;
|
||||||
}
|
}
|
||||||
|
@ -59,14 +65,26 @@
|
||||||
|
|
||||||
.submenu-item {
|
.submenu-item {
|
||||||
@extend .menu-item-base;
|
@extend .menu-item-base;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--menu-foreground-color-hover);
|
color: var(--menu-foreground-color-hover);
|
||||||
|
|
||||||
.shortcut-key {
|
.shortcut-key {
|
||||||
color: var(--menu-shortcut-foreground-color-hover);
|
color: var(--menu-shortcut-foreground-color-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-disabled {
|
||||||
|
color: var(--color-foreground-secondary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: default;
|
||||||
|
color: var(--color-foreground-secondary);
|
||||||
|
background-color: var(--menu-background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.file {
|
&.file {
|
||||||
top: $s-48;
|
top: $s-48;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,11 @@
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.plugins :as dp]
|
[app.main.data.plugins :as dp]
|
||||||
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||||
|
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.plugins.register :as preg]
|
[app.plugins.register :as preg]
|
||||||
|
@ -40,14 +42,22 @@
|
||||||
icon))
|
icon))
|
||||||
|
|
||||||
(mf/defc plugin-entry
|
(mf/defc plugin-entry
|
||||||
[{:keys [index manifest on-open-plugin on-remove-plugin]}]
|
[{:keys [index manifest user-can-edit on-open-plugin on-remove-plugin]}]
|
||||||
|
|
||||||
|
(let [{:keys [plugin-id host icon name description permissions]} manifest
|
||||||
|
plugins-permissions-peek (deref refs/plugins-permissions-peek)
|
||||||
|
permissions (or (get plugins-permissions-peek plugin-id)
|
||||||
|
permissions)
|
||||||
|
is-edition-plugin? (or (contains? permissions "content:write")
|
||||||
|
(contains? permissions "library:write"))
|
||||||
|
can-open? (or user-can-edit
|
||||||
|
(not is-edition-plugin?))
|
||||||
|
|
||||||
(let [{:keys [host icon name description]} manifest
|
|
||||||
handle-open-click
|
handle-open-click
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps index manifest on-open-plugin)
|
(mf/deps index manifest on-open-plugin can-open?)
|
||||||
(fn []
|
(fn []
|
||||||
(when on-open-plugin
|
(when (and can-open? on-open-plugin)
|
||||||
(on-open-plugin manifest))))
|
(on-open-plugin manifest))))
|
||||||
|
|
||||||
handle-delete-click
|
handle-delete-click
|
||||||
|
@ -64,8 +74,14 @@
|
||||||
[:div {:class (stl/css :plugin-description)}
|
[:div {:class (stl/css :plugin-description)}
|
||||||
[:div {:class (stl/css :plugin-title)} name]
|
[:div {:class (stl/css :plugin-title)} name]
|
||||||
[:div {:class (stl/css :plugin-summary)} (d/nilv description "")]]
|
[:div {:class (stl/css :plugin-summary)} (d/nilv description "")]]
|
||||||
[:button {:class (stl/css :open-button)
|
|
||||||
:on-click handle-open-click} (tr "workspace.plugins.button-open")]
|
|
||||||
|
[:> button* {:class (stl/css :open-button)
|
||||||
|
:variant "secondary"
|
||||||
|
:on-click handle-open-click
|
||||||
|
:title (when-not can-open? (tr "workspace.plugins.error.need-editor"))
|
||||||
|
:disabled (not can-open?)} (tr "workspace.plugins.button-open")]
|
||||||
|
|
||||||
[:> icon-button* {:variant "ghost"
|
[:> icon-button* {:variant "ghost"
|
||||||
:aria-label (tr "workspace.plugins.remove-plugin")
|
:aria-label (tr "workspace.plugins.remove-plugin")
|
||||||
:on-click handle-delete-click
|
:on-click handle-delete-click
|
||||||
|
@ -91,6 +107,8 @@
|
||||||
error-manifest? (= :error-manifest input-status)
|
error-manifest? (= :error-manifest input-status)
|
||||||
error? (or error-url? error-manifest?)
|
error? (or error-url? error-manifest?)
|
||||||
|
|
||||||
|
user-can-edit? (:can-edit (deref refs/permissions))
|
||||||
|
|
||||||
handle-close-dialog
|
handle-close-dialog
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -137,7 +155,7 @@
|
||||||
::ev/origin "workspace:plugins"
|
::ev/origin "workspace:plugins"
|
||||||
:name (:name manifest)
|
:name (:name manifest)
|
||||||
:host (:host manifest)}))
|
:host (:host manifest)}))
|
||||||
(dp/open-plugin! manifest)
|
(dp/open-plugin! manifest user-can-edit?)
|
||||||
(modal/hide!)))
|
(modal/hide!)))
|
||||||
|
|
||||||
handle-remove-plugin
|
handle-remove-plugin
|
||||||
|
@ -204,6 +222,7 @@
|
||||||
[:& plugin-entry {:key (dm/str "plugin-" idx)
|
[:& plugin-entry {:key (dm/str "plugin-" idx)
|
||||||
:index idx
|
:index idx
|
||||||
:manifest manifest
|
:manifest manifest
|
||||||
|
:user-can-edit user-can-edit?
|
||||||
:on-open-plugin handle-open-plugin
|
:on-open-plugin handle-open-plugin
|
||||||
:on-remove-plugin handle-remove-plugin}])]])]]]))
|
:on-remove-plugin handle-remove-plugin}])]])]]]))
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@
|
||||||
@include flexCenter;
|
@include flexCenter;
|
||||||
width: $s-20;
|
width: $s-20;
|
||||||
padding: 0 0 0 $s-8;
|
padding: 0 0 0 $s-8;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
@extend .button-icon-small;
|
@extend .button-icon-small;
|
||||||
stroke: var(--icon-foreground);
|
stroke: var(--icon-foreground);
|
||||||
|
@ -114,7 +115,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.open-button {
|
.open-button {
|
||||||
@extend .button-secondary;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
width: $s-68;
|
width: $s-68;
|
||||||
min-width: $s-68;
|
min-width: $s-68;
|
||||||
height: $s-32;
|
height: $s-32;
|
||||||
|
|
|
@ -111,6 +111,8 @@
|
||||||
modifiers (mf/deref refs/workspace-modifiers)
|
modifiers (mf/deref refs/workspace-modifiers)
|
||||||
text-modifiers (mf/deref refs/workspace-text-modifier)
|
text-modifiers (mf/deref refs/workspace-text-modifier)
|
||||||
|
|
||||||
|
render-context-lost? (mf/deref refs/render-context-lost?)
|
||||||
|
|
||||||
objects-modified (mf/with-memo [base-objects text-modifiers modifiers]
|
objects-modified (mf/with-memo [base-objects text-modifiers modifiers]
|
||||||
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
|
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
|
||||||
|
|
||||||
|
@ -175,6 +177,8 @@
|
||||||
|
|
||||||
mode-inspect? (= options-mode :inspect)
|
mode-inspect? (= options-mode :inspect)
|
||||||
|
|
||||||
|
on-render-restore-context #(.reload js/location)
|
||||||
|
|
||||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect z?)
|
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect z?)
|
||||||
on-context-menu (actions/on-context-menu hover hover-ids read-only?)
|
on-context-menu (actions/on-context-menu hover hover-ids read-only?)
|
||||||
on-double-click (actions/on-double-click hover hover-ids hover-top-frame-id drawing-path? base-objects edition drawing-tool z? read-only?)
|
on-double-click (actions/on-double-click hover hover-ids hover-top-frame-id drawing-path? base-objects edition drawing-tool z? read-only?)
|
||||||
|
@ -277,9 +281,9 @@
|
||||||
(p/fmap (fn [ready?]
|
(p/fmap (fn [ready?]
|
||||||
(when ready?
|
(when ready?
|
||||||
(reset! canvas-init? true)
|
(reset! canvas-init? true)
|
||||||
(render.wasm/assign-canvas canvas)))))
|
(render.wasm/setup-canvas canvas)))))
|
||||||
(fn []
|
(fn []
|
||||||
(render.wasm/clear-canvas))))
|
(render.wasm/dispose-canvas canvas))))
|
||||||
|
|
||||||
(mf/with-effect [objects-modified canvas-init?]
|
(mf/with-effect [objects-modified canvas-init?]
|
||||||
(when @canvas-init?
|
(when @canvas-init?
|
||||||
|
@ -635,4 +639,11 @@
|
||||||
{:objects base-objects
|
{:objects base-objects
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:vbox vbox
|
:vbox vbox
|
||||||
:bottom-padding (when palete-size (+ palete-size 8))}]]]]]))
|
:bottom-padding (when palete-size (+ palete-size 8))}]]]]
|
||||||
|
|
||||||
|
(when render-context-lost?
|
||||||
|
[:div {:id "context-lost" :class (stl/css :context-lost)}
|
||||||
|
[:h1 "GL Error Screen"]
|
||||||
|
[:button
|
||||||
|
{:on-click on-render-restore-context}
|
||||||
|
"Restore context"]])]))
|
||||||
|
|
|
@ -35,3 +35,13 @@
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.context-lost {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 100;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.types.shape.impl]
|
[app.common.types.shape.impl]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
[app.main.data.render-wasm :as drw]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[app.util.debug :as dbg]
|
||||||
|
[app.util.dom :as dom]
|
||||||
[promesa.core :as p]))
|
[promesa.core :as p]))
|
||||||
|
|
||||||
(def enabled?
|
(def enabled?
|
||||||
|
@ -82,29 +86,67 @@
|
||||||
:stencil true
|
:stencil true
|
||||||
:alpha true})
|
:alpha true})
|
||||||
|
|
||||||
(defn clear-canvas
|
(defn init-skia
|
||||||
[]
|
[canvas]
|
||||||
;; TODO: perform corresponding cleaning
|
(let [init-fn (unchecked-get internal-module "_init")
|
||||||
)
|
state (init-fn (.-width ^js canvas)
|
||||||
|
(.-height ^js canvas))]
|
||||||
|
(set! internal-gpu-state state)))
|
||||||
|
|
||||||
(defn assign-canvas
|
;; NOTE: This function can be called externally
|
||||||
|
;; by the button in the context lost component (shown
|
||||||
|
;; in viewport-wasm) or called internally by
|
||||||
|
;; on-webgl-context
|
||||||
|
(defn restore-canvas
|
||||||
|
[canvas]
|
||||||
|
(st/emit! (drw/context-restored))
|
||||||
|
;; We need to reinitialize skia when the
|
||||||
|
;; context is restored.
|
||||||
|
(init-skia canvas))
|
||||||
|
|
||||||
|
;; Handles both events: webglcontextlost and
|
||||||
|
;; webglcontextrestored
|
||||||
|
(defn on-webgl-context
|
||||||
|
[event]
|
||||||
|
(dom/prevent-default event)
|
||||||
|
(if (= (.-type event) "webglcontextlost")
|
||||||
|
(st/emit! (drw/context-lost))
|
||||||
|
(restore-canvas (dom/get-target event))))
|
||||||
|
|
||||||
|
(defn dispose-canvas
|
||||||
|
[canvas]
|
||||||
|
;; TODO: perform corresponding cleaning
|
||||||
|
(.removeEventListener canvas "webglcontextlost" on-webgl-context)
|
||||||
|
(.removeEventListener canvas "webglcontextrestored" on-webgl-context))
|
||||||
|
|
||||||
|
(defn init-debug-webgl-context-state
|
||||||
|
[context]
|
||||||
|
(let [context-extension (.getExtension ^js context "WEBGL_lose_context")
|
||||||
|
info-extension (.getExtension ^js context "WEBGL_debug_renderer_info")]
|
||||||
|
(set! (.-penpotGL js/window) #js {:context context-extension
|
||||||
|
:renderer info-extension})
|
||||||
|
(js/console.log "WEBGL_lose_context" context-extension)
|
||||||
|
(js/console.log "WEBGL_debug_renderer_info" info-extension)))
|
||||||
|
|
||||||
|
(defn setup-canvas
|
||||||
[canvas]
|
[canvas]
|
||||||
(let [gl (unchecked-get internal-module "GL")
|
(let [gl (unchecked-get internal-module "GL")
|
||||||
init-fn (unchecked-get internal-module "_init")
|
|
||||||
|
|
||||||
context (.getContext ^js canvas "webgl2" canvas-options)
|
context (.getContext ^js canvas "webgl2" canvas-options)
|
||||||
|
|
||||||
;; Register the context with emscripten
|
;; Register the context with emscripten
|
||||||
handle (.registerContext ^js gl context #js {"majorVersion" 2})
|
handle (.registerContext ^js gl context #js {"majorVersion" 2})
|
||||||
_ (.makeContextCurrent ^js gl handle)
|
_ (.makeContextCurrent ^js gl handle)]
|
||||||
|
|
||||||
;; Initialize Skia
|
(when (dbg/enabled? :gl-context)
|
||||||
state (init-fn (.-width ^js canvas)
|
(init-debug-webgl-context-state context))
|
||||||
(.-height ^js canvas))]
|
|
||||||
|
(.addEventListener canvas "webglcontextlost" on-webgl-context)
|
||||||
|
(.addEventListener canvas "webglcontextrestored" on-webgl-context)
|
||||||
|
|
||||||
(set! (.-width canvas) (.-clientWidth ^js canvas))
|
(set! (.-width canvas) (.-clientWidth ^js canvas))
|
||||||
(set! (.-height canvas) (.-clientHeight ^js canvas))
|
(set! (.-height canvas) (.-clientHeight ^js canvas))
|
||||||
(set! internal-gpu-state state)))
|
|
||||||
|
(init-skia canvas)))
|
||||||
|
|
||||||
(defonce module
|
(defonce module
|
||||||
(->> (js/dynamicImport "/js/render_wasm.js")
|
(->> (js/dynamicImport "/js/render_wasm.js")
|
||||||
|
|
|
@ -89,7 +89,10 @@
|
||||||
:display-touched
|
:display-touched
|
||||||
|
|
||||||
;; Show some visual indicators for bool shape
|
;; Show some visual indicators for bool shape
|
||||||
:bool-shapes})
|
:bool-shapes
|
||||||
|
|
||||||
|
;; Show some information about the WebGL context.
|
||||||
|
:gl-context})
|
||||||
|
|
||||||
(defn enable!
|
(defn enable!
|
||||||
[option]
|
[option]
|
||||||
|
|
|
@ -5859,6 +5859,10 @@ msgstr "Plugins"
|
||||||
msgid "workspace.plugins.remove-plugin"
|
msgid "workspace.plugins.remove-plugin"
|
||||||
msgstr "Remove plugin"
|
msgstr "Remove plugin"
|
||||||
|
|
||||||
|
#: src/app/main/data/plugins.cljs:78
|
||||||
|
msgid "workspace.plugins.error.need-editor"
|
||||||
|
msgstr "You need to be an editor to use this plugin"
|
||||||
|
|
||||||
#: /src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1005
|
#: /src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1005
|
||||||
msgid "workspace.shape.menu.add-layout"
|
msgid "workspace.shape.menu.add-layout"
|
||||||
msgstr "Add layout"
|
msgstr "Add layout"
|
||||||
|
|
|
@ -5837,6 +5837,10 @@ msgstr "Extensiones"
|
||||||
msgid "workspace.plugins.remove-plugin"
|
msgid "workspace.plugins.remove-plugin"
|
||||||
msgstr "Eliminar extensión"
|
msgstr "Eliminar extensión"
|
||||||
|
|
||||||
|
#: src/app/main/data/plugins.cljs:78
|
||||||
|
msgid "workspace.plugins.error.need-editor"
|
||||||
|
msgstr "Debes ser un editor para usar este plugin"
|
||||||
|
|
||||||
#: /src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1005
|
#: /src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1005
|
||||||
msgid "workspace.shape.menu.add-layout"
|
msgid "workspace.shape.menu.add-layout"
|
||||||
msgstr "Añadir layout"
|
msgstr "Añadir layout"
|
||||||
|
|
|
@ -948,10 +948,10 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@penpot/text-editor@penpot/penpot-text-editor#449e3322f3fa40b1318c9154afbbc7932a3cb766":
|
"@penpot/text-editor@penpot/penpot-text-editor#a100aad8d0efcbb070bed9144dbd2782547e78ba":
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
resolution: "@penpot/text-editor@https://github.com/penpot/penpot-text-editor.git#commit=449e3322f3fa40b1318c9154afbbc7932a3cb766"
|
resolution: "@penpot/text-editor@https://github.com/penpot/penpot-text-editor.git#commit=a100aad8d0efcbb070bed9144dbd2782547e78ba"
|
||||||
checksum: 10c0/377fbd1fccc91ce532356601a27fe11afe19f169748127884f39a6b231a037e7e1e8b401149062e39219715901933771b7d752accaa52682fb141889c22dd1d3
|
checksum: 10c0/328c827cd740c5e05df678083cfb1d2b6d006b56523daa0bd2a3c2936a0490a2ae4d0e69a3aec428674609a22a5fafdd5600aae1399cb3f4ed5b80e497c74a5c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -4300,7 +4300,7 @@ __metadata:
|
||||||
"@penpot/hljs": "portal:./vendor/hljs"
|
"@penpot/hljs": "portal:./vendor/hljs"
|
||||||
"@penpot/mousetrap": "portal:./vendor/mousetrap"
|
"@penpot/mousetrap": "portal:./vendor/mousetrap"
|
||||||
"@penpot/svgo": "penpot/svgo#c6fba7a4dcfbc27b643e7fc0c94fc98cf680b77b"
|
"@penpot/svgo": "penpot/svgo#c6fba7a4dcfbc27b643e7fc0c94fc98cf680b77b"
|
||||||
"@penpot/text-editor": "penpot/penpot-text-editor#449e3322f3fa40b1318c9154afbbc7932a3cb766"
|
"@penpot/text-editor": "penpot/penpot-text-editor#a100aad8d0efcbb070bed9144dbd2782547e78ba"
|
||||||
"@playwright/test": "npm:1.48.1"
|
"@playwright/test": "npm:1.48.1"
|
||||||
"@storybook/addon-essentials": "npm:^8.3.6"
|
"@storybook/addon-essentials": "npm:^8.3.6"
|
||||||
"@storybook/addon-themes": "npm:^8.3.6"
|
"@storybook/addon-themes": "npm:^8.3.6"
|
||||||
|
|
18
render-wasm/Cargo.lock
generated
18
render-wasm/Cargo.lock
generated
|
@ -96,6 +96,22 @@ version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "emscripten-functions"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62c026cc030b24957ca45d9555f9fa241d6b3a01d725cd98a25924de249b840a"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"emscripten-functions-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "emscripten-functions-sys"
|
||||||
|
version = "4.1.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65715a5f07b03636d7cd5508a45d1b62486840cb7d91a66564a73f1d7aa70b79"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -370,6 +386,8 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
name = "render"
|
name = "render"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"emscripten-functions",
|
||||||
|
"emscripten-functions-sys",
|
||||||
"gl",
|
"gl",
|
||||||
"skia-safe",
|
"skia-safe",
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,6 +11,8 @@ name = "render_wasm"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
emscripten-functions = "0.2.3"
|
||||||
|
emscripten-functions-sys = "4.1.67"
|
||||||
gl = "0.14.0"
|
gl = "0.14.0"
|
||||||
skia-safe = { version = "0.78.2", features = ["gl"] }
|
skia-safe = { version = "0.78.2", features = ["gl"] }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue