diff --git a/src/content.mts b/src/content.mts index 3f996df..81ac1cf 100644 --- a/src/content.mts +++ b/src/content.mts @@ -232,8 +232,10 @@ interface TermAppender { diacritics: false, }, }; - const updateTermStatus = (term: MatchTerm) => getToolbarOrNull()?.updateTermStatus(term); - const highlighter: AbstractEngineManager = new EngineManager(updateTermStatus, termTokens, termPatterns); + const highlighter: AbstractEngineManager = new EngineManager(termTokens, termPatterns); + highlighter.addHighlightingUpdatedListener(() => { + getToolbarOrNull()?.updateStatuses(); + }); const termSetterInternal: TermSetter = { setTerms: termsNew => { if (itemsMatch(terms, termsNew, termEquals)) { diff --git a/src/modules/call-requester.mts b/src/modules/call-requester.mts index 95205a4..eede9cc 100644 --- a/src/modules/call-requester.mts +++ b/src/modules/call-requester.mts @@ -11,11 +11,11 @@ * @param waitDuration Time to wait after the last request, before fulfilling it. * @param reschedulingDelayMax Maximum total delay time between requests and fulfillment. */ -const requestCallFn = function* ( +const requestCallFn = ( call: () => void, waitDuration: number, reschedulingDelayMax: number, -) { +): (() => void) => { const reschedulingRequestCountMargin = 1; let timeRequestAcceptedLast = 0; let requestCount = 0; @@ -31,15 +31,14 @@ const requestCallFn = function* ( requestCount = 0; call(); }, waitDuration + 20); // Arbitrary small amount added to account for lag (preventing lost updates). - while (true) { + return () => { requestCount++; const dateMs = Date.now(); if (dateMs > timeRequestAcceptedLast + waitDuration) { timeRequestAcceptedLast = dateMs; scheduleRefresh(); } - yield; - } + }; }; export { requestCallFn }; diff --git a/src/modules/highlight/engine-manager.mts b/src/modules/highlight/engine-manager.mts index f016f98..964ea35 100644 --- a/src/modules/highlight/engine-manager.mts +++ b/src/modules/highlight/engine-manager.mts @@ -16,7 +16,6 @@ import { getContainerBlock } from "/dist/modules/highlight/container-blocks.mjs" import type { Engine, PaintEngineMethod } from "/dist/modules/common.mjs"; import type { MatchTerm, TermTokens, TermPatterns } from "/dist/modules/match-term.mjs"; import { requestCallFn } from "/dist/modules/call-requester.mjs"; -import type { UpdateTermStatus } from "/dist/content.mjs"; import { compatibility } from "/dist/modules/common.mjs"; interface AbstractEngineManager extends Highlighter, HighlighterCounterInterface, HighlighterWalkerInterface { @@ -46,7 +45,7 @@ class EngineManager implements AbstractEngineManager { readonly #termTokens: TermTokens; readonly #termPatterns: TermPatterns; - readonly #updateTermStatus: UpdateTermStatus; + readonly #highlightingUpdatedListeners = new Set<() => void>(); #highlighting: { terms: ReadonlyArray @@ -58,13 +57,11 @@ class EngineManager implements AbstractEngineManager { #specialEngine: AbstractSpecialEngine | null = null; constructor ( - updateTermStatus: UpdateTermStatus, termTokens: TermTokens, termPatterns: TermPatterns, ) { this.#termTokens = termTokens; this.#termPatterns = termPatterns; - this.#updateTermStatus = updateTermStatus; } getTermBackgroundStyle (colorA: string, colorB: string, cycle: number): string { @@ -154,14 +151,11 @@ class EngineManager implements AbstractEngineManager { break; }} } - engine.addHighlightingUpdatedListener(requestCallFn( - () => { - for (const term of terms.current) { - this.#updateTermStatus(term); - } - }, - 50, 500, - )); + engine.addHighlightingUpdatedListener(() => { + for (const listener of this.#highlightingUpdatedListeners) { + listener(); + } + }); return engineData; } @@ -264,6 +258,10 @@ class EngineManager implements AbstractEngineManager { } this.#specialEngine = null; } + + addHighlightingUpdatedListener (listener: () => void) { + this.#highlightingUpdatedListeners.add(listener); + } } export type { AbstractEngineManager }; diff --git a/src/modules/highlight/engine.mts b/src/modules/highlight/engine.mts index 178360e..8d1d866 100644 --- a/src/modules/highlight/engine.mts +++ b/src/modules/highlight/engine.mts @@ -18,8 +18,6 @@ interface AbstractEngine extends Highlighter { readonly deactivate: () => void - readonly addHighlightingUpdatedListener: (listener: Generator) => void - readonly getHighlightedElements: () => Iterable } @@ -44,6 +42,8 @@ interface HighlightingInterface { ) => void readonly endHighlighting: () => void + + readonly addHighlightingUpdatedListener: (listener: () => void) => void } export type { diff --git a/src/modules/highlight/engines/element.mts b/src/modules/highlight/engines/element.mts index 05c89f2..67014ff 100644 --- a/src/modules/highlight/engines/element.mts +++ b/src/modules/highlight/engines/element.mts @@ -25,6 +25,8 @@ class ElementEngine implements AbstractTreeEditEngine { readonly #elementsJustHighlighted = new Set(); + readonly #highlightingUpdatedListeners = new Set<() => void>(); + readonly #styleManager = new StyleManager(new HTMLStylesheet(document.head)); readonly #termStyleManagerMap = new Map>>(); @@ -106,8 +108,8 @@ ${HIGHLIGHT_TAG} { highlightElementsThrottled(); } //mutationUpdates.observe(); - for (const listener of this.highlightingUpdatedListeners) { - listener.next(); + for (const listener of this.#highlightingUpdatedListeners) { + listener(); } }); this.#flowMutations = { @@ -215,10 +217,8 @@ ${HIGHLIGHT_TAG} { ); } - readonly highlightingUpdatedListeners = new Set(); - - addHighlightingUpdatedListener (listener: Generator) { - this.highlightingUpdatedListeners.add(listener); + addHighlightingUpdatedListener (listener: () => void) { + this.#highlightingUpdatedListeners.add(listener); } /** @@ -400,8 +400,8 @@ ${HIGHLIGHT_TAG} { highlightInBlock(terms, nodeItems); } } - for (const listener of this.highlightingUpdatedListeners) { - listener.next(); + for (const listener of this.#highlightingUpdatedListeners) { + listener(); } }; })(); diff --git a/src/modules/highlight/engines/highlight.mts b/src/modules/highlight/engines/highlight.mts index fd5d23d..33899a0 100644 --- a/src/modules/highlight/engines/highlight.mts +++ b/src/modules/highlight/engines/highlight.mts @@ -8,7 +8,7 @@ import type { AbstractTreeCacheEngine } from "/dist/modules/highlight/models/tre import type { AbstractFlowTracker, Flow, Span } from "/dist/modules/highlight/models/tree-cache/flow-tracker.mjs"; import { FlowTracker } from "/dist/modules/highlight/models/tree-cache/flow-trackers/flow-tracker.mjs"; import * as TermCSS from "/dist/modules/highlight/term-css.mjs"; -import { MatchTerm, type TermTokens, type TermPatterns } from "/dist/modules/match-term.mjs"; +import type { MatchTerm, TermTokens, TermPatterns } from "/dist/modules/match-term.mjs"; import { StyleManager } from "/dist/modules/style-manager.mjs"; import { HTMLStylesheet } from "/dist/modules/stylesheets/html.mjs"; import { EleID, EleClass, createContainer, type AllReadonly } from "/dist/modules/common.mjs"; @@ -32,8 +32,6 @@ class HighlightEngine implements AbstractTreeCacheEngine { readonly #highlights = new ExtendedHighlightRegistry(); - readonly #highlightingUpdatedListeners = new Set(); - readonly #termStyleManagerMap = new Map>>(); readonly terms = createContainer>([]); @@ -162,8 +160,8 @@ class HighlightEngine implements AbstractTreeCacheEngine { return this.#elementFlowsMap.keys(); } - addHighlightingUpdatedListener (listener: Generator) { - this.#highlightingUpdatedListeners.add(listener); + addHighlightingUpdatedListener (listener: () => void) { + this.#flowTracker.addHighlightingUpdatedListener(listener); } } diff --git a/src/modules/highlight/engines/paint.mts b/src/modules/highlight/engines/paint.mts index 6bdd125..cfbfe9e 100644 --- a/src/modules/highlight/engines/paint.mts +++ b/src/modules/highlight/engines/paint.mts @@ -304,7 +304,7 @@ class PaintEngine implements AbstractTreeCacheEngine, HighlightingStyleObserver return this.#elementHighlightingIdMap.keys(); } - addHighlightingUpdatedListener (listener: Generator) { + addHighlightingUpdatedListener (listener: () => void) { this.#flowTracker.addHighlightingUpdatedListener(listener); } diff --git a/src/modules/highlight/engines/paint/methods/element.mts b/src/modules/highlight/engines/paint/methods/element.mts index ec58034..eb7607a 100644 --- a/src/modules/highlight/engines/paint/methods/element.mts +++ b/src/modules/highlight/engines/paint/methods/element.mts @@ -8,7 +8,7 @@ import type { AbstractMethod } from "/dist/modules/highlight/engines/paint/metho import { getBoxesOwned } from "/dist/modules/highlight/engines/paint/boxes.mjs"; import type { HighlightingStyleObserver, Flow, Span, Box } from "/dist/modules/highlight/engines/paint.mjs"; import * as TermCSS from "/dist/modules/highlight/term-css.mjs"; -import { MatchTerm, type TermTokens } from "/dist/modules/match-term.mjs"; +import type { MatchTerm, TermTokens } from "/dist/modules/match-term.mjs"; import { StyleManager } from "/dist/modules/style-manager.mjs"; import { HTMLStylesheet } from "/dist/modules/stylesheets/html.mjs"; import type { AllReadonly } from "/dist/modules/common.mjs"; diff --git a/src/modules/highlight/models/tree-cache/flow-tracker.mts b/src/modules/highlight/models/tree-cache/flow-tracker.mts index d18f498..c014d71 100644 --- a/src/modules/highlight/models/tree-cache/flow-tracker.mts +++ b/src/modules/highlight/models/tree-cache/flow-tracker.mts @@ -61,7 +61,7 @@ interface AbstractFlowTracker extends FlowMutationObserver { ) => void /** Adds a listener for changes in highlighting. */ - readonly addHighlightingUpdatedListener: (listener: Generator) => void + readonly addHighlightingUpdatedListener: (listener: () => void) => void /** * Generates highlighting information for all text flows below the given element. diff --git a/src/modules/highlight/models/tree-cache/flow-trackers/flow-tracker.mts b/src/modules/highlight/models/tree-cache/flow-trackers/flow-tracker.mts index ab26cd1..e1751be 100644 --- a/src/modules/highlight/models/tree-cache/flow-trackers/flow-tracker.mts +++ b/src/modules/highlight/models/tree-cache/flow-trackers/flow-tracker.mts @@ -7,7 +7,7 @@ import type { Flow, Span, AbstractFlowTracker } from "/dist/modules/highlight/models/tree-cache/flow-tracker.mjs"; import { highlightTags } from "/dist/modules/highlight/highlight-tags.mjs"; import { matchInTextFlow } from "/dist/modules/highlight/matcher.mjs"; -import { MatchTerm, type TermPatterns } from "/dist/modules/match-term.mjs"; +import type { MatchTerm, TermPatterns } from "/dist/modules/match-term.mjs"; import type { RContainer, AllReadonly } from "/dist/modules/common.mjs"; class FlowTracker implements AbstractFlowTracker { @@ -26,7 +26,7 @@ class FlowTracker implements AbstractFlowTracker { #spansCreatedListener?: (flowOwner: HTMLElement, spansCreated: AllReadonly>) => void; #spansRemovedListener?: (flowOwner: HTMLElement, spansRemoved: AllReadonly>) => void; #nonSpanOwnerListener?: (flowOwner: HTMLElement) => void; - readonly #highlightingUpdatedListeners = new Set(); + readonly #highlightingUpdatedListeners = new Set<() => void>(); /** * @@ -146,7 +146,7 @@ class FlowTracker implements AbstractFlowTracker { this.cacheFlowWithSpans(terms, textFlows[i]); } for (const listener of this.#highlightingUpdatedListeners) { - listener.next(); + listener(); } } @@ -220,7 +220,7 @@ class FlowTracker implements AbstractFlowTracker { this.#elementFlowsMap.clear(); } for (const listener of this.#highlightingUpdatedListeners) { - listener.next(); + listener(); } } @@ -332,7 +332,7 @@ class FlowTracker implements AbstractFlowTracker { this.#nonSpanOwnerListener = listener; } - addHighlightingUpdatedListener (listener: Generator) { + addHighlightingUpdatedListener (listener: () => void) { this.#highlightingUpdatedListeners.add(listener); } } diff --git a/src/modules/highlight/tools/term-markers/tree-cache.mts b/src/modules/highlight/tools/term-markers/tree-cache.mts index b0ade08..16026e2 100644 --- a/src/modules/highlight/tools/term-markers/tree-cache.mts +++ b/src/modules/highlight/tools/term-markers/tree-cache.mts @@ -46,6 +46,7 @@ class TermMarker implements AbstractTermMarker { hues: ReadonlyArray, highlightedElements: Iterable, ) { + this.setTermsStyle(terms, hues); const termsSet = new Set(terms); let markersHtml = ""; for (const element of highlightedElements) if (this.#elementFlowsMap.has(element)) { diff --git a/src/modules/interface/toolbar.mts b/src/modules/interface/toolbar.mts index 38ea020..425849f 100644 --- a/src/modules/interface/toolbar.mts +++ b/src/modules/interface/toolbar.mts @@ -28,7 +28,13 @@ interface AbstractToolbar { readonly removeTerm: (term: MatchTerm | number) => void /** - * Updates the look of the control to reflect whether or not its term currently occurs within the document. + * Updates the look of every term control, to reflect whether their terms currently occur within the document. + */ + readonly updateStatuses: () => void + + /** + * Updates the look of a term control, to reflect whether its term currently occurs within the document. + * @param term The control's term. */ readonly updateTermStatus: (term: MatchTerm) => void diff --git a/src/modules/interface/toolbars/toolbar.mts b/src/modules/interface/toolbars/toolbar.mts index 3f30288..60a9232 100644 --- a/src/modules/interface/toolbars/toolbar.mts +++ b/src/modules/interface/toolbars/toolbar.mts @@ -312,6 +312,12 @@ class Toolbar implements AbstractToolbar, ToolbarTermControlInterface, ToolbarCo this.refreshTermControls(); } + updateStatuses () { + for (const termControl of this.#termControls) { + termControl.updateStatus(); + } + } + updateTermStatus (term: MatchTerm) { const termToken = this.#termTokens.get(term); this.#termControls.find(control => control.getTermToken() === termToken)?.updateStatus();