mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 21:38:48 +00:00
✨ Centralize calls to re-measure selrects at the commit level
This commit is contained in:
parent
704cd40182
commit
04c397477f
@ -452,6 +452,25 @@
|
||||
(rx/map (fn [{:keys [ids]}]
|
||||
(dwwt/resize-wasm-text-all ids))))
|
||||
|
||||
;; Re-measure WASM text shapes whose layout-relevant attributes
|
||||
;; changed in a local commit. Centralizing this at the commit
|
||||
;; chokepoint keeps every mutation path (clipboard, libraries,
|
||||
;; plugins, undo/redo…) in sync without each call site having to
|
||||
;; remember to dispatch a resize. Undo/redo replay as commits too,
|
||||
;; so the geometry stays consistent through them (the re-measure
|
||||
;; itself is non-undoable, see `resize-wasm-text-debounce-commit`).
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
(rx/filter render-wasm-ready?)
|
||||
(rx/map deref)
|
||||
(rx/filter #(= :local (:source %)))
|
||||
(rx/mapcat
|
||||
(fn [{:keys [redo-changes]}]
|
||||
(let [ids (dwwt/commit-text-remeasure-ids redo-changes)]
|
||||
(if (seq ids)
|
||||
(rx/of (dwwt/resize-wasm-text-all ids))
|
||||
(rx/empty))))))
|
||||
|
||||
(let [local-commits-s
|
||||
(->> stream
|
||||
(rx/filter dch/commit?)
|
||||
|
||||
@ -1073,8 +1073,7 @@
|
||||
(dwsh/create-and-add-shape :text x y shape
|
||||
(when skip-edition? {:skip-edition? true})))
|
||||
(if skip-edition?
|
||||
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-group id
|
||||
:undo-id undo-id}))
|
||||
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-id undo-id}))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id))))))))))
|
||||
|
||||
(defn- paste-text
|
||||
@ -1105,8 +1104,7 @@
|
||||
(dwsh/create-and-add-shape :text x y shape
|
||||
(when skip-edition? {:skip-edition? true})))
|
||||
(if skip-edition?
|
||||
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-group id
|
||||
:undo-id undo-id}))
|
||||
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-id undo-id}))
|
||||
(rx/of (dwu/commit-undo-transaction undo-id))))))))
|
||||
|
||||
;; TODO: why not implement it in terms of upload-media-workspace?
|
||||
|
||||
@ -1369,7 +1369,7 @@
|
||||
(rx/of update-event)
|
||||
(if (features/active-feature? state "render-wasm/v1")
|
||||
(->> (rx/from ids)
|
||||
(rx/map #(dwwt/resize-wasm-text-debounce % {:undo-group undo-group})))
|
||||
(rx/map #(dwwt/resize-wasm-text-debounce %)))
|
||||
(rx/empty)))))))
|
||||
|
||||
;; -- Text Editor v3
|
||||
|
||||
@ -27,6 +27,34 @@
|
||||
|
||||
(def debounce-resize-text-time 40)
|
||||
|
||||
;; Attributes whose change invalidates the WASM-measured selrect of a text
|
||||
;; shape, i.e. its geometry must be re-derived from the WASM text layout.
|
||||
(def ^:private text-remeasure-attr? #{:content :grow-type})
|
||||
|
||||
(defn commit-text-remeasure-ids
|
||||
"Ids of shapes in a commit's `redo-changes` whose selrect went stale and must
|
||||
be re-measured from the WASM text layout: a `:mod-obj` changed a
|
||||
layout-relevant attribute (see `text-remeasure-attr?`) without also carrying
|
||||
the resulting geometry.
|
||||
|
||||
The `:selrect` guard skips commits that already set the geometry themselves
|
||||
(text-editor finalize, interactive resize, the re-measure commit itself), so
|
||||
those neither trigger a redundant resize nor create a feedback loop.
|
||||
|
||||
Type filtering (text, non-`:fixed`) is left to `resize-wasm-text-all`."
|
||||
[redo-changes]
|
||||
(into #{}
|
||||
(comp
|
||||
(filter #(= :mod-obj (:type %)))
|
||||
(keep (fn [{:keys [id operations]}]
|
||||
(let [attrs (into #{}
|
||||
(comp (filter #(= :set (:type %))) (map :attr))
|
||||
operations)]
|
||||
(when (and (some text-remeasure-attr? attrs)
|
||||
(not (contains? attrs :selrect)))
|
||||
id)))))
|
||||
redo-changes))
|
||||
|
||||
(defn get-wasm-text-new-size
|
||||
"Computes the new {width, height} for a text shape from WASM text layout.
|
||||
For :fixed grow-type, updates WASM content and returns current dimensions (no resize)."
|
||||
@ -95,8 +123,8 @@
|
||||
|
||||
(defn resize-wasm-text-debounce-commit
|
||||
([]
|
||||
(resize-wasm-text-debounce-commit nil nil))
|
||||
([undo-group undo-id]
|
||||
(resize-wasm-text-debounce-commit nil))
|
||||
([undo-id]
|
||||
(ptk/reify ::resize-wasm-text-debounce-commit
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
@ -115,12 +143,14 @@
|
||||
{}
|
||||
ids)
|
||||
|
||||
;; When undo-id is present, extend the current undo transaction instead of
|
||||
;; creating a new one, and commit it after the resize (single undo action).
|
||||
;; The re-measure only syncs the shape's selrect with the WASM text
|
||||
;; layout; it is derived geometry, not a user action, so it must
|
||||
;; never land on the undo stack (an undo of it alone would
|
||||
;; re-expose the stale selrect). Undo/redo of the change that
|
||||
;; triggered it re-derives the geometry through the commit-level
|
||||
;; invalidation in `initialize-workspace`.
|
||||
extend-tx? (some? undo-id)
|
||||
apply-opts (cond-> {}
|
||||
(some? undo-group) (assoc :undo-group undo-group)
|
||||
extend-tx? (assoc :undo-transation? false))]
|
||||
apply-opts {:save-undo? false :undo-transation? false}]
|
||||
(cond
|
||||
(not (empty? modifiers))
|
||||
(if extend-tx?
|
||||
@ -130,7 +160,8 @@
|
||||
(rx/of (dwm/apply-wasm-modifiers modifiers apply-opts)))
|
||||
|
||||
extend-tx?
|
||||
;; No resize needed (e.g. :fixed grow-type) but we must commit the add
|
||||
;; No resize needed (e.g. :fixed grow-type) but we must still close
|
||||
;; the transaction opened by the caller (e.g. for the added shape).
|
||||
(rx/of (dwu/commit-undo-transaction undo-id))
|
||||
|
||||
:else
|
||||
@ -143,7 +174,7 @@
|
||||
(defn resize-wasm-text-debounce-inner
|
||||
([id]
|
||||
(resize-wasm-text-debounce-inner id nil))
|
||||
([id {:keys [undo-group undo-id]}]
|
||||
([id {:keys [undo-id]}]
|
||||
(let [cur-event (js/Symbol)
|
||||
reflow-task (wrf/task :text-resize [id])]
|
||||
(ptk/reify ::resize-wasm-text-debounce-inner
|
||||
@ -168,12 +199,11 @@
|
||||
(rx/take 1)
|
||||
(rx/map (fn [evt]
|
||||
(resize-wasm-text-debounce-commit
|
||||
(some-> evt meta :undo-group)
|
||||
(some-> evt meta :undo-id))))
|
||||
(rx/take-until stopper))
|
||||
(rx/of (with-meta
|
||||
(resize-wasm-text-debounce-inner id)
|
||||
{:undo-group undo-group :undo-id undo-id})))
|
||||
{:undo-id undo-id})))
|
||||
;; Cleanup, reached both after the commit and when the stopper
|
||||
;; cancels the debounce, so the batch always drains and stays
|
||||
;; pending until the resize is applied. All exact tasks in the
|
||||
@ -189,7 +219,7 @@
|
||||
(defn resize-wasm-text-debounce
|
||||
([id]
|
||||
(resize-wasm-text-debounce id nil))
|
||||
([id {:keys [undo-group undo-id] :as opts}]
|
||||
([id {:keys [undo-id] :as opts}]
|
||||
(ptk/reify ::resize-wasm-text-debounce
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
@ -207,10 +237,8 @@
|
||||
|
||||
resize-wasm-stream
|
||||
(if fonts-loaded?
|
||||
(let [pass-opts (when (or (some? undo-group) (some? undo-id))
|
||||
(cond-> {}
|
||||
(some? undo-group) (assoc :undo-group undo-group)
|
||||
(some? undo-id) (assoc :undo-id undo-id)))]
|
||||
(let [pass-opts (when (some? undo-id)
|
||||
{:undo-id undo-id})]
|
||||
(rx/of (resize-wasm-text-debounce-inner id pass-opts)))
|
||||
|
||||
;; Fonts not loaded; retry after 20 msecs
|
||||
@ -223,12 +251,19 @@
|
||||
(wrf/with-pending :text-resize [id] resize-wasm-stream))))))
|
||||
|
||||
(defn resize-wasm-text-all
|
||||
"Resize all text shapes (auto-width/auto-height) from a collection of ids."
|
||||
"Resize all text shapes (auto-width/auto-height) from a collection of ids.
|
||||
|
||||
The shape currently being edited is skipped: the text editor already renders
|
||||
and measures the growing text live and resizes it on finalize, so an
|
||||
automatic per-keystroke resize here would be redundant and reintroduce typing
|
||||
lag (see the guard in `app.main.data.workspace.texts`)."
|
||||
[ids]
|
||||
(ptk/reify ::resize-wasm-text-all
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [resize-stream
|
||||
(let [editing (get-in state [:workspace-local :edition])
|
||||
ids (remove #(= % editing) ids)
|
||||
resize-stream
|
||||
(->> (rx/from ids)
|
||||
(rx/map resize-wasm-text-debounce))]
|
||||
(if (::dwsh/update-shapes-buffer state)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user