Merge pull request #6096 from penpot/niwinz-develop-token-fixes-3

 Add several improvements and fixes to tokens (part 3)
This commit is contained in:
Andrey Antukh 2025-03-19 12:30:05 +01:00 committed by GitHub
commit 8fa24de3d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 290 additions and 385 deletions

View file

@ -648,9 +648,7 @@
(defn detach-comment-thread
"Detach comment threads that are inside a frame when that frame is deleted"
[ids]
(dm/assert!
"expected a valid coll of uuid's"
(sm/check-coll-of-uuid! ids))
(assert (sm/check-coll-of-uuid ids))
(ptk/reify ::detach-comment-thread
ptk/WatchEvent

View file

@ -536,11 +536,8 @@
(defn move-files
[{:keys [ids project-id] :as params}]
(dm/assert! (uuid? project-id))
(dm/assert!
"expected a valid set of uuids"
(sm/check-set-of-uuid! ids))
(assert (uuid? project-id))
(assert (sm/check-set-of-uuid ids))
(ptk/reify ::move-files
ev/Event

View file

@ -350,12 +350,10 @@
(defn create-invitations
[{:keys [emails role team-id resend?] :as params}]
(dm/assert! (keyword? role))
(dm/assert! (uuid? team-id))
(dm/assert!
"expected a valid set of emails"
(sm/check-set-of-emails! emails))
(assert (keyword? role))
(assert (uuid? team-id))
(assert (sm/check-set-of-emails emails))
(ptk/reify ::create-invitations
ev/Event
@ -376,11 +374,8 @@
(defn copy-invitation-link
[{:keys [email team-id] :as params}]
(dm/assert!
"expected a valid email"
(sm/check-email! email))
(dm/assert! (uuid? team-id))
(assert (sm/check-email email))
(assert (uuid? team-id))
(ptk/reify ::copy-invitation-link
IDeref
@ -406,12 +401,9 @@
(defn update-invitation-role
[{:keys [email team-id role] :as params}]
(dm/assert!
"expected a valid email"
(sm/check-email! email))
(dm/assert! (uuid? team-id))
(dm/assert! (contains? ctt/valid-roles role))
(assert (sm/check-email email))
(assert (uuid? team-id))
(assert (contains? ctt/valid-roles role))
(ptk/reify ::update-invitation-role
IDeref
@ -428,8 +420,9 @@
(defn delete-invitation
[{:keys [email team-id] :as params}]
(dm/assert! (sm/check-email! email))
(dm/assert! (uuid? team-id))
(assert (sm/check-email email))
(assert (uuid? team-id))
(ptk/reify ::delete-invitation
ptk/WatchEvent
(watch [_ _ _]

View file

@ -134,9 +134,7 @@
;; Move comment threads that are inside a frame when that frame is moved"
(defmethod ptk/resolve ::move-frame-comment-threads
[_ ids]
(dm/assert!
"expected a valid coll of uuid's"
(sm/check-coll-of-uuid! ids))
(assert (sm/check-coll-of-uuid ids))
(ptk/reify ::move-frame-comment-threads
ptk/WatchEvent

View file

@ -533,14 +533,98 @@
(assoc state :workspace-modifiers modif-tree)))))
(def ^:private xf:without-uuid-zero
(remove #(= % uuid/zero)))
(def ^:private transform-attrs
#{:selrect
:points
:x
:y
:r1
:r2
:r3
:r4
:shadow
:blur
:strokes
:width
:height
:content
:transform
:transform-inverse
:rotation
:flip-x
:flip-y
:grow-type
:position-data
:layout-gap
:layout-padding
:layout-item-h-sizing
:layout-item-max-h
:layout-item-max-w
:layout-item-min-h
:layout-item-min-w
:layout-item-v-sizing
:layout-padding-type
:layout-item-margin
:layout-item-margin-type
:layout-grid-cells
:layout-grid-columns
:layout-grid-rows})
(defn apply-modifiers*
"A lower-level version of apply-modifiers, that expects receive ready
to use objects, object-modifiers and text-modifiers."
[objects object-modifiers text-modifiers options]
(ptk/reify ::apply-modifiers*
ptk/WatchEvent
(watch [_ _ _]
(let [ids
(into [] xf:without-uuid-zero (keys object-modifiers))
ids-with-children
(into ids
(mapcat (partial cfh/get-children-ids objects))
ids)
ignore-tree
(calculate-ignore-tree object-modifiers objects)
options
(-> options
(assoc :reg-objects? true)
(assoc :ignore-tree ignore-tree)
;; Attributes that can change in the transform. This
;; way we don't have to check all the attributes
(assoc :attrs transform-attrs))
update-shape
(fn [shape]
(let [shape-id (dm/get-prop shape :id)
modifiers (dm/get-in object-modifiers [shape-id :modifiers])
text-shape? (cfh/text-shape? shape)
pos-data (when ^boolean text-shape?
(dm/get-in text-modifiers [shape-id :position-data]))]
(-> shape
(gsh/transform-shape modifiers)
(cond-> (d/not-empty? pos-data)
(assoc-position-data pos-data shape))
(cond-> text-shape?
(update-grow-type shape)))))]
(rx/of (ptk/event ::dwg/move-frame-guides {:ids ids-with-children :modifiers object-modifiers})
(ptk/event ::dwcm/move-frame-comment-threads ids-with-children)
(dwsh/update-shapes ids update-shape options))))))
(defn apply-modifiers
([]
(apply-modifiers nil))
([{:keys [modifiers undo-transation? stack-undo? ignore-constraints
ignore-snap-pixel ignore-touched undo-group page-id]
:or {undo-transation? true stack-undo? false ignore-constraints false
ignore-snap-pixel false ignore-touched false}}]
([{:keys [modifiers undo-transation? ignore-constraints
ignore-snap-pixel page-id]
:or {undo-transation? true ignore-constraints false
ignore-snap-pixel false}
:as options}]
(ptk/reify ::apply-modifiers
ptk/WatchEvent
(watch [_ state _]
@ -553,88 +637,17 @@
(calculate-modifiers state ignore-constraints ignore-snap-pixel modifiers page-id)
(get state :workspace-modifiers))
ids
(into []
(remove #(= % uuid/zero))
(keys object-modifiers))
ids-with-children
(into ids
(mapcat (partial cfh/get-children-ids objects))
ids)
ignore-tree
(calculate-ignore-tree object-modifiers objects)
undo-id (js/Symbol)]
undo-id
(js/Symbol)]
(rx/concat
(if undo-transation?
(rx/of (dwu/start-undo-transaction undo-id))
(rx/empty))
(rx/of (ptk/event ::dwg/move-frame-guides {:ids ids-with-children :modifiers object-modifiers})
(ptk/event ::dwcm/move-frame-comment-threads ids-with-children)
(dwsh/update-shapes
ids
(fn [shape]
(let [modif (get-in object-modifiers [(:id shape) :modifiers])
text-shape? (cfh/text-shape? shape)
position-data (when text-shape?
(dm/get-in text-modifiers [(:id shape) :position-data]))]
(-> shape
(gsh/transform-shape modif)
(cond-> (d/not-empty? position-data)
(assoc-position-data position-data shape))
(cond-> text-shape?
(update-grow-type shape)))))
{:reg-objects? true
:stack-undo? stack-undo?
:ignore-tree ignore-tree
:ignore-touched ignore-touched
:undo-group undo-group
:page-id page-id
;; Attributes that can change in the transform. This way we don't have to check
;; all the attributes
:attrs [:selrect
:points
:x
:y
:r1
:r2
:r3
:r4
:shadow
:blur
:strokes
:width
:height
:content
:transform
:transform-inverse
:rotation
:flip-x
:flip-y
:grow-type
:position-data
:layout-gap
:layout-padding
:layout-item-h-sizing
:layout-item-margin
:layout-item-max-h
:layout-item-max-w
:layout-item-min-h
:layout-item-min-w
:layout-item-v-sizing
:layout-padding-type
:layout-gap
:layout-item-margin
:layout-item-margin-type
:layout-grid-cells
:layout-grid-columns
:layout-grid-rows]})
;; We've applied the text-modifier so we can dissoc the temporary data
(rx/of (apply-modifiers* objects object-modifiers text-modifiers options)
(fn [state]
(update state :workspace-text-modifier #(apply dissoc % ids))))
(let [ids (into [] xf:without-uuid-zero (keys object-modifiers))]
(update state :workspace-text-modifier #(apply dissoc % ids)))))
(if (nil? modifiers)
(rx/of (clear-local-transform))
(rx/empty))

View file

@ -51,11 +51,8 @@
([ids update-fn {:keys [reg-objects? save-undo? stack-undo? attrs ignore-tree page-id ignore-touched undo-group with-objects? changed-sub-attr]
:or {reg-objects? false save-undo? true stack-undo? false ignore-touched false with-objects? false}}]
(dm/assert!
"expected a valid coll of uuid's"
(sm/check-coll-of-uuid! ids))
(dm/assert! (fn? update-fn))
(assert (sm/check-coll-of-uuid ids))
(assert (fn? update-fn))
(ptk/reify ::update-shapes
ptk/WatchEvent
@ -162,9 +159,7 @@
([ids] (delete-shapes nil ids {}))
([page-id ids] (delete-shapes page-id ids {}))
([page-id ids options]
(dm/assert!
"expected a valid set of uuid's"
(sm/check-set-of-uuid! ids))
(assert (sm/check-set-of-uuid ids))
(ptk/reify ::delete-shapes
ptk/WatchEvent

View file

@ -340,35 +340,35 @@
(rx/filter (ptk/type? ::trigger-bounding-box-cloaking) stream)))))))
(defn update-dimensions
"Change size of shapes, from the sideber options form.
Will ignore pixel snap used in the options side panel"
"Change size of shapes, from the sidebar options form
(will ignore pixel snap)"
([ids attr value] (update-dimensions ids attr value nil))
([ids attr value options]
(dm/assert! (number? value))
(dm/assert!
"expected valid coll of uuids"
(every? uuid? ids))
(dm/assert!
"expected valid attr"
(contains? #{:width :height} attr))
(ptk/reify ::update-dimensions
ptk/UpdateEvent
(update [_ state]
(let [page-id (or (get options :page-id)
(get state :current-page-id))
(assert (number? value))
(assert (every? uuid? ids)
"expected valid coll of uuids")
(assert (contains? #{:width :height} attr)
"expected valid attr")
(ptk/reify ::update-dimensions
ptk/WatchEvent
(watch [_ state _]
(let [page-id
(or (get options :page-id)
(get state :current-page-id))
objects
(dsh/lookup-page-objects state page-id)
objects (dsh/lookup-page-objects state page-id)
get-modifier
(fn [shape] (ctm/change-dimensions-modifiers shape attr value))
(fn [shape]
(ctm/change-dimensions-modifiers shape attr value))
modif-tree
(-> (dwm/build-modif-tree ids objects get-modifier)
(gm/set-objects-modifiers objects))]
(assoc state :workspace-modifiers modif-tree)))
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwm/apply-modifiers options))))))
(rx/of (dwm/apply-modifiers* objects modif-tree nil options)))))))
(defn change-orientation
"Change orientation of shapes, from the sidebar options form.

View file

@ -22,7 +22,8 @@
;; Change this to :info :debug or :trace to debug this module
(log/set-level! :warn)
(def discard-transaction-time-millis (* 20 1000))
(def ^:private
discard-transaction-time-millis (* 20 1000))
(def ^:private
schema:undo-entry
@ -30,7 +31,7 @@
[:undo-changes [:vector ::cpc/change]]
[:redo-changes [:vector ::cpc/change]]])
(def check-undo-entry!
(def check-undo-entry
(sm/check-fn schema:undo-entry))
(def MAX-UNDO-SIZE 50)
@ -48,8 +49,7 @@
(ptk/reify ::materialize-undo
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:workspace-undo :index] index)))))
(update state :workspace-undo assoc :index index))))
(defn- add-undo-entry
[state entry]
@ -88,12 +88,9 @@
(defn append-undo
[entry stack?]
(dm/assert!
"expected valid undo entry"
(check-undo-entry! entry))
(dm/assert!
(boolean? stack?))
(assert (check-undo-entry entry))
(assert (boolean? stack?))
(ptk/reify ::append-undo
ptk/UpdateEvent
@ -118,17 +115,11 @@
(defn start-undo-transaction
"Start a transaction, so that every changes inside are added together in a single undo entry."
[id]
[id & {:keys [timeout] :or {timeout discard-transaction-time-millis}}]
(ptk/reify ::start-undo-transaction
ptk/WatchEvent
(watch [_ _ _]
(->> (rx/of (check-open-transactions))
;; Wait the configured time
(rx/delay discard-transaction-time-millis)))
ptk/UpdateEvent
(update [_ state]
(log/info :msg "start-undo-transaction")
(log/info :hint "start-undo-transaction")
;; We commit the old transaction before starting the new one
(let [current-tx (get-in state [:workspace-undo :transaction])
pending-tx (get-in state [:workspace-undo :transactions-pending])]
@ -136,20 +127,28 @@
(nil? current-tx) (assoc-in [:workspace-undo :transaction] empty-tx)
(nil? pending-tx) (assoc-in [:workspace-undo :transactions-pending] #{id})
(some? pending-tx) (update-in [:workspace-undo :transactions-pending] conj id)
:always (update-in [:workspace-undo :transactions-pending-ts] assoc id (dt/now)))))))
:always (update-in [:workspace-undo :transactions-pending-ts] assoc id (dt/now)))))
ptk/WatchEvent
(watch [_ _ _]
(when (and timeout (pos? timeout))
(->> (rx/of (check-open-transactions timeout))
;; Wait the configured time
(rx/delay timeout))))))
(defn discard-undo-transaction []
(ptk/reify ::discard-undo-transaction
ptk/UpdateEvent
(update [_ state]
(log/info :msg "discard-undo-transaction")
(log/info :hint "discard-undo-transaction")
(update state :workspace-undo dissoc :transaction :transactions-pending :transactions-pending-ts))))
(defn commit-undo-transaction [id]
(ptk/reify ::commit-undo-transaction
ptk/UpdateEvent
(update [_ state]
(log/info :msg "commit-undo-transaction")
(log/info :hint "commit-undo-transaction")
(let [state (-> state
(update-in [:workspace-undo :transactions-pending] disj id)
(update-in [:workspace-undo :transactions-pending-ts] dissoc id))]
@ -166,15 +165,15 @@
(assoc state :workspace-undo {}))))
(defn check-open-transactions
[]
[timeout]
(ptk/reify ::check-open-transactions
ptk/WatchEvent
(watch [_ state _]
(log/info :msg "check-open-transactions")
(log/info :hint "check-open-transactions" :timeout timeout)
(let [pending-ts (-> (dm/get-in state [:workspace-undo :transactions-pending-ts])
(update-vals #(.toMillis (dt/diff (dt/now) %))))]
(update-vals #(inst-ms (dt/diff (dt/now) %))))]
(->> pending-ts
(filter (fn [[_ ts]] (>= ts discard-transaction-time-millis)))
(filter (fn [[_ ts]] (>= ts timeout)))
(rx/from)
(rx/tap #(js/console.warn (dm/str "FORCE COMMIT TRANSACTION AFTER " (second %) "MS")))
(rx/map first)

View file

@ -1,6 +1,13 @@
;; 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 app.main.ui.workspace.tokens.update
(:require
[app.common.files.helpers :as cfh]
[app.common.logging :as l]
[app.common.types.token :as ctt]
[app.main.data.helpers :as dsh]
[app.main.data.workspace.shapes :as dwsh]
@ -9,6 +16,7 @@
[app.main.ui.workspace.tokens.changes :as wtch]
[app.main.ui.workspace.tokens.style-dictionary :as wtsd]
[app.main.ui.workspace.tokens.token-set :as wtts]
[app.util.time :as dt]
[beicon.v2.core :as rx]
[clojure.data :as data]
[clojure.set :as set]
@ -70,7 +78,7 @@
(reduce
(fn [acc [attrs v]]
(cond
(some attrs #{:widht :height}) (let [[_ a b] (data/diff #{:width :height} attrs)]
(some attrs #{:width :height}) (let [[_ a b] (data/diff #{:width :height} attrs)]
(cond-> (assoc acc b v)
;; Exact match in attrs
a (assoc a v)))
@ -127,8 +135,14 @@
[state resolved-tokens]
(let [file-id (get state :current-file-id)
current-page-id (get state :current-page-id)
fdata (dsh/lookup-file-data state file-id)]
(->> (rx/from (:pages fdata))
fdata (dsh/lookup-file-data state file-id)
tpoint (dt/tpoint-ms)]
(l/inf :status "START" :hint "update-tokens")
(->> (rx/concat
(rx/of current-page-id)
(->> (rx/from (:pages fdata))
(rx/filter (fn [id] (not= id current-page-id)))))
(rx/mapcat
(fn [page-id]
(let [page
@ -140,6 +154,12 @@
actions
(actionize-shapes-update-info page-id attrs)]
(l/inf :status "PROGRESS"
:hint "update-tokens"
:page-id (str page-id)
:elapsed (tpoint)
::l/sync? true)
(rx/merge
(rx/from actions)
(->> (rx/from frame-ids)
@ -151,7 +171,11 @@
(fn [shape]
(dissoc shape :position-data))
{:page-id page-id
:ignore-touched true}))))))))))
:ignore-touched true})))))))
(rx/finalize
(fn [_]
(let [elapsed (tpoint)]
(l/inf :status "END" :hint "update-tokens" :elapsed elapsed)))))))
(defn update-workspace-tokens
[]
@ -164,6 +188,6 @@
(rx/mapcat (fn [sd-tokens]
(let [undo-id (js/Symbol)]
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(rx/of (dwu/start-undo-transaction undo-id :timeout false))
(update-tokens state sd-tokens)
(rx/of (dwu/commit-undo-transaction undo-id)))))))))))