Improve modal fit and Gemini search refinement
build-push / docker (push) Successful in 4m8s

This commit is contained in:
AI Assistant
2026-03-17 12:30:50 +09:00
parent 0b68feff80
commit 556d4d6c1b
8 changed files with 353 additions and 77 deletions
+82 -25
View File
@@ -85,6 +85,8 @@ const activePlatforms = new Set(["envato", "artgrid", "google video"]);
const hlsInstances = new WeakMap();
const debugEntries = [];
const summaryTranslationCache = new Map();
const summaryTranslationInflight = new Map();
let cardSummaryObserver = null;
const PREVIEW_PLACEHOLDER = "https://placehold.co/1280x720/0a0a0a/ffffff?text=Preview";
function proxiedPreviewURL(src) {
@@ -120,9 +122,6 @@ function summarizeReason(reason) {
if (!text) {
return "";
}
if (text === "Ranked candidate pending stronger visual evidence.") {
return "Preview evidence pending";
}
if (text === "Fallback due to missing provider preview.") {
return "Provider preview missing";
}
@@ -491,34 +490,84 @@ function showResultModalGooglePanel(item, message = "") {
}
async function translateSummaryForModal(item, originalText, requestId) {
const translated = await translateSummaryText(originalText);
if (!translated) {
return;
}
if (activeResultItem?.link === item.link && activeResultModalSummaryRequest === requestId) {
resultModalSnippet.textContent = translated;
logEvent("result:modal:summary_translated", { title: item.title, source: item.source });
}
}
async function translateSummaryText(originalText) {
const trimmed = String(originalText || "").trim();
if (!trimmed) {
return;
return "";
}
if (summaryTranslationCache.has(trimmed)) {
if (activeResultItem?.link === item.link && activeResultModalSummaryRequest === requestId) {
resultModalSnippet.textContent = summaryTranslationCache.get(trimmed);
return summaryTranslationCache.get(trimmed);
}
if (summaryTranslationInflight.has(trimmed)) {
return summaryTranslationInflight.get(trimmed);
}
const request = (async () => {
try {
const data = await api("/api/translate/summary", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: trimmed }),
});
const translated = String(data.translatedText || "").trim();
if (translated) {
summaryTranslationCache.set(trimmed, translated);
}
return translated;
} catch {
return "";
} finally {
summaryTranslationInflight.delete(trimmed);
}
})();
summaryTranslationInflight.set(trimmed, request);
try {
return await request;
} catch {
return "";
}
}
async function translateCardSummary(node) {
if (!node || node.dataset.summaryTranslated === "true") {
return;
}
try {
const data = await api("/api/translate/summary", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: trimmed }),
});
const translated = String(data.translatedText || "").trim();
if (!translated) {
return;
}
summaryTranslationCache.set(trimmed, translated);
if (activeResultItem?.link === item.link && activeResultModalSummaryRequest === requestId) {
resultModalSnippet.textContent = translated;
logEvent("result:modal:summary_translated", { title: item.title, source: item.source });
}
} catch (error) {
logEvent("result:modal:summary_translate_failed", { title: item.title, source: item.source, message: error.message });
node.dataset.summaryTranslated = "true";
const originalText = node.dataset.summaryOriginal || "";
const translated = await translateSummaryText(originalText);
if (!translated) {
return;
}
const summaryNode = node.querySelector(".result-reason");
if (summaryNode) {
summaryNode.textContent = translated;
}
}
function ensureCardSummaryObserver() {
if (cardSummaryObserver || typeof IntersectionObserver === "undefined") {
return;
}
cardSummaryObserver = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) {
continue;
}
cardSummaryObserver.unobserve(entry.target);
void translateCardSummary(entry.target);
}
}, { rootMargin: "160px 0px" });
}
function fallbackResultModalMedia(item, reason) {
@@ -536,6 +585,7 @@ function fallbackResultModalMedia(item, reason) {
function renderResults(results) {
searchResults.innerHTML = "";
ensureCardSummaryObserver();
if (!results.length) {
searchResults.innerHTML = `<div class="rounded-3xl border border-white/10 bg-black/30 p-5 text-sm text-zinc-400">No results matched the current search sources.</div>`;
return;
@@ -561,9 +611,11 @@ function renderResults(results) {
mediaFallback.textContent = item.source === "Envato" || item.source === "Artgrid" ? `${item.source} preview unavailable` : "Preview unavailable";
}
node.querySelector("h3").textContent = item.title;
node.querySelector(".result-snippet").textContent = summarizeReason(item.reason) || item.snippet || item.source || "";
node.querySelector(".result-reason").textContent = item.snippet ? `Source: ${item.snippet}` : (item.previewBlockedReason || "");
node.querySelector(".result-snippet").textContent = summarizeReason(item.reason) || item.source || "";
node.querySelector(".result-reason").textContent = item.snippet || item.previewBlockedReason || "";
node.querySelector(".source-badge").textContent = item.source;
node.dataset.summaryOriginal = item.snippet || "";
node.dataset.summaryTranslated = "false";
node.addEventListener("click", () => openResultModal(item));
previewVideo.poster = usableThumbnail ? item.thumbnailUrl : "";
if (item.previewVideoUrl) {
@@ -582,6 +634,11 @@ function renderResults(results) {
overlays.forEach((overlay) => overlay.classList.remove("hidden"));
});
}
if (cardSummaryObserver && item.snippet) {
cardSummaryObserver.observe(node);
} else if (item.snippet) {
void translateCardSummary(node);
}
searchResults.appendChild(node);
}
}