From eff21ee2ce1fdb4328d71d801352ec25f4e457ff Mon Sep 17 00:00:00 2001 From: littleblack111 Date: Wed, 2 Apr 2025 18:49:15 +0800 Subject: feat: ftxui (#17) * ready for merge rm sum random ocmments first and https://github.com/ArthurSonzogni/FTXUI/issues/1024 but still, ready for merge since we can't do anything on our end * style: clang-tidy * ci * ci * style: clang-tidy * fix * fix: scroll https://github.com/ArthurSonzogni/git-tui/blob/master/src/scroller.cpp * focus * update todo * style: clang-format * update todo * sticky scroll * update todxo * smol fix need event to update screen. so we just give event when IO updates * style: clang-format --------- Co-authored-by: github-actions[bot] --- src/inputManager.cpp | 64 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'src/inputManager.cpp') diff --git a/src/inputManager.cpp b/src/inputManager.cpp index 8de26bd..cc3880b 100644 --- a/src/inputManager.cpp +++ b/src/inputManager.cpp @@ -1,10 +1,43 @@ #include "inputManager.hpp" +#include "IOManager.hpp" #include "chatManager.hpp" #include "commandHandler.hpp" #include "log.hpp" -#include +#include "renderManager.hpp" +#include "scroller.hpp" + +CInputManager::CInputManager() + : m_input(ftxui::Input(&m_szInput, "Type here...", {.transform = [](ftxui::InputState state) { + state.element |= ftxui::bgcolor(ftxui::Color::HSVA(0, 0, 0, 0)); + state.element |= ftxui::color(ftxui::Color::White); + return state.element; }, .multiline = false, .on_enter = [&] { + if (m_szInput.empty()) + return; + + g_pCommandHandler->isCommand(m_szInput) ? g_pCommandHandler->handleCommand(m_szInput) : g_pChatManager->newMessage({.msg = m_szInput, .username = "Server"}); + m_szInput.clear(); }}) // NOLINT + ) + , inputComponent(ftxui::Renderer(m_input, [&] { + return ftxui::hbox({ + ftxui::text("> "), + m_input->Render(), + }); + })) + , logComponent(ftxui::Renderer([] { + std::vector messages; + for (const auto &[chat, log] : g_pIOManager->getIO()) { + if (chat && !chat->msg.empty()) { + std::string username = chat->username; + if (username.back() == '\n') + username.pop_back(); + messages.push_back(ftxui::window(ftxui::text(username), ftxui::paragraph(chat->msg))); + } else if (log && !log->log.empty()) + messages.push_back(ftxui::window(ftxui::text(NFormatter::fmt(log->type, "")), ftxui::paragraph(log->log))); + } + + return ftxui::vbox(messages); + })) { -CInputManager::CInputManager() { log(LOG, "InputManager: initialized"); } @@ -12,19 +45,24 @@ CInputManager::~CInputManager() { log(SYS, "InputManager: bye"); } -void CInputManager::run() { - inputLoop(); +void CInputManager::updateIO() { + logComponent->OnEvent(ftxui::Event::Custom); + g_pRenderManager->screen.PostEvent(ftxui::Event::Custom); } void CInputManager::inputLoop() { - while (true) { - std::string input; - std::print("> "); - std::getline(std::cin, input); - - if (input.empty()) - continue; + container = logComponent |= ftxui::Scroller; + container = ftxui::ResizableSplitBottom(inputComponent, container, &bottomSize); - g_pCommandHandler->isCommand(input) ? g_pCommandHandler->handleCommand(input) : g_pChatManager->newMessage({.msg = input, .username = "Server"}); - } + // FIXME: this shit spams TakeFocus(not ideal for power etc reasons) + // consider: custom loop, or just only allow focus to be inputComponent somehow + container |= ftxui::CatchEvent([&](ftxui::Event) { + inputComponent->TakeFocus(); + return false; + }); + g_pRenderManager->setRenderer(ftxui::Renderer(container, [this] { + return container->Render() | ftxui::border; + })); + inputComponent->TakeFocus(); + g_pRenderManager->enterLoop(); } -- cgit v1.2.3