Skip to content

Commit 7987f28

Browse files
Delayed content collect
1 parent e612930 commit 7987f28

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

injected/src/features/page-context.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export default class PageContext extends ContentFeature {
7474
mutationObserver = null;
7575
lastSentContent = null;
7676
listenForUrlChanges = true;
77+
/** @type {ReturnType<typeof setTimeout> | null} */
78+
#delayedRecheckTimer = null;
7779

7880
init() {
7981
if (!this.shouldActivate()) {
@@ -95,7 +97,11 @@ export default class PageContext extends ContentFeature {
9597
});
9698
if (this.getFeatureSettingEnabled('subscribeToHashChange', 'enabled')) {
9799
window.addEventListener('hashchange', () => {
100+
// Immediate collection
98101
this.handleContentCollectionRequest();
102+
103+
// Schedule delayed recheck after DOM settles
104+
this.scheduleDelayedRecheck();
99105
});
100106
}
101107
if (this.getFeatureSettingEnabled('subscribeToPageShow', 'enabled')) {
@@ -145,7 +151,11 @@ export default class PageContext extends ContentFeature {
145151
if (!this.shouldActivate()) {
146152
return;
147153
}
154+
// Immediate collection
148155
this.handleContentCollectionRequest();
156+
157+
// Schedule delayed recheck after DOM settles
158+
this.scheduleDelayedRecheck();
149159
}
150160

151161
setup() {
@@ -169,6 +179,17 @@ export default class PageContext extends ContentFeature {
169179
this.#cachedContent = undefined;
170180
this.#cachedTimestamp = 0;
171181
this.stopObserving();
182+
this.clearTimers();
183+
}
184+
185+
/**
186+
* Clear all pending timers
187+
*/
188+
clearTimers() {
189+
if (this.#delayedRecheckTimer) {
190+
clearTimeout(this.#delayedRecheckTimer);
191+
this.#delayedRecheckTimer = null;
192+
}
172193
}
173194

174195
set cachedContent(content) {
@@ -198,6 +219,69 @@ export default class PageContext extends ContentFeature {
198219
}
199220
}
200221

222+
/**
223+
* Schedule a delayed recheck after navigation events
224+
*/
225+
scheduleDelayedRecheck() {
226+
// Clear any existing delayed recheck
227+
if (this.#delayedRecheckTimer) {
228+
clearTimeout(this.#delayedRecheckTimer);
229+
}
230+
231+
const delayMs = this.getFeatureSetting('navigationRecheckDelayMs') || 1500;
232+
233+
this.log.info('Scheduling delayed recheck', { delayMs });
234+
this.#delayedRecheckTimer = setTimeout(() => {
235+
this.log.info('Performing delayed recheck after navigation');
236+
237+
// Store the previous content for comparison
238+
const previousContent = this.cachedContent;
239+
240+
// Force fresh collection by invalidating cache
241+
this.invalidateCache();
242+
243+
// Collect fresh content
244+
const freshContent = this.collectPageContent();
245+
246+
// Only send if content has meaningfully changed
247+
if (this.hasContentChanged(previousContent, freshContent)) {
248+
this.log.info('Content changed after navigation delay - sending update');
249+
this.sendContentResponse(freshContent);
250+
} else {
251+
this.log.info('No significant content change after navigation delay');
252+
}
253+
254+
this.#delayedRecheckTimer = null;
255+
}, delayMs);
256+
}
257+
258+
/**
259+
* Check if content has meaningfully changed
260+
* @param {any} oldContent
261+
* @param {any} newContent
262+
* @returns {boolean}
263+
*/
264+
hasContentChanged(oldContent, newContent) {
265+
if (!oldContent || !newContent) {
266+
return true;
267+
}
268+
269+
// Compare key content fields
270+
const fieldsToCompare = ['title', 'content', 'headings'];
271+
272+
for (const field of fieldsToCompare) {
273+
const oldValue = JSON.stringify(oldContent[field] || '');
274+
const newValue = JSON.stringify(newContent[field] || '');
275+
276+
if (oldValue !== newValue) {
277+
this.log.info('Content changed in field', field);
278+
return true;
279+
}
280+
}
281+
282+
return false;
283+
}
284+
201285
startObserving() {
202286
this.log.info('Starting observing', this.mutationObserver, this.#cachedContent);
203287
if (this.mutationObserver && this.#cachedContent && !this.isObserving) {

0 commit comments

Comments
 (0)