main.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import os from 'node:os';
  2. import path from 'node:path';
  3. import process from 'node:process';
  4. import { fileURLToPath } from 'node:url';
  5. import {
  6. app,
  7. BrowserWindow,
  8. globalShortcut,
  9. ipcMain,
  10. Menu,
  11. shell,
  12. } from 'electron';
  13. const __dirname = path.dirname(fileURLToPath(import.meta.url));
  14. process.env.APP_ROOT = path.join(__dirname, '../..');
  15. export const MAIN_DIST = path.join(process.env.APP_ROOT, 'dist-electron');
  16. export const RENDERER_DIST = path.join(process.env.APP_ROOT, 'dist');
  17. export const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;
  18. process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
  19. ? path.join(process.env.APP_ROOT, 'public')
  20. : RENDERER_DIST;
  21. // Disable GPU Acceleration for Windows 7
  22. if (os.release().startsWith('6.1')) app.disableHardwareAcceleration();
  23. // Set application name for Windows 10+ notifications
  24. if (process.platform === 'win32') app.setAppUserModelId(app.getName());
  25. if (!app.requestSingleInstanceLock()) {
  26. app.quit();
  27. }
  28. let win: BrowserWindow | null = null;
  29. const preload = path.join(__dirname, '../preload/preload.mjs');
  30. const indexHtml = path.join(RENDERER_DIST, 'index.html');
  31. async function createWindow() {
  32. win = new BrowserWindow({
  33. autoHideMenuBar: true,
  34. frame: false,
  35. height: 900,
  36. icon: path.join(process.env.VITE_PUBLIC as string, 'favicon.ico'),
  37. movable: true,
  38. show: false,
  39. title: 'Main window',
  40. webPreferences: {
  41. contextIsolation: true,
  42. nodeIntegration: false,
  43. preload,
  44. webSecurity: true,
  45. },
  46. width: 1440,
  47. });
  48. // 监听窗口准备好显示的事件
  49. win.once('ready-to-show', () => {
  50. win?.maximize(); // 最大化窗口
  51. win?.show(); // 显示窗口
  52. });
  53. win.on('maximize', () => {
  54. win?.webContents.send('maximize-changed', true);
  55. });
  56. win.on('unmaximize', () => {
  57. win?.webContents.send('maximize-changed', false);
  58. });
  59. if (VITE_DEV_SERVER_URL) {
  60. win.loadURL(VITE_DEV_SERVER_URL);
  61. } else {
  62. win.loadFile(indexHtml);
  63. }
  64. // Test actively push message to the Electron-Renderer
  65. win.webContents.on('did-finish-load', () => {
  66. win?.webContents.send('main-process-message', new Date().toLocaleString());
  67. });
  68. // Make all links open with the browser, not with the application
  69. win.webContents.setWindowOpenHandler(({ url }) => {
  70. if (url.startsWith('https:')) shell.openExternal(url);
  71. return { action: 'deny' };
  72. });
  73. // win.webContents.on('will-navigate', (event, url) => { }) #344
  74. }
  75. Menu.setApplicationMenu(null);
  76. app
  77. .whenReady()
  78. .then(createWindow)
  79. .then(() => {
  80. // 禁用了菜单之后,默认的快捷键也会被禁用,这里重新注册部分常用快捷键
  81. if (VITE_DEV_SERVER_URL) {
  82. // 开发模式下监听快捷键来打开开发者工具
  83. globalShortcut.register('CmdOrCtrl+Shift+I', () => {
  84. BrowserWindow.getFocusedWindow()?.webContents.toggleDevTools();
  85. });
  86. }
  87. // 监听快捷键来刷新页面
  88. globalShortcut.registerAll(['CmdOrCtrl+R', 'CmdOrCtrl+F5'], () => {
  89. BrowserWindow.getFocusedWindow()?.webContents.reload();
  90. });
  91. // 监听快捷键来强制刷新页面
  92. globalShortcut.registerAll(
  93. ['CmdOrCtrl+Shift+R', 'CmdOrCtrl+Shift+F5'],
  94. () => {
  95. BrowserWindow.getFocusedWindow()?.webContents.reloadIgnoringCache();
  96. },
  97. );
  98. });
  99. app.on('window-all-closed', () => {
  100. win = null;
  101. if (process.platform !== 'darwin') app.quit();
  102. });
  103. app.on('will-quit', () => {
  104. globalShortcut.unregisterAll();
  105. });
  106. app.on('second-instance', () => {
  107. if (win) {
  108. // Focus on the main window if the user tried to open another
  109. if (win.isMinimized()) win.restore();
  110. win.focus();
  111. }
  112. });
  113. app.on('activate', () => {
  114. const allWindows = BrowserWindow.getAllWindows();
  115. if (allWindows.length > 0) {
  116. allWindows[0].focus();
  117. } else {
  118. createWindow();
  119. }
  120. });
  121. // New window example arg: new windows url
  122. ipcMain.handle('open-win', (_, arg) => {
  123. const childWindow = new BrowserWindow({
  124. frame: false,
  125. webPreferences: {
  126. contextIsolation: true,
  127. nodeIntegration: true,
  128. preload,
  129. webviewTag: true,
  130. },
  131. });
  132. if (VITE_DEV_SERVER_URL) {
  133. childWindow.loadURL(`${VITE_DEV_SERVER_URL}#${arg}`);
  134. } else {
  135. childWindow.loadFile(indexHtml, { hash: arg });
  136. }
  137. });
  138. ipcMain.handle('app-minimize', (event) => {
  139. const browserWindow = BrowserWindow.fromWebContents(event.sender);
  140. if (browserWindow) {
  141. browserWindow.minimize();
  142. }
  143. });
  144. ipcMain.handle('app-maximize', (event) => {
  145. const browserWindow = BrowserWindow.fromWebContents(event.sender);
  146. if (browserWindow) {
  147. if (browserWindow.isMaximized()) {
  148. browserWindow.restore();
  149. } else {
  150. browserWindow.maximize();
  151. }
  152. }
  153. });
  154. ipcMain.handle('app-close', (event) => {
  155. const browserWindow = BrowserWindow.fromWebContents(event.sender);
  156. if (browserWindow) {
  157. browserWindow.close();
  158. }
  159. });
  160. ipcMain.handle('is-maximized', (event) => {
  161. const browserWindow = BrowserWindow.fromWebContents(event.sender);
  162. if (browserWindow) {
  163. return browserWindow.isMaximized();
  164. }
  165. return false;
  166. });