Repository navigation
fix(sync): resume ended episodes from synced progress - #464
Merged
Merged
Conversation
…tural end Play and resume() on a naturally ended episode restart at 0 even when another device has since saved unfinished progress for it, and the first pause then saves over that progress (#463). The unit tests cover both entry points, a finished episode that starts over, a synced position past the end of the local copy, which must pause short of the end without finishing, and an explicit time, which wins over synced progress. The ended journey pauses with the visible toggle and checks the saved position. The playing-sync journey checks that the remote position merges and playback keeps advancing.
Play and resume() on a naturally ended episode now start at its saved progress, the same position a new load of it starts at, instead of 0. A finished, past-duration or missing record still starts over, and an explicit time still wins. A synced position at or past the end of the local copy pauses short of the end, as a seek does, instead of playing the last moment and finishing the episode (#463).
The journey now flushes local saves, rewrites data.json through the vault adapter, awaits onExternalSettingsChange() and returns the merged progress from the same renderer eval. The separate read after the merge poll could run after the player's next position save had replaced the synced time.
This was referenced Oct 14, 2026
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.
Summary
Fixes #463.
After an episode ends on this device, Play now resumes unfinished progress synced from another device. A saved finished episode still restarts at zero. Both Play entry points use the existing saved-progress policy and respect a rejected seek past the local media duration.
The playing-sync journey flushes pending progress before sync and checks both time bounds. It catches the V-462 mutation that previously survived.
Verification
npm run lint,npm run format:check,npm run typecheck,npm run build,npm run testwith 2,432 tests,npm run test:toolingwith 13 tests, andnpm run docs:build.npm run test:e2epassed all 141 tests on Linux Obsidian 1.14.4.PODNOTES_OBSIDIAN_APP=/opt/Obsidian/obsidian npm run test:e2epassed all 141 on 1.13.7. Both full runs used fresh vaults at the final commit.Fixtures/Local Fixture.wav. After natural end, sync to 30 seconds and flush, visible Play resumed at 30. Master restarted near zero. Unit and E2E regressions failed on master. The strengthened journey failed with the exact V-462 mutation and passed without it.npm run count:writes -- start,report, andstopmatched master at every checkpoint.npm run sizepassed at 311,774 raw and 98,336 gzip bytes, increases of 30 and 12 bytes.Full verification report and evidence archive contain commands, persisted values, review findings, and the verification deviation.
Release impact
No schema, settings, API or URI change. No migration.
Docs at release
In #458's sync handoff and mobile guidance, add that an episode ended here resumes unfinished synced progress when the user presses Play. A saved finished episode still restarts at zero. The ended player may show its old end position until Play.
Retain #462's immediate adoption for a clean paused player, the segment-preview exception, waiting for sync, and selecting the desired episode when a different episode is loaded.
Note
Fix ended-episode replay to resume from synced progress
PlayerController.play()now resumes a naturally ended episode fromresumeTime(episode)when no explicit time is given; an explicit time still takes precedence and marks the position as user-movedPlayerController.resume()on an ended loaded session moves toresumeTime(episode)instead of unconditionally restarting at zeroMacroscope summarized c52b569.