scrollToLoad walks a progressively-loading list to the bottom before the steps that act on its items run. Stopping is two-part: no new matches appeared AND the container was already pinned to the bottom — counting alone stops early on a slow fetch. Hitting the scroll cap is reported rather than passed off as done, so a later step never works quietly on a partial list. The scrolling element is usually not the window. Lists like this live in a div with its own overflow, and scrolling the document does nothing at all, so the step walks up from a matched item to the ancestor that actually scrolls — overflow allows it and there is more content than fits — with containerSelector to name one outright when the guess is wrong. Verified against a page whose document also scrolls, which is the case that tells the two apart: it found the inner div and pulled 12 items up to 60 in 7 scrolls. waitFor gains `absent`, for waiting on something to go rather than arrive — a modal closing after a reset. It only accepts a genuine "selector matched nothing"; an unreachable extension looks the same from a distance and would otherwise satisfy the gate for the wrong reason, sending the next iteration into a page that still has the modal open. The locate queue carries a free-form options blob now, so a new kind of request stops meaning a new column each time. Also fixes a missing comma in the reset flow that broke the build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
25 lines
806 B
TypeScript
25 lines
806 B
TypeScript
import { claimLocateRequest } from '@/lib/db';
|
|
import { corsJson, corsPreflight } from '../../cors';
|
|
|
|
/** The extension takes the oldest pending request. Claiming marks it in-flight so
|
|
* the next poll doesn't run the same click a second time. */
|
|
export async function POST() {
|
|
const row = claimLocateRequest();
|
|
if (!row) return corsJson({ request: null });
|
|
return corsJson({
|
|
request: {
|
|
id: row.id,
|
|
selector: row.selector,
|
|
index: row.match_index,
|
|
urlPattern: row.url_pattern,
|
|
openUrl: row.open_url,
|
|
navigateUrl: row.navigate_url,
|
|
options: (() => { try { return JSON.parse(row.options); } catch { return {}; } })(),
|
|
},
|
|
});
|
|
}
|
|
|
|
export async function OPTIONS() {
|
|
return corsPreflight();
|
|
}
|