This commit is contained in:
@@ -255,6 +255,22 @@
|
||||
- backend debug broadcasts
|
||||
|
||||
## Recent Change Log
|
||||
- Date: `2026-03-16`
|
||||
- What changed:
|
||||
- Hid the expanded query-variant chip list from the search UI while leaving backend/debug query visibility intact.
|
||||
- Reworked the result modal action panel so its primary CTA now follows source capability: `Direct Download` for Google Video and `Open Source` for Envato/Artgrid.
|
||||
- Added a secondary action button area plus internal scrolling for long Source Summary text so long descriptions no longer push action buttons off-screen.
|
||||
- Switched Google Video modal rendering from iframe-style embed-first behavior to a webpage-like preview panel, while keeping Artgrid/Envato on the existing media-mode path.
|
||||
- Bumped the frontend asset version again to force browsers onto the updated modal behavior.
|
||||
- Why it changed:
|
||||
- The remaining user issues were now primarily UX/layout issues: too little visible result choice, hidden buttons under long summaries, query-variant clutter, and modal actions that did not match what each source can actually do.
|
||||
- How it was verified:
|
||||
- `go test ./...`
|
||||
- `bash scripts/selftest.sh`
|
||||
- What is still risky or incomplete:
|
||||
- Live browser validation is still needed to confirm the widened search pool feels better in real queries and that the new Google Video panel feels sufficiently “webpage-like” in practice.
|
||||
- `node` is still unavailable in this environment, so no frontend static syntax/build step was added here.
|
||||
|
||||
- Date: `2026-03-16`
|
||||
- What changed:
|
||||
- Expanded search breadth moderately by increasing base query count, collector query budgets, per-source caps, enrichment scope, and final visible result target while keeping Gemini review cap at `16`.
|
||||
|
||||
+28
-22
@@ -52,6 +52,7 @@ const resultModalGoogleText = document.getElementById("resultModalGoogleText");
|
||||
const resultModalFallbackLabel = document.getElementById("resultModalFallbackLabel");
|
||||
const resultModalOpenExternal = document.getElementById("resultModalOpenExternal");
|
||||
const resultModalDownload = document.getElementById("resultModalDownload");
|
||||
const resultModalSecondaryAction = document.getElementById("resultModalSecondaryAction");
|
||||
const closeResultModal = document.getElementById("closeResultModal");
|
||||
const resultModalReady = Boolean(
|
||||
resultModal &&
|
||||
@@ -69,6 +70,7 @@ const resultModalReady = Boolean(
|
||||
resultModalFallbackLabel &&
|
||||
resultModalOpenExternal &&
|
||||
resultModalDownload &&
|
||||
resultModalSecondaryAction &&
|
||||
closeResultModal,
|
||||
);
|
||||
|
||||
@@ -254,18 +256,7 @@ function syncRanges() {
|
||||
}
|
||||
|
||||
function renderQueryVariants(queries = []) {
|
||||
queryVariants.innerHTML = "";
|
||||
if (!queries.length) {
|
||||
queryVariants.classList.add("hidden");
|
||||
return;
|
||||
}
|
||||
for (const item of queries) {
|
||||
const badge = document.createElement("span");
|
||||
badge.className = "rounded-full border border-white/10 bg-white/[0.03] px-3 py-1 text-xs uppercase tracking-[0.18em] text-zinc-300";
|
||||
badge.textContent = item;
|
||||
queryVariants.appendChild(badge);
|
||||
}
|
||||
queryVariants.classList.remove("hidden");
|
||||
queryVariants.classList.add("hidden");
|
||||
}
|
||||
|
||||
function syncPlatformButtons() {
|
||||
@@ -493,7 +484,7 @@ 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 || "Preview fallback is being shown.";
|
||||
resultModalGoogleText.textContent = message || item.previewBlockedReason || item.snippet || item.reason || "Open source page or use the primary action.";
|
||||
setHidden(resultModalGooglePanel, false, "flex");
|
||||
}
|
||||
|
||||
@@ -596,12 +587,17 @@ function openResultModal(item) {
|
||||
resultModalReason.textContent = summarizeReason(item.reason) || "AI 노트가 없습니다.";
|
||||
resultModalSnippet.textContent = item.snippet || "원본 페이지에서 사용할 수 있는 설명이 없습니다.";
|
||||
resultModalOpenExternal.href = item.link || "#";
|
||||
const canDirectDownload = item.source === "Google Video" && item.link;
|
||||
resultModalDownload.classList.toggle("hidden", !canDirectDownload);
|
||||
resultModalDownload.classList.toggle("hidden", !item.actionType);
|
||||
resultModalDownload.textContent = item.actionLabel || "Open Source";
|
||||
const showSecondary = Boolean(item.secondaryActionLabel && item.link);
|
||||
resultModalSecondaryAction.classList.toggle("hidden", !showSecondary);
|
||||
resultModalSecondaryAction.textContent = item.secondaryActionLabel || "Open Source";
|
||||
resetResultModalMedia();
|
||||
const embedURL = buildResultModalEmbedURL(item);
|
||||
const fallbackReason = item.previewBlockedReason || "Embedded view was unavailable, switched to fallback preview.";
|
||||
if (item.mediaMode === "embed" && embedURL && embedURL !== "about:blank") {
|
||||
if (item.source === "Google Video" && item.mediaMode === "thumbnail") {
|
||||
showResultModalGooglePanel(item, item.snippet || "Open source page or download directly.");
|
||||
} else if (item.mediaMode === "embed" && embedURL && embedURL !== "about:blank") {
|
||||
showResultModalFrame(embedURL);
|
||||
const timeout = window.setTimeout(() => {
|
||||
logEvent("result:modal:iframe_timeout", { title: item.title, source: item.source, embedURL });
|
||||
@@ -782,13 +778,23 @@ if (resultModalReady) {
|
||||
return;
|
||||
}
|
||||
const currentItem = activeResultItem;
|
||||
try {
|
||||
closeResultViewer();
|
||||
await prepareDirectDownload(currentItem.link);
|
||||
} catch (error) {
|
||||
downloadResult.textContent = error.message;
|
||||
logEvent("download:preview:error", { message: error.message, data: error.data || null, source: currentItem?.source || "" });
|
||||
if (currentItem.actionType === "download") {
|
||||
try {
|
||||
closeResultViewer();
|
||||
await prepareDirectDownload(currentItem.link);
|
||||
} catch (error) {
|
||||
downloadResult.textContent = error.message;
|
||||
logEvent("download:preview:error", { message: error.message, data: error.data || null, source: currentItem?.source || "" });
|
||||
}
|
||||
return;
|
||||
}
|
||||
window.open(currentItem.link, "_blank", "noopener,noreferrer");
|
||||
});
|
||||
resultModalSecondaryAction.addEventListener("click", () => {
|
||||
if (!activeResultItem?.link) {
|
||||
return;
|
||||
}
|
||||
window.open(activeResultItem.link, "_blank", "noopener,noreferrer");
|
||||
});
|
||||
}
|
||||
previewModal.addEventListener("click", (event) => {
|
||||
|
||||
+15
-8
@@ -46,7 +46,7 @@
|
||||
<button class="rounded-2xl border border-white bg-white px-7 py-4 text-base font-medium text-black transition hover:bg-zinc-200">AI Search</button>
|
||||
</form>
|
||||
<div id="searchWarning" class="mt-3 hidden rounded-2xl border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-sm text-amber-200"></div>
|
||||
<div id="queryVariants" class="mt-3 hidden flex-wrap gap-2"></div>
|
||||
<div id="queryVariants" class="hidden"></div>
|
||||
<div id="searchResults" class="mt-6 grid gap-5 sm:grid-cols-2 xl:grid-cols-3"></div>
|
||||
</article>
|
||||
|
||||
@@ -184,13 +184,20 @@
|
||||
<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="space-y-4 rounded-2xl border border-white/10 bg-white/[0.03] p-5">
|
||||
<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">
|
||||
Direct Download
|
||||
</button>
|
||||
<div>
|
||||
<div class="flex min-h-[260px] 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
|
||||
</button>
|
||||
<button id="resultModalSecondaryAction" type="button" class="hidden w-full rounded-2xl border border-white/10 px-4 py-3 text-sm font-medium text-zinc-100 transition hover:border-white/30">
|
||||
Secondary Action
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex min-h-0 flex-1 flex-col">
|
||||
<p class="text-xs uppercase tracking-[0.25em] text-zinc-500">Source Summary</p>
|
||||
<p id="resultModalSnippet" class="mt-3 text-sm leading-7 text-zinc-300"></p>
|
||||
<div class="result-summary-scroll mt-3 min-h-0 flex-1 overflow-y-auto pr-2">
|
||||
<p id="resultModalSnippet" class="text-sm leading-7 text-zinc-300"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,6 +223,6 @@
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script src="/app.js?v=20260316h" defer></script>
|
||||
<script src="/app.js?v=20260316i" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -41,6 +41,15 @@ body {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.result-summary-scroll::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.result-summary-scroll::-webkit-scrollbar-thumb {
|
||||
background: rgba(255, 255, 255, 0.16);
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.debug-entry {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||||
padding: 10px 8px;
|
||||
|
||||
Reference in New Issue
Block a user