fix(app): preserve renamed host labels (#1940)

Daemon-advertised hostnames still name new/default hosts, but connection refreshes and re-pairing no longer overwrite labels that users already changed.
This commit is contained in:
Mohamed Boudra
2026-07-08 10:20:06 +00:00
committed by GitHub
parent 5ec7ef9771
commit ed67e6e0f1
2 changed files with 39 additions and 3 deletions
+38 -2
View File
@@ -1775,6 +1775,41 @@ describe("HostRuntimeStore", () => {
store.syncHosts([]); store.syncHosts([]);
}); });
it("preserves a manual host rename when desktop status re-advertises the daemon hostname", async () => {
const advertisedHostname = "macbook-pro.local";
const store = new HostRuntimeStore({
deps: {
createClient: () => new FakeDaemonClient() as unknown as DaemonClient,
connectToDaemon: async ({ host }) => ({
client: makeConnectedProbeClient(5) as unknown as DaemonClient,
serverId: host.serverId,
hostname: advertisedHostname,
}),
getClientId: async () => "cid_test_runtime",
},
storage: createMemoryHostRuntimeStorage(),
});
try {
await store.upsertConnectionFromListen({
listenAddress: "127.0.0.1:6767",
serverId: "srv_desktop",
hostname: advertisedHostname,
});
await store.renameHost("srv_desktop", "mac-dev");
await store.upsertConnectionFromListen({
listenAddress: "127.0.0.1:6767",
serverId: "srv_desktop",
hostname: advertisedHostname,
});
expect(store.getHosts().find((h) => h.serverId === "srv_desktop")?.label).toBe("mac-dev");
} finally {
store.syncHosts([]);
}
});
it("upsertDirectConnection stores SSL and password settings", async () => { it("upsertDirectConnection stores SSL and password settings", async () => {
const store = new HostRuntimeStore({ const store = new HostRuntimeStore({
deps: { deps: {
@@ -1982,7 +2017,7 @@ describe("HostRuntimeStore", () => {
store.syncHosts([]); store.syncHosts([]);
}); });
it("uses the latest advertised hostname when re-pairing an existing relay host", async () => { it("preserves the existing host label when re-pairing an existing relay host", async () => {
const store = new HostRuntimeStore({ const store = new HostRuntimeStore({
deps: { deps: {
createClient: () => new FakeDaemonClient() as unknown as DaemonClient, createClient: () => new FakeDaemonClient() as unknown as DaemonClient,
@@ -1993,6 +2028,7 @@ describe("HostRuntimeStore", () => {
}), }),
getClientId: async () => "cid_test_runtime", getClientId: async () => "cid_test_runtime",
}, },
storage: createMemoryHostRuntimeStorage(),
}); });
await store.upsertRelayConnection({ await store.upsertRelayConnection({
@@ -2005,7 +2041,7 @@ describe("HostRuntimeStore", () => {
await store.upsertConnectionFromOffer(makeOffer(), "mbp"); await store.upsertConnectionFromOffer(makeOffer(), "mbp");
const pairedHost = store.getHosts().find((host) => host.serverId === "srv_offer"); const pairedHost = store.getHosts().find((host) => host.serverId === "srv_offer");
expect(pairedHost?.label).toBe("mbp"); expect(pairedHost?.label).toBe("Custom name");
store.syncHosts([]); store.syncHosts([]);
}); });
+1 -1
View File
@@ -165,7 +165,7 @@ export function upsertHostConnectionInProfiles(input: {
input.connection, input.connection,
]); ]);
const nextLifecycle = prev.lifecycle; const nextLifecycle = prev.lifecycle;
const nextLabel = labelTrimmed || (prev.label === prev.serverId ? derivedLabel : prev.label); const nextLabel = prev.label === prev.serverId ? derivedLabel : prev.label;
const nextPreferredConnectionId = const nextPreferredConnectionId =
prev.preferredConnectionId && prev.preferredConnectionId &&
nextConnections.some((connection) => connection.id === prev.preferredConnectionId) nextConnections.some((connection) => connection.id === prev.preferredConnectionId)