import React, { useEffect, useRef, useState } from 'react'; import Icon from './Icon'; /** * ScriptConsole — нижняя выдвижная панель консоли скриптов (синий wow-стиль). * * Показывает game.log() и ошибки выполнения. Auto-scroll вниз при новых * сообщениях. Кнопка «Очистить» сбрасывает буфер. * * Props: * logs — массив { level, text, ts } * onClear — () => void * onClose — () => void * visible — bool (если false — компонент не рендерится) */ const LEVEL_COLORS = { info: '#6d8aff', error: '#ff6b6b', warn: '#f5b342', }; const LEVEL_BG = { info: 'rgba(79, 116, 255, 0.12)', error: 'rgba(239, 68, 68, 0.14)', warn: 'rgba(245, 158, 11, 0.12)', }; const ScriptConsole = ({ logs = [], onClear, onClose, visible, onOpenScript }) => { const listRef = useRef(null); const [copyState, setCopyState] = useState('idle'); useEffect(() => { if (!visible) return; const el = listRef.current; if (el) el.scrollTop = el.scrollHeight; }, [logs, visible]); const handleCopy = async () => { const text = logs.map(l => { const ts = new Date(l.ts || Date.now()).toLocaleTimeString().slice(0, 8); const prefix = l.level === 'error' ? '[ERROR]' : l.level === 'warn' ? '[WARN]' : '[INFO]'; return `${ts} ${prefix} ${l.text || ''}`; }).join('\n'); try { if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(text); } else { const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); } setCopyState('copied'); setTimeout(() => setCopyState('idle'), 1500); } catch (e) { setCopyState('error'); setTimeout(() => setCopyState('idle'), 1500); } }; if (!visible) return null; const errorsCount = logs.filter(l => l.level === 'error').length; const warnsCount = logs.filter(l => l.level === 'warn').length; return (
{/* Header */}
Консоль скриптов {logs.length} {errorsCount > 0 && ( {errorsCount} )} {warnsCount > 0 && ( {warnsCount} )}
{/* Лог-строки */}
{logs.length === 0 ? (
Здесь появятся логи game.log() и ошибки скриптов.
) : ( logs.map((l, i) => (
{new Date(l.ts || Date.now()).toLocaleTimeString().slice(0, 8)} {l.level === 'error' && } {l.level === 'warn' && } {l.level === 'info' && } {l.text} {/* Ссылка на скрипт-источник (клик открывает его). */} {l.scriptId && ( )}
)) )}
); }; export default ScriptConsole;