import { useCallback, useEffect, useRef, useState } from 'react'; import type { MatrixClient, Room } from 'matrix-js-sdk'; import { connectLiveMatrixClient, listJoinedRooms, loadManualSession, peekPaarrotSession, pickDefaultRoom, saveManualSession, stopLiveMatrixClient, type LiveConnectMode, type ManualSessionInput, } from './liveClient'; type LiveState = { mode: LiveConnectMode; status: 'idle' | 'connecting' | 'ready' | 'error'; error: string | null; client: MatrixClient | null; room: Room | null; rooms: Room[]; sessionLabel: string | null; }; const initial: LiveState = { mode: 'mock', status: 'idle', error: null, client: null, room: null, rooms: [], sessionLabel: null, }; export function usePlaygroundMatrix() { const [state, setState] = useState(initial); const clientRef = useRef(null); const roomIdRef = useRef(undefined); const paarrotSession = peekPaarrotSession(); const hasPaarrotSession = Boolean(paarrotSession); const hasManualSession = Boolean(loadManualSession()); const teardown = useCallback(() => { stopLiveMatrixClient(clientRef.current); clientRef.current = null; }, []); useEffect(() => () => teardown(), [teardown]); const selectRoom = useCallback((roomId: string) => { roomIdRef.current = roomId; setState((prev) => { if (!prev.client) return prev; const room = pickDefaultRoom(prev.client, roomId) ?? null; return { ...prev, room }; }); }, []); const connectLive = useCallback( async (manual?: ManualSessionInput) => { teardown(); setState((prev) => ({ ...prev, mode: 'live', status: 'connecting', error: null, client: null, room: null, rooms: [], sessionLabel: null, })); try { if (manual) saveManualSession(manual); const mx = await connectLiveMatrixClient(manual); clientRef.current = mx; const rooms = listJoinedRooms(mx); const room = pickDefaultRoom(mx, roomIdRef.current) ?? null; if (room) roomIdRef.current = room.roomId; const hs = peekPaarrotSession()?.baseUrl ?? loadManualSession()?.baseUrl ?? ''; setState({ mode: 'live', status: 'ready', error: null, client: mx, room, rooms, sessionLabel: `${mx.getUserId() ?? '?'} ยท ${hs}`, }); } catch (err) { clientRef.current = null; setState({ ...initial, mode: 'live', status: 'error', error: err instanceof Error ? err.message : String(err), }); } }, [teardown] ); const useMocks = useCallback(() => { teardown(); roomIdRef.current = undefined; setState(initial); }, [teardown]); return { ...state, hasPaarrotSession, hasManualSession, paarrotUserId: paarrotSession?.userId ?? null, paarrotBaseUrl: paarrotSession?.baseUrl ?? null, connectLive, useMocks, selectRoom, }; }