mirror of
https://github.com/obsqrbtz/goose-highlighter.git
synced 2026-04-08 20:19:06 +03:00
added import list option
This commit is contained in:
@@ -25,9 +25,11 @@
|
||||
<input type="checkbox" class="hidden-toggle" id="themeToggle" />
|
||||
<i class="toggle-icon theme-icon fa-solid"></i>
|
||||
</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="newListBtn" class="primary"><i class="fa-solid fa-plus"></i> New List</button>
|
||||
</div>
|
||||
<input type="file" id="importFileInput" accept=".json" style="display: none;" />
|
||||
</header>
|
||||
|
||||
<main class="layout">
|
||||
|
||||
@@ -48,8 +48,12 @@ async initialize(): Promise<void> {
|
||||
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<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 {
|
||||
return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'list';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user