From b0fea230818e2617c795a2b979a7592545760be3 Mon Sep 17 00:00:00 2001 From: Mathias Malmqvist Date: Sun, 23 Nov 2025 22:11:42 +0100 Subject: [PATCH] Refactor the code reading and writing local storage --- js/controller-manager.js | 47 ++----- js/core.js | 42 +++--- js/finetune-history.js | 12 +- js/modals/finetune-modal.js | 26 ++-- js/modals/quick-test-modal.js | 35 +++-- js/storage.js | 245 ++++++++++++++++++++++++++++++++++ js/translations.js | 9 +- js/utils.js | 41 +----- 8 files changed, 317 insertions(+), 140 deletions(-) create mode 100644 js/storage.js diff --git a/js/controller-manager.js b/js/controller-manager.js index 4d1b4b6..8ea29eb 100644 --- a/js/controller-manager.js +++ b/js/controller-manager.js @@ -1,7 +1,8 @@ 'use strict'; import { sleep, la } from './utils.js'; -import { l } from './translations.js' +import { l } from './translations.js'; +import { Storage } from './storage.js'; const NOT_GENUINE_SONY_CONTROLLER_MSG = "Your device might not be a genuine Sony controller. If it is not a clone then please report this issue."; @@ -46,50 +47,29 @@ class ControllerManager { } /** - * Generate a unique storage key for the device - * @param {string} serialNumber The device serial number - * @returns {string} Storage key based on serial number - */ - _getDeviceStorageKey(serialNumber) { - if (!serialNumber) return null; - return `changes_${serialNumber}`; - } - - /** - * Save has_changes_to_write state to localStorage + * Save has_changes_to_write state to storage */ async _saveHasChangesState() { if (!this.currentController) return; try { const serialNumber = await this.currentController.getSerialNumber(); - const key = this._getDeviceStorageKey(serialNumber); - if (key) { - localStorage.setItem(key, JSON.stringify(this.has_changes_to_write)); - } + Storage.hasChangesState.set(serialNumber, this.has_changes_to_write); } catch (e) { console.warn('Failed to save changes state:', e); } } /** - * Restore has_changes_to_write state from localStorage + * Restore has_changes_to_write state from storage */ async _restoreHasChangesState() { if (!this.currentController) return; try { const serialNumber = await this.currentController.getSerialNumber(); - const key = this._getDeviceStorageKey(serialNumber); - if (key) { - const saved = localStorage.getItem(key); - if (saved !== null) { - try { - const restoredState = JSON.parse(saved); - this.has_changes_to_write = restoredState; - this._updateUI(); - } catch (e) { - console.warn('Failed to parse changes state:', e); - } - } + const restoredState = Storage.hasChangesState.get(serialNumber); + if (restoredState !== null) { + this.has_changes_to_write = restoredState; + this._updateUI(); } } catch (e) { console.warn('Failed to restore changes state:', e); @@ -108,19 +88,16 @@ class ControllerManager { } /** - * Clear controller state: remove localStorage entry and reset UI + * Clear controller state: remove storage entry and reset UI * @private */ async _clearControllerState() { if (this.currentController) { try { const serialNumber = await this.currentController.getSerialNumber(); - const key = this._getDeviceStorageKey(serialNumber); - if (key) { - localStorage.removeItem(key); - } + Storage.hasChangesState.clear(serialNumber); } catch (e) { - console.warn('Failed to clear localStorage:', e); + console.warn('Failed to clear storage:', e); } } this.has_changes_to_write = false; diff --git a/js/core.js b/js/core.js index 725c5c5..2d28191 100644 --- a/js/core.js +++ b/js/core.js @@ -1,6 +1,7 @@ 'use strict'; -import { sleep, float_to_str, dec2hex, dec2hex32, lerp_color, initAnalyticsApi, la, createCookie, readCookie } from './utils.js'; +import { sleep, float_to_str, dec2hex, dec2hex32, lerp_color, initAnalyticsApi, la } from './utils.js'; +import { Storage } from './storage.js'; import { initControllerManager } from './controller-manager.js'; import ControllerFactory from './controllers/controller-factory.js'; import { lang_init, l } from './translations.js'; @@ -118,9 +119,8 @@ function gboot() { $("input[name='displayMode']").on('change', on_stick_mode_change); - // Setup edge modal "Don't show again" checkbox $('#edgeModalDontShowAgain').on('change', function() { - localStorage.setItem('edgeModalDontShowAgain', this.checked.toString()); + Storage.edgeModalDontShowAgain.set(this.checked); }); } @@ -310,7 +310,7 @@ async function continue_connection({data, device}) { } } - localStorage.setItem('lastConnectedController', JSON.stringify(lastConnectedInfo)); + Storage.lastConnectedController.set(lastConnectedInfo); updateLastConnectedInfo(); // Initialize SVG controller based on model @@ -405,17 +405,15 @@ async function disconnect() { function updateLastConnectedInfo() { const $lastConnected = $("#lastConnected"); const $infoDiv = $("#lastConnectedInfo"); - const lastConnectedInfo = localStorage.getItem('lastConnectedController'); + const info = Storage.lastConnectedController.get(); - if (!lastConnectedInfo) { + if (!info) { console.log("No last connected info found.", $lastConnected); $lastConnected.hide(); return; } try { - const info = JSON.parse(lastConnectedInfo); - const parts = []; if (info.color) parts.push(info.color); if (info.boardModel) parts.push(info.boardModel); @@ -429,10 +427,7 @@ function updateLastConnectedInfo() { $infoDiv.text(text); if (info.serialNumber) { - const storageKey = `changes_${info.serialNumber}`; - const savedChangesState = localStorage.getItem(storageKey); - const hasChanges = savedChangesState ? JSON.parse(savedChangesState) : false; - + const hasChanges = Storage.hasChangesState.get(info.serialNumber); const $warning = $("#lastConnectedWarning"); $warning.toggle(hasChanges); } @@ -497,7 +492,7 @@ function set_edge_progress(score) { } function show_welcome_modal() { - const already_accepted = readCookie("welcome_accepted"); + const already_accepted = Storage.getString("welcome_accepted"); if(already_accepted == "1") return; @@ -506,7 +501,7 @@ function show_welcome_modal() { function welcome_accepted() { la("welcome_accepted"); - createCookie("welcome_accepted", "1"); + Storage.setString("welcome_accepted", "1"); $("#welcomeModal").modal("hide"); } @@ -861,7 +856,7 @@ function detectFailedRangeCalibration(changes) { if (failedCalibration && !app.shownRangeCalibrationWarning && !hasOpenModals) { app.failedCalibrationCount++; - localStorage.setItem('failedCalibrationCount', app.failedCalibrationCount.toString()); + Storage.failedCalibrationCount.set(app.failedCalibrationCount); app.shownRangeCalibrationWarning = true; if (app.failedCalibrationCount <= 6) { // keep it from getting annoying @@ -1088,8 +1083,7 @@ function show_donate_modal() { function show_edge_modal() { // Check if user has chosen not to show the modal again - const dontShowAgain = localStorage.getItem('edgeModalDontShowAgain'); - if (dontShowAgain === 'true') { + if (Storage.edgeModalDontShowAgain.get()) { return; } @@ -1268,7 +1262,7 @@ window.setCenterCalibrationMethod = (method, event) => { event.stopPropagation(); } app.centerCalibrationMethod = method; - localStorage.setItem('centerCalibrationMethod', method); + Storage.centerCalibrationMethod.set(method); updateCalibrationMethodUI(); // Close the dropdown const dropdownButton = event?.target?.closest('.dropdown-menu')?.previousElementSibling; @@ -1310,7 +1304,7 @@ window.setRangeCalibrationMethod = (method, event) => { event.stopPropagation(); } app.rangeCalibrationMethod = method; - localStorage.setItem('rangeCalibrationMethod', method); + Storage.rangeCalibrationMethod.set(method); updateCalibrationMethodUI(); // Close the dropdown const dropdownButton = event?.target?.closest('.dropdown-menu')?.previousElementSibling; @@ -1342,19 +1336,19 @@ function updateCalibrationMethodUI() { } function initCalibrationMethod() { - const savedCenterMethod = localStorage.getItem('centerCalibrationMethod'); + const savedCenterMethod = Storage.centerCalibrationMethod.get(); if (savedCenterMethod && (savedCenterMethod === 'quick' || savedCenterMethod === 'four-step')) { app.centerCalibrationMethod = savedCenterMethod; } - const savedRangeMethod = localStorage.getItem('rangeCalibrationMethod'); + const savedRangeMethod = Storage.rangeCalibrationMethod.get(); if (savedRangeMethod && (savedRangeMethod === 'normal' || savedRangeMethod === 'expert')) { app.rangeCalibrationMethod = savedRangeMethod; } - const savedFailedCalibrationCount = localStorage.getItem('failedCalibrationCount'); - if (savedFailedCalibrationCount) { - app.failedCalibrationCount = parseInt(savedFailedCalibrationCount, 10); + const savedFailedCalibrationCount = Storage.failedCalibrationCount.get(); + if (savedFailedCalibrationCount > 0) { + app.failedCalibrationCount = savedFailedCalibrationCount; } updateCalibrationMethodUI(); diff --git a/js/finetune-history.js b/js/finetune-history.js index 40e1d60..92e4584 100644 --- a/js/finetune-history.js +++ b/js/finetune-history.js @@ -1,6 +1,7 @@ 'use strict'; -const STORAGE_KEY = 'finetuneHistory'; +import { Storage } from './storage.js'; + const MAX_HISTORY_ENTRIES_PER_CONTROLLER = 10; /** @@ -134,13 +135,12 @@ export class FinetuneHistory { // ==================== PRIVATE METHODS ==================== /** - * Get all history from localStorage (for all controllers) + * Get all history from storage (for all controllers) * @private */ static _getAllHistory() { try { - const stored = localStorage.getItem(STORAGE_KEY); - return stored ? JSON.parse(stored) : {}; + return Storage.finetuneHistory.getAll(); } catch (e) { console.error('Failed to parse finetune history:', e); return {}; @@ -148,12 +148,12 @@ export class FinetuneHistory { } /** - * Save all history to localStorage + * Save all history to storage * @private */ static _saveAllHistory(allHistory) { try { - localStorage.setItem(STORAGE_KEY, JSON.stringify(allHistory)); + Storage.finetuneHistory.setAll(allHistory); } catch (e) { console.error('Failed to save finetune history:', e); } diff --git a/js/modals/finetune-modal.js b/js/modals/finetune-modal.js index 72cb3be..99e299f 100644 --- a/js/modals/finetune-modal.js +++ b/js/modals/finetune-modal.js @@ -2,6 +2,7 @@ import { draw_stick_dial } from '../stick-renderer.js'; import { dec2hex32, float_to_str, la } from '../utils.js'; +import { Storage } from '../storage.js'; import { auto_calibrate_stick_centers } from './calib-center-modal.js'; import { calibrate_range } from './calib-range-modal.js'; @@ -496,13 +497,12 @@ export class Finetune { // Private methods /** - * Restore the show raw numbers checkbox state from localStorage + * Restore the show raw numbers checkbox state from storage */ _restoreShowRawNumbersCheckbox() { - const savedState = localStorage.getItem('showRawNumbersCheckbox'); - if (savedState) { - const isChecked = savedState === 'true'; - $("#showRawNumbersCheckbox").prop('checked', isChecked); + const isChecked = Storage.showRawNumbersCheckbox.get(); + if (isChecked) { + $("#showRawNumbersCheckbox").prop('checked', true); } } @@ -740,7 +740,7 @@ export class Finetune { const showRawNumbers = $("#showRawNumbersCheckbox").is(":checked"); const modal = $("#finetuneModal"); modal.toggleClass("hide-raw-numbers", !showRawNumbers); - localStorage.setItem('showRawNumbersCheckbox', showRawNumbers); + Storage.showRawNumbersCheckbox.set(showRawNumbers); this.refresh_finetune_sticks(); } @@ -1156,25 +1156,23 @@ export class Finetune { } /** - * Save step size to localStorage + * Save step size to storage */ _saveStepSizeToLocalStorage() { - localStorage.setItem('finetuneCenterStepSize', this._centerStepSize.toString()); - localStorage.setItem('finetuneCircularityStepSize', this._circularityStepSize.toString()); + Storage.finetuneCenterStepSize.set(this._centerStepSize); + Storage.finetuneCircularityStepSize.set(this._circularityStepSize); } /** - * Restore step size from localStorage + * Restore step size from storage */ _restoreStepSizeFromLocalStorage() { - // Restore center step size - const savedCenterStepSize = localStorage.getItem('finetuneCenterStepSize'); + const savedCenterStepSize = Storage.finetuneCenterStepSize.get(); if (savedCenterStepSize) { this._centerStepSize = parseInt(savedCenterStepSize); } - // Restore circularity step size - const savedCircularityStepSize = localStorage.getItem('finetuneCircularityStepSize'); + const savedCircularityStepSize = Storage.finetuneCircularityStepSize.get(); if (savedCircularityStepSize) { this._circularityStepSize = parseInt(savedCircularityStepSize); } diff --git a/js/modals/quick-test-modal.js b/js/modals/quick-test-modal.js index e2486de..41a9604 100644 --- a/js/modals/quick-test-modal.js +++ b/js/modals/quick-test-modal.js @@ -1,7 +1,8 @@ 'use strict'; import { l } from '../translations.js'; -import { la } from '../utils.js' +import { la } from '../utils.js'; +import { Storage } from '../storage.js'; const TEST_SEQUENCE = ['usb', 'buttons', 'adaptive', 'haptic', 'lights', 'speaker', 'headphone', 'microphone']; const TEST_NAMES = { @@ -98,32 +99,28 @@ export class QuickTestModal { } /** - * Save skipped tests to localStorage + * Save skipped tests to storage */ _saveSkippedTestsToStorage() { try { - localStorage.setItem('quickTestSkippedTests', JSON.stringify(this.state.skippedTests)); + Storage.quickTestSkippedTests.set(this.state.skippedTests); } catch (error) { - console.warn('Failed to save skipped tests to localStorage:', error); + console.warn('Failed to save skipped tests to storage:', error); } } /** - * Load skipped tests from localStorage + * Load skipped tests from storage */ _loadSkippedTestsFromStorage() { try { - const saved = localStorage.getItem('quickTestSkippedTests'); - if (saved) { - const skippedTests = JSON.parse(saved); - if (Array.isArray(skippedTests)) { - this.state.skippedTests = skippedTests.filter(test => TEST_SEQUENCE.includes(test)); - // Apply the skipped tests to the UI - this._applySkippedTestsToUI(); - } + const skippedTests = Storage.quickTestSkippedTests.get(); + if (Array.isArray(skippedTests) && skippedTests.length > 0) { + this.state.skippedTests = skippedTests.filter(test => TEST_SEQUENCE.includes(test)); + this._applySkippedTestsToUI(); } } catch (error) { - console.warn('Failed to load skipped tests from localStorage:', error); + console.warn('Failed to load skipped tests from storage:', error); this.state.skippedTests = []; } } @@ -381,13 +378,13 @@ export class QuickTestModal { } /** - * Clear saved skipped tests from localStorage + * Clear saved skipped tests from storage */ _clearSkippedTestsFromStorage() { try { - localStorage.removeItem('quickTestSkippedTests'); + Storage.quickTestSkippedTests.clear(); } catch (error) { - console.warn('Failed to clear skipped tests from localStorage:', error); + console.warn('Failed to clear skipped tests from storage:', error); } } @@ -1104,7 +1101,7 @@ export class QuickTestModal { this.state.skippedTests.push(testType); } - // Save to localStorage + // Save to storage this._saveSkippedTestsToStorage(); // Stop any ongoing test activities @@ -1520,7 +1517,7 @@ export class QuickTestModal { // Reset state this._initializeState(); - // Load saved skipped tests from localStorage + // Load saved skipped tests from storage this._loadSkippedTestsFromStorage(); // Reset button colors to initial state diff --git a/js/storage.js b/js/storage.js new file mode 100644 index 0000000..bdacdc2 --- /dev/null +++ b/js/storage.js @@ -0,0 +1,245 @@ +'use strict'; + +export const Storage = { + STORAGE_KEYS: { + LAST_CONNECTED_CONTROLLER: 'lastConnectedController', + EDGE_MODAL_DONT_SHOW_AGAIN: 'edgeModalDontShowAgain', + FAILED_CALIBRATION_COUNT: 'failedCalibrationCount', + CENTER_CALIBRATION_METHOD: 'centerCalibrationMethod', + RANGE_CALIBRATION_METHOD: 'rangeCalibrationMethod', + QUICK_TEST_SKIPPED_TESTS: 'quickTestSkippedTests', + SHOW_RAW_NUMBERS_CHECKBOX: 'showRawNumbersCheckbox', + FINETUNE_CENTER_STEP_SIZE: 'finetuneCenterStepSize', + FINETUNE_CIRCULARITY_STEP_SIZE: 'finetuneCircularityStepSize', + FINETUNE_HISTORY: 'finetuneHistory', + }, + + getChangesStorageKey(serialNumber) { + if (!serialNumber) return null; + return `changes_${serialNumber}`; + }, + + setString(key, value) { + try { + localStorage.setItem(key, value); + } catch (e) { + console.warn(`Failed to save to localStorage (${key}):`, e); + } + }, + + getString(key) { + try { + return localStorage.getItem(key); + } catch (e) { + console.warn(`Failed to read from localStorage (${key}):`, e); + return null; + } + }, + + setObject(key, value) { + try { + localStorage.setItem(key, JSON.stringify(value)); + } catch (e) { + console.warn(`Failed to save object to localStorage (${key}):`, e); + } + }, + + getObject(key) { + try { + const value = localStorage.getItem(key); + return value ? JSON.parse(value) : null; + } catch (e) { + console.warn(`Failed to read object from localStorage (${key}):`, e); + return null; + } + }, + + removeItem(key) { + try { + localStorage.removeItem(key); + } catch (e) { + console.warn(`Failed to remove from localStorage (${key}):`, e); + } + }, + + setBoolean(key, value) { + this.setString(key, value.toString()); + }, + + getBoolean(key, defaultValue = false) { + const value = this.getString(key); + return value !== null ? value === 'true' : defaultValue; + }, + + setNumber(key, value) { + this.setString(key, value.toString()); + }, + + getNumber(key, defaultValue = 0) { + const value = this.getString(key); + return value !== null ? parseInt(value, 10) : defaultValue; + }, + + lastConnectedController: { + set(info) { + Storage.setObject(Storage.STORAGE_KEYS.LAST_CONNECTED_CONTROLLER, info); + }, + + get() { + return Storage.getObject(Storage.STORAGE_KEYS.LAST_CONNECTED_CONTROLLER); + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.LAST_CONNECTED_CONTROLLER); + }, + }, + + edgeModalDontShowAgain: { + set(value) { + Storage.setBoolean(Storage.STORAGE_KEYS.EDGE_MODAL_DONT_SHOW_AGAIN, value); + }, + + get() { + return Storage.getBoolean(Storage.STORAGE_KEYS.EDGE_MODAL_DONT_SHOW_AGAIN); + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.EDGE_MODAL_DONT_SHOW_AGAIN); + }, + }, + + failedCalibrationCount: { + set(count) { + Storage.setNumber(Storage.STORAGE_KEYS.FAILED_CALIBRATION_COUNT, count); + }, + + get() { + return Storage.getNumber(Storage.STORAGE_KEYS.FAILED_CALIBRATION_COUNT, 0); + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.FAILED_CALIBRATION_COUNT); + }, + }, + + centerCalibrationMethod: { + set(method) { + Storage.setString(Storage.STORAGE_KEYS.CENTER_CALIBRATION_METHOD, method); + }, + + get(defaultValue = 'four-step') { + return Storage.getString(Storage.STORAGE_KEYS.CENTER_CALIBRATION_METHOD) || defaultValue; + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.CENTER_CALIBRATION_METHOD); + }, + }, + + rangeCalibrationMethod: { + set(method) { + Storage.setString(Storage.STORAGE_KEYS.RANGE_CALIBRATION_METHOD, method); + }, + + get(defaultValue = 'normal') { + return Storage.getString(Storage.STORAGE_KEYS.RANGE_CALIBRATION_METHOD) || defaultValue; + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.RANGE_CALIBRATION_METHOD); + }, + }, + + quickTestSkippedTests: { + set(tests) { + Storage.setObject(Storage.STORAGE_KEYS.QUICK_TEST_SKIPPED_TESTS, tests); + }, + + get() { + return Storage.getObject(Storage.STORAGE_KEYS.QUICK_TEST_SKIPPED_TESTS) || []; + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.QUICK_TEST_SKIPPED_TESTS); + }, + }, + + showRawNumbersCheckbox: { + set(value) { + Storage.setString(Storage.STORAGE_KEYS.SHOW_RAW_NUMBERS_CHECKBOX, value.toString()); + }, + + get() { + const value = Storage.getString(Storage.STORAGE_KEYS.SHOW_RAW_NUMBERS_CHECKBOX); + return value === 'true'; + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.SHOW_RAW_NUMBERS_CHECKBOX); + }, + }, + + finetuneCenterStepSize: { + set(value) { + Storage.setString(Storage.STORAGE_KEYS.FINETUNE_CENTER_STEP_SIZE, value.toString()); + }, + + get() { + return Storage.getString(Storage.STORAGE_KEYS.FINETUNE_CENTER_STEP_SIZE); + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.FINETUNE_CENTER_STEP_SIZE); + }, + }, + + finetuneCircularityStepSize: { + set(value) { + Storage.setString(Storage.STORAGE_KEYS.FINETUNE_CIRCULARITY_STEP_SIZE, value.toString()); + }, + + get() { + return Storage.getString(Storage.STORAGE_KEYS.FINETUNE_CIRCULARITY_STEP_SIZE); + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.FINETUNE_CIRCULARITY_STEP_SIZE); + }, + }, + + hasChangesState: { + set(serialNumber, hasChanges) { + const key = Storage.getChangesStorageKey(serialNumber); + if (key) { + Storage.setObject(key, hasChanges); + } + }, + + get(serialNumber) { + const key = Storage.getChangesStorageKey(serialNumber); + if (!key) return false; + return Storage.getObject(key) || false; + }, + + clear(serialNumber) { + const key = Storage.getChangesStorageKey(serialNumber); + if (key) { + Storage.removeItem(key); + } + }, + }, + + finetuneHistory: { + getAll() { + return Storage.getObject(Storage.STORAGE_KEYS.FINETUNE_HISTORY) || {}; + }, + + setAll(history) { + Storage.setObject(Storage.STORAGE_KEYS.FINETUNE_HISTORY, history); + }, + + clear() { + Storage.removeItem(Storage.STORAGE_KEYS.FINETUNE_HISTORY); + }, + }, +}; diff --git a/js/translations.js b/js/translations.js index 8fd7fa0..f0b5190 100644 --- a/js/translations.js +++ b/js/translations.js @@ -1,6 +1,7 @@ 'use strict'; -import { la, createCookie, readCookie } from './utils.js'; +import { la } from './utils.js'; +import { Storage } from './storage.js'; // Alphabetical order const available_langs = { @@ -50,7 +51,7 @@ export function lang_init(appState, handleLanguageChangeCb, welcomeModalCb) { } translationState.lang_orig_text[".title"] = document.title; - const force_lang = readCookie("force_lang"); + const force_lang = Storage.getString("force_lang"); if (force_lang != null) { lang_set(force_lang, true).catch(error => { console.error("Failed to set forced language:", error); @@ -89,9 +90,9 @@ async function lang_set(lang, skip_modal=false) { } await handleLanguageChange(lang); - createCookie("force_lang", lang); + Storage.setString("force_lang", lang); if(!skip_modal && welcomeModal) { - createCookie("welcome_accepted", "0"); + Storage.setString("welcome_accepted", "0"); welcomeModal(); } } diff --git a/js/utils.js b/js/utils.js index 3b82c66..722b419 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,5 +1,7 @@ 'use strict'; +import { Storage } from './storage.js'; + /** * Utility functions for DualShock controller operations */ @@ -117,49 +119,12 @@ export function lerp_color(a, b, t) { return rgb2hex(c[0], c[1], c[2]); } -/** -* Create a cookie with specified name, value, and expiration days -* @param {string} name Cookie name -* @param {string} value Cookie value -* @param {number} days Number of days until expiration -*/ -export function createCookie(name, value, days) { - const expires = days ? "; expires=" + new Date(Date.now() + days * 24 * 60 * 60 * 1000).toGMTString() : ""; - document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/"; -} - -/** -* Read a cookie value by name -* @param {string} name Cookie name -* @returns {string|null} Cookie value or null if not found -*/ -export function readCookie(name) { - const nameEQ = encodeURIComponent(name) + "="; - const ca = document.cookie.split(';'); - for (let i = 0; i < ca.length; i++) { - let c = ca[i]; - while (c.charAt(0) === ' ') - c = c.substring(1, c.length); - if (c.indexOf(nameEQ) === 0) - return decodeURIComponent(c.substring(nameEQ.length, c.length)); - } - return null; -} - -/** -* Delete a cookie by setting its expiration to the past -* @param {string} name Cookie name to delete -*/ -export function eraseCookie(name) { - createCookie(name, "", -1); -} - /** * Get the appropriate locale for date formatting based on language and timezone * @returns {string} Locale string for use with toLocaleString() */ export function getLocaleForDateFormatting() { - let lang = readCookie('force_lang') || navigator.language; + let lang = Storage.getString('force_lang') || navigator.language; const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; // Replace en_US with en_UK if timezone does not start with "America"