import { useEffect, useState } from 'react'; import { useAdapter } from '../provider'; import type { Person } from '../types'; /** * Start a direct message or a group — Slack-style. Pick people from the org directory: one selected * opens a DM (deduped by the adapter), two or more create a group with an optional name. Shown in * the main pane like the channel browser. */ export function NewConversation({ onCreated }: { onCreated?: (threadId: string) => void }) { const adapter = useAdapter(); const [people, setPeople] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [q, setQ] = useState(''); const [selected, setSelected] = useState([]); const [name, setName] = useState(''); const [busy, setBusy] = useState(false); useEffect(() => { if (!adapter.directory) { setLoading(false); return; } let alive = true; adapter .directory() .then((p) => { if (alive) { setPeople(p); setError(null); } }) .catch((e: unknown) => { if (alive) setError(e instanceof Error ? e.message : String(e)); }) .finally(() => { if (alive) setLoading(false); }); return () => { alive = false; }; }, [adapter]); const filtered = people.filter((p) => p.name.toLowerCase().includes(q.trim().toLowerCase())); const isGroup = selected.length > 1; const canStart = selected.length >= 1 && !busy; function toggle(id: string): void { setSelected((s) => (s.includes(id) ? s.filter((x) => x !== id) : [...s, id])); } async function start(): Promise { if (!canStart) return; setBusy(true); setError(null); try { const res = await adapter.openThread({ participantIds: selected, membership: isGroup ? 'group' : 'dm', ...(isGroup && name.trim() ? { subject: name.trim() } : {}), }); onCreated?.(res.threadId); } catch (e) { setError(e instanceof Error ? e.message : String(e)); } finally { setBusy(false); } } return (
New message
setQ(e.target.value)} placeholder="Search people…" aria-label="Search people" /> {isGroup ? ( setName(e.target.value)} placeholder="Group name (optional)" aria-label="Group name" /> ) : null} {error ?
{error}
: null}
{loading && people.length === 0 ?
Loading…
: null} {!loading && filtered.length === 0 ?
No people found.
: null} {filtered.map((p) => ( ))}
); }