'use client'
import dynamic from 'next/dynamic'
import { useEffect, useRef, useState, type ComponentProps } from 'react'
import { chatText } from '@/lib/i18n/chat'
import { SkeletonLine } from '@/components/Skeleton'
import type { Chat } from './Chat'
const ChatInner = dynamic(() => import('./Chat').then((modul) => modul.Chat), {
loading: () => ,
// Der Chat wird ohnehin erst nach dem Scrollen gebraucht und lebt von einer
// offenen Verbindung. Ihn auf dem Server mitzurendern brächte nichts und
// zöge sein Bündel in die erste Ladung der Fallakte.
ssr: false,
})
/**
* Lädt den Chat erst, wenn er in Sichtweite kommt.
*
* Zwei Gründe, beide handfest: die Fallakte ist das, weswegen die Seite
* geöffnet wird — ihr Bündelbudget soll nicht für einen Chat draufgehen, den
* viele nie aufklappen. Und der Chat hält eine offene Verbindung zum
* Ereignisstrom; wer nur die Akte liest, soll sie nicht aufbauen.
*
* Der Platzhalter hat die Höhe des Chats, damit beim Nachladen nichts springt.
* Siehe docs/09-performance-und-ux.md.
*/
export function ChatLazy(props: ComponentProps) {
const [sichtbar, setSichtbar] = useState(false)
const anker = useRef(null)
useEffect(() => {
const element = anker.current
if (!element) return
// Ohne IntersectionObserver (sehr alte Browser) sofort laden: lieber
// grösser als kaputt.
if (typeof IntersectionObserver === 'undefined') {
setSichtbar(true)
return
}
const beobachter = new IntersectionObserver(
(eintraege) => {
if (eintraege.some((eintrag) => eintrag.isIntersecting)) {
setSichtbar(true)
beobachter.disconnect()
}
},
// Etwas vorher anfangen, damit er beim Ankommen schon steht.
{ rootMargin: '300px' },
)
beobachter.observe(element)
return () => beobachter.disconnect()
}, [])
return
}
function Platzhalter() {
return (
)
}