// Frontend wrapper for the main-process screen-source enumerator. // Pre-migration this called into a Rust command that captured JPEG // thumbnails via xcap; Electron's desktopCapturer returns thumbnails // inline as data URLs so there's no binary/base64 dual-path to juggle. // // The return shape here matches the ipc-types `ScreenSource` contract. import { isTauriRuntime } from './globalShortcut'; export type ScreenSourceKind = 'screen' | 'window'; export interface ScreenSource { /** Chromium desktopCapturer id; feed unchanged to getUserMedia's * chromeMediaSourceId constraint when capturing this source. */ id: string; name: string; kind: ScreenSourceKind; /** Thumbnail as a ready-to-use data URL (image/png). Null when * desktopCapturer returned an empty buffer. */ thumbnailDataUrl: string | null; /** App icon as a data URL for window sources; null for screens. */ iconDataUrl: string | null; displayId: number | null; } export async function listScreenSources(): Promise { if (!isTauriRuntime()) return []; try { return await window.electronAPI.getScreenSources(); } catch (err: unknown) { console.warn('getScreenSources failed', err); return []; } } // Single-source high-res refresh. Re-queries desktopCapturer at 640x360 // so a detail view looks crisp without paying the full enumeration cost // more than once per hover-debounce. export async function captureScreenSourceThumbnail( sourceId: string, ): Promise { if (!isTauriRuntime()) return null; try { return await window.electronAPI.getScreenThumbnail(sourceId); } catch (err: unknown) { console.warn('getScreenThumbnail failed', { sourceId, err }); return null; } } // Legacy name retained for call-sites that expected a Blob. desktopCapturer // already gives us a data URL — callers that need a Blob can fetch() the // URL. This helper keeps the old signature so nothing breaks during the // migration. export async function captureScreenSourceThumbnailBytes( sourceId: string, ): Promise { const url = await captureScreenSourceThumbnail(sourceId); if (!url) return null; try { const res = await fetch(url); return await res.blob(); } catch (err: unknown) { console.warn('thumbnail fetch failed', { sourceId, err }); return null; } } // Legacy single-shot API — now just delegates to listScreenSources. export async function enumerateScreenSources(): Promise { return listScreenSources(); } // Picker tiles bind `src={thumbnailDataUrl(src)}`; we already receive a // data URL so this is just a pass-through for API compatibility. export function thumbnailDataUrl(src: ScreenSource): string | null { return src.thumbnailDataUrl; }