Compare commits

...

3 commits

9 changed files with 65 additions and 27 deletions

View file

@ -4,8 +4,10 @@
"": {
"name": "bun-ssh-portfolio",
"dependencies": {
"@types/qrcode-terminal": "^0.12.2",
"@types/ssh2": "^1.15.4",
"ansi-escapes": "^7.0.0",
"qrcode-terminal": "^0.12.0",
"ssh2": "^1.16.0",
},
"devDependencies": {
@ -21,6 +23,8 @@
"@types/node": ["@types/node@18.19.80", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-kEWeMwMeIvxYkeg1gTc01awpwLbfMRZXdIhwRcakd/KlK53jmRC26LqcbIt7fnAQTu5GzlnWmzA3H6+l1u6xxQ=="],
"@types/qrcode-terminal": ["@types/qrcode-terminal@0.12.2", "", {}, "sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q=="],
"@types/ssh2": ["@types/ssh2@1.15.4", "", { "dependencies": { "@types/node": "^18.11.18" } }, "sha512-9JTQgVBWSgq6mAen6PVnrAmty1lqgCMvpfN+1Ck5WRUsyMYPa6qd50/vMJ0y1zkGpOEgLzm8m8Dx/Y5vRouLaA=="],
"@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="],
@ -41,6 +45,8 @@
"nan": ["nan@2.22.2", "", {}, "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ=="],
"qrcode-terminal": ["qrcode-terminal@0.12.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ=="],
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
"ssh2": ["ssh2@1.16.0", "", { "dependencies": { "asn1": "^0.2.6", "bcrypt-pbkdf": "^1.0.2" }, "optionalDependencies": { "cpu-features": "~0.0.10", "nan": "^2.20.0" } }, "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg=="],

View file

@ -8,6 +8,8 @@ interface ContactProps {
const Contact = ({ width, height }: ContactProps) => {
return (
`${newLine}` +
` Use ⌘/ctrl+click to open the links below!${newLine}` +
`${newLine}` +
` Email: ${link("contact@jokinsuares.fr", "mailto:contact@jokinsuares.fr")}${newLine}` +
` Phone: ${link("+33 6 02 26 22 00", "tel:+33602262200")}${newLine}` +

View file

@ -1,5 +1,6 @@
import { link } from "ansi-escapes";
import { newLine } from "..";
import generateQRCode from "../../wrapers/qr-code-wraper";
interface ProjectProps {
title: string;
@ -8,7 +9,7 @@ interface ProjectProps {
learnMoreLink: string;
}
const Project = ({ title, description, technologies, learnMoreLink }: ProjectProps) => {
const Project = async ({ title, description, technologies, learnMoreLink }: ProjectProps) => {
return (
` ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓${newLine}` +
`\x1b[33m${title.padEnd(80 - 4)}\x1b[0m ┃${newLine}` +
@ -24,6 +25,10 @@ const Project = ({ title, description, technologies, learnMoreLink }: ProjectPro
" \x1b[32mLearn more\x1b[0m ",
learnMoreLink
)}${newLine}` +
(await generateQRCode(learnMoreLink))
.split(newLine)
.map((line) => `${line.padEnd(57 - 4).padStart(80 - 4)}${newLine}`)
.join("") +
` ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛${newLine}`
);
};

View file

@ -9,7 +9,7 @@ interface ProjectsProps {
scrollPosition: number;
}
const Projects = ({ width, height, scrollPosition }: ProjectsProps) => {
const Projects = async ({ width, height, scrollPosition }: ProjectsProps) => {
const projects: ProjectProps[] = [
{
title: "Algoforge",
@ -52,13 +52,18 @@ const Projects = ({ width, height, scrollPosition }: ProjectsProps) => {
learnMoreLink: "https://github.com/Feror-BotMaker/sh-chat",
},
];
const projectsComponents = await Promise.all(projects.map(async (project) => await Project(project)));
return ScrollComponent({
width,
height,
scrollPosition,
text: ` Use the arrows keys to navigate up and down.${newLine}${newLine}${projects
.map((project) => Project(project))
.join(newLine)}`,
text:
` Use the arrows keys to navigate up and down.${newLine}` +
` You can either ⌘/ctrl click a link to open it, or scan the QR code below it.${newLine}` +
`${newLine}` +
`${projectsComponents.join(newLine)}`,
});
};
export default Projects;

View file

@ -9,12 +9,12 @@ interface TabRouterProps {
scrollPosition: number;
}
const TabRouter = ({ width, height, selectedTab, scrollPosition }: TabRouterProps) => {
const TabRouter = async ({ width, height, selectedTab, scrollPosition }: TabRouterProps) => {
switch (selectedTab) {
case "About":
return About({ width, height, scrollPosition });
case "Projects":
return Projects({ width, height, scrollPosition });
return await Projects({ width, height, scrollPosition });
case "Contact":
return Contact({ width, height });
}

View file

@ -22,14 +22,14 @@ const terminalTooSmall = (width: number, height: number) => {
);
};
const Front = ({ columns, rows, selectedTab, scrollPosition }: FrontProps) => {
const Front = async ({ columns, rows, selectedTab, scrollPosition }: FrontProps) => {
if (columns < minimumWidth || rows < minimumHeight) {
return terminalTooSmall(columns, rows);
}
return (
`${Header({ width: columns, height: 3 })}${newLine}` +
`${Categories({ width: columns, height: 3, selectedTab })}${newLine}` +
`${TabRouter({ width: columns, height: rows - 6, selectedTab, scrollPosition })}`
`${await TabRouter({ width: columns, height: rows - 6, selectedTab, scrollPosition })}`
);
};

View file

@ -82,7 +82,7 @@ const server = new Server(
contactFormSelectedField: "name",
};
const render = () => {
const render = async () => {
userWindow.stream?.write(eraseScreen);
userWindow.stream?.write(cursorTo(0, 0));
userWindow.stream?.write(cursorHide);
@ -90,7 +90,7 @@ const server = new Server(
userWindow.stream?.write(ContactForm(userWindow));
return;
}
userWindow.stream?.write(Front(userWindow));
userWindow.stream?.write(await Front(userWindow));
};
session.on("pty", (accept, reject, info) => {

View file

@ -3,6 +3,10 @@
"module": "index.ts",
"type": "module",
"private": true,
"scripts": {
"start": "bun index.ts",
"dev": "bun --watch ."
},
"devDependencies": {
"@types/bun": "latest"
},
@ -10,8 +14,10 @@
"typescript": "^5"
},
"dependencies": {
"@types/qrcode-terminal": "^0.12.2",
"@types/ssh2": "^1.15.4",
"ansi-escapes": "^7.0.0",
"qrcode-terminal": "^0.12.0",
"ssh2": "^1.16.0"
}
}

14
wrapers/qr-code-wraper.ts Normal file
View file

@ -0,0 +1,14 @@
import qrcode from "qrcode-terminal";
import { newLine } from "../front";
const generateQRCode = (text: string): Promise<string> => {
return new Promise((resolve, reject) => {
qrcode.generate(text, { small: true }, (qrCode) => {
// On va enlever les \n et les remplacer par des newLine
qrCode = qrCode.replace(/\n/g, newLine);
resolve(qrCode);
});
});
};
export default generateQRCode;