Added proper exit
This commit is contained in:
parent
360c0fd579
commit
c9d7a74ebc
2 changed files with 57 additions and 80 deletions
11
src/app/commands/exit.tsx
Normal file
11
src/app/commands/exit.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
const exitCommand = (setInputDisabled: (value: boolean) => void, setOutput: (value: JSX.Element[]) => void) => {
|
||||||
|
setInputDisabled(true); // Disable further input
|
||||||
|
setOutput([
|
||||||
|
<div key="exit" className="text-red-400">
|
||||||
|
Terminal exited. Refresh the page to restart. 🚀
|
||||||
|
</div>,
|
||||||
|
]);
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export default exitCommand;
|
|
@ -12,35 +12,33 @@ const Terminal: React.FC = () => {
|
||||||
const [output, setOutput] = useState<JSX.Element[]>([<MOTD key="motd" />]);
|
const [output, setOutput] = useState<JSX.Element[]>([<MOTD key="motd" />]);
|
||||||
const [history, setHistory] = useState<string[]>([]);
|
const [history, setHistory] = useState<string[]>([]);
|
||||||
const [historyIndex, setHistoryIndex] = useState<number | null>(null);
|
const [historyIndex, setHistoryIndex] = useState<number | null>(null);
|
||||||
const [suggestion, setSuggestion] = useState<string | null>(null); // For live suggestions
|
const [suggestion, setSuggestion] = useState<string | null>(null);
|
||||||
|
const [inputDisabled, setInputDisabled] = useState(false); // Disable input after exit
|
||||||
|
|
||||||
const terminalEndRef = useRef<HTMLDivElement>(null);
|
const terminalEndRef = useRef<HTMLDivElement>(null);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const commandsList = ["help", "socials", "exit", "selfhosted"];
|
const commandsList = ["help", "socials", "exit", "selfhosted"];
|
||||||
useEffect(() => {
|
|
||||||
window.scrollTo(0, 0); // Automatically scroll to the top
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
|
|
||||||
const handleInput = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleInput = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// If the input is empty, add a blank line
|
if (inputDisabled) return; // Prevent handling input if disabled
|
||||||
|
|
||||||
if (input.trim() === "") {
|
if (input.trim() === "") {
|
||||||
setOutput((prev) => [
|
setOutput((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
<div key={`blank-${prev.length}`}> </div>, // Blank line
|
<div key={`blank-${prev.length}`}> </div>,
|
||||||
]);
|
]);
|
||||||
setInput(""); // Clear the input field
|
setInput("");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizedInput = input.toLowerCase();
|
const normalizedInput = input.toLowerCase();
|
||||||
const commands: { [key: string]: () => JSX.Element[] } = {
|
const commands: { [key: string]: (setInputDisabled: any, setOutput: any) => JSX.Element[] } = {
|
||||||
help: helpCommand,
|
help: helpCommand,
|
||||||
socials: socialsCommand,
|
socials: socialsCommand,
|
||||||
exit: exitCommand,
|
exit: () => exitCommand(setInputDisabled, setOutput), // Pass control functions
|
||||||
selfhosted: selfhostedCommand,
|
selfhosted: selfhostedCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,53 +53,12 @@ const Terminal: React.FC = () => {
|
||||||
setHistory((prev) => [...prev, input]);
|
setHistory((prev) => [...prev, input]);
|
||||||
setHistoryIndex(null);
|
setHistoryIndex(null);
|
||||||
setInput("");
|
setInput("");
|
||||||
setSuggestion(null); // Clear suggestion after submission
|
setSuggestion(null);
|
||||||
};
|
|
||||||
|
|
||||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
||||||
if (e.key === "Tab") {
|
|
||||||
e.preventDefault(); // Prevent browser default behavior
|
|
||||||
if (suggestion) {
|
|
||||||
setInput(suggestion);
|
|
||||||
setSuggestion(null); // Clear suggestion after Tab
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (history.length === 0) return;
|
|
||||||
|
|
||||||
if (e.key === "ArrowUp") {
|
|
||||||
e.preventDefault();
|
|
||||||
if (historyIndex === null) {
|
|
||||||
setHistoryIndex(history.length - 1);
|
|
||||||
setInput(history[history.length - 1]);
|
|
||||||
} else if (historyIndex > 0) {
|
|
||||||
setHistoryIndex((prev) => {
|
|
||||||
const newIndex = prev! - 1;
|
|
||||||
setInput(history[newIndex]);
|
|
||||||
return newIndex;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === "ArrowDown") {
|
|
||||||
e.preventDefault();
|
|
||||||
if (historyIndex !== null && historyIndex < history.length - 1) {
|
|
||||||
setHistoryIndex((prev) => {
|
|
||||||
const newIndex = prev! + 1;
|
|
||||||
setInput(history[newIndex]);
|
|
||||||
return newIndex;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setHistoryIndex(null);
|
|
||||||
setInput("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputChange = (value: string) => {
|
const handleInputChange = (value: string) => {
|
||||||
setInput(value);
|
setInput(value);
|
||||||
|
|
||||||
// Suggest commands dynamically
|
|
||||||
const normalizedInput = value.toLowerCase();
|
const normalizedInput = value.toLowerCase();
|
||||||
const matchedCommand = commandsList.find((command) =>
|
const matchedCommand = commandsList.find((command) =>
|
||||||
command.startsWith(normalizedInput)
|
command.startsWith(normalizedInput)
|
||||||
|
@ -125,8 +82,14 @@ const Terminal: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={handleInput} className="flex items-center mt-2 relative">
|
<form
|
||||||
|
onSubmit={handleInput}
|
||||||
|
className="flex items-center mt-2 relative"
|
||||||
|
>
|
||||||
|
{!inputDisabled && ( // Hide the prompt if input is disabled
|
||||||
<span className="text-green-500">$</span>
|
<span className="text-green-500">$</span>
|
||||||
|
)}
|
||||||
|
{!inputDisabled && (
|
||||||
<div className="relative flex-1 ml-2">
|
<div className="relative flex-1 ml-2">
|
||||||
<input
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
@ -134,8 +97,8 @@ const Terminal: React.FC = () => {
|
||||||
className="bg-black text-white outline-none w-full"
|
className="bg-black text-white outline-none w-full"
|
||||||
value={input}
|
value={input}
|
||||||
onChange={(e) => handleInputChange(e.target.value)}
|
onChange={(e) => handleInputChange(e.target.value)}
|
||||||
onKeyDown={handleKeyDown}
|
|
||||||
autoFocus
|
autoFocus
|
||||||
|
disabled={inputDisabled} // Disable input when exited
|
||||||
/>
|
/>
|
||||||
{suggestion && input.trim() !== suggestion && (
|
{suggestion && input.trim() !== suggestion && (
|
||||||
<div
|
<div
|
||||||
|
@ -153,12 +116,15 @@ const Terminal: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div ref={terminalEndRef}></div>
|
<div ref={terminalEndRef}></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const MOTD = () => {
|
const MOTD = () => {
|
||||||
const socialsOutput = socialsCommand(false);
|
const socialsOutput = socialsCommand(false);
|
||||||
const selfHostedOutput = selfhostedCommand(false);
|
const selfHostedOutput = selfhostedCommand(false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue