ATC_SIMPLE/FRONTEND/src/components/Modal/ModalConfig.tsx

162 lines
4.2 KiB
TypeScript

import { useEffect, useRef, useState } from "react";
import { Modal, Button, ColorPicker, Group, Grid } from "@mantine/core";
import { Terminal } from "xterm";
import { FitAddon } from "@xterm/addon-fit";
interface Props {
opened: boolean;
onClose: () => void;
onSave: () => void;
}
export default function ModalConfig({ opened, onClose, onSave }: Props) {
const [color, setColor] = useState("#41ee4a");
const [loaded, setLoaded] = useState(false);
const xtermRef = useRef<HTMLDivElement>(null);
const terminal = useRef<Terminal>(null);
const fitRef = useRef<FitAddon>(null);
useEffect(() => {
// Load saved color from localStorage
const saved = localStorage.getItem("terminal-text-color");
if (saved) setColor(saved);
}, []);
const handleSave = () => {
localStorage.setItem("terminal-text-color", color);
onClose();
onSave();
};
useEffect(() => {
if (!loaded || fitRef.current || terminal.current || !xtermRef.current)
return;
const textColor = localStorage.getItem("terminal-text-color") || "#41ee4a";
terminal.current = new Terminal({
disableStdin: true,
cursorBlink: true,
convertEol: true,
fontFamily: "Consolas, 'Courier New', monospace",
fontSize: 12,
theme: {
background: "#000000",
foreground: textColor,
cursor: "#ffffff",
},
rows: 24,
cols: 80,
});
const fitAddon = new FitAddon();
fitRef.current = fitAddon;
terminal.current.loadAddon(fitAddon);
if (xtermRef.current) terminal.current.open(xtermRef.current);
terminal.current?.write(
"Change color \nChange color\nChange color\nChange color"
);
fitAddon.fit();
}, [loaded, xtermRef]);
useEffect(() => {
if (terminal.current && terminal.current.options.theme) {
terminal.current.options.theme = {
background: "#000000",
foreground: color,
cursor: "#ffffff",
};
}
}, [color]);
useEffect(() => {
if (opened) {
setTimeout(() => {
setLoaded(true);
}, 100);
} else {
setLoaded(false);
fitRef.current = null;
terminal.current = null;
const saved = localStorage.getItem("terminal-text-color");
if (saved) setColor(saved);
}
}, [opened]);
return (
<Modal
size={"xl"}
style={{ position: "absolute", left: 0 }}
opened={opened}
onClose={onClose}
title="Terminal Text Color"
>
<Grid>
<Grid.Col span={6}>
<Group>
<ColorPicker
format="hex"
value={color}
onChange={setColor}
fullWidth
withPicker={false}
swatches={[
"#ffffff",
"#41ee4a",
"#fa5252",
"#e64980",
"#be4bdb",
"#7950f2",
"#4c6ef5",
"#228be6",
"#15aabf",
"#12b886",
"#40c057",
"#82c91e",
"#fab005",
"#fd7e14",
]}
/>
<Button fullWidth onClick={handleSave}>
Save
</Button>
</Group>
</Grid.Col>
<Grid.Col span={6}>
<div
style={{
width: "100%",
height: "100%",
backgroundColor: "black",
paddingBottom: "4px",
maxHeight: "220px",
}}
>
<div
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
}}
ref={xtermRef}
style={{
width: "100%",
paddingLeft: "10px",
paddingBottom: "10px",
fontSize: "12px",
maxHeight: "220px",
height: "220px",
padding: "4px",
paddingRight: 0,
}}
onDoubleClick={(event) => {
event.preventDefault();
event.stopPropagation();
}}
/>
</div>
</Grid.Col>
</Grid>
</Modal>
);
}