import { BlogCard, BlogProps } from ':components/BlogBlocks.tsx' import Suspense from ':islands/Suspens.tsx' import { requestApiStream } from ':src/utils.ts' import { Signal, useSignal } from '@preact/signals' import type { JSX, Ref } from 'preact' import { useEffect, useRef } from 'preact/hooks' function fillList( list: Signal, { limit, ac }: { limit?: number; ac?: AbortController }, ) { ;(async () => { const newsList = requestApiStream( 'news/fetchAll', 'GET', ) for await (const news of newsList) { list.value = [ ...list.value, BlogCard({ ...news, lastUpdate: new Date(news.lastUpdate) }), ] if (limit && list.value.length >= limit) break } ac?.abort() })() } export default function BlogCardList( { limit, usePlaceholder, useObserver }: { usePlaceholder?: boolean limit?: number useObserver?: boolean }, ) { const list: Signal = useSignal([]) const ac = new AbortController() const ref = useRef(null) useEffect(() => { if (ref.current && useObserver) { const observer = new IntersectionObserver(([entry]) => { if (entry.isIntersecting) { fillList(list, { limit, ac }) observer.disconnect() } }, { rootMargin: '300px', }) //@ts-expect-error Need to investigate why it's work observer.observe(ref.current.base) } else { fillList(list, { limit, ac }) } }) if (limit && usePlaceholder) { const placeholders = Array .from({ length: limit }) .map((_, index) => ( } fallback={Fallback} signal={ac.signal} > {updateFromList(list, index)} )) return <>{placeholders} } return <>{list} } function Placeholder({ ref }: { ref?: Ref | undefined }) { return (

Chargement ...

) } function Fallback() { return (

Pas de news disponible

) } function updateFromList( list: Signal, index: number, ): Promise { const { promise, resolve } = Promise.withResolvers() list.subscribe((value: JSX.Element[]) => { const selected = value.at(index) if (selected) { resolve(selected) } }) return promise }