diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index 0668a4a0b2..4cb0aea3e0 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -155,9 +155,9 @@ [["" {:middleware [[mw/server-timing] [mw/params] [mw/format-response] - [mw/parse-request] [session/soft-auth cfg] [actoken/soft-auth cfg] + [mw/parse-request] [mw/errors errors/handle] [mw/restrict-methods]]} diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index 6d89efd89e..b6f1a49c48 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -395,9 +395,15 @@ (defn parse-uuid [s] - (if (string? s) - (some->> (re-matches uuid-rx s) uuid/uuid) - s)) + (try + (uuid/parse s) + (catch #?(:clj Exception :cljs :default) _cause + s))) + +(defn encode-uuid + [v] + (when (uuid? v) + (str v))) (register! {:type ::uuid @@ -409,8 +415,8 @@ :gen/gen (sg/uuid) :decode/string parse-uuid :decode/json parse-uuid - :encode/string str - :encode/json str + :encode/string encode-uuid + :encode/json encode-uuid ::oapi/type "string" ::oapi/format "uuid"}}) diff --git a/common/src/app/common/uuid.cljc b/common/src/app/common/uuid.cljc index 707770fcd9..9b21f8f796 100644 --- a/common/src/app/common/uuid.cljc +++ b/common/src/app/common/uuid.cljc @@ -17,9 +17,14 @@ java.util.UUID 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 "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] #?(:clj (UUID/fromString s) :cljs (c/uuid s))) @@ -27,8 +32,21 @@ (defn parse "Parse string uuid representation into proper UUID instance, validates input" [s] - #?(:clj (UUID/fromString s) - :cljs (c/parse-uuid s))) + (if (and (string? s) ^boolean (re-matches regex s)) + #?(:clj (UUID/fromString 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 [] diff --git a/frontend/src/app/libs/file_builder.cljs b/frontend/src/app/libs/file_builder.cljs index 05be149ac8..36e22caef7 100644 --- a/frontend/src/app/libs/file_builder.cljs +++ b/frontend/src/app/libs/file_builder.cljs @@ -239,15 +239,15 @@ (str (:last-id file))) (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] - (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))] (set! file (fb/update-object file old-obj new-obj)))) (deleteObject [_ id] - (set! file (fb/delete-object file (uuid/uuid id)))) + (set! file (fb/delete-object file (uuid/parse id)))) (getId [_] (:id file)) diff --git a/frontend/src/app/libs/render.cljs b/frontend/src/app/libs/render.cljs index 26e6cfe5d6..7ece057c01 100644 --- a/frontend/src/app/libs/render.cljs +++ b/frontend/src/app/libs/render.cljs @@ -15,7 +15,7 @@ [file ^string page-id] ;; 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) data (get-in file-data [:data :pages-index page-id])] (p/create diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 0d7677f821..e4205f9bd7 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -69,7 +69,7 @@ "Retrieves the mentions in the content as an array of uuids" [content] (->> (re-seq r-mentions content) - (mapv (fn [[_ _ id]] (uuid/uuid id))))) + (mapv (fn [[_ _ id]] (uuid/parse id))))) (defn update-mentions "Updates the params object with the mentiosn" diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index dbd96a2900..c18444623a 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -248,7 +248,7 @@ (defn fetch-comments [{:keys [thread-id]}] - (dm/assert! (uuid thread-id)) + (assert (uuid? thread-id)) (letfn [(fetched [comments state] (update state :comments assoc thread-id (d/index-by :id comments)))] (ptk/reify ::retrieve-comments @@ -413,7 +413,7 @@ (watch [_ state _] (let [params (rt/get-params state) 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]))] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 3e1fcba1ba..01dc099c8a 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -369,7 +369,7 @@ (rx/take 1) (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 (rx/filter (ptk/type? ::workspace-initialized)) (rx/observe-on :async) @@ -382,7 +382,7 @@ (rx/take 1) (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 (rx/filter (ptk/type? ::workspace-initialized)) (rx/observe-on :async) @@ -2445,13 +2445,6 @@ (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)))))) -(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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index f67fb755a3..8d4299a3af 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -7,6 +7,7 @@ (ns app.main.ui (:require [app.common.data :as d] + [app.common.uuid :as uuid] [app.config :as cf] [app.main.data.common :as dcm] [app.main.data.team :as dtm] @@ -212,8 +213,8 @@ :dashboard-webhooks :dashboard-settings) (let [params (get params :query) - team-id (some-> params :team-id uuid) - project-id (some-> params :project-id uuid) + team-id (some-> params :team-id uuid/parse*) + project-id (some-> params :project-id uuid/parse*) search-term (some-> params :search-term) plugin-url (some-> params :plugin) template-url (some-> params :template)] @@ -247,9 +248,9 @@ :workspace (let [params (get params :query) - team-id (some-> params :team-id uuid) - file-id (some-> params :file-id uuid) - page-id (some-> params :page-id uuid) + team-id (some-> params :team-id uuid/parse*) + file-id (some-> params :file-id uuid/parse*) + page-id (some-> params :page-id uuid/parse*) layout (some-> params :layout keyword)] [:? {} (when (cf/external-feature-flag "onboarding-03" "test") @@ -276,15 +277,15 @@ :viewer (let [params (get params :query) 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) :interactions) - file-id (some-> (:file-id params) parse-uuid) - page-id (some-> (:page-id params) parse-uuid) + file-id (some-> (:file-id params) uuid/parse*) + page-id (some-> (:page-id params) uuid/parse*) imode (or (some-> (:interactions-mode params) keyword) :show-on-click) - frame-id (some-> (:frame-id params) parse-uuid) + frame-id (some-> (:frame-id params) uuid/parse*) share (:share params)] [:? {} @@ -300,9 +301,9 @@ :workspace-legacy - (let [project-id (some-> params :path :project-id uuid) - file-id (some-> params :path :file-id uuid) - page-id (some-> params :query :page-id uuid) + (let [project-id (some-> params :path :project-id uuid/parse*) + file-id (some-> params :path :file-id uuid/parse*) + page-id (some-> params :query :page-id uuid/parse*) layout (some-> params :query :layout keyword)] [:> workspace-legacy-redirect* @@ -321,8 +322,8 @@ :dashboard-legacy-team-invitations :dashboard-legacy-team-webhooks :dashboard-legacy-team-settings) - (let [team-id (some-> params :path :team-id uuid) - project-id (some-> params :path :project-id uuid) + (let [team-id (some-> params :path :team-id uuid/parse*) + project-id (some-> params :path :project-id uuid/parse*) search-term (some-> params :query :search-term) plugin-url (some-> params :query :plugin) template-url (some-> params :template)] diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 2955543540..1aa3c833e3 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -487,7 +487,7 @@ (dom/stop-propagation event) (let [id (-> (dom/get-current-target event) (dom/get-data "user-id") - (uuid/uuid)) + (uuid/parse)) user (d/seek #(= (:id %) id) members)] diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index bcda5f4b0a..c03aa5bebf 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -9,6 +9,7 @@ (:require [app.common.data.macros :as dm] [app.common.media :as cm] + [app.common.uuid :as uuid] [app.config :as cf] [app.main.data.fonts :as df] [app.main.data.modal :as modal] @@ -121,7 +122,7 @@ (fn [event] (let [id (-> (dom/get-current-target event) (dom/get-data "id") - (parse-uuid)) + (uuid/parse)) item (get fonts id)] (on-upload* item)))) @@ -132,7 +133,7 @@ (let [target (dom/get-current-target event) id (-> target (dom/get-data "id") - (parse-uuid)) + (uuid/parse)) name (dom/get-value target)] (when-not (str/blank? name) (swap! fonts* df/rename-and-regroup id name installed-fonts))))) @@ -143,7 +144,7 @@ (let [target (dom/get-current-target event) id (-> target (dom/get-data "id") - (parse-uuid)) + (uuid/parse)) name (dom/get-value target)] (swap! fonts* update id assoc :font-family-tmp name)))) @@ -153,7 +154,7 @@ (fn [event] (let [id (-> (dom/get-current-target event) (dom/get-data "id") - (parse-uuid))] + (uuid/parse))] (swap! fonts* dissoc id)))) on-upload-all @@ -344,7 +345,7 @@ (fn [event] (let [id (-> (dom/get-current-target event) (dom/get-data "id") - (parse-uuid)) + (uuid/parse)) options {:type :confirm :title (tr "modals.delete-font-variant.title") :message (tr "modals.delete-font-variant.message") diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index 46dd0d270a..1a0d85b747 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -284,7 +284,6 @@ (let [team-id (-> (dom/get-current-target event) (dom/get-data "value") (uuid/parse))] - (st/emit! (dcm/go-to-dashboard-recent :team-id team-id))))) handle-select-default diff --git a/frontend/src/app/main/ui/static.cljs b/frontend/src/app/main/ui/static.cljs index ebe78c50d7..d81d5959ac 100644 --- a/frontend/src/app/main/ui/static.cljs +++ b/frontend/src/app/main/ui/static.cljs @@ -202,9 +202,8 @@ cancel-text]) [:button {:on-click on-click} button-text]]]])) -(mf/defc request-access - {::mf/props :obj} - [{:keys [file-id team-id is-default workspace?]}] +(mf/defc request-access* + [{:keys [file-id team-id is-default is-workspace]}] (let [profile (mf/deref refs/profile) requested* (mf/use-state {:sent false :already-requested false}) requested (deref requested*) @@ -227,11 +226,11 @@ on-request-access (mf/use-fn - (mf/deps file-id team-id workspace?) + (mf/deps file-id team-id is-workspace) (fn [] (let [params (if (some? file-id) {:file-id file-id - :is-viewer (not workspace?)} + :is-viewer (not is-workspace)} {:team-id team-id}) mdata {:on-success on-success :on-error on-error}] @@ -240,7 +239,7 @@ [:* (if (some? file-id) - (if workspace? + (if is-workspace [:div {:class (stl/css :workspace)} [:div {:class (stl/css :workspace-left)} i/logo-icon @@ -341,7 +340,7 @@ [:div {:class (stl/css :sign-info)} [: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)))] [:> error-container* {} @@ -350,58 +349,55 @@ [:div {:class (stl/css :sign-info)} [:button {:on-click on-click} (tr "labels.retry")]]])) -(defn generate-report +(defn- generate-report [data] (try (let [team-id (:current-team-id @st/state) profile-id (:profile-id @st/state) trace (:app.main.errors/trace data) - instance (:app.main.errors/instance data) - content (with-out-str - (println "Hint: " (or (:hint data) (ex-message instance) "--")) - (println "Prof ID:" (str (or profile-id "--"))) - (println "Team ID:" (str (or team-id "--"))) + instance (:app.main.errors/instance data)] + (with-out-str + (println "Hint: " (or (:hint data) (ex-message instance) "--")) + (println "Prof ID:" (str (or profile-id "--"))) + (println "Team ID:" (str (or team-id "--"))) - (when-let [file-id (:file-id data)] - (println "File ID:" (str file-id))) + (when-let [file-id (:file-id data)] + (println "File ID:" (str file-id))) - (println) + (println) - (println "Data:") - (loop [data data] - (-> (d/without-qualified data) - (dissoc :explain) - (d/update-when :data (constantly "(...)")) - (pp/pprint {:level 8 :length 10})) + (println "Data:") + (loop [data data] + (-> (d/without-qualified data) + (dissoc :explain) + (d/update-when :data (constantly "(...)")) + (pp/pprint {:level 8 :length 10})) - (println) + (println) - (when-let [explain (:explain data)] - (print explain)) + (when-let [explain (:explain data)] + (print explain)) - (when (and (= :server-error (:type data)) - (contains? data :data)) - (recur (:data data)))) + (when (and (= :server-error (:type data)) + (contains? data :data)) + (recur (:data data)))) - (println "Trace:") - (println trace) - (println) + (println "Trace:") + (println trace) + (println) - (println "Last events:") - (pp/pprint @st/last-events {:length 200}) + (println "Last events:") + (pp/pprint @st/last-events {:length 200}) - (println))] - (wapi/create-blob content "text/plain")) + (println))) (catch :default cause (.error js/console "error on generating report.txt" cause) nil))) (mf/defc internal-error* - {::mf/props :obj} - [{:keys [data on-reset] :as props}] + [{:keys [on-reset report] :as props}] (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-download @@ -413,8 +409,8 @@ (mf/with-effect [report] (when (some? report) - - (let [uri (wapi/create-uri report)] + (let [report (wapi/create-blob report "text/plain") + uri (wapi/create-uri report)] (mf/set-ref-val! report-uri uri) (fn [] (wapi/revoke-uri uri))))) @@ -455,6 +451,38 @@ (rx/of default) (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/props :obj} @@ -477,42 +505,23 @@ request-access? (and - (or (= (:type data) :not-found) - (= (:type data) :authentication)) + (or (= type :not-found) + (= type :authentication)) (or workspace? dashboard? view?) (or (:file-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] (when-not (:loaded info) (->> (load-info params) - (rx/subs! (partial reset! info*))))) + (rx/subs! (partial reset! info*) + (partial reset! info* {:loaded true}))))) (when loaded? (if request-access? - [:& request-access {:file-id (:file-id info) - :team-id (:team-id info) - :is-default (:team-default info) - :workspace? workspace?}] + [:> request-access* {:file-id (:file-id info) + :team-id (:team-id info) + :is-default (:team-default info) + :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]))))) diff --git a/frontend/src/app/main/ui/viewer/share_link.cljs b/frontend/src/app/main/ui/viewer/share_link.cljs index ddda62a0fb..1db0b902b0 100644 --- a/frontend/src/app/main/ui/viewer/share_link.cljs +++ b/frontend/src/app/main/ui/viewer/share_link.cljs @@ -10,6 +10,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.logging :as log] + [app.common.uuid :as uuid] [app.config :as cf] [app.main.data.common :as dc] [app.main.data.event :as ev] @@ -104,7 +105,7 @@ (fn [event] (let [target (dom/get-target event) 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))) no-one-page (< 1 (count (:pages options))) should-change? (or ^boolean no-one-page diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs index cb703ef5a9..4996eb9d14 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs @@ -11,6 +11,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.types.color :as ctc] + [app.common.uuid :as uuid] [app.main.data.event :as ev] [app.main.data.workspace :as dw] [app.main.data.workspace.colors :as mdc] @@ -62,7 +63,7 @@ (if (or (= event "recent") (= event "file")) (keyword event) - (parse-uuid event))))) + (uuid/parse event))))) valid-color? (mf/use-fn diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index 0c6a8b8feb..40de66b24a 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -228,7 +228,7 @@ (fn [event] (let [library-id (some-> (dom/get-current-target event) (dom/get-data "library-id") - (parse-uuid))] + (uuid/parse))] (reset! selected library-id) (st/emit! (dwl/link-file-to-library file-id library-id))))) @@ -238,7 +238,7 @@ (fn [event] (let [library-id (some-> (dom/get-current-target event) (dom/get-data "library-id") - (parse-uuid))] + (uuid/parse))] (when (= library-id @selected) (reset! selected :file)) (st/emit! (dwl/unlink-file-from-library file-id library-id) @@ -451,7 +451,7 @@ (when-not updating? (let [library-id (some-> (dom/get-target event) (dom/get-data "library-id") - (parse-uuid))] + (uuid/parse))] (st/emit! (dwl/set-updating-library true) (dwl/sync-file file-id library-id))))))] diff --git a/frontend/src/app/main/ui/workspace/palette.cljs b/frontend/src/app/main/ui/workspace/palette.cljs index 431f97935c..ff13a57b13 100644 --- a/frontend/src/app/main/ui/workspace/palette.cljs +++ b/frontend/src/app/main/ui/workspace/palette.cljs @@ -9,6 +9,7 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.uuid :as uuid] [app.main.data.event :as ev] [app.main.data.workspace :as dw] [app.main.data.workspace.colors :as mdc] @@ -87,7 +88,7 @@ value (dom/get-attribute node "data-palette")] (on-select (if (or (= "file" value) (= "recent" value)) (keyword value) - (parse-uuid value)))))) + (uuid/parse value)))))) on-select-text-palette-menu (mf/use-fn diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs index 22e2421fc7..ae2193a23b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs @@ -251,14 +251,14 @@ (mf/deps index update-interaction) (fn [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))))) change-position-relative-to (mf/use-fn (mf/deps index update-interaction) (fn [event] - (let [value (uuid/uuid event)] + (let [value (uuid/parse event)] (update-interaction index #(ctsi/set-position-relative-to % value))))) change-preserve-scroll diff --git a/frontend/src/app/main/ui/workspace/sidebar/versions.cljs b/frontend/src/app/main/ui/workspace/sidebar/versions.cljs index 323d60a433..a4173adabc 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/versions.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/versions.cljs @@ -153,7 +153,7 @@ (mf/deps on-pin-snapshot) (fn [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))))) handle-restore-snapshot @@ -161,7 +161,7 @@ (mf/deps on-restore-snapshot) (fn [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))))) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index b22a8bda79..80702d5846 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -469,7 +469,7 @@ (dom/prevent-default event) (let [point (gpt/point (.-clientX event) (.-clientY event)) 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-type (dnd/get-data event "text/asset-type")] (cond diff --git a/frontend/src/app/plugins/library.cljs b/frontend/src/app/plugins/library.cljs index a269d2ab52..bd430ce729 100644 --- a/frontend/src/app/plugins/library.cljs +++ b/frontend/src/app/plugins/library.cljs @@ -969,7 +969,7 @@ :else (let [file-id (:current-file-id @st/state) - library-id (uuid/uuid library-id)] + library-id (uuid/parse library-id)] (->> st/stream (rx/filter (ptk/type? ::dwl/attach-library-finished)) (rx/take 1) diff --git a/frontend/src/app/plugins/page.cljs b/frontend/src/app/plugins/page.cljs index 373a9b93c5..ba7713f42b 100644 --- a/frontend/src/app/plugins/page.cljs +++ b/frontend/src/app/plugins/page.cljs @@ -160,7 +160,7 @@ (u/display-not-valid :getShapeById shape-id) :else - (let [shape-id (uuid/uuid shape-id) + (let [shape-id (uuid/parse shape-id) shape (u/locate-shape file-id id shape-id)] (when (some? shape) (shape/shape-proxy plugin-id file-id id shape-id))))) diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs index 0ce6aad418..caaa697f74 100644 --- a/frontend/src/app/plugins/parser.cljs +++ b/frontend/src/app/plugins/parser.cljs @@ -13,7 +13,7 @@ (defn parse-id [id] - (when id (uuid/uuid id))) + (when id (uuid/parse id))) (defn parse-keyword [kw] diff --git a/frontend/src/app/worker/import.cljs b/frontend/src/app/worker/import.cljs index 950c98ffba..f2ea47fabe 100644 --- a/frontend/src/app/worker/import.cljs +++ b/frontend/src/app/worker/import.cljs @@ -43,14 +43,14 @@ (defn read-json-key [m] - (or (sm/parse-uuid m) + (or (uuid/parse m) (json/read-kebab-key m))) (defn read-json-val [m] (cond (and (string? m) - (re-matches sm/uuid-rx m)) + (re-matches uuid/regex m)) (uuid/uuid m) (and (string? m) @@ -521,8 +521,8 @@ id (resolve old-id) path (get-in node [:attrs :penpot:path] "") type (parser/get-type content) - main-instance-id (resolve (uuid (get-in node [:attrs :penpot:main-instance-id] ""))) - main-instance-page (resolve (uuid (get-in node [:attrs :penpot:main-instance-page] ""))) + main-instance-id (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-id] ""))) + main-instance-page (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-page] ""))) data (-> (parser/parse-data type content) (assoc :path path) (assoc :id id) @@ -547,12 +547,12 @@ old-id (parser/get-id node) id (resolve old-id) path (get-in node [:attrs :penpot:path] "") - main-instance-id (resolve (uuid (get-in node [:attrs :penpot:main-instance-id] ""))) - main-instance-page (resolve (uuid (get-in node [:attrs :penpot:main-instance-page] ""))) + main-instance-id (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-id] ""))) + 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-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-frame (resolve (uuid (get-in node [:attrs :penpot:main-instance-frame] ""))) + main-instance-parent (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-parent] ""))) + main-instance-frame (resolve (uuid/parse (get-in node [:attrs :penpot:main-instance-frame] ""))) type (parser/get-type content) data (-> (parser/parse-data type content) diff --git a/frontend/src/app/worker/import/parser.cljs b/frontend/src/app/worker/import/parser.cljs index 27ad5f1149..8bf5158eee 100644 --- a/frontend/src/app/worker/import/parser.cljs +++ b/frontend/src/app/worker/import/parser.cljs @@ -20,9 +20,6 @@ (def url-regex #"url\(#([^\)]*)\)") -(def uuid-regex - #"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}") - (def uuid-regex-prefix #"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}-") @@ -84,7 +81,7 @@ (defn get-id [node] (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) (uuid/uuid id)))) @@ -189,10 +186,10 @@ [m] (letfn [(convert [value] (cond - (and (string? value) (re-matches uuid-regex value)) + (and (string? value) (re-matches uuid/regex 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)) (vector? value) @@ -429,11 +426,11 @@ (defn add-library-refs [props node] - (let [stroke-color-ref-id (get-meta node :stroke-color-ref-id uuid/uuid) - stroke-color-ref-file (get-meta node :stroke-color-ref-file uuid/uuid) - component-id (get-meta node :component-id uuid/uuid) - component-file (get-meta node :component-file uuid/uuid) - shape-ref (get-meta node :shape-ref 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/parse) + component-id (get-meta node :component-id uuid/parse) + component-file (get-meta node :component-file uuid/parse) + shape-ref (get-meta node :shape-ref uuid/parse) component-root? (get-meta node :component-root str->bool) main-instance? (get-meta node :main-instance str->bool) touched (get-meta node :touched parse-touched)] @@ -463,8 +460,8 @@ [props node svg-data] (let [fill (:fill svg-data) - fill-color-ref-id (get-meta node :fill-color-ref-id uuid/uuid) - fill-color-ref-file (get-meta node :fill-color-ref-file 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/parse) meta-fill-color (get-meta node :fill-color) meta-fill-opacity (get-meta node :fill-opacity) 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)] {:id (uuid/next) :name (-> attrs :name) - :starting-frame (-> attrs :starting-frame uuid)})) + :starting-frame (-> attrs :starting-frame uuid/parse)})) (defn parse-flows [node] (let [flows-node (get-data node :penpot:flows)] @@ -638,7 +635,7 @@ id (uuid/next)] [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) :position (-> attrs :position d/parse-double)}])) @@ -775,8 +772,8 @@ (parse-gradient node (get-meta fill-node :fill-color))) :fill-image (when 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-id (get-meta fill-node :fill-color-ref-id 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/parse) :fill-opacity (get-meta fill-node :fill-opacity d/parse-double)}))) (mapv d/without-nils) (filterv #(not= (:fill-color %) "none")))] @@ -800,8 +797,8 @@ (parse-gradient node (get-meta stroke-node :stroke-color))) :stroke-image (when 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-id (get-meta stroke-node :stroke-color-ref-id 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/parse) :stroke-opacity (get-meta stroke-node :stroke-opacity d/parse-double) :stroke-style (get-meta stroke-node :stroke-style keyword) :stroke-width (get-meta stroke-node :stroke-width d/parse-double) @@ -993,7 +990,7 @@ align-self justify-self shapes]} (-> cell-node :attrs remove-penpot-prefix) - id (uuid/uuid id)] + id (uuid/parse id)] [id (d/without-nils {:id id :area-name area-name @@ -1006,7 +1003,7 @@ :justify-self (keyword justify-self) :shapes (if (and (some? shapes) (d/not-empty? shapes)) (->> (str/split shapes " ") - (mapv uuid/uuid)) + (mapv uuid/parse)) [])})]))) (into {})))) @@ -1154,7 +1151,7 @@ (assoc :delay (get-meta node :delay d/parse-double)) (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)) (ctsi/has-url interaction) diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index 4d635b99b5..e934f851b5 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -179,7 +179,7 @@ [state name] (let [objects (dsh/lookup-page-objects state) result (or (d/seek (fn [shape] (= name (:name shape))) (vals objects)) - (get objects (uuid/uuid name)))] + (get objects (uuid/parse name)))] result)) (defn ^:export dump-object @@ -222,12 +222,12 @@ (defn ^:export select-by-object-id [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! (dws/select-shape (uuid/uuid shape-id))))) + (st/emit! (dcm/go-to-workspace :page-id (uuid/parse page-id))) + (st/emit! (dws/select-shape (uuid/parse shape-id))))) (defn ^:export select-by-id [shape-id] - (st/emit! (dws/select-shape (uuid/uuid shape-id)))) + (st/emit! (dws/select-shape (uuid/parse shape-id)))) (defn dump-tree' ([state] (dump-tree' state false false false)) @@ -255,7 +255,7 @@ file (dsh/lookup-file state) libraries (get state :files) shape-id (if (some? shape-id) - (uuid/uuid shape-id) + (uuid/parse shape-id) (first (dsh/lookup-selected state)))] (if (some? shape-id) (ctf/dump-subtree file page-id shape-id libraries {:show-ids show-ids @@ -369,7 +369,7 @@ (let [file (dsh/lookup-file @st/state) libraries (get @st/state :files)] (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)])] (cfv/validate-shape shape-id file page libraries)) (cfv/validate-file file libraries)) @@ -426,6 +426,15 @@ [] (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 [id shape-ref] - (st/emit! (dw/set-shape-ref id shape-ref))) + (st/emit! (set-shape-ref* id shape-ref)))