Prettier Linting
This commit is contained in:
parent
7f3eb2888a
commit
4254015cd8
11 changed files with 243 additions and 201 deletions
|
@ -1,173 +1,193 @@
|
|||
<svelte:options runes={true} />
|
||||
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
import {Skeleton} from "$lib/components/ui/skeleton/index.js";
|
||||
import {DoubleArrowUp} from "radix-icons-svelte";
|
||||
import { onMount } from 'svelte';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import { Skeleton } from '$lib/components/ui/skeleton/index.js';
|
||||
import { DoubleArrowUp } from 'radix-icons-svelte';
|
||||
|
||||
let { account, maxToots, accountId, excludeReplies }: { account: string, maxToots?: number, accountId?: string, excludeReplies: boolean } = $props();
|
||||
let {
|
||||
account,
|
||||
maxToots,
|
||||
accountId,
|
||||
excludeReplies
|
||||
}: { account: string; maxToots?: number; accountId?: string; excludeReplies: boolean } = $props();
|
||||
|
||||
let toots: Toot[] = $state([]);
|
||||
let loading = $state(false);
|
||||
let toots: Toot[] = $state([]);
|
||||
let loading = $state(false);
|
||||
|
||||
onMount(() => {
|
||||
loading = true;
|
||||
loadToots(account, accountId, maxToots, excludeReplies);
|
||||
})
|
||||
onMount(() => {
|
||||
loading = true;
|
||||
loadToots(account, accountId, maxToots, excludeReplies);
|
||||
});
|
||||
|
||||
interface Toot {
|
||||
created_at: string;
|
||||
in_reply_to_id: string | null;
|
||||
content: string;
|
||||
url: string;
|
||||
account: {
|
||||
username: string;
|
||||
display_name: string;
|
||||
avatar: string;
|
||||
url: string;
|
||||
};
|
||||
reblog?: Toot;
|
||||
media_attachments: {
|
||||
type: "unknown" | "image" | "gifv" | "video" | "audio";
|
||||
url: string;
|
||||
preview_url: string;
|
||||
description: string;
|
||||
blurhash: string;
|
||||
}[];
|
||||
}
|
||||
interface Toot {
|
||||
created_at: string;
|
||||
in_reply_to_id: string | null;
|
||||
content: string;
|
||||
url: string;
|
||||
account: {
|
||||
username: string;
|
||||
display_name: string;
|
||||
avatar: string;
|
||||
url: string;
|
||||
};
|
||||
reblog?: Toot;
|
||||
media_attachments: {
|
||||
type: 'unknown' | 'image' | 'gifv' | 'video' | 'audio';
|
||||
url: string;
|
||||
preview_url: string;
|
||||
description: string;
|
||||
blurhash: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
export async function getToots(
|
||||
userURL: string,
|
||||
limit: number,
|
||||
excludeReplies: boolean,
|
||||
accountId?: string,
|
||||
): Promise<Toot[]> {
|
||||
const url = new URL(userURL);
|
||||
export async function getToots(
|
||||
userURL: string,
|
||||
limit: number,
|
||||
excludeReplies: boolean,
|
||||
accountId?: string
|
||||
): Promise<Toot[]> {
|
||||
const url = new URL(userURL);
|
||||
|
||||
// Either use the account id specified or look it up based on the username
|
||||
// in the link.
|
||||
const userId: string =
|
||||
accountId ??
|
||||
(await (async () => {
|
||||
// Extract username from URL.
|
||||
const parts = /@(\w+)$/.exec(url.pathname);
|
||||
if (!parts) {
|
||||
throw "not a Mastodon user URL";
|
||||
}
|
||||
const username = parts[1];
|
||||
// Either use the account id specified or look it up based on the username
|
||||
// in the link.
|
||||
const userId: string =
|
||||
accountId ??
|
||||
(await (async () => {
|
||||
// Extract username from URL.
|
||||
const parts = /@(\w+)$/.exec(url.pathname);
|
||||
if (!parts) {
|
||||
throw 'not a Mastodon user URL';
|
||||
}
|
||||
const username = parts[1];
|
||||
|
||||
// Look up user ID from username.
|
||||
const lookupURL = Object.assign(new URL(url), {
|
||||
pathname: "/api/v1/accounts/lookup",
|
||||
search: `?acct=${username}`,
|
||||
});
|
||||
return (await (await fetch(lookupURL)).json())["id"];
|
||||
})());
|
||||
// Look up user ID from username.
|
||||
const lookupURL = Object.assign(new URL(url), {
|
||||
pathname: '/api/v1/accounts/lookup',
|
||||
search: `?acct=${username}`
|
||||
});
|
||||
return (await (await fetch(lookupURL)).json())['id'];
|
||||
})());
|
||||
|
||||
// Fetch toots.
|
||||
const tootURL = Object.assign(new URL(url), {
|
||||
pathname: `/api/v1/accounts/${userId}/statuses`,
|
||||
search: `?limit=${limit ?? 5}&exclude_replies=${!!excludeReplies}`,
|
||||
});
|
||||
// Fetch toots.
|
||||
const tootURL = Object.assign(new URL(url), {
|
||||
pathname: `/api/v1/accounts/${userId}/statuses`,
|
||||
search: `?limit=${limit ?? 5}&exclude_replies=${!!excludeReplies}`
|
||||
});
|
||||
|
||||
return await (await fetch(tootURL)).json();
|
||||
}
|
||||
return await (await fetch(tootURL)).json();
|
||||
}
|
||||
|
||||
|
||||
function loadToots() {
|
||||
getToots(
|
||||
account,
|
||||
maxToots ?? 5,
|
||||
excludeReplies === true,
|
||||
accountId,
|
||||
).then((data) => {
|
||||
toots = data;
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
function loadToots() {
|
||||
getToots(account, maxToots ?? 5, excludeReplies === true, accountId).then((data) => {
|
||||
toots = data;
|
||||
loading = false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet avatar(toot)}
|
||||
<a class="flex flex-row gap-2" href={toot.account.url}>
|
||||
<img class="rounded-md" width="48px" height="48px" src={toot.account.avatar} alt="{toot.account.username} avatar"/>
|
||||
<div class="flex flex-col items-start">
|
||||
<span class="hover:underline font-bold h-6">{toot.account.display_name}</span>
|
||||
<span class="h-4 text-sm text-muted">@{toot.account.username}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a class="flex flex-row gap-2" href={toot.account.url}>
|
||||
<img
|
||||
class="rounded-md"
|
||||
width="48px"
|
||||
height="48px"
|
||||
src={toot.account.avatar}
|
||||
alt="{toot.account.username} avatar"
|
||||
/>
|
||||
<div class="flex flex-col items-start">
|
||||
<span class="h-6 font-bold hover:underline">{toot.account.display_name}</span>
|
||||
<span class="h-4 text-sm text-muted">@{toot.account.username}</span>
|
||||
</div>
|
||||
</a>
|
||||
{/snippet}
|
||||
|
||||
{#snippet body(toot)}
|
||||
<div>
|
||||
<div class="[&>p>span>a]:hover:underline">
|
||||
{@html sanitizeHtml(toot.content)}
|
||||
</div>
|
||||
{#each toot.media_attachments.filter((att) => att.type === "image") as image}
|
||||
<a class="block rounded-md aspect-16/9 w-full overflow-hidden" href={image.url} target="_blank" rel="noopener noreferrer">
|
||||
<img class="h-full w-full object-cover" src={image.preview_url} alt={image.description}/>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
<div class="[&>p>span>a]:hover:underline">
|
||||
{@html sanitizeHtml(toot.content)}
|
||||
</div>
|
||||
{#each toot.media_attachments.filter((att) => att.type === 'image') as image}
|
||||
<a
|
||||
class="block aspect-16/9 w-full overflow-hidden rounded-md"
|
||||
href={image.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<img class="h-full w-full object-cover" src={image.preview_url} alt={image.description} />
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
|
||||
|
||||
<ol class="w-full">
|
||||
{#if loading}
|
||||
{#each Array(maxToots ?? 5) as placeholder}
|
||||
<li class="flex flex-col gap-3 px-4 py-3">
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="flex flex-row gap-2">
|
||||
<Skeleton class="h-12 w-12 rounded-md"/>
|
||||
<div class="flex flex-col items-start gap-1">
|
||||
<Skeleton class="h-6 w-24"></Skeleton>
|
||||
<Skeleton class="h-4 w-20"></Skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton class="h-10 w-16" />
|
||||
</div>
|
||||
<Skeleton class="h-36 w-full"></Skeleton>
|
||||
</li>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each toots as toot}
|
||||
<li class="flex flex-col gap-3 px-4 py-3">
|
||||
{#if toot.reblog}
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="flex flex-col gap-1">
|
||||
<a class="items-center flex flex-row gap-1" href={toot.account.url}>
|
||||
<DoubleArrowUp />
|
||||
<img class="rounded-md" width="23px" height="23px" src={toot.account.avatar} alt="{toot.account.username} avatar"/>
|
||||
<span class="hover:underline font-bold h-6">{toot.account.display_name}</span>
|
||||
</a>
|
||||
{@render avatar(toot.reblog)}
|
||||
</div>
|
||||
<a class="flex flex-col items-center hover:underline text-sm text-muted" href={toot.url}>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleDateString()}
|
||||
</time>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleTimeString()}
|
||||
</time>
|
||||
</a>
|
||||
</div>
|
||||
{@render body(toot.reblog)}
|
||||
{:else}
|
||||
<div class="flex flex-row justify-between">
|
||||
{@render avatar(toot)}
|
||||
<a class="flex flex-col items-center hover:underline text-sm text-muted" href={toot.url}>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleDateString()}
|
||||
</time>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleTimeString()}
|
||||
</time>
|
||||
</a>
|
||||
</div>
|
||||
{@render body(toot)}
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
{/if}
|
||||
{#if loading}
|
||||
{#each Array(maxToots ?? 5) as placeholder}
|
||||
<li class="flex flex-col gap-3 px-4 py-3">
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="flex flex-row gap-2">
|
||||
<Skeleton class="h-12 w-12 rounded-md" />
|
||||
<div class="flex flex-col items-start gap-1">
|
||||
<Skeleton class="h-6 w-24"></Skeleton>
|
||||
<Skeleton class="h-4 w-20"></Skeleton>
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton class="h-10 w-16" />
|
||||
</div>
|
||||
<Skeleton class="h-36 w-full"></Skeleton>
|
||||
</li>
|
||||
{/each}
|
||||
{:else}
|
||||
{#each toots as toot}
|
||||
<li class="flex flex-col gap-3 px-4 py-3">
|
||||
{#if toot.reblog}
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="flex flex-col gap-1">
|
||||
<a class="flex flex-row items-center gap-1" href={toot.account.url}>
|
||||
<DoubleArrowUp />
|
||||
<img
|
||||
class="rounded-md"
|
||||
width="23px"
|
||||
height="23px"
|
||||
src={toot.account.avatar}
|
||||
alt="{toot.account.username} avatar"
|
||||
/>
|
||||
<span class="h-6 font-bold hover:underline">{toot.account.display_name}</span>
|
||||
</a>
|
||||
{@render avatar(toot.reblog)}
|
||||
</div>
|
||||
<a
|
||||
class="flex flex-col items-center text-sm text-muted hover:underline"
|
||||
href={toot.url}
|
||||
>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleDateString()}
|
||||
</time>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleTimeString()}
|
||||
</time>
|
||||
</a>
|
||||
</div>
|
||||
{@render body(toot.reblog)}
|
||||
{:else}
|
||||
<div class="flex flex-row justify-between">
|
||||
{@render avatar(toot)}
|
||||
<a
|
||||
class="flex flex-col items-center text-sm text-muted hover:underline"
|
||||
href={toot.url}
|
||||
>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleDateString()}
|
||||
</time>
|
||||
<time datetime={toot.created_at}>
|
||||
{new Date(toot.created_at).toLocaleTimeString()}
|
||||
</time>
|
||||
</a>
|
||||
</div>
|
||||
{@render body(toot)}
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
{/if}
|
||||
</ol>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Root from "./separator.svelte";
|
||||
import Root from './separator.svelte';
|
||||
|
||||
export {
|
||||
Root,
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { Separator as SeparatorPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils";
|
||||
import { Separator as SeparatorPrimitive } from 'bits-ui';
|
||||
import { cn } from '$lib/utils';
|
||||
|
||||
type $$Props = SeparatorPrimitive.Props;
|
||||
|
||||
let className: $$Props["class"] = undefined;
|
||||
export let orientation: $$Props["orientation"] = "horizontal";
|
||||
export let decorative: $$Props["decorative"] = undefined;
|
||||
let className: $$Props['class'] = undefined;
|
||||
export let orientation: $$Props['orientation'] = 'horizontal';
|
||||
export let decorative: $$Props['decorative'] = undefined;
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<SeparatorPrimitive.Root
|
||||
class={cn(
|
||||
"shrink-0 bg-border",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
||||
'shrink-0 bg-border',
|
||||
orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
|
||||
className
|
||||
)}
|
||||
{orientation}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { writable } from 'svelte/store';
|
||||
import {io} from "socket.io-client";
|
||||
import { io } from 'socket.io-client';
|
||||
|
||||
export let socketStore = writable(io('https://status.neshweb.net/'));
|
|
@ -1,4 +1,4 @@
|
|||
import {type Writable, writable} from 'svelte/store';
|
||||
import type {Heartbeat} from "$lib/types/uptime-kuma-types";
|
||||
import { type Writable, writable } from 'svelte/store';
|
||||
import type { Heartbeat } from '$lib/types/uptime-kuma-types';
|
||||
|
||||
export let uptimeStore: Writable<Map<number, Heartbeat>> = writable(new Map());
|
|
@ -3,18 +3,20 @@
|
|||
<script>
|
||||
import '../app.pcss';
|
||||
import Header from './Header.svelte';
|
||||
import { socketStore } from "$lib/stores/socketStore";
|
||||
import {beforeNavigate} from "$app/navigation";
|
||||
import { socketStore } from '$lib/stores/socketStore';
|
||||
import { beforeNavigate } from '$app/navigation';
|
||||
|
||||
$effect(() => {
|
||||
beforeNavigate((navigation) => {
|
||||
const servers = navigation.to.url.pathname === "/servers" || navigation.from.url.pathname === "/servers"
|
||||
const services = navigation.to.url.pathname === "/services" || navigation.from.url.pathname === "/services"
|
||||
if ( ! (servers && services) ) {
|
||||
$socketStore.close()
|
||||
const servers =
|
||||
navigation.to.url.pathname === '/servers' || navigation.from.url.pathname === '/servers';
|
||||
const services =
|
||||
navigation.to.url.pathname === '/services' || navigation.from.url.pathname === '/services';
|
||||
if (!(servers && services)) {
|
||||
$socketStore.close();
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<Header />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import {Separator} from "$lib/components/ui/separator";
|
||||
import {OpenInNewWindow} from "radix-icons-svelte";
|
||||
import Emfed from "$lib/components/Emfed.svelte";
|
||||
import { Separator } from '$lib/components/ui/separator';
|
||||
import { OpenInNewWindow } from 'radix-icons-svelte';
|
||||
import Emfed from '$lib/components/Emfed.svelte';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@ -9,32 +9,55 @@
|
|||
<meta name="description" content="Landing Page for neshweb.net" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="grid max-h-full grid-cols-3 gap-4 justify-center overflow-auto p-8">
|
||||
<div class="flex flex-col items-center col-span-2">
|
||||
<div class="flex flex-col border rounded-md p-4 bg-black/55 backdrop-blur-sm gap-y-2">
|
||||
<h1 class="text-2xl text-center" >Home Page</h1>
|
||||
<p>I'm not sure what to put here quite yet, maybe I'll think of something eventually. In the meantime I've linked some of my accounts in the sidebar to the right</p>
|
||||
<div class="grid max-h-full grid-cols-3 justify-center gap-4 overflow-auto p-8">
|
||||
<div class="col-span-2 flex flex-col items-center">
|
||||
<div class="flex flex-col gap-y-2 rounded-md border bg-black/55 p-4 backdrop-blur-sm">
|
||||
<h1 class="text-center text-2xl">Home Page</h1>
|
||||
<p>
|
||||
I'm not sure what to put here quite yet, maybe I'll think of something eventually. In the
|
||||
meantime I've linked some of my accounts in the sidebar to the right
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col gap-y-1 items-center border rounded-md bg-black/55 backdrop-blur-sm py-1">
|
||||
<div
|
||||
class="flex flex-col items-center gap-y-1 rounded-md border bg-black/55 py-1 backdrop-blur-sm"
|
||||
>
|
||||
<p class="font-bold">Fediverse Accounts</p>
|
||||
<Separator class="max-w-80" />
|
||||
<a rel="me" href="https://mastodon.neshweb.net/@neshura" target="_blank" class="flex flex-row gap-1 items-center hover:text-secondary">
|
||||
<a
|
||||
rel="me"
|
||||
href="https://mastodon.neshweb.net/@neshura"
|
||||
target="_blank"
|
||||
class="flex flex-row items-center gap-1 hover:text-secondary"
|
||||
>
|
||||
Mastodon
|
||||
<OpenInNewWindow />
|
||||
</a>
|
||||
<a rel="noopener noreferrer" href="https://bookwormstory.social/u/Neshura" target="_blank" class="flex flex-row gap-1 items-center hover:text-secondary">
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="https://bookwormstory.social/u/Neshura"
|
||||
target="_blank"
|
||||
class="flex flex-row items-center gap-1 hover:text-secondary"
|
||||
>
|
||||
Lemmy
|
||||
<OpenInNewWindow />
|
||||
</a>
|
||||
<a rel="noopener noreferrer" href="https://neshweb.tv/c/neshura_ch/videos" target="_blank" class="flex flex-row gap-1 items-center hover:text-secondary">
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="https://neshweb.tv/c/neshura_ch/videos"
|
||||
target="_blank"
|
||||
class="flex flex-row items-center gap-1 hover:text-secondary"
|
||||
>
|
||||
PeerTube
|
||||
<OpenInNewWindow />
|
||||
</a>
|
||||
<Separator class="max-w-80" />
|
||||
<p class="font-bold">Mastodon Feed</p>
|
||||
<Separator class="max-w-80" />
|
||||
<Emfed account="https://mastodon.neshweb.net/@neshura" maxToots={4} accountId="109199738141333007"/>
|
||||
<Emfed
|
||||
account="https://mastodon.neshweb.net/@neshura"
|
||||
maxToots={4}
|
||||
accountId="109199738141333007"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -16,4 +16,3 @@
|
|||
{version}
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<svelte:head>
|
||||
<title>CSS Test</title>
|
||||
<meta name="description" content="CSS playground" />
|
||||
<title>CSS Test</title>
|
||||
<meta name="description" content="CSS playground" />
|
||||
</svelte:head>
|
||||
|
||||
<p class="text-background">Background</p>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import type { Heartbeat } from '$lib/types/uptime-kuma-types';
|
||||
import ServerCard from '$lib/components/ServerCard.svelte';
|
||||
import { socketStore } from '$lib/stores/socketStore';
|
||||
import {uptimeStore} from "$lib/stores/uptimeStore";
|
||||
import { uptimeStore } from '$lib/stores/uptimeStore';
|
||||
|
||||
let { data }: { data: { promise: Promise<string> } } = $props();
|
||||
|
||||
|
@ -30,12 +30,11 @@
|
|||
if (token) {
|
||||
if (!socket.connected) {
|
||||
socket.connect();
|
||||
}
|
||||
else {
|
||||
console.log("already connected");
|
||||
} else {
|
||||
console.log('already connected');
|
||||
}
|
||||
socket.on('connect', () => {
|
||||
console.log("logging in")
|
||||
console.log('logging in');
|
||||
socket.emit('loginByToken', token, () => {});
|
||||
});
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
import type { Service } from '$lib/types/data-types';
|
||||
import { io } from 'socket.io-client';
|
||||
import type { Heartbeat } from '$lib/types/uptime-kuma-types';
|
||||
import {socketStore} from "$lib/stores/socketStore";
|
||||
import {onDestroy} from "svelte";
|
||||
import {uptimeStore} from "$lib/stores/uptimeStore";
|
||||
import { socketStore } from '$lib/stores/socketStore';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { uptimeStore } from '$lib/stores/uptimeStore';
|
||||
|
||||
let { data }: { data: { promise: Promise<string> } } = $props();
|
||||
|
||||
|
@ -29,12 +29,11 @@
|
|||
if (token) {
|
||||
if (!socket.connected) {
|
||||
socket.connect();
|
||||
}
|
||||
else {
|
||||
console.log("connected")
|
||||
} else {
|
||||
console.log('connected');
|
||||
}
|
||||
socket.on('connect', () => {
|
||||
console.log("login")
|
||||
console.log('login');
|
||||
socket.emit('loginByToken', token, () => {});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue