summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/components/Giscus.svelte119
1 files changed, 95 insertions, 24 deletions
diff --git a/src/lib/components/Giscus.svelte b/src/lib/components/Giscus.svelte
index 8a924ef..6659b36 100644
--- a/src/lib/components/Giscus.svelte
+++ b/src/lib/components/Giscus.svelte
@@ -1,27 +1,98 @@
<script lang="ts">
- import { onMount } from "svelte";
-
- let container: HTMLDivElement;
-
- onMount(() => {
- const script = document.createElement("script");
- script.src = "https://giscus.app/client.js";
- script.setAttribute("data-repo", "wenekar/giscus");
- script.setAttribute("data-repo-id", "R_kgDOREZgEQ");
- script.setAttribute("data-category", "Announcements");
- script.setAttribute("data-category-id", "DIC_kwDOREZgEc4C1nRY");
- script.setAttribute("data-mapping", "pathname");
- script.setAttribute("data-strict", "0");
- script.setAttribute("data-reactions-enabled", "1");
- script.setAttribute("data-emit-metadata", "0");
- script.setAttribute("data-input-position", "top");
- script.setAttribute("data-theme", "preferred_color_scheme");
- script.setAttribute("data-lang", "en");
- script.setAttribute("data-loading", "lazy");
- script.crossOrigin = "anonymous";
- script.async = true;
- container.appendChild(script);
- });
+ import { onMount } from "svelte";
+
+ let container: HTMLDivElement | undefined;
+ let trigger: HTMLDivElement | undefined;
+ let observer: IntersectionObserver | undefined;
+ let isLoading = false;
+ let hasLoaded = false;
+
+ function loadComments() {
+ if (!container || isLoading || hasLoaded) return;
+
+ isLoading = true;
+
+ const script = document.createElement("script");
+ script.src = "https://giscus.app/client.js";
+ script.setAttribute("data-repo", "wenekar/giscus");
+ script.setAttribute("data-repo-id", "R_kgDOREZgEQ");
+ script.setAttribute("data-category", "Announcements");
+ script.setAttribute("data-category-id", "DIC_kwDOREZgEc4C1nRY");
+ script.setAttribute("data-mapping", "pathname");
+ script.setAttribute("data-strict", "0");
+ script.setAttribute("data-reactions-enabled", "1");
+ script.setAttribute("data-emit-metadata", "0");
+ script.setAttribute("data-input-position", "top");
+ script.setAttribute("data-theme", "preferred_color_scheme");
+ script.setAttribute("data-lang", "en");
+ script.setAttribute("data-loading", "lazy");
+ script.crossOrigin = "anonymous";
+ script.async = true;
+
+ script.addEventListener("load", () => {
+ isLoading = false;
+ });
+
+ script.addEventListener("error", () => {
+ isLoading = false;
+ hasLoaded = false;
+ script.remove();
+ });
+
+ container.appendChild(script);
+ hasLoaded = true;
+ observer?.disconnect();
+ observer = undefined;
+ }
+
+ onMount(() => {
+ if (!trigger || !("IntersectionObserver" in window)) return;
+
+ observer = new IntersectionObserver(
+ (entries) => {
+ if (entries.some((entry) => entry.isIntersecting)) {
+ loadComments();
+ }
+ },
+ { rootMargin: "300px 0px" },
+ );
+
+ observer.observe(trigger);
+
+ return () => {
+ observer?.disconnect();
+ };
+ });
</script>
-<div class="giscus-container" bind:this={container}></div>
+<div class="giscus-container">
+ {#if !hasLoaded}
+ <button class="comments-toggle" on:click={loadComments} disabled={isLoading}>
+ {isLoading ? "Loading comments..." : "Show comments"}
+ </button>
+ {/if}
+
+ <div class="giscus-trigger" bind:this={trigger}></div>
+ <div bind:this={container}></div>
+</div>
+
+<style>
+ .comments-toggle {
+ margin-bottom: 1rem;
+ padding: 0.6rem 0.9rem;
+ border: 1px solid var(--border);
+ background: transparent;
+ color: var(--text);
+ font: inherit;
+ cursor: pointer;
+ }
+
+ .comments-toggle:disabled {
+ opacity: 0.75;
+ cursor: default;
+ }
+
+ .giscus-trigger {
+ height: 1px;
+ }
+</style>