import * as React from 'react'; import { Pause, Play } from 'react-feather'; import { useTranslation } from 'react-i18next'; import { fetchLogs, reconnect as reconnectLogs, stop as stopLogs } from '~/api/logs'; import ContentHeader from '~/components/ContentHeader'; import LogSearch from '~/components/LogSearch'; import { connect, useStoreActions } from '~/components/StateProvider'; import SvgYacd from '~/components/SvgYacd'; import useRemainingViewPortHeight from '~/hooks/useRemainingViewPortHeight'; import { getClashAPIConfig, getLogStreamingPaused } from '~/store/app'; import { getLogLevel } from '~/store/configs'; import { appendLog, getLogsForDisplay } from '~/store/logs'; import { Log, State } from '~/store/types'; import s from './Logs.module.scss'; import { Fab, position as fabPosition } from './shared/Fab'; const { useCallback, useEffect } = React; const colors = { debug: '#389d3d', info: '#58c3f2', warning: '#cc5abb', error: '#c11c1c', }; const logTypes = { debug: 'debug', info: 'info', warning: 'warn', error: 'error', }; type LogLineProps = Partial; function LogLine({ time, payload, type }: LogLineProps) { return (
{time} [ {logTypes[type]} ] {payload}
); } function Logs({ dispatch, logLevel, apiConfig, logs, logStreamingPaused }) { const actions = useStoreActions(); const toggleIsRefreshPaused = useCallback(() => { logStreamingPaused ? reconnectLogs({ ...apiConfig, logLevel }) : stopLogs(); // being lazy here // ideally we should check the result of previous operation before updating this actions.app.updateAppConfig('logStreamingPaused', !logStreamingPaused); }, [apiConfig, logLevel, logStreamingPaused, actions.app]); const appendLogInternal = useCallback((log) => dispatch(appendLog(log)), [dispatch]); useEffect(() => { fetchLogs({ ...apiConfig, logLevel }, appendLogInternal); }, [apiConfig, logLevel, appendLogInternal]); const [refLogsContainer, containerHeight] = useRemainingViewPortHeight(); const { t } = useTranslation(); return (
{logs.length === 0 ? (
{t('no_logs')}
) : (
{logs.map((log, index) => (
))} : } mainButtonStyles={logStreamingPaused ? { background: '#e74c3c' } : {}} style={fabPosition} text={logStreamingPaused ? t('Resume Refresh') : t('Pause Refresh')} onClick={toggleIsRefreshPaused} >
)}
); } const mapState = (s: State) => ({ logs: getLogsForDisplay(s), logLevel: getLogLevel(s), apiConfig: getClashAPIConfig(s), logStreamingPaused: getLogStreamingPaused(s), }); export default connect(mapState)(Logs);