Files
minecraft_launcher/src/installer-rp/preload.ts
claude-bot fe0d2f75e3 installer-rp: add resume-on-retry and discard-on-quit for failed installs
On install failure the temp folder is now preserved instead of wiped, so
already-downloaded songs/images are skipped on the next attempt. The
error screen offers 재시도 (resume from the failed item) and 처음으로
(discard the partial download and restart). Closing the program without
retrying still wipes the partial download via window-all-closed, and an
explicit cancel also clears it.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
2026-06-05 16:23:34 +09:00

62 lines
2.6 KiB
TypeScript

import { contextBridge, ipcRenderer } from 'electron'
import type { RpFetchedPack } from './types.js'
const api = {
/** i18n 사전을 렌더러에 전달. */
loadLocale: (): Promise<Record<string, unknown>> => ipcRenderer.invoke('rp:i18n:dict'),
/** manifest 와 각 음악퀴즈의 file/list/<key>.json 까지 한 번에 로드. */
loadPacks: (manifestUrl?: string): Promise<RpFetchedPack[]> =>
ipcRenderer.invoke('rp:packs:load', manifestUrl),
/** 음악퀴즈 키를 선택. */
selectPack: (packKey: string): Promise<void> =>
ipcRenderer.invoke('rp:packs:select', packKey),
/** 약관(Markdown) 다운로드. v0.3.4~ : 임의 kind 허용 (사이트에서 설정). */
getTerm: (kind: string): Promise<{ ok: boolean; content?: string; message?: string }> =>
ipcRenderer.invoke('rp:terms:get', kind),
/** rp 인스톨러에 표시할 약관 목록 (사이트의 visibility 토글로 필터링). */
getTermsList: (): Promise<{ ok: boolean; terms?: Array<{ kind: string; label: string }>; message?: string }> =>
ipcRenderer.invoke('rp:terms:list'),
/** 리소스팩 빌드/설치 시작. 완료 또는 취소될 때까지 resolve 되지 않을 수 있음. */
startInstall: (): Promise<{ resourcepackPath: string }> =>
ipcRenderer.invoke('rp:install:start'),
/** 진행 중인 설치 취소. 임시 파일 정리 후 종료. */
cancelInstall: (): Promise<void> =>
ipcRenderer.invoke('rp:install:cancel'),
/** 재시도하지 않고 처음으로 돌아갈 때 받아둔 임시 파일을 정리한다. */
discardInstall: (): Promise<void> =>
ipcRenderer.invoke('rp:install:discard'),
/** %appdata%/.mc_custom/resourcepacks/ 폴더를 OS 파일 탐색기로 연다. */
openResourcepackFolder: (): Promise<void> =>
ipcRenderer.invoke('rp:finish:openFolder'),
/** 프로그램 종료. */
quit: (): Promise<void> => ipcRenderer.invoke('rp:quit'),
/** 로그 스트림 구독. */
onLog: (handler: (line: string) => void): (() => void) => {
const listener = (_event: unknown, line: string) => handler(line)
ipcRenderer.on('log', listener)
return () => ipcRenderer.removeListener('log', listener)
},
/** 설치 진행 이벤트 구독. payload 구조는 renderer 가 알아서 분기. */
onProgress: (handler: (payload: unknown) => void): (() => void) => {
const listener = (_event: unknown, payload: unknown) => handler(payload)
ipcRenderer.on('progress', listener)
return () => ipcRenderer.removeListener('progress', listener)
}
}
contextBridge.exposeInMainWorld('rpInstaller', api)
declare global {
interface Window {
rpInstaller: typeof api
}
}