🐛 Keep component sync when a user text resize joins a derived batch

This commit is contained in:
Elena Torro 2026-09-03 13:28:58 +02:00
parent 87d9110ec5
commit b08002bc0b
3 changed files with 76 additions and 6 deletions

View File

@ -96,10 +96,15 @@
(defn- merge-resize-debounce-opts
[prev {:keys [undo-group undo-id skip-component-sync?]}]
(cond-> (or prev {})
(some? undo-group) (assoc :undo-group undo-group)
(some? undo-id) (assoc :undo-id undo-id)
skip-component-sync? (assoc :skip-component-sync? true)))
;; One commit per batch, so one flag for every shape in it. Keep it on
;; only while every resize in the batch is derived.
(let [prev (or prev {:skip-component-sync? true})]
(cond-> prev
(some? undo-group) (assoc :undo-group undo-group)
(some? undo-id) (assoc :undo-id undo-id)
:always (assoc :skip-component-sync?
(boolean (and skip-component-sync?
(:skip-component-sync? prev)))))))
(defn resize-wasm-text-debounce-commit
[]
@ -160,8 +165,7 @@
(-> state
(update ::resize-wasm-text-debounce-ids (fnil conj []) id)
(update ::resize-wasm-text-reflow-tasks (fnil conj []) reflow-task)
(cond-> (seq opts)
(update ::resize-wasm-text-debounce-opts merge-resize-debounce-opts opts))
(update ::resize-wasm-text-debounce-opts merge-resize-debounce-opts opts)
(cond-> (nil? (::resize-wasm-text-debounce-event state))
(assoc ::resize-wasm-text-debounce-event cur-event))))

View File

@ -0,0 +1,64 @@
;; 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 SUBSIDIARY SL
(ns frontend-tests.render-wasm.resize-debounce-opts-test
(:require
[app.common.test-helpers.compositions :as ctho]
[app.common.test-helpers.files :as cthf]
[app.common.test-helpers.ids-map :as cthi]
[app.common.test-helpers.shapes :as cths]
[app.main.data.workspace.wasm-text :as dwwt]
[cljs.test :as t :include-macros true]
[frontend-tests.helpers.pages :as thp]
[frontend-tests.helpers.state :as ths]
[frontend-tests.helpers.wasm :as thw]))
(t/use-fixtures :each
{:before (fn []
(thp/reset-idmap!)
(thw/setup-wasm-mocks!))
:after thw/teardown-wasm-mocks!})
(defn- setup-file []
(-> (cthf/sample-file :file-1 :page-label :page-1)
(ctho/add-text :text-1 "Derived")
(ctho/add-text :text-2 "User edit")))
(defn- batch-opts
[state]
(get state :app.main.data.workspace.wasm-text/resize-wasm-text-debounce-opts))
(t/deftest derived-flag-does-not-leak-into-a-user-resize-in-the-same-batch
(t/async
done
(let [file (setup-file)
store (ths/setup-store file)
text-1 (cths/get-shape file :text-1)
text-2 (cths/get-shape file :text-2)
;; Same tick => both ids land in the same debounce batch, which is
;; what a font-load resize racing a sidebar resize produces.
events [(dwwt/resize-wasm-text-debounce (:id text-1) {:skip-component-sync? true})
(dwwt/resize-wasm-text-debounce (:id text-2) nil)]]
(ths/run-store
store done events
(fn [state]
;; 3, not 2: the batch owner re-emits itself so text-1 is queued twice.
(t/is (= 3 (count (get state :app.main.data.workspace.wasm-text/resize-wasm-text-debounce-ids))))
(t/is (not (:skip-component-sync? (batch-opts state)))))))))
(t/deftest derived-only-batch-keeps-the-flag
(t/async
done
(let [file (setup-file)
store (ths/setup-store file)
text-1 (cths/get-shape file :text-1)
text-2 (cths/get-shape file :text-2)
events [(dwwt/resize-wasm-text-debounce (:id text-1) {:skip-component-sync? true})
(dwwt/resize-wasm-text-debounce (:id text-2) {:skip-component-sync? true})]]
(ths/run-store
store done events
(fn [state]
(t/is (true? (:skip-component-sync? (batch-opts state)))))))))

View File

@ -63,6 +63,7 @@
[frontend-tests.plugins.value-objects-test]
[frontend-tests.render-dimensions-test]
[frontend-tests.render-wasm.process-objects-test]
[frontend-tests.render-wasm.resize-debounce-opts-test]
[frontend-tests.render-wasm.text-editor-apply-styles-test]
[frontend-tests.render-wasm.text-editor-caret-color-test]
[frontend-tests.svg-fills-test]
@ -167,6 +168,7 @@
'frontend-tests.plugins.utils-test
'frontend-tests.plugins.value-objects-test
'frontend-tests.render-wasm.process-objects-test
'frontend-tests.render-wasm.resize-debounce-opts-test
'frontend-tests.render-wasm.text-editor-apply-styles-test
'frontend-tests.render-wasm.text-editor-caret-color-test
'frontend-tests.svg-fills-test