import { ipcRenderer } from 'electron' import type { AppIdentity } from '../../shared/app-identity' import type { MacosUpgradeSupport } from '../../shared/macos-upgrade-support' import type { FloatingTerminalCwdRequest } from '../../shared/ui-chrome-types' import type { MacCapturedDigitRowChord } from '../../shared/macos-symbolic-hotkeys' import type { MarkdownDocument } from '../../shared/file-listing/file-document' import type { WriteTerminalRenderDesyncEvidenceArgs } from '../../shared/terminal/diagnostics/terminal-render-desync-evidence' import { KEYBOARD_LAYOUT_CHANGED_CHANNEL, type KeyboardLayoutChangeEvent } from '../../shared/keyboard-layout-events' import { prepareAndInvokeAppRestart } from '../renderer-restart-wiring' import { awaitBeforeUnloadCheckpoint, startupDiagnosticsEnabled } from '../preload-runtime-support' import type { PreloadApi } from '../api-types' export const appApi = { getSystemLanguageDetection: (browserPreferences?: readonly string[]) => ipcRenderer.invoke('app:getSystemLanguageDetection', browserPreferences), isProfileStateSaveDelayed: (): Promise => ipcRenderer.invoke('app:isProfileStateSaveDelayed'), onProfileStateSaveDelayChanged: (callback: (delayed: boolean) => void): (() => void) => { const listener = (_event: Electron.IpcRendererEvent, delayed: boolean): void => callback(delayed === true) ipcRenderer.on('app:profileStateSaveDelayChanged', listener) return () => ipcRenderer.removeListener('app:profileStateSaveDelayChanged', listener) }, getIdentity: (): Promise => ipcRenderer.invoke('app:getIdentity'), getWindowsAdministratorStatus: (): Promise => ipcRenderer.invoke('app:getWindowsAdministratorStatus'), getMacosUpgradeSupport: (minimumMacosVersion: string): Promise => ipcRenderer.invoke('app:getMacosUpgradeSupport', minimumMacosVersion), restartAsAdministrator: (): Promise => prepareAndInvokeAppRestart( window, () => ipcRenderer.invoke('app:restartAsAdministrator'), awaitBeforeUnloadCheckpoint ), getFeatureWallAssetBaseUrl: (): Promise => ipcRenderer.invoke('app:getFeatureWallAssetBaseUrl'), setWindowMaterialSuppressed: (suppressed: boolean): Promise => ipcRenderer.invoke('app:setWindowMaterialSuppressed', suppressed), relaunch: (): Promise => prepareAndInvokeAppRestart( window, () => ipcRenderer.invoke('app:relaunch'), awaitBeforeUnloadCheckpoint ), restart: (): Promise => prepareAndInvokeAppRestart( window, () => ipcRenderer.invoke('app:restart'), awaitBeforeUnloadCheckpoint ), reload: (): Promise => prepareAndInvokeAppRestart( window, () => ipcRenderer.invoke('app:reload'), awaitBeforeUnloadCheckpoint ), stageBeforeUnloadSync: (args: Parameters[0]) => { const result: { ok?: unknown; error?: unknown } | null | undefined = ipcRenderer.sendSync( 'app:stage-before-unload-sync', args ) if (result?.ok !== true) { const reason = typeof result?.error === 'string' ? `: ${result.error}` : '.' throw new Error(`Failed to stage renderer state before unload${reason}`) } }, awaitBeforeUnloadCheckpoint: () => awaitBeforeUnloadCheckpoint(), awaitFirstWindowStartupServices: (): Promise => ipcRenderer.invoke('app:awaitFirstWindowStartupServices'), awaitGitEnvironmentStartupBarrier: (): Promise => ipcRenderer.invoke('app:awaitGitEnvironmentStartupBarrier'), prepareTerminalStartupRestoration: (): Promise => ipcRenderer.invoke('app:prepareTerminalStartupRestoration'), holdsStructuredAgentSessions: (): Promise => ipcRenderer.invoke('app:holdsStructuredAgentSessions'), onStructuredAgentSessionsHeldChanged: (callback: (held: boolean) => void): (() => void) => { const listener = (_event: Electron.IpcRendererEvent, held: boolean): void => callback(held === true) ipcRenderer.on('app:structuredAgentSessionsHeldChanged', listener) return () => ipcRenderer.removeListener('app:structuredAgentSessionsHeldChanged', listener) }, recoverLegacyWorkerTerminalsForRendererStartup: (options?: { afterReconnect?: boolean }): Promise => ipcRenderer.invoke('app:recoverLegacyWorkerTerminalsForRendererStartup', options), startupDiagnostic: (event: string, details?: Record): Promise => startupDiagnosticsEnabled ? ipcRenderer.invoke('app:startupDiagnostic', event, details) : Promise.resolve(), getKeyboardInputSourceId: (): Promise => ipcRenderer.invoke('app:getKeyboardInputSourceId'), getMacCapturedDigitRowChords: (): Promise => ipcRenderer.invoke('app:getMacCapturedDigitRowChords'), getKeyboardLayoutSnapshot: () => ipcRenderer.invoke('app:getKeyboardLayoutSnapshot'), onKeyboardLayoutChanged: (callback: (event: KeyboardLayoutChangeEvent) => void): (() => void) => { const listener = (_event: Electron.IpcRendererEvent, event: KeyboardLayoutChangeEvent): void => callback(event) ipcRenderer.on(KEYBOARD_LAYOUT_CHANGED_CHANNEL, listener) return () => ipcRenderer.removeListener(KEYBOARD_LAYOUT_CHANGED_CHANNEL, listener) }, setUnreadDockBadgeCount: (count: number): Promise => ipcRenderer.invoke('app:setUnreadDockBadgeCount', count), getFloatingTerminalCwd: (args?: FloatingTerminalCwdRequest): Promise => ipcRenderer.invoke('app:getFloatingTerminalCwd', args), getFloatingMarkdownDirectory: (): Promise => ipcRenderer.invoke('app:getFloatingMarkdownDirectory'), pickFloatingMarkdownDocument: (): Promise => ipcRenderer.invoke('app:pickFloatingMarkdownDocument'), pickFloatingWorkspaceDirectory: (): Promise => ipcRenderer.invoke('app:pickFloatingWorkspaceDirectory'), writeTerminalRenderDesyncEvidence: (args: WriteTerminalRenderDesyncEvidenceArgs) => ipcRenderer.invoke('terminal:writeRenderDesyncEvidence', args) } satisfies PreloadApi['app']