Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2025-04-15 12:10:53 +02:00
commit bb80da137d
30 changed files with 242 additions and 205 deletions

View file

@ -155,9 +155,9 @@
[["" {:middleware [[mw/server-timing] [["" {:middleware [[mw/server-timing]
[mw/params] [mw/params]
[mw/format-response] [mw/format-response]
[mw/parse-request]
[session/soft-auth cfg] [session/soft-auth cfg]
[actoken/soft-auth cfg] [actoken/soft-auth cfg]
[mw/parse-request]
[mw/errors errors/handle] [mw/errors errors/handle]
[mw/restrict-methods]]} [mw/restrict-methods]]}

View file

@ -395,9 +395,15 @@
(defn parse-uuid (defn parse-uuid
[s] [s]
(if (string? s) (try
(some->> (re-matches uuid-rx s) uuid/uuid) (uuid/parse s)
s)) (catch #?(:clj Exception :cljs :default) _cause
s)))
(defn encode-uuid
[v]
(when (uuid? v)
(str v)))
(register! (register!
{:type ::uuid {:type ::uuid
@ -409,8 +415,8 @@
:gen/gen (sg/uuid) :gen/gen (sg/uuid)
:decode/string parse-uuid :decode/string parse-uuid
:decode/json parse-uuid :decode/json parse-uuid
:encode/string str :encode/string encode-uuid
:encode/json str :encode/json encode-uuid
::oapi/type "string" ::oapi/type "string"
::oapi/format "uuid"}}) ::oapi/format "uuid"}})

View file

@ -17,9 +17,14 @@
java.util.UUID java.util.UUID
java.nio.ByteBuffer))) java.nio.ByteBuffer)))
(def regex
#"^[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$")
(defn uuid (defn uuid
"Creates an UUID instance from string, expectes valid uuid strings, "Creates an UUID instance from string, expectes valid uuid strings,
the existense of validation is implementation detail" the existense of validation is implementation detail.
UNSAFE: this can accept invalid uuids or incomplete uuids"
[s] [s]
#?(:clj (UUID/fromString s) #?(:clj (UUID/fromString s)
:cljs (c/uuid s))) :cljs (c/uuid s)))
@ -27,8 +32,21 @@
(defn parse (defn parse
"Parse string uuid representation into proper UUID instance, validates input" "Parse string uuid representation into proper UUID instance, validates input"
[s] [s]
(if (and (string? s) ^boolean (re-matches regex s))
#?(:clj (UUID/fromString s) #?(:clj (UUID/fromString s)
:cljs (c/parse-uuid s))) :cljs (uuid s))
(let [message (str "invalid string '" s "' for uuid")]
(throw #?(:clj (IllegalArgumentException. message)
:cljs (js/Error. message))))))
(defn parse*
"Exception safe version of `parse`."
[s]
(try
(parse s)
(catch #?(:clj Exception :cljs :default) _cause
nil)))
(defn next (defn next
[] []

View file

@ -156,10 +156,13 @@ http {
} }
location / { location / {
location ~ ^/github/penpot-files/(?<template_file>[a-zA-Z0-9\-\_\.]+) { location ~ ^/github/penpot-files/(.+)$ {
proxy_pass https://raw.githubusercontent.com/penpot/penpot-files/main/$template_file; rewrite ^/github/penpot-files/(.+) /penpot/penpot-files/refs/heads/main/$1 break;
proxy_pass https://raw.githubusercontent.com;
proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Origin;
proxy_set_header User-Agent "curl/7.74.0"; proxy_hide_header Cookies;
proxy_set_header User-Agent "curl/8.5.0";
proxy_set_header Host "raw.githubusercontent.com"; proxy_set_header Host "raw.githubusercontent.com";
proxy_set_header Accept "*/*"; proxy_set_header Accept "*/*";
add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Origin $http_origin;

View file

@ -135,10 +135,13 @@ http {
} }
location / { location / {
location ~ ^/github/penpot-files/(?<template_file>[a-zA-Z0-9\-\_\.]+) { location ~ ^/github/penpot-files/(.+)$ {
proxy_pass https://raw.githubusercontent.com/penpot/penpot-files/main/$template_file; rewrite ^/github/penpot-files/(.+) /penpot/penpot-files/refs/heads/main/$1 break;
proxy_pass https://raw.githubusercontent.com;
proxy_hide_header Access-Control-Allow-Origin; proxy_hide_header Access-Control-Allow-Origin;
proxy_set_header User-Agent "curl/7.74.0"; proxy_hide_header Cookies;
proxy_set_header User-Agent "curl/8.5.0";
proxy_set_header Host "raw.githubusercontent.com"; proxy_set_header Host "raw.githubusercontent.com";
proxy_set_header Accept "*/*"; proxy_set_header Accept "*/*";
add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Origin $http_origin;

View file

@ -239,15 +239,15 @@
(str (:last-id file))) (str (:last-id file)))
(lookupShape [_ shape-id] (lookupShape [_ shape-id]
(clj->js (fb/lookup-shape file (uuid/uuid shape-id)))) (clj->js (fb/lookup-shape file (uuid/parse shape-id))))
(updateObject [_ id new-obj] (updateObject [_ id new-obj]
(let [old-obj (fb/lookup-shape file (uuid/uuid id)) (let [old-obj (fb/lookup-shape file (uuid/parse id))
new-obj (d/deep-merge old-obj (parse-data new-obj))] new-obj (d/deep-merge old-obj (parse-data new-obj))]
(set! file (fb/update-object file old-obj new-obj)))) (set! file (fb/update-object file old-obj new-obj))))
(deleteObject [_ id] (deleteObject [_ id]
(set! file (fb/delete-object file (uuid/uuid id)))) (set! file (fb/delete-object file (uuid/parse id))))
(getId [_] (getId [_]
(:id file)) (:id file))

View file

@ -15,7 +15,7 @@
[file ^string page-id] [file ^string page-id]
;; Better to expose the api as a promise to be consumed from JS ;; Better to expose the api as a promise to be consumed from JS
(let [page-id (uuid/uuid page-id) (let [page-id (uuid/parse page-id)
file-data (.-file file) file-data (.-file file)
data (get-in file-data [:data :pages-index page-id])] data (get-in file-data [:data :pages-index page-id])]
(p/create (p/create

View file

@ -69,7 +69,7 @@
"Retrieves the mentions in the content as an array of uuids" "Retrieves the mentions in the content as an array of uuids"
[content] [content]
(->> (re-seq r-mentions content) (->> (re-seq r-mentions content)
(mapv (fn [[_ _ id]] (uuid/uuid id))))) (mapv (fn [[_ _ id]] (uuid/parse id)))))
(defn update-mentions (defn update-mentions
"Updates the params object with the mentiosn" "Updates the params object with the mentiosn"

View file

@ -248,7 +248,7 @@
(defn fetch-comments (defn fetch-comments
[{:keys [thread-id]}] [{:keys [thread-id]}]
(dm/assert! (uuid thread-id)) (assert (uuid? thread-id))
(letfn [(fetched [comments state] (letfn [(fetched [comments state]
(update state :comments assoc thread-id (d/index-by :id comments)))] (update state :comments assoc thread-id (d/index-by :id comments)))]
(ptk/reify ::retrieve-comments (ptk/reify ::retrieve-comments
@ -413,7 +413,7 @@
(watch [_ state _] (watch [_ state _]
(let [params (rt/get-params state) (let [params (rt/get-params state)
index (some-> params :index parse-long) index (some-> params :index parse-long)
page-id (some-> params :page-id parse-uuid) page-id (some-> params :page-id uuid/parse)
total (count (get-in state [:viewer :pages page-id :frames]))] total (count (get-in state [:viewer :pages page-id :frames]))]

View file

@ -372,7 +372,7 @@
(rx/take 1) (rx/take 1)
(rx/map dwc/set-workspace-visited)) (rx/map dwc/set-workspace-visited))
(when-let [component-id (some-> rparams :component-id parse-uuid)] (when-let [component-id (some-> rparams :component-id uuid/parse)]
(->> stream (->> stream
(rx/filter (ptk/type? ::workspace-initialized)) (rx/filter (ptk/type? ::workspace-initialized))
(rx/observe-on :async) (rx/observe-on :async)
@ -385,7 +385,7 @@
(rx/take 1) (rx/take 1)
(rx/map zoom-to-frame))) (rx/map zoom-to-frame)))
(when-let [comment-id (some-> rparams :comment-id parse-uuid)] (when-let [comment-id (some-> rparams :comment-id uuid/parse)]
(->> stream (->> stream
(rx/filter (ptk/type? ::workspace-initialized)) (rx/filter (ptk/type? ::workspace-initialized))
(rx/observe-on :async) (rx/observe-on :async)
@ -2462,13 +2462,6 @@
(js/console.log "Copies no ref" (count copies-no-ref) (clj->js copies-no-ref)) (js/console.log "Copies no ref" (count copies-no-ref) (clj->js copies-no-ref))
(js/console.log "Childs no ref" (count childs-no-ref) (clj->js childs-no-ref)))))) (js/console.log "Childs no ref" (count childs-no-ref) (clj->js childs-no-ref))))))
(defn set-shape-ref
[id shape-ref]
(ptk/reify ::set-shape-ref
ptk/WatchEvent
(watch [_ _ _]
(rx/of (update-shape (uuid/uuid id) {:shape-ref (uuid/uuid shape-ref)})))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Exports ;; Exports
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -7,6 +7,7 @@
(ns app.main.ui (ns app.main.ui
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.data.common :as dcm] [app.main.data.common :as dcm]
[app.main.data.team :as dtm] [app.main.data.team :as dtm]
@ -69,7 +70,7 @@
(mf/defc dashboard-legacy-redirect* (mf/defc dashboard-legacy-redirect*
{::mf/props :obj {::mf/props :obj
::mf/private true} ::mf/private true}
[{:keys [section team-id project-id search-term plugin-url template-url]}] [{:keys [section team-id project-id search-term plugin-url template]}]
(let [section (case section (let [section (case section
:dashboard-legacy-search :dashboard-legacy-search
:dashboard-search :dashboard-search
@ -97,7 +98,7 @@
:project-id project-id :project-id project-id
:search-term search-term :search-term search-term
:plugin plugin-url :plugin plugin-url
:template-url template-url}] :template template}]
(st/emit! (rt/nav section (d/without-nils params))))) (st/emit! (rt/nav section (d/without-nils params)))))
[:> loader* [:> loader*
@ -212,11 +213,11 @@
:dashboard-webhooks :dashboard-webhooks
:dashboard-settings) :dashboard-settings)
(let [params (get params :query) (let [params (get params :query)
team-id (some-> params :team-id uuid) team-id (some-> params :team-id uuid/parse*)
project-id (some-> params :project-id uuid) project-id (some-> params :project-id uuid/parse*)
search-term (some-> params :search-term) search-term (some-> params :search-term)
plugin-url (some-> params :plugin) plugin-url (some-> params :plugin)
template-url (some-> params :template)] template (some-> params :template)]
[:? [:?
#_[:& app.main.ui.releases/release-notes-modal {:version "2.5"}] #_[:& app.main.ui.releases/release-notes-modal {:version "2.5"}]
#_[:& app.main.ui.onboarding/onboarding-templates-modal] #_[:& app.main.ui.onboarding/onboarding-templates-modal]
@ -243,13 +244,13 @@
:search-term search-term :search-term search-term
:plugin-url plugin-url :plugin-url plugin-url
:project-id project-id :project-id project-id
:template-url template-url}]]]) :template template}]]])
:workspace :workspace
(let [params (get params :query) (let [params (get params :query)
team-id (some-> params :team-id uuid) team-id (some-> params :team-id uuid/parse*)
file-id (some-> params :file-id uuid) file-id (some-> params :file-id uuid/parse*)
page-id (some-> params :page-id uuid) page-id (some-> params :page-id uuid/parse*)
layout (some-> params :layout keyword)] layout (some-> params :layout keyword)]
[:? {} [:? {}
(when (cf/external-feature-flag "onboarding-03" "test") (when (cf/external-feature-flag "onboarding-03" "test")
@ -276,15 +277,15 @@
:viewer :viewer
(let [params (get params :query) (let [params (get params :query)
index (some-> (:index params) parse-long) index (some-> (:index params) parse-long)
share-id (some-> (:share-id params) parse-uuid) share-id (some-> (:share-id params) uuid/parse*)
section (or (some-> (:section params) keyword) section (or (some-> (:section params) keyword)
:interactions) :interactions)
file-id (some-> (:file-id params) parse-uuid) file-id (some-> (:file-id params) uuid/parse*)
page-id (some-> (:page-id params) parse-uuid) page-id (some-> (:page-id params) uuid/parse*)
imode (or (some-> (:interactions-mode params) keyword) imode (or (some-> (:interactions-mode params) keyword)
:show-on-click) :show-on-click)
frame-id (some-> (:frame-id params) parse-uuid) frame-id (some-> (:frame-id params) uuid/parse*)
share (:share params)] share (:share params)]
[:? {} [:? {}
@ -300,9 +301,9 @@
:workspace-legacy :workspace-legacy
(let [project-id (some-> params :path :project-id uuid) (let [project-id (some-> params :path :project-id uuid/parse*)
file-id (some-> params :path :file-id uuid) file-id (some-> params :path :file-id uuid/parse*)
page-id (some-> params :query :page-id uuid) page-id (some-> params :query :page-id uuid/parse*)
layout (some-> params :query :layout keyword)] layout (some-> params :query :layout keyword)]
[:> workspace-legacy-redirect* [:> workspace-legacy-redirect*
@ -321,18 +322,18 @@
:dashboard-legacy-team-invitations :dashboard-legacy-team-invitations
:dashboard-legacy-team-webhooks :dashboard-legacy-team-webhooks
:dashboard-legacy-team-settings) :dashboard-legacy-team-settings)
(let [team-id (some-> params :path :team-id uuid) (let [team-id (some-> params :path :team-id uuid/parse*)
project-id (some-> params :path :project-id uuid) project-id (some-> params :path :project-id uuid/parse*)
search-term (some-> params :query :search-term) search-term (some-> params :query :search-term)
plugin-url (some-> params :query :plugin) plugin-url (some-> params :query :plugin)
template-url (some-> params :template)] template (some-> params :template)]
[:> dashboard-legacy-redirect* [:> dashboard-legacy-redirect*
{:team-id team-id {:team-id team-id
:section section :section section
:project-id project-id :project-id project-id
:search-term search-term :search-term search-term
:plugin-url plugin-url :plugin-url plugin-url
:template-url template-url}]) :template template}])
:viewer-legacy :viewer-legacy
(let [{:keys [query-params path-params]} route (let [{:keys [query-params path-params]} route

View file

@ -487,7 +487,7 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(let [id (-> (dom/get-current-target event) (let [id (-> (dom/get-current-target event)
(dom/get-data "user-id") (dom/get-data "user-id")
(uuid/uuid)) (uuid/parse))
user (d/seek #(= (:id %) id) members)] user (d/seek #(= (:id %) id) members)]

View file

@ -34,12 +34,10 @@
[app.main.ui.workspace.plugins] [app.main.ui.workspace.plugins]
[app.plugins.register :as preg] [app.plugins.register :as preg]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.http :as http]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[app.util.object :as obj] [app.util.object :as obj]
[app.util.storage :as storage] [app.util.storage :as storage]
[app.util.webapi :as wapi]
[beicon.v2.core :as rx] [beicon.v2.core :as rx]
[cuerdas.core :as str] [cuerdas.core :as str]
[goog.events :as events] [goog.events :as events]
@ -211,17 +209,22 @@
(swap! storage/session dissoc :plugin-url)))))) (swap! storage/session dissoc :plugin-url))))))
(defn use-templates-import (defn use-templates-import
[can-edit? template-url project] [can-edit? template project]
(let [project-id (get project :id) (let [project-id (get project :id)
team-id (get project :team-id)] team-id (get project :team-id)]
(mf/with-layout-effect [can-edit? template-url project-id team-id] (mf/with-layout-effect [can-edit? template project-id team-id]
(when (and (some? template-url) (when (and (some? template)
(some? project-id) (some? project-id)
(some? team-id)) (some? team-id))
(if can-edit? (if can-edit?
(let [valid-url? (and (str/ends-with? template-url ".penpot") (let [valid-url? (str/ends-with? template ".penpot")
(str/starts-with? template-url cf/templates-uri))
template-name (when valid-url? (subs template-url (count cf/templates-uri))) ;; Backwards compatibility, ideally the template should be only the .penpot file name, not the full url
template-name (if (str/starts-with? template "http")
(subs template (count cf/templates-uri))
template)
template-url (str "/github/penpot-files/" template-name)
on-import #(st/emit! (dpj/fetch-files project-id) on-import #(st/emit! (dpj/fetch-files project-id)
(dd/fetch-recent-files team-id) (dd/fetch-recent-files team-id)
(dd/fetch-projects team-id) (dd/fetch-projects team-id)
@ -230,30 +233,22 @@
:name template-name :name template-name
:url template-url}))] :url template-url}))]
(if valid-url? (if valid-url?
(do (st/emit!
(st/emit! (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url})) (ptk/event ::ev/event {::ev/name "install-template-from-link" :name template-name :url template-url})
(->> (http/send! {:method :get (modal/show
:uri template-url
:response-type :blob
:omit-default-headers true})
(rx/subs!
(fn [result]
(if (or (< (:status result) 200) (>= (:status result) 300))
(st/emit! (notif/error (tr "dashboard.import.error")))
(st/emit! (modal/show
{:type :import {:type :import
:project-id project-id :project-id project-id
:entries [{:name template-name :uri (wapi/create-uri (:body result))}] :entries [{:name template-name :uri template-url}]
:on-finish-import on-import}))))))) :on-finish-import on-import}))
(st/emit! (notif/error (tr "dashboard.import.bad-url"))))) (st/emit! (notif/error (tr "dashboard.import.bad-url")))))
(st/emit! (notif/error (tr "dashboard.import.no-perms")))) (st/emit! (notif/error (tr "dashboard.import.no-perms"))))
(binding [storage/*sync* true] (binding [storage/*sync* true]
(swap! storage/session dissoc :template-url)))))) (swap! storage/session dissoc :template))))))
(mf/defc dashboard* (mf/defc dashboard*
{::mf/props :obj} {::mf/props :obj}
[{:keys [profile project-id team-id search-term plugin-url template-url section]}] [{:keys [profile project-id team-id search-term plugin-url template section]}]
(let [team (mf/deref refs/team) (let [team (mf/deref refs/team)
projects (mf/deref refs/projects) projects (mf/deref refs/projects)
@ -263,7 +258,7 @@
(filterv #(= team-id (:team-id %))))) (filterv #(= team-id (:team-id %)))))
can-edit? (dm/get-in team [:permissions :can-edit]) can-edit? (dm/get-in team [:permissions :can-edit])
template-url (or template-url (:template-url storage/session)) template (or template (:template storage/session))
plugin-url (or plugin-url (:plugin-url storage/session)) plugin-url (or plugin-url (:plugin-url storage/session))
default-project default-project
@ -289,7 +284,7 @@
(events/unlistenByKey key)))) (events/unlistenByKey key))))
(use-plugin-register plugin-url team-id (:id default-project)) (use-plugin-register plugin-url team-id (:id default-project))
(use-templates-import can-edit? template-url default-project) (use-templates-import can-edit? template default-project)
[:& (mf/provider ctx/current-project-id) {:value project-id} [:& (mf/provider ctx/current-project-id) {:value project-id}
[:> modal-container*] [:> modal-container*]

View file

@ -9,6 +9,7 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.media :as cm] [app.common.media :as cm]
[app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.data.fonts :as df] [app.main.data.fonts :as df]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
@ -121,7 +122,7 @@
(fn [event] (fn [event]
(let [id (-> (dom/get-current-target event) (let [id (-> (dom/get-current-target event)
(dom/get-data "id") (dom/get-data "id")
(parse-uuid)) (uuid/parse))
item (get fonts id)] item (get fonts id)]
(on-upload* item)))) (on-upload* item))))
@ -132,7 +133,7 @@
(let [target (dom/get-current-target event) (let [target (dom/get-current-target event)
id (-> target id (-> target
(dom/get-data "id") (dom/get-data "id")
(parse-uuid)) (uuid/parse))
name (dom/get-value target)] name (dom/get-value target)]
(when-not (str/blank? name) (when-not (str/blank? name)
(swap! fonts* df/rename-and-regroup id name installed-fonts))))) (swap! fonts* df/rename-and-regroup id name installed-fonts)))))
@ -143,7 +144,7 @@
(let [target (dom/get-current-target event) (let [target (dom/get-current-target event)
id (-> target id (-> target
(dom/get-data "id") (dom/get-data "id")
(parse-uuid)) (uuid/parse))
name (dom/get-value target)] name (dom/get-value target)]
(swap! fonts* update id assoc :font-family-tmp name)))) (swap! fonts* update id assoc :font-family-tmp name))))
@ -153,7 +154,7 @@
(fn [event] (fn [event]
(let [id (-> (dom/get-current-target event) (let [id (-> (dom/get-current-target event)
(dom/get-data "id") (dom/get-data "id")
(parse-uuid))] (uuid/parse))]
(swap! fonts* dissoc id)))) (swap! fonts* dissoc id))))
on-upload-all on-upload-all
@ -344,7 +345,7 @@
(fn [event] (fn [event]
(let [id (-> (dom/get-current-target event) (let [id (-> (dom/get-current-target event)
(dom/get-data "id") (dom/get-data "id")
(parse-uuid)) (uuid/parse))
options {:type :confirm options {:type :confirm
:title (tr "modals.delete-font-variant.title") :title (tr "modals.delete-font-variant.title")
:message (tr "modals.delete-font-variant.message") :message (tr "modals.delete-font-variant.message")

View file

@ -284,7 +284,6 @@
(let [team-id (-> (dom/get-current-target event) (let [team-id (-> (dom/get-current-target event)
(dom/get-data "value") (dom/get-data "value")
(uuid/parse))] (uuid/parse))]
(st/emit! (dcm/go-to-dashboard-recent :team-id team-id))))) (st/emit! (dcm/go-to-dashboard-recent :team-id team-id)))))
handle-select-default handle-select-default

View file

@ -82,7 +82,7 @@
(binding [storage/*sync* true] (binding [storage/*sync* true]
(when (some? template) (when (some? template)
(swap! storage/session assoc (swap! storage/session assoc
:template-url template)) :template template))
(when (some? plugin) (when (some? plugin)
(swap! storage/session assoc (swap! storage/session assoc
:plugin-url plugin)))) :plugin-url plugin))))

View file

@ -202,9 +202,8 @@
cancel-text]) cancel-text])
[:button {:on-click on-click} button-text]]]])) [:button {:on-click on-click} button-text]]]]))
(mf/defc request-access (mf/defc request-access*
{::mf/props :obj} [{:keys [file-id team-id is-default is-workspace]}]
[{:keys [file-id team-id is-default workspace?]}]
(let [profile (mf/deref refs/profile) (let [profile (mf/deref refs/profile)
requested* (mf/use-state {:sent false :already-requested false}) requested* (mf/use-state {:sent false :already-requested false})
requested (deref requested*) requested (deref requested*)
@ -227,11 +226,11 @@
on-request-access on-request-access
(mf/use-fn (mf/use-fn
(mf/deps file-id team-id workspace?) (mf/deps file-id team-id is-workspace)
(fn [] (fn []
(let [params (if (some? file-id) (let [params (if (some? file-id)
{:file-id file-id {:file-id file-id
:is-viewer (not workspace?)} :is-viewer (not is-workspace)}
{:team-id team-id}) {:team-id team-id})
mdata {:on-success on-success mdata {:on-success on-success
:on-error on-error}] :on-error on-error}]
@ -240,7 +239,7 @@
[:* [:*
(if (some? file-id) (if (some? file-id)
(if workspace? (if is-workspace
[:div {:class (stl/css :workspace)} [:div {:class (stl/css :workspace)}
[:div {:class (stl/css :workspace-left)} [:div {:class (stl/css :workspace-left)}
i/logo-icon i/logo-icon
@ -341,7 +340,7 @@
[:div {:class (stl/css :sign-info)} [:div {:class (stl/css :sign-info)}
[:button {:on-click handle-retry} (tr "labels.retry")]]])) [:button {:on-click handle-retry} (tr "labels.retry")]]]))
(mf/defc service-unavailable (mf/defc service-unavailable*
[] []
(let [on-click (mf/use-fn #(st/emit! (rt/assign-exception nil)))] (let [on-click (mf/use-fn #(st/emit! (rt/assign-exception nil)))]
[:> error-container* {} [:> error-container* {}
@ -350,15 +349,15 @@
[:div {:class (stl/css :sign-info)} [:div {:class (stl/css :sign-info)}
[:button {:on-click on-click} (tr "labels.retry")]]])) [:button {:on-click on-click} (tr "labels.retry")]]]))
(defn generate-report (defn- generate-report
[data] [data]
(try (try
(let [team-id (:current-team-id @st/state) (let [team-id (:current-team-id @st/state)
profile-id (:profile-id @st/state) profile-id (:profile-id @st/state)
trace (:app.main.errors/trace data) trace (:app.main.errors/trace data)
instance (:app.main.errors/instance data) instance (:app.main.errors/instance data)]
content (with-out-str (with-out-str
(println "Hint: " (or (:hint data) (ex-message instance) "--")) (println "Hint: " (or (:hint data) (ex-message instance) "--"))
(println "Prof ID:" (str (or profile-id "--"))) (println "Prof ID:" (str (or profile-id "--")))
(println "Team ID:" (str (or team-id "--"))) (println "Team ID:" (str (or team-id "--")))
@ -391,17 +390,14 @@
(println "Last events:") (println "Last events:")
(pp/pprint @st/last-events {:length 200}) (pp/pprint @st/last-events {:length 200})
(println))] (println)))
(wapi/create-blob content "text/plain"))
(catch :default cause (catch :default cause
(.error js/console "error on generating report.txt" cause) (.error js/console "error on generating report.txt" cause)
nil))) nil)))
(mf/defc internal-error* (mf/defc internal-error*
{::mf/props :obj} [{:keys [on-reset report] :as props}]
[{:keys [data on-reset] :as props}]
(let [report-uri (mf/use-ref nil) (let [report-uri (mf/use-ref nil)
report (mf/use-memo (mf/deps data) #(generate-report data))
on-reset (or on-reset #(st/emit! (rt/assign-exception nil))) on-reset (or on-reset #(st/emit! (rt/assign-exception nil)))
on-download on-download
@ -413,8 +409,8 @@
(mf/with-effect [report] (mf/with-effect [report]
(when (some? report) (when (some? report)
(let [report (wapi/create-blob report "text/plain")
(let [uri (wapi/create-uri report)] uri (wapi/create-uri report)]
(mf/set-ref-val! report-uri uri) (mf/set-ref-val! report-uri uri)
(fn [] (fn []
(wapi/revoke-uri uri))))) (wapi/revoke-uri uri)))))
@ -455,6 +451,38 @@
(rx/of default) (rx/of default)
(rx/throw cause))))))) (rx/throw cause)))))))
(mf/defc exception-section*
{::mf/private true}
[{:keys [data route] :as props}]
(let [type (get data :type)
report (mf/with-memo [data]
(generate-report data))
props (mf/spread-props props {:report report})]
(mf/with-effect [data route report]
(let [params (:query-params route)
params (u/map->query-string params)]
(st/emit! (ptk/data-event ::ev/event
{::ev/name "exception-page"
:type (get data :type :unknown)
:hint (get data :hint)
:path (get route :path)
:report report
:params params}))))
(case type
:not-found
[:> not-found* {}]
:authentication
[:> not-found* {}]
:bad-gateway
[:> bad-gateway* props]
:service-unavailable
[:> service-unavailable*]
[:> internal-error* props])))
(mf/defc exception-page* (mf/defc exception-page*
{::mf/props :obj} {::mf/props :obj}
@ -477,42 +505,23 @@
request-access? request-access?
(and (and
(or (= (:type data) :not-found) (or (= type :not-found)
(= (:type data) :authentication)) (= type :authentication))
(or workspace? dashboard? view?) (or workspace? dashboard? view?)
(or (:file-id info) (or (:file-id info)
(:team-id info)))] (:team-id info)))]
(mf/with-effect [type path params]
(st/emit! (ptk/data-event ::ev/event
{::ev/name "exception-page"
:type type
:path path
:params (u/map->query-string params)})))
(mf/with-effect [params info] (mf/with-effect [params info]
(when-not (:loaded info) (when-not (:loaded info)
(->> (load-info params) (->> (load-info params)
(rx/subs! (partial reset! info*))))) (rx/subs! (partial reset! info*)
(partial reset! info* {:loaded true})))))
(when loaded? (when loaded?
(if request-access? (if request-access?
[:& request-access {:file-id (:file-id info) [:> request-access* {:file-id (:file-id info)
:team-id (:team-id info) :team-id (:team-id info)
:is-default (:team-default info) :is-default (:team-default info)
:workspace? workspace?}] :is-workspace workspace?}]
[:> exception-section* props]))))
(case (:type data)
:not-found
[:> not-found* {}]
:authentication
[:> not-found* {}]
:bad-gateway
[:> bad-gateway* props]
:service-unavailable
[:& service-unavailable]
[:> internal-error* props])))))

View file

@ -10,6 +10,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.logging :as log] [app.common.logging :as log]
[app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.data.common :as dc] [app.main.data.common :as dc]
[app.main.data.event :as ev] [app.main.data.event :as ev]
@ -104,7 +105,7 @@
(fn [event] (fn [event]
(let [target (dom/get-target event) (let [target (dom/get-target event)
checked? (dom/checked? target) checked? (dom/checked? target)
page-id (parse-uuid (dom/get-data target "page-id")) page-id (uuid/parse (dom/get-data target "page-id"))
dif-pages? (not= page-id (first (:pages options))) dif-pages? (not= page-id (first (:pages options)))
no-one-page (< 1 (count (:pages options))) no-one-page (< 1 (count (:pages options)))
should-change? (or ^boolean no-one-page should-change? (or ^boolean no-one-page

View file

@ -11,6 +11,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.types.color :as ctc] [app.common.types.color :as ctc]
[app.common.uuid :as uuid]
[app.main.data.event :as ev] [app.main.data.event :as ev]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as mdc] [app.main.data.workspace.colors :as mdc]
@ -62,7 +63,7 @@
(if (or (= event "recent") (if (or (= event "recent")
(= event "file")) (= event "file"))
(keyword event) (keyword event)
(parse-uuid event))))) (uuid/parse event)))))
valid-color? valid-color?
(mf/use-fn (mf/use-fn

View file

@ -228,7 +228,7 @@
(fn [event] (fn [event]
(let [library-id (some-> (dom/get-current-target event) (let [library-id (some-> (dom/get-current-target event)
(dom/get-data "library-id") (dom/get-data "library-id")
(parse-uuid))] (uuid/parse))]
(reset! selected library-id) (reset! selected library-id)
(st/emit! (dwl/link-file-to-library file-id library-id))))) (st/emit! (dwl/link-file-to-library file-id library-id)))))
@ -238,7 +238,7 @@
(fn [event] (fn [event]
(let [library-id (some-> (dom/get-current-target event) (let [library-id (some-> (dom/get-current-target event)
(dom/get-data "library-id") (dom/get-data "library-id")
(parse-uuid))] (uuid/parse))]
(when (= library-id @selected) (when (= library-id @selected)
(reset! selected :file)) (reset! selected :file))
(st/emit! (dwl/unlink-file-from-library file-id library-id) (st/emit! (dwl/unlink-file-from-library file-id library-id)
@ -451,7 +451,7 @@
(when-not updating? (when-not updating?
(let [library-id (some-> (dom/get-target event) (let [library-id (some-> (dom/get-target event)
(dom/get-data "library-id") (dom/get-data "library-id")
(parse-uuid))] (uuid/parse))]
(st/emit! (st/emit!
(dwl/set-updating-library true) (dwl/set-updating-library true)
(dwl/sync-file file-id library-id))))))] (dwl/sync-file file-id library-id))))))]

View file

@ -9,6 +9,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.uuid :as uuid]
[app.main.data.event :as ev] [app.main.data.event :as ev]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.colors :as mdc] [app.main.data.workspace.colors :as mdc]
@ -87,7 +88,7 @@
value (dom/get-attribute node "data-palette")] value (dom/get-attribute node "data-palette")]
(on-select (if (or (= "file" value) (= "recent" value)) (on-select (if (or (= "file" value) (= "recent" value))
(keyword value) (keyword value)
(parse-uuid value)))))) (uuid/parse value))))))
on-select-text-palette-menu on-select-text-palette-menu
(mf/use-fn (mf/use-fn

View file

@ -251,14 +251,14 @@
(mf/deps index update-interaction) (mf/deps index update-interaction)
(fn [event] (fn [event]
(let [value event (let [value event
value (when (not= value "") (uuid/uuid value))] value (when (not= value "") (uuid/parse value))]
(update-interaction index #(ctsi/set-destination % value))))) (update-interaction index #(ctsi/set-destination % value)))))
change-position-relative-to change-position-relative-to
(mf/use-fn (mf/use-fn
(mf/deps index update-interaction) (mf/deps index update-interaction)
(fn [event] (fn [event]
(let [value (uuid/uuid event)] (let [value (uuid/parse event)]
(update-interaction index #(ctsi/set-position-relative-to % value))))) (update-interaction index #(ctsi/set-position-relative-to % value)))))
change-preserve-scroll change-preserve-scroll

View file

@ -153,7 +153,7 @@
(mf/deps on-pin-snapshot) (mf/deps on-pin-snapshot)
(fn [event] (fn [event]
(let [node (dom/get-current-target event) (let [node (dom/get-current-target event)
id (-> (dom/get-data node "id") uuid/uuid)] id (-> (dom/get-data node "id") uuid/parse)]
(when on-pin-snapshot (on-pin-snapshot id))))) (when on-pin-snapshot (on-pin-snapshot id)))))
handle-restore-snapshot handle-restore-snapshot
@ -161,7 +161,7 @@
(mf/deps on-restore-snapshot) (mf/deps on-restore-snapshot)
(fn [event] (fn [event]
(let [node (dom/get-current-target event) (let [node (dom/get-current-target event)
id (-> (dom/get-data node "id") uuid/uuid)] id (-> (dom/get-data node "id") uuid/parse)]
(when on-restore-snapshot (on-restore-snapshot id))))) (when on-restore-snapshot (on-restore-snapshot id)))))

View file

@ -469,7 +469,7 @@
(dom/prevent-default event) (dom/prevent-default event)
(let [point (gpt/point (.-clientX event) (.-clientY event)) (let [point (gpt/point (.-clientX event) (.-clientY event))
viewport-coord (uwvv/point->viewport point) viewport-coord (uwvv/point->viewport point)
asset-id (-> (dnd/get-data event "text/asset-id") uuid/uuid) asset-id (-> (dnd/get-data event "text/asset-id") uuid/parse)
asset-name (dnd/get-data event "text/asset-name") asset-name (dnd/get-data event "text/asset-name")
asset-type (dnd/get-data event "text/asset-type")] asset-type (dnd/get-data event "text/asset-type")]
(cond (cond

View file

@ -970,7 +970,7 @@
:else :else
(let [file-id (:current-file-id @st/state) (let [file-id (:current-file-id @st/state)
library-id (uuid/uuid library-id)] library-id (uuid/parse library-id)]
(->> st/stream (->> st/stream
(rx/filter (ptk/type? ::dwl/attach-library-finished)) (rx/filter (ptk/type? ::dwl/attach-library-finished))
(rx/take 1) (rx/take 1)

View file

@ -160,7 +160,7 @@
(u/display-not-valid :getShapeById shape-id) (u/display-not-valid :getShapeById shape-id)
:else :else
(let [shape-id (uuid/uuid shape-id) (let [shape-id (uuid/parse shape-id)
shape (u/locate-shape file-id id shape-id)] shape (u/locate-shape file-id id shape-id)]
(when (some? shape) (when (some? shape)
(shape/shape-proxy plugin-id file-id id shape-id))))) (shape/shape-proxy plugin-id file-id id shape-id)))))

View file

@ -13,7 +13,7 @@
(defn parse-id (defn parse-id
[id] [id]
(when id (uuid/uuid id))) (when id (uuid/parse id)))
(defn parse-keyword (defn parse-keyword
[kw] [kw]

View file

@ -43,14 +43,14 @@
(defn read-json-key (defn read-json-key
[m] [m]
(or (sm/parse-uuid m) (or (uuid/parse m)
(json/read-kebab-key m))) (json/read-kebab-key m)))
(defn read-json-val (defn read-json-val
[m] [m]
(cond (cond
(and (string? m) (and (string? m)
(re-matches sm/uuid-rx m)) (re-matches uuid/regex m))
(uuid/uuid m) (uuid/uuid m)
(and (string? m) (and (string? m)
@ -521,8 +521,8 @@
id (resolve old-id) id (resolve old-id)
path (get-in node [:attrs :penpot:path] "") path (get-in node [:attrs :penpot:path] "")
type (parser/get-type content) type (parser/get-type content)
main-instance-id (resolve (uuid (get-in node [:attrs :penpot:main-instance-id] ""))) main-instance-id (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-id] "")))
main-instance-page (resolve (uuid (get-in node [:attrs :penpot:main-instance-page] ""))) main-instance-page (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-page] "")))
data (-> (parser/parse-data type content) data (-> (parser/parse-data type content)
(assoc :path path) (assoc :path path)
(assoc :id id) (assoc :id id)
@ -547,12 +547,12 @@
old-id (parser/get-id node) old-id (parser/get-id node)
id (resolve old-id) id (resolve old-id)
path (get-in node [:attrs :penpot:path] "") path (get-in node [:attrs :penpot:path] "")
main-instance-id (resolve (uuid (get-in node [:attrs :penpot:main-instance-id] ""))) main-instance-id (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-id] "")))
main-instance-page (resolve (uuid (get-in node [:attrs :penpot:main-instance-page] ""))) main-instance-page (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-page] "")))
main-instance-x (-> (get-in node [:attrs :penpot:main-instance-x] "") (d/parse-double)) main-instance-x (-> (get-in node [:attrs :penpot:main-instance-x] "") (d/parse-double))
main-instance-y (-> (get-in node [:attrs :penpot:main-instance-y] "") (d/parse-double)) main-instance-y (-> (get-in node [:attrs :penpot:main-instance-y] "") (d/parse-double))
main-instance-parent (resolve (uuid (get-in node [:attrs :penpot:main-instance-parent] ""))) main-instance-parent (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-parent] "")))
main-instance-frame (resolve (uuid (get-in node [:attrs :penpot:main-instance-frame] ""))) main-instance-frame (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-frame] "")))
type (parser/get-type content) type (parser/get-type content)
data (-> (parser/parse-data type content) data (-> (parser/parse-data type content)

View file

@ -20,9 +20,6 @@
(def url-regex (def url-regex
#"url\(#([^\)]*)\)") #"url\(#([^\)]*)\)")
(def uuid-regex
#"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}")
(def uuid-regex-prefix (def uuid-regex-prefix
#"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-") #"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-")
@ -84,7 +81,7 @@
(defn get-id (defn get-id
[node] [node]
(let [attr-id (get-in node [:attrs :id]) (let [attr-id (get-in node [:attrs :id])
id (when (string? attr-id) (re-find uuid-regex attr-id))] id (when (string? attr-id) (re-find uuid/regex attr-id))]
(when (some? id) (when (some? id)
(uuid/uuid id)))) (uuid/uuid id))))
@ -189,10 +186,10 @@
[m] [m]
(letfn [(convert [value] (letfn [(convert [value]
(cond (cond
(and (string? value) (re-matches uuid-regex value)) (and (string? value) (re-matches uuid/regex value))
(uuid/uuid value) (uuid/uuid value)
(and (keyword? value) (re-matches uuid-regex (d/name value))) (and (keyword? value) (re-matches uuid/regex (d/name value)))
(uuid/uuid (d/name value)) (uuid/uuid (d/name value))
(vector? value) (vector? value)
@ -429,11 +426,11 @@
(defn add-library-refs (defn add-library-refs
[props node] [props node]
(let [stroke-color-ref-id (get-meta node :stroke-color-ref-id uuid/uuid) (let [stroke-color-ref-id (get-meta node :stroke-color-ref-id uuid/parse)
stroke-color-ref-file (get-meta node :stroke-color-ref-file uuid/uuid) stroke-color-ref-file (get-meta node :stroke-color-ref-file uuid/parse)
component-id (get-meta node :component-id uuid/uuid) component-id (get-meta node :component-id uuid/parse)
component-file (get-meta node :component-file uuid/uuid) component-file (get-meta node :component-file uuid/parse)
shape-ref (get-meta node :shape-ref uuid/uuid) shape-ref (get-meta node :shape-ref uuid/parse)
component-root? (get-meta node :component-root str->bool) component-root? (get-meta node :component-root str->bool)
main-instance? (get-meta node :main-instance str->bool) main-instance? (get-meta node :main-instance str->bool)
touched (get-meta node :touched parse-touched)] touched (get-meta node :touched parse-touched)]
@ -463,8 +460,8 @@
[props node svg-data] [props node svg-data]
(let [fill (:fill svg-data) (let [fill (:fill svg-data)
fill-color-ref-id (get-meta node :fill-color-ref-id uuid/uuid) fill-color-ref-id (get-meta node :fill-color-ref-id uuid/parse)
fill-color-ref-file (get-meta node :fill-color-ref-file uuid/uuid) fill-color-ref-file (get-meta node :fill-color-ref-file uuid/parse)
meta-fill-color (get-meta node :fill-color) meta-fill-color (get-meta node :fill-color)
meta-fill-opacity (get-meta node :fill-opacity) meta-fill-opacity (get-meta node :fill-opacity)
meta-fill-color-gradient (if (str/starts-with? meta-fill-color "url#fill-color-gradient") meta-fill-color-gradient (if (str/starts-with? meta-fill-color "url#fill-color-gradient")
@ -627,7 +624,7 @@
(let [attrs (-> node :attrs remove-penpot-prefix)] (let [attrs (-> node :attrs remove-penpot-prefix)]
{:id (uuid/next) {:id (uuid/next)
:name (-> attrs :name) :name (-> attrs :name)
:starting-frame (-> attrs :starting-frame uuid)})) :starting-frame (-> attrs :starting-frame uuid/parse)}))
(defn parse-flows [node] (defn parse-flows [node]
(let [flows-node (get-data node :penpot:flows)] (let [flows-node (get-data node :penpot:flows)]
@ -638,7 +635,7 @@
id (uuid/next)] id (uuid/next)]
[id [id
{:id id {:id id
:frame-id (when (:frame-id attrs) (-> attrs :frame-id uuid)) :frame-id (when (:frame-id attrs) (-> attrs :frame-id uuid/parse))
:axis (-> attrs :axis keyword) :axis (-> attrs :axis keyword)
:position (-> attrs :position d/parse-double)}])) :position (-> attrs :position d/parse-double)}]))
@ -775,8 +772,8 @@
(parse-gradient node (get-meta fill-node :fill-color))) (parse-gradient node (get-meta fill-node :fill-color)))
:fill-image (when fill-image-id :fill-image (when fill-image-id
(get images fill-image-id)) (get images fill-image-id))
:fill-color-ref-file (get-meta fill-node :fill-color-ref-file uuid/uuid) :fill-color-ref-file (get-meta fill-node :fill-color-ref-file uuid/parse)
:fill-color-ref-id (get-meta fill-node :fill-color-ref-id uuid/uuid) :fill-color-ref-id (get-meta fill-node :fill-color-ref-id uuid/parse)
:fill-opacity (get-meta fill-node :fill-opacity d/parse-double)}))) :fill-opacity (get-meta fill-node :fill-opacity d/parse-double)})))
(mapv d/without-nils) (mapv d/without-nils)
(filterv #(not= (:fill-color %) "none")))] (filterv #(not= (:fill-color %) "none")))]
@ -800,8 +797,8 @@
(parse-gradient node (get-meta stroke-node :stroke-color))) (parse-gradient node (get-meta stroke-node :stroke-color)))
:stroke-image (when stroke-image-id :stroke-image (when stroke-image-id
(get images stroke-image-id)) (get images stroke-image-id))
:stroke-color-ref-file (get-meta stroke-node :stroke-color-ref-file uuid/uuid) :stroke-color-ref-file (get-meta stroke-node :stroke-color-ref-file uuid/parse)
:stroke-color-ref-id (get-meta stroke-node :stroke-color-ref-id uuid/uuid) :stroke-color-ref-id (get-meta stroke-node :stroke-color-ref-id uuid/parse)
:stroke-opacity (get-meta stroke-node :stroke-opacity d/parse-double) :stroke-opacity (get-meta stroke-node :stroke-opacity d/parse-double)
:stroke-style (get-meta stroke-node :stroke-style keyword) :stroke-style (get-meta stroke-node :stroke-style keyword)
:stroke-width (get-meta stroke-node :stroke-width d/parse-double) :stroke-width (get-meta stroke-node :stroke-width d/parse-double)
@ -993,7 +990,7 @@
align-self align-self
justify-self justify-self
shapes]} (-> cell-node :attrs remove-penpot-prefix) shapes]} (-> cell-node :attrs remove-penpot-prefix)
id (uuid/uuid id)] id (uuid/parse id)]
[id (d/without-nils [id (d/without-nils
{:id id {:id id
:area-name area-name :area-name area-name
@ -1006,7 +1003,7 @@
:justify-self (keyword justify-self) :justify-self (keyword justify-self)
:shapes (if (and (some? shapes) (d/not-empty? shapes)) :shapes (if (and (some? shapes) (d/not-empty? shapes))
(->> (str/split shapes " ") (->> (str/split shapes " ")
(mapv uuid/uuid)) (mapv uuid/parse))
[])})]))) [])})])))
(into {})))) (into {}))))
@ -1154,7 +1151,7 @@
(assoc :delay (get-meta node :delay d/parse-double)) (assoc :delay (get-meta node :delay d/parse-double))
(ctsi/has-destination interaction) (ctsi/has-destination interaction)
(assoc :destination (get-meta node :destination uuid/uuid) (assoc :destination (get-meta node :destination uuid/parse)
:preserve-scroll (get-meta node :preserve-scroll str->bool)) :preserve-scroll (get-meta node :preserve-scroll str->bool))
(ctsi/has-url interaction) (ctsi/has-url interaction)

View file

@ -179,7 +179,7 @@
[state name] [state name]
(let [objects (dsh/lookup-page-objects state) (let [objects (dsh/lookup-page-objects state)
result (or (d/seek (fn [shape] (= name (:name shape))) (vals objects)) result (or (d/seek (fn [shape] (= name (:name shape))) (vals objects))
(get objects (uuid/uuid name)))] (get objects (uuid/parse name)))]
result)) result))
(defn ^:export dump-object (defn ^:export dump-object
@ -222,12 +222,12 @@
(defn ^:export select-by-object-id (defn ^:export select-by-object-id
[object-id] [object-id]
(let [[_ page-id shape-id _] (str/split object-id #"/")] (let [[_ page-id shape-id _] (str/split object-id #"/")]
(st/emit! (dcm/go-to-workspace :page-id (uuid/uuid page-id))) (st/emit! (dcm/go-to-workspace :page-id (uuid/parse page-id)))
(st/emit! (dws/select-shape (uuid/uuid shape-id))))) (st/emit! (dws/select-shape (uuid/parse shape-id)))))
(defn ^:export select-by-id (defn ^:export select-by-id
[shape-id] [shape-id]
(st/emit! (dws/select-shape (uuid/uuid shape-id)))) (st/emit! (dws/select-shape (uuid/parse shape-id))))
(defn dump-tree' (defn dump-tree'
([state] (dump-tree' state false false false)) ([state] (dump-tree' state false false false))
@ -255,7 +255,7 @@
file (dsh/lookup-file state) file (dsh/lookup-file state)
libraries (get state :files) libraries (get state :files)
shape-id (if (some? shape-id) shape-id (if (some? shape-id)
(uuid/uuid shape-id) (uuid/parse shape-id)
(first (dsh/lookup-selected state)))] (first (dsh/lookup-selected state)))]
(if (some? shape-id) (if (some? shape-id)
(ctf/dump-subtree file page-id shape-id libraries {:show-ids show-ids (ctf/dump-subtree file page-id shape-id libraries {:show-ids show-ids
@ -369,7 +369,7 @@
(let [file (dsh/lookup-file @st/state) (let [file (dsh/lookup-file @st/state)
libraries (get @st/state :files)] libraries (get @st/state :files)]
(try (try
(->> (if-let [shape-id (some-> shape-id parse-uuid)] (->> (if-let [shape-id (some-> shape-id uuid/parse)]
(let [page (dm/get-in file [:data :pages-index (get @st/state :current-page-id)])] (let [page (dm/get-in file [:data :pages-index (get @st/state :current-page-id)])]
(cfv/validate-shape shape-id file page libraries)) (cfv/validate-shape shape-id file page libraries))
(cfv/validate-file file libraries)) (cfv/validate-file file libraries))
@ -426,6 +426,15 @@
[] []
(st/emit! (dw/find-components-norefs))) (st/emit! (dw/find-components-norefs)))
(defn- set-shape-ref*
[id shape-ref]
(ptk/reify ::set-shape-ref
ptk/WatchEvent
(watch [_ _ _]
(let [shape-id (uuid/parse id)
shape-ref (uuid/parse shape-ref)]
(rx/of (dw/update-shape shape-id {:shape-ref shape-ref}))))))
(defn ^:export set-shape-ref (defn ^:export set-shape-ref
[id shape-ref] [id shape-ref]
(st/emit! (dw/set-shape-ref id shape-ref))) (st/emit! (set-shape-ref* id shape-ref)))