Skip to content

[Image Resizer] Automatically reload settings changes#45266

Open
daverayment wants to merge 3 commits intomicrosoft:mainfrom
daverayment:feat/imageresizer-settings-sync
Open

[Image Resizer] Automatically reload settings changes#45266
daverayment wants to merge 3 commits intomicrosoft:mainfrom
daverayment:feat/imageresizer-settings-sync

Conversation

@daverayment
Copy link
Collaborator

@daverayment daverayment commented Feb 1, 2026

Summary of the Pull Request

This PR introduces real-time settings synchronisation for Image Resizer. External changes to settings.json (via the Settings application or manual edits to the file) are detected and reloaded immediately without requiring a restart.

PR Checklist

  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Reload updates

The reload detection is via an IFileSystemWatcher (as file system operations are abstracted in Image Resizer), which monitors the settings.json file for creation and changes. There is a half second debounce for changes, as the settings file can rapidly change when the user is editing the preset name field.

Hot reloading of the properties required refactoring ReloadCore, which replaces the Sizes preset collection and updates the Custom and AI presets, in addition to the application-wide properties like compression options and the fallback encoder choice.

I changed the combo box data binding from the SelectedSize object to the int SelectedSizeIndex. This was required to resolve a specific WPF issue where reloading the Sizes collection would cause issues with restoring the current combo box selection to the prior value. Binding to the index decouples the selection state from the object lifecycle during the reload process.

Selection preservation is based on the preset ID (for user presets) and preset type (for Custom and AI presets). This ensures that matches are robust even if the user is in the process of renaming an entry in the Settings application. If the preset cannot be matched (for example, if the user deletes the item or changes the ID manually in the file), the Custom preset is selected.

Selection range checks are maintained from the old code, and additional checks have been added to ensure that Custom and AI presets will be present even if they're deleted from the settings file.

The AI preset check from before has been inlined; this guarantees that the AI resize option will not display if the facility is unavailable on the current PC, even if it's present in the settings file.

The reload routine is dispatched to the UI thread, as changes involve updates to the combo box.

ID recovery

Preset IDs are key to preserving the combo box selection between reloads, and a couple of changes were necessary to ensure round-tripping changes were robust.

  1. IDs are not reused. The old code could reuse IDs under certain circumstances, for example if a preset was deleted and re-added via Settings.
  2. The ID Recovery Helper routine sorted the supplied presets by ID before performing duplicate conflict resolution. This is not required and it is more natural to assume that the order in the settings file and the client UI is the source of truth.

New ID assignment is now based on a monotonically increasing ID (seeded at application start) rather than Current Maximum ID + 1. This means that IDs cannot be reused in the same Settings application session. This makes the matching process in the client application more reliable.

A small update was made to the ID Recovery Helper to use HashSet.Add() instead of splitting up the check and addition steps (Add will return false if the value already exists), which saves a massive one line of code.

There were comments about the ID Recovery Helper resolving "empty" or "invalid" entries; this was inaccurate, as IDs are ints, which must by definition always have a valid value. The routine only guards against duplicates, so the comments have been updated to reflect this.

Miscellaneous

The Default Settings property getter previously called Reload every time it was accessed. This is fine when the file is only read at application startup, but I changed this to lazily instantiate and call Reload a single time.

I refactored duplicate code related to settings file/folder strings, and also the creation of the Custom and AI size instances.

Validation Steps Performed

Manual testing:

  1. Add new preset in the Settings application. The new entry is reflected in the client application as it is running.
  2. Delete new preset. The entry is removed in the client application list.
  3. Edit an existing preset. The property change is reflected in the client application.
  4. Add new preset in the Settings application. Select the new preset in the client application. Edit the properties of the new preset in the Settings application and confirm that the updates appear in the client application.
  5. Add new preset in the Settings application. Select the new preset in the client application. Delete the new preset in Settings. Confirm that the current preset is removed and the selection changes to the default in the client application.
  6. Change one or more application-wide properties in the settings file which are represented in the client application, too, e.g. "Make pictures smaller but not larger" (imageresizer_shrinkOnly) or "Overwrite files" (imageresizer_replace). Upon saving, confirm the checkbox changes immediately in the client application.
  7. Edit the settings.json file manually by e.g. adding a new Size preset or editing the width or height property of an existing preset. Upon saving, the change(s) should be reflected in the client application.
  8. Make a change to an existing or new preset which affects the resize operation itself, e.g. the dimensions or the "Make pictures smaller but not larger" setting. Proceed with the resize operation and confirm that the new changes have been applied.

14 new unit tests have been added to SetingsTests.cs to exercise the Settings and IDRecoveryHelper functionality.

…ion or manual user-edits of the settings.json file). Update and simplify IdRecoveryHelper. Add unit tests to exercise updated settings code and IdRecoveryHelper.
@daverayment daverayment added the Product-Image Resizer Things regarding image resizing module label Feb 1, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link

github-actions bot commented Feb 1, 2026

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

Unrecognized words (4)

Gotchas
Metacharacter
registryroot
regroot

These words are not needed and should be removed gotcha ROOTOWNER

Some files were automatically ignored 🙈

These sample patterns would exclude them:

^src/modules/powerrename/unittests/testdata/avif_test\.avif$
^src/modules/powerrename/unittests/testdata/heif_test\.heic$

You should consider adding them to:

.github/actions/spell-check/excludes.txt

File matching is via Perl regular expressions.

To check these files, more of their words need to be in the dictionary than not. You can use patterns.txt to exclude portions, add items to the dictionary (e.g. by adding them to allow.txt), or fix typos.

To accept these unrecognized words as correct, update file exclusions, and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:daverayment/PowerToys.git repository
on the feat/imageresizer-settings-sync branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/c635c2f3f714eec2fcf27b643a1919b9a811ef2e/apply.pl' |
perl - 'https://github.com/microsoft/PowerToys/actions/runs/21559588762/attempts/1' &&
git commit -m 'Update check-spelling metadata'
Warnings ⚠️ (2)

See the 📂 files view, the 📜action log, or 📝 job summary for details.

⚠️ Warnings Count
⚠️ ignored-expect-variant 2
⚠️ large-file 2

See ⚠️ Event descriptions for more information.

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-Image Resizer Things regarding image resizing module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ImageResizer] Pick up settings changes automatically

1 participant