- _meta.json: customLabels -> terms.{label,showInInstaller,showInInstallerRp}
- Drop builtin protection; any term kind can be deleted/added/toggled
- New public route /manifest/terms/<pack>/index.json for installer term lists
- Installers fetch terms:list dynamically; skip agreement step if list empty
- Term editor: 2 visibility checkboxes (설치기 / 리소스팩 설치기), multi-select
- Migration from old schema preserves custom labels (default: visible in both)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
import { contextBridge, ipcRenderer } from 'electron'
|
|
import type { ClientInstallPayload, FetchedPack, RamCheckResult, ServerInstallPayload, PortForwardResult } from './types.js'
|
|
|
|
const api = {
|
|
// i18n
|
|
loadLocale: (): Promise<Record<string, unknown>> => ipcRenderer.invoke('i18n:dict'),
|
|
|
|
// 1단계
|
|
loadPacks: (manifestUrl?: string): Promise<FetchedPack[]> =>
|
|
ipcRenderer.invoke('packs:load', manifestUrl),
|
|
setSelectedPack: (packKey: string): Promise<void> =>
|
|
ipcRenderer.invoke('packs:select', packKey),
|
|
|
|
// 약관(Markdown) 다운로드
|
|
getTerm: (kind: string): Promise<{ ok: boolean; content?: string; message?: string }> =>
|
|
ipcRenderer.invoke('terms:get', kind),
|
|
// 메인 인스톨러용 약관 목록 (사이트의 visibility 토글에 따라 필터링됨)
|
|
getTermsList: (): Promise<{ ok: boolean; terms?: Array<{ kind: string; label: string }>; message?: string }> =>
|
|
ipcRenderer.invoke('terms:list'),
|
|
|
|
// 3-1
|
|
pickFolder: (): Promise<string | null> => ipcRenderer.invoke('dialog:pickFolder'),
|
|
validateInstallPath: (target: string): Promise<{ ok: boolean; message?: string }> =>
|
|
ipcRenderer.invoke('install:validatePath', target),
|
|
|
|
// 3-2
|
|
detectJdk: (): Promise<{ found: boolean; path: string }> => ipcRenderer.invoke('jdk:detect'),
|
|
installJdk: (): Promise<{ ok: boolean; path?: string; message?: string }> => ipcRenderer.invoke('jdk:install'),
|
|
cancelJdkInstall: (): Promise<{ ok: boolean }> => ipcRenderer.invoke('jdk:cancelInstall'),
|
|
|
|
// 3-3
|
|
startServerInstall: (payload: ServerInstallPayload): Promise<void> =>
|
|
ipcRenderer.invoke('server:install', payload),
|
|
readEula: (installPath: string): Promise<{ exists: boolean; content: string }> =>
|
|
ipcRenderer.invoke('server:readEula', installPath),
|
|
fetchMinecraftEula: (): Promise<{ url: string; html: string }> =>
|
|
ipcRenderer.invoke('server:fetchMinecraftEula'),
|
|
acceptEula: (installPath: string): Promise<void> =>
|
|
ipcRenderer.invoke('server:acceptEula', installPath),
|
|
checkRam: (packKey: string): Promise<RamCheckResult> =>
|
|
ipcRenderer.invoke('server:checkRam', packKey),
|
|
|
|
// 3-4
|
|
startServerConfigEditor: (installPath: string): Promise<{ url: string }> =>
|
|
ipcRenderer.invoke('server:configEditor', installPath),
|
|
|
|
// 3-5
|
|
checkPortForward: (port: number): Promise<PortForwardResult> =>
|
|
ipcRenderer.invoke('server:portForward', port),
|
|
|
|
// 4단계
|
|
installClient: (payload: ClientInstallPayload): Promise<void> =>
|
|
ipcRenderer.invoke('client:install', payload),
|
|
|
|
// 5단계
|
|
openServerFolder: (): Promise<void> => ipcRenderer.invoke('finish:openServerFolder'),
|
|
createDesktopShortcut: (): Promise<void> => ipcRenderer.invoke('finish:desktopShortcut'),
|
|
startServer: (): Promise<void> => ipcRenderer.invoke('finish:startServer'),
|
|
startMinecraftLauncher: (): Promise<void> => ipcRenderer.invoke('finish:startLauncher'),
|
|
quitApp: (): Promise<void> => ipcRenderer.invoke('app:quit'),
|
|
|
|
// log stream
|
|
onLog: (handler: (line: string) => void): (() => void) => {
|
|
const listener = (_event: unknown, line: string) => handler(line)
|
|
ipcRenderer.on('log', listener)
|
|
return () => ipcRenderer.removeListener('log', listener)
|
|
}
|
|
}
|
|
|
|
contextBridge.exposeInMainWorld('installer', api)
|
|
|
|
declare global {
|
|
interface Window {
|
|
installer: typeof api
|
|
}
|
|
}
|