mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-09-27 20:11:15 +02:00
feat: allow app to minimize on the systemTray. Could be disable on purpose.
This commit is contained in:
committed by
MasterAcnolo
parent
ce2a0485ab
commit
225ccf4d2d
@@ -228,6 +228,7 @@ Freedom Loader can be configured either through the settings panel in the UI or
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"autoUpdate": true,
|
"autoUpdate": true,
|
||||||
|
"systemTray": true,
|
||||||
"discordRPC": true,
|
"discordRPC": true,
|
||||||
"customTopBar": true,
|
"customTopBar": true,
|
||||||
"autoCheckInfo": true,
|
"autoCheckInfo": true,
|
||||||
@@ -252,6 +253,7 @@ Freedom Loader can be configured either through the settings panel in the UI or
|
|||||||
| Option | Type | Default | Description |
|
| Option | Type | Default | Description |
|
||||||
|------------------------------|---------|----------|------------------------------------------------------------|
|
|------------------------------|---------|----------|------------------------------------------------------------|
|
||||||
| `autoUpdate` | boolean | `true` | Enable automatic application updates |
|
| `autoUpdate` | boolean | `true` | Enable automatic application updates |
|
||||||
|
| `systemTray` | boolean | `true` | Allow app to minimize on close |
|
||||||
| `discordRPC` | boolean | `true` | Enable Discord Rich Presence integration |
|
| `discordRPC` | boolean | `true` | Enable Discord Rich Presence integration |
|
||||||
| `customTopBar` | boolean | `true` | Use custom application top bar |
|
| `customTopBar` | boolean | `true` | Use custom application top bar |
|
||||||
| `autoCheckInfo` | boolean | `true` | Automatically fetch video information on URL paste |
|
| `autoCheckInfo` | boolean | `true` | Automatically fetch video information on URL paste |
|
||||||
@@ -294,6 +296,7 @@ Freedom-Loader/
|
|||||||
│ ├── pathValidator.js
|
│ ├── pathValidator.js
|
||||||
│ ├── splashManager.js
|
│ ├── splashManager.js
|
||||||
│ ├── themeManager.js
|
│ ├── themeManager.js
|
||||||
|
│ ├── tray.js
|
||||||
│ ├── windowManager.js
|
│ ├── windowManager.js
|
||||||
│ └── ytDlpUpdater.js
|
│ └── ytDlpUpdater.js
|
||||||
├── build/ # Build resources and assets
|
├── build/ # Build resources and assets
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const { userThemesPath } = require("../server/helpers/path.helpers");
|
|||||||
*/
|
*/
|
||||||
const FEATURE_WHITELIST = new Set([
|
const FEATURE_WHITELIST = new Set([
|
||||||
"autoUpdate",
|
"autoUpdate",
|
||||||
|
"systemTray",
|
||||||
"discordRPC",
|
"discordRPC",
|
||||||
"customTopBar",
|
"customTopBar",
|
||||||
"autoCheckInfo",
|
"autoCheckInfo",
|
||||||
|
|||||||
100
app/tray.js
Normal file
100
app/tray.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
const {app, Menu, Tray, nativeImage} = require("electron");
|
||||||
|
const path = require("path");
|
||||||
|
const {logger} = require("../server/logger"); // Ajuste le chemin si besoin
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global reference to the Tray instance to prevent garbage collection.
|
||||||
|
* @type {Tray | null}
|
||||||
|
*/
|
||||||
|
let tray = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and configures the cross-platform System Tray.
|
||||||
|
*
|
||||||
|
* Responsibilities:
|
||||||
|
* - Load the appropriate icon for the OS.
|
||||||
|
* - Build the right-click context menu.
|
||||||
|
* - Handle left-click behavior (toggle window visibility).
|
||||||
|
*
|
||||||
|
* @param {import('electron').BrowserWindow} mainWindow - The main application window.
|
||||||
|
* @returns {Tray} The created Tray instance.
|
||||||
|
*/
|
||||||
|
function createSystemTray(mainWindow) {
|
||||||
|
// Prevent creating multiple instances
|
||||||
|
if (tray) return tray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the icon path.
|
||||||
|
* Tip: Use a .png for Linux/macOS and a .ico for Windows for best results.
|
||||||
|
* Here we use a generic PNG assuming it exists in your resources folder.
|
||||||
|
*/
|
||||||
|
const iconPath = config.devMode ?
|
||||||
|
path.join(__dirname, "..", "build", "app-icon-64x64.png") :
|
||||||
|
path.join(process.resourcesPath, "build", "app-icon-64x64.png");
|
||||||
|
|
||||||
|
if (!fs.existsSync(iconPath)) {
|
||||||
|
logger.error(`❌ ERREUR : L'icône du Tray est introuvable à ce chemin : ${iconPath}`);
|
||||||
|
} else {
|
||||||
|
logger.info(`✅ Icône trouvée pour le Tray !`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = nativeImage.createFromPath(iconPath);
|
||||||
|
tray = new Tray(icon);
|
||||||
|
tray.setToolTip("Freedom Loader");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The context menu (Right-click).
|
||||||
|
*/
|
||||||
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
|
{
|
||||||
|
label: "Show Freedom Loader",
|
||||||
|
click: () => {
|
||||||
|
mainWindow.show();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{type: "separator"},
|
||||||
|
{
|
||||||
|
label: "Quit",
|
||||||
|
click: () => {
|
||||||
|
/**
|
||||||
|
* Tell the app it's a deliberate exit,
|
||||||
|
* bypassing the "minimize to tray" behavior.
|
||||||
|
*/
|
||||||
|
app.isQuitting = true;
|
||||||
|
app.quit();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
tray.setContextMenu(contextMenu);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Left-click behavior: Toggle window visibility.
|
||||||
|
* Note: macOS doesn't usually use left-click on tray, but Windows/Linux do.
|
||||||
|
*/
|
||||||
|
tray.on("click", () => {
|
||||||
|
if (mainWindow.isVisible()) {
|
||||||
|
mainWindow.hide();
|
||||||
|
} else {
|
||||||
|
mainWindow.show();
|
||||||
|
mainWindow.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely destroys the tray icon to prevent OS-level crashes (especially on Linux/Wayland).
|
||||||
|
* Should be called right before the application quits.
|
||||||
|
*/
|
||||||
|
function destroyTray() {
|
||||||
|
if (tray && !tray.isDestroyed()) {
|
||||||
|
tray.destroy();
|
||||||
|
tray = null;
|
||||||
|
logger.info("System Tray destroyed cleanly.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {createSystemTray, destroyTray};
|
||||||
@@ -81,6 +81,19 @@ async function createMainWindow() {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts the window close event.
|
||||||
|
* If the app is not explicitly quitting (via Tray menu),
|
||||||
|
* cancels the destruction and hides the window instead.
|
||||||
|
*/
|
||||||
|
mainWindow.on('close', (event) => {
|
||||||
|
if (!app.isQuitting) {
|
||||||
|
event.preventDefault();
|
||||||
|
mainWindow.hide();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up window reference when the main window is closed.
|
* Cleans up window reference when the main window is closed.
|
||||||
* Prevents memory leaks and allows recreation if needed.
|
* Prevents memory leaks and allows recreation if needed.
|
||||||
|
|||||||
BIN
build/app-icon-64x64.png
Normal file
BIN
build/app-icon-64x64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"autoUpdate": true,
|
"autoUpdate": true,
|
||||||
|
"systemTray": true,
|
||||||
"discordRPC": true,
|
"discordRPC": true,
|
||||||
"customTopBar": true,
|
"customTopBar": true,
|
||||||
"autoCheckInfo": true,
|
"autoCheckInfo": true,
|
||||||
|
|||||||
13
main.js
13
main.js
@@ -80,7 +80,9 @@ const { createMainWindow, getMainWindow } = require("./app/windowManager");
|
|||||||
const { registerIpcHandlers } = require("./app/ipcHandlers");
|
const { registerIpcHandlers } = require("./app/ipcHandlers");
|
||||||
const { createSplashWindow, closeSplashWindow, setSplashProgress } = require("./app/splashManager");
|
const { createSplashWindow, closeSplashWindow, setSplashProgress } = require("./app/splashManager");
|
||||||
const { userThemesPath, initUserThemes, isWindows, validateBinaries, defaultDownloadFolder } = require("./server/helpers/path.helpers");
|
const { userThemesPath, initUserThemes, isWindows, validateBinaries, defaultDownloadFolder } = require("./server/helpers/path.helpers");
|
||||||
|
const {createSystemTray, destroyTray} = require("./app/tray");
|
||||||
|
|
||||||
|
app.isQuitting = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If another instance want to run
|
* If another instance want to run
|
||||||
@@ -127,6 +129,11 @@ app.whenReady().then(async () => {
|
|||||||
|
|
||||||
closeSplashWindow();
|
closeSplashWindow();
|
||||||
getMainWindow().show();
|
getMainWindow().show();
|
||||||
|
|
||||||
|
if (configFeatures.systemTray) {
|
||||||
|
createSystemTray(getMainWindow());
|
||||||
|
}
|
||||||
|
|
||||||
if (configFeatures.discordRPC) startRPC();
|
if (configFeatures.discordRPC) startRPC();
|
||||||
|
|
||||||
if (configFeatures.autoUpdate) initAutoUpdater(getMainWindow());
|
if (configFeatures.autoUpdate) initAutoUpdater(getMainWindow());
|
||||||
@@ -138,11 +145,17 @@ app.whenReady().then(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.on("window-all-closed", () => {
|
app.on("window-all-closed", () => {
|
||||||
|
if (app.isQuitting) {
|
||||||
logger.info("Shutting down...");
|
logger.info("Shutting down...");
|
||||||
app.quit();
|
app.quit();
|
||||||
|
} else if (process.platform !== "darwin") {
|
||||||
|
logger.info("Main window closed, app running in background (Tray).");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on("before-quit", async () => {
|
app.on("before-quit", async () => {
|
||||||
|
app.isQuitting = true;
|
||||||
|
destroyTray();
|
||||||
await stopRPC();
|
await stopRPC();
|
||||||
logger.info("All services stopped. Have a nice day!");
|
logger.info("All services stopped. Have a nice day!");
|
||||||
logSessionEnd();
|
logSessionEnd();
|
||||||
|
|||||||
@@ -127,6 +127,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="setting-item">
|
||||||
|
<input data-key="systemTray" id="systemTray" type="checkbox">
|
||||||
|
<div class="setting-info">
|
||||||
|
<span class="setting-title">System Tray</span>
|
||||||
|
<small>Minimize app on close, in the System Tray.</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <div class="setting-item">
|
<!-- <div class="setting-item">
|
||||||
<input type="checkbox" data-key="outputTitleCheck" id="outputTitleCheck">
|
<input type="checkbox" data-key="outputTitleCheck" id="outputTitleCheck">
|
||||||
<div class="setting-info">
|
<div class="setting-info">
|
||||||
|
|||||||
Reference in New Issue
Block a user