Step 7a: Bulk ID Check moves to a detached popup window

New files:
  bulk-check.html, bulk-check.js, bulk-check.css

Popup gains a 📋 launcher button next to the ⚙ Options gear. Clicking
it sends `open-bulk-check` to background.js and closes the popup;
background.js owns window lifecycle:

  - chrome.storage.session.bulkCheckWindowId stashes the open window id
  - existing id → chrome.windows.update({ focused, drawAttention })
  - missing or stale id → chrome.windows.create({ type:'popup',
    width:640, height:540 }) and stash the new id
  - chrome.windows.onRemoved clears the stale id on close

Last-paste persisted to chrome.storage.local.bulkCheckLastPaste,
debounced 500ms on input, restored on window open. quickMode is read
from settings at run time, matching previous behavior. Ctrl/Cmd+Enter
inside the textarea triggers the check.

Options page no longer carries the Bulk ID Check fieldset: removed
from options.html (Library Review pdesc updated to note the
relocation) and the matching handlers from options.js
(1903 → 1852 lines). No manifest permission changes — own-page
chrome.windows.create needs no extra permission.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
admin
2026-05-22 21:27:12 +02:00
parent e4ee06b19f
commit ad4df28a66
9 changed files with 321 additions and 64 deletions
-51
View File
@@ -674,57 +674,6 @@ document.getElementById("search-bench-clear").addEventListener("click", () => {
document.getElementById("search-bench-results").innerHTML = "";
});
// ---------- bulk ID check ----------
function readBulkIds() {
return [...new Set(document.getElementById("bulk-id-input").value
.split(/[\s,]+/)
.map((x) => x.trim())
.filter(Boolean))];
}
function renderBulkResults(r) {
const out = document.getElementById("bulk-id-results");
if (!r || !r.ok) {
out.innerHTML = `<span style="color:#faa;">error:</span> ${escapeHtml(r?.error || "no response")}`;
return;
}
const rows = [
`<div><span style="color:#777;">Mode:</span> ${escapeHtml(r.search_mode || "?")} · <span style="color:#777;">Queries:</span> ${escapeHtml(r.query_count || 0)} · <span style="color:#777;">Hits:</span> ${escapeHtml(r.hits || 0)} · <span style="color:#777;">Host:</span> ${escapeHtml(r.timings?.host_rcjav_ms ?? "?")}ms</div>`,
];
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(`<div style="margin-top:7px;">
<span style="color:${hit ? "#afa" : "#ffa"};font-weight:600;">${hit ? "HIT" : "MISS"}</span>
<span>${escapeHtml(q.query || "?")}</span> · ${escapeHtml(q.hits || 0)} hit(s)
${sample ? `<div style="color:#777;margin-left:12px;">${escapeHtml(sample)}</div>` : `<div style="color:#777;margin-left:12px;">${escapeHtml(q.no_match_title || "No library hit")}</div>`}
</div>`);
}
out.innerHTML = rows.join("");
}
document.getElementById("bulk-id-run").addEventListener("click", async () => {
const out = document.getElementById("bulk-id-results");
const queries = readBulkIds();
if (!queries.length) {
out.innerHTML = `<span style="color:#ffa;">paste at least one ID</span>`;
return;
}
out.textContent = `checking ${queries.length} ID(s)...`;
const r = await chrome.runtime.sendMessage({
type: "bulk-query",
queries,
quick: document.getElementById("quickMode").checked,
});
renderBulkResults(r);
});
document.getElementById("bulk-id-clear").addEventListener("click", () => {
document.getElementById("bulk-id-input").value = "";
document.getElementById("bulk-id-results").innerHTML = "";
});
// ---------- adapters ----------
function renderAdapters(list) {