дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
fix(remote): keep auxiliary windows' remote routing when they hold no project (#1975)
A comparison window (Git Log > Compare with Local) of a remote project rides its parent's session: remote_current answers with the parent's connection, so its commands go to the host where the project is open. But the window never opens a project of its own — it keeps only the settings (restoring the project would overwrite the main window's editor session) — and the useProject subscription read every settings update as 'the window left the remote project', dropping the routing. The next commands then ran on the desktop, where no project is open for the window: Git Log > Compare with Local on a WSL project opened an empty comparison window with 'IpcError: no project is open in this window' (same for SSH remote projects). The subscription now only ends the session when the window's project actually leaves the session's root: it had the session's project open and now holds none or another one. Opening a local project, LightEdit and Close Project still end the routing (open_project / light_edit_open / close_project route locally and end it themselves; closeProject keeps the subscription as its safety net).
Цей коміт міститься в:
1 джерело
2945d20208
коміт
619daa1489
2 files changed
+59
-3
No files matched your search
@@ -1,5 +1,8 @@
|
||||
import { Channel } from "@tauri-apps/api/core";
|
||||
import { beforeAll, describe, expect, it } from "vitest";
|
||||
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
||||
import type { ProjectInfo, Settings } from "./ipc";
|
||||
import { useProject } from "./project";
|
||||
import { disableRemote, enableRemote, useRemote } from "./remote";
|
||||
import { encodeArgs, remoteRouting } from "./remote";
|
||||
|
||||
describe("remote invoke", () => {
|
||||
@@ -42,3 +45,48 @@ describe("remote invoke", () => {
|
||||
expect(encodeArgs(undefined).json).toBe("{}");
|
||||
});
|
||||
});
|
||||
|
||||
describe("remote session lifetime", () => {
|
||||
const session = {
|
||||
target: { kind: "wsl" as const, distro: "Ubuntu" },
|
||||
root: "/home/me/app",
|
||||
host: "Ubuntu",
|
||||
os: "linux",
|
||||
commands: ["vcs_roots"],
|
||||
};
|
||||
const project = {
|
||||
name: "app",
|
||||
root: "/home/me/app",
|
||||
trusted: true,
|
||||
isGit: true,
|
||||
settings: {},
|
||||
} as unknown as ProjectInfo;
|
||||
|
||||
afterEach(() => {
|
||||
disableRemote();
|
||||
useProject.setState({ project: null, settings: null, opening: false, openingPath: null, lightEdit: false });
|
||||
});
|
||||
|
||||
it("keeps routing when a window with no project of its own updates the settings only", () => {
|
||||
// The comparison window: it rides its parent's session and keeps just the settings
|
||||
// (restoring the project would overwrite the main window's editor session).
|
||||
enableRemote(session);
|
||||
useProject.setState({ settings: { editor: { fontSize: 12 } } as unknown as Settings });
|
||||
expect(useRemote.getState().session).not.toBeNull();
|
||||
});
|
||||
|
||||
it("ends routing when the window's project leaves the session's root", () => {
|
||||
enableRemote(session);
|
||||
useProject.setState({ project });
|
||||
// Close Project (or a local project opened over the remote one) — the session goes.
|
||||
useProject.setState({ project: null });
|
||||
expect(useRemote.getState().session).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps routing while the project still sits at the session's root", () => {
|
||||
enableRemote(session);
|
||||
useProject.setState({ project });
|
||||
useProject.setState({ settings: { editor: { fontSize: 14 } } as unknown as Settings });
|
||||
expect(useRemote.getState().session).not.toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -338,7 +338,15 @@ export function forgetRemote(target: RemoteTarget, path: string) {
|
||||
}
|
||||
|
||||
// Any way of leaving the remote project (Close Project, opening a local one) ends remote routing.
|
||||
useProject.subscribe((s) => {
|
||||
useProject.subscribe((s, prev) => {
|
||||
const session = useRemote.getState().session;
|
||||
if (session && !s.opening && s.project?.root !== session.root) disableRemote();
|
||||
if (!session || s.opening) return;
|
||||
// Only a window whose project was the session's root can leave it. Auxiliary windows
|
||||
// (comparison, deployment) hold no project of their own — they ride their parent's
|
||||
// session, and a settings-only update (the comparison window keeps just the settings)
|
||||
// must not drop the routing: its next commands would run here instead of on the host,
|
||||
// where no project is open (`open_project` / `light_edit_open` / `close_project` end
|
||||
// the session themselves, see `route`).
|
||||
if (prev.project?.root !== session.root || s.project?.root === session.root) return;
|
||||
disableRemote();
|
||||
});
|
||||
Reference in new issue
Заблокувати користувача