mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-07-29 18:25:47 +02:00
Push avant Clean
This commit is contained in:
71
public/script/custompath.js
Normal file
71
public/script/custompath.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
This file is part of Freedom Loader.
|
||||
|
||||
Copyright (C) 2025 MasterAcnolo
|
||||
|
||||
Freedom Loader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License.
|
||||
|
||||
Freedom Loader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Ce script attend que le DOM soit complètement chargé pour initialiser
|
||||
l'affichage et la gestion du chemin de sauvegarde personnalisé.
|
||||
|
||||
1. Récupère le chemin de téléchargement par défaut depuis le main process via l'API exposée.
|
||||
2. Met à jour le texte affiché dans l'élément avec l'id "savePath".
|
||||
3. Crée un input caché nommé "savePath" dans le formulaire pour envoyer ce chemin lors du submit.
|
||||
4. Ajoute un écouteur sur le bouton "changePath" pour permettre à l'utilisateur
|
||||
de choisir un dossier via une boîte de dialogue native.
|
||||
5. Met à jour l'affichage et la valeur cachée du chemin sélectionné.
|
||||
*/
|
||||
|
||||
window.addEventListener("DOMContentLoaded", async () => {
|
||||
const savePathElem = document.getElementById("savePath");
|
||||
|
||||
// 1️Essayer de charger depuis le localStorage
|
||||
let savedPath = localStorage.getItem("customDownloadPath");
|
||||
|
||||
// 2️Sinon demander le chemin par défaut à l'API Electron
|
||||
if (!savedPath) {
|
||||
savedPath = await window.electronAPI.getDefaultDownloadPath();
|
||||
}
|
||||
|
||||
// 3 Afficher le chemin
|
||||
if (savePathElem) {
|
||||
savePathElem.textContent = savedPath;
|
||||
}
|
||||
|
||||
// Créer l'input caché s'il n'existe pas déjà
|
||||
let hidden = document.getElementById("savePathInput");
|
||||
if (!hidden) {
|
||||
hidden = document.createElement("input");
|
||||
hidden.type = "hidden";
|
||||
hidden.name = "savePath";
|
||||
hidden.id = "savePathInput";
|
||||
document.getElementById("downloadForm").appendChild(hidden);
|
||||
}
|
||||
hidden.value = savedPath;
|
||||
|
||||
// Gestion du bouton de modification
|
||||
document.getElementById("changePath").addEventListener("click", async () => {
|
||||
const selectedPath = await window.electronAPI.selectDownloadFolder();
|
||||
if (selectedPath) {
|
||||
// Met à jour l'affichage
|
||||
savePathElem.textContent = selectedPath;
|
||||
hidden.value = selectedPath;
|
||||
|
||||
// Et le stocke en localStorage pour la prochaine fois
|
||||
localStorage.setItem("customDownloadPath", selectedPath);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
92
public/script/customthemes.js
Normal file
92
public/script/customthemes.js
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
This file is part of Freedom Loader.
|
||||
|
||||
Copyright (C) 2025 MasterAcnolo
|
||||
|
||||
Freedom Loader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License.
|
||||
|
||||
Freedom Loader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// 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" },
|
||||
light: { label: "Clair", subtitle: "Qui aime ce thème ?" },
|
||||
neon: { label: "Néon", subtitle: "How was your day ?"},
|
||||
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. We’ve 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");
|
||||
option.value = themeKey;
|
||||
option.textContent = themeInfo.label;
|
||||
themeSelect.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
if (savedTheme && themes[savedTheme]) {
|
||||
applyTheme(savedTheme);
|
||||
themeSelect.value = savedTheme;
|
||||
} else {
|
||||
applyTheme("dark"); // thème par défaut
|
||||
themeSelect.value = "dark";
|
||||
}
|
||||
}
|
||||
|
||||
// Quand l'utilisateur change le thème depuis le select
|
||||
themeSelect.addEventListener("change", (event) => {
|
||||
const selectedTheme = event.target.value;
|
||||
if (themes[selectedTheme]) {
|
||||
applyTheme(selectedTheme);
|
||||
saveTheme(selectedTheme);
|
||||
}
|
||||
});
|
||||
|
||||
// Initialisation
|
||||
populateThemeSelect();
|
||||
loadTheme();
|
||||
55
public/script/downloadstatus.js
Normal file
55
public/script/downloadstatus.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
This file is part of Freedom Loader.
|
||||
|
||||
Copyright (C) 2025 MasterAcnolo
|
||||
|
||||
Freedom Loader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License.
|
||||
|
||||
Freedom Loader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const form = document.getElementById("downloadForm");
|
||||
const statusDiv = document.getElementById("downloadStatus");
|
||||
const button = form.querySelector("button");
|
||||
|
||||
form.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
button.disabled = true; // Empêche les clics multiples
|
||||
statusDiv.textContent = "Téléchargement en cours...";
|
||||
|
||||
const formData = new FormData(form);
|
||||
const params = new URLSearchParams(formData);
|
||||
|
||||
try {
|
||||
const res = await fetch("/download", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: params,
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
statusDiv.textContent = "❌ Erreur pendant le téléchargement.";
|
||||
return;
|
||||
}
|
||||
|
||||
const text = await res.text();
|
||||
statusDiv.textContent = text;
|
||||
|
||||
} catch {
|
||||
statusDiv.textContent = "❌ Une erreur s’est produite.";
|
||||
} finally {
|
||||
button.disabled = false;
|
||||
|
||||
setTimeout(() => {
|
||||
statusDiv.textContent = "";
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
122
public/script/fetchinfo.js
Normal file
122
public/script/fetchinfo.js
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
This file is part of Freedom Loader.
|
||||
|
||||
Copyright (C) 2025 MasterAcnolo
|
||||
|
||||
Freedom Loader is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License.
|
||||
|
||||
Freedom Loader is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr || dateStr.length !== 8) return "Inconnue";
|
||||
return `${dateStr.slice(6,8)}/${dateStr.slice(4,6)}/${dateStr.slice(0,4)}`;
|
||||
}
|
||||
|
||||
function formatSize(bytes) {
|
||||
return bytes ? (bytes / (1024*1024)).toFixed(2) + " Mo" : "Inconnue";
|
||||
}
|
||||
|
||||
async function fetchVideoInfo(url) {
|
||||
try {
|
||||
const res = await fetch("/info", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
body: new URLSearchParams({ url }),
|
||||
});
|
||||
|
||||
if (!res.ok) return { error: `Erreur serveur: ${res.status}` };
|
||||
|
||||
const data = await res.json();
|
||||
if (!data) return { error: "Données manquantes" };
|
||||
|
||||
return data;
|
||||
} catch (e) {
|
||||
return { error: "Erreur réseau ou JSON" };
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const urlInput = document.getElementById("UrlInput");
|
||||
const infoDiv = document.getElementById("videoInfo");
|
||||
let lastFetchedUrl = "";
|
||||
|
||||
urlInput.addEventListener("input", async () => {
|
||||
const url = urlInput.value.trim();
|
||||
|
||||
if (!url || url.length < 5) {
|
||||
infoDiv.innerHTML = "";
|
||||
infoDiv.classList.remove("visible");
|
||||
lastFetchedUrl = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (url === lastFetchedUrl) return;
|
||||
lastFetchedUrl = url;
|
||||
|
||||
const data = await fetchVideoInfo(url);
|
||||
if (data.error) {
|
||||
infoDiv.innerHTML = `❌ ${data.error}`;
|
||||
infoDiv.classList.remove("visible");
|
||||
return;
|
||||
}
|
||||
|
||||
// Playlist
|
||||
if (data.type === "playlist") {
|
||||
infoDiv.innerHTML = `
|
||||
<p style="color:orange;"><strong>Playlist détectée – ${data.count} vidéos</strong></p>
|
||||
<h3>${data.title}</h3>
|
||||
<p><strong>Channel :</strong> ${data.channel || "Inconnu"}</p>
|
||||
<div id="playlistVideos"></div>
|
||||
`;
|
||||
const listDiv = document.getElementById("playlistVideos");
|
||||
data.videos.forEach(v => {
|
||||
const durationStr = `${Math.floor(v.duration/60)}m ${(v.duration%60).toString().padStart(2,"0")}s`;
|
||||
listDiv.innerHTML += `
|
||||
<div style="margin-bottom:12px;">
|
||||
<img src="${v.thumbnail}" width="160" alt="Thumbnail">
|
||||
<p><strong>${v.title}</strong></p>
|
||||
<p>Durée : ${durationStr}</p>
|
||||
<p>URL : <a href="${v.webpage_url}" target="_blank">${v.webpage_url}</a></p>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
infoDiv.classList.add("visible");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Vidéo normale
|
||||
const durationStr = `${Math.floor(data.duration/60)}m ${(data.duration%60)
|
||||
.toString()
|
||||
.padStart(2,"0")}s`;
|
||||
const sizeStr = formatSize(data.filesize_approx);
|
||||
const readableDate = formatDate(data.upload_date);
|
||||
const categories = data.categories?.join(", ") || "Non spécifiées";
|
||||
|
||||
infoDiv.innerHTML = `
|
||||
<h3>${data.title}</h3>
|
||||
<img src="${data.thumbnail}" width="320" alt="Thumbnail">
|
||||
<ul>
|
||||
<li><strong>Durée :</strong> ${durationStr}</li>
|
||||
<li><strong>Uploader :</strong> ${data.uploader || "Inconnu"}</li>
|
||||
<li><strong>Date d’upload :</strong> ${readableDate}</li>
|
||||
<li><strong>Vues :</strong> ${data.view_count?.toLocaleString() || "?"}</li>
|
||||
<li><strong>Likes :</strong> ${data.like_count?.toLocaleString() || "?"}</li>
|
||||
<li><strong>URL :</strong> <a href="${data.webpage_url}" target="_blank">${data.webpage_url}</a></li>
|
||||
<li><strong>Channel :</strong> <a href="${data.channel_url}" target="_blank">${data.channel_url}</a></li>
|
||||
<li><strong>Taille estimée :</strong> ${sizeStr}</li>
|
||||
<li><strong>Catégories :</strong> ${categories}</li>
|
||||
</ul>
|
||||
`;
|
||||
infoDiv.classList.add("visible");
|
||||
});
|
||||
})
|
||||
Reference in New Issue
Block a user