/** * Desktop-only surfaces that have no web equivalent in V1 (ticket #13, lot F1): * the native folder picker, OS view-windows and the main↔detached focused-project * channel, plus SSH/WSL remote. On the web client these must fail with a clear, * explicit error rather than reaching for Tauri (which is absent). * * The B0 inventory classified these as `desktop-only`; F1 does NOT implement them * for web. If/when the product wants an equivalent (e.g. a server-side folder * browser to replace `pickFolder`), it gets its own lot. */ import type { GatewayError, Unsubscribe } from "@/domain"; import type { FocusedProject, FocusedProjectGateway, RemoteGateway, ViewWindowClosed, ViewWindowSnapshot, WindowGateway, } from "@/ports"; /** Throws a stable, explicit "unsupported on web" {@link GatewayError}. */ export function unsupportedOnWeb(what: string): never { const err: GatewayError = { code: "UNSUPPORTED_ON_WEB", message: `${what} is not available in the web client (desktop-only).`, }; throw err; } /** Web stub: OS view-windows are desktop-only (no `WebviewWindow` on the web). */ export class WebWindowGateway implements WindowGateway { openViewWindow(): Promise { return unsupportedOnWeb("Detaching a panel into an OS window"); } closeViewWindow(): Promise { return unsupportedOnWeb("Closing a detached OS window"); } listOpenViewWindows(): Promise { // Best-effort by contract (callers treat rejection as "no reconciliation"), // but there are simply never detached OS windows on web → empty list. return Promise.resolve([]); } onViewWindowClosed( _handler: (event: ViewWindowClosed) => void, ): Promise { // No OS windows ⇒ nothing ever fires; return a no-op unsubscribe. return Promise.resolve(() => {}); } } /** * Web stub for the focused-project channel. With no detached windows on web the * channel has no cross-window consumer; F1 keeps it inert (no publish, no focus). * A future multi-tab web build could back this with `BroadcastChannel`. */ export class WebFocusedProjectGateway implements FocusedProjectGateway { setFocusedProject(_project: FocusedProject | null): Promise { // No-op: nothing reads the channel on web V1. return Promise.resolve(); } getFocusedProject(): Promise { return Promise.resolve(null); } onFocusedProjectChanged( _handler: (project: FocusedProject | null) => void, ): Promise { return Promise.resolve(() => {}); } } /** Web stub: SSH/WSL remote connection is desktop-only in V1. */ export class WebRemoteGateway implements RemoteGateway { connect(): Promise { return unsupportedOnWeb("Remote (SSH/WSL) connection"); } }