Removed refilc colors, added theme customisation (WIP)

This commit is contained in:
Zan
2025-09-23 19:31:22 +02:00
parent 0f9bae45a5
commit 636a325470
12 changed files with 989 additions and 228 deletions

View File

@@ -68,8 +68,19 @@ h2 {
display:flex;
align-items:center;
gap:8px;
font-weight:600;
font-size:16px;
color:var(--text-primary);
font-weight:500;
}
.custom-theme-editor .setting-header {
justify-content:space-between;
}
.setting-header > div:first-child {
display:flex;
align-items:center;
gap:8px;
}
.theme-grid,.language-grid {
display:grid;
@@ -140,16 +151,9 @@ h2 {
color:var(--text-primary);
font-size:12px;
font-weight:500;
font-family: "Montserrat", serif;
}
.theme-preview.light-blue {
background:#DAE4F7;
}
.theme-preview.light-blue .preview-header {
background:#EDF3FF;
}
.theme-preview.light-blue .preview-card {
background:#FBFCFF;
}
.theme-preview.light-green {
background:#FAFFF0;
}
@@ -159,15 +163,7 @@ h2 {
.theme-preview.light-green .preview-card {
background:#FEFFFD;
}
.theme-preview.dark-blue {
background:#070A0E;
}
.theme-preview.dark-blue .preview-header {
background:#0F131B;
}
.theme-preview.dark-blue .preview-card {
background:#131822;
}
.theme-preview.dark-green {
background:#0D1202;
}
@@ -201,7 +197,14 @@ h2 {
.about-content p,.support-content p {
margin-bottom:12px;
}
.github-link {
.about-links {
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 8px;
}
.about-link {
display:inline-flex;
align-items:center;
gap:6px;
@@ -209,8 +212,10 @@ h2 {
text-decoration:none;
font-weight:500;
transition:color 0.2s;
padding: 4px 0;
}
.github-link:hover {
.about-link:hover {
color:var(--accent-secondary);
}
.support-buttons {
@@ -243,6 +248,357 @@ h2 {
.version-info {
color:var(--text-secondary);
font-size:12px;
text-align:center;
}
.theme-editor-controls {
display: flex;
gap: 8px;
}
.icon-btn {
background: var(--button-secondaryFill);
border: none !important;
border-radius: 8px;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s ease;
color: var(--text-primary);
}
.icon-btn:hover {
background: var(--accent-accent);
color: white;
transform: translateY(-1px);
}
.icon-btn .material-icons-round {
font-size: 18px;
}
.btn-primary, .btn-secondary {
padding: 8px 16px;
border-radius: 8px;
border: none;
font-family: inherit;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
}
.btn-primary {
background: var(--accent-accent);
color: white;
}
.btn-primary:hover {
background: var(--accent-secondary);
}
.btn-secondary {
background: var(--button-secondaryFill);
color: var(--text-primary);
border: 1px solid var(--accent-15);
}
.btn-secondary:hover {
background: var(--accent-15);
}
.custom-themes-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.custom-theme-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px;
background: var(--button-secondaryFill);
border-radius: 8px;
border: 1px solid var(--accent-15);
}
.custom-theme-info {
display: flex;
align-items: center;
gap: 12px;
}
.custom-theme-preview-mini {
width: 40px;
height: 24px;
border-radius: 4px;
display: flex;
overflow: hidden;
}
.custom-theme-preview-mini .color-strip {
flex: 1;
height: 100%;
}
.custom-theme-name {
font-weight: 500;
color: var(--text-primary);
}
.custom-theme-actions {
display: flex;
gap: 4px;
}
.action-btn {
padding: 6px;
border: none;
border-radius: 4px;
background: var(--accent-15);
color: var(--text-primary);
cursor: pointer;
font-size: 16px;
transition: background 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
}
.action-btn .material-icons-round {
font-size: 16px;
}
.action-btn:hover {
background: var(--accent-accent);
color: white;
}
.action-btn.delete:hover {
background: var(--error-accent);
}
.theme-editor-modal, .import-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-content {
background: var(--card-card);
border-radius: 16px;
width: 90%;
max-width: 500px;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px;
border-bottom: 1px solid var(--accent-15);
}
.modal-header h3 {
margin: 0;
color: var(--text-primary);
font-size: 18px;
}
.close-modal {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 4px;
border-radius: 4px;
transition: background 0.2s ease;
}
.close-modal:hover {
background: var(--accent-15);
}
.modal-body {
padding: 16px;
}
.modal-footer {
display: flex;
gap: 8px;
justify-content: flex-end;
padding: 16px;
border-top: 1px solid var(--accent-15);
}
.theme-name-input {
margin-bottom: 20px;
}
.theme-name-input label {
display: block;
margin-bottom: 4px;
color: var(--text-primary);
font-weight: 500;
}
.theme-name-input input {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--accent-15);
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-primary);
font-family: inherit;
}
.color-groups {
display: flex;
flex-direction: column;
gap: 20px;
margin-bottom: 20px;
}
.color-group h4 {
margin: 0 0 12px 0;
color: var(--text-primary);
font-size: 16px;
}
.color-inputs {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.color-input-group {
display: flex;
flex-direction: column;
gap: 4px;
}
.color-input-group label {
color: var(--text-secondary);
font-size: 12px;
font-weight: 500;
}
.color-input-group input[type="color"] {
width: 100%;
height: 40px;
border: 1px solid var(--accent-15);
border-radius: 8px;
background: var(--card-card);
cursor: pointer;
padding: 4px;
}
.color-input-group input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
border-radius: 6px;
overflow: hidden;
}
.color-input-group input[type="color"]::-webkit-color-swatch {
border: none;
border-radius: 6px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.theme-preview-container h4 {
margin: 0 0 12px 0;
color: var(--text-primary);
font-size: 16px;
}
.custom-theme-preview {
border: 1px solid var(--accent-15);
border-radius: 8px;
overflow: hidden;
height: 120px;
position: relative;
}
.custom-theme-preview .preview-header {
height: 30px;
background: var(--preview-background, var(--background));
border-bottom: 1px solid var(--accent-15);
}
.custom-theme-preview .preview-content {
padding: 12px;
background: var(--preview-background, var(--background));
}
.custom-theme-preview .preview-card {
background: var(--preview-card, var(--card-card));
border-radius: 8px;
padding: 12px;
height: 100%;
display: flex;
flex-direction: column;
gap: 8px;
}
.preview-text-primary {
color: var(--preview-text-primary, var(--text-primary));
font-weight: 600;
font-size: 14px;
}
.preview-text-secondary {
color: var(--preview-text-secondary, var(--text-secondary));
font-size: 12px;
}
.preview-accent {
background: var(--preview-accent, var(--accent-accent));
color: white;
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
display: inline-block;
margin-top: 4px;
}
.import-input {
display: flex;
flex-direction: column;
gap: 8px;
}
.import-input label {
color: var(--text-primary);
font-weight: 500;
}
.import-input textarea {
width: 100%;
padding: 12px;
border: 1px solid var(--accent-15);
border-radius: 8px;
background: var(--button-secondaryFill);
color: var(--text-primary);
font-family: inherit;
resize: vertical;
min-height: 80px;
}
.material-icons-round {
font-size:18px;

View File

@@ -31,15 +31,6 @@
<span data-i18n="settings.theme">Téma</span>
</div>
<div class="theme-grid">
<button class="theme-option" data-theme="default">
<div class="theme-preview light-blue">
<div class="preview-header"></div>
<div class="preview-content">
<div class="preview-card"></div>
</div>
</div>
<span class="theme-name" data-i18n="settings.themes.light_blue">Világos Kék</span>
</button>
<button class="theme-option" data-theme="light-green">
<div class="theme-preview light-green">
<div class="preview-header"></div>
@@ -49,15 +40,7 @@
</div>
<span class="theme-name" data-i18n="settings.themes.light_green">Világos Zöld</span>
</button>
<button class="theme-option" data-theme="dark-blue">
<div class="theme-preview dark-blue">
<div class="preview-header"></div>
<div class="preview-content">
<div class="preview-card"></div>
</div>
</div>
<span class="theme-name" data-i18n="settings.themes.dark_blue">Sötét Kék</span>
</button>
<button class="theme-option" data-theme="dark-green">
<div class="theme-preview dark-green">
<div class="preview-header"></div>
@@ -69,6 +52,127 @@
</button>
</div>
</div>
<div class="setting-section">
<div class="setting-header">
<div>
<span class="material-icons-round">brush</span>
<span data-i18n="settings.custom_theme.title">Egyéni Téma</span>
</div>
<div class="theme-editor-controls">
<button class="icon-btn" id="createCustomTheme" title="Új Téma Létrehozása">
<span class="material-icons-round">add</span>
</button>
<button class="icon-btn" id="importTheme" title="Téma Importálása">
<span class="material-icons-round">file_download</span>
</button>
</div>
</div>
<div class="custom-theme-editor">
<div class="custom-themes-list" id="customThemesList">
</div>
<div class="theme-editor-modal" id="themeEditorModal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3 data-i18n="settings.custom_theme.editor_title">Téma Szerkesztő</h3>
<button class="close-modal" id="closeThemeEditor">
<span class="material-icons-round">close</span>
</button>
</div>
<div class="modal-body">
<div class="theme-name-input">
<label for="themeName" data-i18n="settings.custom_theme.name">Téma neve:</label>
<input type="text" id="themeName" placeholder="Saját téma" maxlength="30">
</div>
<div class="color-groups">
<div class="color-group">
<h4 data-i18n="settings.custom_theme.background">Háttér</h4>
<div class="color-inputs">
<div class="color-input-group">
<label for="background" data-i18n="settings.custom_theme.main_background">Fő háttér:</label>
<input type="color" id="background" value="#DAE4F7">
</div>
<div class="color-input-group">
<label for="cardCard" data-i18n="settings.custom_theme.card_background">Kártya háttér:</label>
<input type="color" id="cardCard" value="#EDF3FF">
</div>
</div>
</div>
<div class="color-group">
<h4 data-i18n="settings.custom_theme.text">Szöveg</h4>
<div class="color-inputs">
<div class="color-input-group">
<label for="textPrimary" data-i18n="settings.custom_theme.primary_text">Elsődleges szöveg:</label>
<input type="color" id="textPrimary" value="#050B15">
</div>
<div class="color-input-group">
<label for="textSecondary" data-i18n="settings.custom_theme.secondary_text">Másodlagos szöveg:</label>
<input type="color" id="textSecondary" value="#050B15">
</div>
</div>
</div>
<div class="color-group">
<h4 data-i18n="settings.custom_theme.accent">Kiemelő színek</h4>
<div class="color-inputs">
<div class="color-input-group">
<label for="accentAccent" data-i18n="settings.custom_theme.primary_accent">Elsődleges kiemelő:</label>
<input type="color" id="accentAccent" value="#3673EE">
</div>
<div class="color-input-group">
<label for="accentSecondary" data-i18n="settings.custom_theme.secondary_accent">Másodlagos kiemelő:</label>
<input type="color" id="accentSecondary" value="#1C469A">
</div>
</div>
</div>
</div>
<div class="theme-preview-container">
<h4 data-i18n="settings.custom_theme.preview">Előnézet</h4>
<div class="custom-theme-preview" id="customThemePreview">
<div class="preview-content">
<div class="preview-card">
<div class="preview-text-primary">Elsődleges szöveg</div>
<div class="preview-text-secondary">Másodlagos szöveg</div>
<div class="preview-accent">Kiemelő szín</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn-secondary" id="cancelThemeEdit" data-i18n="settings.custom_theme.cancel">Mégse</button>
<button class="btn-primary" id="saveTheme" data-i18n="settings.custom_theme.save">Mentés</button>
</div>
</div>
</div>
<div class="import-modal" id="importModal" style="display: none;">
<div class="modal-content">
<div class="modal-header">
<h3 data-i18n="settings.custom_theme.import_title">Téma Importálása</h3>
<button class="close-modal" id="closeImportModal">
<span class="material-icons-round">close</span>
</button>
</div>
<div class="modal-body">
<div class="import-input">
<label for="themeImportString" data-i18n="settings.custom_theme.import_string">Téma azonosítója:</label>
<textarea id="themeImportString" placeholder="Illeszd be ide a téma azonosítóját..." rows="4"></textarea>
</div>
</div>
<div class="modal-footer">
<button class="btn-secondary" id="cancelImport" data-i18n="settings.custom_theme.cancel">Mégse</button>
<button class="btn-primary" id="confirmImport" data-i18n="settings.custom_theme.import">Importálás</button>
</div>
</div>
</div>
</div>
</div>
<div class="setting-section">
<div class="setting-header">
@@ -91,10 +195,20 @@
<h2 data-i18n="settings.about.title">Névjegy</h2>
<div class="about-content">
<p data-i18n="settings.about.description">A Firka egy nyílt forráskódú projekt, amely a KRÉTA rendszerhez készít saját felhasználói felületet.</p>
<a href="https://github.com/QwIT-Development/" target="_blank" class="github-link">
<span class="material-icons-round">code</span>
<span data-i18n="settings.about.github">GitHub</span>
</a>
<div class="about-links">
<a href="https://firka.app" target="_blank" class="about-link">
<span class="material-icons-round">language</span>
<span>Weboldal</span>
</a>
<a href="https://github.com/QwIT-Development/" target="_blank" class="about-link">
<span class="material-icons-round">code</span>
<span data-i18n="settings.about.github">GitHub</span>
</a>
<a href="https://discord.gg/firka-1111649116020285532" target="_blank" class="about-link">
<span class="material-icons-round">forum</span>
<span>Discord</span>
</a>
</div>
</div>
</div>
@@ -115,6 +229,7 @@
<div class="version-info" id="version">v1.1.0</div>
</footer>
</div>
<script src="../tools/storageManager.js"></script>
<script src="../tools/cookieManager.js"></script>
<script src="../global/language.js"></script>
<script src="index.js"></script>

View File

@@ -3,37 +3,9 @@ document.addEventListener("DOMContentLoaded", async () => {
await new Promise((resolve) => setTimeout(resolve, 10));
}
function isThemeDisabled(theme) {
const blueThemesUnlocked =
localStorage.getItem("blueThemesUnlocked") === "true";
return (
(theme === "default" ||
theme === "light-blue" ||
theme === "dark-blue") &&
!blueThemesUnlocked
);
}
function updateThemeAvailability() {
const blueThemesUnlocked =
localStorage.getItem("blueThemesUnlocked") === "true";
document.querySelectorAll(".theme-option").forEach((button) => {
const theme = button.dataset.theme;
if (
theme === "default" ||
theme === "light-blue" ||
theme === "dark-blue"
) {
if (blueThemesUnlocked) {
button.style.display = "block";
button.classList.remove("disabled");
button.removeAttribute("disabled");
} else {
button.style.display = "none";
}
}
});
}
function getCookie(name) {
const cookieName = `${name}=`;
@@ -72,7 +44,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const theme = button.dataset.theme;
button.classList.toggle("active", theme === currentTheme);
});
updateThemeAvailability();
}
function getCurrentLanguage() {
@@ -154,11 +126,6 @@ document.addEventListener("DOMContentLoaded", async () => {
let initialTheme = getCurrentTheme();
if (isThemeDisabled(initialTheme)) {
initialTheme = "light-green";
}
updateThemeAvailability();
await applyTheme(initialTheme);
const initialLanguage = getCurrentLanguage();
@@ -175,52 +142,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const versionElement = document.getElementById("version");
versionElement.textContent = `v${manifest.version}`;
let clickCount = 0;
versionElement.addEventListener("click", () => {
clickCount++;
if (clickCount >= 5) {
localStorage.setItem("blueThemesUnlocked", "true");
updateThemeAvailability();
const notification = document.createElement("div");
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: var(--accent-accent);
color: white;
padding: 12px 20px;
border-radius: 8px;
font-family: 'Montserrat', sans-serif;
font-weight: 500;
z-index: 10000;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
animation: slideIn 0.3s ease-out;
`;
notification.textContent =
window.LanguageManager.t("common.success") +
": " +
window.LanguageManager.t("settings.blue_themes_unlocked");
const style = document.createElement("style");
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
style.remove();
}, 3000);
clickCount = 0;
}
});
themeButtons.forEach((button) => {
button.addEventListener("mouseover", () => {
@@ -247,4 +169,404 @@ document.addEventListener("DOMContentLoaded", async () => {
window.addEventListener("languageChanged", (event) => {
updateLanguageButtons(event.detail.language);
});
class CustomThemeManager {
constructor() {
this.customThemes = this.loadCustomThemes();
this.currentEditingTheme = null;
this.initializeEventListeners();
this.renderCustomThemes();
}
loadCustomThemes() {
const stored = localStorage.getItem('customThemes');
return stored ? JSON.parse(stored) : [];
}
saveCustomThemes() {
localStorage.setItem('customThemes', JSON.stringify(this.customThemes));
}
generateThemeId() {
return 'custom-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
}
createTheme(name, colors) {
const theme = {
id: this.generateThemeId(),
name: name,
colors: colors,
created: new Date().toISOString()
};
this.customThemes.push(theme);
this.saveCustomThemes();
return theme;
}
updateTheme(id, name, colors) {
const index = this.customThemes.findIndex(t => t.id === id);
if (index !== -1) {
this.customThemes[index] = {
...this.customThemes[index],
name: name,
colors: colors,
updated: new Date().toISOString()
};
this.saveCustomThemes();
return this.customThemes[index];
}
return null;
}
deleteTheme(id) {
this.customThemes = this.customThemes.filter(t => t.id !== id);
this.saveCustomThemes();
const currentTheme = getCurrentTheme();
if (currentTheme === id) {
this.applyTheme('light-green');
}
}
applyTheme(themeId) {
if (themeId.startsWith('custom-')) {
const theme = this.customThemes.find(t => t.id === themeId);
if (theme) {
this.applyCustomThemeColors(theme.colors);
setCookie("themePreference", themeId);
localStorage.setItem("themePreference", themeId);
}
} else {
document.documentElement.setAttribute('data-theme', themeId);
setCookie("themePreference", themeId);
localStorage.setItem("themePreference", themeId);
}
updateThemeButtons(themeId);
}
applyCustomThemeColors(colors) {
const root = document.documentElement;
root.removeAttribute('data-theme');
Object.entries(colors).forEach(([key, value]) => {
const cssVar = this.convertToCSSVariable(key);
root.style.setProperty(cssVar, value);
});
}
convertToCSSVariable(key) {
return '--' + key.replace(/([A-Z])/g, '-$1').toLowerCase();
}
exportTheme(themeId) {
const theme = this.customThemes.find(t => t.id === themeId);
if (!theme) return null;
const exportData = {
name: theme.name,
colors: theme.colors,
version: '1.0'
};
const jsonString = JSON.stringify(exportData);
const encoded = btoa(unescape(encodeURIComponent(jsonString)));
return encoded;
}
importTheme(encodedString) {
try {
const jsonString = decodeURIComponent(escape(atob(encodedString)));
const themeData = JSON.parse(jsonString);
if (!themeData.name || !themeData.colors) {
throw new Error('Invalid theme format');
}
const importedTheme = this.createTheme(
themeData.name + ' (Importált)',
themeData.colors
);
this.renderCustomThemes();
return importedTheme;
} catch (error) {
console.error('Theme import failed:', error);
return null;
}
}
renderCustomThemes() {
const container = document.getElementById('customThemesList');
container.innerHTML = '';
if (this.customThemes.length === 0) {
const emptyMessage = window.translations?.settings?.custom_theme?.no_themes || 'Még nincsenek egyéni témák';
container.innerHTML = `<p style="color: var(--text-secondary); font-size: 12px; text-align: center; padding: 20px;">${emptyMessage}</p>`;
return;
}
this.customThemes.forEach(theme => {
const themeElement = this.createThemeElement(theme);
container.appendChild(themeElement);
});
}
createThemeElement(theme) {
const element = document.createElement('div');
element.className = 'custom-theme-item';
const colors = theme.colors;
const previewColors = [
colors.background || '#DAE4F7',
colors.cardCard || '#EDF3FF',
colors.accentAccent || '#3673EE',
colors.textPrimary || '#050B15'
];
const translations = window.translations?.settings?.custom_theme || {};
element.innerHTML = `
<div class="custom-theme-info">
<div class="custom-theme-preview-mini">
${previewColors.map(color => `<div class="color-strip" style="background: ${color}"></div>`).join('')}
</div>
<span class="custom-theme-name">${theme.name}</span>
</div>
<div class="custom-theme-actions">
<button class="action-btn apply" data-theme-id="${theme.id}" title="${translations.apply || 'Alkalmaz'}">
<span class="material-icons-round">check</span>
</button>
<button class="action-btn edit" data-theme-id="${theme.id}" title="${translations.edit || 'Szerkeszt'}">
<span class="material-icons-round">edit</span>
</button>
<button class="action-btn export" data-theme-id="${theme.id}" title="${translations.export || 'Export'}">
<span class="material-icons-round">file_upload</span>
</button>
<button class="action-btn delete" data-theme-id="${theme.id}" title="${translations.delete || 'Töröl'}">
<span class="material-icons-round">delete</span>
</button>
</div>
`;
element.querySelector('.apply').addEventListener('click', () => {
this.applyTheme(theme.id);
});
element.querySelector('.edit').addEventListener('click', () => {
this.editTheme(theme.id);
});
element.querySelector('.export').addEventListener('click', () => {
this.showExportModal(theme.id);
});
element.querySelector('.delete').addEventListener('click', () => {
const confirmMessage = window.translations?.settings?.custom_theme?.delete_confirm || `Biztosan törölni szeretnéd a "${theme.name}" témát?`;
if (confirm(confirmMessage.replace('{name}', theme.name))) {
this.deleteTheme(theme.id);
this.renderCustomThemes();
}
});
return element;
}
editTheme(themeId) {
const theme = this.customThemes.find(t => t.id === themeId);
if (!theme) return;
this.currentEditingTheme = theme;
this.openThemeEditor(theme);
}
openThemeEditor(theme = null) {
const modal = document.getElementById('themeEditorModal');
const nameInput = document.getElementById('themeName');
if (theme) {
nameInput.value = theme.name;
this.loadThemeColorsToEditor(theme.colors);
} else {
nameInput.value = '';
this.loadDefaultColorsToEditor();
}
this.updatePreview();
modal.style.display = 'flex';
}
loadThemeColorsToEditor(colors) {
Object.entries(colors).forEach(([key, value]) => {
const input = document.getElementById(key);
if (input) {
input.value = value;
}
});
}
loadDefaultColorsToEditor() {
const defaults = {
background: '#DAE4F7',
cardCard: '#EDF3FF',
textPrimary: '#050B15',
textSecondary: '#050B15',
accentAccent: '#3673EE',
accentSecondary: '#1C469A'
};
this.loadThemeColorsToEditor(defaults);
}
updatePreview() {
const preview = document.getElementById('customThemePreview');
const colors = this.getColorsFromEditor();
preview.style.setProperty('--preview-background', colors.background);
preview.style.setProperty('--preview-card', colors.cardCard);
preview.style.setProperty('--preview-text-primary', colors.textPrimary);
preview.style.setProperty('--preview-text-secondary', colors.textSecondary);
preview.style.setProperty('--preview-accent', colors.accentAccent);
}
getColorsFromEditor() {
return {
background: document.getElementById('background').value,
cardCard: document.getElementById('cardCard').value,
textPrimary: document.getElementById('textPrimary').value,
textSecondary: document.getElementById('textSecondary').value,
accentAccent: document.getElementById('accentAccent').value,
accentSecondary: document.getElementById('accentSecondary').value
};
}
saveThemeFromEditor() {
const name = document.getElementById('themeName').value.trim();
if (!name) {
alert('Add meg a téma nevét!');
return;
}
const colors = this.getColorsFromEditor();
if (this.currentEditingTheme) {
this.updateTheme(this.currentEditingTheme.id, name, colors);
} else {
this.createTheme(name, colors);
}
this.closeThemeEditor();
this.renderCustomThemes();
}
closeThemeEditor() {
document.getElementById('themeEditorModal').style.display = 'none';
this.currentEditingTheme = null;
}
showExportModal(themeId) {
const exportString = this.exportTheme(themeId);
if (exportString) {
const theme = this.customThemes.find(t => t.id === themeId);
prompt(`${theme.name} téma export azonosítója (másold ki):`, exportString);
}
}
showImportModal() {
document.getElementById('importModal').style.display = 'flex';
}
closeImportModal() {
document.getElementById('importModal').style.display = 'none';
document.getElementById('themeImportString').value = '';
}
importThemeFromModal() {
const importString = document.getElementById('themeImportString').value.trim();
if (!importString) {
alert('Add meg az azonosítót!');
return;
}
const importedTheme = this.importTheme(importString);
if (importedTheme) {
alert(`"${importedTheme.name}" téma sikeresen importálva!`);
this.closeImportModal();
} else {
alert('Hiba történt az importálás során. Ellenőrizd az azonosítót!');
}
}
initializeEventListeners() {
document.getElementById('createCustomTheme').addEventListener('click', () => {
this.openThemeEditor();
});
document.getElementById('importTheme').addEventListener('click', () => {
this.showImportModal();
});
document.getElementById('closeThemeEditor').addEventListener('click', () => {
this.closeThemeEditor();
});
document.getElementById('cancelThemeEdit').addEventListener('click', () => {
this.closeThemeEditor();
});
document.getElementById('saveTheme').addEventListener('click', () => {
this.saveThemeFromEditor();
});
document.getElementById('closeImportModal').addEventListener('click', () => {
this.closeImportModal();
});
document.getElementById('cancelImport').addEventListener('click', () => {
this.closeImportModal();
});
document.getElementById('confirmImport').addEventListener('click', () => {
this.importThemeFromModal();
});
const colorInputs = ['background', 'cardCard', 'textPrimary', 'textSecondary', 'accentAccent', 'accentSecondary'];
colorInputs.forEach(inputId => {
document.getElementById(inputId).addEventListener('input', () => {
this.updatePreview();
});
});
document.getElementById('themeEditorModal').addEventListener('click', (e) => {
if (e.target.id === 'themeEditorModal') {
this.closeThemeEditor();
}
});
document.getElementById('importModal').addEventListener('click', (e) => {
if (e.target.id === 'importModal') {
this.closeImportModal();
}
});
}
}
const customThemeManager = new CustomThemeManager();
const originalGetCurrentTheme = getCurrentTheme;
getCurrentTheme = function() {
const theme = originalGetCurrentTheme();
if (theme && theme.startsWith('custom-')) {
return theme;
}
return theme;
};
const originalUpdateThemeButtons = updateThemeButtons;
updateThemeButtons = function(currentTheme) {
originalUpdateThemeButtons(currentTheme);
document.querySelectorAll('.custom-theme-item').forEach(item => {
const applyBtn = item.querySelector('.apply');
const themeId = applyBtn.dataset.themeId;
item.classList.toggle('active', themeId === currentTheme);
});
};
const currentTheme = getCurrentTheme();
if (currentTheme && currentTheme.startsWith('custom-')) {
customThemeManager.applyTheme(currentTheme);
}
});