From d76fabe294dfa981a55f8a4b02814e92ee7baf1c Mon Sep 17 00:00:00 2001 From: Sidharth Sethi <76687985+TechSpiritSS@users.noreply.github.com> Date: Thu, 22 Jun 2023 16:26:07 +0530 Subject: [PATCH] Added History, History-i, Clear --- src/containers/applications/apps/terminal.jsx | 628 ++++++++++-------- 1 file changed, 344 insertions(+), 284 deletions(-) diff --git a/src/containers/applications/apps/terminal.jsx b/src/containers/applications/apps/terminal.jsx index 78d1f4f43..db5ecf038 100644 --- a/src/containers/applications/apps/terminal.jsx +++ b/src/containers/applications/apps/terminal.jsx @@ -1,24 +1,36 @@ -import React, { useState, useEffect } from "react"; -import { useSelector, useDispatch } from "react-redux"; -import i18next from "i18next"; -import login from "../../../components/login"; +import React, { useState, useEffect } from 'react'; +import { useSelector, useDispatch } from 'react-redux'; +import i18next from 'i18next'; +import login from '../../../components/login'; -import { ToolBar } from "../../../utils/general"; -import dirs from "./assets/dir.json"; +import { ToolBar } from '../../../utils/general'; +import dirs from './assets/dir.json'; export const WnTerminal = () => { const wnapp = useSelector((state) => state.apps.terminal); - const [stack, setStack] = useState(["OS [Version 10.0.22000.51]", ""]); - const [pwd, setPwd] = useState("C:\\Users\\Blue"); + const [stack, setStack] = useState(['OS [Version 10.0.22000.51]', '']); + const [pwd, setPwd] = useState('C:\\Users\\Blue'); const [lastCmd, setLsc] = useState(0); - const [wntitle, setWntitle] = useState("Terminal"); + const [wntitle, setWntitle] = useState('Terminal'); const dispatch = useDispatch(); + const saveHistory = (value) => { + if (value === null || value === undefined || value == 'clear') return; + let record = JSON.parse(localStorage.getItem('history')) || []; + if (record.length > 9) { + record.shift(); + record.push(value); + } else { + record.push(value); + } + localStorage.setItem('history', JSON.stringify(record)); + }; + let IpDetails = []; const getIPDetails = async () => { try { - const response = await fetch("https://ipapi.co/json") + const response = await fetch('https://ipapi.co/json') .then((response) => response.json()) .then((data) => { IpDetails.push(data); @@ -27,28 +39,28 @@ export const WnTerminal = () => { console.log(error); // handling the error IpDetails.push({ - ip: "__network_error", - network: "__kindly check internet connection", - city: "", - region: "", - org: "", - postal: "", + ip: '__network_error', + network: '__kindly check internet connection', + city: '', + region: '', + org: '', + postal: '', }); } }; - const dirFolders = (isFile = "") => { + const dirFolders = (isFile = '') => { var tdir = { ...dirs }, - curr = pwd == "C:\\" ? [] : pwd.replace("C:\\", "").split("\\"); + curr = pwd == 'C:\\' ? [] : pwd.replace('C:\\', '').split('\\'); - if (pwd != "C:\\") { + if (pwd != 'C:\\') { for (var i = 0; i < curr.length; i++) { // console.log(tdir); tdir = tdir[curr[i]]; } } - if (isFile == "") { + if (isFile == '') { return Object.keys(tdir); } else { return tdir[isFile] || {}; @@ -57,252 +69,300 @@ export const WnTerminal = () => { const cmdTool = async (cmd) => { var tmpStack = [...stack]; - tmpStack.push(pwd + ">" + cmd); - var arr = cmd.split(" "), + tmpStack.push(pwd + '>' + cmd); + var arr = cmd.split(' '), type = arr[0].trim().toLowerCase(), - arg = arr.splice(1, arr.length).join(" ") || ""; + arg = arr.splice(1, arr.length).join(' ') || ''; arg = arg.trim(); - if (type == "echo") { - if (arg.length) { - tmpStack.push(arg); + const runSpecificHistoryCmd = (id) => { + let record = JSON.parse(localStorage.getItem('history')) || []; + if (id < 1 || id > record.length) { + tmpStack.push('No History Found for this id!'); } else { - tmpStack.push("ECHO is on."); + tmpStack.push(`Running command: ${record[id - 1]}`); + runCMD(record[id - 1]); } - } else if (type == "eval") { - if (arg.length) { - tmpStack.push(eval(arg).toString()); - } - } else if (type == "python") { - if (arg.length) { - if (window.pythonRunner) { - var content = await window.pythonRunner.runCode(arg); - if (window.pythonResult) { - window.pythonResult.split("\n").forEach((x) => { - if (x.trim().length) tmpStack.push(x); - }); + }; + + const runCMD = async (type) => { + if (type == 'echo') { + if (arg.length) { + tmpStack.push(arg); + } else { + tmpStack.push('ECHO is on.'); + } + } else if (type == 'eval') { + if (arg.length) { + tmpStack.push(eval(arg).toString()); + } + } else if (type == 'python') { + if (arg.length) { + if (window.pythonRunner) { + var content = await window.pythonRunner.runCode(arg); + if (window.pythonResult) { + window.pythonResult.split('\n').forEach((x) => { + if (x.trim().length) tmpStack.push(x); + }); + } } } - } - } else if (type == "cd") { - if (arg.length) { + } else if (type == 'cd') { + if (arg.length) { + var errp = true; + var curr = pwd == 'C:\\' ? [] : pwd.replace('C:\\', '').split('\\'); + + if (arg == '.') { + errp = false; + } else if (arg == '..') { + errp = false; + curr.pop(); + setPwd('C:\\' + curr.join('\\')); + } else if (!arg.includes('.')) { + var tdir = dirFolders(); + + for (var i = 0; i < tdir.length; i++) { + if (arg.toLowerCase() == tdir[i].toLowerCase() && errp) { + curr.push(tdir[i]); + errp = false; + setPwd('C:\\' + curr.join('\\')); + break; + } + } + } else { + errp = false; + tmpStack.push('The directory name is invalid.'); + } + + if (errp) { + tmpStack.push('The system cannot find the path specified.'); + } + } else { + tmpStack.push(pwd); + } + } else if (type == 'dir') { + tmpStack.push(' Directory of ' + pwd); + tmpStack.push(''); + tmpStack.push(' .'); + tmpStack.push(' ..'); + + var tdir = dirFolders(); + for (var i = 0; i < tdir.length; i++) { + if (!tdir[i].includes('.')) { + tmpStack.push('...' + tdir[i]); + } else { + tmpStack.push('FILE....' + tdir[i]); + } + } + } else if (type == 'cls') { + tmpStack = []; + } else if (type == 'color') { + let color = '#FFFFFF'; + let background = '#000000'; + let re = /^[A-Fa-f0-9]+$/g; + if (!arg || (arg.length < 3 && re.test(arg))) { + if (arg.length == 2) { + color = colorCode(arg[1]); + background = colorCode(arg[0]); + } else if (arg.length == 1) { + color = colorCode(arg[0]); + } + + //set background color of the element id cmdCont + var cmdcont = document.getElementById('cmdcont'); + cmdcont.style.backgroundColor = background; + + //set color of text of .cmdLine class + cmdcont.style.color = color; + } else { + tmpStack.push( + 'Set the color of the background and the text for the console.' + ); + tmpStack.push('COLOR [arg]'); + tmpStack.push('arg\t\tSpecifies the color for the console output'); + tmpStack.push( + 'The color attribute is a combination of the following values:' + ); + tmpStack.push('0\t\tBlack'); + tmpStack.push('1\t\tBlue'); + tmpStack.push('2\t\tGreen'); + tmpStack.push('3\t\tCyan'); + tmpStack.push('4\t\tRed'); + tmpStack.push('5\t\tMagenta'); + tmpStack.push('6\t\tBrown'); + tmpStack.push('7\t\tLight Gray'); + tmpStack.push('8\t\tDark Gray'); + tmpStack.push('9\t\tLight Blue'); + tmpStack.push('A\t\tLight Green'); + tmpStack.push('B\t\tLight Cyan'); + tmpStack.push('C\t\tLight Red'); + tmpStack.push('D\t\tLight Magenta'); + tmpStack.push('E\t\tYellow'); + tmpStack.push('F\t\tWhite'); + tmpStack.push( + 'Example: COLOR 0a for black text on a green background' + ); + } + } else if (type == 'type') { var errp = true; - var curr = pwd == "C:\\" ? [] : pwd.replace("C:\\", "").split("\\"); - - if (arg == ".") { - errp = false; - } else if (arg == "..") { - errp = false; - curr.pop(); - setPwd("C:\\" + curr.join("\\")); - } else if (!arg.includes(".")) { + + if (arg.includes('.')) { var tdir = dirFolders(); for (var i = 0; i < tdir.length; i++) { if (arg.toLowerCase() == tdir[i].toLowerCase() && errp) { - curr.push(tdir[i]); errp = false; - setPwd("C:\\" + curr.join("\\")); + var file = dirFolders(tdir[i]); + var content = file.content || ''; + content = content.split('\n'); + for (var i = 0; i < content.length; i++) { + tmpStack.push(content[i]); + } break; } } - } else { - errp = false; - tmpStack.push("The directory name is invalid."); } if (errp) { - tmpStack.push("The system cannot find the path specified."); - } - } else { - tmpStack.push(pwd); - } - } else if (type == "dir") { - tmpStack.push(" Directory of " + pwd); - tmpStack.push(""); - tmpStack.push(" ."); - tmpStack.push(" .."); - - var tdir = dirFolders(); - for (var i = 0; i < tdir.length; i++) { - if (!tdir[i].includes(".")) { - tmpStack.push("..." + tdir[i]); - } else { - tmpStack.push("FILE...." + tdir[i]); - } - } - } else if (type == "cls") { - tmpStack = []; - } else if (type == "color") { - let color = "#FFFFFF"; - let background = "#000000"; - let re = /^[A-Fa-f0-9]+$/g; - if (!arg || (arg.length < 3 && re.test(arg))) { - if (arg.length == 2) { - color = colorCode(arg[1]); - background = colorCode(arg[0]); - } else if (arg.length == 1) { - color = colorCode(arg[0]); + tmpStack.push('The system cannot find the file specified.'); } - - //set background color of the element id cmdCont - var cmdcont = document.getElementById("cmdcont"); - cmdcont.style.backgroundColor = background; - - //set color of text of .cmdLine class - cmdcont.style.color = color; - } else { + } else if (type == 'start') { + dispatch({ type: 'EDGELINK', payload: arg }); + } else if (type == 'date') { tmpStack.push( - "Set the color of the background and the text for the console." + 'The current date is: ' + new Date().toLocaleDateString() ); - tmpStack.push("COLOR [arg]"); - tmpStack.push("arg\t\tSpecifies the color for the console output"); + } else if (type == 'time') { tmpStack.push( - "The color attribute is a combination of the following values:" + 'The current time is: ' + + new Date() + .toLocaleTimeString('en-GB', { + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }) + .replaceAll(':', '.') + + '.' + + Math.floor(Math.random() * 100) ); - tmpStack.push("0\t\tBlack"); - tmpStack.push("1\t\tBlue"); - tmpStack.push("2\t\tGreen"); - tmpStack.push("3\t\tCyan"); - tmpStack.push("4\t\tRed"); - tmpStack.push("5\t\tMagenta"); - tmpStack.push("6\t\tBrown"); - tmpStack.push("7\t\tLight Gray"); - tmpStack.push("8\t\tDark Gray"); - tmpStack.push("9\t\tLight Blue"); - tmpStack.push("A\t\tLight Green"); - tmpStack.push("B\t\tLight Cyan"); - tmpStack.push("C\t\tLight Red"); - tmpStack.push("D\t\tLight Magenta"); - tmpStack.push("E\t\tYellow"); - tmpStack.push("F\t\tWhite"); - tmpStack.push("Example: COLOR 0a for black text on a green background"); - } - } else if (type == "type") { - var errp = true; - - if (arg.includes(".")) { - var tdir = dirFolders(); - - for (var i = 0; i < tdir.length; i++) { - if (arg.toLowerCase() == tdir[i].toLowerCase() && errp) { - errp = false; - var file = dirFolders(tdir[i]); - var content = file.content || ""; - content = content.split("\n"); - for (var i = 0; i < content.length; i++) { - tmpStack.push(content[i]); - } - break; - } + } else if (type == 'exit') { + tmpStack = ['OS [Version 10.0.22000.51]', '']; + dispatch({ type: wnapp.action, payload: 'close' }); + } else if (type == 'title') { + setWntitle(arg.length ? arg : 'Terminal'); + } else if (type == 'hostname') { + tmpStack.push('blue'); + } else if (type == 'login') { + login(); + tmpStack.push('started login'); + } else if (type == 'lang-test') { + i18next.changeLanguage('fr-FR'); + tmpStack.push('French'); + } else if (type == 'blue') { + tmpStack.push('blueedgetechno'); + } else if (type == 'dev') { + tmpStack.push('https://dev.blueedge.me/'); + } else if (type == 'ver') { + tmpStack.push('OS [Version 10.0.22000.51]'); + } else if (type == 'systeminfo') { + var dvInfo = [ + 'Host Name: BLUE', + 'OS Name: Win11React Dummys Edition', + 'OS Version: 10.0.22000 N/A Build 22000.51', + 'OS Manufacturer: ', + 'OS Configuration: Standalone Workstation', + 'OS Build Type: Multiprocessor Free', + 'Registered Owner: Blue', + 'Registered Organization: N/A', + 'Product ID: 7H1S1-5AP1R-473DV-3R5I0N', + ]; + + for (var i = 0; i < dvInfo.length; i++) { + tmpStack.push(dvInfo[i]); + } + } else if (type == 'help') { + var helpArr = [ + 'CD Displays the name of or changes the current directory.', + 'CLS Clears the screen.', + 'COLOR Sets the default console foreground and background colors.', + 'DATE Displays or sets the date.', + 'DIR Displays a list of files and subdirectories in a directory.', + 'ECHO Displays messages, or turns command echoing on or off.', + 'EXIT Quits the CMD.EXE program (command interpreter).', + 'HELP Provides Help information for Windows commands.', + 'IPCONFIG Displays all current TCP/IP network configuration values.', + 'START Starts a separate window to run a specified program or command.', + 'SYSTEMINFO Displays machine specific properties and configuration.', + 'TIME Displays or sets the system time.', + 'TITLE Sets the window title for a CMD.EXE session.', + 'TYPE Displays the contents of a text file.', + 'VER Displays the Windows version.', + 'PYTHON EXECUTE PYTHON CODE.', + 'EVAL RUNS JavaScript statements.', + 'HISTORY DISPLAYS COMMAND HISTORY.', + 'HISTORY-ID EXECUTES COMMAND FROM HISTORY.', + 'CLEAR CLEARS THE HISTORY.', + ]; + + for (var i = 0; i < helpArr.length; i++) { + tmpStack.push(helpArr[i]); + } + } else if (type == '') { + } else if (type == 'ipconfig') { + const IP = IpDetails[0]; + tmpStack.push('Windows IP Configuration'); + tmpStack.push(''); + tmpStack.push('IPv6: ' + IP.ip); + tmpStack.push('Network: ' + IP.network); + tmpStack.push('City: ' + IP.city); + tmpStack.push('Network Org: ' + IP.org); + tmpStack.push('Region: ' + IP.region); + tmpStack.push('Postal: ' + IP.postal); + } else if (type == 'history') { + let record = JSON.parse(localStorage.getItem('history')) || []; + if (record.length === 0) + tmpStack.push('No commands in history to display.'); + else { + record.forEach((item, index) => { + if (item !== null) tmpStack.push(`${index + 1}. ${item}`); + }); } } - - if (errp) { - tmpStack.push("The system cannot find the file specified."); - } - } else if (type == "start") { - dispatch({ type: "EDGELINK", payload: arg }); - } else if (type == "date") { - tmpStack.push("The current date is: " + new Date().toLocaleDateString()); - } else if (type == "time") { - tmpStack.push( - "The current time is: " + - new Date() - .toLocaleTimeString("en-GB", { - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - }) - .replaceAll(":", ".") + - "." + - Math.floor(Math.random() * 100) - ); - } else if (type == "exit") { - tmpStack = ["OS [Version 10.0.22000.51]", ""]; - dispatch({ type: wnapp.action, payload: "close" }); - } else if (type == "title") { - setWntitle(arg.length ? arg : "Terminal"); - } else if (type == "hostname") { - tmpStack.push("blue"); - } else if (type == "login") { - login(); - tmpStack.push("started login"); - } else if (type == "lang-test") { - i18next.changeLanguage("fr-FR"); - tmpStack.push("French"); - } else if (type == "blue") { - tmpStack.push("blueedgetechno"); - } else if (type == "dev") { - tmpStack.push("https://dev.blueedge.me/"); - } else if (type == "ver") { - tmpStack.push("OS [Version 10.0.22000.51]"); - } else if (type == "systeminfo") { - var dvInfo = [ - "Host Name: BLUE", - "OS Name: Win11React Dummys Edition", - "OS Version: 10.0.22000 N/A Build 22000.51", - "OS Manufacturer: ", - "OS Configuration: Standalone Workstation", - "OS Build Type: Multiprocessor Free", - "Registered Owner: Blue", - "Registered Organization: N/A", - "Product ID: 7H1S1-5AP1R-473DV-3R5I0N", - ]; - - for (var i = 0; i < dvInfo.length; i++) { - tmpStack.push(dvInfo[i]); - } - } else if (type == "help") { - var helpArr = [ - "CD Displays the name of or changes the current directory.", - "CLS Clears the screen.", - "COLOR Sets the default console foreground and background colors.", - "DATE Displays or sets the date.", - "DIR Displays a list of files and subdirectories in a directory.", - "ECHO Displays messages, or turns command echoing on or off.", - "EXIT Quits the CMD.EXE program (command interpreter).", - "HELP Provides Help information for Windows commands.", - "START Starts a separate window to run a specified program or command.", - "SYSTEMINFO Displays machine specific properties and configuration.", - "TIME Displays or sets the system time.", - "TITLE Sets the window title for a CMD.EXE session.", - "TYPE Displays the contents of a text file.", - "VER Displays the Windows version.", - "PYTHON EXECUTE PYTHON CODE.", - "EVAL RUNS JavaScript statements.", - ]; - - for (var i = 0; i < helpArr.length; i++) { - tmpStack.push(helpArr[i]); + // history id + else if (type.includes('history')) { + const id = type.split('-')[1]; + let record = JSON.parse(localStorage.getItem('history')) || []; + if (record.length === 0) + tmpStack.push('No commands in history to display.'); + else runSpecificHistoryCmd(id); + } else if (type === 'clear') { + localStorage.removeItem('history'); + setStack(['']); + setLsc(0); + } else { + tmpStack.push( + `'${type}' is not recognized as an internal or external command,` + ); + tmpStack.push('operable program or batch file.'); + tmpStack.push(''); + tmpStack.push('Type "help" for available commands'); } - } else if (type == "") { - } else if (type == "ipconfig") { - const IP = IpDetails[0]; - tmpStack.push("Windows IP Configuration"); - tmpStack.push(""); - tmpStack.push("IPv6: " + IP.ip); - tmpStack.push("Network: " + IP.network); - tmpStack.push("City: " + IP.city); - tmpStack.push("Network Org: " + IP.org); - tmpStack.push("Region: " + IP.region); - tmpStack.push("Postal: " + IP.postal); - } else { - tmpStack.push( - `'${type}' is not recognized as an internal or external command,` - ); - tmpStack.push("operable program or batch file."); - tmpStack.push(""); - tmpStack.push('Type "help" for available commands'); - } + }; - if (type.length > 0) tmpStack.push(""); + runCMD(type); + + if (type.length > 0) tmpStack.push(''); setStack(tmpStack); }; + useEffect(() => { + let x = stack[lastCmd - 1]?.split('>'); + if (x) saveHistory(x[1]); + }, [stack, lastCmd]); + const colorCode = (color) => { - let code = "#000000"; + let code = '#000000'; /* 0: Black 1: Blue @@ -323,53 +383,53 @@ export const WnTerminal = () => { */ switch (color.toUpperCase()) { - case "0": - code = "#000000"; + case '0': + code = '#000000'; break; - case "1": - code = "#0000AA"; + case '1': + code = '#0000AA'; break; - case "2": - code = "#00AA00"; + case '2': + code = '#00AA00'; break; - case "3": - code = "#00AAAA"; + case '3': + code = '#00AAAA'; break; - case "4": - code = "#AA0000"; + case '4': + code = '#AA0000'; break; - case "5": - code = "#AA00AA"; + case '5': + code = '#AA00AA'; break; - case "6": - code = "#AA5500"; + case '6': + code = '#AA5500'; break; - case "7": - code = "#AAAAAA"; + case '7': + code = '#AAAAAA'; break; - case "8": - code = "#555555"; + case '8': + code = '#555555'; break; - case "9": - code = "#5555FF"; + case '9': + code = '#5555FF'; break; - case "A": - code = "#55FF55"; + case 'A': + code = '#55FF55'; break; - case "B": - code = "#55FFFF"; + case 'B': + code = '#55FFFF'; break; - case "C": - code = "#FF5555"; + case 'C': + code = '#FF5555'; break; - case "D": - code = "#FF55FF"; + case 'D': + code = '#FF55FF'; break; - case "E": - code = "#FFFF55"; + case 'E': + code = '#FFFF55'; break; - case "F": - code = "#FFFFFF"; + case 'F': + code = '#FFFFFF'; break; } @@ -377,46 +437,46 @@ export const WnTerminal = () => { }; const action = (event) => { - var cmdline = document.getElementById("curcmd"); + var cmdline = document.getElementById('curcmd'); var action = event.target.dataset.action; if (cmdline) { - if (action == "hover") { + if (action == 'hover') { var crline = cmdline.parentNode; - var cmdcont = document.getElementById("cmdcont"); + var cmdcont = document.getElementById('cmdcont'); if (crline && cmdcont) { cmdcont.scrollTop = crline.offsetTop; } cmdline.focus(); - } else if (action == "enter") { - if (event.key == "Enter") { + } else if (action == 'enter') { + if (event.key == 'Enter') { event.preventDefault(); var tmpStack = [...stack]; var cmd = event.target.innerText.trim(); - event.target.innerText = ""; + event.target.innerText = ''; setLsc(tmpStack.length + 1); cmdTool(cmd); - } else if (event.key == "ArrowUp" || event.key == "ArrowDown") { + } else if (event.key == 'ArrowUp' || event.key == 'ArrowDown') { event.preventDefault(); - var i = lastCmd + [1, -1][Number(event.key == "ArrowUp")]; + var i = lastCmd + [1, -1][Number(event.key == 'ArrowUp')]; while (i >= 0 && i < stack.length) { - if (stack[i].startsWith("C:\\") && stack[i].includes(">")) { - var tp = stack[i].split(">"); - event.target.innerText = tp[1] || ""; + if (stack[i].startsWith('C:\\') && stack[i].includes('>')) { + var tp = stack[i].split('>'); + event.target.innerText = tp[1] || ''; setLsc(i); break; } - i += [1, -1][Number(event.key == "ArrowUp")]; + i += [1, -1][Number(event.key == 'ArrowUp')]; } cmdline.focus(); - } else if (event.key == "Tab") { + } else if (event.key == 'Tab') { event.preventDefault(); var cmd = event.target.innerText.trim(), - arr = cmd.split(" "); - var arg = arr.splice(1, arr.length).join(" ") || ""; + arr = cmd.split(' '); + var arg = arr.splice(1, arr.length).join(' ') || ''; var tdir = dirFolders(); for (var i = 0; i < tdir.length; i++) { @@ -424,7 +484,7 @@ export const WnTerminal = () => { arg.length && tdir[i].toLowerCase().startsWith(arg.toLowerCase()) ) { - event.target.innerText = arr[0] + " " + tdir[i]; + event.target.innerText = arr[0] + ' ' + tdir[i]; break; } } @@ -439,7 +499,7 @@ export const WnTerminal = () => { if (wnapp.dir && wnapp.dir != pwd) { setPwd(wnapp.dir); - dispatch({ type: "OPENTERM", payload: null }); + dispatch({ type: 'OPENTERM', payload: null }); } }); @@ -449,11 +509,11 @@ export const WnTerminal = () => { data-size={wnapp.size} data-max={wnapp.max} style={{ - ...(wnapp.size == "cstm" ? wnapp.dim : null), + ...(wnapp.size == 'cstm' ? wnapp.dim : null), zIndex: wnapp.z, }} data-hide={wnapp.hide} - id={wnapp.icon + "App"} + id={wnapp.icon + 'App'} >