summaryrefslogtreecommitdiff
path: root/src/lib/components/Giscus.svelte
blob: 6659b366da7316f83e85c69475bf2c24f44beaae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<script lang="ts">
	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">
	{#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>