mirror of
https://github.com/penpot/penpot.git
synced 2026-05-19 14:14:05 -04:00
🐛 Fix update library dialog when a component position changes
Do not show the library sync popup when the only differences are global x/y changes on library components. We now generate the actual sync changes and only notify if there are real redo-changes to apply. Run cll/generate-sync-file-changes for candidate libraries and filter out those with empty :redo-changes. The expensive check is deferred via rx/timer 0 so it runs asynchronously and does not block the UI. Why: Position-only changes are normalized during sync (via reposition-shape) and never propagate to copies; showing the popup in that case was a false positive. Performance: The check is deferred to the next tick to avoid UI stutter on large files with many libraries.
This commit is contained in:
@@ -26,6 +26,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 update library dialog when a component position changes [Taiga #11981](https://tree.taiga.io/project/penpot/issue/11981)
|
||||
|
||||
## 2.16.0 (Unreleased)
|
||||
|
||||
|
||||
@@ -1281,38 +1281,61 @@
|
||||
file (dsh/lookup-file state file-id)
|
||||
file-data (get file :data)
|
||||
ignore-until (get file :ignore-sync-until)
|
||||
permissions (:permissions state)
|
||||
permissions (:permissions state)
|
||||
|
||||
libraries-need-sync
|
||||
(->> (vals (get state :files))
|
||||
(filter #(= (:library-of %) file-id))
|
||||
(filter #(seq (assets-need-sync % file-data ignore-until))))
|
||||
(filter #(seq (assets-need-sync % file-data ignore-until))))]
|
||||
|
||||
do-more-info
|
||||
#(modal/show! :libraries-dialog {:starting-tab "updates" :file-id file-id})
|
||||
(if-not (and (:can-edit permissions)
|
||||
(seq libraries-need-sync))
|
||||
;; Fast path: no libraries need sync based on timestamps
|
||||
(rx/empty)
|
||||
|
||||
do-update
|
||||
#(do (apply st/emit! (map (fn [library]
|
||||
(sync-file (:current-file-id state)
|
||||
(:id library)))
|
||||
libraries-need-sync))
|
||||
(st/emit! (ntf/hide)))
|
||||
;; Defer the expensive change generation check to avoid blocking the UI.
|
||||
;; For files with many libraries, this prevents stuttering/freezing.
|
||||
(->> (rx/timer 0)
|
||||
(rx/map (fn [_]
|
||||
;; This runs asynchronously on the next tick.
|
||||
;; Filter libraries to only those that would produce actual sync changes.
|
||||
(let [libraries (dsh/lookup-libraries state)]
|
||||
(filter (fn [library]
|
||||
(seq (:redo-changes
|
||||
(cll/generate-sync-file-changes
|
||||
(pcb/empty-changes)
|
||||
nil
|
||||
nil
|
||||
file-id
|
||||
nil
|
||||
(:id library)
|
||||
libraries
|
||||
file-id))))
|
||||
libraries-need-sync))))
|
||||
(rx/filter seq)
|
||||
(rx/map (fn [libraries-with-changes]
|
||||
(let [do-more-info
|
||||
#(modal/show! :libraries-dialog {:starting-tab "updates" :file-id file-id})
|
||||
|
||||
do-dismiss
|
||||
#(st/emit! ignore-sync (ntf/hide))]
|
||||
do-update
|
||||
#(do (apply st/emit! (map (fn [library]
|
||||
(sync-file file-id (:id library)))
|
||||
libraries-with-changes))
|
||||
(st/emit! (ntf/hide)))
|
||||
|
||||
(when (and (:can-edit permissions)
|
||||
(seq libraries-need-sync))
|
||||
(rx/of (ntf/dialog
|
||||
:content (tr "workspace.updates.there-are-updates")
|
||||
:controls :inline-actions
|
||||
:links [{:label (tr "workspace.updates.more-info")
|
||||
:callback do-more-info}]
|
||||
:cancel {:label (tr "workspace.updates.dismiss")
|
||||
:callback do-dismiss}
|
||||
:accept {:label (tr "workspace.updates.update")
|
||||
:callback do-update}
|
||||
:tag :sync-dialog)))))))
|
||||
do-dismiss
|
||||
#(st/emit! ignore-sync (ntf/hide))]
|
||||
|
||||
(ntf/dialog
|
||||
:content (tr "workspace.updates.there-are-updates")
|
||||
:controls :inline-actions
|
||||
:links [{:label (tr "workspace.updates.more-info")
|
||||
:callback do-more-info}]
|
||||
:cancel {:label (tr "workspace.updates.dismiss")
|
||||
:callback do-dismiss}
|
||||
:accept {:label (tr "workspace.updates.update")
|
||||
:callback do-update}
|
||||
:tag :sync-dialog))))))))))
|
||||
|
||||
(defn touch-component
|
||||
"Update the modified-at attribute of the component to now"
|
||||
|
||||
Reference in New Issue
Block a user