diff --git a/bun.lock b/bun.lock index 2d90eef..3d2c36b 100644 --- a/bun.lock +++ b/bun.lock @@ -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=="], diff --git a/front/Tabs/Project.ts b/front/Tabs/Project.ts index 8d05878..8bb0d6f 100644 --- a/front/Tabs/Project.ts +++ b/front/Tabs/Project.ts @@ -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}` ); }; diff --git a/front/Tabs/Projects.ts b/front/Tabs/Projects.ts index 6ea4813..9c029e9 100644 --- a/front/Tabs/Projects.ts +++ b/front/Tabs/Projects.ts @@ -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,14 @@ 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}${newLine}${projectsComponents.join(newLine)}`, }); }; export default Projects; diff --git a/front/Tabs/TabRouter.ts b/front/Tabs/TabRouter.ts index a2f53be..8c3d2cf 100644 --- a/front/Tabs/TabRouter.ts +++ b/front/Tabs/TabRouter.ts @@ -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 }); } diff --git a/front/index.ts b/front/index.ts index da8d68d..f376c5d 100644 --- a/front/index.ts +++ b/front/index.ts @@ -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 })}` ); }; diff --git a/index.ts b/index.ts index 405fb95..d59673c 100644 --- a/index.ts +++ b/index.ts @@ -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) => { diff --git a/package.json b/package.json index 3fa027b..2bcb70b 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,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" } } \ No newline at end of file diff --git a/wrapers/qr-code-wraper.ts b/wrapers/qr-code-wraper.ts new file mode 100644 index 0000000..2eaaa92 --- /dev/null +++ b/wrapers/qr-code-wraper.ts @@ -0,0 +1,14 @@ +import qrcode from "qrcode-terminal"; +import { newLine } from "../front"; + +const generateQRCode = (text: string): Promise => { + 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;