20260711存档01

This commit is contained in:
2026-07-11 23:33:44 +08:00
parent 9cb6a6e571
commit 2b19144352
56 changed files with 2156 additions and 627 deletions
+27
View File
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerBackgroundHandlers = registerBackgroundHandlers;
const electron_1 = __importDefault(require("electron"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const config_1 = require("../config");
const { ipcMain } = electron_1.default;
function registerBackgroundHandlers() {
@@ -98,4 +100,29 @@ function registerBackgroundHandlers() {
return { success: false, data: null, error: String(e) };
}
});
// Copy file to userData and return the destination path
ipcMain.handle('background:copyToUserData', async (_event, srcPath, ext) => {
try {
const userDataPath = electron_1.default.app.getPath('userData');
const destPath = path_1.default.join(userDataPath, `background-custom${ext}`);
fs_1.default.copyFileSync(srcPath, destPath);
return destPath;
}
catch {
return null;
}
});
// Get cached background file path from userData
ipcMain.handle('background:getCachedPath', async () => {
try {
const userDataPath = electron_1.default.app.getPath('userData');
const files = fs_1.default.readdirSync(userDataPath).filter(f => f.startsWith('background-custom'));
if (files.length === 0)
return null;
return path_1.default.join(userDataPath, files[0]);
}
catch {
return null;
}
});
}
+26
View File
@@ -1,4 +1,6 @@
import electron from 'electron';
import fs from 'fs';
import path from 'path';
import { loadConfig, saveConfig } from '../config';
const { ipcMain } = electron;
@@ -91,4 +93,28 @@ export function registerBackgroundHandlers() {
return { success: false, data: null, error: String(e) };
}
});
// Copy file to userData and return the destination path
ipcMain.handle('background:copyToUserData', async (_event, srcPath: string, ext: string) => {
try {
const userDataPath = electron.app.getPath('userData');
const destPath = path.join(userDataPath, `background-custom${ext}`);
fs.copyFileSync(srcPath, destPath);
return destPath;
} catch {
return null;
}
});
// Get cached background file path from userData
ipcMain.handle('background:getCachedPath', async () => {
try {
const userDataPath = electron.app.getPath('userData');
const files = fs.readdirSync(userDataPath).filter(f => f.startsWith('background-custom'));
if (files.length === 0) return null;
return path.join(userDataPath, files[0]);
} catch {
return null;
}
});
}
+117 -13
View File
@@ -7,10 +7,18 @@ exports.registerInstanceHandlers = registerInstanceHandlers;
const electron_1 = __importDefault(require("electron"));
const instance_1 = require("../core/instance");
const { ipcMain } = electron_1.default;
function registerInstanceHandlers() {
function registerInstanceHandlers(win) {
ipcMain.handle('instance:create', async (_event, payload) => {
try {
const data = await (0, instance_1.createInstance)(payload.name, payload.gamePath, payload.mcVersion, payload.loaderType, payload.loaderVersion, payload.javaPath, payload.memory);
const data = await (0, instance_1.createInstance)(payload.name, payload.gamePath, payload.runtime, {
author: payload.author,
description: payload.description,
java: payload.java,
minMemory: payload.minMemory,
maxMemory: payload.maxMemory,
vmOptions: payload.vmOptions,
mcOptions: payload.mcOptions,
});
return { success: true, data, error: null };
}
catch (e) {
@@ -19,16 +27,7 @@ function registerInstanceHandlers() {
});
ipcMain.handle('instance:list', async (_event, payload) => {
try {
const data = await (0, instance_1.listInstances)(payload.instancesPath);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:delete', async (_event, payload) => {
try {
const data = await (0, instance_1.deleteInstance)(payload.name, payload.instancesPath);
const data = await (0, instance_1.listInstances)(payload.gamePath);
return { success: true, data, error: null };
}
catch (e) {
@@ -37,7 +36,112 @@ function registerInstanceHandlers() {
});
ipcMain.handle('instance:info', async (_event, payload) => {
try {
const data = await (0, instance_1.getInstanceInfo)(payload.name, payload.instancesPath);
const data = await (0, instance_1.getInstanceInfo)(payload.name, payload.gamePath);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:delete', async (_event, payload) => {
try {
const data = await (0, instance_1.deleteInstance)(payload.name, payload.gamePath);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:update', async (_event, payload) => {
try {
const data = await (0, instance_1.updateInstance)(payload.name, payload.gamePath, payload.patch);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:install', async (_event, payload) => {
try {
const requestId = `install-${Date.now()}`;
(0, instance_1.installInstanceGame)(payload.name, payload.gamePath, {
onProgress: (progress) => {
win.mainWindow?.webContents.send('instance:progress', { requestId, ...progress });
},
}).then((data) => {
win.mainWindow?.webContents.send('instance:install-complete', { requestId, data });
}).catch((err) => {
win.mainWindow?.webContents.send('instance:install-error', { requestId, error: String(err) });
});
return { success: true, data: { requestId }, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:launch', async (_event, payload) => {
try {
const requestId = `launch-${Date.now()}`;
(0, instance_1.launchInstance)(payload.name, payload.gamePath, {
username: payload.username,
uuid: payload.uuid,
accessToken: payload.accessToken,
javaPath: payload.javaPath,
server: payload.server,
onEvent: (event) => {
win.mainWindow?.webContents.send('instance:launch-event', { requestId, ...event });
},
}).then((data) => {
win.mainWindow?.webContents.send('instance:launch-complete', { requestId, data });
}).catch((err) => {
win.mainWindow?.webContents.send('instance:launch-error', { requestId, error: String(err) });
});
return { success: true, data: { requestId }, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:diagnose', async (_event, payload) => {
try {
const data = await (0, instance_1.diagnoseInstance)(payload.name, payload.gamePath);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
// Version list APIs
ipcMain.handle('instance:version-list', async (_event, payload) => {
try {
const data = await (0, instance_1.getMinecraftVersionList)(payload.type);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:forge-version-list', async (_event, payload) => {
try {
const data = await (0, instance_1.getForgeVersionList)(payload.mcVersion);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:fabric-version-list', async (_event, payload) => {
try {
const data = await (0, instance_1.getFabricVersionList)(payload.mcVersion);
return { success: true, data, error: null };
}
catch (e) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:quilt-version-list', async (_event, payload) => {
try {
const data = await (0, instance_1.getQuiltVersionList)(payload.mcVersion);
return { success: true, data, error: null };
}
catch (e) {
+157 -18
View File
@@ -1,27 +1,54 @@
import electron from 'electron';
import { createInstance, listInstances, deleteInstance, getInstanceInfo } from '../core/instance';
import {
createInstance,
listInstances,
getInstanceInfo,
deleteInstance,
updateInstance,
installInstanceGame,
launchInstance,
diagnoseInstance,
getMinecraftVersionList,
getForgeVersionList,
getFabricVersionList,
getQuiltVersionList,
type InstanceRuntime,
type InstanceConfig,
} from '../core/instance';
const { ipcMain } = electron;
export function registerInstanceHandlers() {
interface WinRef {
mainWindow: electron.BrowserWindow | null;
}
export function registerInstanceHandlers(win: WinRef) {
ipcMain.handle('instance:create', async (_event, payload: {
name: string;
gamePath: string;
mcVersion: string;
loaderType?: string;
loaderVersion?: string;
javaPath?: string;
memory?: { min?: string; max?: string };
runtime: InstanceRuntime;
author?: string;
description?: string;
java?: string;
minMemory?: number;
maxMemory?: number;
vmOptions?: string[];
mcOptions?: string[];
}) => {
try {
const data = await createInstance(
payload.name,
payload.gamePath,
payload.mcVersion,
payload.loaderType,
payload.loaderVersion,
payload.javaPath,
payload.memory
payload.runtime,
{
author: payload.author,
description: payload.description,
java: payload.java,
minMemory: payload.minMemory,
maxMemory: payload.maxMemory,
vmOptions: payload.vmOptions,
mcOptions: payload.mcOptions,
}
);
return { success: true, data, error: null };
} catch (e: unknown) {
@@ -29,27 +56,139 @@ export function registerInstanceHandlers() {
}
});
ipcMain.handle('instance:list', async (_event, payload: { instancesPath: string }) => {
ipcMain.handle('instance:list', async (_event, payload: { gamePath: string }) => {
try {
const data = await listInstances(payload.instancesPath);
const data = await listInstances(payload.gamePath);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:delete', async (_event, payload: { name: string; instancesPath: string }) => {
ipcMain.handle('instance:info', async (_event, payload: { name: string; gamePath: string }) => {
try {
const data = await deleteInstance(payload.name, payload.instancesPath);
const data = await getInstanceInfo(payload.name, payload.gamePath);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:info', async (_event, payload: { name: string; instancesPath: string }) => {
ipcMain.handle('instance:delete', async (_event, payload: { name: string; gamePath: string }) => {
try {
const data = await getInstanceInfo(payload.name, payload.instancesPath);
const data = await deleteInstance(payload.name, payload.gamePath);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:update', async (_event, payload: {
name: string;
gamePath: string;
patch: Partial<Omit<InstanceConfig, 'name' | 'creationDate'>>;
}) => {
try {
const data = await updateInstance(payload.name, payload.gamePath, payload.patch);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:install', async (_event, payload: { name: string; gamePath: string }) => {
try {
const requestId = `install-${Date.now()}`;
installInstanceGame(payload.name, payload.gamePath, {
onProgress: (progress) => {
win.mainWindow?.webContents.send('instance:progress', { requestId, ...progress });
},
}).then((data) => {
win.mainWindow?.webContents.send('instance:install-complete', { requestId, data });
}).catch((err) => {
win.mainWindow?.webContents.send('instance:install-error', { requestId, error: String(err) });
});
return { success: true, data: { requestId }, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:launch', async (_event, payload: {
name: string;
gamePath: string;
username: string;
uuid: string;
accessToken?: string;
javaPath?: string;
server?: { host: string; port?: number };
}) => {
try {
const requestId = `launch-${Date.now()}`;
launchInstance(payload.name, payload.gamePath, {
username: payload.username,
uuid: payload.uuid,
accessToken: payload.accessToken,
javaPath: payload.javaPath,
server: payload.server,
onEvent: (event) => {
win.mainWindow?.webContents.send('instance:launch-event', { requestId, ...event });
},
}).then((data) => {
win.mainWindow?.webContents.send('instance:launch-complete', { requestId, data });
}).catch((err) => {
win.mainWindow?.webContents.send('instance:launch-error', { requestId, error: String(err) });
});
return { success: true, data: { requestId }, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:diagnose', async (_event, payload: { name: string; gamePath: string }) => {
try {
const data = await diagnoseInstance(payload.name, payload.gamePath);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
// Version list APIs
ipcMain.handle('instance:version-list', async (_event, payload: { type?: string }) => {
try {
const data = await getMinecraftVersionList(payload.type);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:forge-version-list', async (_event, payload: { mcVersion?: string }) => {
try {
const data = await getForgeVersionList(payload.mcVersion);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:fabric-version-list', async (_event, payload: { mcVersion?: string }) => {
try {
const data = await getFabricVersionList(payload.mcVersion);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
}
});
ipcMain.handle('instance:quilt-version-list', async (_event, payload: { mcVersion?: string }) => {
try {
const data = await getQuiltVersionList(payload.mcVersion);
return { success: true, data, error: null };
} catch (e: unknown) {
return { success: false, data: null, error: String(e) };
+18 -3
View File
@@ -6,8 +6,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.registerWindowHandlers = registerWindowHandlers;
const electron_1 = __importDefault(require("electron"));
const path_1 = __importDefault(require("path"));
const { ipcMain, dialog } = electron_1.default;
const { ipcMain, dialog, shell } = electron_1.default;
const isDev = !electron_1.default.app.isPackaged;
const MIME_MAP = {
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
webp: 'image/webp',
gif: 'image/gif',
bmp: 'image/bmp',
svg: 'image/svg+xml',
};
function createSplashWindow() {
const splash = new electron_1.default.BrowserWindow({
width: 480,
@@ -67,7 +76,7 @@ function registerWindowHandlers(win) {
}
return { success: true };
});
// File dialog
// File dialog — returns source path and extension for preload to handle
ipcMain.handle('dialog:openFile', async (_event, payload) => {
const result = await dialog.showOpenDialog(win.mainWindow, {
properties: ['openFile'],
@@ -75,6 +84,12 @@ function registerWindowHandlers(win) {
});
if (result.canceled || result.filePaths.length === 0)
return null;
return result.filePaths[0];
const srcPath = result.filePaths[0];
const ext = path_1.default.extname(srcPath).toLowerCase() || '.png';
return { srcPath, ext };
});
// Open external URL in system browser
ipcMain.handle('shell:openExternal', async (_event, url) => {
await shell.openExternal(url);
});
}
+20 -3
View File
@@ -1,7 +1,7 @@
import electron from 'electron';
import path from 'path';
const { ipcMain, dialog } = electron;
const { ipcMain, dialog, shell } = electron;
const isDev = !electron.app.isPackaged;
@@ -10,6 +10,16 @@ interface WinRef {
splashWindow: electron.BrowserWindow | null;
}
const MIME_MAP: Record<string, string> = {
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
webp: 'image/webp',
gif: 'image/gif',
bmp: 'image/bmp',
svg: 'image/svg+xml',
};
function createSplashWindow(): electron.BrowserWindow {
const splash = new electron.BrowserWindow({
width: 480,
@@ -77,7 +87,7 @@ export function registerWindowHandlers(win: WinRef) {
return { success: true };
});
// File dialog
// File dialog — returns source path and extension for preload to handle
ipcMain.handle('dialog:openFile', async (_event, payload: {
filters?: { name: string; extensions: string[] }[];
}) => {
@@ -86,6 +96,13 @@ export function registerWindowHandlers(win: WinRef) {
filters: payload.filters,
});
if (result.canceled || result.filePaths.length === 0) return null;
return result.filePaths[0];
const srcPath = result.filePaths[0];
const ext = path.extname(srcPath).toLowerCase() || '.png';
return { srcPath, ext };
});
// Open external URL in system browser
ipcMain.handle('shell:openExternal', async (_event, url: string) => {
await shell.openExternal(url);
});
}