Merge pull request #2727 from nickofolas/feature/editor-tab-actions

Script Editor Tab Actions
This commit is contained in:
hydroflame 2022-01-26 00:50:23 -05:00 committed by GitHub
commit a05ecc76c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,6 +33,8 @@ import Typography from "@mui/material/Typography";
import Link from "@mui/material/Link"; import Link from "@mui/material/Link";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import SettingsIcon from "@mui/icons-material/Settings"; import SettingsIcon from "@mui/icons-material/Settings";
import SyncIcon from '@mui/icons-material/Sync';
import CloseIcon from '@mui/icons-material/Close';
import Table from "@mui/material/Table"; import Table from "@mui/material/Table";
import TableCell from "@mui/material/TableCell"; import TableCell from "@mui/material/TableCell";
import TableRow from "@mui/material/TableRow"; import TableRow from "@mui/material/TableRow";
@ -41,6 +43,7 @@ import { PromptEvent } from "../../ui/React/PromptManager";
import { Modal } from "../../ui/React/Modal"; import { Modal } from "../../ui/React/Modal";
import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts"; import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts";
import { Tooltip } from "@mui/material";
interface IProps { interface IProps {
// Map of filename -> code // Map of filename -> code
@ -692,17 +695,56 @@ export function Root(props: IProps): React.ReactElement {
} }
} }
function onTabUpdate(index: number): void {
const openScript = openScripts[index];
const serverScriptCode = getServerCode(index);
if (serverScriptCode === null) return;
if (openScript.code !== serverScriptCode) {
PromptEvent.emit({
txt: "Do you want to overwrite the current editor content with the contents of " +
openScript.fileName + " on the server? This cannot be undone.",
resolve: (result: boolean) => {
if (result) {
// Save changes
openScript.code = serverScriptCode;
// Switch to target tab
onTabClick(index)
if (editorRef.current !== null && openScript !== null) {
if (openScript.model === undefined || openScript.model.isDisposed()) {
regenerateModel(openScript);
}
editorRef.current.setModel(openScript.model);
editorRef.current.setValue(openScript.code);
updateRAM(openScript.code);
editorRef.current.focus();
}
}
},
});
}
}
function dirty(index: number): string { function dirty(index: number): string {
const openScript = openScripts[index];
const serverScriptCode = getServerCode(index);
if (serverScriptCode === null) return " *";
// The server code is stored with its starting & trailing whitespace removed
const openScriptFormatted = Script.formatCode(openScript.code);
return serverScriptCode !== openScriptFormatted ? " *" : "";
}
function getServerCode(index: number): string | null {
const openScript = openScripts[index]; const openScript = openScripts[index];
const server = GetServer(openScript.hostname); const server = GetServer(openScript.hostname);
if (server === null) throw new Error(`Server '${openScript.hostname}' should not be null, but it is.`); if (server === null) throw new Error(`Server '${openScript.hostname}' should not be null, but it is.`);
const serverScript = server.scripts.find((s) => s.filename === openScript.fileName); const serverScript = server.scripts.find((s) => s.filename === openScript.fileName);
if (serverScript === undefined) return " *"; return serverScript?.code ?? null;
// The server code is stored with its starting & trailing whitespace removed
const openScriptFormatted = Script.formatCode(openScript.code);
return serverScript.code !== openScriptFormatted ? " *" : "";
} }
// Toolbars are roughly 112px: // Toolbars are roughly 112px:
@ -734,57 +776,74 @@ export function Root(props: IProps): React.ReactElement {
overflowX: "scroll", overflowX: "scroll",
}} }}
> >
{openScripts.map(({ fileName, hostname }, index) => ( {openScripts.map(({ fileName, hostname }, index) => {
<Draggable const iconButtonStyle = {
key={fileName + hostname} maxWidth: "25px",
draggableId={fileName + hostname} minWidth: "25px",
index={index} minHeight: '38.5px',
disableInteractiveElementBlocking={true} maxHeight: '38.5px',
> ...(currentScript?.fileName === openScripts[index].fileName ? {
{(provided) => ( background: Settings.theme.button,
<div borderColor: Settings.theme.button,
ref={provided.innerRef} color: Settings.theme.primary
{...provided.draggableProps} } : {
{...provided.dragHandleProps} background: Settings.theme.backgroundsecondary,
style={{ borderColor: Settings.theme.backgroundsecondary,
...provided.draggableProps.style, color: Settings.theme.secondary
marginRight: "5px", })
flexShrink: 0, };
}} return (
> <Draggable
<Button key={fileName + hostname}
onClick={() => onTabClick(index)} draggableId={fileName + hostname}
style={ index={index}
currentScript?.fileName === openScripts[index].fileName ? { disableInteractiveElementBlocking={true}
background: Settings.theme.button, >
color: Settings.theme.primary {(provided) => (
} : { <div
background: Settings.theme.backgroundsecondary, ref={provided.innerRef}
color: Settings.theme.secondary {...provided.draggableProps}
}} {...provided.dragHandleProps}
>
{hostname}:~/{fileName} {dirty(index)}
</Button>
<Button
onClick={() => onTabClose(index)}
style={{ style={{
maxWidth: "20px", ...provided.draggableProps.style,
minWidth: "20px", marginRight: "5px",
...(currentScript?.fileName === openScripts[index].fileName ? { flexShrink: 0,
background: Settings.theme.button, border: '1px solid ' + Settings.theme.well,
color: Settings.theme.primary
} : {
background: Settings.theme.backgroundsecondary,
color: Settings.theme.secondary
})
}} }}
> >
x <Button
</Button> onClick={() => onTabClick(index)}
</div> onMouseDown={e => {
)} e.preventDefault();
</Draggable> if (e.button === 1) onTabClose(index);
))} }}
style={{
...(currentScript?.fileName === openScripts[index].fileName ? {
background: Settings.theme.button,
borderColor: Settings.theme.button,
color: Settings.theme.primary
} : {
background: Settings.theme.backgroundsecondary,
borderColor: Settings.theme.backgroundsecondary,
color: Settings.theme.secondary
})
}}
>
{hostname}:~/{fileName} {dirty(index)}
</Button>
<Tooltip title="Overwrite editor content with saved file content">
<Button onClick={() => onTabUpdate(index)} style={iconButtonStyle} >
<SyncIcon fontSize='small' />
</Button>
</Tooltip>
<Button onClick={() => onTabClose(index)} style={iconButtonStyle}>
<CloseIcon fontSize='small' />
</Button>
</div>
)}
</Draggable>
)
})}
{provided.placeholder} {provided.placeholder}
</Box> </Box>
)} )}