Initial Commit ...

This commit is contained in:
2026-04-17 17:04:44 +03:30
commit a986295e19
842 changed files with 97431 additions and 0 deletions
+460
View File
@@ -0,0 +1,460 @@
//
//#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