import { invoke, isTauri } from '@tauri-apps/api/core' import { listen } from '@tauri-apps/api/event' import { getCurrentWindow } from '@tauri-apps/api/window' import { createSerialQueue, createSubscription, singleFlight } from './async' import type { UpdaterStatus } from '../types/updater' import type { GameExitedPayload, InstallProgressPayload, JavaInstallation, LauncherSettings, LinkChallenge, LinkStatus, NativeHost, ProfileInspection, ServerStatus, ShaCraftAccount, ShaCraftLoginResult, SyncResult, ProfileMetadata, PreparationResult, LegacyMod, LegacySelection, LegacyBackup, } from '../types/launcher' export const isNative = () => typeof window !== 'undefined' && isTauri() const accountRequests = createSerialQueue() const restoreAccount = singleFlight(() => accountRequests.enqueue(() => invoke('get_shacraft_account'))) // Keep the IPC contract in one place. UI components never invoke native // commands directly and cannot pass arbitrary URLs or filesystem paths. export const native = { updaterStatus: () => invoke('updater_status'), checkUpdater: () => invoke('updater_check'), installUpdater: () => invoke('updater_download_install'), restartUpdater: () => invoke('updater_restart'), openUpdaterRelease: () => invoke('updater_open_release_page'), host: () => invoke('native_host'), metadata: (profileId: string) => invoke('profile_metadata', { profileId }), legacyMods: (profileId: string) => invoke('legacy_mods', { profileId }), backupLegacyMods: (profileId: string, selections: LegacySelection[]) => invoke('backup_legacy_mods', { profileId, selections }), loadSettings: () => invoke('load_settings'), saveSettings: (settings: LauncherSettings) => invoke('save_settings', { settings }), detectJava: () => invoke('detect_java'), inspectProfile: (profileId: string) => invoke('inspect_remote_profile', { profileId }), syncProfile: (profileId: string) => invoke('sync_remote_profile', { profileId }), getAccount: restoreAccount, authenticate: (username: string, password: string, register: boolean) => accountRequests.enqueue(() => invoke('shacraft_authenticate', { username, password, register })), logout: () => accountRequests.enqueue(() => invoke('shacraft_logout')), startLink: (nickname: string) => accountRequests.enqueue(() => invoke('shacraft_start_link', { nickname })), linkStatus: (challengeId: number) => accountRequests.enqueue(() => invoke('shacraft_link_status', { challengeId })), serverStatus: (profileId: string) => invoke('get_server_status', { profileId }), installGame: (profileId: string) => invoke('ensure_game_installed', { profileId }), launchGame: (profileId: string) => invoke('launch_game', { profileId }), launchOnboarding: (profileId: string, nickname: string) => invoke('launch_onboarding', { profileId, nickname }), } export function watchUpdater(receive: (status: UpdaterStatus) => void) { return createSubscription([ listen('launcher-update-status', ({ payload }) => receive(payload)), ]) } export const windowControls = { minimize: () => getCurrentWindow().minimize(), toggleMaximize: () => getCurrentWindow().toggleMaximize(), close: () => getCurrentWindow().close(), } export function watchGame(handlers: { progress: (payload: InstallProgressPayload) => void exited: (payload: GameExitedPayload) => void }) { return createSubscription([ listen('game-install-progress', ({ payload }) => handlers.progress(payload)), listen('game-exited', ({ payload }) => handlers.exited(payload)), ]) }