diff --git a/common/src/app/common/logic/shapes.cljc b/common/src/app/common/logic/shapes.cljc index 24b89bc1a..4f544280d 100644 --- a/common/src/app/common/logic/shapes.cljc +++ b/common/src/app/common/logic/shapes.cljc @@ -14,8 +14,33 @@ [app.common.types.container :as ctn] [app.common.types.shape.interactions :as ctsi] [app.common.types.shape.layout :as ctl] + [app.common.types.token :as cto] [app.common.uuid :as uuid])) +(defn- check-unapply-tokens + [changes objects] + (let [mod-obj-changes (->> (:redo-changes changes) + (filter #(= (:type %) :mod-obj))) + + check-attr (fn [shape changes attr] + (let [tokens (get shape :applied-tokens {}) + token-attrs (cto/shape-attr->token-attrs attr)] + (if (some #(contains? tokens %) token-attrs) + (pcb/update-shapes changes [(:id shape)] #(cto/unapply-token-id % token-attrs)) + changes))) + + check-shape (fn [changes mod-obj-change] + (let [shape (get objects (:id mod-obj-change)) + xf (comp (filter #(= (:type %) :set)) + (map :attr)) + attrs (into [] xf (:operations mod-obj-change))] + (reduce (partial check-attr shape) + changes + attrs)))] + (reduce check-shape + changes + mod-obj-changes))) + (defn generate-update-shapes [changes ids update-fn objects {:keys [attrs ignore-tree ignore-touched with-objects?]}] (let [changes (reduce @@ -29,8 +54,12 @@ (pcb/with-objects objects)) ids) grid-ids (->> ids (filter (partial ctl/grid-layout? objects))) - changes (pcb/update-shapes changes grid-ids ctl/assign-cell-positions {:with-objects? true}) - changes (pcb/reorder-grid-children changes ids)] + changes (-> changes + (pcb/update-shapes grid-ids ctl/assign-cell-positions {:with-objects? true}) + (pcb/reorder-grid-children ids) + (cond-> + (not ignore-touched) + (check-unapply-tokens objects)))] changes)) (defn- generate-update-shape-flags diff --git a/common/src/app/common/test_helpers/tokens.cljc b/common/src/app/common/test_helpers/tokens.cljc index 7ddb78a3d..cc008c70d 100644 --- a/common/src/app/common/test_helpers/tokens.cljc +++ b/common/src/app/common/test_helpers/tokens.cljc @@ -23,6 +23,14 @@ [file f] (ctf/update-file-data file #(update % :tokens-lib f))) +(defn get-token + [file set-name token-name] + (let [tokens-lib (:tokens-lib (:data file))] + (when tokens-lib + (-> tokens-lib + (ctob/get-set set-name) + (ctob/get-token token-name))))) + (defn- set-stroke-width [shape stroke-width] (let [strokes (if (seq (:strokes shape)) diff --git a/common/test/common_tests/logic/token_apply_test.cljc b/common/test/common_tests/logic/token_apply_test.cljc new file mode 100644 index 000000000..7e53608c8 --- /dev/null +++ b/common/test/common_tests/logic/token_apply_test.cljc @@ -0,0 +1,198 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns common-tests.logic.token-apply-test + (:require + [app.common.files.changes-builder :as pcb] + [app.common.logic.shapes :as cls] + [app.common.test-helpers.compositions :as tho] + [app.common.test-helpers.files :as thf] + [app.common.test-helpers.ids-map :as thi] + [app.common.test-helpers.shapes :as ths] + [app.common.test-helpers.tokens :as tht] + [app.common.types.container :as ctn] + [app.common.types.token :as cto] + [app.common.types.tokens-lib :as ctob] + [clojure.test :as t])) + +(t/use-fixtures :each thi/test-fixture) + +(defn- setup-file + [] + (-> (thf/sample-file :file1) + (tht/add-tokens-lib) + (tht/update-tokens-lib #(-> % + (ctob/add-set (ctob/make-token-set :name "test-token-set")) + (ctob/add-theme (ctob/make-token-theme :name "test-theme" + :sets #{"test-token-set"})) + (ctob/set-active-themes #{"/test-theme"}) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "token-radius" + :type :border-radius + :value 10)) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "token-rotation" + :type :rotation + :value 30)) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "token-opacity" + :type :opacity + :value 0.7)) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "token-stroke-width" + :type :stroke-width + :value 2)) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "token-color" + :type :color + :value "#00ff00")) + (ctob/add-token-in-set "test-token-set" + (ctob/make-token :name "token-dimensions" + :type :dimensions + :value 100)))) + (tho/add-frame :frame1))) + +(defn- apply-all-tokens + [file] + (-> file + (tht/apply-token-to-shape :frame1 "token-radius" [:rx :ry] [:rx :ry] 10) + (tht/apply-token-to-shape :frame1 "token-rotation" [:rotation] [:rotation] 30) + (tht/apply-token-to-shape :frame1 "token-opacity" [:opacity] [:opacity] 0.7) + (tht/apply-token-to-shape :frame1 "token-stroke-width" [:stroke-width] [:stroke-width] 2) + (tht/apply-token-to-shape :frame1 "token-color" [:stroke-color] [:stroke-color] "#00ff00") + (tht/apply-token-to-shape :frame1 "token-color" [:fill] [:fill] "#00ff00") + (tht/apply-token-to-shape :frame1 "token-dimensions" [:width :height] [:width :height] 100))) + +(t/deftest apply-tokens-to-shape + (let [;; ==== Setup + file (setup-file) + page (thf/current-page file) + frame1 (ths/get-shape file :frame1) + token-radius (tht/get-token file "test-token-set" "token-radius") + token-rotation (tht/get-token file "test-token-set" "token-rotation") + token-opacity (tht/get-token file "test-token-set" "token-opacity") + token-stroke-width (tht/get-token file "test-token-set" "token-stroke-width") + token-color (tht/get-token file "test-token-set" "token-color") + token-dimensions (tht/get-token file "test-token-set" "token-dimensions") + + ;; ==== Action + changes (-> (-> (pcb/empty-changes nil) + (pcb/with-page page) + (pcb/with-objects (:objects page))) + (cls/generate-update-shapes [(:id frame1)] + (fn [shape] + (as-> shape $ + (cto/maybe-apply-token-to-shape {:token nil ; test nil case + :shape $ + :attributes []}) + (cto/maybe-apply-token-to-shape {:token token-radius + :shape $ + :attributes [:rx :ry]}) + (cto/maybe-apply-token-to-shape {:token token-rotation + :shape $ + :attributes [:rotation]}) + (cto/maybe-apply-token-to-shape {:token token-opacity + :shape $ + :attributes [:opacity]}) + (cto/maybe-apply-token-to-shape {:token token-stroke-width + :shape $ + :attributes [:stroke-width]}) + (cto/maybe-apply-token-to-shape {:token token-color + :shape $ + :attributes [:stroke-color]}) + (cto/maybe-apply-token-to-shape {:token token-color + :shape $ + :attributes [:fill]}) + (cto/maybe-apply-token-to-shape {:token token-dimensions + :shape $ + :attributes [:width :height]}))) + (:objects page) + {})) + + file' (thf/apply-changes file changes) + + ;; ==== Get + frame1' (ths/get-shape file' :frame1) + applied-tokens' (:applied-tokens frame1')] + + ;; ==== Check + (t/is (= (count applied-tokens') 9)) + (t/is (= (:rx applied-tokens') "token-radius")) + (t/is (= (:ry applied-tokens') "token-radius")) + (t/is (= (:rotation applied-tokens') "token-rotation")) + (t/is (= (:opacity applied-tokens') "token-opacity")) + (t/is (= (:stroke-width applied-tokens') "token-stroke-width")) + (t/is (= (:stroke-color applied-tokens') "token-color")) + (t/is (= (:fill applied-tokens') "token-color")) + (t/is (= (:width applied-tokens') "token-dimensions")) + (t/is (= (:height applied-tokens') "token-dimensions")))) + +(t/deftest unapply-tokens-from-shape + (let [;; ==== Setup + file (-> (setup-file) + (apply-all-tokens)) + page (thf/current-page file) + frame1 (ths/get-shape file :frame1) + + ;; ==== Action + changes (-> (-> (pcb/empty-changes nil) + (pcb/with-page page) + (pcb/with-objects (:objects page))) + (cls/generate-update-shapes [(:id frame1)] + (fn [shape] + (-> shape + (cto/unapply-token-id [:rx :ry]) + (cto/unapply-token-id [:rotation]) + (cto/unapply-token-id [:opacity]) + (cto/unapply-token-id [:stroke-width]) + (cto/unapply-token-id [:stroke-color]) + (cto/unapply-token-id [:fill]) + (cto/unapply-token-id [:width :height]))) + (:objects page) + {})) + + file' (thf/apply-changes file changes) + + ;; ==== Get + frame1' (ths/get-shape file' :frame1) + applied-tokens' (:applied-tokens frame1')] + + ;; ==== Check + (t/is (= (count applied-tokens') 0)))) + +(t/deftest unapply-tokens-automatic + (let [;; ==== Setup + file (-> (setup-file) + (apply-all-tokens)) + page (thf/current-page file) + frame1 (ths/get-shape file :frame1) + + ;; ==== Action + changes (-> (-> (pcb/empty-changes nil) + (pcb/with-page page) + (pcb/with-objects (:objects page))) + (cls/generate-update-shapes [(:id frame1)] + (fn [shape] + (-> shape + (ctn/set-shape-attr :rx 0) + (ctn/set-shape-attr :ry 0) + (ctn/set-shape-attr :rotation 0) + (ctn/set-shape-attr :opacity 0) + (ctn/set-shape-attr :strokes []) + (ctn/set-shape-attr :fills []) + (ctn/set-shape-attr :width 0) + (ctn/set-shape-attr :height 0))) + (:objects page) + {})) + + file' (thf/apply-changes file changes) + + ;; ==== Get + frame1' (ths/get-shape file' :frame1) + applied-tokens' (:applied-tokens frame1')] + + ;; ==== Check + (t/is (= (count applied-tokens') 0)))) \ No newline at end of file diff --git a/frontend/test/frontend_tests/logic/components_and_tokens.cljs b/frontend/test/frontend_tests/logic/components_and_tokens.cljs index a51985ef8..9d25de27c 100644 --- a/frontend/test/frontend_tests/logic/components_and_tokens.cljs +++ b/frontend/test/frontend_tests/logic/components_and_tokens.cljs @@ -297,27 +297,27 @@ (ctob/add-theme (ctob/make-token-theme :name "test-theme" :sets #{"test-token-set"})) (ctob/set-active-themes #{"/test-theme"}) - (ctob/add-token-in-set "token-radius" + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "token-radius" :type :border-radius :value 10)) - (ctob/add-token-in-set "token-rotation" + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "token-rotation" :type :rotation :value 30)) - (ctob/add-token-in-set "token-opacity" + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "token-opacity" :type :opacity :value 0.7)) - (ctob/add-token-in-set "token-stroke-width" + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "token-stroke-width" :type :stroke-width :value 2)) - (ctob/add-token-in-set "token-color" + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "token-color" :type :color :value "#00ff00")) - (ctob/add-token-in-set "token-dimensions" + (ctob/add-token-in-set "test-token-set" (ctob/make-token :name "token-dimensions" :type :dimensions :value 100)))) diff --git a/frontend/test/frontend_tests/tokens/helpers/tokens.cljs b/frontend/test/frontend_tests/tokens/helpers/tokens.cljs index 29316a1fa..5bfe1ed70 100644 --- a/frontend/test/frontend_tests/tokens/helpers/tokens.cljs +++ b/frontend/test/frontend_tests/tokens/helpers/tokens.cljs @@ -4,11 +4,6 @@ [app.common.types.tokens-lib :as ctob] [app.main.ui.workspace.tokens.token :as wtt])) -(defn add-token [state label params] - (let [id (thi/new-id! label) - token (assoc params :id id)] - (update-in state [:data :tokens] assoc id token))) - (defn get-token [file name] (some-> (get-in file [:data :tokens-lib]) (ctob/get-active-themes-set-tokens)