Refine modal actions and hide query variants
build-push / docker (push) Successful in 4m29s

This commit is contained in:
AI Assistant
2026-03-16 17:09:56 +09:00
parent 19425c9503
commit 001f4fd4bb
4 changed files with 68 additions and 30 deletions
+16
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+9
View File
@@ -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;