461 lines
9.6 KiB
JavaScript
461 lines
9.6 KiB
JavaScript
//
|
|
//#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
|