// Standalone Bulk ID Check window.
// Launched via chrome.windows.create from popup; background.js owns
// the windowId lifecycle (chrome.storage.session.bulkCheckWindowId).
const LAST_PASTE_KEY = "bulkCheckLastPaste";
const SAVE_DEBOUNCE_MS = 500;
function escapeHtml(s) {
return String(s ?? "").replace(/[&<>"']/g, (c) =>
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]));
}
function readBulkIds() {
return [...new Set(document.getElementById("bulk-id-input").value
.split(/[\s,]+/)
.map((x) => x.trim())
.filter(Boolean))];
}
function updateCountPill() {
const ids = readBulkIds();
const pill = document.getElementById("count-pill");
pill.textContent = ids.length ? `${ids.length} unique ID${ids.length === 1 ? "" : "s"}` : "";
}
function renderBulkResults(r) {
const out = document.getElementById("bulk-id-results");
if (!r || !r.ok) {
out.innerHTML = `error: ${escapeHtml(r?.error || "no response")}`;
return;
}
const rows = [
`
Mode: ${escapeHtml(r.search_mode || "?")} · Queries: ${escapeHtml(r.query_count || 0)} · Hits: ${escapeHtml(r.hits || 0)} · Host: ${escapeHtml(r.timings?.host_rcjav_ms ?? "?")}ms
`,
];
for (const q of r.queries || []) {
const hit = q.hits > 0;
const sample = (q.structured || []).slice(0, 3).map((h) => h.full_path || h.path || h.jav_id).join(" | ");
rows.push(`
${hit ? "HIT" : "MISS"}
${escapeHtml(q.query || "?")} · ${escapeHtml(q.hits || 0)} hit(s)
${sample ? `
${escapeHtml(sample)}
` : `
${escapeHtml(q.no_match_title || "No library hit")}
`}
`);
}
out.innerHTML = rows.join("");
}
async function refreshModePill() {
const pill = document.getElementById("mode-pill");
try {
const settings = await chrome.runtime.sendMessage({ type: "get-settings" });
const mode = settings?.quickMode !== false ? "LIVE" : "CACHE";
pill.textContent = mode;
pill.dataset.mode = mode;
} catch {
pill.textContent = "?";
}
}
let _saveTimer = null;
function schedulePersist() {
if (_saveTimer) clearTimeout(_saveTimer);
_saveTimer = setTimeout(async () => {
_saveTimer = null;
const value = document.getElementById("bulk-id-input").value;
try {
await chrome.storage.local.set({ [LAST_PASTE_KEY]: value });
} catch { /* ignore */ }
}, SAVE_DEBOUNCE_MS);
}
async function restoreLastPaste() {
try {
const stored = await chrome.storage.local.get(LAST_PASTE_KEY);
const value = stored?.[LAST_PASTE_KEY];
if (typeof value === "string" && value) {
document.getElementById("bulk-id-input").value = value;
updateCountPill();
}
} catch { /* ignore */ }
}
document.getElementById("bulk-id-input").addEventListener("input", () => {
updateCountPill();
schedulePersist();
});
document.getElementById("bulk-id-clear").addEventListener("click", () => {
document.getElementById("bulk-id-input").value = "";
document.getElementById("bulk-id-results").innerHTML = "";
updateCountPill();
schedulePersist();
});
document.getElementById("bulk-id-run").addEventListener("click", async () => {
const runBtn = document.getElementById("bulk-id-run");
const out = document.getElementById("bulk-id-results");
const queries = readBulkIds();
if (!queries.length) {
out.innerHTML = `paste at least one ID`;
return;
}
runBtn.disabled = true;
runBtn.classList.add("running");
out.textContent = `checking ${queries.length} ID(s)...`;
try {
const settings = await chrome.runtime.sendMessage({ type: "get-settings" });
const quick = settings?.quickMode !== false;
const r = await chrome.runtime.sendMessage({
type: "bulk-query",
queries,
quick,
});
renderBulkResults(r);
} catch (err) {
out.innerHTML = `error: ${escapeHtml(err?.message || String(err))}`;
} finally {
runBtn.disabled = false;
runBtn.classList.remove("running");
}
});
// Ctrl/Cmd+Enter inside textarea = run
document.getElementById("bulk-id-input").addEventListener("keydown", (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
e.preventDefault();
document.getElementById("bulk-id-run").click();
}
});
(async () => {
await restoreLastPaste();
await refreshModePill();
})();