diff --git a/src/interface/hooks/BackgroundDataLoader.ts b/src/interface/hooks/BackgroundDataLoader.ts index 94a5020b..141ae05b 100644 --- a/src/interface/hooks/BackgroundDataLoader.ts +++ b/src/interface/hooks/BackgroundDataLoader.ts @@ -1,8 +1,20 @@ import { type DBSchema, type IDBPDatabase, openDB } from "idb"; +/** + * Defines the schema for the IndexedDB database used for storing background image data. + * + * @interface BackgroundDB + * @extends {DBSchema} + * @property {object} backgrounds - The object store for background images. + * @property {string} backgrounds.key - The type of the key for the object store (in this case, it's `id` as defined in `keyPath`). + * @property {object} backgrounds.value - The structure of the objects stored. + * @property {string} backgrounds.value.id - The unique identifier for the background image record. + * @property {string} backgrounds.value.type - The MIME type of the image (e.g., "image/png", "image/jpeg"). + * @property {Blob} backgrounds.value.blob - The binary large object (Blob) containing the image data. + */ interface BackgroundDB extends DBSchema { backgrounds: { - key: string; + key: string; // Corresponds to the 'id' property due to keyPath: "id" value: { id: string; type: string; @@ -13,6 +25,14 @@ interface BackgroundDB extends DBSchema { let db: IDBPDatabase | null = null; +/** + * Initializes and opens an IndexedDB connection or returns an existing one. + * If the database doesn't exist or needs an upgrade, the `upgrade` callback + * creates the 'backgrounds' object store with 'id' as the keyPath. + * + * @async + * @returns {Promise>} A promise that resolves with the database instance. + */ export async function openDatabase(): Promise> { if (db) return db; @@ -25,6 +45,12 @@ export async function openDatabase(): Promise> { return db; } +/** + * Retrieves all background image records from the 'backgrounds' object store in IndexedDB. + * + * @async + * @returns {Promise>} A promise that resolves with an array of all background image records. + */ export async function readAllData(): Promise< Array<{ id: string; type: string; blob: Blob }> > { @@ -32,6 +58,16 @@ export async function readAllData(): Promise< return db.getAll("backgrounds"); } +/** + * Writes or updates a background image record in the 'backgrounds' object store. + * If a record with the given `id` already exists, it will be updated. Otherwise, a new record is created. + * + * @async + * @param {string} id - The unique identifier for the background image record. + * @param {string} type - The MIME type of the image (e.g., "image/png"). + * @param {Blob} blob - The Blob object containing the image data. + * @returns {Promise} A promise that resolves when the data has been successfully written. + */ export async function writeData( id: string, type: string, @@ -41,16 +77,37 @@ export async function writeData( await db.put("backgrounds", { id, type, blob }); } +/** + * Deletes a background image record from the 'backgrounds' object store by its ID. + * + * @async + * @param {string} id - The unique identifier of the background image record to delete. + * @returns {Promise} A promise that resolves when the data has been successfully deleted. + */ export async function deleteData(id: string): Promise { const db = await openDatabase(); await db.delete("backgrounds", id); } +/** + * Clears all records from the 'backgrounds' object store in IndexedDB. + * + * @async + * @returns {Promise} A promise that resolves when all data has been successfully cleared. + */ export async function clearAllData(): Promise { const db = await openDatabase(); await db.clear("backgrounds"); } +/** + * Retrieves a single background image record from the 'backgrounds' object store by its ID. + * + * @async + * @param {string} id - The unique identifier of the background image record to retrieve. + * @returns {Promise<{id: string, type: string, blob: Blob} | undefined>} A promise that resolves with the + * background image record if found, or undefined otherwise. + */ export async function getDataById( id: string, ): Promise<{ id: string; type: string; blob: Blob } | undefined> { @@ -58,6 +115,10 @@ export async function getDataById( return db.get("backgrounds", id); } +/** + * Closes the active IndexedDB connection and nullifies the global `db` variable. + * This is important to release resources and allow for proper database management. + */ export function closeDatabase(): void { if (db) { db.close(); @@ -65,12 +126,24 @@ export function closeDatabase(): void { } } -// Helper function to check if IndexedDB is supported +/** + * Checks if IndexedDB is supported by the current browser environment. + * + * @returns {boolean} True if IndexedDB is supported, false otherwise. + */ export function isIndexedDBSupported(): boolean { return "indexedDB" in window; } -// Helper function to check if there's enough storage space +/** + * Estimates available storage space and checks if it's sufficient for the specified `requiredSpace`. + * Uses the `navigator.storage.estimate()` API if available. + * If the API is not available or cannot determine space, it defaults to assuming enough space is available. + * + * @async + * @param {number} requiredSpace - The amount of storage space required, in bytes. + * @returns {Promise} A promise that resolves with true if enough space is estimated to be available, false otherwise. + */ export async function hasEnoughStorageSpace( requiredSpace: number, ): Promise { diff --git a/src/interface/hooks/BackgroundUpdates.ts b/src/interface/hooks/BackgroundUpdates.ts index 9fedb9a5..9ef22f2d 100644 --- a/src/interface/hooks/BackgroundUpdates.ts +++ b/src/interface/hooks/BackgroundUpdates.ts @@ -1,11 +1,21 @@ type BackgroundUpdateCallback = () => void; +/** + * A singleton class used to notify listeners about generic background updates or events. + * These updates typically signify that UI components or other parts of the application + * might need to refresh or re-evaluate background-related data (e.g., after a new background + * image is added, removed, or changed). + */ class BackgroundUpdates { private static instance: BackgroundUpdates; private listeners: Set = new Set(); private constructor() {} + /** + * Gets the singleton instance of the BackgroundUpdates class. + * @returns {BackgroundUpdates} The singleton instance. + */ public static getInstance(): BackgroundUpdates { if (!BackgroundUpdates.instance) { BackgroundUpdates.instance = new BackgroundUpdates(); @@ -13,14 +23,31 @@ class BackgroundUpdates { return BackgroundUpdates.instance; } + /** + * Registers a callback function to be invoked when a background update is triggered. + * + * @param {BackgroundUpdateCallback} callback The function to call when a background update occurs. + * This callback takes no arguments and returns void. + */ public addListener(callback: BackgroundUpdateCallback): void { this.listeners.add(callback); } + /** + * Unregisters a previously added callback function. + * After calling this method, the provided callback will no longer be invoked when a background update is triggered. + * + * @param {BackgroundUpdateCallback} callback The callback function to remove from the listeners. + */ public removeListener(callback: BackgroundUpdateCallback): void { this.listeners.delete(callback); } + /** + * Invokes all registered listener callbacks, signifying that a background update has occurred. + * This method should be called whenever a change to background data happens that requires + * other parts of the application to be notified. + */ public triggerUpdate(): void { this.listeners.forEach((callback) => callback()); } diff --git a/src/interface/hooks/SettingsPopup.ts b/src/interface/hooks/SettingsPopup.ts index ecf79621..b54bb84c 100644 --- a/src/interface/hooks/SettingsPopup.ts +++ b/src/interface/hooks/SettingsPopup.ts @@ -21,14 +21,30 @@ class SettingsPopup { return SettingsPopup.instance; } + /** + * Registers a callback function to be invoked when the settings popup is closed. + * + * @param {SettingsPopupCallback} callback The function to call when the settings popup closes. + * This callback takes no arguments and returns void. + */ public addListener(callback: SettingsPopupCallback): void { this.listeners.add(callback); } + /** + * Unregisters a previously added callback function. + * After calling this method, the provided callback will no longer be invoked when the settings popup closes. + * + * @param {SettingsPopupCallback} callback The callback function to remove from the listeners. + */ public removeListener(callback: SettingsPopupCallback): void { this.listeners.delete(callback); } + /** + * Invokes all registered listener callbacks. + * This method should be called when the settings popup is closed to notify all subscribed components or services. + */ public triggerClose(): void { this.listeners.forEach((callback) => callback()); } diff --git a/src/interface/hooks/ThemeUpdates.ts b/src/interface/hooks/ThemeUpdates.ts index f8a50093..a82c69ce 100644 --- a/src/interface/hooks/ThemeUpdates.ts +++ b/src/interface/hooks/ThemeUpdates.ts @@ -1,11 +1,21 @@ type ThemeUpdateCallback = () => void; +/** + * A singleton class used to notify listeners about theme-related updates. + * These updates can include events like theme changes, custom theme modifications, + * or any other event that might require UI components to refresh their appearance + * or re-apply theme styles. + */ class ThemeUpdates { private static instance: ThemeUpdates; private listeners: Set = new Set(); private constructor() {} + /** + * Gets the singleton instance of the ThemeUpdates class. + * @returns {ThemeUpdates} The singleton instance. + */ public static getInstance(): ThemeUpdates { if (!ThemeUpdates.instance) { ThemeUpdates.instance = new ThemeUpdates(); @@ -13,14 +23,31 @@ class ThemeUpdates { return ThemeUpdates.instance; } + /** + * Registers a callback function to be invoked when a theme update is triggered. + * + * @param {ThemeUpdateCallback} callback The function to call when a theme update occurs. + * This callback takes no arguments and returns void. + */ public addListener(callback: ThemeUpdateCallback): void { this.listeners.add(callback); } + /** + * Unregisters a previously added callback function. + * After calling this method, the provided callback will no longer be invoked when a theme update is triggered. + * + * @param {ThemeUpdateCallback} callback The callback function to remove from the listeners. + */ public removeListener(callback: ThemeUpdateCallback): void { this.listeners.delete(callback); } + /** + * Invokes all registered listener callbacks, signifying that a theme-related update has occurred. + * This method should be called whenever a change related to themes happens that requires + * other parts of the application to be notified. + */ public triggerUpdate(): void { this.listeners.forEach((callback) => callback()); } diff --git a/src/interface/utils/themeImageHandlers.ts b/src/interface/utils/themeImageHandlers.ts index 0981fccf..062abbce 100644 --- a/src/interface/utils/themeImageHandlers.ts +++ b/src/interface/utils/themeImageHandlers.ts @@ -1,9 +1,27 @@ import type { LoadedCustomTheme } from "@/types/CustomThemes"; +/** + * Generates a random 9-character alphanumeric string to be used as a unique ID for images. + * This helps in identifying and managing custom images within a theme. + * + * @returns {string} A randomly generated unique ID string. + */ export function generateImageId(): string { return Math.random().toString(36).substr(2, 9); } +/** + * Handles the upload of a new custom image from a file input event. + * If a file is selected, it reads the file using FileReader, converts it to a Blob, + * generates a unique ID and a default variable name for it, and then adds this new image + * to the `CustomImages` array within the provided `theme` object. + * + * @param {Event} event The file input change event, typically from an `` element. + * @param {LoadedCustomTheme} theme The current theme object to which the new image will be added. + * @returns {Promise | LoadedCustomTheme} A Promise that resolves with the updated theme object + * containing the new image if a file was processed. + * Returns the original theme object synchronously if no file was selected. + */ export function handleImageUpload( event: Event, theme: LoadedCustomTheme, @@ -34,6 +52,16 @@ export function handleImageUpload( return theme; } +/** + * Removes a custom image from the theme based on its ID. + * It filters out the image with the specified `imageId` from the `CustomImages` array + * in the `theme` object. + * + * @param {string} imageId The unique ID of the custom image to be removed. + * @param {LoadedCustomTheme} theme The current theme object from which the image will be removed. + * @returns {LoadedCustomTheme} A new theme object with the specified image removed from its `CustomImages` array. + * This function is synchronous. + */ export function handleRemoveImage( imageId: string, theme: LoadedCustomTheme, @@ -44,6 +72,17 @@ export function handleRemoveImage( } as LoadedCustomTheme; } +/** + * Updates the CSS variable name associated with a specific custom image in the theme. + * It finds the image by `imageId` in the `CustomImages` array of the `theme` object + * and updates its `variableName` property. + * + * @param {string} imageId The unique ID of the custom image whose variable name is to be updated. + * @param {string} variableName The new CSS variable name to assign to the image. + * @param {LoadedCustomTheme} theme The current theme object containing the image to be updated. + * @returns {LoadedCustomTheme} A new theme object with the updated image variable name. + * This function is synchronous. + */ export function handleImageVariableChange( imageId: string, variableName: string, @@ -57,6 +96,17 @@ export function handleImageVariableChange( } as LoadedCustomTheme; } +/** + * Handles the upload of a cover image for the theme from a file input event. + * If a file is selected, it reads the file using FileReader, converts it to a Blob, + * and then updates the `coverImage` property of the provided `theme` object with this new blob. + * + * @param {Event} event The file input change event, typically from an `` element. + * @param {LoadedCustomTheme} theme The current theme object whose cover image will be updated. + * @returns {Promise} A Promise that resolves with the updated theme object + * containing the new cover image if a file was processed. + * Returns a Promise resolving with the original theme object if no file was selected. + */ export function handleCoverImageUpload( event: Event, theme: LoadedCustomTheme,