This commit is contained in:
Pablo Alba 2026-05-13 13:31:16 +02:00
parent 1e746add31
commit 7adffc473d
5 changed files with 699 additions and 597 deletions

View File

@ -0,0 +1,5 @@
[-1358936ms] [INFO] Autofocus processing was blocked because a document already has a focused element. @ devtools://devtools/bundled/devtools_app.html?remoteBase=https://chrome-devtools-frontend.appspot.com/serve_file/@8625e066febc721e015ea99842da12901eb7ed73/&targetType=tab&can_dock=true:0
[-1358953ms] [TIMEEND] Main._createAppUI: 218.40185546875 ms @ devtools://devtools/bundled/entrypoints/main/main.js:10
[-1358877ms] [TIMEEND] Main._showAppUI: 75.088134765625 ms @ devtools://devtools/bundled/entrypoints/main/main.js:10
[-1358543ms] [TIMEEND] Main._initializeTarget: 333.44091796875 ms @ devtools://devtools/bundled/entrypoints/main/main.js:10
[-1358443ms] [TIMEEND] Main._lateInitialization: 0.358154296875 ms @ devtools://devtools/bundled/entrypoints/main/main.js:10

View File

@ -24,6 +24,7 @@
- Fix lost-update race on `team.features` during concurrent file creation (by @web-dev0521) [Github #9197](https://github.com/penpot/penpot/issues/9197)
- Fix copy and paste actions crashing the workspace on insecure origins (plain HTTP / non-`localhost`) where the Clipboard API is unavailable (by @MilosM348) [Github #6514](https://github.com/penpot/penpot/issues/6514)
- Fix blend-mode dropdown leaving the canvas rendered with the last hover-preview blend mode when dismissed without selecting an option; the WASM render is now reverted to the saved blend mode on pointer-leave (by @edwin-rivera-dev) [Github #XXXX](https://github.com/penpot/penpot/issues/XXXX)
- Fix copy/paste of nested swapped component sub-instances persisting with a missing swap slot, causing the server to reject the change with a `:referential-integrity` validation error; when the clipboard advances a sub-instance head's `shape-ref` to the next reference level, the original `shape-ref` is now preserved as a swap slot
## 2.16.0 (Unreleased)

View File

@ -169,13 +169,28 @@
objects))
(advance-shape [file libraries page level-delta objects shape]
(let [new-shape-ref (ctf/advance-shape-ref file page libraries shape level-delta {:include-deleted? true})
container (ctn/make-container page :page)
new-touched (ctf/get-touched-from-ref-chain-until-target-ref container libraries shape new-shape-ref)]
(let [new-shape-ref (ctf/advance-shape-ref file page libraries shape level-delta {:include-deleted? true})
container (ctn/make-container page :page)
new-touched (ctf/get-touched-from-ref-chain-until-target-ref container libraries shape new-shape-ref)
old-shape-ref (:shape-ref shape)
ref-changed? (and (some? new-shape-ref) (not= new-shape-ref old-shape-ref))
;; If we advance the shape-ref of a subinstance head, the new
;; shape-ref will no longer match the parent component child
;; at the same position, so the shape becomes "swapped" with
;; respect to the enclosing instance. Preserve the original
;; shape-ref as swap-slot so that referential integrity holds
;; when the copy is pasted in a context where the parent's
;; near main is reachable.
needs-swap-slot? (and ref-changed?
(ctc/subinstance-head? shape)
(nil? (ctc/get-swap-slot shape)))]
(cond-> objects
(and (some? new-shape-ref) (not= new-shape-ref (:shape-ref shape)))
ref-changed?
(-> (assoc-in [(:id shape) :shape-ref] new-shape-ref)
(assoc-in [(:id shape) :touched] new-touched)))))
(assoc-in [(:id shape) :touched] new-touched))
needs-swap-slot?
(update (:id shape) ctc/set-swap-slot old-shape-ref))))
(on-copy-error [error]
(js/console.error "clipboard blocked:" error)

View File

@ -247,10 +247,21 @@
objects))
(advance-shape [file libraries page level-delta objects shape]
(let [new-shape-ref (ctf/advance-shape-ref file page libraries shape level-delta {:include-deleted? true})]
(let [new-shape-ref (ctf/advance-shape-ref file page libraries shape level-delta {:include-deleted? true})
container (ctn/make-container page :page)
new-touched (ctf/get-touched-from-ref-chain-until-target-ref container libraries shape new-shape-ref)
old-shape-ref (:shape-ref shape)
ref-changed? (and (some? new-shape-ref) (not= new-shape-ref old-shape-ref))
needs-swap-slot? (and ref-changed?
(ctk/subinstance-head? shape)
(nil? (ctk/get-swap-slot shape)))]
(cond-> objects
(and (some? new-shape-ref) (not= new-shape-ref (:shape-ref shape)))
(assoc-in [(:id shape) :shape-ref] new-shape-ref))))]
ref-changed?
(-> (assoc-in [(:id shape) :shape-ref] new-shape-ref)
(assoc-in [(:id shape) :touched] new-touched))
needs-swap-slot?
(update (:id shape) ctk/set-swap-slot old-shape-ref))))]
(let [file-id (:id file)
frame-id (cfh/common-parent-frame objects selected)