Added loading hint for comments

This commit is contained in:
ClovertaTheTrilobita 2026-09-19 14:06:35 +08:00
parent ef530b99d9
commit 88f4ac2c82
2 changed files with 113 additions and 10 deletions

View file

@ -1,10 +1,13 @@
--- ---
import Remark42Status from "./Remark42Status.astro";
const { slug } = Astro.props; const { slug } = Astro.props;
const pagePath = `/posts/${slug}/`; const pagePath = `/posts/${slug}/`;
const host = import.meta.env.PUBLIC_REMARK42_HOST; const host = import.meta.env.PUBLIC_REMARK42_HOST;
const siteId = import.meta.env.PUBLIC_REMARK42_SITE_ID; const siteId = import.meta.env.PUBLIC_REMARK42_SITE_ID;
--- ---
<Remark42Status />
<div id="remark42"></div> <div id="remark42"></div>
<script define:vars={{ pagePath, host, siteId }} is:inline data-astro-rerun> <script define:vars={{ pagePath, host, siteId }} is:inline data-astro-rerun>
function getTheme() { function getTheme() {
@ -55,27 +58,96 @@ const siteId = import.meta.env.PUBLIC_REMARK42_SITE_ID;
} }
script.onload = () => resolve(true); script.onload = () => resolve(true);
script.onerror = reject; script.onerror = (error) => {
script.remove();
reject(error);
};
document.head.appendChild(script); document.head.appendChild(script);
}); });
} }
async function mountRemark42() { async function mountRemark42() {
const node = document.getElementById("remark42"); const node = document.getElementById("remark42");
if (!node) return; const status = document.getElementById("remark42-status");
const loadingStatus = status?.querySelector("[data-remark42-loading]");
const failedStatus = status?.querySelector("[data-remark42-failed]");
if (!node || !loadingStatus || !failedStatus) return;
setRemarkConfig(); window.__remark42LoadCleanup?.();
await ensureScript();
if (!window.REMARK42) return; let active = true;
let iframe = null;
let timer;
if (typeof window.REMARK42.destroy === "function") { const onIframeLoad = () => {
window.REMARK42.destroy(); if (!active || !iframe || !node.contains(iframe)) return;
loadingStatus.hidden = true;
failedStatus.hidden = true;
clearTimeout(timer);
observer.disconnect();
};
const watchIframe = () => {
const nextIframe = node.querySelector("iframe");
if (nextIframe === iframe) return;
iframe?.removeEventListener("load", onIframeLoad);
iframe = nextIframe;
iframe?.addEventListener("load", onIframeLoad, { once: true });
};
const observer = new MutationObserver(watchIframe);
observer.observe(node, { childList: true, subtree: true });
watchIframe();
const showFailure = () => {
if (!active || loadingStatus.hidden) return;
loadingStatus.hidden = true;
failedStatus.hidden = false;
};
window.__remark42LoadCleanup = () => {
active = false;
clearTimeout(timer);
observer.disconnect();
iframe?.removeEventListener("load", onIframeLoad);
};
loadingStatus.hidden = false;
failedStatus.hidden = true;
timer = setTimeout(showFailure, 15000);
if (!host || !siteId) {
showFailure();
return;
} }
if (typeof window.REMARK42.createInstance === "function") { try {
node.innerHTML = ""; const alreadyLoaded = Boolean(window.REMARK42);
window.REMARK42.createInstance(window.remark_config); setRemarkConfig();
await ensureScript();
if (!active) return;
if (!window.REMARK42) {
showFailure();
return;
}
if (alreadyLoaded && typeof window.REMARK42.destroy === "function") {
window.REMARK42.destroy();
}
// The script creates the first iframe itself. Only remount when
// reusing it on a new page/theme, or if it did not create one.
if (
(alreadyLoaded || !node.querySelector("iframe")) &&
typeof window.REMARK42.createInstance === "function"
) {
node.innerHTML = "";
window.REMARK42.createInstance(window.remark_config);
}
} catch {
showFailure();
} }
} }

View file

@ -0,0 +1,31 @@
---
import { getLangFromUrl } from "@/i18n";
const lang = getLangFromUrl(Astro.url);
const loadingText = lang === "zh" ? "评论区加载中……" : "Loading comments…";
const failedText = lang === "zh" ? "评论区加载失败" : "Failed to load comments";
---
<div id="remark42-status" role="status" aria-atomic="true">
<p class="remark42-loading" data-remark42-loading>{loadingText}</p>
<p class="remark42-failed" data-remark42-failed hidden>{failedText}</p>
</div>
<style>
.remark42-loading,
.remark42-failed {
margin: 0.75rem 0;
color: #6b7680;
font-size: 0.85rem;
line-height: 1.6;
}
[hidden] {
display: none;
}
:global(html.dark) .remark42-loading,
:global(html.dark) .remark42-failed {
color: #aab7c4;
}
</style>