Fix result modal cache mismatch
build-push / docker (push) Successful in 4m22s

This commit is contained in:
AI Assistant
2026-03-16 12:05:47 +09:00
parent 45ff5b860c
commit 975bd99610
3 changed files with 68 additions and 29 deletions
+10
View File
@@ -255,6 +255,16 @@
- backend debug broadcasts
## Recent Change Log
- Date: `2026-03-16`
- What changed:
- Bumped frontend asset version and added result-modal initialization guards to avoid click failures when browser cache serves mismatched HTML/JS.
- Why it changed:
- The result modal stopped opening after the modal markup refactor, which is consistent with stale cached frontend assets or partially initialized modal DOM.
- How it was verified:
- static code inspection of modal DOM/JS bindings
- What is still risky or incomplete:
- Browser cache behavior itself was not fully reproduced here, so a hard refresh may still be needed in an already-open client session.
- Date: `2026-03-16`
- What changed:
- Envato preview extraction now also inspects `INITIAL_HYDRATION_DATA` when direct page meta / JSON-LD preview URLs are missing.
+57 -28
View File
@@ -49,6 +49,20 @@ const resultModalMediaFrame = document.getElementById("resultModalMediaFrame");
const resultModalVideo = document.getElementById("resultModalVideo");
const resultModalThumbnail = document.getElementById("resultModalThumbnail");
const resultModalEmbedNotice = document.getElementById("resultModalEmbedNotice");
const resultModalReady = Boolean(
resultModal &&
resultModalTitle &&
resultModalSource &&
resultModalSnippet &&
resultModalReason &&
resultModalOpenExternal &&
resultModalDownload &&
closeResultModal &&
resultModalMediaFrame &&
resultModalVideo &&
resultModalThumbnail &&
resultModalEmbedNotice,
);
let pendingDownload = null;
let cropStart = 0;
@@ -349,6 +363,9 @@ function hideModal(element) {
}
function resetResultModalMedia() {
if (!resultModalReady) {
return;
}
resultModalVideo.pause();
detachVideoSource(resultModalVideo);
resultModalMediaFrame.style.aspectRatio = "";
@@ -420,6 +437,10 @@ async function prepareDirectDownload(targetUrl) {
}
function openResultModal(item) {
if (!resultModalReady) {
logEvent("result:modal:error", { message: "result modal is not fully initialized" });
return;
}
activeResultItem = item;
resultModalTitle.textContent = item.title || "Untitled";
resultModalSource.textContent = item.source || "";
@@ -444,6 +465,9 @@ function openResultModal(item) {
}
function closeResultViewer() {
if (!resultModalReady) {
return;
}
if (!resultModal.classList.contains("hidden")) {
logEvent("result:modal:close", { title: activeResultItem?.title || "" });
}
@@ -586,24 +610,27 @@ confirmDownload.addEventListener("click", async () => {
});
closePreviewModal.addEventListener("click", closeModal);
closeResultModal.addEventListener("click", closeResultViewer);
resultModal.addEventListener("click", (event) => {
if (event.target === resultModal) {
closeResultViewer();
}
});
resultModalDownload.addEventListener("click", async () => {
if (!activeResultItem?.link) {
return;
}
try {
closeResultViewer();
await prepareDirectDownload(activeResultItem.link);
} catch (error) {
downloadResult.textContent = error.message;
logEvent("download:preview:error", { message: error.message, data: error.data || null, source: activeResultItem?.source || "" });
}
});
if (resultModalReady) {
closeResultModal.addEventListener("click", closeResultViewer);
resultModal.addEventListener("click", (event) => {
if (event.target === resultModal) {
closeResultViewer();
}
});
resultModalDownload.addEventListener("click", async () => {
if (!activeResultItem?.link) {
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 || "" });
}
});
}
previewModal.addEventListener("click", (event) => {
if (event.target === previewModal) {
closeModal();
@@ -663,16 +690,18 @@ previewThumbnail.addEventListener("load", () => {
previewMediaFrame.style.aspectRatio = `${previewThumbnail.naturalWidth} / ${previewThumbnail.naturalHeight}`;
}
});
resultModalVideo.addEventListener("loadedmetadata", () => {
if (resultModalVideo.videoWidth > 0 && resultModalVideo.videoHeight > 0) {
resultModalMediaFrame.style.aspectRatio = `${resultModalVideo.videoWidth} / ${resultModalVideo.videoHeight}`;
}
});
resultModalThumbnail.addEventListener("load", () => {
if (!resultModalVideo.src && resultModalThumbnail.naturalWidth > 0 && resultModalThumbnail.naturalHeight > 0) {
resultModalMediaFrame.style.aspectRatio = `${resultModalThumbnail.naturalWidth} / ${resultModalThumbnail.naturalHeight}`;
}
});
if (resultModalReady) {
resultModalVideo.addEventListener("loadedmetadata", () => {
if (resultModalVideo.videoWidth > 0 && resultModalVideo.videoHeight > 0) {
resultModalMediaFrame.style.aspectRatio = `${resultModalVideo.videoWidth} / ${resultModalVideo.videoHeight}`;
}
});
resultModalThumbnail.addEventListener("load", () => {
if (!resultModalVideo.src && resultModalThumbnail.naturalWidth > 0 && resultModalThumbnail.naturalHeight > 0) {
resultModalMediaFrame.style.aspectRatio = `${resultModalThumbnail.naturalWidth} / ${resultModalThumbnail.naturalHeight}`;
}
});
}
for (const button of platformToggles) {
button.addEventListener("click", () => {
const platform = button.dataset.platformToggle;
+1 -1
View File
@@ -206,6 +206,6 @@
</button>
</template>
<script src="/app.js?v=20260316a" defer></script>
<script src="/app.js?v=20260316b" defer></script>
</body>
</html>