From 8c57152fe4dc85443edf8525c8785707a8000b54 Mon Sep 17 00:00:00 2001 From: Zan <62830223+Zan1456@users.noreply.github.com> Date: Mon, 15 Sep 2025 22:17:50 +0200 Subject: [PATCH] Use localstorage rather than cookies --- absences/absences.js | 8 +- dashboard/dashboard.js | 21 +++-- global/language.js | 36 ++++---- global/navigation.js | 16 ++-- global/theme.js | 59 +++++++----- grades/grades.js | 32 +++---- homework/homework.js | 22 ++--- logout/logout.js | 6 +- manifest.json | 12 ++- roleselect/roleselect.js | 8 +- search/search.js | 4 +- timetable/timetable.js | 75 ++++++++------- tools/background.js | 106 +++++++++++++++++++++ tools/cookieManager.js | 25 ----- tools/createTemplate.js | 9 +- tools/storageManager.js | 193 +++++++++++++++++++++++++++++++++++++++ 16 files changed, 470 insertions(+), 162 deletions(-) create mode 100644 tools/background.js delete mode 100644 tools/cookieManager.js create mode 100644 tools/storageManager.js diff --git a/absences/absences.js b/absences/absences.js index de4e023..0729a96 100644 --- a/absences/absences.js +++ b/absences/absences.js @@ -1,11 +1,11 @@ async function collectAbsencesData() { const basicData = { schoolInfo: { - name: cookieManager.get("schoolName") || "Iskola", - id: cookieManager.get("schoolCode") || "", + name: await storageManager.get("schoolName", "OM azonosító - Iskola neve"), + id: await storageManager.get("schoolCode", ""), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználónév"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || "45:00", @@ -281,7 +281,7 @@ async function transformAbsencesPage() { container.className = 'kreta-container'; const headerDiv = document.createElement('div'); const parser = new DOMParser(); - const doc = parser.parseFromString(createTemplate.header(), 'text/html'); + const doc = parser.parseFromString(await createTemplate.header(), 'text/html'); const tempDiv = doc.body; while (tempDiv.firstChild) { headerDiv.appendChild(tempDiv.firstChild); diff --git a/dashboard/dashboard.js b/dashboard/dashboard.js index 2c74233..fdedd2f 100644 --- a/dashboard/dashboard.js +++ b/dashboard/dashboard.js @@ -292,18 +292,22 @@ class DashboardDataManager { class DashboardRenderer { constructor(data) { + this.baseData = data; + } + + async init() { this.data = { - ...data, + ...this.baseData, schoolInfo: { name: - cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL, - id: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || "", + await storageManager.get("schoolName", "OM azonosító - Iskola neve"), + id: await storageManager.get("schoolCode", ""), }, userData: { - name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER, + name: await storageManager.get("userName", "Felhasználónév"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || - DEFAULT_VALUES.TIMER, + "45:00", }, }; this.schoolNameFull = `${this.data.schoolInfo.id} - ${this.data.schoolInfo.name}`; @@ -475,14 +479,15 @@ class DashboardRenderer { `; } - render() { + async render() { + await this.init(); document.body.innerHTML = ''; const kretaContainer = document.createElement('div'); kretaContainer.className = 'kreta-container'; const headerDiv = document.createElement('div'); const parser = new DOMParser(); - const headerDoc = parser.parseFromString(createTemplate.header(), 'text/html'); + const headerDoc = parser.parseFromString(await createTemplate.header(), 'text/html'); const headerContent = headerDoc.body; while (headerContent.firstChild) { headerDiv.appendChild(headerContent.firstChild); @@ -573,7 +578,7 @@ class DashboardApplication { const dashboardData = await dataManager.extractAllData(); const renderer = new DashboardRenderer(dashboardData); - renderer.render(); + await renderer.render(); } catch (error) { console.error("Error initializing dashboard:", error); } diff --git a/global/language.js b/global/language.js index 9441a9d..420a155 100644 --- a/global/language.js +++ b/global/language.js @@ -6,7 +6,8 @@ try { currentLanguage = language; - cookieManager.set("languagePreference", language); + await storageManager.set("languagePreference", language); + localStorage.setItem("languagePreference", language); await loadTranslations(language); @@ -82,20 +83,25 @@ } async function initializeLanguage() { - const cookieLanguage = cookieManager.get("languagePreference"); - const localStorageLanguage = localStorage.getItem("languagePreference"); + try { + const storageLanguage = await storageManager.get("languagePreference"); + const localStorageLanguage = localStorage.getItem("languagePreference"); + const language = storageLanguage || localStorageLanguage || "hu"; - const language = cookieLanguage || localStorageLanguage || "hu"; + await setLanguage(language); + loadTranslationsForPage(); - await setLanguage(language); - loadTranslationsForPage(); - - if (cookieLanguage !== localStorageLanguage) { - if (cookieLanguage) { - localStorage.setItem("languagePreference", cookieLanguage); - } else if (localStorageLanguage) { - cookieManager.set("languagePreference", localStorageLanguage); + if (storageLanguage !== localStorageLanguage) { + if (storageLanguage) { + localStorage.setItem("languagePreference", storageLanguage); + } else if (localStorageLanguage) { + await storageManager.set("languagePreference", localStorageLanguage); + } } + } catch (error) { + console.error("Error initializing language:", error); + await setLanguage("hu"); + loadTranslationsForPage(); } } @@ -121,8 +127,7 @@ function loadTranslationsForPage() { try { applyTranslations(); - - // Figyeljük a DOM változásokat és alkalmazzuk a fordításokat új elemekre + const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'childList') { @@ -142,8 +147,7 @@ } } }); - - // Ha maga az elem is tartalmaz data-i18n attribútumot + if (node.hasAttribute && node.hasAttribute('data-i18n')) { const key = node.getAttribute('data-i18n'); const translation = getTranslation(key); diff --git a/global/navigation.js b/global/navigation.js index 24347e7..e06d7d6 100644 --- a/global/navigation.js +++ b/global/navigation.js @@ -11,16 +11,16 @@ const DEFAULT_VALUES = { TIMER: "45:00", }; -function updateHeaderInfo() { +async function updateHeaderInfo() { const schoolName = document.querySelector(".nav-school-name"); const userName = document.querySelector(".nav-user-name"); const logoutTimer = document.querySelector(".nav-logout-timer"); const userData = { schoolName: - cookieManager.get(COOKIE_KEYS.SCHOOL_NAME) || DEFAULT_VALUES.SCHOOL, - schoolId: cookieManager.get(COOKIE_KEYS.SCHOOL_CODE) || "", - name: cookieManager.get(COOKIE_KEYS.USER_NAME) || DEFAULT_VALUES.USER, + await storageManager.get("schoolName", DEFAULT_VALUES.SCHOOL), + schoolId: await storageManager.get("schoolCode", ""), + name: await storageManager.get("userName", DEFAULT_VALUES.USER), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || DEFAULT_VALUES.TIMER, @@ -59,8 +59,8 @@ function startLogoutTimer(timeString) { setInterval(updateTimer, 1000); } -document.addEventListener("DOMContentLoaded", () => { - updateHeaderInfo(); +document.addEventListener("DOMContentLoaded", async () => { + await updateHeaderInfo(); }); function setupUserDropdown() { @@ -169,8 +169,8 @@ function setupMobileNavigation() { }, 100); } -document.addEventListener("DOMContentLoaded", () => { - updateHeaderInfo(); +document.addEventListener("DOMContentLoaded", async () => { + await updateHeaderInfo(); setupUserDropdown(); setupSettingsButton(); setupMobileNavigation(); diff --git a/global/theme.js b/global/theme.js index e09df5f..b9b30e5 100644 --- a/global/theme.js +++ b/global/theme.js @@ -1,10 +1,12 @@ (() => { - function setTheme(theme) { + async function setTheme(theme) { try { const actualTheme = theme === "default" ? "light-blue" : theme; document.documentElement.setAttribute("data-theme", actualTheme); - cookieManager.set("themePreference", actualTheme); + + await storageManager.set("themePreference", actualTheme); + localStorage.setItem("themePreference", actualTheme); chrome.runtime @@ -104,22 +106,29 @@ } } - function initializeTheme() { - const cookieTheme = cookieManager.get("themePreference"); - const localStorageTheme = localStorage.getItem("themePreference"); + async function initializeTheme() { + try { + const storageTheme = await storageManager.get("themePreference"); + const localStorageTheme = localStorage.getItem("themePreference"); - const theme = cookieTheme || localStorageTheme || "light-green"; + const theme = storageTheme || localStorageTheme || "light-green"; - setTheme(theme); - setPageTitleAndFavicon(); - importFonts(); + await setTheme(theme); + setPageTitleAndFavicon(); + importFonts(); - if (cookieTheme !== localStorageTheme) { - if (cookieTheme) { - localStorage.setItem("themePreference", cookieTheme); - } else if (localStorageTheme) { - cookieManager.set("themePreference", localStorageTheme); + if (storageTheme !== localStorageTheme) { + if (storageTheme) { + localStorage.setItem("themePreference", storageTheme); + } else if (localStorageTheme) { + await storageManager.set("themePreference", localStorageTheme); + } } + } catch (error) { + console.error("Error initializing theme:", error); + await setTheme("light-green"); + setPageTitleAndFavicon(); + importFonts(); } } @@ -146,17 +155,21 @@ let titleCheckTimeout; - const observer = new MutationObserver((mutations) => { + const observer = new MutationObserver(async (mutations) => { const currentTheme = document.documentElement.getAttribute("data-theme"); - const savedTheme = - cookieManager.get("themePreference") || - localStorage.getItem("themePreference"); + + try { + const savedTheme = await storageManager.get("themePreference") || + localStorage.getItem("themePreference"); - if ( - (!currentTheme && savedTheme) || - (currentTheme !== savedTheme && savedTheme) - ) { - setTheme(savedTheme); + if ( + (!currentTheme && savedTheme) || + (currentTheme !== savedTheme && savedTheme) + ) { + await setTheme(savedTheme); + } + } catch (error) { + console.error("Error checking theme in observer:", error); } const titleChanged = mutations.some( diff --git a/grades/grades.js b/grades/grades.js index 3ff6b13..b343020 100644 --- a/grades/grades.js +++ b/grades/grades.js @@ -11,7 +11,7 @@ window.currentGradesData = gradesData; document.body.innerHTML = ''; const parser = new DOMParser(); - const doc = parser.parseFromString(generatePageHTML( + const doc = parser.parseFromString(await generatePageHTML( gradesData, studentAverage, classAverage, @@ -61,24 +61,24 @@ } const data = await response.json(); - return processAPIGradesData(data); + return await processAPIGradesData(data); } catch (error) { console.error("Error fetching grades from API:", error); - return extractGradesDataFromDOM(); + return await extractGradesDataFromDOM(); } } - function processAPIGradesData(apiData) { + async function processAPIGradesData(apiData) { const subjects = []; if (!apiData.Data || !Array.isArray(apiData.Data)) { return { schoolInfo: { - id: cookieManager.get("schoolCode") || "", - name: cookieManager.get("schoolName") || "Iskola", + id: await storageManager.get("schoolCode", ""), + name: await storageManager.get("schoolName", "OM azonosító - Iskola neve"), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználónév"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || "45:00", @@ -195,11 +195,11 @@ return { schoolInfo: { - id: cookieManager.get("schoolCode") || "", - name: cookieManager.get("schoolName") || "Iskola", + id: await storageManager.get("schoolCode", ""), + name: await storageManager.get("schoolName", "Iskola"), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználó"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || "45:00", @@ -208,7 +208,7 @@ }; } - function extractGradesDataFromDOM() { + async function extractGradesDataFromDOM() { const subjects = []; const rows = document.querySelectorAll( "#Osztalyzatok_7895TanuloErtekelesByTanuloGrid tbody tr", @@ -293,11 +293,11 @@ return { schoolInfo: { - id: cookieManager.get("schoolCode") || "", - name: cookieManager.get("schoolName") || "Iskola", + id: await storageManager.get("schoolCode", ""), + name: await storageManager.get("schoolName", "Iskola"), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználó"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || "45:00", @@ -376,7 +376,7 @@ return distribution; } - function generatePageHTML(data, studentAverage, classAverage) { + async function generatePageHTML(data, studentAverage, classAverage) { const totalGrades = data.subjects.reduce( (sum, subject) => sum + subject.grades.length, 0, @@ -393,7 +393,7 @@ return `
- ${createTemplate.header()} + ${await createTemplate.header()}
diff --git a/homework/homework.js b/homework/homework.js index c01a2d2..135f832 100644 --- a/homework/homework.js +++ b/homework/homework.js @@ -29,11 +29,11 @@ async function collectHomeworkData() { const basicData = { schoolInfo: { - name: cookieManager.get("schoolName") || "Iskola", - id: cookieManager.get("schoolCode") || "", + name: await storageManager.get("schoolName", "OM azonosító - Iskola neve"), + id: await storageManager.get("schoolCode", ""), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználónév"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || "45:00", @@ -124,7 +124,7 @@ async function transformHomeworkPage() { kretaContainer.className = 'kreta-container'; const headerDiv = document.createElement('div'); const parser = new DOMParser(); - const headerDoc = parser.parseFromString(createTemplate.header(), 'text/html'); + const headerDoc = parser.parseFromString(await createTemplate.header(), 'text/html'); const headerContent = headerDoc.body; while (headerContent.firstChild) { headerDiv.appendChild(headerContent.firstChild); @@ -624,28 +624,28 @@ function updateDateGroupsVisibility() { }); } -function getHomeworkCompletionStatus(homeworkId) { - const completedHomework = cookieManager.get('completedHomework'); +async function getHomeworkCompletionStatus(homeworkId) { + const completedHomework = await storageManager.get('completedHomework'); if (!completedHomework) return false; try { const completedList = JSON.parse(completedHomework); return completedList.includes(homeworkId.toString()); } catch (error) { - console.error('Error parsing completed homework cookie:', error); + console.error('Error parsing completed homework storage:', error); return false; } } -function setHomeworkCompletionStatus(homeworkId, isCompleted) { - let completedHomework = cookieManager.get('completedHomework'); +async function setHomeworkCompletionStatus(homeworkId, isCompleted) { + let completedHomework = await storageManager.get('completedHomework'); let completedList = []; if (completedHomework) { try { completedList = JSON.parse(completedHomework); } catch (error) { - console.error('Error parsing completed homework cookie:', error); + console.error('Error parsing completed homework storage:', error); completedList = []; } } @@ -660,7 +660,7 @@ function setHomeworkCompletionStatus(homeworkId, isCompleted) { completedList = completedList.filter(id => id !== homeworkIdStr); } - cookieManager.set('completedHomework', JSON.stringify(completedList)); + await storageManager.set('completedHomework', JSON.stringify(completedList)); } function setupHomeworkCheckboxes() { diff --git a/logout/logout.js b/logout/logout.js index 132d68b..7d4adf9 100644 --- a/logout/logout.js +++ b/logout/logout.js @@ -1,10 +1,10 @@ (() => { - function transformLogoutPage() { + async function transformLogoutPage() { const theme = - cookieManager.get("themePreference") || + await storageManager.get("themePreference", null) || localStorage.getItem("themePreference") || "light-green"; - const instituteCode = cookieManager.get("schoolSubdomain"); + const instituteCode = await storageManager.get("schoolSubdomain", null); document.documentElement.setAttribute("data-theme", theme); const newHTML = ` diff --git a/manifest.json b/manifest.json index 23f2b3b..aa53af7 100644 --- a/manifest.json +++ b/manifest.json @@ -12,6 +12,12 @@ "128": "images/firka_logo_128.png" } }, + "permissions": [ + "storage" + ], + "background": { + "service_worker": "tools/background.js" + }, "browser_specific_settings": { "gecko": { "id": "firxa@zan1456.hu", @@ -31,7 +37,9 @@ "icons/*.svg", "grades/chart.js", "i18n/*.json", - "tools/cookieManager.js" + "tools/cookieManager.js", + "tools/storageManager.js", + "tools/storageTest.js" ], "matches": [ "" @@ -58,7 +66,7 @@ "global/language.js", "global/theme.js", "tools/loadingScreen.js", - "tools/cookieManager.js", + "tools/storageManager.js", "tools/helper.js", "tools/createTemplate.js", "global/maintenance.js", diff --git a/roleselect/roleselect.js b/roleselect/roleselect.js index 5f73237..51c5356 100644 --- a/roleselect/roleselect.js +++ b/roleselect/roleselect.js @@ -120,12 +120,12 @@ userNameEl?.textContent.trim() || LanguageManager.t("common.username"); if (schoolCode && fullSchoolName) { - cookieManager.set("schoolCode", schoolCode); - cookieManager.set("schoolName", fullSchoolName); - cookieManager.set("schoolSubdomain", schoolSubdomain); + await storageManager.set("schoolCode", schoolCode); + await storageManager.set("schoolName", fullSchoolName); + await storageManager.set("schoolSubdomain", schoolSubdomain); } if (userName) { - cookieManager.set("userName", userName); + await storageManager.set("userName", userName); } document.body.innerHTML = ''; const parser = new DOMParser(); diff --git a/search/search.js b/search/search.js index da311e8..e3633e6 100644 --- a/search/search.js +++ b/search/search.js @@ -20,10 +20,10 @@ if ( setTimeout(initializeTransformation, 1000); } -function applyFirkaStyling() { +async function applyFirkaStyling() { try { const theme = - cookieManager.get("themePreference") || + await storageManager.get("themePreference") || localStorage.getItem("themePreference") || "light-green"; document.documentElement.setAttribute("data-theme", theme); diff --git a/timetable/timetable.js b/timetable/timetable.js index 4901226..5cdad73 100644 --- a/timetable/timetable.js +++ b/timetable/timetable.js @@ -1,8 +1,8 @@ (() => { - function getCompletedHomework() { - if (typeof cookieManager !== 'undefined') { + async function getCompletedHomework() { + if (typeof storageManager !== 'undefined') { try { - const value = cookieManager.get('completedHomework'); + const value = await storageManager.get('completedHomework'); if (value) { return JSON.parse(value); } @@ -13,14 +13,14 @@ return []; } - function saveCompletedHomework(completedList) { - if (typeof cookieManager !== 'undefined') { - cookieManager.set('completedHomework', JSON.stringify(completedList), 365); + async function saveCompletedHomework(completedList) { + if (typeof storageManager !== 'undefined') { + await storageManager.set('completedHomework', JSON.stringify(completedList)); } } - function toggleHomeworkCompletion(lessonId) { - const completed = getCompletedHomework(); + async function toggleHomeworkCompletion(lessonId) { + const completed = await getCompletedHomework(); const index = completed.indexOf(lessonId); if (index > -1) { @@ -29,19 +29,20 @@ completed.push(lessonId); } - saveCompletedHomework(completed); + await saveCompletedHomework(completed); return index === -1; } - function isHomeworkCompleted(lessonId) { - return getCompletedHomework().includes(lessonId); + async function isHomeworkCompleted(lessonId) { + const completed = await getCompletedHomework(); + return completed.includes(lessonId); } - function getCustomHomework() { - if (typeof cookieManager !== 'undefined') { + async function getCustomHomework() { + if (typeof storageManager !== 'undefined') { try { - const value = cookieManager.get('customHomework'); + const value = await storageManager.get('customHomework'); if (value) { return JSON.parse(value); } @@ -52,16 +53,16 @@ return {}; } - function saveCustomHomework(customHomework) { - if (typeof cookieManager !== 'undefined') { - cookieManager.set('customHomework', JSON.stringify(customHomework), 365); + async function saveCustomHomework(customHomework) { + if (typeof storageManager !== 'undefined') { + await storageManager.set('customHomework', JSON.stringify(customHomework)); } } - function getCustomTests() { - if (typeof cookieManager !== 'undefined') { + async function getCustomTests() { + if (typeof storageManager !== 'undefined') { try { - const value = cookieManager.get('customTests'); + const value = await storageManager.get('customTests'); if (value) { return JSON.parse(value); } @@ -72,9 +73,9 @@ return {}; } - function saveCustomTests(customTests) { - if (typeof cookieManager !== 'undefined') { - cookieManager.set('customTests', JSON.stringify(customTests), 365); + async function saveCustomTests(customTests) { + if (typeof storageManager !== 'undefined') { + await storageManager.set('customTests', JSON.stringify(customTests)); } } @@ -162,8 +163,8 @@ return `${lesson.subject}_${lesson.startTime}_${lesson.day}`; } - function updateHomeworkIconsFromCookie() { - const completedHomework = getCompletedHomework(); + async function updateHomeworkIconsFromCookie() { + const completedHomework = await getCompletedHomework(); completedHomework.forEach(lessonId => { const lessonCards = document.querySelectorAll(`[data-lesson-id="${lessonId}"]`); lessonCards.forEach(card => { @@ -2206,11 +2207,11 @@ const lessons = convertAPIDataToLessons(apiData, weekDates); const data = { schoolInfo: { - name: cookieManager.get("schoolName") || "Iskola", - id: cookieManager.get("schoolCode") || "", + name: await storageManager.get("schoolName", "OM azonosító - Iskola neve"), + id: await storageManager.get("schoolCode", ""), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználónév"), time: "45:00", }, weekInfo: { @@ -2232,7 +2233,7 @@ const headerDiv = document.createElement('div'); const parser2 = new DOMParser(); - const headerDoc = parser2.parseFromString(createTemplate.header(), 'text/html'); + const headerDoc = parser2.parseFromString(await createTemplate.header(), 'text/html'); const headerContent = headerDoc.body; while (headerContent.firstChild) { headerDiv.appendChild(headerContent.firstChild); @@ -2390,8 +2391,8 @@ timetableContainer.appendChild(timetableGrid); - setTimeout(() => { - updateHomeworkIconsFromCookie(); + setTimeout(async () => { + await updateHomeworkIconsFromCookie(); }, 100); main.appendChild(weekControls); @@ -2403,8 +2404,12 @@ document.body.appendChild(kretaContainer); - setupUserDropdown(); - setupMobileNavigation(); + if (typeof setupUserDropdown === 'function') { + setupUserDropdown(); + } + if (typeof setupMobileNavigation === 'function') { + setupMobileNavigation(); + } setupEventListeners(data); initializeWeekSelector(); @@ -2549,8 +2554,8 @@ } setupLessonCardListeners(); - setTimeout(() => { - updateHomeworkIconsFromCookie(); + setTimeout(async () => { + await updateHomeworkIconsFromCookie(); }, 100); } }) diff --git a/tools/background.js b/tools/background.js new file mode 100644 index 0000000..683d691 --- /dev/null +++ b/tools/background.js @@ -0,0 +1,106 @@ +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + (async () => { + try { + switch (request.action) { + case 'storage_set': + await handleStorageSet(request.key, request.value); + sendResponse({ success: true }); + break; + + case 'storage_get': + const value = await handleStorageGet(request.key, request.defaultValue); + sendResponse({ success: true, value: value }); + break; + + case 'storage_remove': + await handleStorageRemove(request.key); + sendResponse({ success: true }); + break; + + case 'storage_clear': + await handleStorageClear(); + sendResponse({ success: true }); + break; + + default: + console.warn('[Background] Unknown action:', request.action); + sendResponse({ success: false, error: 'Unknown action' }); + } + } catch (error) { + console.error('[Background] Error handling message:', error); + sendResponse({ success: false, error: error.message }); + } + })(); + return true; +}); + +async function handleStorageSet(key, value) { + try { + await chrome.storage.sync.set({ [key]: value }); + } catch (error) { + console.error(`[Background] Failed to save ${key}:`, error); + throw error; + } +} + +async function handleStorageGet(key, defaultValue = null) { + try { + const result = await chrome.storage.sync.get(key); + const value = result[key]; + return value !== undefined ? value : defaultValue; + } catch (error) { + console.error(`[Background] Failed to get ${key}:`, error); + throw error; + } +} + +async function handleStorageRemove(key) { + try { + await chrome.storage.sync.remove(key); + } catch (error) { + console.error(`[Background] Failed to remove ${key}:`, error); + throw error; + } +} + +async function handleStorageClear() { + try { + const allData = await chrome.storage.sync.get(null); + const firkaKeys = Object.keys(allData).filter(key => key.startsWith('firka_')); + + if (firkaKeys.length > 0) { + await chrome.storage.sync.remove(firkaKeys); + } + } catch (error) { + console.error('[Background] Failed to clear storage:', error); + throw error; + } +} + +chrome.storage.onChanged.addListener((changes, namespace) => { + if (namespace === 'sync') { + const firkaChanges = Object.keys(changes).filter(key => key.startsWith('firka_')); + if (firkaChanges.length > 0) { + notifyContentScriptsOfChanges(changes); + } + } +}); + +async function notifyContentScriptsOfChanges(changes) { + try { + const tabs = await chrome.tabs.query({ url: 'https://*.e-kreta.hu/*' }); + + for (const tab of tabs) { + try { + await chrome.tabs.sendMessage(tab.id, { + action: 'storage_changed', + changes: changes + }); + } catch (error) { + console.debug(`[Background] Could not notify tab ${tab.id}:`, error.message); + } + } + } catch (error) { + console.error('[Background] Failed to notify content scripts:', error); + } +} \ No newline at end of file diff --git a/tools/cookieManager.js b/tools/cookieManager.js deleted file mode 100644 index edbe1e5..0000000 --- a/tools/cookieManager.js +++ /dev/null @@ -1,25 +0,0 @@ -const cookieManager = { - get(name) { - const cookieName = `${name}=`; - const decodedCookie = decodeURIComponent(document.cookie); - const cookieArray = decodedCookie.split(";"); - - for (let i = 0; i < cookieArray.length; i++) { - let cookie = cookieArray[i]; - while (cookie.charAt(0) === " ") { - cookie = cookie.substring(1); - } - if (cookie.indexOf(cookieName) === 0) { - return cookie.substring(cookieName.length, cookie.length); - } - } - return null; - }, - - set(name, value, days = 365) { - const date = new Date(); - date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); - const expires = `expires=${date.toUTCString()}`; - document.cookie = `${name}=${value}; ${expires}; path=/; domain=.e-kreta.hu`; - }, -}; diff --git a/tools/createTemplate.js b/tools/createTemplate.js index 8e34b20..9113ed3 100644 --- a/tools/createTemplate.js +++ b/tools/createTemplate.js @@ -1,16 +1,15 @@ const createTemplate = { - header() { + async header() { const data = { schoolInfo: { - name: cookieManager.get("schoolName") || "Iskola", - id: cookieManager.get("schoolCode") || "", + name: await storageManager.get("schoolName", "OM azonosító - Iskola neve"), + id: await storageManager.get("schoolCode", ""), }, userData: { - name: cookieManager.get("userName") || "Felhasználó", + name: await storageManager.get("userName", "Felhasználónév"), time: document.querySelector(".usermenu_timer")?.textContent?.trim() || "45:00", - email: cookieManager.get("userEmail") || "", }, }; diff --git a/tools/storageManager.js b/tools/storageManager.js new file mode 100644 index 0000000..b5d9a27 --- /dev/null +++ b/tools/storageManager.js @@ -0,0 +1,193 @@ +const storageManager = { + isExtensionContext() { + return typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.id; + }, + + isContentScript() { + return typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.sendMessage; + }, + + async set(key, value) { + const prefixedKey = `firka_${key}`; + + try { + if (this.isExtensionContext()) { + await chrome.storage.sync.set({ [prefixedKey]: value }); + } else if (this.isContentScript()) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({ + action: 'storage_set', + key: prefixedKey, + value: value + }, (response) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else if (response && response.success) { + resolve(); + } else { + reject(new Error('Failed to save via message passing')); + } + }); + }); + } else { + localStorage.setItem(prefixedKey, JSON.stringify(value)); + } + } catch (error) { + console.warn(`[StorageManager] Primary storage failed for ${key}, falling back to cookie:`, error); + if (typeof cookieManager !== 'undefined') { + cookieManager.set(prefixedKey, JSON.stringify(value)); + } + } + }, + + async get(key, defaultValue = null) { + const prefixedKey = `firka_${key}`; + + try { + if (this.isExtensionContext()) { + const result = await chrome.storage.sync.get(prefixedKey); + const value = result[prefixedKey]; + return value !== undefined ? value : defaultValue; + } else if (this.isContentScript()) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({ + action: 'storage_get', + key: prefixedKey, + defaultValue: defaultValue + }, (response) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else if (response && response.hasOwnProperty('value')) { + resolve(response.value); + } else { + reject(new Error('Failed to get via message passing')); + } + }); + }); + } else { + const value = localStorage.getItem(prefixedKey); + if (value !== null) { + return JSON.parse(value); + } + return defaultValue; + } + } catch (error) { + console.warn(`[StorageManager] Primary storage failed for ${key}, falling back to cookie:`, error); + if (typeof cookieManager !== 'undefined') { + const cookieValue = cookieManager.get(prefixedKey); + if (cookieValue) { + try { + return JSON.parse(cookieValue); + } catch (parseError) { + return cookieValue; + } + } + } + return defaultValue; + } + }, + + async remove(key) { + const prefixedKey = `firka_${key}`; + + try { + if (this.isExtensionContext()) { + await chrome.storage.sync.remove(prefixedKey); + } else if (this.isContentScript()) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({ + action: 'storage_remove', + key: prefixedKey + }, (response) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else if (response && response.success) { + resolve(); + } else { + reject(new Error('Failed to remove via message passing')); + } + }); + }); + } else { + localStorage.removeItem(prefixedKey); + } + } catch (error) { + console.warn(`[StorageManager] Failed to remove ${key}:`, error); + } + }, + + async clear() { + try { + if (this.isExtensionContext()) { + const allData = await chrome.storage.sync.get(null); + const firkaKeys = Object.keys(allData).filter(key => key.startsWith('firka_')); + if (firkaKeys.length > 0) { + await chrome.storage.sync.remove(firkaKeys); + } + } else if (this.isContentScript()) { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({ + action: 'storage_clear' + }, (response) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else if (response && response.success) { + resolve(); + } else { + reject(new Error('Failed to clear via message passing')); + } + }); + }); + } else { + const keysToRemove = []; + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key && key.startsWith('firka_')) { + keysToRemove.push(key); + } + } + keysToRemove.forEach(key => localStorage.removeItem(key)); + } + } catch (error) { + console.warn('[StorageManager] Failed to clear storage:', error); + } + }, + + async migrateFromCookies() { + if (typeof cookieManager === 'undefined') { + return; + } + + const knownSettings = [ + 'theme', 'language', 'notifications', 'autoRefresh', + 'compactMode', 'showGrades', 'showAbsences' + ]; + + let migratedCount = 0; + + for (const setting of knownSettings) { + try { + const cookieValue = cookieManager.get(`firka_${setting}`); + if (cookieValue !== null) { + let value; + try { + value = JSON.parse(cookieValue); + } catch { + value = cookieValue; + } + + await this.set(setting, value); + migratedCount++; + } + } catch (error) { + console.warn(`[StorageManager] Failed to migrate ${setting}:`, error); + } + } + } +}; + +if (typeof document !== 'undefined') { + document.addEventListener('DOMContentLoaded', () => { + storageManager.migrateFromCookies().catch(console.error); + }); +} \ No newline at end of file