// //#region Required Modules ... const url = require("url"); const path = require("path"); const { Subject } = require("rxjs"); const uuid = require("./modules/tools/x-uuid.tools"); const XLogger = require("./modules/tools/x-logger.tools"); const windowManager = require('./modules/tools/x-window.tools'); const { XElectronChannel, XElectronMessage } = require('./modules/services/x-electron.service'); const { app, shell, Tray, ipcMain, BrowserWindow, Menu } = require("electron"); //#endregion // //#region Prepare Required Config Data ... // // Set Environment ... process.env.NODE_ENV = 'production'; // const isDevelopment = process.env.NODE_ENV !== "production" ? true : false; // app.isPackaged; const isMac = process.platform === "darwin" ? true : false; // // Show Logs ... const showLogs = false; // // Show Debug Window ... const showDebug = false; // // Force Window to show fullscreen ... const isFullscreen = false; // // Show Window on Startup ... const showWindowOnStartup = true; // const iconPath = path.join(__dirname, "www/assets/icon/favicon.png"); const trayIconPath = path.join(__dirname, "www/assets/icon/icon-16x16.png"); //#endregion // //#region Handle Logging ... if (showLogs) { XLogger.enableLogging(); } else { XLogger.disableLogging(); } // console.log('XLogger State: ', XLogger.isLoggingEnable()); //#endregion // //#region Global Objects ... // let tray; let mainUrl; let mainWindow; let mainWindowID; // const appId = uuid.generateUuid('XFrameworkElectronApp'); //#endregion // //#region Subscribers ... // const otherChannelsSubject = new Subject(); const defaultChannelSubject = new Subject(); const handShakeChannelSubject = new Subject(); // // Register Handshake Handler ... handShakeChannelSubject .asObservable() .subscribe(message => { // XLogger.logWarn( XLogger.XLogMessage( XLogger.XLogTag.Warn, `Handshake Channel`, [message] ) ); }); // // Register Default Handler ... defaultChannelSubject .asObservable() .subscribe(message => { // XLogger.logWarn( XLogger.XLogMessage( XLogger.XLogTag.Warn, `Default Channel`, [message] ) ); }); // // Register Other Handler ... otherChannelsSubject .asObservable() .subscribe(async message => { // XLogger.logWarn( XLogger.XLogMessage( XLogger.XLogTag.Warn, `Other Channel`, [message] ) ); // // File Service ... if (message && message.channel === XElectronChannel.FileService) { await handleFileServiceAction(message); } // // Projects Service ... if (message && message.channel === XElectronChannel.ProjectsService) { await handleProjectsServiceAction(message); } }); //#endregion // //#region Creator Fuctions ... /** * Creat SysTray Object for using in app ... */ function createTray() { // // Create Tray Instance ... tray = new Tray(trayIconPath); XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Tray Created ...')); // // Attach Event Listener to Tray Click ... tray.on("click", () => { // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Tray Clicked ...')); // toggleMainWindow(); }); // // Attach Event Listener to Tray RightClick ... tray.on("right-click", () => { // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Tray Right Clicked ...')); // const contextMenu = Menu.buildFromTemplate([ { label: "quit", click: () => { // app.isClosing = true; app.quit(); }, }, ]); // tray.popUpContextMenu(contextMenu); }); } /** * Create Main Window Instance ... */ function createWindow() { // // Create Main Window ... mainWindow = new BrowserWindow({ icon: iconPath, show: showWindowOnStartup, width: isDevelopment ? 1200 : 800, height: isDevelopment ? 800 : 600, webPreferences: { nodeIntegration: true, contextIsolation: false }, }); // // Handle FullScreen state if Window shown on startup ... if (isFullscreen && showWindowOnStartup) { mainWindow.maximize(); mainWindow.setFullScreen(true); } // // Generate Main Windows UUID ... mainWindowID = uuid.generateUuid("XFrameworkElectronWindow"); mainWindow.name = mainWindowID; XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Window ${mainWindowID} Created ...`)); // // Fix new Window Open action ... mainWindow.webContents.on("new-window", function (e, url) { e.preventDefault(); // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'New Window Requested ...')); // shell.openExternal(url); }); // // Handle load Main Url on Navigate for handling Navigation on Angular Apps ... mainWindow.webContents.on("will-navigate", function (e, url) { e.preventDefault(); // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Window Will Navigate Called ...')); // mainWindow.loadURL(mainUrl); }); // // Prepare Main Url ... mainUrl = url.format({ pathname: path.join(__dirname, "/www/index.html"), protocol: "file", slashes: true, }); // // Load Content on Main Window ... mainWindow.loadURL(mainUrl); // // Remove Browser Window Default menu ... mainWindow.removeMenu(); // // Open Dev Tools on Development environment ... if (showDebug) { // mainWindow.webContents.openDevTools(); XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, 'Window Dev Tools Opened ...')); } // // Handle Window Closed ... mainWindow.on("closed", () => { // mainWindow = null; windowManager.remove(mainWindowID); // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Window ${mainWindowID} Closed ...`)); }); // // Handle Window Close ... mainWindow.on("close", (e) => { // if (!app.isClosing) { // e.preventDefault(); // mainWindow.hide(); // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Window ${mainWindowID} Hided ...`)); } // return true; }); // // Send Handshake Message to Angular App for Notifing id of main window ... mainWindow.webContents.on("did-finish-load", () => { // // Instancing new Message for Sending ... const handshakeMsg = new XElectronMessage( appId, mainWindowID, undefined, undefined, XElectronChannel.Handshake, new Date().getTime() ); // // Sending Handshake Message to MainWindow ... sendMessage(handshakeMsg); // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `sending Handshake to Window ${mainWindowID} ...`)); }); // //#region IPC Handlers ... // // Register Event Handler for HandShake ... ipcMain.on(XElectronChannel.Handshake, (event, message) => { // if (!message || !message.sender) { return; } // const windowID = message.sender; windowManager.set(windowID, mainWindow); // handShakeChannelSubject.next(message); }); // // Register Event Handler for Message ... ipcMain.on(XElectronChannel.Default, (event, message) => { defaultChannelSubject.next(message); }); // const channels = Object.assign({}, XElectronChannel); delete channels.Default; delete channels.Handshake; // Object.keys(channels).forEach(channel => { // // Register Event Handler for Message on other Channel ... ipcMain.on(channels[channel], (event, message) => { otherChannelsSubject.next(message); }); }); //#endregion } /** * Toggle Show/Hide Main Window ... */ function toggleMainWindow() { // if (!mainWindow) { return; } // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `Toggle Window ...`)); // if (mainWindow.isVisible()) { mainWindow.hide(); } else { // if (isFullscreen) { mainWindow.maximize(); mainWindow.setFullScreen(true); } mainWindow.show(); } } //#endregion // //#region Event Emitters ... /** * attach event to call when it's ready, to app object ... */ app.whenReady().then(() => { // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `App Ready ...`)); // createTray(); createWindow(); }); /** * attach event to call when all application Windows closed, to app object ... */ app.on("window-all-closed", () => { // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `All Windows Closed ...`)); // if (!isMac) { app.quit(); } }); /** * attach event to call when application activated, to app object ... */ app.on("activate", () => { // XLogger.logDebug(XLogger.XLogMessage(XLogger.XLogTag.Debug, `App Activated ...`)); // if (!mainWindow) { createWindow(); } }); //#endregion // //#region Window Comminucations ... /** * send a message to specified window ... * * @param {XElectronMessageDto} message the message which required to send ... */ function sendMessage(message) { // if (!message) { return; } // if (!message.sender) { message.sender = appId; } // if (!message.reciever) { message.reciever = mainWindowID; } // let destWindow = undefined; if (windowManager.count() === 0) { destWindow = mainWindow; } else { destWindow = windowManager.get(message.reciever); } // if (!destWindow) { // const errorMessage = 'Dest Window not found ...'; XLogger.logError(XLogger.XLogMessage(XLogger.XLogTag.Error, errorMessage)) throw errorMessage; } // // Sending Message to Window ... destWindow.webContents.send( message.channel, JSON.stringify(message) ); } //#endregion