better terminal scrolling

This commit is contained in:
Olivier Gagnon 2021-09-16 20:14:09 -04:00
parent 3fc46c8fc6
commit b6924d6889
3 changed files with 45 additions and 36 deletions

@ -8,9 +8,6 @@
-ms-overflow-style: none; /* for Internet Explorer, Edge */ -ms-overflow-style: none; /* for Internet Explorer, Edge */
scrollbar-width: none; /* for Firefox */ scrollbar-width: none; /* for Firefox */
flex-grow: 1; flex-grow: 1;
overflow-y: scroll;
height: 100vh;
bottom: 0px;
} }
#generic-react-container::-webkit-scrollbar { #generic-react-container::-webkit-scrollbar {

@ -77,7 +77,7 @@ export class Terminal implements ITerminal {
commandHistory: string[] = []; commandHistory: string[] = [];
commandHistoryIndex = 0; commandHistoryIndex = 0;
outputHistory: (Output | Link)[] = [{ text: `Bitburner v${CONSTANTS.Version}`, color: "primary" }]; outputHistory: (Output | Link)[] = [new Output(`Bitburner v${CONSTANTS.Version}`, "primary")];
// True if a Coding Contract prompt is opened // True if a Coding Contract prompt is opened
contractOpen = false; contractOpen = false;
@ -489,6 +489,7 @@ export class Terminal implements ITerminal {
} }
clear(): void { clear(): void {
// TODO: remove this once we figure out the height issue.
this.outputHistory = [new Output(`Bitburner v${CONSTANTS.Version}`, "primary")]; this.outputHistory = [new Output(`Bitburner v${CONSTANTS.Version}`, "primary")];
this.hasChanges = true; this.hasChanges = true;
} }

@ -1,11 +1,11 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useRef } from "react";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import List from "@mui/material/List"; import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem"; import ListItem from "@mui/material/ListItem";
import { Link as MuiLink } from "@mui/material"; import { Link as MuiLink } from "@mui/material";
import { Theme } from "@mui/material/styles"; import { Theme } from "@mui/material/styles";
import makeStyles from '@mui/styles/makeStyles'; import makeStyles from "@mui/styles/makeStyles";
import createStyles from '@mui/styles/createStyles'; import createStyles from "@mui/styles/createStyles";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import { ITerminal, Output, Link } from "../ITerminal"; import { ITerminal, Output, Link } from "../ITerminal";
import { IEngine } from "../../IEngine"; import { IEngine } from "../../IEngine";
@ -47,6 +47,7 @@ interface IProps {
} }
export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactElement { export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactElement {
const scrollHook = useRef<HTMLDivElement>(null);
const setRerender = useState(false)[1]; const setRerender = useState(false)[1];
function rerender(): void { function rerender(): void {
setRerender((old) => !old); setRerender((old) => !old);
@ -59,36 +60,46 @@ export function TerminalRoot({ terminal, engine, player }: IProps): React.ReactE
return () => clearInterval(id); return () => clearInterval(id);
}, []); }, []);
const hook = scrollHook.current;
if (hook !== null) {
setTimeout(() => hook.scrollIntoView(true), 10);
}
const classes = useStyles(); const classes = useStyles();
return ( return (
<Box position="fixed" bottom="0" width="100%" px={1}> <>
<List classes={{ root: classes.list }}> <Box width="100%" minHeight="100vh" px={1}>
{terminal.outputHistory.map((item, i) => { <List classes={{ root: classes.list }}>
if (item instanceof Output) {terminal.outputHistory.map((item, i) => {
return ( if (item instanceof Output)
<ListItem key={i} classes={{ root: classes.nopadding }}> return (
<Typography classes={{ root: classes.preformatted }} color={item.color} paragraph={false}> <ListItem key={i} classes={{ root: classes.nopadding }}>
{item.text} <Typography classes={{ root: classes.preformatted }} color={item.color} paragraph={false}>
</Typography> {item.text}
</ListItem> </Typography>
); </ListItem>
if (item instanceof Link) );
return ( if (item instanceof Link)
<ListItem key={i} classes={{ root: classes.nopadding }}> return (
<MuiLink <ListItem key={i} classes={{ root: classes.nopadding }}>
classes={{ root: classes.preformatted }} <MuiLink
color={"secondary"} classes={{ root: classes.preformatted }}
paragraph={false} color={"secondary"}
onClick={() => terminal.connectToServer(player, item.hostname)} paragraph={false}
> onClick={() => terminal.connectToServer(player, item.hostname)}
&gt;&nbsp;{item.hostname} >
</MuiLink> &gt;&nbsp;{item.hostname}
</ListItem> </MuiLink>
); </ListItem>
})} );
</List> })}
{terminal.action !== null && <ActionTimer terminal={terminal} />} </List>
<TerminalInput player={player} engine={engine} terminal={terminal} /> {terminal.action !== null && <ActionTimer terminal={terminal} />}
</Box> <div ref={scrollHook}></div>
</Box>
<Box position="sticky" bottom={0} width="100%" px={1}>
<TerminalInput player={player} engine={engine} terminal={terminal} />
</Box>
</>
); );
} }