import React, { useState, useRef, useEffect } from 'react'; import { Modal } from '../ui/Modal'; import { Avatar } from '../ui/Avatar'; import { useUIStore } from '../../stores/uiStore'; import { useSpaceStore, getApiForOrigin } from '../../stores/spaceStore'; import { api } from '../../api/client'; import type { User } from '@backspace/shared'; export function AddDmMemberModal() { const [query, setQuery] = useState(''); const [results, setResults] = useState([]); const [isSearching, setIsSearching] = useState(false); const [error, setError] = useState(''); const [isAdding, setIsAdding] = useState(false); const activeModal = useUIStore((s) => s.activeModal); const modalData = useUIStore((s) => s.modalData); const closeModal = useUIStore((s) => s.closeModal); const dmChannels = useSpaceStore((s) => s.dmChannels); const channelOriginMap = useSpaceStore((s) => s.channelOriginMap); const inputRef = useRef(null); const searchTimer = useRef>(); const isOpen = activeModal === 'addDmMember'; const dmChannelId = modalData.dmChannelId as string | undefined; const dmChannel = dmChannels.find(dm => dm.id === dmChannelId); const currentMemberIds = new Set(dmChannel?.members.map(m => m.id) ?? []); const memberCount = dmChannel?.members.length ?? 0; useEffect(() => { if (isOpen) { setQuery(''); setResults([]); setError(''); setIsAdding(false); setTimeout(() => inputRef.current?.focus(), 100); } }, [isOpen]); const handleSearch = (value: string) => { setQuery(value); setError(''); if (searchTimer.current) { clearTimeout(searchTimer.current); } if (value.trim().length < 2) { setResults([]); return; } searchTimer.current = setTimeout(async () => { setIsSearching(true); try { const users = await api.social.search(value.trim()); // Filter out users already in the DM setResults(users.filter(u => !currentMemberIds.has(u.id))); } catch { setResults([]); } finally { setIsSearching(false); } }, 300); }; const handleSelectUser = async (user: User) => { if (!dmChannelId || isAdding) return; setError(''); setIsAdding(true); try { const origin = channelOriginMap.get(dmChannelId) || ''; const targetApi = getApiForOrigin(origin); await targetApi.dm.addMember(dmChannelId, { userId: user.id }); closeModal(); } catch (err) { setError((err as Error).message || 'Failed to add member'); } finally { setIsAdding(false); } }; return (

Search for a user to add to this conversation.

{memberCount}/10
handleSearch(e.target.value)} placeholder="Search for a user..." className="w-full px-3 py-2 bg-surface-input text-txt-primary placeholder-txt-tertiary/60 rounded-[4px] text-[14px] outline-none focus:ring-1 focus:ring-accent-primary" disabled={memberCount >= 10} /> {memberCount >= 10 && (

This group DM has reached the 10-member limit.

)} {error && (

{error}

)}
{isSearching && (
Searching...
)} {!isSearching && query.trim().length >= 2 && results.length === 0 && (
No users found
)} {results.map((user) => ( ))}
); }