дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(workbench): Open files from Finder in the single-file window (#152)
On macOS, OpenIDEA is now listed under Finder's Open With for text and source files and for folders. It never becomes the default app for any of them: all document types are declared with rank Alternate, and only in tauri.macos.conf.json, so Windows and Linux installers register nothing. Files opened from Finder, the Dock or a second instance share one routing path (plan_open). A file inside a local project that is already open, or still opening, goes to that project's window, choosing the deepest root when projects are nested. Any other file goes to the existing single-file window, or to a new one. A folder focuses the window that already has it open, otherwise it opens as a project. Paths that arrive before setup are queued and opened with the first launch. The single-file window now closes with its last tab, restores its files the next time it opens, and only offers Open File and drop hints when empty. Also fixes a regression: reopening projects on startup no longer replaces a file opened at cold start. Refs #128
Цей коміт міститься в:
1 джерело
2d7726cf53
коміт
1d383e608c
12 files changed
+581
-42
No files matched your search
@@ -65,6 +65,25 @@ describe("EditorController", () => {
|
||||
expect(openFilePaths(useTabs.getState())).toEqual(["/p/a.ts", "/p/b.ts"]);
|
||||
});
|
||||
|
||||
it("reopens the LightEdit files the next time a window switches to LightEdit", async () => {
|
||||
ctrl = new EditorController(createMemoryBackend({ "/x/a.txt": "a", "/y/b.md": "b" }));
|
||||
ctrl.start();
|
||||
useProject.setState({ lightEdit: true });
|
||||
await ctrl.openFile("/x/a.txt", { focus: false });
|
||||
await ctrl.openFile("/y/b.md", { focus: false });
|
||||
// The LightEdit window closes with its tabs open.
|
||||
useProject.setState({ lightEdit: false });
|
||||
expect(openFilePaths(useTabs.getState())).toEqual([]);
|
||||
useProject.setState({ lightEdit: true });
|
||||
expect(openFilePaths(useTabs.getState())).toEqual(["/x/a.txt", "/y/b.md"]);
|
||||
// Closing every tab leaves nothing to reopen.
|
||||
ctrl.closeEverything();
|
||||
useProject.setState({ lightEdit: false });
|
||||
useProject.setState({ lightEdit: true });
|
||||
expect(openFilePaths(useTabs.getState())).toEqual([]);
|
||||
useProject.setState({ lightEdit: false });
|
||||
});
|
||||
|
||||
it("closes a tab by its input key", async () => {
|
||||
ctrl = new EditorController(createMemoryBackend());
|
||||
ctrl.start();
|
||||
|
||||
@@ -102,6 +102,9 @@ export function isTextInput(input: EditorInput): input is EditorInput & { path:
|
||||
|
||||
export const useTabs = create<TabsState>(() => initialTabsState());
|
||||
|
||||
/** Session key of the LightEdit window: its tabs reopen the next time a window switches to LightEdit. */
|
||||
export const LIGHT_EDIT_SESSION = "<lightEdit>";
|
||||
|
||||
export interface EditorStatus {
|
||||
path: string;
|
||||
doc: number;
|
||||
@@ -179,7 +182,7 @@ export class EditorController implements SlotHost {
|
||||
activeSlot: EditorSlot | null = null;
|
||||
private statusScheduled = false;
|
||||
private disposers: Array<() => void> = [];
|
||||
/** Project root whose editor session is being tracked (null while switching). */
|
||||
/** Project root (or {@link LIGHT_EDIT_SESSION}) whose editor session is being tracked (null while switching). */
|
||||
private sessionRoot: string | null = null;
|
||||
private sessionTimer: ReturnType<typeof setTimeout> | undefined;
|
||||
/** Restored caret / scroll per path, applied when the file's first slot is created. */
|
||||
@@ -237,6 +240,7 @@ export class EditorController implements SlotHost {
|
||||
this.nav.clear();
|
||||
this.edits.clear();
|
||||
if (root) this.restoreSession(root);
|
||||
else if (s.lightEdit) this.restoreSession(LIGHT_EDIT_SESSION);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in new issue
Заблокувати користувача