fix: use out/ directory for electron-vite dev mode compatibility
This commit is contained in:
@@ -0,0 +1,591 @@
|
||||
import { app, screen, safeStorage, ipcMain, BrowserWindow, nativeTheme, dialog, nativeImage } from "electron";
|
||||
import { join } from "path";
|
||||
import { readFileSync, writeFile } from "fs";
|
||||
import Store from "electron-store";
|
||||
import Redis from "ioredis";
|
||||
import __cjs_mod__ from "node:module";
|
||||
const __filename = import.meta.filename;
|
||||
const __dirname = import.meta.dirname;
|
||||
const require2 = __cjs_mod__.createRequire(import.meta.url);
|
||||
const STATE_FILE = join(app.getPath("userData"), "jrdm-win-state.json");
|
||||
const MIN_WIDTH = 900;
|
||||
const MIN_HEIGHT = 600;
|
||||
const DEFAULT_WIDTH = 1200;
|
||||
const DEFAULT_HEIGHT = 800;
|
||||
function parseJson(str) {
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function getLastState() {
|
||||
try {
|
||||
const raw = readFileSync(STATE_FILE, "utf-8");
|
||||
const state = parseJson(raw);
|
||||
if (state) {
|
||||
const display = screen.getPrimaryDisplay().workArea;
|
||||
if (state.x != null && (state.x < 0 || state.x > display.width - 100)) {
|
||||
state.x = null;
|
||||
state.y = null;
|
||||
}
|
||||
if (state.y != null && (state.y < 0 || state.y > display.height - 100)) {
|
||||
state.x = null;
|
||||
state.y = null;
|
||||
}
|
||||
state.width = Math.max(state.width || DEFAULT_WIDTH, MIN_WIDTH);
|
||||
state.height = Math.max(state.height || DEFAULT_HEIGHT, MIN_HEIGHT);
|
||||
return state;
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
return { x: null, y: null, width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT, maximized: false };
|
||||
}
|
||||
function saveState(win) {
|
||||
const bounds = win.getBounds();
|
||||
const state = { ...bounds, maximized: win.isMaximized() };
|
||||
writeFile(STATE_FILE, JSON.stringify(state), "utf-8", () => {
|
||||
});
|
||||
}
|
||||
function restoreAndTrack(win) {
|
||||
const lastState = getLastState();
|
||||
if (lastState.x != null && lastState.y != null) {
|
||||
win.setBounds({ x: lastState.x, y: lastState.y, width: lastState.width, height: lastState.height });
|
||||
}
|
||||
if (lastState.maximized) {
|
||||
win.maximize();
|
||||
}
|
||||
win.on("close", () => saveState(win));
|
||||
}
|
||||
const store = new Store({
|
||||
name: "jrdm-config",
|
||||
defaults: {
|
||||
connections: [],
|
||||
settings: {
|
||||
theme: "system",
|
||||
locale: "en",
|
||||
fontSize: 13,
|
||||
scanCount: 500
|
||||
}
|
||||
}
|
||||
});
|
||||
function encrypt(text) {
|
||||
if (!safeStorage.isEncryptionAvailable()) {
|
||||
return Buffer.from(text).toString("base64");
|
||||
}
|
||||
return safeStorage.encryptString(text).toString("base64");
|
||||
}
|
||||
function decrypt(encoded) {
|
||||
if (!safeStorage.isEncryptionAvailable()) {
|
||||
return Buffer.from(encoded, "base64").toString("utf-8");
|
||||
}
|
||||
return safeStorage.decryptString(Buffer.from(encoded, "base64"));
|
||||
}
|
||||
const clients = /* @__PURE__ */ new Map();
|
||||
function buildRedisOptions(opts) {
|
||||
const options = {
|
||||
host: opts.host,
|
||||
port: opts.port,
|
||||
username: opts.username || void 0,
|
||||
password: opts.password || void 0,
|
||||
stringNumbers: true,
|
||||
enableReadyCheck: true,
|
||||
family: 0,
|
||||
connectTimeout: 1e4,
|
||||
retryStrategy(times) {
|
||||
if (times > 3) return null;
|
||||
return Math.min(times * 200, 1e3);
|
||||
},
|
||||
maxRetriesPerRequest: 3
|
||||
};
|
||||
if (opts.tls) {
|
||||
options.tls = {
|
||||
rejectUnauthorized: false,
|
||||
checkServerIdentity: () => void 0
|
||||
};
|
||||
}
|
||||
return options;
|
||||
}
|
||||
function getClient(id) {
|
||||
return clients.get(id);
|
||||
}
|
||||
function isClientConnected(id) {
|
||||
const client = clients.get(id);
|
||||
return client?.status === "ready";
|
||||
}
|
||||
async function connect(id, opts) {
|
||||
if (clients.has(id)) {
|
||||
await disconnect(id);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const redis = new Redis(buildRedisOptions(opts));
|
||||
redis.once("ready", () => {
|
||||
clients.set(id, redis);
|
||||
resolve();
|
||||
});
|
||||
redis.once("error", (err) => {
|
||||
redis.disconnect();
|
||||
reject(err);
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (!clients.has(id)) {
|
||||
redis.disconnect();
|
||||
reject(new Error("连接超时,请检查主机和端口"));
|
||||
}
|
||||
}, 12e3);
|
||||
});
|
||||
}
|
||||
async function disconnect(id) {
|
||||
const client = clients.get(id);
|
||||
if (client) {
|
||||
client.disconnect();
|
||||
clients.delete(id);
|
||||
}
|
||||
}
|
||||
async function getKeyType(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.type(key);
|
||||
}
|
||||
async function getKeyTTL(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.ttl(key);
|
||||
}
|
||||
async function deleteKey(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.del(key);
|
||||
}
|
||||
async function setKeyTTL(id, key, ttl) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
if (ttl < 0) {
|
||||
await client.persist(key);
|
||||
} else {
|
||||
await client.expire(key, ttl);
|
||||
}
|
||||
}
|
||||
async function renameKey(id, oldKey, newKey) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.rename(oldKey, newKey);
|
||||
}
|
||||
async function existsKey(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return await client.exists(key) === 1;
|
||||
}
|
||||
async function batchDelete(id, keys) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
if (keys.length === 0) return 0;
|
||||
const pipeline = client.pipeline();
|
||||
for (const key of keys) {
|
||||
pipeline.del(key);
|
||||
}
|
||||
const results = await pipeline.exec();
|
||||
return results?.filter(([err]) => !err).length ?? 0;
|
||||
}
|
||||
async function memoryUsage(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.memory("USAGE", key);
|
||||
}
|
||||
async function scanKeys(id, cursor, pattern, count) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
const [nextCursor, keys] = await client.scan(cursor, "MATCH", pattern, "COUNT", count);
|
||||
return { cursor: nextCursor, keys };
|
||||
}
|
||||
async function getStringValue(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.get(key);
|
||||
}
|
||||
async function setStringValue(id, key, value) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.set(key, value);
|
||||
}
|
||||
async function getHashFields(id, key, cursor, count) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
const [nextCursor, raw] = await client.hscan(key, cursor, "COUNT", count);
|
||||
const fields = [];
|
||||
for (let i = 0; i < raw.length; i += 2) {
|
||||
fields.push([raw[i], raw[i + 1]]);
|
||||
}
|
||||
return { cursor: nextCursor, fields };
|
||||
}
|
||||
async function setHashField(id, key, field, value) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.hset(key, field, value);
|
||||
}
|
||||
async function deleteHashField(id, key, field) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.hdel(key, field);
|
||||
}
|
||||
async function listRange(id, key, start, stop) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.lrange(key, start, stop);
|
||||
}
|
||||
async function listLength(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.llen(key);
|
||||
}
|
||||
async function listPush(id, key, ...values) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.rpush(key, ...values);
|
||||
}
|
||||
async function listSet(id, key, index, value) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.lset(key, index, value);
|
||||
}
|
||||
async function listRemove(id, key, count, value) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.lrem(key, count, value);
|
||||
}
|
||||
async function setMembers(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.smembers(key);
|
||||
}
|
||||
async function setSize(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.scard(key);
|
||||
}
|
||||
async function setAdd(id, key, ...members) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.sadd(key, ...members);
|
||||
}
|
||||
async function setRemove(id, key, ...members) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.srem(key, ...members);
|
||||
}
|
||||
async function zsetRange(id, key, start, stop, withScores) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
if (withScores) return client.zrange(key, start, stop, "WITHSCORES");
|
||||
return client.zrange(key, start, stop);
|
||||
}
|
||||
async function zsetSize(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.zcard(key);
|
||||
}
|
||||
async function zsetAdd(id, key, score, member) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.zadd(key, score, member);
|
||||
}
|
||||
async function zsetRemove(id, key, ...members) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.zrem(key, ...members);
|
||||
}
|
||||
async function streamInfo(id, key) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.xinfo("STREAM", key);
|
||||
}
|
||||
async function streamRange(id, key, start, end, count) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.xrange(key, start, end, "COUNT", count);
|
||||
}
|
||||
async function streamAdd(id, key, streamId, fieldValues) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.xadd(key, streamId, ...fieldValues);
|
||||
}
|
||||
async function streamTrim(id, key, maxLen) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.xtrim(key, "MAXLEN", maxLen);
|
||||
}
|
||||
async function streamDel(id, key, ...ids) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.xdel(key, ...ids);
|
||||
}
|
||||
async function execute(id, command, args) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.call(command, ...args);
|
||||
}
|
||||
async function getServerInfo(id) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.info();
|
||||
}
|
||||
async function selectDb(id, db) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
await client.select(db);
|
||||
}
|
||||
async function dbSize(id) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.dbsize();
|
||||
}
|
||||
async function ping(id) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.ping();
|
||||
}
|
||||
async function slowLogGet(id, count) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.slowlog("GET", count);
|
||||
}
|
||||
async function slowLogLen(id) {
|
||||
const client = getClient(id);
|
||||
if (!client) throw new Error(`Client ${id} not found`);
|
||||
return client.slowlog("LEN");
|
||||
}
|
||||
function registerIpcHandlers() {
|
||||
ipcMain.on("window:minimize", () => BrowserWindow.getFocusedWindow()?.minimize());
|
||||
ipcMain.on("window:maximize", () => {
|
||||
const win = BrowserWindow.getFocusedWindow();
|
||||
if (win) win.isMaximized() ? win.unmaximize() : win.maximize();
|
||||
});
|
||||
ipcMain.on("window:close", () => BrowserWindow.getFocusedWindow()?.close());
|
||||
ipcMain.handle("theme:get", () => nativeTheme.shouldUseDarkColors);
|
||||
ipcMain.on("theme:set", (_e, theme) => {
|
||||
nativeTheme.themeSource = theme;
|
||||
});
|
||||
ipcMain.handle("dialog:openFile", async (_e, options) => {
|
||||
const win = BrowserWindow.getFocusedWindow();
|
||||
if (!win) return null;
|
||||
const result = await dialog.showOpenDialog(win, options);
|
||||
if (result.canceled || result.filePaths.length === 0) return null;
|
||||
const fs = await import("fs");
|
||||
try {
|
||||
return { path: result.filePaths[0], content: fs.readFileSync(result.filePaths[0], "utf-8") };
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
ipcMain.handle("credential:encrypt", (_e, text) => encrypt(text));
|
||||
ipcMain.handle("credential:decrypt", (_e, encoded) => decrypt(encoded));
|
||||
ipcMain.handle("storage:getConnections", () => store.get("connections", []));
|
||||
ipcMain.handle("storage:saveConnection", (_e, conn) => {
|
||||
const connections = store.get("connections", []);
|
||||
const idx = connections.findIndex((c) => c.id === conn.id);
|
||||
if (idx >= 0) connections[idx] = conn;
|
||||
else connections.push(conn);
|
||||
store.set("connections", connections);
|
||||
return connections;
|
||||
});
|
||||
ipcMain.handle("storage:deleteConnection", (_e, id) => {
|
||||
const connections = store.get("connections", []).filter((c) => c.id !== id);
|
||||
store.set("connections", connections);
|
||||
return connections;
|
||||
});
|
||||
ipcMain.handle("storage:reorderConnections", (_e, ids) => {
|
||||
const connections = store.get("connections", []);
|
||||
const reordered = ids.map((id, i) => {
|
||||
const conn = connections.find((c) => c.id === id);
|
||||
conn.order = i;
|
||||
return conn;
|
||||
});
|
||||
store.set("connections", reordered);
|
||||
return reordered;
|
||||
});
|
||||
ipcMain.handle("storage:getSettings", () => store.get("settings"));
|
||||
ipcMain.handle("storage:saveSettings", (_e, settings) => {
|
||||
store.set("settings", settings);
|
||||
});
|
||||
ipcMain.handle("redis:connect", async (_e, id, opts) => {
|
||||
try {
|
||||
await connect(id, opts);
|
||||
return { success: true };
|
||||
} catch (err) {
|
||||
return { success: false, error: err.message };
|
||||
}
|
||||
});
|
||||
ipcMain.handle("redis:disconnect", async (_e, id) => {
|
||||
await disconnect(id);
|
||||
});
|
||||
ipcMain.handle("redis:ping", async (_e, id) => {
|
||||
return ping(id);
|
||||
});
|
||||
ipcMain.handle("redis:isConnected", (_e, id) => {
|
||||
return isClientConnected(id);
|
||||
});
|
||||
ipcMain.handle("redis:execute", async (_e, id, command, args) => {
|
||||
return execute(id, command, args);
|
||||
});
|
||||
ipcMain.handle("redis:getInfo", async (_e, id) => {
|
||||
return getServerInfo(id);
|
||||
});
|
||||
ipcMain.handle("redis:selectDb", async (_e, id, db) => {
|
||||
await selectDb(id, db);
|
||||
});
|
||||
ipcMain.handle("redis:dbSize", async (_e, id) => {
|
||||
return dbSize(id);
|
||||
});
|
||||
ipcMain.handle("redis:slowLogGet", async (_e, id, count) => {
|
||||
return slowLogGet(id, count);
|
||||
});
|
||||
ipcMain.handle("redis:slowLogLen", async (_e, id) => {
|
||||
return slowLogLen(id);
|
||||
});
|
||||
ipcMain.handle("redis:scanKeys", async (_e, id, cursor, pattern, count) => {
|
||||
return scanKeys(id, cursor, pattern, count);
|
||||
});
|
||||
ipcMain.handle("redis:getKeyType", async (_e, id, key) => {
|
||||
return getKeyType(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:getKeyTTL", async (_e, id, key) => {
|
||||
return getKeyTTL(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:setTTL", async (_e, id, key, ttl) => {
|
||||
await setKeyTTL(id, key, ttl);
|
||||
});
|
||||
ipcMain.handle("redis:deleteKey", async (_e, id, key) => {
|
||||
await deleteKey(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:renameKey", async (_e, id, oldKey, newKey) => {
|
||||
await renameKey(id, oldKey, newKey);
|
||||
});
|
||||
ipcMain.handle("redis:existsKey", async (_e, id, key) => {
|
||||
return existsKey(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:batchDelete", async (_e, id, keys) => {
|
||||
return batchDelete(id, keys);
|
||||
});
|
||||
ipcMain.handle("redis:memoryUsage", async (_e, id, key) => {
|
||||
return memoryUsage(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:getString", async (_e, id, key) => {
|
||||
return getStringValue(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:setString", async (_e, id, key, value) => {
|
||||
await setStringValue(id, key, value);
|
||||
});
|
||||
ipcMain.handle("redis:hashScan", async (_e, id, key, cursor, count) => {
|
||||
return getHashFields(id, key, cursor, count);
|
||||
});
|
||||
ipcMain.handle("redis:hashSet", async (_e, id, key, field, value) => {
|
||||
await setHashField(id, key, field, value);
|
||||
});
|
||||
ipcMain.handle("redis:hashDel", async (_e, id, key, field) => {
|
||||
await deleteHashField(id, key, field);
|
||||
});
|
||||
ipcMain.handle("redis:listRange", async (_e, id, key, start, stop) => {
|
||||
return listRange(id, key, start, stop);
|
||||
});
|
||||
ipcMain.handle("redis:listLength", async (_e, id, key) => {
|
||||
return listLength(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:listPush", async (_e, id, key, values) => {
|
||||
return listPush(id, key, ...values);
|
||||
});
|
||||
ipcMain.handle("redis:listSet", async (_e, id, key, index, value) => {
|
||||
await listSet(id, key, index, value);
|
||||
});
|
||||
ipcMain.handle("redis:listRemove", async (_e, id, key, count, value) => {
|
||||
return listRemove(id, key, count, value);
|
||||
});
|
||||
ipcMain.handle("redis:setMembers", async (_e, id, key) => {
|
||||
return setMembers(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:setSize", async (_e, id, key) => {
|
||||
return setSize(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:setAdd", async (_e, id, key, members) => {
|
||||
return setAdd(id, key, ...members);
|
||||
});
|
||||
ipcMain.handle("redis:setRemove", async (_e, id, key, members) => {
|
||||
return setRemove(id, key, ...members);
|
||||
});
|
||||
ipcMain.handle("redis:zsetRange", async (_e, id, key, start, stop, withScores) => {
|
||||
return zsetRange(id, key, start, stop, withScores);
|
||||
});
|
||||
ipcMain.handle("redis:zsetSize", async (_e, id, key) => {
|
||||
return zsetSize(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:zsetAdd", async (_e, id, key, score, member) => {
|
||||
return zsetAdd(id, key, score, member);
|
||||
});
|
||||
ipcMain.handle("redis:zsetRemove", async (_e, id, key, members) => {
|
||||
return zsetRemove(id, key, ...members);
|
||||
});
|
||||
ipcMain.handle("redis:streamInfo", async (_e, id, key) => {
|
||||
return streamInfo(id, key);
|
||||
});
|
||||
ipcMain.handle("redis:streamRange", async (_e, id, key, start, end, count) => {
|
||||
return streamRange(id, key, start, end, count);
|
||||
});
|
||||
ipcMain.handle("redis:streamAdd", async (_e, id, key, streamId, fieldValues) => {
|
||||
return streamAdd(id, key, streamId, fieldValues);
|
||||
});
|
||||
ipcMain.handle("redis:streamTrim", async (_e, id, key, maxLen) => {
|
||||
return streamTrim(id, key, maxLen);
|
||||
});
|
||||
ipcMain.handle("redis:streamDel", async (_e, id, key, ids) => {
|
||||
return streamDel(id, key, ...ids);
|
||||
});
|
||||
}
|
||||
let mainWindow = null;
|
||||
function getIconPath() {
|
||||
return join(__dirname, "../../build/icons/icon_256.png");
|
||||
}
|
||||
function createWindow() {
|
||||
const iconPath = getIconPath();
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
minWidth: 900,
|
||||
minHeight: 600,
|
||||
title: "JRedisDesktop",
|
||||
icon: nativeImage.createFromPath(iconPath),
|
||||
backgroundColor: nativeTheme.shouldUseDarkColors ? "#0f0f1a" : "#f8fafc",
|
||||
webPreferences: {
|
||||
preload: join(__dirname, "../preload/index.mjs"),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: false
|
||||
},
|
||||
frame: false,
|
||||
titleBarStyle: "hidden"
|
||||
});
|
||||
if (process.platform === "linux" && mainWindow) {
|
||||
mainWindow.setIcon(nativeImage.createFromPath(iconPath));
|
||||
}
|
||||
restoreAndTrack(mainWindow);
|
||||
if (process.env.ELECTRON_RENDERER_URL) {
|
||||
mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL);
|
||||
mainWindow.webContents.openDevTools();
|
||||
} else {
|
||||
mainWindow.loadFile(join(__dirname, "../renderer/index.html"));
|
||||
}
|
||||
mainWindow.on("closed", () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
nativeTheme.on("updated", () => {
|
||||
mainWindow?.webContents.send("theme:os-updated", nativeTheme.shouldUseDarkColors);
|
||||
});
|
||||
}
|
||||
app.whenReady().then(() => {
|
||||
registerIpcHandlers();
|
||||
createWindow();
|
||||
});
|
||||
app.on("window-all-closed", () => {
|
||||
app.quit();
|
||||
});
|
||||
app.on("activate", () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
});
|
||||
Reference in New Issue
Block a user