import { useEffect, useState } from 'react'; import { useThread, useMessages } from '@insignia/iios-message-web'; import { InboxProvider, useInbox } from '@insignia/iios-inbox-web'; import { SupportProvider, useEscalate } from '@insignia/iios-support-web'; const SERVICE = 'http://localhost:3200'; const APP_ID = 'portal-demo'; async function devToken(userId: string, name: string): Promise { const r = await fetch(`${SERVICE}/v1/dev/token`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ appId: APP_ID, userId, name }), }); if (!r.ok) throw new Error(`devToken ${r.status} (is the service running with IIOS_DEV_TOKENS=1?)`); return ((await r.json()) as { token: string }).token; } function ChatInner({ label, threadId, onCreated, }: { label: string; threadId: string | null; onCreated?: (id: string) => void; }) { const { open } = useThread(); const [tid, setTid] = useState(threadId); const [text, setText] = useState(''); useEffect(() => { if (threadId) { setTid(threadId); return; } if (onCreated) { void open().then((id) => { setTid(id); onCreated(id); }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [threadId]); const { messages, send, typing, typingUsers, markRead, reads } = useMessages(tid); const escalate = useEscalate(); return (

{label}

thread: {tid ?? '…'}
{messages.map((m) => (
{m.senderActorId.slice(0, 6)}: {m.content} {reads.includes(m.id) ? '✓✓' : ''}
))} {typingUsers.length > 0 && {typingUsers.join(', ')} typing…}
{ setText(e.target.value); typing(); }} onKeyDown={(e) => { if (e.key === 'Enter' && text.trim()) { void send(text.trim()); setText(''); } }} />
); } function InboxSidebar() { const { items, done, snooze } = useInbox({ state: 'OPEN' }); return (
Inbox ({items.length}) {items.length === 0 &&
nothing to reply to
} {items.map((i) => (
{i.title}
{i.kind}
))}
); } function Pane(props: { token: string | null; label: string; threadId: string | null; onCreated?: (id: string) => void }) { if (!props.token) return
loading {props.label}…
; return (
); } export function App() { const [alice, setAlice] = useState(null); const [bob, setBob] = useState(null); const [threadId, setThreadId] = useState(null); useEffect(() => { void devToken('alice', 'Alice').then(setAlice); void devToken('bob', 'Bob').then(setBob); }, []); return (

IIOS P2 — realtime demo (Alice ↔ Bob)

Type in either pane — it appears live in the other. ✓✓ = read receipt.

); }