From 4f7a6b7ae9ccabcc0b8248db6edbc7142fc04af6 Mon Sep 17 00:00:00 2001
From: vorotamoroz
Date: Fri, 23 Oct 2026 16:32:12 +0000
Subject: [PATCH] Explain compatibility costs in device review
---
docs/settings.md | 2 +-
src/common/messages/LiveSyncProvisionalMessages.ts | 10 ++++++----
.../LiveSyncUI/dialogues/JoinedDevicesDialog.svelte | 5 +++++
src/serviceFeatures/useJoinedDevices.ts | 4 ++--
test/e2e-obsidian/scripts/joined-devices.ts | 9 ++++++++-
updates.md | 2 +-
6 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/docs/settings.md b/docs/settings.md
index 1a81032c..330815e1 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -240,7 +240,7 @@ Choose **Review devices** under **Joined devices** to read the device records on
The list shows each device ID, recorded platform, plug-in version, app version, and last recorded connection time. Older clients may have incomplete information. These records do not establish whether a device is online. On a locked remote, a device outside the accepted list is shown as **Locked out**.
-Before synchronisation starts, and when this dialogue refreshes, Self-hosted LiveSync checks for recorded plug-in versions newer or older than its own. These Notices are advisory and do not stop synchronisation. Unknown development version labels are left unclassified. Automatic checks run at most once per minute when synchronisation starts; they do not poll a continuously running connection.
+Before synchronisation starts, and when this dialogue refreshes, Self-hosted LiveSync checks for recorded plug-in versions newer or older than its own. These Notices recommend reviewing and aligning plug-in versions across devices; they are advisory and do not stop synchronisation. The dialogue explains that even compatible versions can reduce Chunk reuse and increase storage use when files are rewritten, while preserving file contents. P2P synchronisation may also be unavailable between incompatible versions. Unknown development version labels are left unclassified. Automatic checks run at most once per minute when synchronisation starts; they do not poll a continuously running connection.
**Forget device** removes another device's participation records after confirmation. It preserves the remote lock state and every other device. It does not delete Vault files or revoke credentials. A device can register again on an unlocked remote; on a locked remote, the existing recovery process applies. The result is checked after saving to CouchDB; if it cannot be confirmed, refresh the list and try again. CouchDB stores these records together in a local document which does not reject simultaneous updates, so changes from other devices can be overwritten. Pausing synchronisation on the other devices avoids that overlap. Object Storage uses conditional updates; if the server cannot support them, the record is retained.
diff --git a/src/common/messages/LiveSyncProvisionalMessages.ts b/src/common/messages/LiveSyncProvisionalMessages.ts
index 054bb7ba..40dd3d34 100644
--- a/src/common/messages/LiveSyncProvisionalMessages.ts
+++ b/src/common/messages/LiveSyncProvisionalMessages.ts
@@ -42,10 +42,10 @@ export const liveSyncProvisionalEnglishMessages = {
Refresh: "Refresh",
"Plug-in version": "Plug-in version",
Platform: "Platform",
- "An older plug-in version was detected in other device records: ${versions}. We recommend checking whether those devices need updating.":
- "An older plug-in version was detected in other device records: ${versions}. We recommend checking whether those devices need updating.",
- "A newer plug-in version was detected in other device records: ${versions}. We recommend checking whether this device needs updating.":
- "A newer plug-in version was detected in other device records: ${versions}. We recommend checking whether this device needs updating.",
+ "An older plug-in version was detected in other device records: ${versions}. Reviewing and aligning the plug-in versions across devices is recommended.":
+ "An older plug-in version was detected in other device records: ${versions}. Reviewing and aligning the plug-in versions across devices is recommended.",
+ "A newer plug-in version was detected in other device records: ${versions}. Reviewing and aligning the plug-in versions across devices is recommended.":
+ "A newer plug-in version was detected in other device records: ${versions}. Reviewing and aligning the plug-in versions across devices is recommended.",
Open: "Open",
"Not recorded": "Not recorded",
"Not accepted": "Not accepted",
@@ -59,6 +59,8 @@ export const liveSyncProvisionalEnglishMessages = {
"Joined devices are available after database startup with an active CouchDB or Object Storage connection.",
"Joined devices": "Joined devices",
"Review devices": "Review devices",
+ "Even compatible plug-in versions can create different Chunks for the same file. When files are rewritten, this can reduce Chunk reuse and increase storage use while preserving file contents. P2P synchronisation may also be unavailable between incompatible versions. Reviewing and aligning the plug-in versions across devices is recommended.":
+ "Even compatible plug-in versions can create different Chunks for the same file. When files are rewritten, this can reduce Chunk reuse and increase storage use while preserving file contents. P2P synchronisation may also be unavailable between incompatible versions. Reviewing and aligning the plug-in versions across devices is recommended.",
"Forgetting…": "Forgetting…",
"Forgetting the record does not delete Vault files or revoke credentials.":
"Forgetting the record does not delete Vault files or revoke credentials.",
diff --git a/src/modules/services/LiveSyncUI/dialogues/JoinedDevicesDialog.svelte b/src/modules/services/LiveSyncUI/dialogues/JoinedDevicesDialog.svelte
index 91c54b0f..67b5a04f 100644
--- a/src/modules/services/LiveSyncUI/dialogues/JoinedDevicesDialog.svelte
+++ b/src/modules/services/LiveSyncUI/dialogues/JoinedDevicesDialog.svelte
@@ -2,6 +2,7 @@
import { onDestroy, onMount } from "svelte";
import type { GuestDialogProps } from "@/modules/services/LiveSyncUI/svelteDialog";
import DialogHeader from "@/modules/services/LiveSyncUI/components/DialogHeader.svelte";
+ import InfoNote from "@/modules/services/LiveSyncUI/components/InfoNote.svelte";
import { $msg as translate } from "@/common/translation";
import type {
JoinedDeviceRow,
@@ -121,6 +122,10 @@
{translate("This list shows device information recorded by the remote. It does not show whether a device is online now.")}
+
+
{#if view}
{#if !view.milestonePresent}
{translate("This remote does not currently have a record of joined devices.")}
diff --git a/src/serviceFeatures/useJoinedDevices.ts b/src/serviceFeatures/useJoinedDevices.ts
index c5fcc759..424f5ce9 100644
--- a/src/serviceFeatures/useJoinedDevices.ts
+++ b/src/serviceFeatures/useJoinedDevices.ts
@@ -63,13 +63,13 @@ export function useJoinedDevicesFeature(host: JoinedDevicesHost, notices: Obsidi
message:
direction === "newer"
? $msg(
- "A newer plug-in version was detected in other device records: ${versions}. We recommend checking whether this device needs updating.",
+ "A newer plug-in version was detected in other device records: ${versions}. Reviewing and aligning the plug-in versions across devices is recommended.",
{
versions: versions.join(", "),
}
)
: $msg(
- "An older plug-in version was detected in other device records: ${versions}. We recommend checking whether those devices need updating.",
+ "An older plug-in version was detected in other device records: ${versions}. Reviewing and aligning the plug-in versions across devices is recommended.",
{
versions: versions.join(", "),
}
diff --git a/test/e2e-obsidian/scripts/joined-devices.ts b/test/e2e-obsidian/scripts/joined-devices.ts
index 15d496e8..9cca9011 100644
--- a/test/e2e-obsidian/scripts/joined-devices.ts
+++ b/test/e2e-obsidian/scripts/joined-devices.ts
@@ -213,6 +213,13 @@ async function assertInitialDialogue(dialogue: Locator, self: SelfDeviceInfo, pa
{ exact: true }
)
.waitFor({ state: "visible", timeout: uiTimeoutMs });
+ await dialogue
+ .locator(".sls-info-note")
+ .getByText(
+ "Even compatible plug-in versions can create different Chunks for the same file. When files are rewritten, this can reduce Chunk reuse and increase storage use while preserving file contents. P2P synchronisation may also be unavailable between incompatible versions. Reviewing and aligning the plug-in versions across devices is recommended.",
+ { exact: true }
+ )
+ .waitFor({ state: "visible", timeout: uiTimeoutMs });
await dialogue
.getByText("This remote is locked.", { exact: false })
.waitFor({ state: "visible", timeout: uiTimeoutMs });
@@ -409,7 +416,7 @@ async function main(): Promise {
await dialoguePage
.locator(".notice")
.getByText(
- "A newer plug-in version was detected in other device records: 999.0.0. We recommend checking whether this device needs updating.",
+ "A newer plug-in version was detected in other device records: 999.0.0. Reviewing and aligning the plug-in versions across devices is recommended.",
{ exact: true }
)
.waitFor({ state: "visible", timeout: uiTimeoutMs });
diff --git a/updates.md b/updates.md
index 534eac87..161bb640 100644
--- a/updates.md
+++ b/updates.md
@@ -29,7 +29,7 @@ Earlier releases remain available in the 1.0 release history, the 1.0 preview hi
- We can choose **Review devices** in Remote Configuration, the command palette, or a version Notice to review participating devices.
- Our device appears first, with its lockout state. Other records show the platform, plug-in version, app version, and last recorded connection time when available.
- - Advisory Notices highlight newer or older plug-in versions detected in device records and help us check which devices may need updating.
+ - Advisory Notices highlight newer or older plug-in versions detected in device records and recommend reviewing and aligning our versions. The dialogue explains possible storage costs and P2P compatibility limits.
- We can forget records belonging to lost or retired devices while preserving the remote lock state and other devices.
- Forgetting a record does not delete Vault files or revoke credentials. A returning device can register again on an unlocked remote.