Added Layout to the editor page

This commit is contained in:
inaseem 2021-10-03 19:49:58 +05:30
parent c82b287c8a
commit c5e00165dd
7 changed files with 209 additions and 172 deletions

View File

@ -0,0 +1,32 @@
import React from "react";
import { EventEmitter } from "../utils/EventEmitter";
import Split from "react-split";
const Layouts = (props) => {
const { splitType, children } = props;
return (
<>
<Split
className="split"
minSize={0}
snapOffset={0}
expandToMin={false}
gutterSize={10}
gutterAlign="center"
dragInterval={1}
direction={splitType}
style={{
flexGrow: 1,
...(splitType === "horizontal"
? { display: "flex", flexDirection: "row", alignItems: "stretch" }
: {}),
}}
onDragEnd={() => EventEmitter.dispatch("resize")}
>
{children}
</Split>
</>
);
};
export default Layouts;

View File

@ -19,6 +19,9 @@ function RijuTerminal() {
term.loadAddon(fitAddon); term.loadAddon(fitAddon);
window.addEventListener("resize", () => fitAddon.fit()); window.addEventListener("resize", () => fitAddon.fit());
EventEmitter.subscribe("resize", () => {
fitAddon.fit();
});
EventEmitter.subscribe("terminal", (payload) => { EventEmitter.subscribe("terminal", (payload) => {
if (!payload) return; if (!payload) return;
const { type, data } = payload; const { type, data } = payload;
@ -40,7 +43,14 @@ function RijuTerminal() {
}, []); }, []);
return ( return (
<Box id="riju-term" sx={{ height: `calc(100% - 8px)`, mt: 1, ml: 2 }} /> <Box
id="riju-term"
sx={{
height: "100%",
width: "100%",
backgroundColor: "#292D3E",
}}
/>
); );
} }

View File

@ -1,13 +1,30 @@
import MonacoEditor, { useMonaco } from "@monaco-editor/react"; import MonacoEditor, { useMonaco } from "@monaco-editor/react";
import { Circle, Code as Format, Home, PlayArrow } from "@mui/icons-material"; import {
Circle,
Code as Format,
Home,
HorizontalSplit,
PlayArrow,
VerticalSplit,
} from "@mui/icons-material";
import { LoadingButton } from "@mui/lab"; import { LoadingButton } from "@mui/lab";
import { Box, Button, Chip, Divider, Typography } from "@mui/material"; import {
Box,
Button,
Chip,
Divider,
Stack,
ToggleButton,
ToggleButtonGroup,
Typography,
} from "@mui/material";
import ansi from "ansicolor"; import ansi from "ansicolor";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import Head from "next/head"; import Head from "next/head";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { createMessageConnection } from "vscode-jsonrpc"; import { createMessageConnection } from "vscode-jsonrpc";
import Layouts from "../../components/Layouts";
import langs from "../../static/langs.json"; import langs from "../../static/langs.json";
import { EventEmitter } from "../../utils/EventEmitter"; import { EventEmitter } from "../../utils/EventEmitter";
ansi.rgb = { ansi.rgb = {
@ -27,12 +44,14 @@ const CodeRunner = (props) => {
const router = useRouter(); const router = useRouter();
const { langConfig } = props; const { langConfig } = props;
const editorRef = useRef(null); const editorRef = useRef(null);
const paneRef = useRef(null);
const [config, setConfig] = useState(langConfig); const [config, setConfig] = useState(langConfig);
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const [isRunning, setRunning] = useState(false); const [isRunning, setRunning] = useState(false);
const [isFormatting, setFormatting] = useState(false); const [isFormatting, setFormatting] = useState(false);
const [isLspStarted, setLspStarted] = useState(false); const [isLspStarted, setLspStarted] = useState(false);
const [isLspRequested, setIsLspRequested] = useState(false); const [isLspRequested, setIsLspRequested] = useState(false);
const [splitType, setSplitType] = useState("horizontal");
const monaco = useMonaco(); const monaco = useMonaco();
const [status, setStatus] = useState("connecting"); const [status, setStatus] = useState("connecting");
@ -233,8 +252,6 @@ const CodeRunner = (props) => {
case "lsp": case "lsp":
setLspStarted(false); setLspStarted(false);
setIsLspRequested(false); setIsLspRequested(false);
// lspButton.classList.add("is-light");
// lspButtonState.innerText = "CRASHED";
break; break;
case "terminal": case "terminal":
sendToTerminal( sendToTerminal(
@ -307,13 +324,42 @@ const CodeRunner = (props) => {
showValue(); showValue();
}, },
}); });
// editor.getModel().onDidChangeContent(() => recordActivity());
// window.addEventListener("resize", () => editor.layout());
editor.getModel().setValue(config.template + "\n"); editor.getModel().setValue(config.template + "\n");
monaco.editor.setModelLanguage( monaco.editor.setModelLanguage(
editor.getModel(), editor.getModel(),
config.monacoLang || "plaintext" config.monacoLang || "plaintext"
); );
// Below code is just for adding an empty line in editor
monaco.languages.registerCodeLensProvider(
config.monacoLang || "plaintext",
{
provideCodeLenses: function (model, token) {
return {
lenses: [
{
range: {
startLineNumber: 1,
startColumn: 1,
endLineNumber: 2,
endColumn: 1,
},
id: "Format",
command: {
// id: commandId,
// title: "Format",
title: "",
},
},
],
dispose: () => {},
};
},
resolveCodeLens: function (model, codeLens, token) {
return codeLens;
},
}
);
setMounted(true); setMounted(true);
} }
@ -338,6 +384,17 @@ const CodeRunner = (props) => {
} }
}; };
const handleLayout = (event, value) => {
const e = document.querySelector(".split .gutter");
e.classList.replace(`gutter-${splitType}`, `gutter-${value}`);
const es = document.querySelectorAll(".split .panel");
for (const e of es) {
e.removeAttribute("style");
e.removeAttribute("style");
}
setSplitType(value);
};
return ( return (
<> <>
<Head> <Head>
@ -352,25 +409,20 @@ const CodeRunner = (props) => {
content="minimum-scale=1, initial-scale=1, width=device-width" content="minimum-scale=1, initial-scale=1, width=device-width"
/> />
</Head> </Head>
<Box <Stack
sx={{ direction="column"
display: "flex", sx={{ height: "100vh", bgcolor: "white" }}
flexDirection: "column", alignItems="stretch"
height: "100vh",
bgcolor: "#fff",
}}
component="main"
> >
<Box <Stack
direction="row"
alignItems="stretch"
sx={{ sx={{
display: "flex", boxShadow: `0 2px 4px rgb(0 0 0 / 10%)`,
flexDirection: "row", zIndex: (t) => t.zIndex.appBar,
alignItems: "stretch",
boxShadow: `0 2px 4px rgb(0 0 0 / 2%)`,
width: "60%",
}} }}
> >
<Box sx={{ flexGrow: 1, display: "flex", alignItems: "center" }}> <Stack direction="row" sx={{ flexGrow: 1 }} alignItems="stretch">
<Button <Button
variant="contained" variant="contained"
sx={{ borderRadius: 0, minWidth: 0 }} sx={{ borderRadius: 0, minWidth: 0 }}
@ -383,7 +435,10 @@ const CodeRunner = (props) => {
> >
<Home fontSize={"small"} /> <Home fontSize={"small"} />
</Button> </Button>
<Typography sx={{ fontSize: 14, px: 2, fontWeight: 600 }}> <Typography
sx={{ fontSize: 14, px: 2, fontWeight: 600, alignSelf: "center" }}
textAlign="center"
>
{config.name} {config.name}
</Typography> </Typography>
<Chip <Chip
@ -397,7 +452,7 @@ const CodeRunner = (props) => {
}} }}
label={status} label={status}
/> />
</Box> </Stack>
<LoadingButton <LoadingButton
onClick={handleLspClick} onClick={handleLspClick}
size="small" size="small"
@ -423,6 +478,31 @@ const CodeRunner = (props) => {
> >
<Typography sx={{ fontSize: 12 }}>Autocomplete</Typography> <Typography sx={{ fontSize: 12 }}>Autocomplete</Typography>
</LoadingButton> </LoadingButton>
<ToggleButtonGroup
size="small"
value={splitType}
color="primary"
exclusive
onChange={handleLayout}
aria-label="split type"
sx={{ mr: 1 }}
>
<ToggleButton
value="vertical"
aria-label="vertical split"
sx={{ borderRadius: 0 }}
>
<VerticalSplit fontSize="small" />
</ToggleButton>
<ToggleButton
value="horizontal"
aria-label="horizontal split"
sx={{ borderRadius: 0 }}
>
<HorizontalSplit fontSize="small" />
</ToggleButton>
</ToggleButtonGroup>
<LoadingButton <LoadingButton
onClick={sendFormat} onClick={sendFormat}
loading={isFormatting} loading={isFormatting}
@ -451,26 +531,17 @@ const CodeRunner = (props) => {
> >
<Typography sx={{ fontSize: 12, color: "#fff" }}>Run</Typography> <Typography sx={{ fontSize: 12, color: "#fff" }}>Run</Typography>
</LoadingButton> </LoadingButton>
</Box> </Stack>
<Divider /> <Layouts splitType={splitType}>
<Box <Box className="panel editor">
sx={{ <MonacoEditor
display: "flex",
flexDirection: "row",
flexGrow: 1,
alignItems: "stretch",
}}
>
<Box sx={{ backgroundColor: "white", width: "60%" }}>
<Box
component={MonacoEditor}
wrapperClassName={"rijuEditor"} wrapperClassName={"rijuEditor"}
onChange={handleChange} onChange={handleChange}
height="90vh" // height="100vh"
defaultLanguage="javascript" defaultLanguage="javascript"
defaultValue="// some comment" defaultValue="// some comment"
options={{ options={{
minimap: { enabled: false }, minimap: { enabled: splitType == "horizontal" ? false : true },
scrollbar: { verticalScrollbarSize: 0 }, scrollbar: { verticalScrollbarSize: 0 },
fontLigatures: true, fontLigatures: true,
fontFamily: "Fira Code", fontFamily: "Fira Code",
@ -478,17 +549,11 @@ const CodeRunner = (props) => {
onMount={editorDidMount} onMount={editorDidMount}
/> />
</Box> </Box>
<Box <Box className="panel" sx={{ bgcolor: "#292D3E", p: 2 }}>
sx={{
overflow: "hidden",
backgroundColor: "#292D3E",
width: "40%",
}}
>
<RijuTerminal /> <RijuTerminal />
</Box> </Box>
</Box> </Layouts>
</Box> </Stack>
</> </>
); );
}; };

View File

@ -1,121 +0,0 @@
.container {
min-height: 100vh;
padding: 0 0.5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.main {
padding: 5rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.footer {
width: 100%;
height: 100px;
border-top: 1px solid #eaeaea;
display: flex;
justify-content: center;
align-items: center;
}
.footer a {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}
.title a {
color: #0070f3;
text-decoration: none;
}
.title a:hover,
.title a:focus,
.title a:active {
text-decoration: underline;
}
.title {
margin: 0;
line-height: 1.15;
font-size: 4rem;
}
.title,
.description {
text-align: center;
}
.description {
line-height: 1.5;
font-size: 1.5rem;
}
.code {
background: #fafafa;
border-radius: 5px;
padding: 0.75rem;
font-size: 1.1rem;
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}
.grid {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
max-width: 800px;
margin-top: 3rem;
}
.card {
margin: 1rem;
padding: 1.5rem;
text-align: left;
color: inherit;
text-decoration: none;
border: 1px solid #eaeaea;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;
width: 45%;
}
.card:hover,
.card:focus,
.card:active {
color: #0070f3;
border-color: #0070f3;
}
.card h2 {
margin: 0 0 1rem 0;
font-size: 1.5rem;
}
.card p {
margin: 0;
font-size: 1.25rem;
line-height: 1.5;
}
.logo {
height: 1em;
margin-left: 0.5rem;
}
@media (max-width: 600px) {
.grid {
width: 100%;
flex-direction: column;
}
}

View File

@ -20,6 +20,43 @@ a {
} }
.rijuEdutor { .rijuEdutor {
overflow: hidden; height: 100%;
height: calc(100% - 8px); width: 100%;
}
/* Split pane */
.split {
overflow: auto;
}
.split .panel {
overflow: auto;
}
.split .editor {
overflow: hidden;
}
.split .gutter {
background-color: #eee;
opacity: 1;
z-index: 1;
background-repeat: no-repeat;
background-position: 50%;
}
/* .split .gutter:hover {
opacity: 1;
-webkit-transition: all 2s ease;
transition: all 2s ease;
} */
.split .gutter.gutter-vertical {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=");
cursor: row-resize;
width: 100% !important;
}
.split .gutter.gutter-horizontal {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==");
cursor: col-resize;
height: 100% !important;
} }

View File

@ -51,6 +51,7 @@
"prettier": "^2.3.1", "prettier": "^2.3.1",
"react": "17.0.2", "react": "17.0.2",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"react-split": "^2.0.13",
"regenerator-runtime": "^0.13.7", "regenerator-runtime": "^0.13.7",
"setimmediate": "^1.0.5", "setimmediate": "^1.0.5",
"strip-ansi": "^6.0.0", "strip-ansi": "^6.0.0",

View File

@ -4787,7 +4787,7 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2: prop-types@15.7.2, prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -4952,6 +4952,14 @@ react-refresh@0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
react-split@^2.0.13:
version "2.0.13"
resolved "https://registry.yarnpkg.com/react-split/-/react-split-2.0.13.tgz#8d55fcb17edfd6cd2fb0203ab8324c02ec39a81a"
integrity sha512-suq/UH4epMu2aF4NBh+imlpUvntsIvU3li9EBBLdxqNtYEg+nY7TGl8Ij65mD1qYyhs3dQhA1Pv3rLXd1s5/lQ==
dependencies:
prop-types "^15.5.7"
split.js "^1.6.0"
react-transition-group@^4.4.2: react-transition-group@^4.4.2:
version "4.4.2" version "4.4.2"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
@ -5432,6 +5440,11 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies: dependencies:
extend-shallow "^3.0.0" extend-shallow "^3.0.0"
split.js@^1.6.0:
version "1.6.4"
resolved "https://registry.yarnpkg.com/split.js/-/split.js-1.6.4.tgz#13d47cba53382adef230a53294ce5dacb2a2f2e1"
integrity sha512-kYmQZprRJrF1IOjg/E+gdBEsKFv5kbgUE6RJVJZvrIzTOK/IHzKSqIeiJnWs7IP5D9TnpTQ2CbanuDuIWcyDUQ==
ssri@^6.0.1: ssri@^6.0.1:
version "6.0.2" version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"