'use client'; import { useState, useRef, useEffect } from 'react'; interface SpaceInfo { slug: string; name: string; icon?: string; role?: string; } interface SpaceSwitcherProps { /** Current app domain, e.g. 'rchats.online'. Space links become . */ domain?: string; } /** Read the EncryptID token from localStorage (set by token-relay across r*.online) */ function getEncryptIDToken(): string | null { if (typeof window === 'undefined') return null; try { return localStorage.getItem('encryptid_token'); } catch { return null; } } export function SpaceSwitcher({ domain }: SpaceSwitcherProps) { const [open, setOpen] = useState(false); const [spaces, setSpaces] = useState([]); const [loaded, setLoaded] = useState(false); const [isAuthenticated, setIsAuthenticated] = useState(false); const ref = useRef(null); // Derive domain from window.location if not provided const appDomain = domain || (typeof window !== 'undefined' ? window.location.hostname.split('.').slice(-2).join('.') : 'rspace.online'); useEffect(() => { function handleClick(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false); } } document.addEventListener('click', handleClick); return () => document.removeEventListener('click', handleClick); }, []); // Check auth status on mount useEffect(() => { const token = getEncryptIDToken(); if (token) { setIsAuthenticated(true); } else { // Fallback: check /api/me fetch('/api/me') .then((r) => r.json()) .then((data) => { if (data.authenticated) setIsAuthenticated(true); }) .catch(() => {}); } }, []); const loadSpaces = async () => { if (loaded) return; try { // Pass EncryptID token so the proxy can forward it to rSpace const token = getEncryptIDToken(); const headers: Record = {}; if (token) headers['Authorization'] = `Bearer ${token}`; const res = await fetch('/api/spaces', { headers }); if (res.ok) { const data = await res.json(); setSpaces(data.spaces || []); } } catch { // API not available } setLoaded(true); }; const handleOpen = async () => { const nowOpen = !open; setOpen(nowOpen); if (nowOpen && !loaded) { await loadSpaces(); } }; /** Build URL for a space: . */ const spaceUrl = (slug: string) => `https://${slug}.${appDomain}`; const mySpaces = spaces.filter((s) => s.role); const publicSpaces = spaces.filter((s) => !s.role); return (
{open && (
{!loaded ? (
Loading spaces...
) : spaces.length === 0 ? ( <>
{isAuthenticated ? 'No spaces yet' : 'Sign in to see your spaces'}
setOpen(false)} > + Create new space ) : ( <> {mySpaces.length > 0 && ( <>
Your spaces
{mySpaces.map((s) => ( setOpen(false)} > {s.icon || '🌐'} {s.name} {s.role && ( {s.role} )} ))} )} {publicSpaces.length > 0 && ( <> {mySpaces.length > 0 && ); }