import {LogMessage, ServerLogUIEvents} from "tc-shared/ui/frames/log/Definitions"; import {VariadicTranslatable} from "tc-shared/ui/react-elements/i18n"; import {Registry} from "tc-shared/events"; import {useEffect, useRef, useState} from "react"; import * as React from "react"; import {findLogDispatcher} from "tc-shared/ui/frames/log/DispatcherLog"; const cssStyle = require("./Renderer.scss"); const LogFallbackDispatcher = (_unused, __unused, eventType) => (
<>{eventType}
); const LogEntryRenderer = React.memo((props: { entry: LogMessage, handlerId: string }) => { const dispatcher = findLogDispatcher(props.entry.type as any) || LogFallbackDispatcher; const rendered = dispatcher(props.entry.data, props.handlerId, props.entry.type); if(!rendered) /* hide message */ return null; const date = new Date(props.entry.timestamp); return (
<{ ("0" + date.getHours()).substr(-2) + ":" + ("0" + date.getMinutes()).substr(-2) + ":" + ("0" + date.getSeconds()).substr(-2) }>
{rendered}
); }); export const ServerLogRenderer = (props: { events: Registry, handlerId: string }) => { const [ logs, setLogs ] = useState(() => { props.events.fire_async("query_log"); return "loading"; }); const [ revision, setRevision ] = useState(0); const refContainer = useRef(); const scrollOffset = useRef("bottom"); props.events.reactUse("notify_log", event => { const logs = event.log.slice(0); logs.splice(0, Math.max(0, logs.length - 100)); logs.sort((a, b) => a.timestamp - b.timestamp); setLogs(logs); }); props.events.reactUse("notify_log_add", event => { if(logs === "loading") { return; } if(__build.mode === "debug") { const index = logs.findIndex(e => e.uniqueId === event.event.uniqueId); if(index !== -1) { debugger; } } logs.push(event.event); logs.splice(0, Math.max(0, logs.length - 100)); logs.sort((a, b) => a.timestamp - b.timestamp); setRevision(revision + 1); }); useEffect(() => { const id = requestAnimationFrame(() => { if(!refContainer.current) return; refContainer.current.scrollTop = scrollOffset.current === "bottom" ? refContainer.current.scrollHeight : scrollOffset.current; }); return () => cancelAnimationFrame(id); }); return (
{ const target = event.target as HTMLDivElement; const top = target.scrollTop; const total = target.scrollHeight - target.clientHeight; const shouldFollow = top + 50 > total; scrollOffset.current = shouldFollow ? "bottom" : top; }}> {logs === "loading" ? null : logs.map(e => )}
); };