169 lines
6.4 KiB
TypeScript
169 lines
6.4 KiB
TypeScript
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron'
|
|
import { electronAPI } from '@electron-toolkit/preload'
|
|
import { IPC } from '@shared/ipc/channels'
|
|
|
|
/** 暴露给渲染进程的类型安全 API */
|
|
const api = {
|
|
store: {
|
|
get: <T>(key: string): Promise<T> => ipcRenderer.invoke(IPC.STORE_GET, key),
|
|
set: (key: string, value: unknown): Promise<void> =>
|
|
ipcRenderer.invoke(IPC.STORE_SET, key, value),
|
|
delete: (key: string): Promise<void> => ipcRenderer.invoke(IPC.STORE_DELETE, key)
|
|
},
|
|
db: {
|
|
query: <T>(sql: string, params: unknown[] = []): Promise<T[]> =>
|
|
ipcRenderer.invoke(IPC.DB_QUERY, sql, params),
|
|
exec: (
|
|
sql: string,
|
|
params: unknown[] = []
|
|
): Promise<{ changes: number; lastInsertRowid: number }> =>
|
|
ipcRenderer.invoke(IPC.DB_EXEC, sql, params)
|
|
},
|
|
http: {
|
|
start: (root: string, port: number) => ipcRenderer.invoke(IPC.HTTP_START, root, port),
|
|
stop: () => ipcRenderer.invoke(IPC.HTTP_STOP),
|
|
status: () => ipcRenderer.invoke(IPC.HTTP_STATUS)
|
|
},
|
|
net: {
|
|
lanIps: () => ipcRenderer.invoke(IPC.NET_LAN_IPS),
|
|
fetchJson: <T>(url: string): Promise<T> => ipcRenderer.invoke(IPC.NET_FETCH_JSON, url),
|
|
fetchText: (url: string): Promise<string> => ipcRenderer.invoke(IPC.NET_FETCH_TEXT, url)
|
|
},
|
|
library: {
|
|
sync: (): Promise<{ version: number; albums: number; musics: number }> =>
|
|
ipcRenderer.invoke(IPC.LIBRARY_SYNC),
|
|
dataVersion: (): Promise<string> => ipcRenderer.invoke(IPC.LIBRARY_DATA_VERSION)
|
|
},
|
|
convert: {
|
|
start: (input: string, output: string) =>
|
|
ipcRenderer.invoke(IPC.CONVERT_START, input, output),
|
|
stop: () => ipcRenderer.invoke(IPC.CONVERT_STOP),
|
|
onProgress: (cb: (data: { input: string; progress: number }) => void) => {
|
|
const listener = (_: IpcRendererEvent, data: { input: string; progress: number }): void =>
|
|
cb(data)
|
|
ipcRenderer.on(IPC.CONVERT_PROGRESS, listener)
|
|
return () => ipcRenderer.removeListener(IPC.CONVERT_PROGRESS, listener)
|
|
},
|
|
onDone: (cb: (data: { input: string; output: string }) => void) => {
|
|
const listener = (_: IpcRendererEvent, data: { input: string; output: string }): void =>
|
|
cb(data)
|
|
ipcRenderer.on(IPC.CONVERT_DONE, listener)
|
|
return () => ipcRenderer.removeListener(IPC.CONVERT_DONE, listener)
|
|
}
|
|
},
|
|
wifi: {
|
|
ensureIosWav: (items: { baseUrl: string; musicPath: string }[]) =>
|
|
ipcRenderer.invoke(IPC.WIFI_ENSURE_IOS_WAV, items),
|
|
cleanIosWav: (item: { baseUrl: string; musicPath: string }) =>
|
|
ipcRenderer.invoke(IPC.WIFI_CLEAN_IOS_WAV, item)
|
|
},
|
|
musicServer: {
|
|
start: () => ipcRenderer.invoke(IPC.MUSIC_SERVER_START),
|
|
stop: () => ipcRenderer.invoke(IPC.MUSIC_SERVER_STOP),
|
|
send: (cmd: string, body: string) => ipcRenderer.invoke(IPC.MUSIC_SERVER_SEND, cmd, body),
|
|
onEvent: (cb: (e: unknown) => void) => {
|
|
const listener = (_: IpcRendererEvent, e: unknown): void => cb(e)
|
|
ipcRenderer.on(IPC.MUSIC_SERVER_EVENT, listener)
|
|
return () => ipcRenderer.removeListener(IPC.MUSIC_SERVER_EVENT, listener)
|
|
}
|
|
},
|
|
dataServer: {
|
|
start: () => ipcRenderer.invoke(IPC.DATA_SERVER_START),
|
|
stop: () => ipcRenderer.invoke(IPC.DATA_SERVER_STOP),
|
|
send: (cmd: string, body: string) => ipcRenderer.invoke(IPC.DATA_SERVER_SEND, cmd, body),
|
|
onEvent: (cb: (e: unknown) => void) => {
|
|
const listener = (_: IpcRendererEvent, e: unknown): void => cb(e)
|
|
ipcRenderer.on(IPC.DATA_SERVER_EVENT, listener)
|
|
return () => ipcRenderer.removeListener(IPC.DATA_SERVER_EVENT, listener)
|
|
}
|
|
},
|
|
dialog: {
|
|
openDir: (): Promise<string | null> => ipcRenderer.invoke(IPC.DIALOG_OPEN_DIR),
|
|
openFile: (): Promise<string[] | null> => ipcRenderer.invoke(IPC.DIALOG_OPEN_FILE)
|
|
},
|
|
lyric: {
|
|
toggle: (show: boolean) => ipcRenderer.invoke(IPC.LYRIC_TOGGLE, show),
|
|
update: (payload: unknown) => ipcRenderer.send(IPC.LYRIC_UPDATE, payload),
|
|
setIgnoreMouse: (ignore: boolean) => ipcRenderer.send(IPC.LYRIC_SET_IGNORE_MOUSE, ignore),
|
|
onUpdate: (cb: (payload: unknown) => void) => {
|
|
const listener = (_: IpcRendererEvent, p: unknown): void => cb(p)
|
|
ipcRenderer.on(IPC.LYRIC_UPDATE, listener)
|
|
return () => ipcRenderer.removeListener(IPC.LYRIC_UPDATE, listener)
|
|
},
|
|
onState: (cb: (show: boolean) => void) => {
|
|
const listener = (_: IpcRendererEvent, show: boolean): void => cb(show)
|
|
ipcRenderer.on(IPC.LYRIC_STATE, listener)
|
|
return () => ipcRenderer.removeListener(IPC.LYRIC_STATE, listener)
|
|
}
|
|
},
|
|
win: {
|
|
minimize: () => ipcRenderer.send(IPC.WIN_MIN),
|
|
maximize: () => ipcRenderer.send(IPC.WIN_MAX),
|
|
close: () => ipcRenderer.send(IPC.WIN_CLOSE)
|
|
},
|
|
player: {
|
|
onControl: (cb: (action: 'playpause' | 'next' | 'prev') => void) => {
|
|
const listener = (_: IpcRendererEvent, action: 'playpause' | 'next' | 'prev'): void =>
|
|
cb(action)
|
|
ipcRenderer.on(IPC.PLAYER_CONTROL, listener)
|
|
return () => ipcRenderer.removeListener(IPC.PLAYER_CONTROL, listener)
|
|
}
|
|
},
|
|
exporter: {
|
|
run: (
|
|
dest: string,
|
|
platform: 'android' | 'ios',
|
|
list: unknown[]
|
|
): Promise<{ done: number; total: number; fail: number }> =>
|
|
ipcRenderer.invoke(IPC.EXPORT_SONGS, dest, platform, list),
|
|
onProgress: (
|
|
cb: (p: {
|
|
musicUId: string
|
|
status: 'converting' | 'copying' | 'done' | 'fail'
|
|
done: number
|
|
total: number
|
|
}) => void
|
|
) => {
|
|
const listener = (
|
|
_: IpcRendererEvent,
|
|
p: {
|
|
musicUId: string
|
|
status: 'converting' | 'copying' | 'done' | 'fail'
|
|
done: number
|
|
total: number
|
|
}
|
|
): void => cb(p)
|
|
ipcRenderer.on(IPC.EXPORT_PROGRESS, listener)
|
|
return () => ipcRenderer.removeListener(IPC.EXPORT_PROGRESS, listener)
|
|
}
|
|
},
|
|
update: {
|
|
check: (): Promise<{
|
|
version: string
|
|
latest: string
|
|
hasUpdate: boolean
|
|
message: string
|
|
url: string
|
|
error?: boolean
|
|
}> => ipcRenderer.invoke(IPC.UPDATE_CHECK),
|
|
openDownload: (url: string): Promise<boolean> =>
|
|
ipcRenderer.invoke(IPC.UPDATE_OPEN_DOWNLOAD, url)
|
|
}
|
|
}
|
|
|
|
export type ApiType = typeof api
|
|
|
|
if (process.contextIsolated) {
|
|
try {
|
|
contextBridge.exposeInMainWorld('electron', electronAPI)
|
|
contextBridge.exposeInMainWorld('api', api)
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
} else {
|
|
// @ts-ignore (define in dts)
|
|
window.electron = electronAPI
|
|
// @ts-ignore
|
|
window.api = api
|
|
}
|