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 currentIndex = targetItem.sortIndex; const targetIndex = this.nextQueueItemSortIndex(currentIndex, direction); const existingItem = this.queue.find( (item) => item.sortIndex === targetIndex, ); if (existingItem !== undefined && targetIndex !== undefined) { existingItem.sortIndex = currentIndex; 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.sortIndex - b.sortIndex)[0]; } public nextQueueItemSortIndex( currentIndex: number, direction: Queue.MoveDirection, ): number | undefined { this.queue.sort((a, b) => { return direction === 'up' ? b.sortIndex - a.sortIndex : a.sortIndex - b.sortIndex; }); let foundCurrent = false; for (const item of this.queue) { if (foundCurrent) { return item.sortIndex; } if (item.sortIndex === currentIndex) { foundCurrent = true; } } } 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, }); } }