Skip to content

DynamoDS/DYN-10515: As a Dynamo user, I want my graph to AutoSave#17117

Open
eamiri wants to merge 9 commits into
masterfrom
10515-autosave-graphs
Open

DynamoDS/DYN-10515: As a Dynamo user, I want my graph to AutoSave#17117
eamiri wants to merge 9 commits into
masterfrom
10515-autosave-graphs

Conversation

@eamiri
Copy link
Copy Markdown

@eamiri eamiri commented May 22, 2026

Closes https://jira.autodesk.com/browse/DYN-10515

h1. AutoSave Graphs Implementation Plan

h2. Overview

Add VSCode-style AutoSave to Dynamo: when a user edits a graph that has already been saved to disk, changes are automatically written back to the canonical file after a debounce delay (default 30 s of inactivity). The feature is opt-in via a toggle in Preferences > Backup settings. The existing backup mechanism continues to run unchanged alongside AutoSave.

h2. Current State Analysis

h3. Key Discoveries

  • {{private Timer backupFilesTimer}} declared at {{src/DynamoCore/Models/DynamoModel.cs:137}}, started at line 1043 in constructor — writes to a separate {{BackupDirectory}}, not the original file path
  • {{WorkspaceModel.HasUnsavedChanges}} at {{src/DynamoCore/Graph/Workspaces/WorkspaceModel.cs:1092}} raises {{PropertyChanged("HasUnsavedChanges")}} — the ideal AutoSave trigger point
  • {{WorkspaceModel.Save(string filePath, bool isBackup = false, EngineController engine = null)}} at line 1618 calls {{File.WriteAllText}} synchronously at line 1637; routed through {{DynamoViewModel.InternalSaveAs}} at line 2769 in the WPF layer
  • {{SaveContext}} enum at {{src/DynamoCore/Graph/ModelBase.cs:16}} currently has 7 values ({{File}} obsolete, {{Copy}}, {{Undo}}, {{Preset}}, {{None}}, {{Save}}, {{SaveAs}}) — {{AutoSave}} must be added so extension listeners (Watch3D, Python migration, WorkspaceDependency) can distinguish and skip expensive work
  • {{ActionDebouncer}} at {{src/DynamoCoreWpf/Utilities/ActionDebouncer.cs}} (internal, {{Dynamo.Wpf.Utilities}}) — constructor takes {{ILogger}}, exposes {{Debounce(int timeout, Action action)}}, {{Cancel()}}, implements {{IDisposable}}. Fires action on the UI thread via captured {{SynchronizationContext}}. Already used at {{WorkspaceViewModel.cs:597}} and {{SearchViewModel.cs:415}}
  • {{EnableNotificationCenter}} property at {{PreferenceSettings.cs:760-779}} → {{PreferencesViewModel.NotificationCenterIsChecked}} at lines 1103-1117 → {{ToggleButton}} in {{PreferencesView.xaml:919-924}} — the exact template to replicate
  • {{BackupInterval}}/{{BackupFilesCount}} exist only on the concrete {{PreferenceSettings}}, not on {{IPreferences}} (interface only has {{BackupFiles}} at line 114) — {{EnableAutoSave}} follows the same concrete-only pattern
  • {{DynamoViewModel.InternalSaveAs}} at line 2769 handles {{IOException}}/{{UnauthorizedAccessException}} with user-facing dialogs and calls {{AddToRecentFiles}} only for non-backup saves
  • {{DynamoViewModel.SaveAs(Guid id, string path, bool isBackup, SaveContext)}} at line 2861 — the correct entry point for programmatic saves by workspace GUID (same as backup)
  • {{WorkspaceModel.OnSaved()}} at line 428 sets {{HasUnsavedChanges = false}} and {{LastSaved = DateTime.Now}} after a successful save — clears the dirty flag automatically, preventing re-triggering

h2. Desired End State

  • A user who has previously saved a graph can enable AutoSave in Preferences > Backup section via a toggle
  • When enabled, edits to a saved graph trigger a debounced write to the same canonical file after 30 seconds of inactivity
  • Untitled (unsaved) graphs: AutoSave is a no-op; existing backup continues to cover crash recovery for these
  • The {{WorkspaceSaving}} event fires with {{SaveContext.AutoSave}} so extension listeners can distinguish
  • {{HasUnsavedChanges}} clears after each AutoSave (via existing {{OnSaved()}} logic), preventing re-triggering unless the user makes another edit
  • The backup mechanism continues to run unchanged alongside AutoSave
  • {{EnableAutoSave = false}} by default (opt-in)
  • Verifiable by: (1) asserting AutoSave writes to {{workspace.FileName}} (not backup dir), (2) setting {{HasUnsavedChanges = true}} on a saved workspace and observing a file write after the debounce window, (3) confirming {{HasUnsavedChanges == false}} after AutoSave

h2. What We're NOT Doing

  • NOT triggering AutoSave for untitled workspaces (no {{FileName}}) — existing backup covers crash recovery for these
  • NOT disabling the backup mechanism when AutoSave is enabled — they serve distinct purposes
  • NOT adding a File menu checkable item in this pass — Preferences placement is consistent with all other feature toggles; a File menu shortcut can be added later based on UX guidance
  • NOT making file I/O truly async via {{File.WriteAllTextAsync}} — a new pattern with complex event-ordering implications; the debounced trigger already ensures the write doesn't block the user's editing interaction; can be added in a follow-up if performance profiling reveals a problem
  • NOT adding a configurable AutoSave interval in this first pass — constant 30 s debounce delay; can be exposed as a preference in a follow-up

h2. Implementation Approach

AutoSave will be implemented entirely in the WPF layer ({{DynamoViewModel}}). When a workspace is opened or becomes active, {{DynamoViewModel}} subscribes to its {{PropertyChanged}} event. When {{HasUnsavedChanges}} becomes {{true}} for a workspace with a non-empty {{FileName}} and {{EnableAutoSave}} is {{true}}, a per-workspace {{ActionDebouncer}} fires the existing {{SaveAs(Guid, string, bool, SaveContext)}} pipeline after 30 seconds. On workspace close or removal, the debouncer is cancelled and disposed.

This approach reuses existing infrastructure ({{ActionDebouncer}}, {{InternalSaveAs}}, {{SaveAs(Guid, ...)}}) with no new patterns and no changes to {{DynamoCore}}'s threading model.
h2.

h3. TASK 1: Add {{SaveContext.AutoSave}} enum value [HIGH PRIORITY]
Status: DONE
Milestone: Extension listeners can distinguish AutoSave events and skip expensive work by checking {{saveContext == SaveContext.AutoSave}}.

  • Add {{AutoSave}} to the {{SaveContext}} enum at {{src/DynamoCore/Graph/ModelBase.cs:16}} (after {{SaveAs}})
  • Grep for {{switch.*saveContext|case SaveContext}} to verify no exhaustive switch statements need a new {{case AutoSave:}} branch
  • Add enum entry to {{src/DynamoCore/PublicAPI.Unshipped.txt}}

Validation: Build succeeds with no exhaustive-switch warnings; {{grep -r "SaveContext.AutoSave" src/}} returns the new declaration.

Requirements from spec:

  • AutoSave events should be distinguishable from interactive saves so listeners can opt out of expensive work

Files to Modify:

  • {{src/DynamoCore/Graph/ModelBase.cs}} — add {{AutoSave}} to enum on line 16: {{public enum SaveContext { [Obsolete(...)] File, Copy, Undo, Preset, None, Save, SaveAs, AutoSave };}}
  • {{src/DynamoCore/PublicAPI.Unshipped.txt}} — add: {{Dynamo.Graph.SaveContext.AutoSave = 7 -> Dynamo.Graph.SaveContext}}
    h2.

h3. TASK 2: Add {{EnableAutoSave}} to {{PreferenceSettings}} [HIGH PRIORITY]
Status: DONE
Milestone: {{EnableAutoSave}} persists across Dynamo restarts (round-trips through XML serialization) and defaults to {{false}}.

  • Add backing field {{private bool isAutoSaveEnabled;}} near {{isNotificationCenterEnabled}} in {{src/DynamoCore/Configuration/PreferenceSettings.cs}}
  • Add {{EnableAutoSave}} property using {{RaisePropertyChanged(nameof(EnableAutoSave))}} — pattern from lines 760-779
  • Set {{EnableAutoSave = false;}} in the defaults block (near line 1101 where {{EnableNotificationCenter = true}} is set)
  • Add entries to {{src/DynamoCore/PublicAPI.Unshipped.txt}}

Validation: {{dotnet test src/DynamoCoreTests/DynamoCoreTests.csproj --filter "Name~PreferenceSettings"}} — all existing tests pass; new round-trip test passes.

Requirements from spec:

  • Feature must be opt-in (default disabled)
  • Setting must persist across restarts

Files to Modify:

  • {{src/DynamoCore/Configuration/PreferenceSettings.cs}} — add backing field + {{EnableAutoSave}} property + default value
  • {{src/DynamoCore/PublicAPI.Unshipped.txt}} — add:
    ** {{Dynamo.Configuration.PreferenceSettings.EnableAutoSave.get -> bool}}
    ** {{Dynamo.Configuration.PreferenceSettings.EnableAutoSave.set -> void}}
    h2.

h3. TASK 3: Implement AutoSave debouncer in {{DynamoViewModel}} [HIGH PRIORITY]
Status: DONE
Milestone: With {{EnableAutoSave = true}}, editing a saved graph and waiting 30 seconds results in the file being written to {{workspace.FileName}}; {{HasUnsavedChanges}} becomes {{false}}; no user prompt appears on close.

  • Add {{private const int AutoSaveDebounceMs = 30_000;}} constant near the top of {{DynamoViewModel.cs}}
  • Add field {{private Dictionary<Guid, ActionDebouncer> autoSaveDebouncers = new();}}
  • Add {{private void SubscribeAutoSaveForWorkspace(WorkspaceModel workspace)}} — subscribes to {{workspace.PropertyChanged}}, filtering on {{"HasUnsavedChanges"}}; creates an {{ActionDebouncer}} for the workspace keyed by {{workspace.Guid}}
  • In the {{PropertyChanged}} handler: if {{HasUnsavedChanges == true}} and {{workspace.FileName != string.Empty}} and {{preferenceSettings.EnableAutoSave}}, call {{autoSaveDebouncers[workspace.Guid].Debounce(AutoSaveDebounceMs, () => TriggerAutoSave(workspace.Guid))}}
  • Add {{private void TriggerAutoSave(Guid workspaceGuid)}} — resolves the workspace from {{Model.Workspaces}}, checks {{FileName}} is still non-empty, then calls {{SaveAs(workspaceGuid, workspace.FileName, isBackup: false, SaveContext.AutoSave)}} at line 2861
  • Add {{private void UnsubscribeAutoSaveForWorkspace(WorkspaceModel workspace)}} — cancels and disposes the debouncer, removes from dict, unsubscribes from {{PropertyChanged}}
  • Wire up: subscribe on {{Model.WorkspaceAdded}}; unsubscribe on {{Model.WorkspaceRemoved}}
  • Dispose all remaining debouncers in {{DynamoViewModel.Dispose()}} / shutdown cleanup

Validation:

  • Test: enable AutoSave, save a temp {{.dyn}} file, set {{workspace.HasUnsavedChanges = true}}, advance mock clock past debounce, assert file was modified and {{HasUnsavedChanges == false}}
  • Test: untitled workspace — assert no save event fires

Requirements from spec:

  • "triggered when the graph needs to be marked dirty" — debounce on {{HasUnsavedChanges = true}}
  • "Need to be async and non-blocking" — {{ActionDebouncer}} fires via {{Task.Delay}}, not synchronously during user's edit

Files to Modify:

  • {{src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs}} — add constant, field, subscribe/unsubscribe/trigger methods, wire to workspace lifecycle events, dispose

Implementation Details:

  • {{ActionDebouncer}} primary constructor requires {{ILogger}} — pass {{Model.Logger}}
  • The debounced action fires on the UI thread (debouncer captures {{SynchronizationContext.Current}}); route through {{SaveAs(Guid, string, bool, SaveContext)}} at line 2861 for safe programmatic save
  • {{workspace.FileName}} is re-read at trigger time (not captured at debounce-schedule time) so a Save As between schedule and fire picks up the new path correctly
  • {{HasUnsavedChanges = false}} is set automatically by {{WorkspaceModel.OnSaved()}} at line 428 after a successful save — prevents re-triggering without user edits
  • Cancelled/disposed debouncer for a workspace that was closed before the 30 s elapsed means no stale write to a file that may have been re-used
    h2.

h3. TASK 4: Add AutoSave toggle to Preferences UI [MEDIUM PRIORITY]
Status: DONE
Milestone: The Preferences window shows an AutoSave toggle in the Backup settings expander; toggling it updates {{PreferenceSettings.EnableAutoSave}} and the change persists across restarts.

  • Add {{AutoSaveIsChecked}} property to {{PreferencesViewModel.cs}} (pattern: {{NotificationCenterIsChecked}} lines 1103-1117):
    {code:csharp}public bool AutoSaveIsChecked
    {
    get { return preferenceSettings.EnableAutoSave; }
    set { preferenceSettings.EnableAutoSave = value; RaisePropertyChanged(nameof(AutoSaveIsChecked)); }
    }
    {code}
  • Add a {{ToggleButton}} row inside {{BackupSettingsExpander}} in {{PreferencesView.xaml}} (pattern: {{NotificationCenterToggle}} lines 919-924), with {{Name="AutoSaveToggle"}}, bound to {{{Binding AutoSaveIsChecked}}}, label {{{x:Static p:Resources.PreferencesViewEnableAutoSave}}}, tooltip from {{PreferencesViewAutoSaveTooltip}}
  • Add to {{src/DynamoCoreWpf/PublicAPI.Unshipped.txt}}:
    ** {{Dynamo.ViewModels.PreferencesViewModel.AutoSaveIsChecked.get -> bool}}
    ** {{Dynamo.ViewModels.PreferencesViewModel.AutoSaveIsChecked.set -> void}}

Validation: Launch Dynamo sandbox, open Preferences, verify toggle appears in Backup section, toggle on/off, close and re-open Preferences — verify value persists.

Requirements from spec:

  • "May need UI/UX input on where to put the option" — Preferences > Backup expander follows all existing toggle precedents; File menu placement deferred to UX review

Files to Modify:

  • {{src/DynamoCoreWpf/ViewModels/Menu/PreferencesViewModel.cs}} — add {{AutoSaveIsChecked}} property
  • {{src/DynamoCoreWpf/Views/Menu/PreferencesView.xaml}} — add {{ToggleButton}} row inside {{BackupSettingsExpander}}
  • {{src/DynamoCoreWpf/PublicAPI.Unshipped.txt}} — add 2 entries
    h2.

h3. TASK 5: Add localization strings [MEDIUM PRIORITY]
Status: DONE
Milestone: All user-facing AutoSave strings compile; the toggle label displays correctly in English at runtime.

  • Add to {{src/DynamoCoreWpf/Properties/Resources.resx}}:
    ** {{PreferencesViewEnableAutoSave}} = {{"Enable AutoSave"}}
    ** {{PreferencesViewAutoSaveTooltip}} = {{"Automatically save your graph to its original file after a period of inactivity. Only applies to graphs that have already been saved to disk."}}
  • Mirror both entries to {{src/DynamoCoreWpf/Properties/Resources.en-US.resx}}
  • Add placeholder entries (copy en-US value) to all 13 localized {{.resx}} siblings under {{src/DynamoCoreWpf/Properties/}}: {{cs-CZ}}, {{de-DE}}, {{en-GB}}, {{es-ES}}, {{fr-FR}}, {{it-IT}}, {{ja-JP}}, {{ko-KR}}, {{pl-PL}}, {{pt-BR}}, {{ru-RU}}, {{zh-CN}}, {{zh-TW}}

Validation: Build succeeds with no missing resource key warnings; UI displays "Enable AutoSave" next to the toggle.

Requirements from spec:

  • AGENTS.md: "User-facing strings in {{.resx}} files"

Files to Modify:

  • {{src/DynamoCoreWpf/Properties/Resources.resx}}
  • {{src/DynamoCoreWpf/Properties/Resources.en-US.resx}}
  • All 13 localized sibling {{.resx}} files
    h2.

h3. TASK 6: Add tests [MEDIUM PRIORITY]
Status: DONE
Milestone: All new test cases pass; existing preference and save tests continue to pass.

  • In {{test/DynamoCoreTests/Configuration/PreferenceSettingsTests.cs}}:
    ** {{WhenDefaultSettingsThenAutoSaveIsDisabled}} — assert {{EnableAutoSave == false}} (pattern: line 70)
    ** {{WhenSettingsSavedAndLoadedThenAutoSaveRoundTrips}} — mutate {{EnableAutoSave = true}}, save/reload, assert {{true}} persists (pattern: lines 105-159)
  • In {{test/DynamoCoreWpf3Tests/WorkspaceSaving.cs}}:
    ** {{WhenAutoSaveEnabledAndWorkspaceIsDirtyAndHasFileNameThenSaveIsCalledAfterDebounce}} — enable AutoSave, create saved temp workspace, set {{HasUnsavedChanges = true}}, trigger debounce, assert file modified and {{HasUnsavedChanges == false}}
    ** {{WhenAutoSaveEnabledAndWorkspaceHasNoFileNameThenSaveIsNotCalled}} — untitled workspace, set {{HasUnsavedChanges = true}}, assert no save event fires
    ** {{WhenAutoSaveEnabledAndSaveFiredThenSaveContextIsAutoSave}} — capture {{WorkspaceSaving}} event arg, assert {{saveContext == SaveContext.AutoSave}}
    ** {{WhenAutoSaveDisabledAndWorkspaceIsDirtyThenSaveIsNotCalled}} — disable AutoSave, dirty workspace, assert no save after debounce window
    ** {{WhenAutoSaveEnabledAndWorkspaceClosedBeforeDebounceElapsedThenSaveIsNotCalled}} — verify debouncer cancel on workspace remove prevents stale write
  • Add {{false}} to {{test/settings/DynamoSettings-NewSettings.xml}} if needed for fixture round-trip coverage

Validation: {{dotnet test src/DynamoCoreTests/DynamoCoreTests.csproj --filter "NameAutoSave"}} and {{dotnet test test/DynamoCoreWpf3Tests/ --filter "NameAutoSave"}} — all new tests pass.

Requirements from spec:

  • "Look for any performance degradations, add tests if possible"
  • NUnit naming: {{WhenConditionThenExpectedBehavior}}; one behavior per test; Arrange-Act-Assert

Files to Modify:

  • {{test/DynamoCoreTests/Configuration/PreferenceSettingsTests.cs}}
  • {{test/DynamoCoreWpf3Tests/WorkspaceSaving.cs}}
  • {{test/settings/DynamoSettings-NewSettings.xml}} (if needed)
    h2.

h2. Testing Strategy

h3. Unit Tests

  • {{EnableAutoSave}} default value is {{false}}
  • {{EnableAutoSave}} round-trips through {{PreferenceSettings}} XML serialization
  • AutoSave fires for a saved workspace when {{HasUnsavedChanges = true}} and debounce elapses
  • AutoSave is a no-op for untitled workspaces ({{FileName == string.Empty}})
  • AutoSave does not fire when {{EnableAutoSave = false}}
  • {{WorkspaceSaving}} event carries {{SaveContext.AutoSave}}
  • {{HasUnsavedChanges}} is {{false}} after successful AutoSave
  • Debouncer is cancelled/disposed when the workspace is removed before debounce fires

h3. Integration Tests

  • Open a real {{.dyn}} file, make an edit, wait for debounce (or trigger directly), verify file on disk is updated
  • Verify backup files still written on the existing interval alongside AutoSave

h3. Manual Testing Steps

Enable AutoSave in Preferences > Backup section

Open an existing saved graph, add a node — title bar shows unsaved indicator

Wait 30 seconds without editing — verify title bar clears and file on disk timestamp updated

Open an untitled graph, add a node, wait 30 seconds — verify no unexpected file write

Disable AutoSave in Preferences, make an edit — verify no automatic save occurs

Close a graph after AutoSave has fired — verify no "Unsaved changes" dialog appears

Close a graph within the 30 s debounce window (before AutoSave fires) — verify the "Unsaved changes" dialog still appears correctly

h2. Performance Considerations

  • {{ActionDebouncer}} resets its {{Task.Delay}} on every call — rapid edits accumulate only one pending save (cancels and restarts the 30 s clock), no O(n) overhead during editing
  • {{WorkspaceModel.ToJson}} and {{File.WriteAllText}} happen synchronously on the UI thread during the debounced action. For graphs with 1000+ nodes this may cause a brief pause. If performance profiling on test graphs under {{test/core/Performance/}} reveals this is a problem, a follow-up should offload the file write via {{DelegateBasedAsyncTask}}.
  • AutoSave does not trigger during graph evaluation (since {{HasUnsavedChanges}} is set by edit operations, not evaluation events) — no re-entrancy concern with {{UpdateGraphAsyncTask}}

h2. Migration Notes

  • {{EnableAutoSave}} defaults to {{false}} — existing users see no behavior change unless they opt in
  • {{SaveContext.AutoSave}} is a new enum value — existing code that does not {{switch}} over {{SaveContext}} is unaffected; verify no exhaustive switch statements exist before submitting (grep: {{switch.*SaveContext}})
  • Backup mechanism unchanged — no migration of backup settings needed

@eamiri eamiri added the kiln Created by kiln label May 22, 2026
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-10515

@eamiri eamiri added the paused Workflow paused — will auto-resume on next daemon start label May 22, 2026
eamiri and others added 3 commits May 22, 2026 09:27
Add EnableAutoSave property to PreferenceSettings with default false,
backing field, and PublicAPI entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@eamiri eamiri removed the paused Workflow paused — will auto-resume on next daemon start label May 22, 2026
eamiri and others added 4 commits May 22, 2026 09:36
Subscribe to each workspace's PropertyChanged event and trigger a
debounced save to the original file when HasUnsavedChanges becomes true,
gated on PreferenceSettings.EnableAutoSave and a non-empty FileName.
Per-workspace ActionDebouncer coalesces rapid edits into a single save
after 30s of inactivity; saves route through the existing SaveAs(Guid,
...) entry point with SaveContext.AutoSave so extension listeners can
distinguish AutoSave events.

Debouncers are created on workspace add (and for the initial workspace
in the constructor), cancelled/disposed on workspace remove, and all
remaining debouncers are disposed during shutdown.
Wire EnableAutoSave preference to a ToggleButton in the Preferences >
Backup expander via a new AutoSaveIsChecked property on
PreferencesViewModel. Include the user-facing resource strings in the
primary and en-US resx files so the build compiles; other locales
follow in TASK 5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add PreferencesViewEnableAutoSave and PreferencesViewAutoSaveTooltip
entries to all 13 localized resx siblings as English placeholders.
Translation team will localize in a follow-up pass.
…DYN-10515)

Adds NUnit coverage for:
- EnableAutoSave default value (false) and XML round-trip
- AutoSave fires for dirty saved workspaces with SaveContext.AutoSave
- AutoSave is a no-op for untitled workspaces and when disabled
- Debouncer is disposed when a workspace is removed

Exposes the AutoSave debouncer dictionaries and TriggerAutoSave as
internal to keep tests deterministic without the 30s debounce delay.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@eamiri eamiri marked this pull request as ready for review May 22, 2026 13:53
Copilot AI review requested due to automatic review settings May 22, 2026 13:53
@eamiri eamiri added the pr_ready PR is ready for review label May 22, 2026
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements an opt-in “AutoSave” feature for Dynamo graphs (VSCode-style), allowing saved workspaces to be automatically written back to their canonical .dyn file after inactivity, while preserving the existing backup mechanism. This is primarily done in the WPF layer (DynamoViewModel) and surfaced via a new Preferences toggle.

Changes:

  • Added SaveContext.AutoSave and updated PublicAPI tracking for the new enum value.
  • Added PreferenceSettings.EnableAutoSave (persisted, default false) plus Preferences UI toggle + localized strings.
  • Implemented per-workspace AutoSave scheduling in DynamoViewModel and added/updated tests and settings fixtures.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/settings/DynamoSettings-NewSettings.xml Adds <EnableAutoSave> to the “new settings” fixture for import/copy settings coverage.
test/DynamoCoreWpf3Tests/WorkspaceSaving.cs Adds WPF-layer tests around AutoSave triggering/context and workspace removal behavior.
test/DynamoCoreTests/Configuration/PreferenceSettingsTests.cs Adds unit tests for AutoSave default value and XML round-tripping.
src/DynamoCoreWpf/Views/Menu/PreferencesView.xaml Adds an AutoSave toggle to Preferences → General → Backup UI.
src/DynamoCoreWpf/ViewModels/Menu/PreferencesViewModel.cs Adds AutoSaveIsChecked bound to PreferenceSettings.EnableAutoSave.
src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs Implements AutoSave subscription, debouncing, triggering, and shutdown cleanup.
src/DynamoCoreWpf/PublicAPI.Unshipped.txt Tracks new public API surface for PreferencesViewModel.AutoSaveIsChecked.
src/DynamoCoreWpf/Properties/Resources.resx Adds AutoSave label/tooltip strings.
src/DynamoCoreWpf/Properties/Resources.en-US.resx Adds AutoSave label/tooltip strings (en-US).
src/DynamoCoreWpf/Properties/Resources.cs-CZ.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.de-DE.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.en-GB.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.es-ES.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.fr-FR.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.it-IT.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.ja-JP.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.ko-KR.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.pl-PL.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.pt-BR.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.ru-RU.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.zh-CN.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCoreWpf/Properties/Resources.zh-TW.resx Adds AutoSave label/tooltip keys (localized file placeholder values).
src/DynamoCore/PublicAPI.Unshipped.txt Tracks new public APIs (SaveContext.AutoSave, PreferenceSettings.EnableAutoSave).
src/DynamoCore/Graph/ModelBase.cs Adds SaveContext.AutoSave enum value.
src/DynamoCore/Configuration/PreferenceSettings.cs Adds persisted EnableAutoSave preference with default false.

Comment on lines +4776 to +4780
foreach (var debouncer in autoSaveDebouncers.Values)
{
debouncer.Dispose();
}
autoSaveDebouncers.Clear();
return;
}

SaveAs(workspaceGuid, workspace.FileName, isBackup: false, SaveContext.AutoSave);
Comment on lines +1761 to +1765
workspace.HasUnsavedChanges = true;
Assert.IsTrue(workspace.HasUnsavedChanges);

ViewModel.TriggerAutoSave(workspace.Guid);

Comment on lines +1866 to +1869
ViewModel.Model.RemoveWorkspace(customNodeWorkspace);

Assert.IsFalse(ViewModel.autoSaveDebouncers.ContainsKey(workspaceGuid));
Assert.IsFalse(ViewModel.autoSaveHandlers.ContainsKey(workspaceGuid));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kiln Created by kiln pr_ready PR is ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants