Load and cache popular instances

This commit is contained in:
Nikita Karamov 2023-08-26 16:24:14 +02:00
parent 870406209e
commit e84fed7952
No known key found for this signature in database
GPG key ID: 41D6F71EE78E77CD
2 changed files with 54 additions and 3 deletions

View file

@ -7,7 +7,7 @@
const { prefilledInstance } = Astro.props;
---
<datalist id="instance-list"></datalist>
<datalist id="instances"></datalist>
<label id="s2f-instanceContainer">
Fediverse instance
<div class="instance-input">
@ -17,7 +17,7 @@ const { prefilledInstance } = Astro.props;
name="instance"
id="instance"
placeholder="mastodon.social"
list="instance-list"
list="instances"
required
aria-describedby="https-label"
value={prefilledInstance}
@ -67,6 +67,7 @@ const { prefilledInstance } = Astro.props;
<script>
import { getUrlDomain, normalizeURL } from "@scripts/util";
import { $savedInstances, save } from "@stores/saved-instances";
import { $popularInstances } from "@stores/popular-instances";
const $form = document.querySelector("#js-s2f-form") as HTMLFormElement;
const $instanceContainer = document.querySelector(
@ -112,5 +113,17 @@ const { prefilledInstance } = Astro.props;
return true;
});
const instancesElement = document.querySelector("#instances");
if (instancesElement != undefined) {
$popularInstances.subscribe((instances) => {
instancesElement.replaceChildren(
...instances.map((domain) => {
const option = document.createElement("option");
option.value = domain;
return option;
}),
);
});
}
</script>
<script src="../scripts/fetch-instances.ts"></script>

View file

@ -0,0 +1,38 @@
import { persistentAtom } from "@nanostores/persistent";
import { onMount, task } from "nanostores";
const UPDATE_INTERVAL_MS = 1000 * 60 * 60 * 24; // one day
export const $popularInstances = persistentAtom<string[]>(
"popularInstances",
[],
{
encode: JSON.stringify,
decode: JSON.parse,
},
);
export const $lastFetched = persistentAtom<Date>(
"popularInstancesLastFetched",
new Date(0),
{
encode: (date) => date.toISOString(),
decode: (encoded) => new Date(encoded),
},
);
onMount($popularInstances, () => {
task(async () => {
if (Date.now() - $lastFetched.get().getTime() < UPDATE_INTERVAL_MS) {
return;
}
try {
const response = await fetch("/api/instances");
$popularInstances.set(await response.json());
$lastFetched.set(new Date());
} catch (error) {
console.error("Could not fetch popular instances:", error);
}
});
});