windowManage.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { join } from "node:path";
  2. import { BrowserWindow, shell, ipcMain } from "electron";
  3. import { isLinux, isMac, isWin } from "../utils";
  4. import { destroyTray } from "./trayManage";
  5. import { getStore } from "./storeManage";
  6. import { getIsForceQuit } from "./appManage";
  7. import { registerShortcuts, unregisterShortcuts } from "./shortcutManage";
  8. const url = process.env.VITE_DEV_SERVER_URL;
  9. let mainWindow: BrowserWindow | null = null;
  10. let splashWindow: BrowserWindow | null = null;
  11. let callingWindow: BrowserWindow | null = null;
  12. const store = getStore();
  13. function createSplashWindow() {
  14. splashWindow = new BrowserWindow({
  15. frame: false,
  16. width: 200,
  17. height: 200,
  18. resizable: false,
  19. transparent: true,
  20. });
  21. splashWindow.loadFile(global.pathConfig.splashHtml);
  22. splashWindow.on("closed", () => {
  23. splashWindow = null;
  24. });
  25. }
  26. export function createMainWindow() {
  27. createSplashWindow();
  28. mainWindow = new BrowserWindow({
  29. title: "OpenIM",
  30. icon: join(global.pathConfig.publicPath, "favicon.ico"),
  31. frame: false,
  32. show: false,
  33. minWidth: 680,
  34. minHeight: 550,
  35. titleBarStyle: "hiddenInset",
  36. webPreferences: {
  37. preload: global.pathConfig.preload,
  38. // Warning: Enable nodeIntegration and disable contextIsolation is not secure in production
  39. // Consider using contextBridge.exposeInMainWorld
  40. // Read more on https://www.electronjs.org/docs/latest/tutorial/context-isolation
  41. nodeIntegration: false,
  42. contextIsolation: true,
  43. sandbox: false,
  44. devTools: true,
  45. webSecurity: false,
  46. },
  47. });
  48. if (process.env.VITE_DEV_SERVER_URL) {
  49. // Open devTool if the app is not packaged
  50. mainWindow.loadURL(url);
  51. } else {
  52. mainWindow.loadFile(global.pathConfig.indexHtml);
  53. }
  54. // // Make all links open with the browser, not with the application
  55. mainWindow.webContents.setWindowOpenHandler(({ url }) => {
  56. if (url.startsWith("https:")) shell.openExternal(url);
  57. return { action: "deny" };
  58. });
  59. mainWindow.on("focus", () => {
  60. mainWindow?.flashFrame(false);
  61. registerShortcuts();
  62. });
  63. mainWindow.on("blur", () => {
  64. unregisterShortcuts();
  65. });
  66. mainWindow.on("close", (e) => {
  67. if (
  68. getIsForceQuit() ||
  69. !mainWindow.isVisible() ||
  70. store.get("closeAction") === "quit"
  71. ) {
  72. mainWindow = null;
  73. destroyTray();
  74. } else {
  75. e.preventDefault();
  76. if (isMac && mainWindow.isFullScreen()) {
  77. mainWindow.setFullScreen(false);
  78. }
  79. mainWindow?.hide();
  80. }
  81. });
  82. ipcMain.on('calling-window', createCallingWindow)
  83. return mainWindow;
  84. }
  85. export function createCallingWindow(event, msg) {
  86. if (callingWindow) {
  87. return
  88. }
  89. callingWindow = new BrowserWindow({
  90. title: "OpenIM calling -----",
  91. icon: join(global.pathConfig.publicPath, "favicon.ico"),
  92. modal: true,
  93. titleBarStyle: "default",
  94. webPreferences: {
  95. preload: global.pathConfig.preload,
  96. },
  97. });
  98. if (process.env.VITE_DEV_SERVER_URL) {
  99. // Open devTool if the app is not packaged
  100. callingWindow.loadURL(`${url}/#/calling`);
  101. } else {
  102. callingWindow.loadFile(global.pathConfig.callingHtml);
  103. }
  104. callingWindow.on('close',()=>{
  105. callingWindow = null
  106. })
  107. return callingWindow;
  108. }
  109. export function splashEnd() {
  110. splashWindow?.close();
  111. mainWindow?.show();
  112. }
  113. // utils
  114. export const isExistMainWindow = (): boolean =>
  115. !!mainWindow && !mainWindow?.isDestroyed();
  116. export const isShowMainWindow = (): boolean => {
  117. if (!mainWindow) return false;
  118. return mainWindow.isVisible() && (isWin ? true : mainWindow.isFocused());
  119. };
  120. export const closeWindow = () => {
  121. if (!mainWindow) return;
  122. mainWindow.close();
  123. };
  124. export const sendEvent = (name: string, ...args: any[]) => {
  125. if (!mainWindow) return;
  126. mainWindow.webContents.send(name, ...args);
  127. };
  128. export const minimize = () => {
  129. if (!mainWindow) return;
  130. mainWindow.minimize();
  131. };
  132. export const updateMaximize = () => {
  133. if (!mainWindow) return;
  134. if (mainWindow.isMaximized()) {
  135. mainWindow.unmaximize();
  136. } else {
  137. mainWindow.maximize();
  138. }
  139. };
  140. export const toggleHide = () => {
  141. if (!mainWindow) return;
  142. mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
  143. };
  144. export const toggleMinimize = () => {
  145. if (!mainWindow) return;
  146. if (mainWindow.isMinimized()) {
  147. if (!mainWindow.isVisible()) {
  148. mainWindow.show();
  149. }
  150. mainWindow.restore();
  151. mainWindow.focus();
  152. } else {
  153. mainWindow.minimize();
  154. }
  155. };
  156. export const showWindow = () => {
  157. if (!mainWindow) return;
  158. if (mainWindow.isMinimized()) {
  159. mainWindow.restore();
  160. }
  161. if (mainWindow.isVisible()) {
  162. mainWindow.focus();
  163. } else {
  164. mainWindow.show();
  165. }
  166. };
  167. export const hideWindow = () => {
  168. if (!mainWindow) return;
  169. mainWindow.hide();
  170. };
  171. export const setFullScreen = (isFullscreen: boolean): boolean => {
  172. if (!mainWindow) return false;
  173. if (isLinux) {
  174. // linux It needs to be resizable before it can be full screen
  175. if (isFullscreen) {
  176. mainWindow.setResizable(isFullscreen);
  177. mainWindow.setFullScreen(isFullscreen);
  178. } else {
  179. mainWindow.setFullScreen(isFullscreen);
  180. mainWindow.setResizable(isFullscreen);
  181. }
  182. } else {
  183. mainWindow.setFullScreen(isFullscreen);
  184. }
  185. return isFullscreen;
  186. };
  187. export const getWebContents = (): Electron.WebContents => {
  188. if (!mainWindow) throw new Error("main window is undefined");
  189. return mainWindow.webContents;
  190. };
  191. export const toggleDevTools = () => {
  192. if (!mainWindow) return;
  193. if (mainWindow.webContents.isDevToolsOpened()) {
  194. mainWindow.webContents.closeDevTools();
  195. } else {
  196. mainWindow.webContents.openDevTools({
  197. mode: "detach",
  198. });
  199. }
  200. };