feat: add Load More button for paginated solve results

Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Alex-GilbertandClaude Opus 4.6 committed 2026-02-23 14:51:49 -06:00
1 parent b51dc18d9c
commit 44e324e2f5
3 files changed
+52 -2

No files matched your search

+1
View File
@@ -38,6 +38,7 @@ export const solveStop = document.getElementById("solve-stop");
export const solveAccept = document.getElementById("solve-accept");
export const solveStatus = document.getElementById("solve-status");
export const solveResults = document.getElementById("solve-results");
export const solveLoadMore = /** @type {HTMLButtonElement} */ (document.getElementById("solve-load-more"));
export const fontToolbar = document.getElementById("font-toolbar");
export const fontSelect = /** @type {HTMLSelectElement} */ (document.getElementById("font-select"));
export const sizeSlider = /** @type {HTMLInputElement} */ (document.getElementById("size-slider"));
+1
View File
@@ -153,6 +153,7 @@
<span id="solve-status"></span>
</div>
<div id="solve-results"></div>
<button id="solve-load-more" class="solve-btn" hidden>Load more</button>
</div>
<div id="doc-container">
<img id="doc-image" alt="Document page">
+50 -2
View File
@@ -6,7 +6,7 @@ import {
solveCharset, solveTolerance, solveMode, solveFilter,
solveKnownStart, solveKnownEnd, solvePlural, solveVocab,
solveResults, solveStatus, solveStart, solveStop,
solveAccept, redactionMarker, escapeHtml,
solveAccept, solveLoadMore, redactionMarker, escapeHtml,
} from './dom.js';
import { renderCanvas } from './canvas.js';
import { matchAssociates, tierBadgeClass, tierLabel, isVictimMatch, showAssocDetail } from './associates.js';
@@ -14,6 +14,11 @@ import { matchAssociates, tierBadgeClass, tierLabel, isVictimMatch, showAssocDet
/** @type {AbortController|null} */
let activeEventSource = null;
/** @type {string|null} */
let currentSolveId = null;
let displayedCount = 0;
let totalFound = 0;
export function startSolve() {
const id = state.activeRedaction;
if (!id) return;
@@ -32,6 +37,10 @@ export function startSolve() {
const rightCtx = rightText.length > 0 ? rightText[0] : "";
solveResults.innerHTML = "";
solveLoadMore.hidden = true;
currentSolveId = null;
displayedCount = 0;
totalFound = 0;
solveStatus.textContent = "Starting...";
solveStart.hidden = true;
solveStop.hidden = false;
@@ -184,10 +193,19 @@ function handleSolveEvent(data, redactionId) {
solveResults.appendChild(div);
}
solveStatus.textContent = `Found ${solveResults.children.length} matches`;
displayedCount++;
solveStatus.textContent = `Found ${displayedCount} matches`;
} else if (data.status === "running") {
solveStatus.textContent = `Checked ${data.checked}, found ${data.found}...`;
} else if (data.status === "page_complete") {
currentSolveId = data.solve_id;
solveStatus.textContent = `Found ${displayedCount} matches, searching for more...`;
} else if (data.status === "done") {
totalFound = data.total_found;
if (totalFound > displayedCount) {
solveLoadMore.textContent = `Load more (showing ${displayedCount} of ${totalFound})`;
solveLoadMore.hidden = false;
}
solveStatus.textContent = `Done. ${data.total_found} total matches.`;
solveStart.hidden = false;
solveStop.hidden = true;
@@ -231,8 +249,38 @@ export function acceptSolution() {
r.solveFullText = null;
}
async function loadMore() {
if (!currentSolveId) return;
solveLoadMore.disabled = true;
solveLoadMore.textContent = "Loading...";
try {
const resp = await fetch(
`/api/solve/${currentSolveId}/results?offset=${displayedCount}&limit=200`
);
if (!resp.ok) throw new Error("Failed to load results");
const data = await resp.json();
const redactionId = state.activeRedaction;
for (const item of data.results) {
handleSolveEvent({ status: "match", ...item }, redactionId);
}
if (displayedCount >= totalFound) {
solveLoadMore.hidden = true;
} else {
solveLoadMore.textContent = `Load more (showing ${displayedCount} of ${totalFound})`;
solveLoadMore.disabled = false;
}
} catch (err) {
solveLoadMore.textContent = "Error loading — click to retry";
solveLoadMore.disabled = false;
}
}
/** Set up solver button listeners. Call once from main.js. */
export function initSolver() {
solveStart.addEventListener("click", startSolve);
solveStop.addEventListener("click", stopSolve);
solveLoadMore.addEventListener("click", loadMore);
}