diff --git a/main/source/window/window.cpp b/main/source/window/window.cpp index 3ed231b2d..06d62bdd7 100644 --- a/main/source/window/window.cpp +++ b/main/source/window/window.cpp @@ -576,9 +576,10 @@ namespace hex { } } - if (!open || !popupDisplaying) { + if (!open && !popupDisplaying) { sizeSet = false; popupDisplaying = false; + popupSize = ImVec2(0, 0); popups.pop_back(); } } diff --git a/plugins/builtin/include/content/popups/popup_docs_question.hpp b/plugins/builtin/include/content/popups/popup_docs_question.hpp new file mode 100644 index 000000000..194e915e9 --- /dev/null +++ b/plugins/builtin/include/content/popups/popup_docs_question.hpp @@ -0,0 +1,128 @@ +#include + +#include + +#include +#include + +#include +#include + +namespace hex::plugin::builtin { + + class PopupDocsQuestion : public Popup { + public: + PopupDocsQuestion() + : hex::Popup("hex.builtin.popup.docs_question.title", true, true) { } + + enum class TextBlockType { + Text, + Code + }; + + void drawContent() override { + ImGui::PushItemWidth(600_scaled); + ImGui::BeginDisabled(this->m_requestTask.isRunning()); + if (ImGui::InputText("##input", this->m_inputBuffer, ImGuiInputTextFlags_EnterReturnsTrue)) { + this->executeQuery(); + } + ImGui::EndDisabled(); + ImGui::PopItemWidth(); + + if (ImGui::BeginChild("##answer", scaled(ImVec2(600, 350)), true, ImGuiWindowFlags_AlwaysVerticalScrollbar)) { + if (!this->m_requestTask.isRunning()) { + if (this->m_answer.empty()) { + if (this->m_noAnswer) + ImGui::TextFormattedCentered("{}", "hex.builtin.popup.docs_question.no_answer"_lang); + else + ImGui::TextFormattedCentered("{}", "hex.builtin.popup.docs_question.prompt"_lang); + } else { + for (auto &[type, text] : this->m_answer) { + switch (type) { + case TextBlockType::Text: + ImGui::TextFormattedWrapped("{}", text); + break; + case TextBlockType::Code: + ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyle().Colors[ImGuiCol_WindowBg]); + auto textWidth = 400_scaled - ImGui::GetStyle().FramePadding.x * 4 - ImGui::GetStyle().ScrollbarSize; + auto textHeight = ImGui::CalcTextSize(text.c_str(), nullptr, false, textWidth).y + ImGui::GetStyle().FramePadding.y * 6; + if (ImGui::BeginChild("##code", ImVec2(textWidth, textHeight), true)) { + ImGui::TextFormattedWrapped("{}", text); + ImGui::EndChild(); + } + ImGui::PopStyleColor(); + + break; + } + } + } + } else { + ImGui::TextFormattedCentered("{}", "hex.builtin.popup.docs_question.thinking"_lang); + } + } + ImGui::EndChild(); + } + + [[nodiscard]] ImGuiWindowFlags getFlags() const override { + return ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize; + } + + private: + void executeQuery() { + this->m_requestTask = TaskManager::createBackgroundTask("Query Docs", [this, input = this->m_inputBuffer](Task &) { + this->m_noAnswer = false; + for (auto space : { "xj7sbzGbHH260vbpZOu1", "WZzDdGjxmgMSIE3xly6o" }) { + this->m_answer.clear(); + + auto request = HttpRequest("POST", hex::format("https://api.gitbook.com/v1/spaces/{}/search/ask", space)); + + request.setBody(hex::format(R"({{ "query": "{}" }})", input)); + request.addHeader("Content-Type", "application/json"); + + auto response = request.execute().get(); + if (!response.isSuccess()) + continue; + + try { + auto json = nlohmann::json::parse(response.getData()); + if (!json.contains("answer")) + continue; + + auto answer = json["answer"]["text"].get(); + if (answer.empty()) + break; + + auto blocks = wolv::util::splitString(answer, "```"); + for (auto &block : blocks) { + if (block.empty()) + continue; + + block = wolv::util::trim(block); + + if (block.starts_with("rust\n")) { + block = block.substr(5); + this->m_answer.emplace_back(TextBlockType::Code, block); + } else if (block.starts_with("cpp\n")) { + block = block.substr(4); + this->m_answer.emplace_back(TextBlockType::Code, block); + } else { + this->m_answer.emplace_back(TextBlockType::Text, block); + } + } + } catch(...) { + continue; + } + + this->m_noAnswer = this->m_answer.empty(); + } + }); + } + + private: + std::string m_inputBuffer; + std::vector> m_answer; + TaskHolder m_requestTask; + bool m_noAnswer = false; + }; + +} \ No newline at end of file diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 27ea52dba..0b72fd7d8 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -179,6 +179,7 @@ "hex.builtin.menu.file.quit": "Quit ImHex", "hex.builtin.menu.file.reload_provider": "Reload Provider", "hex.builtin.menu.help": "Help", + "hex.builtin.menu.help.ask_for_help": "Ask Documentation...", "hex.builtin.menu.layout": "Layout", "hex.builtin.menu.view": "View", "hex.builtin.menu.view.demo": "Show ImGui Demo", @@ -361,6 +362,10 @@ "hex.builtin.pl_visualizer.3d.scale": "Scale", "hex.builtin.popup.close_provider.desc": "There are unsaved changes made to this Provider\nthat haven't been saved to a Project yet.\n\nAre you sure you want to close it?", "hex.builtin.popup.close_provider.title": "Close Provider?", + "hex.builtin.popup.docs_question.title": "Documentation query", + "hex.builtin.popup.docs_question.no_answer": "The documentation didn't have an answer for this question", + "hex.builtin.popup.docs_question.prompt": "Ask the documentation AI for help!", + "hex.builtin.popup.docs_question.thinking": "Thinking...", "hex.builtin.popup.error.create": "Failed to create new file!", "hex.builtin.popup.error.file_dialog.common": "An error occurred while opening the file browser: {}", "hex.builtin.popup.error.file_dialog.portal": "There was an error while opening the file browser: {}.\nThis might be caused by your system not having a xdg-desktop-portal backend installed correctly.\n\nOn KDE, it's xdg-desktop-portal-kde.\nOn Gnome it's xdg-desktop-portal-gnome.\nOn wlroots it's xdg-desktop-portal-wlr.\nOtherwise, you can try to use xdg-desktop-portal-gtk.\n\nReboot your system after installing it.\n\nIf the file browser still doesn't work after this, submit an issue at https://github.com/WerWolv/ImHex/issues\n\nIn the meantime files can still be opened by dragging them onto the ImHex window!", diff --git a/plugins/builtin/source/content/main_menu_items.cpp b/plugins/builtin/source/content/main_menu_items.cpp index 5b997a410..e7c086bcd 100644 --- a/plugins/builtin/source/content/main_menu_items.cpp +++ b/plugins/builtin/source/content/main_menu_items.cpp @@ -12,6 +12,7 @@ #include "content/global_actions.hpp" #include +#include #include @@ -453,6 +454,10 @@ namespace hex::plugin::builtin { static void createHelpMenu() { ContentRegistry::Interface::registerMainMenuItem("hex.builtin.menu.help", 5000); + + ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.help", "hex.builtin.menu.help.ask_for_help" }, 5000, CTRLCMD + SHIFT + Keys::D, [] { + PopupDocsQuestion::open(); + }); } void registerMainMenuEntries() {