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:
parent
6031d959ea
commit
d3fb510bbb
6 changed files with 87 additions and 69 deletions
40
lib/main.js
40
lib/main.js
|
@ -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);
|
||||
|
|
61
src/components/instance-select.astro
Normal file
61
src/components/instance-select.astro
Normal 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>
|
16
src/pages/api/instances.ts
Normal file
16
src/pages/api/instances.ts
Normal 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",
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
|
@ -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();
|
||||
|
|
|
@ -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 ‘Publish!’"
|
||||
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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue