Rewrite the instance selector

This commit adds a new '/api/instances' endpoint that returns
the domains of the available Mastodon instances. This also changes the
input field, making it accept a host rather than the full domain.
This commit is contained in:
Nikita Karamov 2023-03-17 22:53:25 +01:00
parent 6031d959ea
commit d3fb510bbb
No known key found for this signature in database
GPG Key ID: 41D6F71EE78E77CD
6 changed files with 87 additions and 69 deletions

View File

@ -26,13 +26,11 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
const INSTANCE_LIST_URL = "https://api.joinmastodon.org/servers";
const LOCAL_STORAGE_KEY = "recentInstances";
const RECENT_INSTANCES_SIZE = 5;
const $form = document.querySelector("#js-s2f-form");
const $instance = document.querySelector("#instance");
const $instanceDatalist = document.querySelector("#instanceDatalist");
/**
* Adds missing "https://" and ending slash to the URL
@ -50,43 +48,6 @@ function normalizeUrl(url) {
return url;
}
function onLoadInstancesError() {
console.error("Couldn't load instance list");
}
function onLoadInstancesSuccess() {
if (this.status >= 400) {
return onLoadInstancesError();
}
const currentInstance = $instance.value;
const instanceDomains = JSON.parse(this.responseText).map(
(index) => index.domain,
);
if (currentInstance && !instanceDomains.includes(currentInstance)) {
instanceDomains.push(currentInstance);
}
instanceDomains.sort();
for (const instanceDomain of instanceDomains) {
const $option = document.createElement("option");
$option.value = normalizeUrl(instanceDomain);
$instanceDatalist.append($option);
}
}
function loadInstances() {
if ($instanceDatalist.children.length === 0) {
const request = new XMLHttpRequest();
request.addEventListener("load", onLoadInstancesSuccess);
request.addEventListener("error", onLoadInstancesError);
request.open("GET", INSTANCE_LIST_URL);
request.send();
}
}
function getRecentInstances() {
const storedValue = window.localStorage.getItem(LOCAL_STORAGE_KEY);
if (!storedValue) return [];
@ -136,5 +97,4 @@ if (prefillInstance != undefined) {
$instance.value = normalizeUrl(prefillInstance);
}
$instance.addEventListener("focus", loadInstances);
$form.addEventListener("submit", onFormSubmit);

View File

@ -0,0 +1,61 @@
---
let instances;
try {
const response = await fetch(new URL("/api/instances", Astro.url));
instances = await response.json();
} catch {
console.error("Couln't fetch instances");
instances = [];
}
---
<datalist id="instanceDatalist">
{instances.map((instance) => <option value="{instance}" />)}
</datalist>
<label>
Mastodon, Pleroma, or GNU Social instance
<div class="instance-input">
<span id="https-label">https://</span>
<input
type="text"
name="instance"
id="instance"
placeholder="mastodon.social"
list="instanceDatalist"
required
aria-describedby="https-label"
/>
</div>
</label>
<label for="remember">
<input
type="checkbox"
id="remember"
name="remember"
/>
Remember my instance on this device
</label>
<style lang="scss">
.instance-input {
position: relative;
display: flex;
flex-wrap: wrap;
align-items: stretch;
width: 100%;
span {
display: flex;
align-items: center;
padding: 0.5rem;
font-size: 1rem;
}
input[type="text"] {
position: relative;
flex: 1 1 auto;
width: 1%;
}
}
</style>

View File

@ -0,0 +1,16 @@
import { APIRoute } from "astro";
export const get: APIRoute = async () => {
const response = await fetch("https://api.joinmastodon.org/servers");
const instances = await response.json();
return new Response(
JSON.stringify(instances.map((instance) => instance.domain)),
{
headers: {
"Cache-Control": "s-maxage=86400, max-age=86400, public",
"Content-Type": "application/json",
},
},
);
};

View File

@ -4,10 +4,10 @@ export const post: APIRoute = async ({ redirect, request }) => {
const formData = await request.formData();
const text = (formData.get("text") as string) || "";
const instanceURL =
(formData.get("instance") as string) || "https://mastodon.social";
const instanceDomain =
(formData.get("instance") as string) || "mastodon.social";
const publishUrl = new URL("/share", instanceURL);
const publishUrl = new URL("/share", `https://${instanceDomain}/`);
publishUrl.search = new URLSearchParams({
text,
}).toString();

View File

@ -1,4 +1,5 @@
---
import InstanceSelect from "../components/instance-select.astro";
import "../styles/main.scss";
---
@ -22,9 +23,7 @@ import "../styles/main.scss";
along with this program. If not, see <https://www.gnu.org/licenses/>.
SPDX-License-Identifier: AGPL-3.0-or-later
-->
<!DOCTYPE html>
--><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
@ -37,7 +36,7 @@ import "../styles/main.scss";
</title>
<meta
name="description"
content="Share₂Fedi is a share page for Mastodon, Pleroma, and GNU Social. Type in your post text and the instance URL and click &lsquo;Publish!&rsquo;"
content="Share₂Fedi is a share page for Mastodon, Pleroma, and GNU Social. Type in your post text and the instance URL and click Publish!"
/>
<link
rel="canonical"
@ -107,27 +106,7 @@ import "../styles/main.scss";
></textarea>
</label>
<datalist id="instanceDatalist"></datalist>
<label>
Choose your Mastodon, Pleroma, or GNU Social instance
<input
type="url"
name="instance"
id="instance"
placeholder="https://"
list="instanceDatalist"
required
/>
</label>
<label for="remember">
<input
type="checkbox"
id="remember"
name="remember"
/>
Remember my instance on this device
</label>
<InstanceSelect />
<input
type="submit"

View File

@ -31,6 +31,7 @@
--s2f-accent-color-light: #5d8379;
--s2f-accent-color-contrast: #005e4e;
--s2f-border-color: #ccc;
--s2f-input-group-bg-color: #eee;
--s2f-input-bg-color: #fff;
--s2f-input-text-color: #000;
--s2f-button-text-color: #fff;
@ -103,7 +104,7 @@ textarea {
resize: vertical;
}
input[type="url"],
input[type="text"],
textarea {
width: 100%;
color: var(--s2f-input-text-color);
@ -137,6 +138,7 @@ input[type="submit"] {
--s2f-accent-color-light: #619587;
--s2f-accent-color-contrast: #a8f7e2;
--s2f-border-color: #333;
--s2f-input-group-bg-color: #111;
}
}