Files
2026-05-23 17:17:56 -07:00

73 lines
2.5 KiB
TypeScript

import { useEffect, useState } from 'react'
import type { BackendArt } from '../../functions/BackendTypes'
import { BackendDebounce, BackendFetch } from '../../functions/Backend'
import { setTitle, stateRecover } from '../../functions/Route'
import { useScrollRoot } from '../../functions/Context'
import LayoutBrowser, { type RecoverForLayoutBrowser } from '../layout/LayoutBrowser'
import HeaderMessage from '../layout/HeaderMessage'
import HeaderLoading from '../layout/HeaderLoading'
import FooterLoading from '../layout/FooterLoading'
import FooterError from '../layout/FooterError'
import FooterText from '../layout/FooterText'
export default function ViewHomepage() {
const scrollRoot = useScrollRoot()
const recovered = stateRecover<RecoverForLayoutBrowser>()
const [error, setError] = useState<string>()
const [isFetching, setFetching] = useState(false)
const [isLoading, setLoading] = useState(false)
const [isBottom, setBottom] = useState(false)
const [items, setItems] = useState(recovered?.items ?? [])
async function loadMore() {
if (isFetching || isBottom) return
setFetching(true)
setLoading(true)
try {
const limit = 30
const resp = await BackendFetch<BackendArt[]>(`/art/latest?limit=${limit}&after=${items.at(-1)?.id}`)
if (!resp.success) {
const d = BackendDebounce(resp, 1)
if (!d.ratelimit) {
setError(resp.error)
setLoading(false)
}
await d.sleep
return
}
if (resp.json.length < limit) {
setBottom(true)
}
setItems((prev) => [...prev, ...resp.json])
setError(undefined)
setLoading(false)
} finally {
setFetching(false)
}
}
useEffect(() => {
if (!scrollRoot) return
if (scrollRoot.scrollHeight <= scrollRoot.clientHeight) {
loadMore()
}
}, [items, scrollRoot])
setTitle('Homepage')
return (
<>
<HeaderMessage label="View: Homepage <Sort: Latest>" />
<LayoutBrowser position={recovered?.position ?? 0} items={items} onEndReached={loadMore} />
{error && <FooterError reason={error} />}
{isBottom && <FooterText label="- You've reached the end, now be free my child -" />}
{isLoading && (items.length ? <FooterLoading reason={undefined} /> : <HeaderLoading reason={undefined} />)}
</>
)
}