added import list option

This commit is contained in:
2026-02-05 14:34:20 +03:00
parent 22bc39cf6a
commit cdb2937e63
2 changed files with 91 additions and 0 deletions

View File

@@ -25,9 +25,11 @@
<input type="checkbox" class="hidden-toggle" id="themeToggle" /> <input type="checkbox" class="hidden-toggle" id="themeToggle" />
<i class="toggle-icon theme-icon fa-solid"></i> <i class="toggle-icon theme-icon fa-solid"></i>
</label> </label>
<button id="importListBtn" class="ghost"><i class="fa-solid fa-upload"></i> Import List</button>
<button id="exportListBtn" class="ghost"><i class="fa-solid fa-download"></i> Export List</button> <button id="exportListBtn" class="ghost"><i class="fa-solid fa-download"></i> Export List</button>
<button id="newListBtn" class="primary"><i class="fa-solid fa-plus"></i> New List</button> <button id="newListBtn" class="primary"><i class="fa-solid fa-plus"></i> New List</button>
</div> </div>
<input type="file" id="importFileInput" accept=".json" style="display: none;" />
</header> </header>
<main class="layout"> <main class="layout">

View File

@@ -48,8 +48,12 @@ async initialize(): Promise<void> {
document.getElementById('activateListsBtn')?.addEventListener('click', () => this.setSelectedListsActive(true)); document.getElementById('activateListsBtn')?.addEventListener('click', () => this.setSelectedListsActive(true));
document.getElementById('deactivateListsBtn')?.addEventListener('click', () => this.setSelectedListsActive(false)); document.getElementById('deactivateListsBtn')?.addEventListener('click', () => this.setSelectedListsActive(false));
document.getElementById('applyListSettingsBtn')?.addEventListener('click', () => this.applyListSettings()); document.getElementById('applyListSettingsBtn')?.addEventListener('click', () => this.applyListSettings());
document.getElementById('importListBtn')?.addEventListener('click', () => this.triggerImport());
document.getElementById('exportListBtn')?.addEventListener('click', () => this.exportCurrentList()); 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('selectAllWordsBtn')?.addEventListener('click', () => this.selectAllWords());
document.getElementById('clearSelectedWordsBtn')?.addEventListener('click', () => this.clearSelectedWords()); document.getElementById('clearSelectedWordsBtn')?.addEventListener('click', () => this.clearSelectedWords());
document.getElementById('enableWordsBtn')?.addEventListener('click', () => this.setSelectedWordsActive(true)); document.getElementById('enableWordsBtn')?.addEventListener('click', () => this.setSelectedWordsActive(true));
@@ -225,6 +229,91 @@ const wordSearch = document.getElementById('wordSearch') as HTMLInputElement;
URL.revokeObjectURL(url); 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<void> {
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 { private sanitizeFileName(name: string): string {
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'list'; return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'list';
} }