From fa741364cf543cf12afa488f4f145ffbf5d39528 Mon Sep 17 00:00:00 2001 From: dragon Date: Thu, 15 Oct 2026 11:10:17 +0800 Subject: [PATCH 1/2] Forget the box's Wi-Fi address while it joins again or fails A failed join on the network it was last joined to kept the old address, and joining again showed it as joined until the new attempt ended. Found in the #137 hardware acceptance run. Co-Authored-By: Claude Opus 5.5 --- daemon/src/status.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/daemon/src/status.rs b/daemon/src/status.rs index 0f47c58..be96ee6 100644 --- a/daemon/src/status.rs +++ b/daemon/src/status.rs @@ -212,7 +212,11 @@ impl DeviceState { self.wifi_network = None; self.wifi_address = None; self.wifi_error = None; + } else if line.starts_with("WIFI CONNECTING ") { + // Joining again, say with a new password for the same network: the last join's address is gone. + self.wifi_address = None; } else if let Some(why) = line.strip_prefix("WIFI FAILED ") { + self.wifi_address = None; self.wifi_error = Some(wifi_failure(why.trim())); } else if line.trim() == "WIFI CONNECTED" { self.wifi_error = None; @@ -480,6 +484,19 @@ mod tests { assert_eq!(state.wifi_address, None); } + #[test] + fn joining_the_same_network_again_forgets_the_last_address() { + let mut state = DeviceState::default(); + state.apply(&line("WIFI NETWORK Home")); + state.apply(&line("WIFI ADDRESS 192.168.1.23")); + state.apply(&line("WIFI NETWORK Home")); + state.apply(&line("WIFI CONNECTING Home")); + assert_eq!(state.wifi_address, None, "not joined while it tries again"); + state.apply(&line("WIFI ADDRESS 192.168.1.23")); + state.apply(&line("WIFI FAILED AuthenticationExpired")); + assert_eq!((state.wifi_address, state.wifi_error.as_deref()), (None, Some("wrong_password"))); + } + #[test] fn a_box_reached_over_the_local_network_is_joined_there() { let mut state = DeviceState::default(); From b93bb7c7c8d70aa95facfe83343cfd412aed13ed Mon Sep 17 00:00:00 2001 From: dragon Date: Thu, 15 Oct 2026 11:10:17 +0800 Subject: [PATCH 2/2] Say the paired computers need the cable, on Mac and Linux The box lists them over the cable only, so over Wi-Fi or the Relay the Device tab showed an empty list. Found in the #137 hardware acceptance run. Co-Authored-By: Claude Opus 5.5 --- app/Localization/zh-Hans.lproj/Localizable.strings | 1 + app/Sources/VibeBuddy/SettingsView.swift | 4 ++++ desktop/src/main.rs | 3 +++ 3 files changed, 8 insertions(+) diff --git a/app/Localization/zh-Hans.lproj/Localizable.strings b/app/Localization/zh-Hans.lproj/Localizable.strings index 5c75fc0..aeb5af6 100644 --- a/app/Localization/zh-Hans.lproj/Localizable.strings +++ b/app/Localization/zh-Hans.lproj/Localizable.strings @@ -281,6 +281,7 @@ "Not set" = "未设置"; "Plug in the cable to change the box's network." = "要更换盒子的网络,请插上数据线。"; "Plug in the cable to update the box's firmware." = "要更新盒子的固件,请插上数据线。"; +"Plug in the cable to see the paired computers." = "插上数据线才能看到已配对的电脑。"; "Network name" = "网络名称"; "Password" = "密码"; "Join" = "加入"; diff --git a/app/Sources/VibeBuddy/SettingsView.swift b/app/Sources/VibeBuddy/SettingsView.swift index b6a1a69..a0dbcb1 100644 --- a/app/Sources/VibeBuddy/SettingsView.swift +++ b/app/Sources/VibeBuddy/SettingsView.swift @@ -505,6 +505,10 @@ struct PairedComputersSection: View { var body: some View { Section { + // The box lists them over the cable only (ERROR cable_only otherwise), so the list would be empty. + if device.network == true { + Text("Plug in the cable to see the paired computers.").foregroundStyle(.secondary) + } ForEach(device.pairedComputers ?? []) { computer in LabeledContent(computer.name.isEmpty ? String(localized: "Unnamed computer") : computer.name) { if computer.key == device.computerKey { diff --git a/desktop/src/main.rs b/desktop/src/main.rs index f537424..082339d 100644 --- a/desktop/src/main.rs +++ b/desktop/src/main.rs @@ -1421,8 +1421,11 @@ impl App { }; row![text(name).size(13), space::horizontal(), action].spacing(12).into() }); + // The box lists them over the cable only (ERROR cable_only otherwise), so the list would be empty. + let unlisted = device.network.then(|| text(tr("Plug in the cable to see the paired computers.", &[])).size(13)); column![text(tr("Paired computers", &[]))] .extend(rows) + .push(unlisted) .push( text(tr("A computer pairs with the box when it's plugged in. To forget them all, use COMPUTERS in the box's menu.", &[])) .size(13),