/** * Tauri adapter for {@link FocusedProjectGateway} (ticket #47). Bridges the * main-window ⇄ detached-panel focused-project channel to the backend commands * and event. Like the sibling adapters, this is the only layer allowed to touch * `@tauri-apps/api`; components reach it exclusively through the port. * * Command/event names and payloads mirror the backend contract owned by * DevBackend: `set_focused_project` / `get_focused_project` and the * `focused-project://changed` event whose payload is `{ project: FocusedProject * | null }`. */ import { invoke } from "@tauri-apps/api/core"; import { listen } from "@tauri-apps/api/event"; import type { Unsubscribe } from "@/domain"; import type { FocusedProject, FocusedProjectGateway } from "@/ports"; /** The Tauri event carrying focused-project transitions. */ const FOCUSED_PROJECT_CHANGED = "focused-project://changed"; /** Backend payload for `focused-project://changed`. */ interface FocusedProjectChanged { project: FocusedProject | null; } export class TauriFocusedProjectGateway implements FocusedProjectGateway { async setFocusedProject(project: FocusedProject | null): Promise { // The backend command takes `project: Option`; `null` // clears the focus (no project open). await invoke("set_focused_project", { project }); } async getFocusedProject(): Promise { const project = await invoke("get_focused_project"); return project ?? null; } async onFocusedProjectChanged( handler: (project: FocusedProject | null) => void, ): Promise { const unlisten = await listen( FOCUSED_PROJECT_CHANGED, (e) => handler(e.payload.project ?? null), ); return unlisten; } }