mirror of
https://github.com/penpot/penpot.git
synced 2026-09-14 07:59:36 +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]}]
|
(rx/map (fn [{:keys [ids]}]
|
||||||
(dwwt/resize-wasm-text-all 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
|
(let [local-commits-s
|
||||||
(->> stream
|
(->> stream
|
||||||
(rx/filter dch/commit?)
|
(rx/filter dch/commit?)
|
||||||
|
|||||||
@ -1073,8 +1073,7 @@
|
|||||||
(dwsh/create-and-add-shape :text x y shape
|
(dwsh/create-and-add-shape :text x y shape
|
||||||
(when skip-edition? {:skip-edition? true})))
|
(when skip-edition? {:skip-edition? true})))
|
||||||
(if skip-edition?
|
(if skip-edition?
|
||||||
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-group id
|
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-id undo-id}))
|
||||||
:undo-id undo-id}))
|
|
||||||
(rx/of (dwu/commit-undo-transaction undo-id))))))))))
|
(rx/of (dwu/commit-undo-transaction undo-id))))))))))
|
||||||
|
|
||||||
(defn- paste-text
|
(defn- paste-text
|
||||||
@ -1105,8 +1104,7 @@
|
|||||||
(dwsh/create-and-add-shape :text x y shape
|
(dwsh/create-and-add-shape :text x y shape
|
||||||
(when skip-edition? {:skip-edition? true})))
|
(when skip-edition? {:skip-edition? true})))
|
||||||
(if skip-edition?
|
(if skip-edition?
|
||||||
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-group id
|
(rx/of (dwwt/resize-wasm-text-debounce id {:undo-id undo-id}))
|
||||||
:undo-id undo-id}))
|
|
||||||
(rx/of (dwu/commit-undo-transaction undo-id))))))))
|
(rx/of (dwu/commit-undo-transaction undo-id))))))))
|
||||||
|
|
||||||
;; TODO: why not implement it in terms of upload-media-workspace?
|
;; TODO: why not implement it in terms of upload-media-workspace?
|
||||||
|
|||||||
@ -1369,7 +1369,7 @@
|
|||||||
(rx/of update-event)
|
(rx/of update-event)
|
||||||
(if (features/active-feature? state "render-wasm/v1")
|
(if (features/active-feature? state "render-wasm/v1")
|
||||||
(->> (rx/from ids)
|
(->> (rx/from ids)
|
||||||
(rx/map #(dwwt/resize-wasm-text-debounce % {:undo-group undo-group})))
|
(rx/map #(dwwt/resize-wasm-text-debounce %)))
|
||||||
(rx/empty)))))))
|
(rx/empty)))))))
|
||||||
|
|
||||||
;; -- Text Editor v3
|
;; -- Text Editor v3
|
||||||
|
|||||||
@ -27,6 +27,34 @@
|
|||||||
|
|
||||||
(def debounce-resize-text-time 40)
|
(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
|
(defn get-wasm-text-new-size
|
||||||
"Computes the new {width, height} for a text shape from WASM text layout.
|
"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)."
|
For :fixed grow-type, updates WASM content and returns current dimensions (no resize)."
|
||||||
@ -95,8 +123,8 @@
|
|||||||
|
|
||||||
(defn resize-wasm-text-debounce-commit
|
(defn resize-wasm-text-debounce-commit
|
||||||
([]
|
([]
|
||||||
(resize-wasm-text-debounce-commit nil nil))
|
(resize-wasm-text-debounce-commit nil))
|
||||||
([undo-group undo-id]
|
([undo-id]
|
||||||
(ptk/reify ::resize-wasm-text-debounce-commit
|
(ptk/reify ::resize-wasm-text-debounce-commit
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
@ -115,12 +143,14 @@
|
|||||||
{}
|
{}
|
||||||
ids)
|
ids)
|
||||||
|
|
||||||
;; When undo-id is present, extend the current undo transaction instead of
|
;; The re-measure only syncs the shape's selrect with the WASM text
|
||||||
;; creating a new one, and commit it after the resize (single undo action).
|
;; 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)
|
extend-tx? (some? undo-id)
|
||||||
apply-opts (cond-> {}
|
apply-opts {:save-undo? false :undo-transation? false}]
|
||||||
(some? undo-group) (assoc :undo-group undo-group)
|
|
||||||
extend-tx? (assoc :undo-transation? false))]
|
|
||||||
(cond
|
(cond
|
||||||
(not (empty? modifiers))
|
(not (empty? modifiers))
|
||||||
(if extend-tx?
|
(if extend-tx?
|
||||||
@ -130,7 +160,8 @@
|
|||||||
(rx/of (dwm/apply-wasm-modifiers modifiers apply-opts)))
|
(rx/of (dwm/apply-wasm-modifiers modifiers apply-opts)))
|
||||||
|
|
||||||
extend-tx?
|
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))
|
(rx/of (dwu/commit-undo-transaction undo-id))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
@ -143,7 +174,7 @@
|
|||||||
(defn resize-wasm-text-debounce-inner
|
(defn resize-wasm-text-debounce-inner
|
||||||
([id]
|
([id]
|
||||||
(resize-wasm-text-debounce-inner id nil))
|
(resize-wasm-text-debounce-inner id nil))
|
||||||
([id {:keys [undo-group undo-id]}]
|
([id {:keys [undo-id]}]
|
||||||
(let [cur-event (js/Symbol)
|
(let [cur-event (js/Symbol)
|
||||||
reflow-task (wrf/task :text-resize [id])]
|
reflow-task (wrf/task :text-resize [id])]
|
||||||
(ptk/reify ::resize-wasm-text-debounce-inner
|
(ptk/reify ::resize-wasm-text-debounce-inner
|
||||||
@ -168,12 +199,11 @@
|
|||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/map (fn [evt]
|
(rx/map (fn [evt]
|
||||||
(resize-wasm-text-debounce-commit
|
(resize-wasm-text-debounce-commit
|
||||||
(some-> evt meta :undo-group)
|
|
||||||
(some-> evt meta :undo-id))))
|
(some-> evt meta :undo-id))))
|
||||||
(rx/take-until stopper))
|
(rx/take-until stopper))
|
||||||
(rx/of (with-meta
|
(rx/of (with-meta
|
||||||
(resize-wasm-text-debounce-inner id)
|
(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
|
;; Cleanup, reached both after the commit and when the stopper
|
||||||
;; cancels the debounce, so the batch always drains and stays
|
;; cancels the debounce, so the batch always drains and stays
|
||||||
;; pending until the resize is applied. All exact tasks in the
|
;; pending until the resize is applied. All exact tasks in the
|
||||||
@ -189,7 +219,7 @@
|
|||||||
(defn resize-wasm-text-debounce
|
(defn resize-wasm-text-debounce
|
||||||
([id]
|
([id]
|
||||||
(resize-wasm-text-debounce id nil))
|
(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/reify ::resize-wasm-text-debounce
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
@ -207,10 +237,8 @@
|
|||||||
|
|
||||||
resize-wasm-stream
|
resize-wasm-stream
|
||||||
(if fonts-loaded?
|
(if fonts-loaded?
|
||||||
(let [pass-opts (when (or (some? undo-group) (some? undo-id))
|
(let [pass-opts (when (some? undo-id)
|
||||||
(cond-> {}
|
{:undo-id undo-id})]
|
||||||
(some? undo-group) (assoc :undo-group undo-group)
|
|
||||||
(some? undo-id) (assoc :undo-id undo-id)))]
|
|
||||||
(rx/of (resize-wasm-text-debounce-inner id pass-opts)))
|
(rx/of (resize-wasm-text-debounce-inner id pass-opts)))
|
||||||
|
|
||||||
;; Fonts not loaded; retry after 20 msecs
|
;; Fonts not loaded; retry after 20 msecs
|
||||||
@ -223,12 +251,19 @@
|
|||||||
(wrf/with-pending :text-resize [id] resize-wasm-stream))))))
|
(wrf/with-pending :text-resize [id] resize-wasm-stream))))))
|
||||||
|
|
||||||
(defn resize-wasm-text-all
|
(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]
|
[ids]
|
||||||
(ptk/reify ::resize-wasm-text-all
|
(ptk/reify ::resize-wasm-text-all
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [resize-stream
|
(let [editing (get-in state [:workspace-local :edition])
|
||||||
|
ids (remove #(= % editing) ids)
|
||||||
|
resize-stream
|
||||||
(->> (rx/from ids)
|
(->> (rx/from ids)
|
||||||
(rx/map resize-wasm-text-debounce))]
|
(rx/map resize-wasm-text-debounce))]
|
||||||
(if (::dwsh/update-shapes-buffer state)
|
(if (::dwsh/update-shapes-buffer state)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user