it works, but sideways
This commit is contained in:
11
src/main.cpp
11
src/main.cpp
@@ -1,6 +1,13 @@
|
||||
#include "portfolioapp.hpp"
|
||||
#include <ftxui/component/screen_interactive.hpp>
|
||||
#include <ftxui/dom/elements.hpp>
|
||||
#include <ftxui/dom/node.hpp>
|
||||
#include <ftxui/screen/screen.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
std::cout << "Hello, C++23 with Clang and submodules!\n";
|
||||
return 0;
|
||||
ftxui::ScreenInteractive screen = ftxui::ScreenInteractive::Fullscreen();
|
||||
ftxui::Component app = std::make_shared<PortfolioApp>();
|
||||
screen.Loop(app);
|
||||
return 0;
|
||||
}
|
||||
|
||||
175
src/portfolioapp.cpp
Normal file
175
src/portfolioapp.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
#include <ftxui/component/component.hpp>
|
||||
#include <ftxui/component/component_base.hpp>
|
||||
#include <ftxui/component/screen_interactive.hpp>
|
||||
#include <ftxui/dom/elements.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "portfolioapp.hpp"
|
||||
using namespace ftxui;
|
||||
|
||||
|
||||
|
||||
// ------------------
|
||||
// Pages
|
||||
// ------------------
|
||||
|
||||
Component MakeAboutPage() {
|
||||
std::string content =
|
||||
"Hi, I'm Krishna — cybersecurity and AI researcher.\n"
|
||||
"🔹 Rustacean | 🔹 CTF Red Teamer | 🔹 OSS Contributor\n\n"
|
||||
"Focus areas: Secure systems, ML accuracy, and privacy.";
|
||||
|
||||
return Renderer([content]() -> Element {
|
||||
return paragraph(content) | flex;
|
||||
});
|
||||
}
|
||||
|
||||
Component MakeProjectsPage() {
|
||||
std::vector<Project> projects = {
|
||||
{"🔐 VaultX — Stego-auth password vault", "https://github.com/krishna/vaultx"},
|
||||
{"🌐 P2PChat — Gossip-based secure chat", "https://github.com/krishna/p2pchat"},
|
||||
{"📊 Tenderlabs — Options research tool", ""},
|
||||
{"🛰️ SpaceData Viz — TUI telemetry monitor", "https://github.com/krishna/spacedata"}
|
||||
};
|
||||
|
||||
Component container = Container::Vertical({});
|
||||
|
||||
for (const Project& project : projects) {
|
||||
Component card = Renderer([project]() -> Element {
|
||||
Element title = text(project.title);
|
||||
Element link_line = project.link.empty()
|
||||
? text("")
|
||||
: text("🔗 " + project.link) | color(Color::Blue);
|
||||
|
||||
return vbox({
|
||||
title,
|
||||
link_line
|
||||
}) | border;
|
||||
});
|
||||
|
||||
container->Add(card);
|
||||
}
|
||||
|
||||
return Renderer(container, [container]() -> Element {
|
||||
return vbox(container->Render()) | vscroll_indicator | yframe | flex;
|
||||
});
|
||||
}
|
||||
|
||||
Component MakeEducationPage() {
|
||||
std::vector<std::string> entries = {
|
||||
"🏫 STEM Endorsed High School\nGPA: 4.52 | 2021–2025",
|
||||
"🎓 Self-study: MIT OCW (Linear Algebra, ML)",
|
||||
"🔍 NSA Codebreaker, Lockheed Red Team"
|
||||
};
|
||||
|
||||
Component container = Container::Vertical({});
|
||||
|
||||
for (const std::string& entry : entries) {
|
||||
Component card = Renderer([entry]() -> Element {
|
||||
return text(entry) | border;
|
||||
});
|
||||
container->Add(card);
|
||||
}
|
||||
|
||||
return Renderer(container, [container]() -> Element {
|
||||
return vbox(container->Render()) | vscroll_indicator | yframe | flex;
|
||||
});
|
||||
}
|
||||
|
||||
Component MakeWorkPage() {
|
||||
std::vector<std::string> jobs = {
|
||||
"🔧 Founder @ Tenderlabs\nQuant research & trading infrastructure",
|
||||
"💻 IT Army of Ukraine\nCyberdefense and red-teaming (2023–24)",
|
||||
"🏢 Lockheed Martin Competitions\n2nd in 2025, 4th in 2024"
|
||||
};
|
||||
|
||||
Component container = Container::Vertical({});
|
||||
|
||||
for (const std::string& job : jobs) {
|
||||
Component card = Renderer([job]() -> Element {
|
||||
return text(job) | border;
|
||||
});
|
||||
container->Add(card);
|
||||
}
|
||||
|
||||
return Renderer(container, [container]() -> Element {
|
||||
return vbox(container->Render()) | vscroll_indicator | yframe | flex;
|
||||
});
|
||||
}
|
||||
|
||||
Component MakeContactPage() {
|
||||
std::string contact_info =
|
||||
"📫 Email: krishna@domain.com\n"
|
||||
"💻 GitHub: github.com/krishna\n"
|
||||
"🔗 LinkedIn: linkedin.com/in/krishna\n"
|
||||
"📍 Based in DFW Metroplex";
|
||||
|
||||
return Renderer([contact_info]() -> Element {
|
||||
return paragraph(contact_info) | flex;
|
||||
});
|
||||
}
|
||||
|
||||
// Constructor implementation
|
||||
PortfolioApp::PortfolioApp() {
|
||||
// Build individual pages
|
||||
about_page_ = MakeAboutPage();
|
||||
projects_page_ = MakeProjectsPage();
|
||||
education_page_ = MakeEducationPage();
|
||||
work_page_ = MakeWorkPage();
|
||||
contact_page_ = MakeContactPage();
|
||||
|
||||
// Add pages to vector
|
||||
pages_.push_back(about_page_);
|
||||
pages_.push_back(projects_page_);
|
||||
pages_.push_back(education_page_);
|
||||
pages_.push_back(work_page_);
|
||||
pages_.push_back(contact_page_);
|
||||
|
||||
// Create navigation sidebar
|
||||
navigation_ = Container::Vertical({
|
||||
Button("About", [&] { SwitchPage(0); }),
|
||||
Button("Projects", [&] { SwitchPage(1); }),
|
||||
Button("Education", [&] { SwitchPage(2); }),
|
||||
Button("Work", [&] { SwitchPage(3); }),
|
||||
Button("Contact", [&] { SwitchPage(4); }),
|
||||
});
|
||||
|
||||
// Initial layout
|
||||
Add(Container::Horizontal({
|
||||
navigation_,
|
||||
pages_[current_page_]
|
||||
}));
|
||||
}
|
||||
|
||||
// SwitchPage method implementation
|
||||
void PortfolioApp::SwitchPage(int index) {
|
||||
current_page_ = index;
|
||||
|
||||
// Clear and rebuild layout
|
||||
DetachAllChildren();
|
||||
Add(Container::Horizontal({
|
||||
navigation_,
|
||||
pages_[current_page_]
|
||||
}));
|
||||
}
|
||||
|
||||
// Render method implementation
|
||||
ftxui::Element PortfolioApp::Render() {
|
||||
return hbox({
|
||||
navigation_->Render() | border,
|
||||
pages_[current_page_]->Render() | border | flex
|
||||
});
|
||||
}
|
||||
|
||||
// OnEvent method implementation
|
||||
bool PortfolioApp::OnEvent(ftxui::Event event) {
|
||||
if (event == ftxui::Event::ArrowRight) {
|
||||
SwitchPage((current_page_ + 1) % pages_.size());
|
||||
return true;
|
||||
}
|
||||
if (event == ftxui::Event::ArrowLeft) {
|
||||
SwitchPage((current_page_ - 1 + pages_.size()) % pages_.size());
|
||||
return true;
|
||||
}
|
||||
return ftxui::ComponentBase::OnEvent(event);
|
||||
}
|
||||
99
src/portfolioapp.hpp
Normal file
99
src/portfolioapp.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include <ftxui/component/component.hpp>
|
||||
#include <ftxui/component/component_base.hpp>
|
||||
#include <ftxui/component/screen_interactive.hpp>
|
||||
#include <ftxui/dom/elements.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ------------------
|
||||
// Structs
|
||||
// ------------------
|
||||
|
||||
struct Project {
|
||||
std::string title;
|
||||
std::string link; // Leave empty if no link
|
||||
};
|
||||
|
||||
// ------------------
|
||||
// Page Factory Functions
|
||||
// ------------------
|
||||
|
||||
/**
|
||||
* Creates the About page component
|
||||
* @return Component containing personal introduction and focus areas
|
||||
*/
|
||||
ftxui::Component MakeAboutPage();
|
||||
|
||||
/**
|
||||
* Creates the Projects page component
|
||||
* @return Component displaying list of projects with links
|
||||
*/
|
||||
ftxui::Component MakeProjectsPage();
|
||||
|
||||
/**
|
||||
* Creates the Education page component
|
||||
* @return Component showing educational background and achievements
|
||||
*/
|
||||
ftxui::Component MakeEducationPage();
|
||||
|
||||
/**
|
||||
* Creates the Work page component
|
||||
* @return Component displaying work experience and competitions
|
||||
*/
|
||||
ftxui::Component MakeWorkPage();
|
||||
|
||||
/**
|
||||
* Creates the Contact page component
|
||||
* @return Component with contact information
|
||||
*/
|
||||
ftxui::Component MakeContactPage();
|
||||
|
||||
// ------------------
|
||||
// Main Application Class
|
||||
// ------------------
|
||||
|
||||
/**
|
||||
* Main portfolio application class that manages navigation and page switching
|
||||
* Inherits from ftxui::ComponentBase to provide custom rendering and event handling
|
||||
*/
|
||||
class PortfolioApp : public ftxui::ComponentBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor - initializes all pages and navigation
|
||||
*/
|
||||
PortfolioApp();
|
||||
|
||||
/**
|
||||
* Switch to a specific page by index
|
||||
* @param index The page index to switch to (0-4)
|
||||
*/
|
||||
void SwitchPage(int index);
|
||||
|
||||
/**
|
||||
* Render the current application state
|
||||
* @return Element representing the full UI layout
|
||||
*/
|
||||
ftxui::Element Render();
|
||||
|
||||
/**
|
||||
* Handle keyboard events for navigation
|
||||
* @param event The keyboard event to process
|
||||
* @return true if event was handled, false otherwise
|
||||
*/
|
||||
bool OnEvent(ftxui::Event event) override;
|
||||
|
||||
private:
|
||||
int current_page_ = 0; // Currently active page index
|
||||
|
||||
// UI Components
|
||||
ftxui::Component navigation_; // Navigation sidebar
|
||||
ftxui::Component about_page_; // About page component
|
||||
ftxui::Component projects_page_; // Projects page component
|
||||
ftxui::Component education_page_; // Education page component
|
||||
ftxui::Component work_page_; // Work page component
|
||||
ftxui::Component contact_page_; // Contact page component
|
||||
|
||||
std::vector<ftxui::Component> pages_; // Vector of all page components
|
||||
};
|
||||
Reference in New Issue
Block a user