mirror of
https://github.com/MasterAcnolo/Freedom-Loader.git
synced 2026-07-29 18:25:47 +02:00
256 lines
8.8 KiB
JavaScript
256 lines
8.8 KiB
JavaScript
const themeSelect = document.getElementById("themeSelect");
|
|
/**
|
|
* Currently selected themes loaded from backend.
|
|
* Used as cache for UI theme switching.
|
|
*/
|
|
let loadedThemes = [];
|
|
|
|
/**
|
|
* Applies a theme object to the application UI by mapping
|
|
* theme configuration values to CSS variables and DOM properties.
|
|
*
|
|
* This function mutates:
|
|
* - document.body (background styling)
|
|
* - :root CSS variables (design system tokens)
|
|
* - subtitle DOM element (theme metadata display)
|
|
*
|
|
* @param {Object} theme - Theme definition object
|
|
* @param {Object} theme.style - Style configuration
|
|
*/
|
|
function applyTheme(theme) {
|
|
const root = document.documentElement;
|
|
const style = theme.style;
|
|
|
|
// Background
|
|
if (theme.image) {
|
|
document.body.style.backgroundImage = `url('${theme.image}')`;
|
|
document.body.style.backgroundSize = style.background?.size || "cover";
|
|
document.body.style.backgroundPosition = style.background?.position || "center";
|
|
document.body.style.backgroundAttachment = style.background?.attachment || "fixed";
|
|
} else {
|
|
document.body.style.backgroundImage = "";
|
|
}
|
|
|
|
// CSS variables (design tokens)
|
|
root.style.setProperty("--background-color", style.colors?.background || "#121212");
|
|
root.style.setProperty("--default-text-color", style.colors?.text?.default || "#e0e0e0");
|
|
root.style.setProperty("--subtitle-color", style.colors?.text?.subtitle || "#2196f3");
|
|
root.style.setProperty("--audio-only-label-color", style.colors?.text?.audioOnly || "#f5f5f5");
|
|
|
|
root.style.setProperty("--form-bg-color", style.form?.background || "#1e1e1e");
|
|
root.style.setProperty("--form-input-bg-color", style.form?.input?.background || "#2a2a2a");
|
|
root.style.setProperty("--form-input-border-color", style.form?.input?.border || "#444444");
|
|
root.style.setProperty("--form-input-border-focus-color", style.form?.input?.borderFocus || "#2196f3");
|
|
root.style.setProperty("--form-input-text-color", style.form?.input?.text || "#f5f5f5");
|
|
root.style.setProperty("--form-input-placeholder-color", style.form?.input?.placeholder || "#888888");
|
|
root.style.setProperty("--form-button-bg-color", style.form?.button?.background || "#2196f3");
|
|
root.style.setProperty("--form-button-text-color", style.form?.button?.text || "#ffffff");
|
|
root.style.setProperty("--form-button-bg-hover-color", style.form?.button?.hover || "#1976d2");
|
|
root.style.setProperty("--paste-button-icon-color", style.form?.pasteButtonIcon || "#ffffff");
|
|
|
|
root.style.setProperty("--checkbox-unchecked-bg-color", style.checkbox?.background?.unchecked || "#555555");
|
|
root.style.setProperty("--checkbox-checked-bg-color", style.checkbox?.background?.checked || "#2196f3");
|
|
root.style.setProperty("--checkbox-checkmark-border-color", style.checkbox?.checkmarkBorder || "#ffffff");
|
|
root.style.setProperty("--checkbox-pulse-color", style.checkbox?.pulse || "rgba(33, 150, 243, 0.5)");
|
|
|
|
root.style.setProperty("--download-status-color", style.download?.status || "#2196f3");
|
|
|
|
root.style.setProperty("--progress-bar-bg-color", style.progressBar?.background || "#444444");
|
|
root.style.setProperty("--progress-bar-fill-color", style.progressBar?.fill || "#2196f3");
|
|
|
|
root.style.setProperty("--video-info-bg-color", style.videoInfo?.background || "#1a1a1a");
|
|
root.style.setProperty("--video-info-text-color", style.videoInfo?.text || "#e0e0e0");
|
|
root.style.setProperty("--video-info-heading-color", style.videoInfo?.heading || "#2196f3");
|
|
root.style.setProperty("--video-info-list-color", style.videoInfo?.list || "#cccccc");
|
|
root.style.setProperty("--video-info-list-strong-color", style.videoInfo?.strong || "#ffffff");
|
|
root.style.setProperty("--video-info-link-color", style.videoInfo?.link || "#2196f3");
|
|
root.style.setProperty("--video-info-link-hover-color", style.videoInfo?.linkHover || "#1976d2");
|
|
|
|
root.style.setProperty("--playlist-background-color", style.playlist?.background || "#303030");
|
|
|
|
root.style.setProperty("--settings-button-bg-color", style.settings?.button?.background || "#1e1e1e");
|
|
root.style.setProperty("--settings-button-text-color", style.settings?.button?.text || "#e0e0e0");
|
|
root.style.setProperty("--open-theme-button-bg-color", style.settings?.openThemeButton?.background || "#2196f3");
|
|
root.style.setProperty("--open-theme-button-text-color", style.settings?.openThemeButton?.text || "#ffffff");
|
|
root.style.setProperty("--open-json-button-bg-color", style.settings?.openJsonButton?.background || style.settings?.button?.background || "#1e1e1e");
|
|
root.style.setProperty("--open-json-button-text-color", style.settings?.openJsonButton?.text || style.settings?.button?.text || "#e0e0e0");
|
|
root.style.setProperty("--settings-modal-bg-color", style.settings?.background?.modal || "#1e1e1e");
|
|
root.style.setProperty("--settings-section-bg-color", style.settings?.background?.section || "#2a2a2a");
|
|
root.style.setProperty("--settings-text-color", style.settings?.text || "#e0e0e0");
|
|
root.style.setProperty("--settings-subtitle-color", style.settings?.subtitle || "#aaaaaa");
|
|
|
|
const subtitleEl = document.getElementById("subtitle");
|
|
if (subtitleEl) subtitleEl.textContent = theme.subtitle || theme.name;
|
|
}
|
|
|
|
/**
|
|
* Persists selected theme ID into Electron backend features storage.
|
|
*
|
|
* @param {string} themeId
|
|
*/
|
|
function saveTheme(themeId) {
|
|
window.electronAPI.setFeature("theme", themeId);
|
|
}
|
|
|
|
/**
|
|
* Populates theme dropdown selector with available themes.
|
|
*
|
|
* @param {Array} themes
|
|
*/
|
|
function populateThemeSelect(themes) {
|
|
themeSelect.innerHTML = "";
|
|
|
|
for (const theme of themes) {
|
|
const option = document.createElement("option");
|
|
option.value = theme.id;
|
|
option.textContent = theme.name;
|
|
themeSelect.appendChild(option);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes theme system:
|
|
* - loads themes from backend
|
|
* - restores saved theme
|
|
* - applies selected theme
|
|
*/
|
|
async function initThemes() {
|
|
loadedThemes = await window.electronAPI.getThemes();
|
|
|
|
if (!loadedThemes.length) {
|
|
const defaultTheme = {
|
|
id: "dark",
|
|
name: "Dark",
|
|
subtitle: "Darkness is my ally",
|
|
style: {
|
|
background: {
|
|
size: "cover",
|
|
position: "center",
|
|
attachment: "fixed"
|
|
},
|
|
|
|
colors: {
|
|
background: "#121212",
|
|
text: {
|
|
default: "#e0e0e0",
|
|
subtitle: "#2196f3",
|
|
audioOnly: "#f5f5f5"
|
|
}
|
|
},
|
|
|
|
form: {
|
|
background: "#1e1e1e",
|
|
input: {
|
|
background: "#2a2a2a",
|
|
border: "#444444",
|
|
borderFocus: "#2196f3",
|
|
text: "#f5f5f5",
|
|
placeholder: "#888888"
|
|
},
|
|
button: {
|
|
background: "#2196f3",
|
|
text: "#ffffff",
|
|
hover: "#1976d2"
|
|
},
|
|
pasteButtonIcon: "#ffffff"
|
|
},
|
|
|
|
checkbox: {
|
|
background: {
|
|
unchecked: "#555555",
|
|
checked: "#2196f3"
|
|
},
|
|
checkmarkBorder: "#ffffff",
|
|
pulse: "rgba(33, 150, 243, 0.5)"
|
|
},
|
|
|
|
download: {
|
|
status: "#2196f3"
|
|
},
|
|
|
|
progressBar: {
|
|
background: "#444444",
|
|
fill: "#2196f3"
|
|
},
|
|
|
|
videoInfo: {
|
|
background: "#1a1a1a",
|
|
text: "#e0e0e0",
|
|
heading: "#2196f3",
|
|
list: "#cccccc",
|
|
strong: "#ffffff",
|
|
link: "#2196f3",
|
|
linkHover: "#1976d2"
|
|
},
|
|
|
|
playlist: {
|
|
background: "#303030"
|
|
},
|
|
|
|
settings: {
|
|
button: {
|
|
background: "#1e1e1e",
|
|
text: "#e0e0e0"
|
|
},
|
|
openThemeButton: {
|
|
background: "#2196f3",
|
|
text: "#ffffff"
|
|
},
|
|
openJsonButton: {
|
|
background: "#2196f3",
|
|
text: "#ffffff"
|
|
},
|
|
background: {
|
|
modal: "#1e1e1e",
|
|
section: "#2a2a2a"
|
|
},
|
|
text: "#e0e0e0",
|
|
subtitle: "#aaaaaa"
|
|
}
|
|
}
|
|
};
|
|
|
|
loadedThemes = [defaultTheme];
|
|
}
|
|
|
|
populateThemeSelect(loadedThemes);
|
|
|
|
const features = await window.electronAPI.getFeatures();
|
|
const savedId = features.theme;
|
|
|
|
const theme = loadedThemes.find(t => t.id === savedId) || loadedThemes[0];
|
|
|
|
themeSelect.value = theme.id;
|
|
applyTheme(theme);
|
|
}
|
|
|
|
/**
|
|
* Handles theme selection change from UI dropdown.
|
|
*/
|
|
themeSelect.addEventListener("change", (e) => {
|
|
const theme = loadedThemes.find(t => t.id === e.target.value);
|
|
if (!theme) return;
|
|
|
|
applyTheme(theme);
|
|
saveTheme(theme.id);
|
|
});
|
|
|
|
/**
|
|
* Reloads themes from backend and reapplies current selection.
|
|
*/
|
|
async function refreshThemes() {
|
|
loadedThemes = await window.electronAPI.reloadThemes();
|
|
populateThemeSelect(loadedThemes);
|
|
|
|
const features = await window.electronAPI.getFeatures();
|
|
const savedId = features.theme;
|
|
|
|
const theme = loadedThemes.find(t => t.id === savedId) || loadedThemes[0];
|
|
|
|
themeSelect.value = theme.id;
|
|
applyTheme(theme);
|
|
}
|
|
|
|
window.refreshThemes = refreshThemes;
|
|
|
|
initThemes(); |