chore(desktop): add build configuration and output files
- Add electron-vite configuration for main and preload processes - Add .gitignore to exclude node_modules - Add compiled output files for main and preload processes - Add TypeScript configuration for project setup - Add package-lock.json for dependency management - Initialize build artifacts for desktop application distribution
This commit is contained in:
233
out/main/index.js
Normal file
233
out/main/index.js
Normal file
@@ -0,0 +1,233 @@
|
||||
"use strict";
|
||||
const electron = require("electron");
|
||||
const electronUpdater = require("electron-updater");
|
||||
const path = require("path");
|
||||
const url = require("url");
|
||||
const __dirname$1 = path.dirname(url.fileURLToPath(require("url").pathToFileURL(__filename).href));
|
||||
let mainWindow = null;
|
||||
let tray = null;
|
||||
const isDev = process.env.NODE_ENV === "development" || !electron.app.isPackaged;
|
||||
const API_URL = isDev ? "http://localhost:8080" : "https://api.timeline.com";
|
||||
function createMainWindow() {
|
||||
mainWindow = new electron.BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
title: "Timeline",
|
||||
icon: path.join(__dirname$1, "../build/icon.png"),
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
preload: path.join(__dirname$1, "preload.js"),
|
||||
webSecurity: true
|
||||
},
|
||||
frame: true,
|
||||
show: false,
|
||||
backgroundColor: "#ffffff"
|
||||
});
|
||||
if (isDev) {
|
||||
mainWindow.loadURL("http://localhost:8000");
|
||||
mainWindow.webContents.openDevTools();
|
||||
} else {
|
||||
mainWindow.loadURL(API_URL);
|
||||
}
|
||||
mainWindow.once("ready-to-show", () => {
|
||||
mainWindow?.show();
|
||||
});
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url: url2 }) => {
|
||||
electron.shell.openExternal(url2);
|
||||
return { action: "deny" };
|
||||
});
|
||||
mainWindow.on("close", (event) => {
|
||||
if (process.platform === "darwin") {
|
||||
event.preventDefault();
|
||||
mainWindow?.hide();
|
||||
}
|
||||
});
|
||||
mainWindow.on("closed", () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
}
|
||||
function createTray() {
|
||||
const iconPath = path.join(__dirname$1, "../build/tray.png");
|
||||
const icon = electron.nativeImage.createFromPath(iconPath);
|
||||
tray = new electron.Tray(icon.resize({ width: 16, height: 16 }));
|
||||
const contextMenu = electron.Menu.buildFromTemplate([
|
||||
{
|
||||
label: "显示主窗口",
|
||||
click: () => {
|
||||
mainWindow?.show();
|
||||
mainWindow?.focus();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "创建时刻",
|
||||
click: () => {
|
||||
mainWindow?.show();
|
||||
mainWindow?.webContents.send("navigate", "/story/create");
|
||||
}
|
||||
},
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "退出",
|
||||
click: () => {
|
||||
electron.app.quit();
|
||||
}
|
||||
}
|
||||
]);
|
||||
tray.setToolTip("Timeline");
|
||||
tray.setContextMenu(contextMenu);
|
||||
tray.on("click", () => {
|
||||
mainWindow?.show();
|
||||
mainWindow?.focus();
|
||||
});
|
||||
}
|
||||
function createMenu() {
|
||||
const template = [
|
||||
{
|
||||
label: "Timeline",
|
||||
submenu: [
|
||||
{ role: "about", label: "关于 Timeline" },
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "偏好设置",
|
||||
accelerator: "CmdOrCtrl+,",
|
||||
click: () => {
|
||||
mainWindow?.webContents.send("navigate", "/settings");
|
||||
}
|
||||
},
|
||||
{ type: "separator" },
|
||||
{ role: "quit", label: "退出" }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "编辑",
|
||||
submenu: [
|
||||
{ role: "undo", label: "撤销" },
|
||||
{ role: "redo", label: "重做" },
|
||||
{ type: "separator" },
|
||||
{ role: "cut", label: "剪切" },
|
||||
{ role: "copy", label: "复制" },
|
||||
{ role: "paste", label: "粘贴" },
|
||||
{ role: "selectAll", label: "全选" }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "视图",
|
||||
submenu: [
|
||||
{ role: "reload", label: "刷新" },
|
||||
{ role: "forceReload", label: "强制刷新" },
|
||||
{ type: "separator" },
|
||||
{ role: "resetZoom", label: "重置缩放" },
|
||||
{ role: "zoomIn", label: "放大" },
|
||||
{ role: "zoomOut", label: "缩小" },
|
||||
{ type: "separator" },
|
||||
{ role: "togglefullscreen", label: "全屏" }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "窗口",
|
||||
submenu: [
|
||||
{ role: "minimize", label: "最小化" },
|
||||
{ role: "close", label: "关闭" }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "帮助",
|
||||
submenu: [
|
||||
{
|
||||
label: "查看文档",
|
||||
click: () => electron.shell.openExternal("https://docs.timeline.com")
|
||||
},
|
||||
{
|
||||
label: "反馈问题",
|
||||
click: () => electron.shell.openExternal("https://github.com/timeline/issues")
|
||||
},
|
||||
{ type: "separator" },
|
||||
{
|
||||
label: "检查更新",
|
||||
click: () => checkForUpdates()
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
if (isDev) {
|
||||
template[2].submenu?.push(
|
||||
{ type: "separator" },
|
||||
{ role: "toggleDevTools", label: "开发者工具" }
|
||||
);
|
||||
}
|
||||
const menu = electron.Menu.buildFromTemplate(template);
|
||||
electron.Menu.setApplicationMenu(menu);
|
||||
}
|
||||
async function checkForUpdates() {
|
||||
try {
|
||||
const result = await electronUpdater.autoUpdater.checkForUpdates();
|
||||
if (result) {
|
||||
console.log("发现新版本:", result.updateInfo.version);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("检查更新失败:", error);
|
||||
}
|
||||
}
|
||||
function setupAutoUpdater() {
|
||||
electronUpdater.autoUpdater.autoDownload = false;
|
||||
electronUpdater.autoUpdater.autoInstallOnAppQuit = true;
|
||||
electronUpdater.autoUpdater.on("update-available", (info) => {
|
||||
mainWindow?.webContents.send("update-available", info);
|
||||
});
|
||||
electronUpdater.autoUpdater.on("update-downloaded", (info) => {
|
||||
mainWindow?.webContents.send("update-downloaded", info);
|
||||
});
|
||||
electronUpdater.autoUpdater.on("error", (error) => {
|
||||
console.error("更新错误:", error);
|
||||
});
|
||||
}
|
||||
function setupIpc() {
|
||||
electron.ipcMain.handle("get-version", () => {
|
||||
return electron.app.getVersion();
|
||||
});
|
||||
electron.ipcMain.handle("get-platform", () => {
|
||||
return process.platform;
|
||||
});
|
||||
electron.ipcMain.handle("check-update", async () => {
|
||||
try {
|
||||
const result = await electronUpdater.autoUpdater.checkForUpdates();
|
||||
return result?.updateInfo;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
electron.ipcMain.handle("download-update", async () => {
|
||||
await electronUpdater.autoUpdater.downloadUpdate();
|
||||
});
|
||||
electron.ipcMain.handle("install-update", () => {
|
||||
electronUpdater.autoUpdater.quitAndInstall();
|
||||
});
|
||||
electron.ipcMain.handle("open-external", (_, url2) => {
|
||||
electron.shell.openExternal(url2);
|
||||
});
|
||||
}
|
||||
electron.app.whenReady().then(() => {
|
||||
createMainWindow();
|
||||
createMenu();
|
||||
createTray();
|
||||
setupAutoUpdater();
|
||||
setupIpc();
|
||||
electron.app.on("activate", () => {
|
||||
if (electron.BrowserWindow.getAllWindows().length === 0) {
|
||||
createMainWindow();
|
||||
} else {
|
||||
mainWindow?.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
electron.app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
electron.app.quit();
|
||||
}
|
||||
});
|
||||
electron.app.on("before-quit", () => {
|
||||
tray?.destroy();
|
||||
});
|
||||
28
out/preload/index.js
Normal file
28
out/preload/index.js
Normal file
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
const electron = require("electron");
|
||||
electron.contextBridge.exposeInMainWorld("electronAPI", {
|
||||
// 应用信息
|
||||
getVersion: () => electron.ipcRenderer.invoke("get-version"),
|
||||
getPlatform: () => electron.ipcRenderer.invoke("get-platform"),
|
||||
// 更新相关
|
||||
checkUpdate: () => electron.ipcRenderer.invoke("check-update"),
|
||||
downloadUpdate: () => electron.ipcRenderer.invoke("download-update"),
|
||||
installUpdate: () => electron.ipcRenderer.invoke("install-update"),
|
||||
// 更新事件监听
|
||||
onUpdateAvailable: (callback) => {
|
||||
electron.ipcRenderer.on("update-available", (_, info) => callback(info));
|
||||
},
|
||||
onUpdateDownloaded: (callback) => {
|
||||
electron.ipcRenderer.on("update-downloaded", (_, info) => callback(info));
|
||||
},
|
||||
// 外部链接
|
||||
openExternal: (url) => electron.ipcRenderer.invoke("open-external", url),
|
||||
// 导航事件
|
||||
onNavigate: (callback) => {
|
||||
electron.ipcRenderer.on("navigate", (_, path) => callback(path));
|
||||
},
|
||||
// 移除监听器
|
||||
removeAllListeners: (channel) => {
|
||||
electron.ipcRenderer.removeAllListeners(channel);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user