aesy/reddit-comment-highlights

View on GitHub
src/options/ExtensionOptions.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { bind } from "bind-decorator";
import { onOptionsChanged } from "@/common/Events";
import { Logging } from "@/logger/Logging";
import { type Storage } from "@/storage/Storage";

const logger = Logging.getLogger("ExtensionOptions");

// These properties must keep their names for backwards compatibility
export interface Options {
    clearCommentOnClick: boolean;
    clearCommentincludeChildren: boolean;
    border: string | null;
    backColor: string;
    backNightColor: string;
    frontColor: string;
    frontNightColor: string;
    linkColor: string | null;
    linkNightColor: string | null;
    quoteTextColor: string | null;
    quoteTextNightColor: string | null;
    customCSS: string | null;
    customCSSClassName: string;
    threadRemovalTimeSeconds: number;
    useCompression: boolean;
    sync: boolean;
    debug: boolean;
}

export class ExtensionOptions {
    public constructor(
        public readonly storage: Storage<Partial<Options>>,
        public readonly defaults: Readonly<Options>,
    ) {
        storage.onChange.subscribe(this.onStorageChange);
    }

    public dispose(): void {
        this.storage.onChange.unsubscribe(this.onStorageChange);
    }

    public async get(): Promise<Options> {
        logger.debug("Reading ExtensionOptions");

        const data = await this.storage.load();

        return Object.assign({}, this.defaults, data);
    }

    public async set(values: Partial<Options>): Promise<void> {
        logger.debug("Saving ExtensionOptions");

        const oldData = await this.storage.load();
        const newData = Object.assign({}, oldData, values);
        const obj = newData as Record<string, unknown>;

        for (const key of Object.keys(obj)) {
            if (obj[key] === undefined) {
                delete obj[key];
            }
        }

        await this.storage.save(newData);
    }

    public async clear(): Promise<void> {
        logger.debug("Clearing ExtensionOptions");

        await this.storage.clear();
    }

    @bind
    private async onStorageChange(): Promise<void> {
        logger.debug("ExtensionOptions underlying storage changed");

        const options = await this.get();

        onOptionsChanged.dispatch(options);
    }
}