import ChatMessageRow from '../ChatMessageRow/index.jsx'; import ButtonBoxTile from '../ButtonBoxTile/index.jsx'; function getSafeWikiUrl(rawUrl) { const text = String(rawUrl || '').trim(); if (!text) return ''; try { /* Wiki links are operator-authored registry data, but this still normalizes them before rendering an anchor. Allowing only http/https avoids turning a barcode registry typo into a javascript: link while still supporting both absolute URLs and local wiki paths such as /wiki/object-name. */ const parsed = new URL(text, window.location.origin); if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return ''; return parsed.href; } catch { return ''; } } function BarcodeScanToast({ payload }) { const wikiUrl = getSafeWikiUrl(payload?.wikiUrl); const label = payload?.label || payload?.code || 'unknown barcode'; return (

Barcode scanned: {label} {wikiUrl ? ( Wiki link ) : null}

); } function UndockedExitWarningToast() { return (

Please dock your rover

Your rover is still undocked. Please dock it before leaving the page.

); } export default function AlertContent({ alert }) { if (alert.kind === 'buttonbox-active' && alert.payload) { const payload = alert.payload; return (
{payload.description ? (

{payload.description}

) : null}
); } if (alert.kind === 'chat' && alert.payload) { return ; } if (alert.kind === 'chat-typing' && alert.payload) { return ( // Override only the feed's typing surface so whole-alert opacity has one owner.
); } if (alert.kind === 'barcode-scan' && alert.payload) { return ; } if (alert.kind === 'undocked-exit-warning') { return ; } const color = typeof alert.color === 'string' ? alert.color.trim() : ''; const backgroundColor = /^#?[0-9a-f]{6}$/i.test(color) ? `#${color.replace('#', '')}` : '#2196f3'; return (

{alert.title || 'Alert'} ยท {alert.message}

); }