import browser from 'webextension-polyfill'; import {migrate} from '@holllo/migration-helper'; import {History} from '../utilities/history.js'; import { dataMigrations, deserializeQueue, serializeQueue, } from './migrations.js'; export class Settings { public static async fromSyncStorage(): Promise { const settings = new Settings(); const sync = await browser.storage.sync.get(null); const migrated = (await migrate( sync, sync.version ?? settings.version, dataMigrations, )) as Record; settings.queue = deserializeQueue(migrated); settings.version = migrated.version as string; await settings.save(); return settings; } public manifest: browser.Manifest.ManifestBase; public queue: Queue.Item[]; public version: string; constructor() { this.manifest = browser.runtime.getManifest(); this.queue = []; this.version = '0.0.0'; } public async insertQueueItem(text: string, url: string): Promise { const id = this.newQueueItemId(); const item: Queue.Item = { added: new Date(), id, sortIndex: id, text, url, }; this.queue.push(item); await browser.storage.sync.set({ [`qi${id}`]: { added: item.added.toISOString(), id, sortIndex: id, text, url, }, }); } public async moveQueueItem( id: number, direction: Queue.MoveDirection, ): Promise { const targetItem = this.queue.find((item) => item.id === id); if (targetItem === undefined) { throw new Error(`Failed to move item with ID: ${id}`); } const previousIndex = targetItem.sortIndex; let targetIndex = previousIndex; if (direction === 'down') { targetIndex += 1; } else if (direction === 'up') { targetIndex -= 1; } const existingItem = this.queue.find( (item) => item.sortIndex === targetIndex, ); if (existingItem !== undefined) { existingItem.sortIndex = previousIndex; targetItem.sortIndex = targetIndex; await this.save(); } } public newQueueItemId(): number { const item = this.queue.sort((a, b) => b.id - a.id)[0]; return item === undefined ? 1 : item.id + 1; } public nextQueueItem(): Queue.Item | undefined { return this.queue.sort((a, b) => a.added.getTime() - b.added.getTime())[0]; } public async removeQueueItem(id: number): Promise { const itemIndex = this.queue.findIndex((item) => item.id === id); if (itemIndex === -1) { console.error(`Tried to remove an item with unknown ID: ${id}`); return; } const removedItems = this.queue.splice(itemIndex, 1); await browser.storage.sync.remove(removedItems.map(({id}) => `qi${id}`)); const history = await History.fromLocalStorage(); await history.insertItems(removedItems); } public async save(): Promise { await browser.storage.sync.set({ ...serializeQueue(this.queue), version: this.version, }); } }