Added neofetch command
This commit is contained in:
parent
24eb482da7
commit
922d01e583
6 changed files with 156 additions and 3 deletions
|
|
@ -53,6 +53,7 @@
|
||||||
"error",
|
"error",
|
||||||
"double"
|
"double"
|
||||||
],
|
],
|
||||||
|
"default-case": "off",
|
||||||
"jsdoc/no-undefined-types": "warn",
|
"jsdoc/no-undefined-types": "warn",
|
||||||
"jsdoc/require-param": "warn",
|
"jsdoc/require-param": "warn",
|
||||||
"jsdoc/check-tag-names": "warn",
|
"jsdoc/check-tag-names": "warn",
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,13 @@ const HOSTNAME = "prozilla-os";
|
||||||
* @param {string} props.text
|
* @param {string} props.text
|
||||||
*/
|
*/
|
||||||
function OutputLine({ text }) {
|
function OutputLine({ text }) {
|
||||||
return (
|
const lines = text?.split("\n");
|
||||||
<p className={styles.Output}>{text}</p>
|
|
||||||
);
|
return (<>
|
||||||
|
{lines.map((line, index) =>
|
||||||
|
<p key={index} className={styles.Output}>{line}</p>
|
||||||
|
)}
|
||||||
|
</>);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
text-align: start;
|
text-align: start;
|
||||||
|
white-space: break-spaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Input {
|
.Input {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,25 @@
|
||||||
|
import { START_DATE } from "../../../index.js";
|
||||||
|
import { formatRelativeTime } from "../../utils/date.js";
|
||||||
|
import ApplicationsManager from "../applications.js";
|
||||||
|
|
||||||
|
export const ASCII_LOGO = `
|
||||||
|
:.
|
||||||
|
-==.
|
||||||
|
.=====:
|
||||||
|
---::..:=======-.
|
||||||
|
:===+=----------::..
|
||||||
|
=+=---------------:..
|
||||||
|
--------------=-----:.
|
||||||
|
.:-+=---=*#*#*==*#*##=---.
|
||||||
|
:==+---=#%+=+%#+##**+=---:.
|
||||||
|
.=---=#%+=+%*+*++*%+---:.
|
||||||
|
==---=*###*==*###*=---.
|
||||||
|
==+-------------------:.
|
||||||
|
...::---------------:.
|
||||||
|
.::---------::..
|
||||||
|
....::...
|
||||||
|
`;
|
||||||
|
|
||||||
export class Command {
|
export class Command {
|
||||||
/**
|
/**
|
||||||
* @param {string} name
|
* @param {string} name
|
||||||
|
|
@ -125,5 +147,31 @@ export class Command {
|
||||||
new Command("hostname", (args, { hostname }) => {
|
new Command("hostname", (args, { hostname }) => {
|
||||||
return hostname;
|
return hostname;
|
||||||
}),
|
}),
|
||||||
|
new Command("neofetch", (args, { username, hostname }) => {
|
||||||
|
const leftColumn = ASCII_LOGO.split("\n");
|
||||||
|
const rightColumn = [
|
||||||
|
`${username}@${hostname}`,
|
||||||
|
"-".repeat(username.length + hostname.length + 1),
|
||||||
|
"OS: ProzillaOS",
|
||||||
|
`UPTIME: ${formatRelativeTime(START_DATE, 2, false)}`,
|
||||||
|
`RESOLUTION: ${window.innerWidth}x${window.innerHeight}`,
|
||||||
|
"THEME: default",
|
||||||
|
"ICONS: Font Awesome",
|
||||||
|
`TERMINAL: ${ApplicationsManager.getApplication("terminal")?.name ?? "Unknown"}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
const combined = [];
|
||||||
|
for (let i = 1; i < leftColumn.length - 1; i++) {
|
||||||
|
let line = `${leftColumn[i]} `;
|
||||||
|
|
||||||
|
if (i <= rightColumn.length) {
|
||||||
|
line += rightColumn[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
combined.push(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return combined.join("\n");
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
94
src/features/utils/date.js
Normal file
94
src/features/utils/date.js
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
const TIME_INDICATORS = {
|
||||||
|
"s": 1000,
|
||||||
|
"m": 1000 * 60,
|
||||||
|
"h": 1000 * 60 * 60,
|
||||||
|
"d": 1000 * 60 * 60 * 24,
|
||||||
|
"w": 1000 * 60 * 60 * 24 * 7,
|
||||||
|
"n": 1000 * 60 * 60 * 24 * 31,
|
||||||
|
"y": 1000 * 60 * 60 * 24 * 365,
|
||||||
|
"c": 1000 * 60 * 60 * 24 * 365 * 100
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a time
|
||||||
|
* @param {number} time - Time in milliseconds
|
||||||
|
* @param {number} maxLength - The maximum amount of units, e.g.: 3 => years, months, days
|
||||||
|
* @param {boolean} allowAffixes
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const formatTime = (time, maxLength = 3, allowAffixes) => {
|
||||||
|
const result = [];
|
||||||
|
|
||||||
|
const formatResult = (result, inPast) => {
|
||||||
|
if (!allowAffixes)
|
||||||
|
return result.join(", ");
|
||||||
|
|
||||||
|
let prefix = "";
|
||||||
|
let suffix = "";
|
||||||
|
|
||||||
|
if (inPast) {
|
||||||
|
suffix = "ago";
|
||||||
|
} else {
|
||||||
|
prefix = "in";
|
||||||
|
}
|
||||||
|
|
||||||
|
return [prefix, result.join(", "), suffix].join(" ").trim();
|
||||||
|
};
|
||||||
|
|
||||||
|
let inPast = false;
|
||||||
|
|
||||||
|
if (time < 0) {
|
||||||
|
time = -time;
|
||||||
|
inPast = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(time) < TIME_INDICATORS.s) {
|
||||||
|
return formatResult(["less than a second"], inPast);
|
||||||
|
}
|
||||||
|
|
||||||
|
const units = [];
|
||||||
|
const unitLabels = {
|
||||||
|
"s": "seconds",
|
||||||
|
"m": "minutes",
|
||||||
|
"h": "hours",
|
||||||
|
"d": "days",
|
||||||
|
"n": "months",
|
||||||
|
"y": "years",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(TIME_INDICATORS).reverse()) {
|
||||||
|
if (key === "w" || key === "c")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const amount = Math.floor(time / value);
|
||||||
|
time -= amount * value;
|
||||||
|
|
||||||
|
if (amount > 0)
|
||||||
|
units.push({ amount, label: unitLabels[key] });
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < maxLength; i++) {
|
||||||
|
const unit = units[i];
|
||||||
|
|
||||||
|
if (unit)
|
||||||
|
result.push(`${unit.amount} ${unit.label}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.length === 0) {
|
||||||
|
return formatResult(["less than a second"], inPast);
|
||||||
|
} else {
|
||||||
|
return formatResult(result, inPast);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a time relative to now
|
||||||
|
* @param {Date} date - The date
|
||||||
|
* @param {number} maxLength - The maximum amount of units, e.g.: 3 => years, months, days
|
||||||
|
* @param {boolean} allowAffixes
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export const formatRelativeTime = (date, maxLength = 3, allowAffixes) => {
|
||||||
|
const difference = date - new Date();
|
||||||
|
return formatTime(difference, maxLength, allowAffixes);
|
||||||
|
};
|
||||||
|
|
@ -3,6 +3,9 @@ import ReactDOM from "react-dom/client";
|
||||||
import "./styles/global.css";
|
import "./styles/global.css";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import reportWebVitals from "./reportWebVitals";
|
import reportWebVitals from "./reportWebVitals";
|
||||||
|
import { ASCII_LOGO } from "./features/applications/terminal/commands.js";
|
||||||
|
|
||||||
|
export const START_DATE = new Date();
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById("root"));
|
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||||
root.render(
|
root.render(
|
||||||
|
|
@ -11,6 +14,8 @@ root.render(
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log(ASCII_LOGO);
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
// If you want to start measuring performance in your app, pass a function
|
||||||
// to log results (for example: reportWebVitals(console.log))
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue