diff --git a/packages/web/src/components/chat/FriendsPage.test.tsx b/packages/web/src/components/chat/FriendsPage.test.tsx index 82ec41ec..c1c2f551 100644 --- a/packages/web/src/components/chat/FriendsPage.test.tsx +++ b/packages/web/src/components/chat/FriendsPage.test.tsx @@ -108,11 +108,6 @@ vi.mock('../../stores/activityStore', () => ({ ), })); -// Mock ConnectInstanceModal -vi.mock('../modals/ConnectInstanceModal', () => ({ - ConnectInstanceModal: () => null, -})); - const mockNavigate = vi.fn(); vi.mock('react-router-dom', async () => { const actual = await vi.importActual('react-router-dom'); diff --git a/packages/web/src/components/modals/ConnectInstanceModal.tsx b/packages/web/src/components/modals/ConnectInstanceModal.tsx deleted file mode 100644 index 4676af4e..00000000 --- a/packages/web/src/components/modals/ConnectInstanceModal.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import React, { useState, useEffect, useRef } from 'react'; -import { createPortal } from 'react-dom'; -import { useInstanceConnect } from '../../hooks/useInstanceConnect'; - -interface ConnectInstanceModalProps { - domain: string; - targetDisplayName: string; - isReconnect?: boolean; - actionLabel?: string; - onConnected(result: 'new' | 'reconnect'): void; - onCancel(): void; -} - -export function ConnectInstanceModal({ - domain, - targetDisplayName, - isReconnect = false, - actionLabel, - onConnected, - onCancel, -}: ConnectInstanceModalProps) { - const [password, setPassword] = useState(''); - const { connect, isConnecting, error, clearError } = useInstanceConnect(); - const inputRef = useRef(null); - - const resolvedLabel = actionLabel - ?? (isReconnect ? 'Reconnect & Add Friend' : 'Connect & Add Friend'); - - // Focus password input on mount - useEffect(() => { - const timer = setTimeout(() => inputRef.current?.focus(), 50); - return () => clearTimeout(timer); - }, []); - - // Escape key handler — stop propagation to prevent parent modal from closing - useEffect(() => { - const handleKey = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - e.stopPropagation(); - onCancel(); - } - }; - document.addEventListener('keydown', handleKey, true); // capture phase - return () => document.removeEventListener('keydown', handleKey, true); - }, [onCancel]); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - if (!password.trim() || isConnecting) return; - - try { - const result = await connect(domain, password.trim()); - onConnected(result); - } catch { - // Error state is managed by the hook — UI updates via `error` - } - }; - - return createPortal( -
- {/* Lighter backdrop to avoid compounding with parent modal */} -
- -
- {/* Header */} -
-
-
- - - -
-

- {isReconnect ? 'Reconnect to Instance' : 'Connect to Instance'} -

-
- -

- {isReconnect ? ( - <> - Your connection to {domain} was lost. - Re-enter your password to reconnect and send a friend request to{' '} - {targetDisplayName}. - - ) : ( - <> - {targetDisplayName} is on{' '} - {domain}, an instance you - haven't connected to yet. Connect to send a friend request. - - )} -

- - {/* Instance badge */} -
-
- - - -
-
-
{domain}
-
Remote Backspace instance
-
-
-
- - {/* Form */} -
- { - setPassword(e.target.value); - if (error) clearError(); - }} - disabled={isConnecting} - autoComplete="current-password" - /> - - {/* Error text */} - {error && ( -

{error}

- )} - -
- - -
-
-
-
, - document.body - ); -}