0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-09 13:31:23 -05:00

♻️ Simplifies RPC pattern for tokens ()

* ♻️ Refactor to RPC pattern

Co-authored-by: andrei <andrei@hyma.io>

* ♻️ Remove unused alias

* ♻️ Change function signature

---------

Co-authored-by: andrei <andrei@hyma.io>
Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
This commit is contained in:
Florian Schrödl 2025-02-11 12:32:28 +01:00 committed by GitHub
parent 5c32ec8cfa
commit 8b380a01e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 143 additions and 88 deletions
common
src/app/common
test/common_tests
frontend/src/app/main/data

View file

@ -458,24 +458,12 @@
[:type [:= :set-tokens-lib]]
[:tokens-lib :any]]]
[:add-token
[:map {:title "AddTokenChange"}
[:type [:= :add-token]]
[:set-token
[:map {:title "SetTokenChange"}
[:type [:= :set-token]]
[:set-name :string]
[:token ::cto/token]]]
[:mod-token
[:map {:title "ModTokenChange"}
[:type [:= :mod-token]]
[:set-name :string]
[:name :string]
[:token ::cto/token]]]
[:del-token
[:map {:title "DelTokenChange"}
[:type [:= :del-token]]
[:set-name :string]
[:name :string]]]]])
[:token-name :string]
[:token [:maybe ::cto/token]]]]]])
(def schema:changes
[:sequential {:gen/max 5 :gen/min 1} schema:change])
@ -1036,29 +1024,21 @@
[data {:keys [tokens-lib]}]
(assoc data :tokens-lib tokens-lib))
(defmethod process-change :add-token
[data {:keys [set-name token]}]
(update data :tokens-lib #(-> %
(ctob/ensure-tokens-lib)
(ctob/add-token-in-set set-name (ctob/make-token token)))))
(defmethod process-change :set-token
[data {:keys [set-name token-name token]}]
(update data :tokens-lib
(fn [lib]
(let [lib' (ctob/ensure-tokens-lib lib)]
(cond
(not token)
(ctob/delete-token-from-set lib' set-name token-name)
(defmethod process-change :mod-token
[data {:keys [set-name name token]}]
(update data :tokens-lib #(-> %
(ctob/ensure-tokens-lib)
(ctob/update-token-in-set
set-name
name
(fn [old-token]
(ctob/make-token (merge old-token token)))))))
(not (ctob/get-token-in-set lib' set-name token-name))
(ctob/add-token-in-set lib' set-name (ctob/make-token token))
(defmethod process-change :del-token
[data {:keys [set-name name]}]
(update data :tokens-lib #(-> %
(ctob/ensure-tokens-lib)
(ctob/delete-token-from-set
set-name
name))))
:else
(ctob/update-token-in-set lib' set-name token-name (fn [prev-token]
(ctob/make-token (merge prev-token token)))))))))
(defmethod process-change :add-temporary-token-theme
[data {:keys [token-theme]}]

View file

@ -884,30 +884,31 @@
(update :undo-changes conj {:type :set-tokens-lib :tokens-lib prev-tokens-lib})
(apply-changes-local))))
(defn add-token
[changes set-name token]
(-> changes
(update :redo-changes conj {:type :add-token :set-name set-name :token token})
(update :undo-changes conj {:type :del-token :set-name set-name :name (:name token)})
(apply-changes-local)))
(defn update-token
[changes set-name token prev-token]
(-> changes
(update :redo-changes conj {:type :mod-token :set-name set-name :name (:name prev-token) :token token})
(update :undo-changes conj {:type :mod-token :set-name set-name :name (:name token) :token (or prev-token token)})
(apply-changes-local)))
(defn delete-token
[changes set-name token-name]
(defn set-token [changes set-name token-name token]
(assert-library! changes)
(let [library-data (::library-data (meta changes))
prev-token (some-> (get library-data :tokens-lib)
(ctob/get-set set-name)
(ctob/get-token token-name))]
(-> changes
(update :redo-changes conj {:type :del-token :set-name set-name :name token-name})
(update :undo-changes conj {:type :add-token :set-name set-name :token prev-token})
(update :redo-changes conj {:type :set-token
:set-name set-name
:token-name token-name
:token token})
(update :undo-changes conj (if prev-token
{:type :set-token
:set-name set-name
:token-name (or
;; Undo of edit
(:name token)
;; Undo of delete
token-name)
:token prev-token}
;; Undo of create token
{:type :set-token
:set-name set-name
:token-name token-name
:token nil}))
(apply-changes-local))))
(defn add-component

View file

@ -35,6 +35,11 @@
(ctob/get-set set-name)
(ctob/get-token token-name)))))
(defn token-data-eq?
"Compare token data without comparing modified timestamp"
[t1 t2]
(= (dissoc t1 :modified-at) (dissoc t2 :modified-at)))
(defn- set-stroke-width
[shape stroke-width]
(let [strokes (if (seq (:strokes shape))

View file

@ -801,6 +801,7 @@ used for managing active sets without a user created theme.")
(set-path-exists? [_ path] "if a set at `path` exists")
(set-group-path-exists? [_ path] "if a set group at `path` exists")
(add-token-in-set [_ set-name token] "add token to a set")
(get-token-in-set [_ set-name token-name] "get token in a set")
(update-token-in-set [_ set-name token-name f] "update a token in a set")
(delete-token-from-set [_ set-name token-name] "delete a token from a set")
(toggle-set-in-theme [_ group-name theme-name set-name] "toggle a set used / not used in a theme")
@ -1134,6 +1135,11 @@ Will return a value that matches this schema:
(dm/assert! "expected valid token instance" (check-token! token))
(update-set this set-name #(add-token % token)))
(get-token-in-set [this set-name token-name]
(some-> this
(get-set set-name)
(get-token token-name)))
(update-token-in-set [this set-name token-name f]
(update-set this set-name #(update-token % token-name f)))

View file

@ -73,6 +73,70 @@
;; Undo
(t/is (some? (ctob/get-hidden-theme undo-lib))))))
(t/deftest set-token-test
(t/testing "delete token"
(let [set-name "foo"
token-name "to.delete.color.red"
file (setup-file #(-> %
(ctob/add-set (ctob/make-token-set :name set-name))
(ctob/add-token-in-set set-name (ctob/make-token {:name token-name
:value "red"
:type :color}))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-name token-name nil))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (nil? (ctob/get-token-in-set redo-lib set-name token-name)))
;; Undo
(t/is (some? (ctob/get-token-in-set undo-lib set-name token-name)))))
(t/testing "add token"
(let [set-name "foo"
token (ctob/make-token {:name "to.add.color.red"
:value "red"
:type :color})
file (setup-file #(-> % (ctob/add-set (ctob/make-token-set :name set-name))))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-name (:name token) token))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (= token (ctob/get-token-in-set redo-lib set-name (:name token))))
;; Undo
(t/is (nil? (ctob/get-token-in-set undo-lib set-name (:name token))))))
(t/testing "update token"
(let [set-name "foo"
prev-token (ctob/make-token {:name "to.update.color.red"
:value "red"
:type :color})
token (-> prev-token
(assoc :name "color.red.changed")
(assoc :value "blue"))
file (setup-file #(-> %
(ctob/add-set (ctob/make-token-set :name set-name))
(ctob/add-token-in-set set-name prev-token)))
changes (-> (pcb/empty-changes)
(pcb/with-library-data (:data file))
(pcb/set-token set-name (:name prev-token) token))
redo (thf/apply-changes file changes)
redo-lib (tht/get-tokens-lib redo)
undo (thf/apply-undo-changes redo changes)
undo-lib (tht/get-tokens-lib undo)]
(t/is (tht/token-data-eq? token (ctob/get-token-in-set redo-lib set-name (:name token))))
(t/is (nil? (ctob/get-token-in-set redo-lib set-name (:name prev-token))))
;; Undo
(t/is (tht/token-data-eq? prev-token (ctob/get-token-in-set undo-lib set-name (:name prev-token))))
(t/is (nil? (ctob/get-token-in-set undo-lib set-name (:name token)))))))
(t/deftest generate-toggle-token-set-group-test
(t/testing "toggling set group with no active sets inside will activate all child sets"
(let [file (setup-file #(-> %

View file

@ -7,8 +7,8 @@
(ns common-tests.types.tokens-lib-test
(:require
#?(:clj [app.common.fressian :as fres])
#?(:clj [clojure.data.json :as json])
[app.common.data :as d]
[app.common.test-helpers.tokens :as tht]
[app.common.time :as dt]
[app.common.transit :as tr]
[app.common.types.tokens-lib :as ctob]
@ -1188,8 +1188,7 @@
lib (ctob/decode-dtcg-json (ctob/ensure-tokens-lib nil) json)
get-set-token (fn [set-name token-name]
(some-> (ctob/get-set lib set-name)
(ctob/get-token token-name)
(dissoc :modified-at)))
(ctob/get-token token-name)))
token-theme (ctob/get-theme lib "group-1" "theme-1")]
(t/is (= '("core" "light" "dark" "theme") (ctob/get-ordered-set-names lib)))
(t/testing "set exists in theme"
@ -1197,21 +1196,21 @@
(t/is (= (:name token-theme) "theme-1"))
(t/is (= (:sets token-theme) #{"light"})))
(t/testing "tokens exist in core set"
(t/is (= (get-set-token "core" "colors.red.600")
{:name "colors.red.600"
:type :color
:value "#e53e3e"
:description nil}))
(t/is (= (get-set-token "core" "spacing.multi-value")
{:name "spacing.multi-value"
:type :spacing
:value "{dimension.sm} {dimension.xl}"
:description "You can have multiple values in a single spacing token"}))
(t/is (= (get-set-token "theme" "button.primary.background")
{:name "button.primary.background"
:type :color
:value "{accent.default}"
:description nil})))
(t/is (tht/token-data-eq? (get-set-token "core" "colors.red.600")
{:name "colors.red.600"
:type :color
:value "#e53e3e"
:description nil}))
(t/is (tht/token-data-eq? (get-set-token "core" "spacing.multi-value")
{:name "spacing.multi-value"
:type :spacing
:value "{dimension.sm} {dimension.xl}"
:description "You can have multiple values in a single spacing token"}))
(t/is (tht/token-data-eq? (get-set-token "theme" "button.primary.background")
{:name "button.primary.background"
:type :color
:value "{accent.default}"
:description nil})))
(t/testing "invalid tokens got discarded"
(t/is (nil? (get-set-token "typography" "H1.Bold"))))))

View file

@ -20,7 +20,6 @@
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.tokens.selected-set :as dwts]
[app.main.data.workspace.undo :as dwu]
[app.main.store :as st]
[app.main.ui.workspace.tokens.update :as wtu]
[app.util.i18n :refer [tr]]
[beicon.v2.core :as rx]
@ -241,14 +240,15 @@
[{:keys [token prev-token-name]}]
(ptk/reify ::update-create-token
ptk/WatchEvent
(watch [_ state _]
(let [token-set (dwts/get-selected-token-set state)
token-set-name (or (:name token-set) "Global")
(watch [it state _]
(let [data (dsh/lookup-file-data state)
token-set (dwts/get-selected-token-set state)
set-name (or (:name token-set) "Global")
changes (if (not token-set)
;; No set created add a global set
(let [tokens-lib (get-tokens-lib state)
token-set (ctob/make-token-set :name token-set-name :tokens {(:name token) token})
hidden-theme (ctob/make-hidden-token-theme :sets [token-set-name])
token-set (ctob/make-token-set :name set-name :tokens {(:name token) token})
hidden-theme (ctob/make-hidden-token-theme :sets [set-name])
active-theme-paths (some-> tokens-lib ctob/get-active-theme-paths)
add-to-hidden-theme? (= active-theme-paths #{ctob/hidden-token-theme-path})
base-changes (pcb/add-token-set (pcb/empty-changes) token-set)]
@ -262,14 +262,14 @@
(pcb/update-token-theme (ctob/toggle-set prev-hidden-theme ctob/hidden-token-theme-path) prev-hidden-theme)))
:else base-changes))
;; Either update or add token to existing set
(if-let [prev-token (ctob/get-token token-set (or prev-token-name (:name token)))]
(pcb/update-token (pcb/empty-changes) (:name token-set) token prev-token)
(do
(st/emit! (ptk/event ::ev/event {::ev/name "create-tokens"}))
(pcb/add-token (pcb/empty-changes) (:name token-set) token))))]
(-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/set-token set-name (or prev-token-name (:name token)) token)))]
(rx/of
(dwts/set-selected-token-set-name token-set-name)
(dwts/set-selected-token-set-name set-name)
(when-not prev-token-name
(ptk/event ::ev/event {::ev/name "create-tokens"}))
(dch/commit-changes changes))))))
(defn delete-token
@ -282,7 +282,7 @@
(let [data (dsh/lookup-file-data state)
changes (-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/delete-token set-name token-name))]
(pcb/set-token set-name token-name nil))]
(rx/of (dch/commit-changes changes))))))
(defn duplicate-token