Files
photocraft/apps
Hector VillarrealandClaude Opus 5.5 284f569264 fix(engine): defined and imported patterns survive a restart (#9317) (#9318)
* fix(engine): defined and imported patterns survive a restart (#9317)

The pattern library lived only in memory: patterns defined with Edit >
Define Pattern or imported from a .pat file were gone after a restart,
while their Patterns panel folders (saved with the preferences) still
named them. Photoshop keeps them.

The preset store now writes the user patterns (the library minus the
built-ins, in order) to patterns.pat, Photoshop's own pattern file
format, whenever their ids, names, sizes or order change, and loads
them when the store attaches. Like actions.json, a file that fails to
load is warned about and never overwritten. The web store accepts the
new record.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Patterns: persist same-id pixel replacements, retry a failed removal

CodeRabbit (discussion_r4369506324, r4369506326):
- an imported .pat whose id is already in the library replaces its
  pixels, which the id/name/size key didn't show, so the old pixels came
  back after a restart; PatternLibrary::pixels_rev is bumped on such a
  replacement and is part of the key;
- a failed patterns.pat removal recorded the empty library as saved and
  was never retried, so the deleted pattern came back; it now stays
  pending, as a failed write does.

Tests: a_same_id_pattern_replacement_survives_a_restart,
a_failed_patterns_removal_is_retried.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Patterns: persist replaced built-ins and ASL replacements

CodeRabbit (discussion_r4369536978, r4369536981):
- a .pat import that replaced a built-in pattern by id was filtered out
  as a built-in and never saved; only built-ins exactly as shipped
  (is_pristine_builtin) are skipped now, and on load a saved built-in
  takes the shipped one's place unless it changed before attachment;
- style.presets.importAsl replaced patterns by id without bumping
  pixels_rev; both imports now go through PatternLibrary::upsert.

Tests: an_imported_builtin_replacement_survives_a_restart,
an_asl_pattern_replacement_bumps_pixels_rev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* .pat: refuse names and counts the reader won't load, on write too

CodeRabbit (review 5641404908, outside-diff, two findings): now that the
preset store writes the user patterns, a file its own loader rejects or
truncates loses patterns at the next start.
- a name of 65,536+ UTF-16 units (with its NUL) was written although the
  reader refuses it; write_pattern refuses it now;
- more than 100,000 patterns were written, and the reader kept the first
  100,000 without a word; both now refuse counts over MAX_PAT_PATTERNS.

Tests: a_name_the_reader_refuses_is_refused_on_write,
more_patterns_than_a_pat_file_holds_are_refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Patterns: an early same-id import with other pixels is saved

CodeRabbit (review 5641454449, outside-diff, preset_store.rs:1191-1202):
a pattern imported before the store finished loading, with the id, name
and size of a saved one but other pixels, was appended (no pixels_rev
bump), won the merge, and then matched the loaded file's key, so it was
never written and a restart brought the old pixels back. The merge now
bumps pixels_rev when the copy it keeps differs from the saved one.

Test: an_early_same_id_import_wins_and_is_saved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 10:18:23 -04:00
..