From b1937535b5749b901f44863016ccee5ee6778629 Mon Sep 17 00:00:00 2001 From: MrBeldum <157205701+MrBeldum@users.noreply.github.com> Date: Fri, 2 Oct 2026 08:33:56 -0700 Subject: [PATCH] Register the LatchStream service when setup moves an older engine Setup builds its plan from whether an engine is up, and an engine in the folder 4.0 used is up, so the plan skipped the engine step. The retire step had by then moved the folder and deleted BroLinkStream, and nothing registered LatchStream: the engine would have run only once someone signed in. An engine in the old folder now counts as needing the step. Version 4.1.1. Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 8 ++++++++ Cargo.lock | 10 +++++----- Cargo.toml | 2 +- crates/client/src/stream.rs | 2 +- crates/host/src/app.rs | 7 +++++-- crates/host/src/setup.rs | 3 ++- crates/host/src/streamer.rs | 23 ++++++++++++++++++++++- 7 files changed, 44 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10b5637..d430318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ The release workflow publishes the section that matches the tag as the GitHub release notes, so each version gets a heading of the form `## X.Y.Z (date)`. +## 4.1.1 (2026-10-02) + +- Setting up a Windows PC that an earlier version had set up (when the + app was called BroLink) now registers the `LatchStream` service. Setup + moved the engine's folder and removed the old service, but treated the + running engine as needing nothing more, so the new service was never + registered and the engine ran only once someone had signed in. + ## 4.1.0 (2026-10-02) - **BroLink is now Latch, by Bardbro.** The app, the repository diff --git a/Cargo.lock b/Cargo.lock index 195261e..a5c05c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2114,7 +2114,7 @@ dependencies = [ [[package]] name = "latch-client" -version = "4.1.0" +version = "4.1.1" dependencies = [ "anyhow", "eframe", @@ -2137,7 +2137,7 @@ dependencies = [ [[package]] name = "latch-core" -version = "4.1.0" +version = "4.1.1" dependencies = [ "anyhow", "directories", @@ -2155,7 +2155,7 @@ dependencies = [ [[package]] name = "latch-host" -version = "4.1.0" +version = "4.1.1" dependencies = [ "anyhow", "arboard", @@ -2180,7 +2180,7 @@ dependencies = [ [[package]] name = "latch-stream" -version = "4.1.0" +version = "4.1.1" dependencies = [ "aes", "aes-gcm", @@ -2203,7 +2203,7 @@ dependencies = [ [[package]] name = "latch-ui" -version = "4.1.0" +version = "4.1.1" dependencies = [ "egui", "latch-core", diff --git a/Cargo.toml b/Cargo.toml index d37bdff..ddee38c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ ] [workspace.package] -version = "4.1.0" +version = "4.1.1" edition = "2021" license = "GPL-3.0-or-later" authors = ["Latch Contributors"] diff --git a/crates/client/src/stream.rs b/crates/client/src/stream.rs index 047c7cd..6d5d416 100644 --- a/crates/client/src/stream.rs +++ b/crates/client/src/stream.rs @@ -2105,7 +2105,7 @@ pub(crate) mod tests { v }, Extra { - handover: Some("Installing Latch Host 4.1.0 on Gaming-PC: waiting for it to fetch the file…".into()), + handover: Some("Installing Latch Host 4.1.1 on Gaming-PC: waiting for it to fetch the file…".into()), ..windows() }, None, diff --git a/crates/host/src/app.rs b/crates/host/src/app.rs index 7b1d24c..fbabb86 100644 --- a/crates/host/src/app.rs +++ b/crates/host/src/app.rs @@ -213,7 +213,10 @@ impl HostApp { } let cfg = self.cfg.clone(); let ctx = ctx.clone(); - let install_engine = !status.streamer.installed || migrate || !status.streamer.running; + let install_engine = !status.streamer.installed + || migrate + || !status.streamer.running + || crate::streamer::find().is_some_and(|i| crate::streamer::in_old_folder(&i)); let adapter = status.wake_adapter.clone(); let desc = status.wake_adapter_description.clone(); std::thread::spawn(move || { @@ -1249,7 +1252,7 @@ mod snapshots { }), setup: vec![], log: vec![ - "Latch 4.1.0 listening on TCP 47850".into(), + "Latch 4.1.1 listening on TCP 47850".into(), "listening for wake packets on UDP 9".into(), "Tailscale up as user@example.com (100.64.0.10)".into(), "the streaming engine is running and Latch is signed in".into(), diff --git a/crates/host/src/setup.rs b/crates/host/src/setup.rs index d75adb4..59863cd 100644 --- a/crates/host/src/setup.rs +++ b/crates/host/src/setup.rs @@ -692,9 +692,10 @@ pub fn run_as_admin() -> Result<()> { let kind = install.as_ref().map(|i| i.kind).unwrap_or(""); let migrate = crate::migrate::uses_old_engine(kind); let running = install.is_some() && crate::streamer::running(); + let old_folder = install.as_ref().is_some_and(crate::streamer::in_old_folder); let plan = Plan { exe: &exe, - install_engine: install.is_none() || migrate || !running, + install_engine: install.is_none() || migrate || !running || old_folder, migrate, dry_run: false, sunshine_user: &cfg.sunshine_user, diff --git a/crates/host/src/streamer.rs b/crates/host/src/streamer.rs index 690c506..d90ef5c 100644 --- a/crates/host/src/streamer.rs +++ b/crates/host/src/streamer.rs @@ -6,7 +6,7 @@ use anyhow::{bail, Context, Result}; use latch_core::{SUNSHINE_PORT, SUNSHINE_WEB_PORT}; use std::net::{SocketAddr, TcpStream}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; use std::time::Duration; @@ -25,6 +25,13 @@ pub const INSTALL_DIRS: [(&str, &str); 4] = [ ("Apollo", r"C:\Program Files\Apollo"), ]; +/// Whether `install` is the engine in the folder an earlier version used. +/// Setup moves it to [`ENGINE_DIR`] and registers the service under its new +/// name, so it has to run the engine step even though an engine is up. +pub fn in_old_folder(install: &Install) -> bool { + install.dir.as_path() == Path::new(crate::legacy::WINDOWS_ENGINE_DIR) +} + /// GitHub repository the setup script fetches the engine archive from. pub const REPO: &str = "LizardByte/Sunshine"; @@ -580,6 +587,20 @@ mod tests { let _ = SUNSHINE_PORT; } + #[test] + fn an_engine_in_the_old_folder_is_recognised_so_setup_moves_it() { + let old = Install { + kind: "Latch", + dir: PathBuf::from(crate::legacy::WINDOWS_ENGINE_DIR), + }; + let new = Install { + kind: "Latch", + dir: PathBuf::from(ENGINE_DIR), + }; + assert!(in_old_folder(&old)); + assert!(!in_old_folder(&new)); + } + #[test] fn session_listed_reads_current_app_and_running_flags() { assert!(!session_listed(&serde_json::json!({"apps": []})));