This commit is contained in:
+40
-2
@@ -80,9 +80,11 @@ let cropEnd = 0;
|
||||
let cropMax = 0;
|
||||
let activeThumb = null;
|
||||
let activeResultItem = null;
|
||||
let activeResultModalSummaryRequest = 0;
|
||||
const activePlatforms = new Set(["envato", "artgrid", "google video"]);
|
||||
const hlsInstances = new WeakMap();
|
||||
const debugEntries = [];
|
||||
const summaryTranslationCache = new Map();
|
||||
const PREVIEW_PLACEHOLDER = "https://placehold.co/1280x720/0a0a0a/ffffff?text=Preview";
|
||||
|
||||
function proxiedPreviewURL(src) {
|
||||
@@ -484,10 +486,41 @@ function showResultModalGooglePanel(item, message = "") {
|
||||
resultModalFallbackLabel.textContent = item.source || "Preview Fallback";
|
||||
resultModalGoogleImage.src = hasUsableThumbnail(item.thumbnailUrl) ? item.thumbnailUrl : PREVIEW_PLACEHOLDER;
|
||||
resultModalGoogleImage.alt = item.title || "";
|
||||
resultModalGoogleText.textContent = message || item.previewBlockedReason || item.snippet || item.reason || "Open source page or use the primary action.";
|
||||
resultModalGoogleText.textContent = summarizeReason(message || item.previewBlockedReason || item.snippet || item.reason || "Open source page or use the primary action.");
|
||||
setHidden(resultModalGooglePanel, false, "flex");
|
||||
}
|
||||
|
||||
async function translateSummaryForModal(item, originalText, requestId) {
|
||||
const trimmed = String(originalText || "").trim();
|
||||
if (!trimmed) {
|
||||
return;
|
||||
}
|
||||
if (summaryTranslationCache.has(trimmed)) {
|
||||
if (activeResultItem?.link === item.link && activeResultModalSummaryRequest === requestId) {
|
||||
resultModalSnippet.textContent = summaryTranslationCache.get(trimmed);
|
||||
}
|
||||
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 });
|
||||
}
|
||||
}
|
||||
|
||||
function fallbackResultModalMedia(item, reason) {
|
||||
logEvent("result:modal:fallback", { title: item.title, source: item.source, reason, mediaMode: item.mediaMode });
|
||||
if (item.previewVideoUrl) {
|
||||
@@ -582,10 +615,13 @@ function openResultModal(item) {
|
||||
return;
|
||||
}
|
||||
activeResultItem = item;
|
||||
activeResultModalSummaryRequest += 1;
|
||||
const summaryRequestId = activeResultModalSummaryRequest;
|
||||
resultModalTitle.textContent = item.title || "Untitled";
|
||||
resultModalSource.textContent = item.source || "";
|
||||
resultModalReason.textContent = summarizeReason(item.reason) || "AI 노트가 없습니다.";
|
||||
resultModalSnippet.textContent = item.snippet || "원본 페이지에서 사용할 수 있는 설명이 없습니다.";
|
||||
const originalSummary = item.snippet || "원본 페이지에서 사용할 수 있는 설명이 없습니다.";
|
||||
resultModalSnippet.textContent = originalSummary;
|
||||
resultModalOpenExternal.href = item.link || "#";
|
||||
resultModalDownload.classList.toggle("hidden", !item.actionType);
|
||||
resultModalDownload.textContent = item.actionLabel || "Open Source";
|
||||
@@ -617,6 +653,7 @@ function openResultModal(item) {
|
||||
fallbackResultModalMedia(item, fallbackReason);
|
||||
}
|
||||
showModal(resultModal);
|
||||
void translateSummaryForModal(item, item.snippet, summaryRequestId);
|
||||
logEvent("result:modal:open", { title: item.title, source: item.source, link: item.link });
|
||||
}
|
||||
|
||||
@@ -627,6 +664,7 @@ function closeResultViewer() {
|
||||
if (!resultModal.classList.contains("hidden")) {
|
||||
logEvent("result:modal:close", { title: activeResultItem?.title || "" });
|
||||
}
|
||||
activeResultModalSummaryRequest += 1;
|
||||
activeResultItem = null;
|
||||
resetResultModalMedia();
|
||||
hideModal(resultModal);
|
||||
|
||||
+8
-8
@@ -149,8 +149,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="resultModal" class="fixed inset-0 z-50 hidden items-center justify-center bg-black/80 px-4">
|
||||
<div class="flex w-full max-w-7xl flex-col overflow-hidden rounded-3xl border border-white/10 bg-zinc-950 shadow-2xl">
|
||||
<div id="resultModal" class="fixed inset-0 z-50 hidden items-center justify-center bg-black/80 px-3 py-3 sm:px-4 sm:py-4">
|
||||
<div class="result-modal-shell flex w-full max-w-6xl min-h-0 flex-col overflow-hidden rounded-3xl border border-white/10 bg-zinc-950 shadow-2xl">
|
||||
<div class="flex items-center justify-between border-b border-white/10 px-5 py-4">
|
||||
<div class="min-w-0">
|
||||
<p id="resultModalSource" class="text-xs uppercase tracking-[0.25em] text-zinc-500"></p>
|
||||
@@ -161,8 +161,8 @@
|
||||
<button id="closeResultModal" type="button" class="rounded-full border border-white/10 px-3 py-2 text-xs uppercase tracking-[0.2em] text-zinc-300">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-b border-white/10 bg-black/40 p-4">
|
||||
<div id="resultModalMediaFrame" class="aspect-video overflow-hidden rounded-2xl border border-white/10 bg-black">
|
||||
<div class="border-b border-white/10 bg-black/40 p-3 sm:p-4">
|
||||
<div id="resultModalMediaFrame" class="result-modal-media-frame aspect-video overflow-hidden rounded-2xl border border-white/10 bg-black">
|
||||
<iframe id="resultModalFrame" class="hidden h-full w-full bg-white" referrerpolicy="no-referrer" allow="autoplay; fullscreen; encrypted-media; picture-in-picture" allowfullscreen></iframe>
|
||||
<video id="resultModalVideo" class="hidden h-full w-full bg-black object-contain" controls playsinline></video>
|
||||
<img id="resultModalThumbnail" class="hidden h-full w-full object-contain" alt="" />
|
||||
@@ -179,12 +179,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-5 px-5 py-5 lg:grid-cols-[1.6fr_0.8fr]">
|
||||
<div class="rounded-2xl border border-white/10 bg-white/[0.03] p-5">
|
||||
<div class="result-modal-details grid min-h-0 gap-4 px-4 py-4 sm:gap-5 sm:px-5 sm:py-5 lg:grid-cols-[1.6fr_0.8fr]">
|
||||
<div class="min-h-[200px] rounded-2xl border border-white/10 bg-white/[0.03] p-5">
|
||||
<p class="text-xs uppercase tracking-[0.25em] text-zinc-500">AI Note</p>
|
||||
<p id="resultModalReason" class="mt-3 whitespace-pre-wrap text-sm leading-7 text-zinc-200"></p>
|
||||
</div>
|
||||
<div class="flex min-h-[260px] flex-col rounded-2xl border border-white/10 bg-white/[0.03] p-5">
|
||||
<div class="flex min-h-[240px] min-w-0 flex-col rounded-2xl border border-white/10 bg-white/[0.03] p-5">
|
||||
<div class="mb-4 flex flex-col gap-3">
|
||||
<button id="resultModalDownload" type="button" class="hidden w-full rounded-2xl border border-white bg-white px-4 py-3 text-sm font-medium text-black transition hover:bg-zinc-200">
|
||||
Primary Action
|
||||
@@ -223,6 +223,6 @@
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script src="/app.js?v=20260316i" defer></script>
|
||||
<script src="/app.js?v=20260317a" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -50,6 +50,24 @@ body {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.result-modal-shell {
|
||||
max-height: calc(100vh - 1.5rem);
|
||||
}
|
||||
|
||||
.result-modal-media-frame {
|
||||
max-height: min(48vh, 32rem);
|
||||
}
|
||||
|
||||
.result-modal-details {
|
||||
flex: 1 1 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#resultModalSnippet {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.debug-entry {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||||
padding: 10px 8px;
|
||||
@@ -72,3 +90,19 @@ body {
|
||||
word-break: break-word;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
@media (max-height: 900px) {
|
||||
.result-modal-media-frame {
|
||||
max-height: min(40vh, 26rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-height: 720px) {
|
||||
.result-modal-shell {
|
||||
max-height: calc(100vh - 1rem);
|
||||
}
|
||||
|
||||
.result-modal-media-frame {
|
||||
max-height: min(34vh, 18rem);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user