feat(app): add Github star count

This commit is contained in:
Mathieu Schimmerling
2023-07-16 10:44:41 +07:00
parent 04453e6542
commit 642a77d64c
5 changed files with 110 additions and 19 deletions

View File

@@ -3,7 +3,9 @@ import { useEffect, useState } from "react";
export default function Name() {
const [name, setName] = useState("John");
useEffect(() => setName("Jane"), []);
useEffect(() => {
setName("Jane");
}, []);
return <h1>Hello {name}</h1>;
}
}

View File

@@ -57,6 +57,7 @@
:root {
/* bg-gray-900 */
--bg-color: rgb(17 24 39);
color-scheme: dark;
}
html {

View File

@@ -1,7 +1,3 @@
:root {
color-scheme: dark;
}
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -0,0 +1,103 @@
<script>
import { onMount } from "svelte";
import createLocaleStorage from "../lib/createLocaleStorage";
import GithubIcon from "./GithubIcon.svelte";
const REPOSITORY_PATH = "matschik/component-party.dev";
const DURATION_2_MIN = 1000 * 60 * 2;
const STAR_COUNT_DURATION_EXPIRATION = DURATION_2_MIN;
const starCountStorage = createLocaleStorage("github-star-count");
let starCount = 0;
let isFetchingStarCount = false;
async function getRepoStarCount() {
const starCountStorageData = starCountStorage.getJSON();
if (starCountStorageData) {
starCount = starCountStorageData.value;
if (
starCountStorageData.fetchedAt >
Date.now() - STAR_COUNT_DURATION_EXPIRATION
) {
return;
}
}
isFetchingStarCount = true;
// Github public API rate limit: 60 requests per hour
const data = await fetch(
`https://api.github.com/repos/${REPOSITORY_PATH}`,
{
headers: {
Accept: "application/vnd.github.v3.star+json",
Authorization: "",
},
}
)
.finally(() => {
isFetchingStarCount = false;
})
.then((r) => r.json());
if (data.stargazers_count) {
starCount = data.stargazers_count;
starCountStorage.setJSON({
value: starCount,
fetchedAt: Date.now(),
});
}
}
onMount(() => {
getRepoStarCount();
});
function onButtonClick() {
starCountStorage.remove();
}
</script>
<a
class="bg-[#21262d] text-[#c9d1d9] border border-[#373b43] py-1 rounded flex items-center text-sm shadow-inner hover:opacity-90"
href={`https://github.com/${REPOSITORY_PATH}`}
target="_blank"
aria-label={`Star ${REPOSITORY_PATH} on GitHub`}
on:click={onButtonClick}
>
<span
class="space-x-2 flex items-center border-r border-[#373b43] font-medium px-2"
>
<GithubIcon class="w-[1.1rem] h-[1.1rem]" />
<span class="mt-px">Star</span>
</span>
{#if isFetchingStarCount || starCount !== 0}
<div class="h-full flex justify-center items-center pl-3 pr-3 font-medium">
{#if isFetchingStarCount && starCount === 0}
<svg
class="animate-spin h-4 w-4 mx-1"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
/>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
{:else}
<span class="mt-px">{starCount}</span>
{/if}
</div>
{/if}
</a>

View File

@@ -1,5 +1,5 @@
<script>
import GithubIcon from "./GithubIcon.svelte";
import GithubStarButton from "./GithubStarButton.svelte";
</script>
<header class="backdrop-blur bg-gray-900/80 border-b border-gray-700">
@@ -9,18 +9,7 @@
<img src="/popper.svg" alt="logo" class="w-5 h-5" />
<span>Component party</span>
</a>
<div>
<a
href="https://github.com/matschik/component-party"
title="Contribute on Github"
target="_blank"
rel="noopener noreferrer"
>
<GithubIcon class="h-6 w-6" />
<span class="sr-only">github</span>
</a>
</div>
<GithubStarButton />
</div>
</div>
</header>