Removed Cyberpunk | Spicy | Vilbrequin Theme, Info Fix, Fix Progress Bar. Centralized Ressources

This commit is contained in:
MasterAcnolo
2025-11-14 23:41:03 +01:00
parent c2e4e12512
commit cdca4a82ab
16 changed files with 805 additions and 4256 deletions

View File

@@ -1,25 +0,0 @@
const { FusesPlugin } = require('@electron-forge/plugin-fuses');
const { FuseV1Options, FuseVersion } = require('@electron/fuses');
module.exports = {
packagerConfig: { asar: true },
rebuildConfig: {},
makers: [
{
name: '@electron-forge/maker-squirrel',
config: {},
},
],
plugins: [
{ name: '@electron-forge/plugin-auto-unpack-natives', config: {} },
new FusesPlugin({
version: FuseVersion.V1,
[FuseV1Options.RunAsNode]: false,
[FuseV1Options.EnableCookieEncryption]: true,
[FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
[FuseV1Options.EnableNodeCliInspectArguments]: false,
[FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
[FuseV1Options.OnlyLoadAppFromAsar]: true,
}),
],
};

View File

@@ -20,7 +20,7 @@ if (!gotLock) {
});
}
app.disableHardwareAcceleration(); // safe sur GPU old / soucis Electron
app.disableHardwareAcceleration();
const logsFolderPath = logDir;
const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader");
@@ -110,7 +110,9 @@ app.whenReady().then(async () => {
logSessionStart();
logger.info("App prête, démarrage du serveur Express...");
const expressServer = require("./server/server.js");
const serverPath = path.join(__dirname, "server", "server.js");
const expressServer = require(serverPath);
try {
await expressServer.startServer();
logger.info("Serveur Express démarré");

4771
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
"description": "Freedom Loader",
"main": "main.js",
"scripts": {
"start": "electron-forge start",
"start": "electron .",
"dist": "electron-builder"
},
"dependencies": {
@@ -16,18 +16,11 @@
"electron-squirrel-startup": "^1.0.1",
"electron-updater": "^6.6.2",
"express": "^5.1.0",
"webidl-conversions": "^8.0.0",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0"
},
"devDependencies": {
"@electron-forge/cli": "^7.8.1",
"@electron-forge/maker-deb": "^7.8.1",
"@electron-forge/maker-rpm": "^7.8.1",
"@electron-forge/maker-squirrel": "^7.8.1",
"@electron-forge/maker-zip": "^7.8.1",
"@electron-forge/plugin-auto-unpack-natives": "^7.8.1",
"@electron-forge/plugin-fuses": "^7.8.1",
"@electron/fuses": "^1.8.0",
"electron": "^37.1.0",
"electron-builder": "^26.0.12"
},
@@ -44,7 +37,9 @@
"files": [
"**/*",
"node_modules/**/*",
"!logs/*.json"
"!logs/*.json",
"server/**/*",
"server/node_modules/**/*"
],
"directories": {
"buildResources": "build"
@@ -70,6 +65,10 @@
{
"from": "ressources/ffprobe.exe",
"to": "ffprobe.exe"
},
{
"from": "server",
"to": "server"
}
],
"win": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 805 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,6 +1,3 @@
// Définition des thèmes disponibles
// Chaque thème a un label (affiché dans le select) et un subtitle (texte sous le titre)
const themes = {
default: { label: "Default", subtitle: "Because why not?" },
dark: { label: "Sombre", subtitle: "Darkness is my ally" },
@@ -9,16 +6,11 @@ const themes = {
nf: { label: "NF", subtitle: "You call it music, i call it my Therapist" },
drift: { label: "Drift", subtitle: "Si la route t'appelle, contre appel" },
fanatic: { label: "Fanatic", subtitle: "Always Fnatic !" },
cyberpunk: { label: "Cyberpunk", subtitle: "Wake up, choom. Weve got a city to burn." },
chirac: { label: "Chirac", subtitle: "J'aime les pommes" },
spicy: { label: "Spicy", subtitle: "The Spiciest One" },
vilbrequin: { label: "Vilbrequin", subtitle: "Rend l'argent" }
};
const themeSelect = document.getElementById("themeSelect");
// Remplir le select avec les options à partir du dictionnaire
function populateThemeSelect() {
for (const [themeKey, themeInfo] of Object.entries(themes)) {
const option = document.createElement("option");
@@ -28,14 +20,10 @@ function populateThemeSelect() {
}
}
// Appliquer un thème sur le body et mettre à jour le subtitle
function applyTheme(themeKey) {
// Supprimer les classes de tous les thèmes
document.body.classList.remove(...Object.keys(themes));
// Ajouter la classe correspondant au thème sélectionné
document.body.classList.add(themeKey);
// Mettre à jour le subtitle
const subtitleElement = document.getElementById("subtitle");
if (subtitleElement && themes[themeKey]) {
subtitleElement.textContent = themes[themeKey].subtitle;
@@ -43,12 +31,10 @@ function applyTheme(themeKey) {
}
// Sauvegarder le thème choisi dans le navigateur
function saveTheme(themeKey) {
localStorage.setItem("selectedTheme", themeKey);
}
// Charger le thème sauvegardé au démarrage
function loadTheme() {
const savedTheme = localStorage.getItem("selectedTheme");

View File

@@ -18,7 +18,7 @@ form.addEventListener("submit", async (e) => {
});
if (!res.ok) {
statusDiv.textContent = "❌ Erreur pendant le téléchargement.";
statusDiv.textContent = res;
return;
}

View File

@@ -16,14 +16,27 @@ function resetProgress() {
progressWrapper.style.display = "none";
}
function resetProgressFile() {
progressBar.style.width = "0%";
// progressWrapper reste visible
}
// Connexion SSE, c'est Server-sent events est une technologie grâce à laquelle un navigateur reçoit des mises à jour automatiques à partir d'un serveur via une connexion HTTP.
const evtSource = new EventSource("/download/progress");
evtSource.onmessage = e => {
if (e.data === "reset") {
startProgress();
return;
}
if (e.data === "done") {
resetProgress();
return;
}
const percent = parseFloat(e.data);
if (!isNaN(percent)) {
updateProgress(percent);
if (percent >= 100) {
setTimeout(resetProgress, 500);
}
if (percent >= 100) setTimeout(resetProgressFile, 500);
}
};
};

View File

@@ -1,43 +0,0 @@
body.cyberpunk {
background-image: url('../../assets/images/Cyberpunk.webp');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
/* Couleurs générales */
--background-color: #0d0d0d;
--default-text-color: #e0e0e0;
--subtitle-color: #ffea00;
--mp3-text-color: #ffea00;
/* Formulaire */
--form-bg-color: #141414;
--form-input-bg-color: #1a1a1a;
--form-input-border-color: #333333;
--form-input-border-focus-color: #ffea00;
--form-input-text-color: #e0e0e0;
--form-input-placeholder-color: #777777;
--form-button-bg-color: #ffea00;
--form-button-text-color: #0d0d0d;
--form-button-bg-hover-color: #d4c000;
/* Checkbox */
--checkbox-bg-default: #333333;
--checkbox-bg-checked: #ffea00;
--checkbox-checkmark-border-color: #0d0d0d;
--checkbox-pulse-color: rgba(255, 234, 0, 0.5);
/* Download status */
--download-status-color: #fffbd1;
/* Video Info Box */
--infos-box-color: #1a1a1a;
--video-info-text-color: #e0e0e0;
--video-info-heading-color: #ffea00;
--video-info-list-color: #cccccc;
--video-info-list-strong-color: #ffffff;
--video-info-link-color: #ffea00;
--video-info-link-hover-color: #d4c000;
}

View File

@@ -1,43 +0,0 @@
body.spicy {
background-image: url('../../assets/images/spicy.webp');
background-size:contain;
background-position: center;
background-attachment: fixed;
background-repeat: no-repeat;
/* Couleurs générales */
--background-color: #121212;
--default-text-color: #581010;
--subtitle-color: #3d0909;
--mp3-text-color: #ffffff;
/* Formulaire */
--form-bg-color: #1a1a1a;
--form-input-bg-color: #2b2b2b;
--form-input-border-color: #444444;
--form-input-border-focus-color: #ff1a1a;
--form-input-text-color: #eeeeee;
--form-input-placeholder-color: #888888;
--form-button-bg-color: #ff1a1a;
--form-button-text-color: #ffffff;
--form-button-bg-hover-color: #cc0000;
/* Checkbox */
--checkbox-bg-default: #555555;
--checkbox-bg-checked: #ff1a1a;
--checkbox-checkmark-border-color: #f5f5f5;
--checkbox-pulse-color: rgba(255, 26, 26, 0.5);
/* Download status */
--download-status-color: #ffffff;
/* Video Info Box */
--infos-box-color: #1a1a1a;
--video-info-text-color: #f5f5f5;
--video-info-heading-color: #ff1a1a;
--video-info-list-color: #cccccc;
--video-info-list-strong-color: #ffffff;
--video-info-link-color: #ff1a1a;
--video-info-link-hover-color: #cc0000;
}

View File

@@ -1,46 +0,0 @@
body.vilbrequin {
background-image: url('../../assets/images/Vilbrequin.webp');
background-size: cover;
background-position: center;
background-attachment: fixed;
/* Couleurs générales */
--background-color: #0a1f3d;
--default-text-color: #535353;
--subtitle-color: #001696;
--mp3-text-color: #ffffff;
/* Formulaire */
--form-bg-color: #12284f;
--form-input-bg-color: #1c3760;
--form-input-border-color: #2a4b80;
--form-input-border-focus-color: #00bfff;
--form-input-text-color: #f0f0f0;
--form-input-placeholder-color: #b0c4de;
--form-button-bg-color: #ffd700;
--form-button-text-color: #0a1f3d;
--form-button-bg-hover-color: #e6c200;
/* Checkbox */
--checkbox-bg-default: #2a4b80;
--checkbox-bg-checked: #00bfff;
--checkbox-checkmark-border-color: #f0f0f0;
--checkbox-pulse-color: rgba(0,191,255,0.5);
/* Download status */
--download-status-color: #ffd700;
/* Video Info Box */
--infos-box-color: #12284f;
--video-info-text-color: #f0f0f0;
--video-info-heading-color: #00bfff;
--video-info-list-color: #dcdcdc;
--video-info-list-strong-color: #ffffff;
--video-info-link-color: #00bfff;
--video-info-link-hover-color: #009acd;
}
body.vilbrequin .download-path{
color: white;
}

View File

@@ -4,15 +4,20 @@ const { app } = require("electron");
const config = require("../../config");
let userYtDlp;
let ffmpegPath;
const sourceYtDlp = path.join(process.resourcesPath, "yt-dlp.exe");
if (config.localMode === true) {
userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe");
if (config.localMode) {
userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe");
ffmpegPath = path.join(__dirname, "../../ressources/ffmpeg.exe");
} else {
userYtDlp = path.join(app.getPath("userData"), "yt-dlp.exe");
ffmpegPath = path.join(process.resourcesPath, "ffmpeg.exe");
userYtDlp = path.join(app.getPath("userData"), "yt-dlp.exe");
if (!fs.existsSync(userYtDlp)) fs.copyFileSync(sourceYtDlp, userYtDlp);
if (!fs.existsSync(userYtDlp)) {
fs.copyFileSync(sourceYtDlp, userYtDlp);
}
}
module.exports = { userYtDlp, sourceYtDlp };
module.exports = { userYtDlp, sourceYtDlp, ffmpegPath };

View File

@@ -9,7 +9,6 @@ const config = require("../../config");
const { isValidUrl, isSafePath } = require("../helpers/validation");
const { buildYtDlpArgs } = require("../helpers/buildArgs");
const { notifyDownloadFinished } = require("../helpers/notify");
const { userYtDlp } = require("../helpers/path");
const listeners = [];
@@ -23,43 +22,62 @@ router.post("/", (req, res) => {
outputFolder: req.body.savePath || path.join(process.env.USERPROFILE, "Downloads", "Freedom Loader"),
};
// Vérifications
if (!options.url || !isValidUrl(options.url)) return res.status(400).send("❌ URL invalide !");
if (!isSafePath(options.outputFolder)) return res.status(400).send("❌ Chemin de sauvegarde non autorisé.");
// Création dossier si inexistant
fs.mkdirSync(options.outputFolder, { recursive: true });
// Construire les arguments yt-dlp
const args = buildYtDlpArgs(options);
logger.info(args)
logger.info(`[yt-dlp args] ${args.join(" ")}`);
const child = execFile(userYtDlp, args);
// Gestion erreurs
child.on("error", err => {
logger.error(`Erreur yt-dlp : ${err.message}`);
res.status(500).send(`❌ Erreur yt-dlp : ${err.message}`);
});
// Téléchargement terminé
child.on("close", code => {
if (code === 0) {
notifyDownloadFinished(options.outputFolder);
// signal SSE fin de playlist
listeners.forEach(fn => fn("done"));
res.send("✅ Téléchargement terminé !");
} else res.status(500).send(`❌ yt-dlp a échoué avec le code : ${code}`);
} else {
res.status(500).send(`❌ yt-dlp a échoué avec le code : ${code}`);
listeners.forEach(fn => fn("done"));
}
});
if (config.debugMode == true) {
child.stdout.on("data", data => data.toString().split("\n").forEach(line => line.trim() && logger.info(`[yt-dlp stdout] ${line}`)));
child.stderr.on("data", data => data.toString().split("\n").forEach(line => line.trim() && logger.error(`[yt-dlp stderr] ${line}`)));
}
child.stdout.on("data", data => {
data.toString().split("\n").forEach(line => line.trim() && logger.info(`[yt-dlp stdout] ${line}`));
});
child.stderr.on("data", data => {
data.toString().split("\n").forEach(line => line.trim() && logger.error(`[yt-dlp stderr] ${line}`));
});
child.stdout.on("data", data => {
const lines = data.toString().split("\n");
lines.forEach(line => {
// reset progress si nouveau fichier
if (line.startsWith("[download] Destination:")) {
listeners.forEach(fn => fn("reset")); // tu peux envoyer un signal spécial
}
// envoyer le % classique
const match = line.match(/\[download\]\s+(\d+\.\d+)%/);
if (match) {
const percent = parseFloat(match[1]);
if (listeners.length > 0) {
listeners.forEach(fn => fn(percent));
}
listeners.forEach(fn => fn(percent));
}
});
});
@@ -78,10 +96,7 @@ router.get("/progress", (req, res) => {
'Connection': 'keep-alive',
});
const sendProgress = (percent) => {
res.write(`data: ${percent}\n\n`);
};
const sendProgress = percent => res.write(`data: ${percent}\n\n`);
listeners.push(sendProgress);
req.on('close', () => {
@@ -90,5 +105,4 @@ router.get("/progress", (req, res) => {
});
});
module.exports = router;
module.exports = router;

View File

@@ -28,7 +28,9 @@ router.post("/", (req, res) => {
"--cookies-from-browser",
`${getUserBrowser()}`,
"--extractor-args",
"youtube:player_client=default"
"youtube:player_client=default",
"--ignore-no-formats-error"
];
execFile(userYtDlp, args, { timeout: 30_000, maxBuffer: 10 * 1024 * 1024 }, (error, stdout, stderr) => {