Skip to content

[Fixes #461, #462, #463] Make loading auto-saved model changes opt-in - #464

Merged
LaCuneta merged 7 commits into
mainfrom
opt-in-wip-load
Sep 22, 2026
Merged

LaCuneta merged 7 commits into
mainfrom
opt-in-wip-load

Conversation

@omargfh

@omargfh omargfh commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Make loading auto-saved model changes opt-in

Fixes #461, #462, and #463.

Changes

Behavior

  • Cached changes are no longer applied automatically on load. When a cached copy exists, a "Load Changes" toast offers to apply it. The "revert to original" toast is removed.
  • Removed the setting "Automatically save changes made to models and reuse them when reloading." Changes are always saved.
  • Added a setting to hide the "Load Changes" toast. Defaults to shown.

API

  • fromNlogo takes workInProgressNlogo: String | null and compiles whatever it is handed. newSession no longer takes workInProgressState.
  • WorkInProgressState gains enabled-with-unloaded-wip.
  • loadWip returns WipInfo | null.
  • _syncState returns the state so setSession reads it once.

Call sites

  • loadWorkInProgress in simulation.js guards against a null listener or an empty cache.
  • nlw-revert-wip collapses to loadSource(wipListener.getNlogoSource(), null); revertWip clears the source title.
  • HubNet Web's loadHubNetWeb updated for the new newSession signature.

Why WIP handling moved out of Tortoise

Tortoise used to own WIP state because cached changes were applied at load time, so the loader was the only place that knew both which nlogo it compiled and whether it came from the cache. It derived workInProgressState and passed it through newSession so the Revert button rendered correctly from the first frame, and the listener sometimes had to patch that state afterwards.

Opt-in loading separates the two questions. The loader now compiles whatever workInProgressNlogo it is handed, the page decides when to hand it over via loadWip and loadSource, and WipListener.getState() derives state on demand from what only the listener knows. The loader could not compute enabled-with-unloaded-wip anyway, since that state never touches the compile path.

#462 fix

Cached changes are always exported as nlogox XML by compiler.exportNlogoXML, but Tortoise.fromNlogo was picking the parser based on the format of the original file. Loading a legacy .nlogo file with cached changes therefore handed XML to the .nlogo parser and crashed the engine.

fromNlogo now dispatches on the string it actually compiles, using the new exported isOldFormatNlogo helper in nlogo-source.coffee.

#463 fix

Anchor links inside toasts inherited the page's default link color and were unreadable against the toast background. Toast anchors now get their own color and underline so they read at any toast variant.

Side effects

  • NetTango fromURL now passes null for WIP, so URL-loaded NetTango models show disabled instead of enabled with an empty cache. This hides the Revert button, which was always disabled in that case anyway.

Known limitations

  • The old workInProgress.enabled = false setting is ignored. No storage version bump. Why? The current storage version is 1, which means no one had tried to update it before. I recall Jeremy's recent work on pinning engine versions, and I can imagine a scenario where the version stored is higher than the one expected.

Testing

Chrome and Firefox:

  • Open a model, move a widget, refresh, click Load Changes. Changes load.
  • Open a model, move a widget, refresh, edit the model again, refresh, click Load Changes. Latest changes load.
  • Open a model, move a widget with the keyboard, refresh, click Load Changes.
  • Open a model, move a widget, refresh while in authoring mode.
  • Load Patch and World Size.nlogo, edit, refresh, click Load Changes. No crash (Engine crashes when loading a WIP .nlogo file #462).
  • HubNet Web join.
  • demomodels/All Widgets.
  • coffee compiles
  • coffeelint and test
  • node --check

@omargfh
omargfh marked this pull request as ready for review September 15, 2026 18:15

@LaCuneta LaCuneta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you for your work on this! I really like that I can keep using my existing model edits without much friction. I also appreciate the bug fixes.

Three issues I found:

  1. If you open a model with cached changes, then select to load those changes, things work as expected. But if I then upload a model that also has cached changes, I do not get prompted to apply them. If I refresh the page and re-upload, it does work, so it seems like the page state is getting set by the first model loaded from cache.
  2. This is a silly edge case, but if you open a model with cached changes then use your fleetest fingers to make an edit while the Load Changes toast is up, when you hit Load Changes it'll load the change you just made, not the one that was in the cache when the toast was shown. I think my preference is to just hide the toast early if someone dives into editing right away.
  3. Previously we displayed the source of the model (switch code from createWorkInProgressAlert() when talking about it in the toast, now all models are "dismiss to keep the model as linked". I think being more specific is helpful, but I don't consider it a blocker to merge.

@omargfh

omargfh commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Hi @LaCuneta, thank you for taking the time to review this PR. I am glad it is going smooth.

The devel direction right now is to get rid of the toast in favor of highlighting the Load Changes button.

I'll look into the remaining concerns and address them shortly.

@omargfh
omargfh requested a review from LaCuneta September 18, 2026 18:46
@omargfh

omargfh commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author
  1. If you open a model with cached changes, then select to load those changes, things work as expected. But if I then upload a model that also has cached changes, I do not get prompted to apply them. If I refresh the page and re-upload, it does work, so it seems like the page state is getting set by the first model loaded from cache.

Toast no longer exists.

  1. This is a silly edge case, but if you open a model with cached changes then use your fleetest fingers to make an edit while the Load Changes toast is up, when you hit Load Changes it'll load the change you just made, not the one that was in the cache when the toast was shown. I think my preference is to just hide the toast early if someone dives into editing right away.

Toast no longer exists.

  1. Previously we displayed the source of the model (switch code from createWorkInProgressAlert() when talking about it in the toast, now all models are "dismiss to keep the model as linked". I think being more specific is helpful, but I don't consider it a blocker to merge.

Toast no longer exists but I added it as a hover title on the "Load Changes" button.

@LaCuneta LaCuneta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, looks good to me. The "load model, Load Changes, upload a model, don't see cached changes" bug is still there even without the toast, but I'll go ahead and merge this as I noticed a related existing bug with reverting that'll need fixing anyways. I'll take care of the other at the same time.

@LaCuneta
LaCuneta merged commit db84c75 into main Sep 22, 2026
5 checks passed
@LaCuneta
LaCuneta deleted the opt-in-wip-load branch September 22, 2026 23:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make auto-saved model loading opt-in rather than automatic.

2 participants