From cdb2937e63c263c1e5489ae1c3c36b6c7dc0463b Mon Sep 17 00:00:00 2001 From: Daniel Dada Date: Thu, 5 Feb 2026 14:34:20 +0300 Subject: [PATCH] added import list option --- list-manager/list-manager.html | 2 + src/list-manager/ListManagerController.ts | 89 +++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/list-manager/list-manager.html b/list-manager/list-manager.html index d4afae1..5af26f0 100644 --- a/list-manager/list-manager.html +++ b/list-manager/list-manager.html @@ -25,9 +25,11 @@ + +
diff --git a/src/list-manager/ListManagerController.ts b/src/list-manager/ListManagerController.ts index 5167cbf..edaf480 100644 --- a/src/list-manager/ListManagerController.ts +++ b/src/list-manager/ListManagerController.ts @@ -48,8 +48,12 @@ async initialize(): Promise { document.getElementById('activateListsBtn')?.addEventListener('click', () => this.setSelectedListsActive(true)); document.getElementById('deactivateListsBtn')?.addEventListener('click', () => this.setSelectedListsActive(false)); document.getElementById('applyListSettingsBtn')?.addEventListener('click', () => this.applyListSettings()); + document.getElementById('importListBtn')?.addEventListener('click', () => this.triggerImport()); document.getElementById('exportListBtn')?.addEventListener('click', () => this.exportCurrentList()); + const importFileInput = document.getElementById('importFileInput') as HTMLInputElement; + importFileInput?.addEventListener('change', (e) => this.handleImportFile(e)); + document.getElementById('selectAllWordsBtn')?.addEventListener('click', () => this.selectAllWords()); document.getElementById('clearSelectedWordsBtn')?.addEventListener('click', () => this.clearSelectedWords()); document.getElementById('enableWordsBtn')?.addEventListener('click', () => this.setSelectedWordsActive(true)); @@ -225,6 +229,91 @@ const wordSearch = document.getElementById('wordSearch') as HTMLInputElement; URL.revokeObjectURL(url); } + private triggerImport(): void { + const fileInput = document.getElementById('importFileInput') as HTMLInputElement; + if (fileInput) { + fileInput.value = ''; + fileInput.click(); + } + } + + private async handleImportFile(event: Event): Promise { + const input = event.target as HTMLInputElement; + const file = input.files?.[0]; + if (!file) return; + + try { + const text = await file.text(); + const data = JSON.parse(text); + + if (!this.validateImportData(data)) { + alert('Invalid file format. Please select a valid Goose Highlighter export file.'); + return; + } + + this.importLists(data); + } catch (error) { + console.error('Import error:', error); + alert('Failed to import file. Please ensure it is a valid JSON file.'); + } + } + + private validateImportData(data: any): data is ExportData { + if (!data || typeof data !== 'object') return false; + if (!Array.isArray(data.lists)) return false; + + return data.lists.every((list: any) => + list && + typeof list === 'object' && + typeof list.name === 'string' && + typeof list.background === 'string' && + typeof list.foreground === 'string' && + typeof list.active === 'boolean' && + Array.isArray(list.words) && + list.words.every((word: any) => + word && + typeof word === 'object' && + typeof word.wordStr === 'string' && + typeof word.background === 'string' && + typeof word.foreground === 'string' && + typeof word.active === 'boolean' + ) + ); + } + + private importLists(data: ExportData): void { + const importedLists = data.lists.map(list => ({ + ...list, + id: Date.now() + Math.random(), + name: this.getUniqueListName(list.name) + })); + + const count = importedLists.length; + const wordCount = importedLists.reduce((sum, list) => sum + list.words.length, 0); + + if (!confirm(`Import ${count} list(s) with ${wordCount} total word(s)?`)) return; + + this.lists.push(...importedLists); + this.currentListIndex = this.lists.length - 1; + this.selectedLists.clear(); + this.save(); + + alert(`Successfully imported ${count} list(s) with ${wordCount} word(s).`); + } + + private getUniqueListName(baseName: string): string { + const existingNames = new Set(this.lists.map(list => list.name)); + if (!existingNames.has(baseName)) return baseName; + + let counter = 1; + let newName = `${baseName} (${counter})`; + while (existingNames.has(newName)) { + counter++; + newName = `${baseName} (${counter})`; + } + return newName; + } + private sanitizeFileName(name: string): string { return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'list'; }