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" />
|
<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">
|
||||||
|
|||||||
@@ -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';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user