mirror of
https://github.com/obsqrbtz/goose-highlighter.git
synced 2026-04-08 20:19:06 +03:00
fix: lighten debounce() usage, do not do full re-render on every change
This commit is contained in:
@@ -2,7 +2,6 @@ import { HighlightList, MessageData } from '../types.js';
|
|||||||
import { StorageService } from '../services/StorageService.js';
|
import { StorageService } from '../services/StorageService.js';
|
||||||
import { MessageService } from '../services/MessageService.js';
|
import { MessageService } from '../services/MessageService.js';
|
||||||
import { HighlightEngine } from './HighlightEngine.js';
|
import { HighlightEngine } from './HighlightEngine.js';
|
||||||
import { DOMUtils } from '../utils/DOMUtils.js';
|
|
||||||
|
|
||||||
export class ContentScript {
|
export class ContentScript {
|
||||||
private lists: HighlightList[] = [];
|
private lists: HighlightList[] = [];
|
||||||
@@ -22,7 +21,6 @@ export class ContentScript {
|
|||||||
private async initialize(): Promise<void> {
|
private async initialize(): Promise<void> {
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
this.setupMessageListener();
|
this.setupMessageListener();
|
||||||
this.setupScrollHandler();
|
|
||||||
this.processHighlights();
|
this.processHighlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,10 +65,6 @@ export class ContentScript {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupScrollHandler(): void {
|
|
||||||
const debouncedProcess = DOMUtils.debounce(() => this.processHighlights(), CONSTANTS.DEBOUNCE_DELAY);
|
|
||||||
window.addEventListener('scroll', debouncedProcess);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleWordListUpdate(): Promise<void> {
|
private async handleWordListUpdate(): Promise<void> {
|
||||||
const data = await StorageService.get(['lists']);
|
const data = await StorageService.get(['lists']);
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ export class PopupController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
wordList.addEventListener('input', (e) => {
|
wordList.addEventListener('change', (e) => {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
const index = +(target.dataset.bgEdit ?? target.dataset.fgEdit ?? -1);
|
const index = +(target.dataset.bgEdit ?? target.dataset.fgEdit ?? -1);
|
||||||
if (index === -1) return;
|
if (index === -1) return;
|
||||||
@@ -219,13 +219,14 @@ export class PopupController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let scrollTimeout: number;
|
let scrolling = false;
|
||||||
wordList.addEventListener('scroll', () => {
|
wordList.addEventListener('scroll', () => {
|
||||||
if (scrollTimeout) return;
|
if (scrolling) return;
|
||||||
scrollTimeout = window.setTimeout(() => {
|
scrolling = true;
|
||||||
requestAnimationFrame(() => this.renderWords());
|
requestAnimationFrame(() => {
|
||||||
scrollTimeout = 0;
|
this.renderWords();
|
||||||
}, 16);
|
scrolling = false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,24 +279,38 @@ export class PopupController {
|
|||||||
const matchCase = document.getElementById('matchCase') as HTMLInputElement;
|
const matchCase = document.getElementById('matchCase') as HTMLInputElement;
|
||||||
const matchWhole = document.getElementById('matchWhole') as HTMLInputElement;
|
const matchWhole = document.getElementById('matchWhole') as HTMLInputElement;
|
||||||
|
|
||||||
globalToggle.addEventListener('change', () => {
|
globalToggle.addEventListener('change', async () => {
|
||||||
this.globalHighlightEnabled = globalToggle.checked;
|
this.globalHighlightEnabled = globalToggle.checked;
|
||||||
this.updateGlobalToggleState();
|
await StorageService.update('globalHighlightEnabled', this.globalHighlightEnabled);
|
||||||
|
MessageService.sendToAllTabs({
|
||||||
|
type: 'GLOBAL_TOGGLE_UPDATED',
|
||||||
|
enabled: this.globalHighlightEnabled
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
matchCase.addEventListener('change', () => {
|
matchCase.addEventListener('change', async () => {
|
||||||
this.matchCaseEnabled = matchCase.checked;
|
this.matchCaseEnabled = matchCase.checked;
|
||||||
this.save();
|
await StorageService.update('matchCaseEnabled', this.matchCaseEnabled);
|
||||||
|
MessageService.sendToAllTabs({
|
||||||
|
type: 'MATCH_OPTIONS_UPDATED',
|
||||||
|
matchCase: this.matchCaseEnabled,
|
||||||
|
matchWhole: this.matchWholeEnabled
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
matchWhole.addEventListener('change', () => {
|
matchWhole.addEventListener('change', async () => {
|
||||||
this.matchWholeEnabled = matchWhole.checked;
|
this.matchWholeEnabled = matchWhole.checked;
|
||||||
this.save();
|
await StorageService.update('matchWholeEnabled', this.matchWholeEnabled);
|
||||||
|
MessageService.sendToAllTabs({
|
||||||
|
type: 'MATCH_OPTIONS_UPDATED',
|
||||||
|
matchCase: this.matchCaseEnabled,
|
||||||
|
matchWhole: this.matchWholeEnabled
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupExceptions(): void {
|
private setupExceptions(): void {
|
||||||
document.getElementById('toggleExceptionBtn')?.addEventListener('click', () => {
|
document.getElementById('toggleExceptionBtn')?.addEventListener('click', async () => {
|
||||||
if (!this.currentTabHost) return;
|
if (!this.currentTabHost) return;
|
||||||
|
|
||||||
const isException = this.exceptionsList.includes(this.currentTabHost);
|
const isException = this.exceptionsList.includes(this.currentTabHost);
|
||||||
@@ -308,26 +323,29 @@ export class PopupController {
|
|||||||
|
|
||||||
this.updateExceptionButton();
|
this.updateExceptionButton();
|
||||||
this.renderExceptions();
|
this.renderExceptions();
|
||||||
this.save();
|
await StorageService.update('exceptionsList', this.exceptionsList);
|
||||||
|
MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' });
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('clearExceptionsBtn')?.addEventListener('click', () => {
|
document.getElementById('clearExceptionsBtn')?.addEventListener('click', async () => {
|
||||||
if (confirm(chrome.i18n.getMessage('confirm_clear_exceptions') || 'Clear all exceptions?')) {
|
if (confirm(chrome.i18n.getMessage('confirm_clear_exceptions') || 'Clear all exceptions?')) {
|
||||||
this.exceptionsList = [];
|
this.exceptionsList = [];
|
||||||
this.updateExceptionButton();
|
this.updateExceptionButton();
|
||||||
this.renderExceptions();
|
this.renderExceptions();
|
||||||
this.save();
|
await StorageService.update('exceptionsList', this.exceptionsList);
|
||||||
|
MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('exceptionsList')?.addEventListener('click', (e) => {
|
document.getElementById('exceptionsList')?.addEventListener('click', async (e) => {
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (target.classList.contains('exception-remove')) {
|
if (target.classList.contains('exception-remove')) {
|
||||||
const domain = target.dataset.domain!;
|
const domain = target.dataset.domain!;
|
||||||
this.exceptionsList = this.exceptionsList.filter(d => d !== domain);
|
this.exceptionsList = this.exceptionsList.filter(d => d !== domain);
|
||||||
this.updateExceptionButton();
|
this.updateExceptionButton();
|
||||||
this.renderExceptions();
|
this.renderExceptions();
|
||||||
this.save();
|
await StorageService.update('exceptionsList', this.exceptionsList);
|
||||||
|
MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -436,29 +454,13 @@ export class PopupController {
|
|||||||
exceptionsList: this.exceptionsList
|
exceptionsList: this.exceptionsList
|
||||||
});
|
});
|
||||||
|
|
||||||
this.render();
|
this.renderLists();
|
||||||
MessageService.sendToAllTabs({ type: 'WORD_LIST_UPDATED' });
|
MessageService.sendToAllTabs({ type: 'WORD_LIST_UPDATED' });
|
||||||
MessageService.sendToAllTabs({
|
|
||||||
type: 'GLOBAL_TOGGLE_UPDATED',
|
|
||||||
enabled: this.globalHighlightEnabled
|
|
||||||
});
|
|
||||||
MessageService.sendToAllTabs({
|
|
||||||
type: 'MATCH_OPTIONS_UPDATED',
|
|
||||||
matchCase: this.matchCaseEnabled,
|
|
||||||
matchWhole: this.matchWholeEnabled
|
|
||||||
});
|
|
||||||
MessageService.sendToAllTabs({ type: 'EXCEPTIONS_LIST_UPDATED' });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private async updateGlobalToggleState(): Promise<void> {
|
|
||||||
await StorageService.update('globalHighlightEnabled', this.globalHighlightEnabled);
|
|
||||||
MessageService.sendToAllTabs({
|
|
||||||
type: 'GLOBAL_TOGGLE_UPDATED',
|
|
||||||
enabled: this.globalHighlightEnabled
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private render(): void {
|
private render(): void {
|
||||||
this.renderLists();
|
this.renderLists();
|
||||||
@@ -500,11 +502,9 @@ export class PopupController {
|
|||||||
const totalItemHeight = itemHeight + itemSpacing;
|
const totalItemHeight = itemHeight + itemSpacing;
|
||||||
const containerHeight = wordList.clientHeight || 250;
|
const containerHeight = wordList.clientHeight || 250;
|
||||||
const scrollTop = wordList.scrollTop;
|
const scrollTop = wordList.scrollTop;
|
||||||
const startIndex = Math.floor(scrollTop / totalItemHeight);
|
const startIndex = Math.max(0, Math.floor(scrollTop / totalItemHeight) - 1);
|
||||||
const endIndex = Math.min(
|
const visibleCount = Math.ceil(containerHeight / totalItemHeight);
|
||||||
startIndex + Math.ceil(containerHeight / totalItemHeight) + 2,
|
const endIndex = Math.min(startIndex + visibleCount + 2, filteredWords.length);
|
||||||
filteredWords.length
|
|
||||||
);
|
|
||||||
|
|
||||||
wordList.innerHTML = '';
|
wordList.innerHTML = '';
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,6 @@ export const DEFAULT_STORAGE: StorageData = {
|
|||||||
|
|
||||||
export const CONSTANTS = {
|
export const CONSTANTS = {
|
||||||
WORD_ITEM_HEIGHT: 32,
|
WORD_ITEM_HEIGHT: 32,
|
||||||
DEBOUNCE_DELAY: 300,
|
DEBOUNCE_DELAY: 150,
|
||||||
SCROLL_THROTTLE: 16
|
SCROLL_THROTTLE: 16
|
||||||
} as const;
|
} as const;
|
||||||
Reference in New Issue
Block a user