From b85c9f04dbb3efadf0ffd2bc5c1388c56bedeaa2 Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Sun, 11 Oct 2026 10:38:25 +0200 Subject: [PATCH 1/4] docs(sync): explain merged persistence and save recovery --- docs/src/content/docs/faq.md | 9 +++-- docs/src/content/docs/sync.md | 65 +++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/docs/src/content/docs/faq.md b/docs/src/content/docs/faq.md index f1863cb9..5c3175ca 100644 --- a/docs/src/content/docs/faq.md +++ b/docs/src/content/docs/faq.md @@ -94,6 +94,11 @@ See [Transcripts](/transcripts/). ## Does playback progress sync between devices? Saved progress, subscriptions, playlists, templates, and preferences can travel with PodNotes' `data.json` when your sync service includes plugin data. -PodNotes has no separate sync account or live playback handoff. Two devices can overwrite each other's changes. +PodNotes merges changes from other devices before saving and updates its library when Obsidian reports a synced file change. +If both devices change the same progress record or feed, the device saving keeps its own version of that entry. +Periodic playback checkpoints write at most once every 10 seconds. Pausing or hiding or closing the player requests a save at once. +Sync does not switch an episode already loaded in the player or seek to another device's position. +Changes that arrive during a write can still be overwritten. Keep PodNotes updated on every device and let sync finish before switching. API key values and protected private-feed URLs remain local to each device. -See [Sync and devices](/sync/) before switching between devices. +If PodNotes stops saving and shows a notice, follow [Restore saving after a notice](/sync/#restore-saving-after-a-notice). +See [Sync and devices](/sync/) for conflict and download limits. diff --git a/docs/src/content/docs/sync.md b/docs/src/content/docs/sync.md index 5fb8df06..a136bdc9 100644 --- a/docs/src/content/docs/sync.md +++ b/docs/src/content/docs/sync.md @@ -30,18 +30,39 @@ The **Default Playback Rate** preference is saved. Saved progress provides a res ## Changes on two devices -PodNotes saves a snapshot of its local state. It does not merge subscriptions, playlists, preferences, or progress changed on another device. -An open instance does not automatically reload a synced `data.json`. +Before each save, PodNotes reads `data.json` and compares it with the last loaded or saved copy and this device's changes. +It merges changes to different entries, including subscriptions, progress, playlists, and preferences. For example, one device can add a podcast while another updates its playback progress. -The second device's next save can replace the first device's subscription change with its older library snapshot. -The outcome depends on sync timing and your sync service's conflict handling. +Once the subscription reaches the second device's `data.json`, its next save keeps both changes. +When Obsidian reports a synced file change, PodNotes updates its library without a restart. +Sync does not switch an episode already loaded in the player or seek to another device's position. -Using one device at a time reduces this risk. Allow sync to finish before loading PodNotes on the second device. -If sync is still running when Obsidian starts, PodNotes can load an older snapshot before the synced file arrives. -This includes sync services that run inside Obsidian. On mobile, data loads even while the player stays closed. -Keep PodNotes disabled on the second device while sync finishes, then enable it to load the transferred data. -Syncing a file into an already open session does not update that session's in-memory library. +If both devices change the same entry before seeing each other's changes, the device saving keeps its own version. +PodNotes takes these entries whole, rather than combining their fields: + +- A saved feed, including its URL and private-feed secret reference. +- An episode's progress record or note mapping. +- The current episode, including a playlist's current episode. +- Each episode in the queue, favorites, Local Files, custom playlists, or downloads. + +Episodes match by podcast name and title, so equal titles from different podcasts stay separate. +A download's stream URL, file path, and record that PodNotes downloaded it stay together. + +A change that arrives between the read and write can still be overwritten. +Sync can also see a partly written file because PodNotes writes `data.json` in place. +An older PodNotes version on another device can overwrite the whole file. +Keep PodNotes updated on every device and let sync finish before switching devices. + +## When PodNotes saves + +User changes request a save at once. Changes made during a save share the next save. +During playback, periodic position checkpoints write at most once every 10 seconds. +Pausing, hiding the player's window, or closing the player requests a position save at once, including in a popout. +Once the Obsidian window starts closing, PodNotes starts no new writes and lets an in-flight write finish when Obsidian quits. + +PodNotes reads the file back after each write to check that the saved data matches. +A mismatch counts as a failed save. ## Secrets on each device @@ -99,10 +120,24 @@ Older links can contain the original private URL and are not rewritten by the se ## Unreadable plugin data -If `data.json` exists but Obsidian cannot read or parse it, PodNotes leaves the file unchanged. -It starts with default settings and shows a persistent notice that nothing is saved. -The notice includes the actual file path. +If a non-empty `data.json` cannot be read or parsed, PodNotes leaves it unchanged and shows a persistent notice that saving has stopped. +The notice includes the file path. If the file is unreadable at startup, PodNotes starts with default settings. +It accepts a replacement only if that file loads without repairs that could discard data. +When a readable file arrives during a session with a loaded library, invalid entries are not treated as deletions. +PodNotes keeps their last known values while merging other changes. + +If a copy from an older data format arrives during a session, PodNotes stops saving and shows a notice asking you to restart Obsidian. +Restarting runs the migration, including moving old API keys into secret storage. + +An empty file counts as missing. At startup, it starts a new library. +After a failed write leaves the file empty, the next save can write the data again, including changes merged from another device. +PodNotes does not repair a non-empty, partly written file. + +### Restore saving after a notice + +1. For an unreadable file, let sync finish. Check available disk space and file permissions if the notice remains. +2. Restore a readable backup of the file named in the notice if needed. PodNotes resumes saving when it reads a usable copy. +3. For an older-format notice, update PodNotes on every device, let sync finish, and restart Obsidian to migrate the file. -Saving remains disabled until you restore or delete that file and restart Obsidian. -Restoring a readable backup preserves the previous library. Deleting the file starts a new library. -Changes made while saving is disabled do not become a replacement for the unreadable file. +If you want to discard the old library, back up the file, delete it, and restart Obsidian. +Deletion starts a new library. Changes made with saving disabled are not saved over the unreadable file. From 2b2df8b55da8f112bb9f52b69ec8bd9700dfcbb4 Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Sun, 11 Oct 2026 10:49:56 +0200 Subject: [PATCH 2/4] docs(sync): clarify player persistence and recovery steps --- docs/src/content/docs/faq.md | 10 ++++++++-- docs/src/content/docs/sync.md | 21 ++++++++++++++------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/docs/src/content/docs/faq.md b/docs/src/content/docs/faq.md index 5c3175ca..3f4fe8dc 100644 --- a/docs/src/content/docs/faq.md +++ b/docs/src/content/docs/faq.md @@ -96,9 +96,15 @@ See [Transcripts](/transcripts/). Saved progress, subscriptions, playlists, templates, and preferences can travel with PodNotes' `data.json` when your sync service includes plugin data. PodNotes merges changes from other devices before saving and updates its library when Obsidian reports a synced file change. If both devices change the same progress record or feed, the device saving keeps its own version of that entry. -Periodic playback checkpoints write at most once every 10 seconds. Pausing or hiding or closing the player requests a save at once. + +Periodic playback checkpoints write at most once every 10 seconds. +Pausing, hiding the player's window, or closing the player requests a save at once. Sync does not switch an episode already loaded in the player or seek to another device's position. -Changes that arrive during a write can still be overwritten. Keep PodNotes updated on every device and let sync finish before switching. +The loaded episode stays current on this device, and the player saves its own position even after synced progress arrives. + +Changes that arrive between the read and write can still be overwritten. +Keep PodNotes updated on every device and let sync finish before switching. +On a new device, keep PodNotes disabled until its plugin data finishes syncing. API key values and protected private-feed URLs remain local to each device. If PodNotes stops saving and shows a notice, follow [Restore saving after a notice](/sync/#restore-saving-after-a-notice). See [Sync and devices](/sync/) for conflict and download limits. diff --git a/docs/src/content/docs/sync.md b/docs/src/content/docs/sync.md index a136bdc9..73a40445 100644 --- a/docs/src/content/docs/sync.md +++ b/docs/src/content/docs/sync.md @@ -37,8 +37,10 @@ For example, one device can add a podcast while another updates its playback pro Once the subscription reaches the second device's `data.json`, its next save keeps both changes. When Obsidian reports a synced file change, PodNotes updates its library without a restart. Sync does not switch an episode already loaded in the player or seek to another device's position. +The loaded episode stays current on this device. +The player saves its own position for that episode, even after progress from another device arrives. -If both devices change the same entry before seeing each other's changes, the device saving keeps its own version. +For other changes, conflicts favor the device saving when both devices edit the same setting or entry before seeing each other's changes. PodNotes takes these entries whole, rather than combining their fields: - A saved feed, including its URL and private-feed secret reference. @@ -47,19 +49,21 @@ PodNotes takes these entries whole, rather than combining their fields: - Each episode in the queue, favorites, Local Files, custom playlists, or downloads. Episodes match by podcast name and title, so equal titles from different podcasts stay separate. -A download's stream URL, file path, and record that PodNotes downloaded it stay together. +A download's stream URL, file path, and ownership record stay together. A change that arrives between the read and write can still be overwritten. Sync can also see a partly written file because PodNotes writes `data.json` in place. An older PodNotes version on another device can overwrite the whole file. Keep PodNotes updated on every device and let sync finish before switching devices. +On a new device, keep PodNotes disabled until sync delivers `data.json`. Then enable it. ## When PodNotes saves User changes request a save at once. Changes made during a save share the next save. During playback, periodic position checkpoints write at most once every 10 seconds. Pausing, hiding the player's window, or closing the player requests a position save at once, including in a popout. -Once the Obsidian window starts closing, PodNotes starts no new writes and lets an in-flight write finish when Obsidian quits. +Once the Obsidian window starts closing, PodNotes starts no new writes. +When Obsidian quits, it lets an in-flight write finish. PodNotes reads the file back after each write to check that the saved data matches. A mismatch counts as a failed save. @@ -122,14 +126,14 @@ Older links can contain the original private URL and are not rewritten by the se If a non-empty `data.json` cannot be read or parsed, PodNotes leaves it unchanged and shows a persistent notice that saving has stopped. The notice includes the file path. If the file is unreadable at startup, PodNotes starts with default settings. -It accepts a replacement only if that file loads without repairs that could discard data. -When a readable file arrives during a session with a loaded library, invalid entries are not treated as deletions. +After an unreadable startup, a replacement must load without repairs before saving resumes. +When PodNotes already has a loaded library, entries dropped while reading a synced file do not count as deletions. PodNotes keeps their last known values while merging other changes. If a copy from an older data format arrives during a session, PodNotes stops saving and shows a notice asking you to restart Obsidian. Restarting runs the migration, including moving old API keys into secret storage. -An empty file counts as missing. At startup, it starts a new library. +An empty file counts as missing. At startup, PodNotes starts a new library. After a failed write leaves the file empty, the next save can write the data again, including changes merged from another device. PodNotes does not repair a non-empty, partly written file. @@ -137,7 +141,10 @@ PodNotes does not repair a non-empty, partly written file. 1. For an unreadable file, let sync finish. Check available disk space and file permissions if the notice remains. 2. Restore a readable backup of the file named in the notice if needed. PodNotes resumes saving when it reads a usable copy. + If the notice remains, restart Obsidian. 3. For an older-format notice, update PodNotes on every device, let sync finish, and restart Obsidian to migrate the file. If you want to discard the old library, back up the file, delete it, and restart Obsidian. -Deletion starts a new library. Changes made with saving disabled are not saved over the unreadable file. +Deletion starts a new library. +After an unreadable startup, PodNotes adopts the recovered library instead of merging changes made while saving was disabled. +If PodNotes had already loaded a library, it merges those changes with the recovered file. From ece3a9abf0f5a30c8d7f40e07f2f12697503cddf Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Sun, 11 Oct 2026 15:56:23 +0200 Subject: [PATCH 3/4] docs(sync): explain how separate libraries combine --- docs/src/content/docs/faq.md | 5 ++++- docs/src/content/docs/sync.md | 12 ++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/src/content/docs/faq.md b/docs/src/content/docs/faq.md index 3f4fe8dc..2f46b39c 100644 --- a/docs/src/content/docs/faq.md +++ b/docs/src/content/docs/faq.md @@ -95,6 +95,10 @@ See [Transcripts](/transcripts/). Saved progress, subscriptions, playlists, templates, and preferences can travel with PodNotes' `data.json` when your sync service includes plugin data. PodNotes merges changes from other devices before saving and updates its library when Obsidian reports a synced file change. + +When their `data.json` files identify separate libraries, PodNotes combines their podcasts, progress records, and playlists. +This also works when a new device starts before sync finishes. +PodNotes records the library's identity in `data.json` and keeps the identity of the library that started first. If both devices change the same progress record or feed, the device saving keeps its own version of that entry. Periodic playback checkpoints write at most once every 10 seconds. @@ -104,7 +108,6 @@ The loaded episode stays current on this device, and the player saves its own po Changes that arrive between the read and write can still be overwritten. Keep PodNotes updated on every device and let sync finish before switching. -On a new device, keep PodNotes disabled until its plugin data finishes syncing. API key values and protected private-feed URLs remain local to each device. If PodNotes stops saving and shows a notice, follow [Restore saving after a notice](/sync/#restore-saving-after-a-notice). See [Sync and devices](/sync/) for conflict and download limits. diff --git a/docs/src/content/docs/sync.md b/docs/src/content/docs/sync.md index 73a40445..e5a18d1a 100644 --- a/docs/src/content/docs/sync.md +++ b/docs/src/content/docs/sync.md @@ -11,6 +11,7 @@ Using the same library on several devices depends on the files your vault sync s PodNotes stores preferences and library state in `.obsidian/plugins/podnotes/data.json`. If you use a different Obsidian configuration folder, the path starts with that folder instead of `.obsidian`. +A `libraryId` in `data.json` records which library the file belongs to. The file contains the following data: @@ -30,11 +31,19 @@ The **Default Playback Rate** preference is saved. Saved progress provides a res ## Changes on two devices -Before each save, PodNotes reads `data.json` and compares it with the last loaded or saved copy and this device's changes. +Before each save, PodNotes reads `data.json`. +For files from the same library, it compares the file with the last loaded or saved copy and this device's changes. It merges changes to different entries, including subscriptions, progress, playlists, and preferences. For example, one device can add a podcast while another updates its playback progress. Once the subscription reaches the second device's `data.json`, its next save keeps both changes. + +When `data.json` files identify different libraries, PodNotes combines their podcasts, progress records, and playlists. +This includes a new device that starts PodNotes before its synced data arrives. +A setting changed from its default in only one library keeps that library's value. +The combined file keeps the identity of the library that started first. +If a podcast has different names in the two libraries, both names appear. + When Obsidian reports a synced file change, PodNotes updates its library without a restart. Sync does not switch an episode already loaded in the player or seek to another device's position. The loaded episode stays current on this device. @@ -55,7 +64,6 @@ A change that arrives between the read and write can still be overwritten. Sync can also see a partly written file because PodNotes writes `data.json` in place. An older PodNotes version on another device can overwrite the whole file. Keep PodNotes updated on every device and let sync finish before switching devices. -On a new device, keep PodNotes disabled until sync delivers `data.json`. Then enable it. ## When PodNotes saves From e3ce5c441d5ec2d89d886c7ab026eab812a67f99 Mon Sep 17 00:00:00 2001 From: Christian Bager Bach Houmann Date: Sun, 11 Oct 2026 16:04:58 +0200 Subject: [PATCH 4/4] docs(sync): clarify recovery when libraries combine --- docs/src/content/docs/faq.md | 7 ++++--- docs/src/content/docs/sync.md | 15 ++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/docs/src/content/docs/faq.md b/docs/src/content/docs/faq.md index 2f46b39c..6ade3619 100644 --- a/docs/src/content/docs/faq.md +++ b/docs/src/content/docs/faq.md @@ -96,9 +96,10 @@ See [Transcripts](/transcripts/). Saved progress, subscriptions, playlists, templates, and preferences can travel with PodNotes' `data.json` when your sync service includes plugin data. PodNotes merges changes from other devices before saving and updates its library when Obsidian reports a synced file change. -When their `data.json` files identify separate libraries, PodNotes combines their podcasts, progress records, and playlists. -This also works when a new device starts before sync finishes. -PodNotes records the library's identity in `data.json` and keeps the identity of the library that started first. +When `data.json` files identify different libraries, PodNotes combines their entries, including podcasts, progress records, and playlists. +A new device's library combines with the synced library even if PodNotes starts before sync delivers `data.json`. +PodNotes records which library a file belongs to with a `libraryId` in `data.json`. +The combined file keeps the `libraryId` of the library that started first. If both devices change the same progress record or feed, the device saving keeps its own version of that entry. Periodic playback checkpoints write at most once every 10 seconds. diff --git a/docs/src/content/docs/sync.md b/docs/src/content/docs/sync.md index e5a18d1a..4f70a470 100644 --- a/docs/src/content/docs/sync.md +++ b/docs/src/content/docs/sync.md @@ -38,11 +38,11 @@ It merges changes to different entries, including subscriptions, progress, playl For example, one device can add a podcast while another updates its playback progress. Once the subscription reaches the second device's `data.json`, its next save keeps both changes. -When `data.json` files identify different libraries, PodNotes combines their podcasts, progress records, and playlists. -This includes a new device that starts PodNotes before its synced data arrives. +When `data.json` files identify different libraries, PodNotes combines their entries, including podcasts, progress records, and playlists. +A new device's library combines with the synced library even if PodNotes starts before sync delivers `data.json`. A setting changed from its default in only one library keeps that library's value. -The combined file keeps the identity of the library that started first. -If a podcast has different names in the two libraries, both names appear. +The combined file keeps the `libraryId` of the library that started first. +If a podcast has different names in the two libraries, it appears twice, once under each name. When Obsidian reports a synced file change, PodNotes updates its library without a restart. Sync does not switch an episode already loaded in the player or seek to another device's position. @@ -152,7 +152,8 @@ PodNotes does not repair a non-empty, partly written file. If the notice remains, restart Obsidian. 3. For an older-format notice, update PodNotes on every device, let sync finish, and restart Obsidian to migrate the file. -If you want to discard the old library, back up the file, delete it, and restart Obsidian. -Deletion starts a new library. -After an unreadable startup, PodNotes adopts the recovered library instead of merging changes made while saving was disabled. +After an unreadable startup, PodNotes adopts the recovered library instead of merging changes made after saving stopped. If PodNotes had already loaded a library, it merges those changes with the recovered file. + +To start a new library on this device, back up `data.json`, delete it, and restart Obsidian. +Another device with the old library loaded combines it with the new library when the new file arrives.