// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 import React from 'react'; import { CustomStyleRulesCallback } from 'common/custom-theme'; import { Typography } from '@mui/material'; import { WithStyles } from '@mui/styles'; import withStyles from '@mui/styles/withStyles'; import { ArvadosTheme } from 'common/custom-theme'; import classNames from 'classnames'; import { connect, DispatchProp } from 'react-redux'; import { RootState } from 'store/store'; import { FederationConfig } from 'routes/routes'; import { renderLinks } from './code-snippet'; import { FixedSizeList } from 'react-window'; import AutoSizer from "react-virtualized-auto-sizer"; type CssRules = 'root' | 'space' | 'content' ; const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({ root: { boxSizing: 'border-box', height: '100%', padding: theme.spacing(1), }, space: { marginLeft: '15px', }, content: { maxHeight: '100%', height: '100vh', }, }); export interface CodeSnippetDataProps { lines: string[]; lineFormatter?: (lines: string[], index: number) => string; className?: string; apiResponse?: boolean; linked?: boolean; } interface CodeSnippetAuthProps { auth: FederationConfig; } type CodeSnippetProps = CodeSnippetDataProps & WithStyles<CssRules>; const mapStateToProps = (state: RootState): CodeSnippetAuthProps => ({ auth: state.auth, }); export const VirtualCodeSnippet = withStyles(styles)(connect(mapStateToProps)( ({ classes, lines, lineFormatter, linked, className, apiResponse, dispatch, auth }: CodeSnippetProps & CodeSnippetAuthProps & DispatchProp) => { const RenderRow = ({index, style}) => { const lineContents = lineFormatter ? lineFormatter(lines, index) : lines[index]; return <span style={style}>{linked ? renderLinks(auth, dispatch)(lineContents) : lineContents}</span> }; return <Typography component="div" data-cy="virtual-code-snippet" className={classNames([classes.root, className])}> <Typography className={classNames(classes.content, apiResponse ? classes.space : className)} component="pre"> <AutoSizer> {({ height, width }) => <FixedSizeList height={height} width={width} itemSize={21} itemCount={lines.length} > {RenderRow} </FixedSizeList> } </AutoSizer> </Typography> </Typography>; }));