import type { AuthUser, RefreshStore } from '@pipu/core'; import { createContext, createElement, useContext, type ReactNode } from 'react'; type Tauri = { core: { invoke: (cmd: string, args?: Record) => Promise }; event: { listen: (event: string, handler: (e: { payload: string }) => void) => Promise<() => void> }; }; function api(): Tauri | undefined { return (window as Window & { __TAURI__?: Tauri }).__TAURI__; } export function isDesktop(): boolean { return api() !== undefined; } function invoke(cmd: string, args?: Record): Promise { const tauri = api(); if (!tauri) throw new Error('Tauri API unavailable'); return tauri.core.invoke(cmd, args) as Promise; } export type DesktopHandle = { proxyBase: string; server: string | null; setServer: (url: string) => Promise; clearServer: () => Promise; refreshStore: RefreshStore; listenMedia: (handler: (action: string) => void) => Promise<() => void>; setMedia: (info: { title: string; artist: string; album: string; coverUrl?: string | null; playing: boolean }) => void; }; export const DesktopContext = createContext(null); export function DesktopProvider({ value, children }: { value: DesktopHandle | null; children: ReactNode }) { return createElement(DesktopContext.Provider, { value }, children); } export function useDesktop(): DesktopHandle | null { return useContext(DesktopContext); } let active: DesktopHandle | null = null; export function desktopHandle(): DesktopHandle | null { return active; } export async function createDesktop(): Promise { if (!isDesktop()) return null; const boot = await invoke<{ proxyBase: string; server: string | null }>('bootstrap'); const handle: DesktopHandle = { proxyBase: boot.proxyBase, server: boot.server, setServer: async (url) => { const server = await invoke('set_server', { url }); handle.server = server; return server; }, clearServer: async () => { await invoke('clear_server'); handle.server = null; }, refreshStore: { get: () => invoke('token_get'), set: (token) => invoke('token_set', { token }), clear: async () => { await invoke('token_clear'); await invoke('user_clear'); }, getUser: async () => { const json = await invoke('user_get'); return json ? (JSON.parse(json) as AuthUser) : null; }, setUser: (user) => invoke('user_set', { json: JSON.stringify(user) }), }, listenMedia: async (handler) => { const tauri = api(); if (!tauri) return () => undefined; return tauri.event.listen('media', (e) => handler(e.payload)); }, setMedia: (info) => { void invoke('media_set', { title: info.title, artist: info.artist, album: info.album, coverUrl: info.coverUrl ?? null, playing: info.playing, }); }, }; active = handle; return handle; }