diff options
| author | Haishan <[email protected]> | 2019-01-13 23:37:22 +0800 |
|---|---|---|
| committer | Haishan <[email protected]> | 2019-01-13 23:37:22 +0800 |
| commit | 29048908df7cb4be642880f9fedba8766dbefa17 (patch) | |
| tree | 555980f680847a33ac634769edc945e9a3178e5e /src/components | |
| parent | fa7e03b9265ea18278ed785a2f48231722dd28d8 (diff) | |
perf(logs): optimize with windowed scrolling
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/Logs.js | 68 | ||||
| -rw-r--r-- | src/components/Logs.module.scss | 11 |
2 files changed, 47 insertions, 32 deletions
diff --git a/src/components/Logs.js b/src/components/Logs.js index ad551ee..43f64a9 100644 --- a/src/components/Logs.js +++ b/src/components/Logs.js @@ -1,11 +1,13 @@ -import React, { useState, useEffect } from 'react'; +import React, { memo, useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { useStoreState, useActions } from 'm/store'; import { getClashAPIConfig } from 'd/app'; import Icon from 'c/Icon'; +import { FixedSizeList as List, areEqual } from 'react-window'; import ContentHeader from 'c/ContentHeader'; +import useRemainingViewPortHeight from '../hooks/useRemainingViewPortHeight'; // TODO move this into a redux action import { fetchLogs } from '../api/logs'; import { getLogsForDisplay, appendLog } from 'd/logs'; @@ -13,6 +15,7 @@ import { getLogsForDisplay, appendLog } from 'd/logs'; import yacd from 's/yacd.svg'; import s0 from 'c/Logs.module.scss'; +const paddingBottom = 30; const colors = { debug: 'none', // debug: '#8a8a8a', @@ -23,9 +26,9 @@ const colors = { }; function LogLine({ time, even, payload, type }) { - const className = cx({ even }); + const className = cx({ even }, s0.log); return ( - <li className={className}> + <div className={className}> <div className={s0.logMeta}> <div className={s0.logTime}>{time}</div> <div className={s0.logType} style={{ backgroundColor: colors[type] }}> @@ -33,16 +36,23 @@ function LogLine({ time, even, payload, type }) { </div> <div className={s0.logText}>{payload}</div> </div> - </li> + </div> ); } -LogLine.propTypes = { - time: PropTypes.string, - even: PropTypes.bool, - type: PropTypes.string.isRequired, - payload: PropTypes.string.isRequired -}; +function itemKey(index, data) { + const item = data[index]; + return item.id; +} + +const Row = memo(({ index, style, data }) => { + const r = data[index]; + return ( + <div style={style}> + <LogLine {...r} /> + </div> + ); +}, areEqual); const actions = { appendLog }; @@ -57,26 +67,34 @@ export default function Logs() { }, [hostname, port, secret] ); + const [refLogsContainer, containerHeight] = useRemainingViewPortHeight(); return ( <div> <ContentHeader title="Logs" /> - {logs.length === 0 ? ( - <div className={s0.logPlaceholder}> - <div className={s0.logPlaceholderIcon}> - <Icon id={yacd.id} width={200} height={200} /> + <div ref={refLogsContainer} style={{ paddingBottom }}> + {logs.length === 0 ? ( + <div className={s0.logPlaceholder}> + <div className={s0.logPlaceholderIcon}> + <Icon id={yacd.id} width={200} height={200} /> + </div> + <div>No logs yet, hang tight...</div> </div> - <div>No logs yet, hang tight...</div> - </div> - ) : ( - <div className={s0.logs}> - <ul className={s0.logUl}> - {logs.map(l => ( - <LogLine key={l.id} {...l} /> - ))} - </ul> - </div> - )} + ) : ( + <div className={s0.logsWrapper}> + <List + height={containerHeight - paddingBottom} + width="100%" + itemCount={logs.length} + itemSize={80} + itemData={logs} + itemKey={itemKey} + > + {Row} + </List> + </div> + )} + </div> </div> ); } diff --git a/src/components/Logs.module.scss b/src/components/Logs.module.scss index adc6f0f..4351bcb 100644 --- a/src/components/Logs.module.scss +++ b/src/components/Logs.module.scss @@ -40,10 +40,9 @@ $heightHeader: 76px; ////////// -.logUl { +.logsWrapper { margin: 0; padding: 0; - list-style: none; color: var(--color-text); :global { @@ -56,14 +55,12 @@ $heightHeader: 76px; } } -///////// - -.logs { +.log { padding: 10px 40px; - height: calc(100vh - #{$heightHeader}); - overflow: scroll; } +///////// + .logPlaceholder { height: calc(100vh - #{$heightHeader}); display: flex; |
