diff options
| author | Haishan <[email protected]> | 2021-11-12 20:39:01 +0800 |
|---|---|---|
| committer | Haishan <[email protected]> | 2021-11-12 20:39:01 +0800 |
| commit | ce3ed3d99f6c8fcc13747c9fea12ce7f6cbebd72 (patch) | |
| tree | 865e8d6f6d15897dbd4294f7019abbcb68eb5d55 /src | |
| parent | b1ea08a4ee8dcb133b6be7dc4282eaffab32c046 (diff) | |
Add float action button to pause/start log streaming
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/logs.ts | 21 | ||||
| -rw-r--r-- | src/components/Connections.tsx | 6 | ||||
| -rw-r--r-- | src/components/Logs.tsx | 54 | ||||
| -rw-r--r-- | src/components/Root.scss | 12 |
4 files changed, 46 insertions, 47 deletions
diff --git a/src/api/logs.ts b/src/api/logs.ts index cb74bf3..044a31b 100644 --- a/src/api/logs.ts +++ b/src/api/logs.ts @@ -5,6 +5,12 @@ import { LogsAPIConfig } from 'src/types'; import { buildLogsWebSocketURL, getURLAndInit } from '../misc/request-helper'; type AppendLogFn = (x: Log) => void; +enum WebSocketReadyState { + Connecting = 0, + Open = 1, + Closing = 2, + Closed = 3, +} const endpoint = '/logs'; const textDecoder = new TextDecoder('utf-8'); @@ -86,20 +92,13 @@ function makeConnStr(c: LogsAPIConfig) { let prevConnStr: string; let controller: AbortController; -// 1 OPEN -// other value CLOSED -// similar to ws readyState but not the same -// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState -let wsState: number; export function fetchLogs(apiConfig: LogsAPIConfig, appendLog: AppendLogFn) { if (apiConfig.logLevel === 'uninit') return; - if (fetched || wsState === 1) return; + if (fetched || (ws && ws.readyState === WebSocketReadyState.Open)) return; prevAppendLogFn = appendLog; - wsState = 1; const url = buildLogsWebSocketURL(apiConfig, endpoint); ws = new WebSocket(url); ws.addEventListener('error', () => { - wsState = 3; fetchLogsWithFetch(apiConfig, appendLog); }); ws.addEventListener('message', function (event) { @@ -107,10 +106,14 @@ export function fetchLogs(apiConfig: LogsAPIConfig, appendLog: AppendLogFn) { }); } +export function stop() { + ws.close(); + if (controller) controller.abort(); +} + export function reconnect(apiConfig: LogsAPIConfig) { if (!prevAppendLogFn || !ws) return; ws.close(); - wsState = 3; fetched = false; fetchLogs(apiConfig, prevAppendLogFn); } diff --git a/src/components/Connections.tsx b/src/components/Connections.tsx index e5b4466..4c8bcff 100644 --- a/src/components/Connections.tsx +++ b/src/components/Connections.tsx @@ -235,11 +235,7 @@ function Conn({ apiConfig }) { isRefreshPaused ? <Play size={16} /> : <Pause size={16} /> } mainButtonStyles={ - isRefreshPaused - ? { - background: '#e74c3c', - } - : {} + isRefreshPaused ? { background: '#e74c3c' } : {} } style={fabPosition} text={isRefreshPaused ? 'Resume Refresh' : 'Pause Refresh'} diff --git a/src/components/Logs.tsx b/src/components/Logs.tsx index 019edd5..8f4ed1e 100644 --- a/src/components/Logs.tsx +++ b/src/components/Logs.tsx @@ -1,12 +1,8 @@ import cx from 'clsx'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; -import { - areEqual, - FixedSizeList as List, - ListChildComponentProps, -} from 'react-window'; -import { fetchLogs } from 'src/api/logs'; +import { areEqual, FixedSizeList as List, ListChildComponentProps } from 'react-window'; +import { fetchLogs, stop as stopLogs, reconnect as reconnectLogs } from 'src/api/logs'; import ContentHeader from 'src/components/ContentHeader'; import LogSearch from 'src/components/LogSearch'; import { connect } from 'src/components/StateProvider'; @@ -16,10 +12,12 @@ import { getClashAPIConfig } from 'src/store/app'; import { getLogLevel } from 'src/store/configs'; import { appendLog, getLogsForDisplay } from 'src/store/logs'; import { Log, State } from 'src/store/types'; +import { Pause, Play } from 'react-feather'; +import { Fab, position as fabPosition } from './shared/Fab'; import s from './Logs.module.scss'; -const { useCallback, memo, useEffect } = React; +const { useState, useCallback, memo, useEffect } = React; const paddingBottom = 30; const colors = { @@ -51,23 +49,22 @@ function itemKey(index: number, data: LogLineProps[]) { return item.id; } -const Row = memo( - ({ index, style, data }: ListChildComponentProps<LogLineProps>) => { - const r = data[index]; - return ( - <div style={style}> - <LogLine {...r} /> - </div> - ); - }, - areEqual -); +const Row = memo(({ index, style, data }: ListChildComponentProps<LogLineProps>) => { + const r = data[index]; + return ( + <div style={style}> + <LogLine {...r} /> + </div> + ); +}, areEqual); function Logs({ dispatch, logLevel, apiConfig, logs }) { - const appendLogInternal = useCallback( - (log) => dispatch(appendLog(log)), - [dispatch] - ); + const [isRefreshPaused, setIsRefreshPaused] = useState(false); + const toggleIsRefreshPaused = useCallback(() => { + isRefreshPaused ? reconnectLogs({ ...apiConfig, logLevel }) : stopLogs(); + setIsRefreshPaused((x) => !x); + }, [isRefreshPaused, apiConfig, logLevel]); + const appendLogInternal = useCallback((log) => dispatch(appendLog(log)), [dispatch]); useEffect(() => { fetchLogs({ ...apiConfig, logLevel }, appendLogInternal); }, [apiConfig, logLevel, appendLogInternal]); @@ -80,10 +77,7 @@ function Logs({ dispatch, logLevel, apiConfig, logs }) { <LogSearch /> <div ref={refLogsContainer} style={{ paddingBottom }}> {logs.length === 0 ? ( - <div - className={s.logPlaceholder} - style={{ height: containerHeight - paddingBottom }} - > + <div className={s.logPlaceholder} style={{ height: containerHeight - paddingBottom }}> <div className={s.logPlaceholderIcon}> <SvgYacd width={200} height={200} /> </div> @@ -101,6 +95,14 @@ function Logs({ dispatch, logLevel, apiConfig, logs }) { > {Row} </List> + + <Fab + icon={isRefreshPaused ? <Play size={16} /> : <Pause size={16} />} + mainButtonStyles={isRefreshPaused ? { background: '#e74c3c' } : {}} + style={fabPosition} + text={isRefreshPaused ? 'Resume Refresh' : 'Pause Refresh'} + onClick={toggleIsRefreshPaused} + ></Fab> </div> )} </div> diff --git a/src/components/Root.scss b/src/components/Root.scss index 55198ab..0df5819 100644 --- a/src/components/Root.scss +++ b/src/components/Root.scss @@ -53,18 +53,14 @@ :root { --font-mono: 'Roboto Mono', Menlo, monospace; - --font-normal: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, - Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, - 'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; + // prettier-ignore + --font-normal: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, 'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif; --color-focus-blue: #1a73e8; --btn-bg: #387cec; } body { - font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, - Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, - Segoe UI Symbol, 'PingFang SC', 'Microsoft YaHei', '微软雅黑', Arial, - sans-serif; + font-family: var(--font-normal); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-text-size-adjust: 100%; -webkit-font-smoothing: antialiased; @@ -135,10 +131,12 @@ body { :root[data-theme='dark'] { @include dark; + color-scheme: dark; } :root[data-theme='light'] { @include light; + color-scheme: light; } .flexCenter { |
