chore: parse ansi

This commit is contained in:
jialin
2024-10-18 15:20:55 +08:00
parent b9c9fe7a97
commit 2fea3a4b40
8 changed files with 253 additions and 430 deletions
+46 -54
View File
@@ -1,19 +1,13 @@
import useSetChunkRequest from '@/hooks/use-chunk-request';
import useSetChunkFetch from '@/hooks/use-chunk-fetch';
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import { FitAddon } from '@xterm/addon-fit';
import { Terminal } from '@xterm/xterm';
import '@xterm/xterm/css/xterm.css';
import classNames from 'classnames';
import _ from 'lodash';
import {
memo,
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState
} from 'react';
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import './index.less';
import useSize from './use-size';
import parseAnsi from './parse-ansi';
interface LogsViewerProps {
height: number;
@@ -22,39 +16,41 @@ interface LogsViewerProps {
params?: object;
}
const LogsViewer: React.FC<LogsViewerProps> = (props) => {
const { height, content, url } = props;
const { setChunkRequest } = useSetChunkRequest();
const { height, url } = props;
const { initialize, updateScrollerPosition } = useOverlayScroller({
theme: 'os-theme-light'
});
const { setChunkFetch } = useSetChunkFetch();
const chunkRequedtRef = useRef<any>(null);
const scroller = useRef<any>({});
const termRef = useRef<any>({});
const termwrapRef = useRef<any>({});
const fitAddonRef = useRef<any>({});
const cacheDataRef = useRef<any>('');
const [logs, setLogs] = useState('');
const size = useSize(scroller);
const uidRef = useRef<any>(0);
const [logs, setLogs] = useState<any[]>([]);
const throttleScroll = _.throttle(() => {
termRef.current?.scrollToBottom?.();
}, 100);
const updateContent = useCallback(
_.throttle((data: string) => {
cacheDataRef.current = '';
termRef.current?.clear?.();
cacheDataRef.current = data;
termRef.current?.write?.(data);
setLogs(data);
}, 100),
[]
);
const fitTerm = () => {
fitAddonRef.current?.fit?.();
const setId = () => {
uidRef.current += 1;
return uidRef.current;
};
const clearScreen = () => {
cacheDataRef.current = '';
};
const updateContent = useCallback(
(data: string) => {
cacheDataRef.current += data;
const res = parseAnsi(cacheDataRef.current, setId, clearScreen);
setLogs(res);
},
[setLogs, setId]
);
const createChunkConnection = async () => {
chunkRequedtRef.current?.current?.cancel?.();
chunkRequedtRef.current = setChunkRequest({
chunkRequedtRef.current?.current?.abort?.();
chunkRequedtRef.current = setChunkFetch({
url,
params: {
...props.params,
@@ -65,7 +61,8 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
});
};
const initTerm = () => {
const initTerm = useCallback(() => {
termRef.current?.clear?.();
termRef.current?.dispose?.();
termRef.current = new Terminal({
lineHeight: 1.2,
@@ -84,43 +81,38 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
fitAddonRef.current = new FitAddon();
termRef.current.loadAddon(fitAddonRef.current);
termRef.current.open(termwrapRef.current);
};
const handleResize = _.throttle(() => {
fitTerm();
}, 100);
}, [termwrapRef.current]);
useEffect(() => {
createChunkConnection();
return () => {
chunkRequedtRef.current?.current?.cancel?.();
chunkRequedtRef.current?.current?.abort?.();
};
}, [url, props.params]);
useEffect(() => {
if (termwrapRef.current) {
initTerm();
if (scroller.current) {
initialize(scroller.current);
}
return () => {
termRef.current?.dispose?.();
};
}, [termwrapRef.current]);
useLayoutEffect(() => {
if (size) {
handleResize();
}
}, [size]);
}, [scroller.current, initialize]);
useEffect(() => {
throttleScroll();
if (logs) {
updateScrollerPosition();
}
}, [logs]);
return (
<div className="logs-viewer-wrap-w2">
<div className="wrap" style={{ height: height }} ref={scroller}>
<div className={classNames('content')}>
<div className="text" ref={termwrapRef}></div>
{_.map(logs, (item: any, index: number) => {
return (
<div key={item.uid} className="text">
{item.content}
</div>
);
})}
</div>
</div>
</div>