Files
firka-extension/settings/index.js
2025-09-23 22:01:14 +02:00

571 lines
17 KiB
JavaScript

document.addEventListener("DOMContentLoaded", async () => {
while (typeof window.LanguageManager === "undefined") {
await new Promise((resolve) => setTimeout(resolve, 10));
}
function getCurrentTheme() {
return (
localStorage.getItem("themePreference") ||
"light-green"
);
}
function updateThemeButtons(currentTheme) {
document.querySelectorAll(".theme-option").forEach((button) => {
const theme = button.dataset.theme;
button.classList.toggle("active", theme === currentTheme);
});
}
function getCurrentLanguage() {
return (
localStorage.getItem("languagePreference") ||
"hu"
);
}
function updateLanguageButtons(currentLanguage) {
document.querySelectorAll(".language-option").forEach((button) => {
const language = button.dataset.language;
button.classList.toggle("active", language === currentLanguage);
});
}
async function applyLanguage(language) {
localStorage.setItem("languagePreference", language);
updateLanguageButtons(language);
const tabs = await chrome.tabs.query({});
tabs.forEach((tab) => {
chrome.tabs
.sendMessage(tab.id, {
action: "changeLanguage",
language: language,
})
.catch(() => {});
});
}
async function applyTheme(theme) {
localStorage.setItem("themePreference", theme);
document.documentElement.setAttribute("data-theme", theme);
updateThemeButtons(theme);
const tabs = await chrome.tabs.query({});
tabs.forEach((tab) => {
chrome.tabs
.sendMessage(tab.id, {
action: "changeTheme",
theme: theme,
})
.catch(() => {});
});
}
const themeButtons = document.querySelectorAll(".theme-option");
themeButtons.forEach((button) => {
button.addEventListener("click", () => {
const theme = button.dataset.theme;
if (button.hasAttribute("disabled")) {
alert(
window.LanguageManager.t("common.warning") +
": " +
window.LanguageManager.t("settings.theme_not_available"),
);
return;
}
applyTheme(theme);
});
});
const languageButtons = document.querySelectorAll(".language-option");
languageButtons.forEach((button) => {
button.addEventListener("click", () => {
const language = button.dataset.language;
applyLanguage(language);
});
});
let initialTheme = getCurrentTheme();
await applyTheme(initialTheme);
const initialLanguage = getCurrentLanguage();
updateLanguageButtons(initialLanguage);
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "themeChanged") {
updateThemeButtons(message.theme);
document.documentElement.setAttribute("data-theme", message.theme);
}
});
const manifest = chrome.runtime.getManifest();
const versionElement = document.getElementById("version");
versionElement.textContent = `v${manifest.version}`;
themeButtons.forEach((button) => {
button.addEventListener("mouseover", () => {
if (!button.hasAttribute("disabled")) {
button.style.transform = "translateY(-2px)";
}
});
button.addEventListener("mouseout", () => {
button.style.transform = "translateY(0)";
});
});
languageButtons.forEach((button) => {
button.addEventListener("mouseover", () => {
button.style.transform = "translateY(-2px)";
});
button.addEventListener("mouseout", () => {
button.style.transform = "translateY(0)";
});
});
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() {
const existingIds = this.customThemes.map(theme => theme.id);
let counter = 1;
let id;
do {
id = 'custom-' + counter;
counter++;
} while (existingIds.includes(id));
return id;
}
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);
localStorage.setItem("themePreference", themeId);
}
} else {
document.documentElement.setAttribute('data-theme', 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 colors = theme.colors;
const colorString = [
colors.background.substring(1),
colors.cardCard.substring(1),
colors.textPrimary.substring(1),
colors.textSecondary.substring(1),
colors.accentAccent.substring(1),
colors.accentSecondary.substring(1)
].join('');
return theme.name + '|' + colorString;
}
importTheme(themeString) {
try {
const parts = themeString.split('|');
if (parts.length !== 2) {
throw new Error('Invalid theme format - expected name|colors');
}
const [themeName, colorString] = parts;
if (colorString.length !== 36) {
throw new Error('Invalid theme format - expected 36 hex characters');
}
const hexPattern = /^[0-9A-Fa-f]{36}$/;
if (!hexPattern.test(colorString)) {
throw new Error('Invalid hex color format');
}
const colors = [];
for (let i = 0; i < 36; i += 6) {
colors.push(colorString.substring(i, i + 6));
}
const themeColors = {
background: '#' + colors[0],
cardCard: '#' + colors[1],
textPrimary: '#' + colors[2],
textSecondary: '#' + colors[3],
accentAccent: '#' + colors[4],
accentSecondary: '#' + colors[5]
};
const importedTheme = this.createTheme(
themeName + ' (Importált)',
themeColors
);
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);
}
});