feat(F-129): completed feature
This commit is contained in:
@@ -54,27 +54,7 @@ interface ServerLogViewerProps {
|
||||
export function ServerLogViewer({ backendUrl = 'http://192.168.18.93:3000' }: ServerLogViewerProps) {
|
||||
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||
const [status, setStatus] = useState<'connecting' | 'live' | 'reconnecting' | 'error'>('connecting');
|
||||
const [autoScroll, setAutoScroll] = useState(true);
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const isAtBottomRef = useRef(true);
|
||||
|
||||
const scrollToBottom = useCallback(() => {
|
||||
if (autoScroll) bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
}, [autoScroll]);
|
||||
|
||||
// Track if user scrolled up
|
||||
const handleScroll = useCallback(() => {
|
||||
const el = containerRef.current;
|
||||
if (!el) return;
|
||||
const distFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
|
||||
isAtBottomRef.current = distFromBottom < 50;
|
||||
setAutoScroll(isAtBottomRef.current);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'live') scrollToBottom();
|
||||
}, [logs, scrollToBottom, status]);
|
||||
|
||||
useEffect(() => {
|
||||
setStatus('connecting');
|
||||
@@ -163,15 +143,6 @@ export function ServerLogViewer({ backendUrl = 'http://192.168.18.93:3000' }: Se
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<label className="flex items-center gap-1.5 text-xs text-gray-400 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={autoScroll}
|
||||
onChange={e => { setAutoScroll(e.target.checked); if (e.target.checked) bottomRef.current?.scrollIntoView(); }}
|
||||
className="rounded border-gray-600 text-[#2D6A4F] focus:ring-[#2D6A4F]"
|
||||
/>
|
||||
Auto-scroll
|
||||
</label>
|
||||
<button
|
||||
onClick={() => setLogs([])}
|
||||
className="px-2 py-1 text-xs border border-gray-600 text-gray-400 rounded hover:bg-gray-800 hover:text-gray-200 transition-colors"
|
||||
@@ -181,11 +152,10 @@ export function ServerLogViewer({ backendUrl = 'http://192.168.18.93:3000' }: Se
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Log content */}
|
||||
{/* Log content — F-129: flex-col-reverse para mostrar el más reciente arriba */}
|
||||
<div
|
||||
ref={containerRef}
|
||||
onScroll={handleScroll}
|
||||
className="flex-1 overflow-y-auto bg-[#0d1117] font-mono text-xs leading-relaxed"
|
||||
className="flex-1 overflow-y-auto bg-[#0d1117] font-mono text-xs leading-relaxed flex flex-col-reverse"
|
||||
style={{ minHeight: 0 }}
|
||||
>
|
||||
<table className="w-full table-fixed">
|
||||
@@ -226,7 +196,6 @@ export function ServerLogViewer({ backendUrl = 'http://192.168.18.93:3000' }: Se
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user