fix: detect media_metadata changes for save-changes prompt (#377)#520
Open
FelipeDefensor wants to merge 2 commits into
Open
fix: detect media_metadata changes for save-changes prompt (#377)#520FelipeDefensor wants to merge 2 commits into
FelipeDefensor wants to merge 2 commits into
Conversation
…nnotator#377) is_file_modified compared current state against self.file.__dict__, but for media_metadata both sides referenced the SAME live MediaMetadata object — on_set_media_metadata_field mutates self.file.media_metadata in place, and get_app_state takes dict(self.file.media_metadata) of that same mutated object. The comparison was always equal, so editing notes (or any other field) never set the file to "modified" and the save-changes dialog never appeared on close. The reporter only flagged "notes" because the notes UI is the only field whose edits go straight to MEDIA_METADATA_FIELD_SET without sitting next to a side-channel that happens to also dirty the file. Title, custom-field edits, etc. were broken too in the same way — verified locally before the fix. Track a snapshot of media_metadata at the last save/load: - self._saved_metadata is set by a property setter on `file`, so every place that reassigns the file (init, _setup_file, save, update_file, app.on_open's `file_manager.file = file`) refreshes it for free. - is_file_modified compares dict(current_data["media_metadata"]) against this snapshot. The existing are_tilia_data_equal call is kept for the other fields (timelines_hash, media_path). - on_player_duration_changed and set_media_duration also update the snapshot, since those mutations are system-driven (the player reports the loaded media's length) and shouldn't show up as user edits — without this, the existing test_is_file_modified_empty_file assertion would flip to True after the fixture sets the duration. Tests: test_is_file_modified_after_notes_edit and test_is_file_modified_after_title_edit cover the regression. The existing modification tests (modified title via custom params dict, removed metadata field, modified media_path, etc.) keep working — their flow already used different objects on each side, so the snapshot path is harmlessly redundant for them.
ce2294e to
9abb24c
Compare
azfoo
requested changes
May 14, 2026
azfoo
left a comment
Collaborator
There was a problem hiding this comment.
Added some tests, don't know if their behaviour is expected. Invert their logic if they are!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #377.
Summary
`FileManager.is_file_modified` compared the current app state against `self.file.dict`, but for `media_metadata` both sides referenced the same live `MediaMetadata` object: `on_set_media_metadata_field` mutates `self.file.media_metadata` in place, and `get_app_state` takes `dict(self.file.media_metadata)` of that same mutated object. The comparison was always equal, so editing notes never set the file to "modified" and the save-changes dialog never appeared on close.
The reporter flagged "notes" specifically, but it's not unique to that field — the title, custom fields, etc. were broken in the same way. Verified manually before the fix:
```
Initial is_file_modified: False
After title change is_file_modified: False
After notes change is_file_modified: False
```
After the fix:
```
Initial is_file_modified: False
After title change is_file_modified: True
After notes change is_file_modified: True
```
Approach
Track a snapshot of `media_metadata` taken at the last save / file-load.
Test plan
Note for the reviewer
The pre-existing `media_path` comparison has the same structural shape — `on_player_url_changed` writes the live path to `self.file.media_path`, and `get(Get.MEDIA_PATH)` reads it from the player, so the two sides drift only because the player doesn't immediately propagate. It happens to work in current usage because of that timing, but it's fragile. Out of scope here — happy to follow up if you'd like the same snapshot treatment for it.