improved component composition and added tests.

This commit is contained in:
Moon.eth
2026-07-29 10:30:28 +09:00
parent 95f9d73681
commit 264ae17a8d
39 changed files with 1811 additions and 147 deletions
+45 -19
View File
@@ -8,11 +8,8 @@
* what its local timeline looks like right now.
*/
import type { Account, Notification, Status } from '$lib/api/types'
import { session } from '$lib/stores/session.svelte'
import { useAppServices } from '$lib/app-services'
import {
fetchFollowing,
fetchNotifications,
fetchTimeline,
instanceDomain,
instanceStats,
instanceThumbnail,
@@ -25,6 +22,8 @@
import RichText from '$components/common/RichText.svelte'
import Composer from '$components/blog/Composer.svelte'
const { endpoints, session } = useAppServices()
let friendStatus = $state<Status[]>([])
let bulletins = $state<Status[]>([])
let following = $state<Account[]>([])
@@ -38,6 +37,7 @@
*/
let friendStatusError = $state<string | null>(null)
let bulletinError = $state<string | null>(null)
let loadGeneration = 0
const me = $derived(session.me)
const domain = $derived(session.host ? instanceDomain(session.instance, session.host) : '')
@@ -65,13 +65,18 @@
const host = session.host
const signedIn = session.signedIn
if (!host) {
loadGeneration += 1
loading = false
return
}
void load(signedIn)
const generation = ++loadGeneration
void load(signedIn, host, generation)
return () => {
if (generation === loadGeneration) loadGeneration += 1
}
})
async function load(signedIn: boolean): Promise<void> {
async function load(signedIn: boolean, host = session.host, generation = ++loadGeneration): Promise<void> {
loading = true
error = null
friendStatusError = null
@@ -81,32 +86,49 @@
// Everything here is independent; a failure in one shouldn't blank the page.
const [statusPage, bulletinPage] = await Promise.all([
signedIn
? fetchTimeline(session.api, 'home', { limit: 10 }).catch((cause) => {
friendStatusError = messageOf(cause)
? endpoints.fetchTimeline(session.api, 'home', { limit: 10 }).catch((cause) => {
if (generation === loadGeneration) friendStatusError = messageOf(cause)
return { items: [], links: {} }
})
: Promise.resolve({ items: [], links: {} }),
fetchTimeline(session.api, 'local', { limit: 10 }).catch((cause) => {
bulletinError = messageOf(cause)
endpoints.fetchTimeline(session.api, 'local', { limit: 10 }).catch((cause) => {
if (generation === loadGeneration) bulletinError = messageOf(cause)
return { items: [], links: {} }
}),
])
if (generation !== loadGeneration || session.host !== host) return
friendStatus = statusPage.items
bulletins = bulletinPage.items
if (signedIn && session.me) {
void fetchFollowing(session.api, session.me.id, { limit: 12 })
.then((page) => (following = page.items))
.catch(() => (following = []))
void fetchNotifications(session.api, { limit: 40 })
.then((page) => (notifications = page.items))
.catch(() => (notifications = []))
const accountId = session.me.id
void endpoints
.fetchFollowing(session.api, accountId, { limit: 12 })
.then((page) => {
if (generation === loadGeneration) following = page.items
})
.catch(() => {
if (generation === loadGeneration) following = []
})
void endpoints
.fetchNotifications(session.api, { limit: 40 })
.then((page) => {
if (generation === loadGeneration) notifications = page.items
})
.catch(() => {
if (generation === loadGeneration) notifications = []
})
} else {
following = []
notifications = []
}
} catch (cause) {
error = cause instanceof Error ? cause.message : 'Could not load your home page.'
if (generation === loadGeneration) {
error = cause instanceof Error ? cause.message : 'Could not load your home page.'
}
} finally {
loading = false
if (generation === loadGeneration) loading = false
}
}
@@ -214,7 +236,11 @@
<div class="layout-column layout-column--main">
{#if session.signedIn}
<Module title="Post a bulletin">
<Composer placeholder="What are you up to?" submitLabel="Post" onposted={() => void load(true)} />
<Composer
placeholder="What are you up to?"
submitLabel="Post"
onposted={() => void load(true)}
/>
</Module>
{/if}