From 289fdd925707d03efff35868d2bd4610ecac4ea5 Mon Sep 17 00:00:00 2001 From: Daniel Dada Date: Wed, 11 Feb 2026 13:34:23 +0300 Subject: [PATCH] use exceptionList for blacklist for clean migration --- manifest.json | 1 + sample-import-config.json | 1 + src/background.ts | 10 ++--- src/content/ContentScript.ts | 13 +++++- src/popup/PopupController.ts | 77 +++++++++++++++++++++++++++++------- src/types.ts | 3 ++ 6 files changed, 83 insertions(+), 22 deletions(-) diff --git a/manifest.json b/manifest.json index e22d356..4a19f5a 100644 --- a/manifest.json +++ b/manifest.json @@ -4,6 +4,7 @@ "description": "__MSG_extension_description__", "version": "1.12.1", "default_locale": "en", + "id": "kdoehicejfnccbmecpkfjlbljpfogoep", "permissions": [ "scripting", "storage", diff --git a/sample-import-config.json b/sample-import-config.json index 5471bb7..0ffaa3c 100644 --- a/sample-import-config.json +++ b/sample-import-config.json @@ -209,5 +209,6 @@ "github.com", "www.wikipedia.org" ], + "exceptionsWhiteList": [], "exceptionsMode": "blacklist" } diff --git a/src/background.ts b/src/background.ts index 24931c5..e7e00be 100644 --- a/src/background.ts +++ b/src/background.ts @@ -38,16 +38,16 @@ class BackgroundService { private setupInstallListener(): void { chrome.runtime.onInstalled.addListener(async (): Promise => { - const data = await StorageService.get(['exceptionsList', 'exceptionsMode']); - const updates: { exceptionsList?: string[]; exceptionsMode?: 'blacklist' | 'whitelist' } = {}; - if (!data.exceptionsList) { - updates.exceptionsList = []; + const data = await StorageService.get(['exceptionsList', 'exceptionsWhiteList', 'exceptionsMode']); + const updates: Record = {}; + if (data.exceptionsWhiteList === undefined) { + updates.exceptionsWhiteList = []; } if (data.exceptionsMode !== 'blacklist' && data.exceptionsMode !== 'whitelist') { updates.exceptionsMode = 'blacklist'; } if (Object.keys(updates).length > 0) { - await StorageService.set(updates); + await chrome.storage.local.set(updates); } }); } diff --git a/src/content/ContentScript.ts b/src/content/ContentScript.ts index ab98fbf..323c87a 100644 --- a/src/content/ContentScript.ts +++ b/src/content/ContentScript.ts @@ -7,6 +7,7 @@ export class ContentScript { private lists: HighlightList[] = []; private isGlobalHighlightEnabled = true; private exceptionsList: string[] = []; + private exceptionsWhiteList: string[] = []; private exceptionsMode: ExceptionsMode = 'blacklist'; private shouldSkipDueToExceptions = false; private matchCase = false; @@ -32,6 +33,7 @@ export class ContentScript { 'matchCaseEnabled', 'matchWholeEnabled', 'exceptionsList', + 'exceptionsWhiteList', 'exceptionsMode' ]); @@ -40,13 +42,19 @@ export class ContentScript { this.matchCase = data.matchCaseEnabled ?? false; this.matchWhole = data.matchWholeEnabled ?? false; this.exceptionsList = data.exceptionsList || []; + this.exceptionsWhiteList = data.exceptionsWhiteList || []; this.exceptionsMode = data.exceptionsMode === 'whitelist' ? 'whitelist' : 'blacklist'; this.shouldSkipDueToExceptions = this.computeShouldSkipDueToExceptions(); } + private getCurrentExceptionsList(): string[] { + return this.exceptionsMode === 'whitelist' ? this.exceptionsWhiteList : this.exceptionsList; + } + private computeShouldSkipDueToExceptions(): boolean { const currentHostname = window.location.hostname; - const isInList = this.exceptionsList.includes(currentHostname); + const list = this.getCurrentExceptionsList(); + const isInList = list.includes(currentHostname); if (this.exceptionsMode === 'blacklist') { return isInList; } @@ -98,8 +106,9 @@ export class ContentScript { } private async handleExceptionsUpdate(): Promise { - const data = await StorageService.get(['exceptionsList', 'exceptionsMode']); + const data = await StorageService.get(['exceptionsList', 'exceptionsWhiteList', 'exceptionsMode']); this.exceptionsList = data.exceptionsList || []; + this.exceptionsWhiteList = data.exceptionsWhiteList || []; this.exceptionsMode = data.exceptionsMode === 'whitelist' ? 'whitelist' : 'blacklist'; this.shouldSkipDueToExceptions = this.computeShouldSkipDueToExceptions(); this.processHighlights(); diff --git a/src/popup/PopupController.ts b/src/popup/PopupController.ts index 8fbd069..283ce10 100644 --- a/src/popup/PopupController.ts +++ b/src/popup/PopupController.ts @@ -15,7 +15,13 @@ export class PopupController { private matchCaseEnabled = false; private matchWholeEnabled = false; private exceptionsList: string[] = []; + private exceptionsWhiteList: string[] = []; private exceptionsMode: ExceptionsMode = 'blacklist'; + + private getCurrentExceptionsList(): string[] { + return this.exceptionsMode === 'whitelist' ? this.exceptionsWhiteList : this.exceptionsList; + } + private currentTabHost = ''; private activeTab = 'lists'; private pageHighlights: Array<{ word: string; count: number; background: string; foreground: string; listId?: number; listName?: string; listNames: string[] }> = []; @@ -59,6 +65,7 @@ export class PopupController { this.matchCaseEnabled = data.matchCaseEnabled ?? false; this.matchWholeEnabled = data.matchWholeEnabled ?? false; this.exceptionsList = data.exceptionsList || []; + this.exceptionsWhiteList = data.exceptionsWhiteList || []; this.exceptionsMode = data.exceptionsMode === 'whitelist' ? 'whitelist' : 'blacklist'; if (this.lists.length === 0) { @@ -285,6 +292,7 @@ export class PopupController { const data: ExportData = { lists: this.lists, exceptionsList: [...this.exceptionsList], + exceptionsWhiteList: [...this.exceptionsWhiteList], exceptionsMode: this.exceptionsMode }; const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); @@ -336,7 +344,10 @@ export class PopupController { this.exceptionsList = obj.exceptionsList.filter((d): d is string => typeof d === 'string'); exceptionsApplied = true; } - + if (Array.isArray(obj.exceptionsWhiteList)) { + this.exceptionsWhiteList = obj.exceptionsWhiteList.filter((d): d is string => typeof d === 'string'); + exceptionsApplied = true; + } if (obj.exceptionsMode === 'whitelist' || obj.exceptionsMode === 'blacklist') { this.exceptionsMode = obj.exceptionsMode; exceptionsApplied = true; @@ -1213,6 +1224,8 @@ export class PopupController { MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' }); this.updateExceptionsModeLabel(); this.updateExceptionsModeHint(); + this.renderExceptions(); + this.updateAddCurrentSiteButton(); }); document.getElementById('addExceptionBtn')?.addEventListener('click', () => this.addExceptionFromInput()); @@ -1223,10 +1236,17 @@ export class PopupController { document.getElementById('clearExceptionsBtn')?.addEventListener('click', async () => { if (confirm(chrome.i18n.getMessage('confirm_clear_exceptions') || 'Clear all exceptions?')) { - this.exceptionsList = []; + if (this.exceptionsMode === 'whitelist') { + this.exceptionsWhiteList = []; + } else { + this.exceptionsList = []; + } this.renderExceptions(); this.updateAddCurrentSiteButton(); - await StorageService.update('exceptionsList', this.exceptionsList); + await StorageService.set({ + exceptionsList: this.exceptionsList, + exceptionsWhiteList: this.exceptionsWhiteList + }); MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' }); } }); @@ -1235,10 +1255,17 @@ export class PopupController { const button = (e.target as HTMLElement).closest('.exception-remove'); if (button) { const domain = (button as HTMLElement).dataset.domain!; - this.exceptionsList = this.exceptionsList.filter(d => d !== domain); + if (this.exceptionsMode === 'whitelist') { + this.exceptionsWhiteList = this.exceptionsWhiteList.filter(d => d !== domain); + } else { + this.exceptionsList = this.exceptionsList.filter(d => d !== domain); + } this.renderExceptions(); this.updateAddCurrentSiteButton(); - await StorageService.update('exceptionsList', this.exceptionsList); + await StorageService.set({ + exceptionsList: this.exceptionsList, + exceptionsWhiteList: this.exceptionsWhiteList + }); MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' }); } }); @@ -1377,6 +1404,7 @@ export class PopupController { matchCaseEnabled: this.matchCaseEnabled, matchWholeEnabled: this.matchWholeEnabled, exceptionsList: this.exceptionsList, + exceptionsWhiteList: this.exceptionsWhiteList, exceptionsMode: this.exceptionsMode }); @@ -1387,7 +1415,7 @@ export class PopupController { private setupStorageSync(): void { chrome.storage.onChanged.addListener((changes, areaName) => { if (areaName !== 'local') return; - if (changes.lists || changes.globalHighlightEnabled || changes.matchCaseEnabled || changes.matchWholeEnabled || changes.exceptionsList || changes.exceptionsMode) { + if (changes.lists || changes.globalHighlightEnabled || changes.matchCaseEnabled || changes.matchWholeEnabled || changes.exceptionsList || changes.exceptionsWhiteList || changes.exceptionsMode) { this.reloadFromStorage(); } }); @@ -1400,6 +1428,7 @@ export class PopupController { this.matchCaseEnabled = data.matchCaseEnabled ?? false; this.matchWholeEnabled = data.matchWholeEnabled ?? false; this.exceptionsList = data.exceptionsList || []; + this.exceptionsWhiteList = data.exceptionsWhiteList || []; this.exceptionsMode = data.exceptionsMode === 'whitelist' ? 'whitelist' : 'blacklist'; if (this.lists.length === 0) { @@ -1676,15 +1705,23 @@ export class PopupController { const domain = this.normalizeDomain(input.value); if (!domain) return; - if (this.exceptionsList.includes(domain)) { + const list = this.getCurrentExceptionsList(); + if (list.includes(domain)) { input.value = ''; return; } - this.exceptionsList.push(domain); + if (this.exceptionsMode === 'whitelist') { + this.exceptionsWhiteList.push(domain); + } else { + this.exceptionsList.push(domain); + } input.value = ''; this.renderExceptions(); - StorageService.update('exceptionsList', this.exceptionsList).then(() => { + StorageService.set({ + exceptionsList: this.exceptionsList, + exceptionsWhiteList: this.exceptionsWhiteList + }).then(() => { MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' }); }); } @@ -1697,10 +1734,18 @@ export class PopupController { } if (!host) return; const domain = host.toLowerCase(); - if (this.exceptionsList.includes(domain)) return; - this.exceptionsList.push(domain); + const list = this.getCurrentExceptionsList(); + if (list.includes(domain)) return; + if (this.exceptionsMode === 'whitelist') { + this.exceptionsWhiteList.push(domain); + } else { + this.exceptionsList.push(domain); + } this.renderExceptions(); - await StorageService.update('exceptionsList', this.exceptionsList); + await StorageService.set({ + exceptionsList: this.exceptionsList, + exceptionsWhiteList: this.exceptionsWhiteList + }); MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' }); this.updateAddCurrentSiteButton(); } @@ -1729,7 +1774,8 @@ export class PopupController { const btn = document.getElementById('addCurrentSiteBtn') as HTMLButtonElement | null; if (!btn) return; const host = this.currentTabHost.toLowerCase(); - const alreadyInList = host !== '' && this.exceptionsList.includes(host); + const list = this.getCurrentExceptionsList(); + const alreadyInList = host !== '' && list.includes(host); btn.disabled = !host || alreadyInList; } @@ -1737,12 +1783,13 @@ export class PopupController { const container = document.getElementById('exceptionsList'); if (!container) return; - if (this.exceptionsList.length === 0) { + const list = this.getCurrentExceptionsList(); + if (list.length === 0) { container.innerHTML = `
${chrome.i18n.getMessage('no_exceptions') || 'No exceptions'}
`; return; } - container.innerHTML = this.exceptionsList.map(domain => + container.innerHTML = list.map(domain => `
${DOMUtils.escapeHtml(domain)} diff --git a/src/types.ts b/src/types.ts index 2c2094e..4ac9234 100644 --- a/src/types.ts +++ b/src/types.ts @@ -22,6 +22,7 @@ export interface StorageData { matchCaseEnabled: boolean; matchWholeEnabled: boolean; exceptionsList: string[]; + exceptionsWhiteList: string[]; exceptionsMode: ExceptionsMode; } @@ -56,6 +57,7 @@ export interface MessageData { export interface ExportData { lists: HighlightList[]; exceptionsList: string[]; + exceptionsWhiteList?: string[]; exceptionsMode?: ExceptionsMode; } @@ -65,6 +67,7 @@ export const DEFAULT_STORAGE: StorageData = { matchCaseEnabled: false, matchWholeEnabled: false, exceptionsList: [], + exceptionsWhiteList: [], exceptionsMode: 'blacklist' };