penpot/frontend
alonso.torres 98ae356fac ♻️ Simplify the component sync walk and its changes
- The sync walk took its direction as a map of seven closures
  (direct-sync, inverse-sync). The two directions are fixed, so each
  is now a plain recursive function: sync-copy-recursive (main to
  copy, a sync or a reset) and update-main-recursive (copy to main),
  with sync-copy-shape and update-main-shape for the pair itself.
  Both share compare-children, which takes the children, a pair?
  predicate and four callbacks instead of 13 arguments; the inverse
  branch's call of the swapped callback, which could never run, goes.
- The container of the main shapes is found once, at the start of the
  walk. The walk holds the :remote-synced a reset or an update main
  gives the copy shapes, instead of initial-root? and two branches.
  add-shape-to-instance and add-shape-to-main take the parent from the
  pair being walked instead of searching the whole subtree for it.
- pcb/add-changes takes a container and the redo and undo changes, and
  applies them locally. Eight sync functions and the library
  typography sync each wrote that block; make-change goes from both
  namespaces. One list holds the attributes that link a copy shape
  with its main, and one shape-label prints shapes in the log lines.
- change-touched chose what to write from three flags. It is now
  set-touched, which takes the value each caller computes. The swap's
  restore of the kept properties passes ignore-touched instead of
  calling it afterwards to put the groups back.
- generate-sync-shape was a multimethod over the three asset types; it
  is a case in generate-sync-container. generate-sync-file loses its
  unused arity. The 100-line comment that opened the sync helpers
  described an older model; a short note points at the component sync
  contract. text-content-with-overrides only called
  txt/merge-overrides, which sync and switch now call.
- update-flex-child-copy-attrs and update-flex-child-main-attrs are one
  function, update-flex-children, and the omit-touched? argument that
  was always false goes.
- In the variant switch, sized-geometry-value builds the resized
  :selrect and :points that two geometry policies each built, and a
  binding of skip? shadowed by a second one is skip-attr?.

add-shape-to-main keeps two changes that look wrong, now marked F102:
its :reg-objects names the component, so it only reaches a deleted
component's objects, and the undo of its new shapes deletes them from
the copy's page.

No behavior change: the golden masters and the suites are unchanged.
libraries.cljc: 1816 -> 1284 lines.

Benchmark (lower quantile, ms; baseline / now / ratio):
  deepest-edit-through-three-levels    35.2 /  15.2 / 0.43
  edit-through-a-chain-of-dependents   68.9 /  35.7 / 0.52
  library-update-into-copies           83.1 /  40.5 / 0.49
  main-edit-among-many-shapes           4.8 /   2.4 / 0.51
  main-edit-into-10-copies              1.8 /   0.8 / 0.46
  main-edit-into-100-copies            15.4 /   7.8 / 0.51
  main-edit-into-1000-copies          153.1 /  97.4 / 0.64
  variant-switch-into-copies           32.1 /  17.6 / 0.55
(The machine was busy for the 1000-copies world: its mean was 119 ms,
against about 83 in the runs of the earlier steps, at 0.49-0.52.)

AI-assisted-by: claude-opus-5-5

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 00:35:54 +02:00
..
2026-10-13 19:59:34 +02:00
2026-10-06 15:12:15 +02:00
2026-09-29 09:07:34 +02:00
2026-10-07 10:41:29 +02:00