bdf1f16e8bcf

fix: propagate mesh relay settings (v2.3.76)

time
2026-07-26 04:38 UTC · 3 months ago
machine
koh2
parent
cd7deee44786
5 files app/build.gradle+2 −2app/src/main/java/com/peachpasswords/sync/PairedDeviceStore.kt+13 −0app/src/main/java/com/peachpasswords/ui/settings/SettingsCardBodies.kt+4 −3app/src/main/java/com/peachpasswords/ui/sync/SyncViewModel.kt+3 −1app/src/test/java/com/peachpasswords/sync/RelaySettingsPropagationTest.kt+33 −0
app/build.gradle+2 −2
@@ -16,8 +16,8 @@1616         applicationId "com.peachpasswords"1717         minSdk 261818         targetSdk 3519-        versionCode 23750020-        versionName "2.3.75"19+        versionCode 23760020+        versionName "2.3.76"2121 2222         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"2323         vectorDrawables {

view file

app/src/main/java/com/peachpasswords/sync/PairedDeviceStore.kt+13 −0
@@ -94,6 +94,14 @@9494     }9595 9696     /**97+     * Reconnect prefers each pair's relay over the global fallback. Rewrite all98+     * established pairs when the user changes the mesh relay in Settings.99+     */100+    fun setRelayUrlForAll(relayUrl: String) {101+        persist(withRelayUrl(getAll(), relayUrl))102+    }103+104+    /**97105      * Observe the full list. EncryptedSharedPreferences supports98106      * OnSharedPreferenceChangeListener, so this emits on every persist —99107      * including writes from other components in-process.@@ -119,3 +127,8 @@119127         val json = Json { encodeDefaults = true; ignoreUnknownKeys = true }120128     }121129 }130+131+internal fun withRelayUrl(132+    devices: List<PairedDevice>,133+    relayUrl: String,134+): List<PairedDevice> = devices.map { it.copy(relayUrl = relayUrl) }

view file

app/src/main/java/com/peachpasswords/ui/settings/SettingsCardBodies.kt+4 −3
@@ -741,9 +741,10 @@741741     SubLabel("CONNECTION", fg)742742     RowLine(fg) {743743         Column(Modifier.weight(1f)) {744-            Text("LAN only", color = fg, fontFamily = PeachType.Body, fontSize = 13.sp)744+            Text("Use local network only (no relay)", color = fg, fontFamily = PeachType.Body, fontSize = 13.sp)745745             Text(746-                "Disable internet relay fallback. Nearby-device sync still works.",746+                "Sync will only work when your devices share the same local network. " +747+                    "It won't work over VPN or when your devices are in different locations.",747748                 color = fg.copy(alpha = 0.7f), fontFamily = PeachType.Body, fontSize = 11.sp, lineHeight = 16.sp,748749                 modifier = Modifier.padding(top = 2.dp),749750             )@@ -751,7 +752,7 @@751752         Toggle(lanOnly, fg) { syncVm.setLanOnly(it) }752753     }753754     Text(754-        "RELAY URL",755+        "MESH RELAY URL",755756         color = fg.copy(alpha = 0.6f),756757         fontFamily = PeachType.Mono,757758         fontSize = 8.sp,

view file

app/src/main/java/com/peachpasswords/ui/sync/SyncViewModel.kt+3 −1
@@ -71,7 +71,9 @@7171     }7272 7373     fun setRelayUrl(input: String): Boolean = runCatching {74-        _relayUrl.value = relaySettings.setRelayUrl(input)74+        val normalized = relaySettings.setRelayUrl(input)75+        deviceStore.setRelayUrlForAll(normalized)76+        _relayUrl.value = normalized7577     }.isSuccess7678 7779     fun setLanOnly(on: Boolean) {

view file

app/src/test/java/com/peachpasswords/sync/RelaySettingsPropagationTest.kt+33 −0
@@ -0,0 +1,33 @@1+package com.peachpasswords.sync2+3+import org.junit.Assert.assertEquals4+import org.junit.Test5+6+class RelaySettingsPropagationTest {7+    @Test8+    fun changing_mesh_relay_updates_every_existing_pair() {9+        val devices = listOf(10+            PairedDevice(11+                deviceId = "browser",12+                relayUrl = "wss://old-relay.example",13+                pairedAt = 1L,14+            ),15+            PairedDevice(16+                deviceId = "phone",17+                relayUrl = null,18+                pairedAt = 2L,19+            ),20+        )21+22+        val updated = withRelayUrl(devices, "wss://new-relay.example/base")23+24+        assertEquals(25+            listOf(26+                "wss://new-relay.example/base",27+                "wss://new-relay.example/base",28+            ),29+            updated.map { it.relayUrl },30+        )31+        assertEquals(listOf("browser", "phone"), updated.map { it.deviceId })32+    }33+}

view file