From 92bcc0e6355485dcd468722e5cd2312158d86475 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 9 Oct 2026 13:56:39 +0200 Subject: [PATCH] :bug: Show live text size in Design tab while editing (#12250) Auto-grow text geometry is finalize-only to avoid typing lag, so the Design tab kept the committed selrect (0.01 for new texts) until Esc. Patch display W/H from live WASM layout while editing, matching the viewport outline, without restoring per-keystroke modifiers. Closes #12244 --- .../src/app/main/data/workspace/texts.cljs | 34 ++++++++++++++ .../shapes/text/text_edition_outline.cljs | 14 +++--- .../sidebar/options/shapes/text.cljs | 15 ++++++- .../data/workspace_texts_test.cljs | 45 +++++++++++++++++++ 4 files changed, 98 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 4ddaf0eded..1eb94ca1c0 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -900,6 +900,40 @@ new-shape) shape)) +(defn merge-live-text-dimensions + "Pick displayed width/height while editing auto-grow text. + + Geometry commits are finalize-only (see `v2-update-text-shape-content`), so the + Design tab and edition outline read live WASM layout for growing axes: + - `:auto-width` → live width and height + - `:auto-height` → selrect width, live height + - `:fixed` → selrect for both + + Nil or non-positive live axes fall back to the committed selrect so a missing + WASM measure never flashes `0`." + [grow-type {:keys [width height]} live] + (let [lw (when (map? live) (:width live)) + lh (when (map? live) (:height live))] + {:width (if (and (= grow-type :auto-width) (number? lw) (pos? lw)) lw width) + :height (if (and (not= grow-type :fixed) (number? lh) (pos? lh)) lh height)})) + +(defn shape-with-live-text-dimensions + "Display-only patch of shape selrect (and :width/:height) from live WASM text + layout. Does not write to the store. Returns `shape` unchanged when WASM is + unavailable or dimensions do not change." + [shape] + (let [selrect (:selrect shape) + live (when (wasm.api/initialized?) + (wasm.api/get-text-dimensions (:id shape))) + {:keys [width height]} (merge-live-text-dimensions (:grow-type shape) selrect live)] + (if (and (mth/close? width (:width selrect)) + (mth/close? height (:height selrect))) + shape + (-> shape + (assoc :selrect (grc/make-rect (:x selrect) (:y selrect) width height)) + (cond-> (contains? shape :width) (assoc :width width)) + (cond-> (contains? shape :height) (assoc :height height)))))) + (defn commit-update-text-modifier [] (ptk/reify ::commit-update-text-modifier diff --git a/frontend/src/app/main/ui/workspace/shapes/text/text_edition_outline.cljs b/frontend/src/app/main/ui/workspace/shapes/text/text_edition_outline.cljs index 93e7562438..43d2b492d0 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/text_edition_outline.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/text_edition_outline.cljs @@ -22,17 +22,15 @@ [selrect transform] (dsh/get-selrect selrect-transform shape) ;; While editing, the committed selrect lags the text (geometry is - ;; finalize-only), so measure the live WASM text for the growing axes: - ;; width grows on auto-width, height on auto-width/auto-height. - grow-type (:grow-type shape) - {live-width :width live-height :height} (wasm.api/get-text-dimensions (:id shape)) - sr-width (if (= grow-type :auto-width) live-width (:width selrect)) - sr-height (if (= grow-type :fixed) (:height selrect) live-height)] + ;; finalize-only), so measure the live WASM text for the growing axes. + live (wasm.api/get-text-dimensions (:id shape)) + {:keys [width height]} (dwt/merge-live-text-dimensions + (:grow-type shape) selrect live)] [:rect.main.viewport-selrect {:x (:x selrect) :y (:y selrect) - :width sr-width - :height sr-height + :width width + :height height :transform transform :style {:stroke "var(--color-accent-tertiary)" :stroke-width (/ 1 zoom) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs index 3158f59be2..dd2c9dc102 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs @@ -31,8 +31,19 @@ (mf/defc options* [{:keys [shape libraries file-id page-id]}] - (let [id (dm/get-prop shape :id) - type (dm/get-prop shape :type) + (let [id (dm/get-prop shape :id) + type (dm/get-prop shape :type) + edition (mf/deref refs/selected-edition) + ;; While editing auto-grow text, committed selrect lags (finalize-only + ;; geometry). Patch display size from live WASM so Design W/H match the + ;; viewport outline without writing to the store. + shape + (cond-> shape + (and (= id edition) + (not= :fixed (:grow-type shape)) + (features/active-feature? @st/state "render-wasm/v1")) + (dwt/shape-with-live-text-dimensions)) + ids (mf/with-memo [id] [id]) shapes (mf/with-memo [shape] [shape]) diff --git a/frontend/test/frontend_tests/data/workspace_texts_test.cljs b/frontend/test/frontend_tests/data/workspace_texts_test.cljs index 14eef12d50..9fe41428e7 100644 --- a/frontend/test/frontend_tests/data/workspace_texts_test.cljs +++ b/frontend/test/frontend_tests/data/workspace_texts_test.cljs @@ -581,3 +581,48 @@ (t/testing "a non-root content (e.g. paragraph) is left alone" (let [node {:type "paragraph" :children []}] (t/is (= node (dwt/ensure-valid-text-content node)))))) + +;; --------------------------------------------------------------------------- +;; Tests: merge-live-text-dimensions (Design tab / edition outline) +;; --------------------------------------------------------------------------- + +(t/deftest merge-live-text-dimensions-auto-width-uses-live-axes + (t/testing "auto-width takes live width and height" + (let [selrect {:width 0.01 :height 0.01} + live {:width 70 :height 17} + result (dwt/merge-live-text-dimensions :auto-width selrect live)] + (t/is (= 70 (:width result))) + (t/is (= 17 (:height result)))))) + +(t/deftest merge-live-text-dimensions-auto-height-keeps-width + (t/testing "auto-height keeps selrect width and takes live height" + (let [selrect {:width 300 :height 40} + live {:width 120 :height 80} + result (dwt/merge-live-text-dimensions :auto-height selrect live)] + (t/is (= 300 (:width result))) + (t/is (= 80 (:height result)))))) + +(t/deftest merge-live-text-dimensions-fixed-keeps-selrect + (t/testing "fixed keeps both selrect axes" + (let [selrect {:width 300 :height 60} + live {:width 90 :height 20} + result (dwt/merge-live-text-dimensions :fixed selrect live)] + (t/is (= 300 (:width result))) + (t/is (= 60 (:height result)))))) + +(t/deftest merge-live-text-dimensions-nil-live-falls-back + (t/testing "nil live map falls back to selrect" + (let [selrect {:width 50 :height 25} + result (dwt/merge-live-text-dimensions :auto-width selrect nil)] + (t/is (= 50 (:width result))) + (t/is (= 25 (:height result))))) + (t/testing "nil live axes fall back per axis" + (let [selrect {:width 50 :height 25} + result (dwt/merge-live-text-dimensions :auto-width selrect {:width nil :height nil})] + (t/is (= 50 (:width result))) + (t/is (= 25 (:height result))))) + (t/testing "non-positive live axes do not wipe selrect" + (let [selrect {:width 50 :height 25} + result (dwt/merge-live-text-dimensions :auto-width selrect {:width 0 :height 0})] + (t/is (= 50 (:width result))) + (t/is (= 25 (:height result))))))