Skip to content

Autosave unexported annotations and offer to restore them - #226

Merged
mfl28 merged 5 commits into
masterfrom
feature/autosave
Oct 11, 2026
Merged

mfl28 merged 5 commits into
masterfrom
feature/autosave

Conversation

@mfl28

@mfl28 mfl28 commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Annotations that were not exported yet are now saved automatically, so a crash, a forced quit or a power loss no longer loses the work since the last export.

How it works

  • 5 seconds after the last edit, the open folder's unexported annotations are saved as one JSON file per folder in the app data folder (macOS: ~/Library/Application Support/BoundingBoxEditor/autosave, Windows: %APPDATA%\BoundingBoxEditor\autosave, Linux: $XDG_DATA_HOME or ~/.local/share/boundingboxeditor/autosave). Files are written on a background thread into a temporary file and then moved into place.
  • The file is deleted once the annotations are exported, or when the user quits and chooses not to save.
  • Opening a folder with an autosave asks "Restore Unsaved Annotations". Restored annotations still count as unexported. At startup the app offers to reopen the most recent folder that has an autosave.
  • The status bar's saved-status dot has a tooltip: exported, not exported, or not exported but saved automatically at a given time. A failed autosave shows a status message.
  • A save requested while an earlier one is still waiting replaces it (AutosaveWriter), so saves never pile up on slow disks. Measured: about 12 ms on the UI thread for 200k boxes, and the writing happens in the background.

Also

  • The JSON format now supports masks ("mask": {"size", "counts"}, COCO RLE), so autosaves keep them and JSON exports no longer drop them.
  • Fix: annotations that are imported while the shown image is still loading were placed against the wrong image size and added a second time once the image had loaded. Imported shapes are now shown by the image's load listener in that case.

Tests

  • AutosaveStoreTest, AutosaveWriterTest (unit) and AutosaveTests (UI: autosave and deletion after export, restore, declining, restore while the image is still loading).
  • The test task points the autosave folder at build/tmp/test-autosave, and BoundingBoxEditorTestBase empties it before each UI test, so tests never touch the user's autosaves.
  • The startup offer to reopen the last folder isn't covered by an automated test.

mfl28 added 5 commits October 10, 2026 20:31
Unexported annotations of the open folder are saved a few seconds after
each edit as one JSON file per folder in the app data folder. The file is
deleted once the annotations are exported or discarded on quit. Opening a
folder with an autosave offers to restore it, and at startup the app offers
to reopen the last folder that has one. The JSON format now supports masks
(COCO RLE), so autosaves keep them.
A restored autosave is often imported before the image has loaded. Its
shapes were then placed against the wrong image size and added a second
time when the image finished loading. Now the image's load listener
shows them once its size is known.
The status bar's saved-status indicator now has a tooltip that says whether
the annotations are exported and, if not, when they were last saved
automatically.
AutosaveWriter writes the autosaves on the background thread. A save that
is requested while an earlier one still waits replaces it, so slow disks
never make saves pile up.
On Windows CI the previous UI test's autosave timer fired during the next
test and wrote an autosave for the shared test folder, which then asked to
be restored. Autosaving now stops (after a running save) when the window
is hidden.

Also: tests for invalid JSON masks, the startup offer to reopen the last
folder, a failing autosave and the tooltip's date format, and Sonar fixes
(unnamed catch variables, AutosaveStore as a record).
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Oct 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.31469% with 42 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.05%. Comparing base (c277d54) to head (e81bd8d).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
...mfl28/boundingboxeditor/controller/Controller.java 83.05% 11 Missing and 9 partials ⚠️
...28/boundingboxeditor/controller/AutosaveStore.java 75.00% 8 Missing and 3 partials ⚠️
...8/boundingboxeditor/controller/AutosaveWriter.java 75.67% 8 Missing and 1 partial ⚠️
...8/boundingboxeditor/model/io/JSONLoadStrategy.java 95.34% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #226      +/-   ##
============================================
- Coverage     90.20%   90.05%   -0.15%     
- Complexity     2317     2374      +57     
============================================
  Files           132      135       +3     
  Lines          8618     8901     +283     
  Branches        833      865      +32     
============================================
+ Hits           7774     8016     +242     
- Misses          437      462      +25     
- Partials        407      423      +16     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mfl28
mfl28 merged commit 509e580 into master Oct 11, 2026
19 checks passed
@mfl28
mfl28 deleted the feature/autosave branch October 11, 2026 07:34
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.

1 participant