initial commit

This commit is contained in:
2026-08-08 18:34:12 +08:00
commit 0d7438e368
82 changed files with 17407 additions and 0 deletions

164
src/main/ipc/index.ts Normal file
View File

@@ -0,0 +1,164 @@
import { ipcMain, dialog, BrowserWindow, shell } from 'electron'
import { IPC } from '@shared/ipc/channels'
import { getStore } from '../services/store'
import { dbQuery, dbExec } from '../services/database'
import {
startFileServer,
stopFileServer,
getFileServerStatus
} from '../services/fileServer'
import { getLanIps } from '../services/lanInfo'
import { fetchJson, fetchText } from '../services/network'
import { syncLibrary } from '../services/library'
import { convertFlacToWav, stopConvert } from '../services/transcode'
import {
startMusicServer,
stopMusicServer,
sendMusicCmd
} from '../services/musicServer'
import { startDataServer, stopDataServer, sendDataCmd } from '../services/dataServer'
import {
toggleDesktopLyric,
updateDesktopLyric,
setLyricIgnoreMouse
} from '../window/desktopLyricWindow'
import { checkUpdate } from '../services/update'
import { exportSongs, type ExportItem } from '../services/export'
import { cleanIosWavFile, ensureIosWavFiles, type WifiAudioRef } from '../services/wifiTransfer'
function broadcast(channel: string, payload: unknown): void {
BrowserWindow.getAllWindows().forEach((w) => w.webContents.send(channel, payload))
}
export function registerIpc(): void {
/* ---------- 配置 ---------- */
const store = getStore()
ipcMain.handle(IPC.STORE_GET, (_e, key: string) => store.get(key as never))
ipcMain.handle(IPC.STORE_SET, (_e, key: string, value: unknown) =>
store.set(key as never, value as never)
)
ipcMain.handle(IPC.STORE_DELETE, (_e, key: string) => store.delete(key as never))
/* ---------- 数据库 ---------- */
ipcMain.handle(IPC.DB_QUERY, (_e, sql: string, params: unknown[]) => dbQuery(sql, params))
ipcMain.handle(IPC.DB_EXEC, (_e, sql: string, params: unknown[]) => {
const r = dbExec(sql, params)
return { changes: r.changes, lastInsertRowid: Number(r.lastInsertRowid) }
})
/* ---------- HTTP 文件服务 ---------- */
ipcMain.handle(IPC.HTTP_START, async (_e, root: string, port: number) =>
startFileServer(root, port)
)
ipcMain.handle(IPC.HTTP_STOP, async () => {
await stopFileServer()
return true
})
ipcMain.handle(IPC.HTTP_STATUS, () => getFileServerStatus())
/* ---------- 局域网 ---------- */
ipcMain.handle(IPC.NET_LAN_IPS, () => getLanIps())
/* ---------- OSS 元数据 ---------- */
ipcMain.handle(IPC.NET_FETCH_JSON, (_e, url: string) => fetchJson(url))
ipcMain.handle(IPC.NET_FETCH_TEXT, (_e, url: string) => fetchText(url))
/* ---------- 曲库同步 ---------- */
ipcMain.handle(IPC.LIBRARY_SYNC, async () => {
const result = await syncLibrary()
store.set('dataVersion', String(result.version))
return result
})
ipcMain.handle(IPC.LIBRARY_DATA_VERSION, () => store.get('dataVersion'))
/* ---------- 转码 ---------- */
ipcMain.handle(IPC.CONVERT_START, async (_e, input: string, output: string) => {
await convertFlacToWav({
input,
output,
onProgress: (p) => broadcast(IPC.CONVERT_PROGRESS, { input, progress: p })
})
broadcast(IPC.CONVERT_DONE, { input, output })
return true
})
ipcMain.handle(IPC.CONVERT_STOP, () => {
stopConvert()
return true
})
ipcMain.handle(IPC.WIFI_ENSURE_IOS_WAV, async (_e, items: WifiAudioRef[]) => {
await ensureIosWavFiles(items || [])
return true
})
ipcMain.handle(IPC.WIFI_CLEAN_IOS_WAV, (_e, item: WifiAudioRef) => {
cleanIosWavFile(item)
return true
})
/* ---------- 传歌服务4388 ---------- */
ipcMain.handle(IPC.MUSIC_SERVER_START, () => {
startMusicServer((e) => broadcast(IPC.MUSIC_SERVER_EVENT, e))
return true
})
ipcMain.handle(IPC.MUSIC_SERVER_STOP, () => {
stopMusicServer()
return true
})
ipcMain.handle(IPC.MUSIC_SERVER_SEND, (_e, cmd: string, body: string) =>
sendMusicCmd(cmd, body)
)
/* ---------- 数据同步服务4389 ---------- */
ipcMain.handle(IPC.DATA_SERVER_START, () => {
startDataServer((e) => broadcast(IPC.DATA_SERVER_EVENT, e))
return true
})
ipcMain.handle(IPC.DATA_SERVER_STOP, () => {
stopDataServer()
return true
})
ipcMain.handle(IPC.DATA_SERVER_SEND, (_e, cmd: string, body: string) =>
sendDataCmd(cmd, body)
)
/* ---------- 对话框 ---------- */
ipcMain.handle(IPC.DIALOG_OPEN_DIR, async () => {
const r = await dialog.showOpenDialog({ properties: ['openDirectory'] })
return r.canceled ? null : r.filePaths[0]
})
ipcMain.handle(IPC.DIALOG_OPEN_FILE, async () => {
const r = await dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] })
return r.canceled ? null : r.filePaths
})
/* ---------- 桌面歌词 ---------- */
ipcMain.handle(IPC.LYRIC_TOGGLE, (_e, show: boolean) => {
toggleDesktopLyric(show)
broadcast(IPC.LYRIC_STATE, show)
return true
})
ipcMain.on(IPC.LYRIC_UPDATE, (_e, payload) => updateDesktopLyric(payload))
ipcMain.on(IPC.LYRIC_SET_IGNORE_MOUSE, (_e, ignore: boolean) => setLyricIgnoreMouse(ignore))
/* ---------- 窗口控制 ---------- */
ipcMain.on(IPC.WIN_MIN, (e) => BrowserWindow.fromWebContents(e.sender)?.minimize())
ipcMain.on(IPC.WIN_MAX, (e) => {
const w = BrowserWindow.fromWebContents(e.sender)
if (!w) return
w.isMaximized() ? w.unmaximize() : w.maximize()
})
ipcMain.on(IPC.WIN_CLOSE, (e) => BrowserWindow.fromWebContents(e.sender)?.close())
/* ---------- 导出歌曲 ---------- */
ipcMain.handle(
IPC.EXPORT_SONGS,
async (_e, dest: string, platform: 'android' | 'ios', list: ExportItem[]) =>
exportSongs(dest, platform, list, (p) => broadcast(IPC.EXPORT_PROGRESS, p))
)
/* ---------- 更新 ---------- */
ipcMain.handle(IPC.UPDATE_CHECK, () => checkUpdate())
ipcMain.handle(IPC.UPDATE_OPEN_DOWNLOAD, (_e, url: string) => {
if (url) shell.openExternal(url)
return true
})
}