// Inter Instance Panel // Purpose: Renders remote rover servers discovered through the inter-instance directory. // Scope: Owns external server metadata presentation while reusing RoverQueuesPanel for rover/queue rows. import { useMemo, useState } from 'react'; import { useSessionSelector } from '../../context/SessionContext.jsx'; import CardFrame from '../CardFrame/index.jsx'; import RoverQueuesPanel from '../RoverQueuesPanel/index.jsx'; import { openExternalRoverWithPrompt } from '../../lib/interInstanceTransfer.js'; import { isFeatureEnabled } from '../../lib/features.js'; function classNames(...values) { return values.filter(Boolean).join(' '); } function useRemoteInstances() { return useSessionSelector((state) => state.session?.interInstances?.instances ?? []); } function useInterInstanceEnabled() { return useSessionSelector((state) => isFeatureEnabled(state, 'interInstance')); } function featureEntries(features = {}) { return Object.entries(features || {}) .filter(([, enabled]) => Boolean(enabled)) .map(([name]) => name); } function InstanceStatus({ remote }) { const mode = remote?.instance?.mode || 'unknown'; const online = Boolean(remote?.online); return (
{online ? 'Online' : 'Offline'} {mode} {remote?.latencyMs != null ? ( {remote.latencyMs}ms ) : null}
); } function OfflineInstanceCard({ remote }) { const name = remote?.instance?.name || remote?.url || 'External server'; return (

{remote?.url || 'No URL available.'}

{remote?.lastError ?

{remote.lastError}

: null}
); } function InstanceMetadata({ remote }) { const instance = remote?.instance || {}; const features = featureEntries(instance.features); const color = instance.color || '#64748b'; return ( } bodyClassName="space-y-0.5 p-0.5 text-sm" >
{instance.description ?

{instance.description}

: null}
{instance.publicUrl ? {instance.publicUrl} : null}
{features.length ? (
{features.map((feature) => ( {feature} ))}
) : (

No advertised feature flags.

)}
); } function RemoteMediaStrip({ remote }) { const roverSnapshots = (remote.roster || []) .map((rover) => ({ id: rover.id, name: rover.name || rover.id, url: rover.snapshots?.latestUrl, updatedAt: rover.snapshots?.updatedAt, })) .filter((entry) => entry.url); const roomCameras = Array.isArray(remote.roomCameras) ? remote.roomCameras.filter((camera) => camera.snapshotUrl) : []; const items = [ ...roverSnapshots.map((entry) => ({ ...entry, kind: 'Rover' })), ...roomCameras.map((entry) => ({ ...entry, name: entry.name || entry.id, url: entry.snapshotUrl, kind: 'Room' })), ]; if (!items.length) return null; return (
{items.map((item) => (
{item.name}
{item.name} {item.kind}
))}
); } export function ExternalInstancesCompact() { const [expanded, setExpanded] = useState(false); const [popupOpen, setPopupOpen] = useState(false); const enabled = useInterInstanceEnabled(); const instances = useRemoteInstances(); const visible = useMemo(() => instances.filter((remote) => remote?.online || remote?.url), [instances]); if (!enabled) return null; if (!visible.length) return null; return (
{expanded ? (
{visible.map((remote) => remote.online ? ( ) : ( ), )}
) : null} {popupOpen ? setPopupOpen(false)} /> : null}
); } export function InterInstancePopup({ onClose }) { const enabled = useInterInstanceEnabled(); if (!enabled) return null; return (
Close } className="w-full max-w-6xl" bodyClassName="max-h-[82vh] overflow-y-auto p-0.5" clipOverflow={false} >
); } export default function InterInstancePanel({ compact = false, centered = false }) { const enabled = useInterInstanceEnabled(); const instances = useRemoteInstances(); if (!enabled) return null; if (compact) return ; if (!instances.length) { return (

No external instances discovered.

); } return (
{instances.map((remote) => (
{remote.online ? ( <> ) : ( )}
))}
); }