2022-03-04 19:06:29 +01:00
# include "content/views/view_about.hpp"
2022-02-01 18:09:40 +01:00
2023-11-05 19:57:29 +01:00
# include <hex/api_urls.hpp>
2022-02-01 18:09:40 +01:00
# include <hex/api/content_registry.hpp>
2023-08-06 21:33:15 +02:00
# include <hex/api/achievement_manager.hpp>
2020-11-14 21:16:03 +01:00
2021-09-06 20:35:38 +02:00
# include <hex/helpers/fmt.hpp>
2022-03-04 11:36:37 +01:00
# include <hex/helpers/fs.hpp>
2022-02-01 18:09:40 +01:00
# include <hex/helpers/utils.hpp>
2023-11-05 19:57:29 +01:00
# include <hex/helpers/http_requests.hpp>
2021-09-06 20:35:38 +02:00
2023-05-12 08:38:32 +02:00
# include <content/popups/popup_docs_question.hpp>
2022-01-22 23:11:28 +01:00
# include <romfs/romfs.hpp>
2023-11-05 19:57:29 +01:00
# include <wolv/utils/string.hpp>
2022-01-22 23:11:28 +01:00
2021-12-07 22:47:41 +01:00
namespace hex : : plugin : : builtin {
2020-11-14 21:16:03 +01:00
2023-11-21 13:47:50 +01:00
ViewAbout : : ViewAbout ( ) : View : : Modal ( " hex.builtin.view.help.about.name " ) {
2023-08-26 12:54:52 +02:00
// Add "About" menu item to the help menu
2023-03-20 13:11:43 +01:00
ContentRegistry : : Interface : : addMenuItem ( { " hex.builtin.menu.help " , " hex.builtin.view.help.about.name " } , 1000 , Shortcut : : None , [ this ] {
this - > getWindowOpenState ( ) = true ;
} ) ;
2023-05-12 08:38:32 +02:00
ContentRegistry : : Interface : : addMenuItemSeparator ( { " hex.builtin.menu.help " } , 2000 ) ;
2023-08-26 12:54:52 +02:00
// Add documentation links to the help menu
2023-05-12 08:38:32 +02:00
ContentRegistry : : Interface : : addMenuItem ( { " hex.builtin.menu.help " , " hex.builtin.view.help.documentation " } , 3000 , Shortcut : : None , [ ] {
2023-08-06 21:33:15 +02:00
hex : : openWebpage ( " https://docs.werwolv.net/imhex " ) ;
AchievementManager : : unlockAchievement ( " hex.builtin.achievement.starting_out " , " hex.builtin.achievement.starting_out.docs.name " ) ;
2022-01-23 02:28:38 +01:00
} ) ;
2023-05-12 08:38:32 +02:00
ContentRegistry : : Interface : : addMenuItem ( { " hex.builtin.menu.help " , " hex.builtin.menu.help.ask_for_help " } , 4000 , CTRLCMD + SHIFT + Keys : : D , [ ] {
PopupDocsQuestion : : open ( ) ;
} ) ;
2020-11-14 21:16:03 +01:00
}
2020-11-30 21:44:40 +01:00
2023-11-25 00:43:03 +01:00
void ViewAbout : : drawAboutMainPage ( )
{
2023-08-26 12:54:52 +02:00
// Draw main about table
2022-01-23 20:46:19 +01:00
if ( ImGui : : BeginTable ( " about_table " , 2 , ImGuiTableFlags_SizingFixedFit ) ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
2023-08-26 12:54:52 +02:00
// Draw the ImHex icon
2023-08-26 23:43:35 +02:00
if ( ! this - > m_logoTexture . isValid ( ) )
2023-11-16 22:24:06 +01:00
this - > m_logoTexture = ImGuiExt : : Texture ( romfs : : get ( " assets/common/logo.png " ) . span ( ) ) ;
2023-08-26 23:43:35 +02:00
2023-11-25 00:43:03 +01:00
ImGui : : Image ( this - > m_logoTexture , scaled ( { 100 , 100 } ) ) ;
2023-11-05 19:57:29 +01:00
if ( ImGui : : IsItemHovered ( ) & & ImGui : : IsItemClicked ( ) ) {
this - > m_clickCount + = 1 ;
}
2022-01-23 20:46:19 +01:00
ImGui : : TableNextColumn ( ) ;
2021-08-25 19:54:59 +02:00
2023-11-25 00:43:03 +01:00
ImGuiExt : : BeginSubWindow ( " Build Information " , ImVec2 ( 0 , 0 ) , ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY ) ;
{
if ( ImGui : : BeginTable ( " Information " , 1 , ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInner ) ) {
ImGui : : TableNextRow ( ) ;
2021-12-12 13:35:07 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : TableNextColumn ( ) ;
{
// Draw basic information about ImHex and its version
ImGuiExt : : TextFormatted ( " ImHex Hex Editor v{} by WerWolv " ICON_FA_CODE_BRANCH , ImHexApi : : System : : getImHexVersion ( ) ) ;
2023-08-26 12:54:52 +02:00
2023-11-25 00:43:03 +01:00
ImGui : : SameLine ( ) ;
2022-01-23 20:46:19 +01:00
2023-11-25 00:43:03 +01:00
// Draw a clickable link to the current commit
if ( ImGuiExt : : Hyperlink ( hex : : format ( " {0}@{1} " , ImHexApi : : System : : getCommitBranch ( ) , ImHexApi : : System : : getCommitHash ( ) ) . c_str ( ) ) )
hex : : openWebpage ( " https://github.com/WerWolv/ImHex/commit/ " + ImHexApi : : System : : getCommitHash ( true ) ) ;
}
2023-10-30 23:24:00 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : TableNextColumn ( ) ;
{
// Draw the build date and time
ImGuiExt : : TextFormatted ( " Compiled on {} at {} " , __DATE__ , __TIME__ ) ;
}
2022-01-23 20:46:19 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : TableNextColumn ( ) ;
{
// Draw the author of the current translation
ImGui : : TextUnformatted ( " hex.builtin.view.help.about.translator " _lang ) ;
}
2023-08-26 12:54:52 +02:00
2023-11-25 00:43:03 +01:00
ImGui : : TableNextColumn ( ) ;
{
// Draw information about the open-source nature of ImHex
ImGui : : TextUnformatted ( " hex.builtin.view.help.about.source " _lang ) ;
ImGui : : SameLine ( ) ;
2023-08-26 12:54:52 +02:00
2023-11-25 00:43:03 +01:00
// Draw a clickable link to the GitHub repository
if ( ImGuiExt : : Hyperlink ( " WerWolv/ImHex " ) )
hex : : openWebpage ( " https://github.com/WerWolv/ImHex " ) ;
}
ImGui : : EndTable ( ) ;
}
}
ImGuiExt : : EndSubWindow ( ) ;
2022-01-23 20:46:19 +01:00
ImGui : : EndTable ( ) ;
}
2020-11-30 21:44:40 +01:00
2023-08-26 12:54:52 +02:00
// Draw donation links
2023-11-25 00:43:03 +01:00
ImGuiExt : : Header ( " hex.builtin.view.help.about.donations " _lang ) ;
2021-12-12 13:35:07 +01:00
2023-11-16 22:24:06 +01:00
ImGuiExt : : TextFormattedWrapped ( " {} " , static_cast < const char * > ( " hex.builtin.view.help.about.thanks " _lang ) ) ;
2021-12-12 13:35:07 +01:00
ImGui : : NewLine ( ) ;
2021-01-23 00:46:50 +01:00
2023-11-25 00:43:03 +01:00
struct DonationPage {
ImGuiExt : : Texture texture ;
const char * link ;
} ;
static std : : array DonationPages = {
DonationPage { ImGuiExt : : Texture ( romfs : : get ( " assets/common/donation/paypal.png " ) . span < std : : byte > ( ) ) , " https://werwolv.net/donate " } ,
DonationPage { ImGuiExt : : Texture ( romfs : : get ( " assets/common/donation/github.png " ) . span < std : : byte > ( ) ) , " https://github.com/sponsors/WerWolv " } ,
DonationPage { ImGuiExt : : Texture ( romfs : : get ( " assets/common/donation/patreon.png " ) . span < std : : byte > ( ) ) , " https://patreon.com/werwolv " } ,
} ;
ImGui : : NewLine ( ) ;
if ( ImGui : : BeginTable ( " DonationLinks " , 5 , ImGuiTableFlags_SizingStretchSame , ImGui : : GetContentRegionAvail ( ) ) ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
for ( const auto & page : DonationPages ) {
ImGui : : TableNextColumn ( ) ;
const auto size = page . texture . getSize ( ) / 1.5F ;
const auto startPos = ImGui : : GetCursorScreenPos ( ) ;
ImGui : : Image ( page . texture , page . texture . getSize ( ) / 1.5F ) ;
if ( ImGui : : IsItemHovered ( ) ) {
ImGui : : GetForegroundDrawList ( ) - > AddShadowCircle ( startPos + size / 2 , size . x / 2 , ImGui : : GetColorU32 ( ImGuiCol_Button ) , 100.0F , ImVec2 ( ) , ImDrawFlags_ShadowCutOutShapeBackground ) ;
}
if ( ImGui : : IsItemClicked ( ) ) {
hex : : openWebpage ( page . link ) ;
}
}
ImGui : : EndTable ( ) ;
2021-12-12 13:35:07 +01:00
}
}
2021-01-23 00:46:50 +01:00
2022-03-04 19:06:29 +01:00
void ViewAbout : : drawContributorPage ( ) {
2023-11-25 00:43:03 +01:00
struct Contributor {
const char * name ;
const char * description ;
const char * link ;
2023-11-25 12:44:20 +01:00
bool mainContributor ;
2023-11-25 00:43:03 +01:00
} ;
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
constexpr static std : : array Contributors = {
2023-11-25 12:44:20 +01:00
Contributor { " iTrooz " , " A huge amount of help maintaining ImHex and the CI " , " https://github.com/iTrooz " , true } ,
Contributor { " jumanji144 " , " A ton of help with the Pattern Language, API and usage stats " , " https://github.com/Nowilltolife " , true } ,
Contributor { " Mary " , " Porting ImHex to macOS originally " , " https://github.com/marysaka " , false } ,
Contributor { " Roblabla " , " Adding the MSI Windows installer " , " https://github.com/roblabla " , false } ,
Contributor { " jam1garner " , " Adding support for Rust plugins " , " https://github.com/jam1garner " , false } ,
Contributor { " All other amazing contributors " , " Being part of the community, opening issues, PRs and donating " , " https://github.com/WerWolv/ImHex/graphs/contributors " , false }
2023-11-25 00:43:03 +01:00
} ;
2023-08-26 12:54:52 +02:00
2023-11-25 13:42:51 +01:00
ImGuiExt : : TextFormattedWrapped ( " These amazing people have contributed some incredible things to ImHex in the past. \n Consider opening a PR on the Git Repository to take your place among them! " ) ;
2023-08-26 12:54:52 +02:00
ImGui : : NewLine ( ) ;
2023-11-25 00:43:03 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( ) ) ;
ImGuiExt : : BeginSubWindow ( " Contributors " , ImVec2 ( ImGui : : GetContentRegionAvail ( ) . x , 0 ) , ImGuiChildFlags_AutoResizeX ) ;
2023-11-25 12:44:20 +01:00
ImGui : : PopStyleVar ( ) ;
2023-11-25 00:43:03 +01:00
{
if ( ImGui : : BeginTable ( " Contributors " , 1 , ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders ) ) {
for ( const auto & contributor : Contributors ) {
ImGui : : TableNextRow ( ) ;
2023-11-25 13:15:21 +01:00
if ( contributor . mainContributor ) {
2023-11-25 13:42:51 +01:00
ImGui : : TableSetBgColor ( ImGuiTableBgTarget_RowBg0 , ImGui : : GetColorU32 ( ImGuiCol_PlotHistogram ) & 0x1FFFFFFF ) ;
2023-11-25 13:15:21 +01:00
}
2023-11-25 00:43:03 +01:00
ImGui : : TableNextColumn ( ) ;
2022-03-04 19:06:29 +01:00
2023-11-25 13:15:21 +01:00
if ( ImGuiExt : : Hyperlink ( contributor . name ) )
hex : : openWebpage ( contributor . link ) ;
2023-11-25 12:44:20 +01:00
2023-11-25 13:15:21 +01:00
ImGui : : Indent ( ) ;
ImGui : : TextUnformatted ( contributor . description ) ;
ImGui : : Unindent ( ) ;
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
}
ImGui : : EndTable ( ) ;
}
}
ImGuiExt : : EndSubWindow ( ) ;
2021-12-12 13:35:07 +01:00
}
2021-01-23 00:46:50 +01:00
2022-03-04 19:06:29 +01:00
void ViewAbout : : drawLibraryCreditsPage ( ) {
2021-01-23 00:46:50 +01:00
2023-11-25 00:43:03 +01:00
struct Library {
const char * name ;
const char * author ;
const char * link ;
} ;
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
constexpr static std : : array ImGuiLibraries = {
Library { " ImGui " , " ocornut " , " https://github.com/ocornut/imgui " } ,
Library { " ImPlot " , " epezent " , " https://github.com/epezent/implot " } ,
Library { " imnodes " , " Nelarius " , " https://github.com/Nelarius/imnodes " } ,
Library { " ImGuiColorTextEdit " , " BalazsJako " , " https://github.com/BalazsJako/ImGuiColorTextEdit " } ,
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
} ;
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
constexpr static std : : array ExternalLibraries = {
Library { " PatternLanguage " , " WerWolv " , " https://github.com/WerWolv/PatternLanguage " } ,
Library { " libwolv " , " WerWolv " , " https://github.com/WerWolv/libwolv " } ,
Library { " libromfs " , " WerWolv " , " https://github.com/WerWolv/libromfs " } ,
} ;
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
constexpr static std : : array ThirdPartyLibraries = {
Library { " capstone " , " aquynh " , " https://github.com/aquynh/capstone " } ,
Library { " json " , " nlohmann " , " https://github.com/nlohmann/json " } ,
Library { " yara " , " VirusTotal " , " https://github.com/VirusTotal/yara " } ,
Library { " nativefiledialog-extended " , " btzy " , " https://github.com/btzy/nativefiledialog-extended " } ,
Library { " microtar " , " rxi " , " https://github.com/rxi/microtar " } ,
Library { " xdgpp " , " danyspin97 " , " https://sr.ht/~danyspin97/xdgpp " } ,
Library { " freetype " , " freetype " , " https://gitlab.freedesktop.org/freetype/freetype " } ,
Library { " mbedTLS " , " ARMmbed " , " https://github.com/ARMmbed/mbedtls " } ,
Library { " curl " , " curl " , " https://github.com/curl/curl " } ,
Library { " fmt " , " fmtlib " , " https://github.com/fmtlib/fmt " } ,
Library { " file " , " file " , " https://github.com/file/file " } ,
Library { " glfw " , " glfw " , " https://github.com/glfw/glfw " } ,
Library { " llvm " , " llvm-project " , " https://github.com/llvm/llvm-project " } ,
} ;
constexpr static auto drawTable = [ ] ( const char * category , const auto & libraries ) {
const auto width = ImGui : : GetContentRegionAvail ( ) . x ;
ImGuiExt : : BeginSubWindow ( category ) ;
{
for ( const auto & library : libraries ) {
ImGui : : PushStyleColor ( ImGuiCol_ChildBg , ImGui : : GetColorU32 ( ImGuiCol_TableHeaderBg ) ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_ChildRounding , 50 ) ;
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , scaled ( { 12 , 3 } ) ) ;
if ( ImGui : : BeginChild ( library . link , ImVec2 ( ) , ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY ) ) {
if ( ImGuiExt : : Hyperlink ( hex : : format ( " {}/{} " , library . author , library . name ) . c_str ( ) ) ) {
hex : : openWebpage ( library . link ) ;
}
2023-11-25 13:15:21 +01:00
ImGui : : SetItemTooltip ( " %s " , library . link ) ;
2023-11-25 00:43:03 +01:00
}
ImGui : : EndChild ( ) ;
2021-01-23 00:46:50 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : SameLine ( ) ;
2023-11-25 12:44:20 +01:00
if ( ImGui : : GetCursorPosX ( ) > ( width - 100 _scaled ) )
2023-11-25 00:43:03 +01:00
ImGui : : NewLine ( ) ;
2022-03-04 19:06:29 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : PopStyleColor ( ) ;
ImGui : : PopStyleVar ( 2 ) ;
}
}
ImGuiExt : : EndSubWindow ( ) ;
2023-11-25 12:44:20 +01:00
ImGui : : NewLine ( ) ;
2023-11-25 00:43:03 +01:00
} ;
ImGuiExt : : TextFormattedWrapped ( " ImHex builds on top of the amazing work of a ton of talented library developers without which this project wouldn't stand. " ) ;
2022-03-04 19:06:29 +01:00
ImGui : : NewLine ( ) ;
2023-11-25 00:43:03 +01:00
drawTable ( " ImGui " , ImGuiLibraries ) ;
drawTable ( " External " , ExternalLibraries ) ;
drawTable ( " Third Party " , ThirdPartyLibraries ) ;
2021-12-12 13:35:07 +01:00
}
2021-01-23 00:46:50 +01:00
2022-03-04 19:06:29 +01:00
void ViewAbout : : drawPathsPage ( ) {
2023-11-25 00:43:03 +01:00
constexpr static std : : array < std : : pair < const char * , fs : : ImHexPath > , size_t ( fs : : ImHexPath : : END ) - 1U > PathTypes = {
{
{ " Patterns " , fs : : ImHexPath : : Patterns } ,
{ " Patterns Includes " , fs : : ImHexPath : : PatternsInclude } ,
{ " Magic " , fs : : ImHexPath : : Magic } ,
{ " Plugins " , fs : : ImHexPath : : Plugins } ,
{ " Libraries " , fs : : ImHexPath : : Libraries } ,
{ " Yara Patterns " , fs : : ImHexPath : : Yara } ,
{ " Config " , fs : : ImHexPath : : Config } ,
{ " Resources " , fs : : ImHexPath : : Resources } ,
{ " Constants lists " , fs : : ImHexPath : : Constants } ,
{ " Custom encodings " , fs : : ImHexPath : : Encodings } ,
{ " Logs " , fs : : ImHexPath : : Logs } ,
{ " Recent files " , fs : : ImHexPath : : Recent } ,
{ " Scripts " , fs : : ImHexPath : : Scripts } ,
{ " Themes " , fs : : ImHexPath : : Themes } ,
{ " Data inspector scripts " , fs : : ImHexPath : : Inspectors } ,
{ " Custom data processor nodes " , fs : : ImHexPath : : Nodes } ,
}
} ;
2021-12-12 13:35:07 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( ) ) ;
ImGuiExt : : BeginSubWindow ( " Paths " , ImGui : : GetContentRegionAvail ( ) ) ;
{
if ( ImGui : : BeginTable ( " ##imhex_paths " , 2 , ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit ) ) {
ImGui : : TableSetupScrollFreeze ( 0 , 1 ) ;
ImGui : : TableSetupColumn ( " Type " ) ;
ImGui : : TableSetupColumn ( " Paths " ) ;
// Draw the table
ImGui : : TableHeadersRow ( ) ;
for ( const auto & [ name , type ] : PathTypes ) {
ImGui : : TableNextRow ( ) ;
ImGui : : TableNextColumn ( ) ;
ImGui : : TextUnformatted ( name ) ;
2021-12-12 13:35:07 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : TableNextColumn ( ) ;
for ( auto & path : fs : : getDefaultPaths ( type , true ) ) {
// Draw hyperlink to paths that exist or red text if they don't
if ( wolv : : io : : fs : : isDirectory ( path ) ) {
if ( ImGuiExt : : Hyperlink ( wolv : : util : : toUTF8String ( path ) . c_str ( ) ) ) {
fs : : openFolderExternal ( path ) ;
}
} else {
ImGuiExt : : TextFormattedColored ( ImGuiExt : : GetCustomColorVec4 ( ImGuiCustomCol_ToolbarRed ) , wolv : : util : : toUTF8String ( path ) ) ;
2023-06-05 13:50:55 +02:00
}
2022-10-13 08:07:46 +02:00
}
}
2021-12-12 13:35:07 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : EndTable ( ) ;
}
2021-12-12 13:35:07 +01:00
}
2023-11-25 00:43:03 +01:00
ImGuiExt : : EndSubWindow ( ) ;
ImGui : : PopStyleVar ( ) ;
2021-12-12 13:35:07 +01:00
}
2023-11-05 19:57:29 +01:00
void ViewAbout : : drawReleaseNotesPage ( ) {
static std : : string releaseTitle ;
static std : : vector < std : : string > releaseNotes ;
2022-01-22 23:11:28 +01:00
2023-11-05 19:57:29 +01:00
// Set up the request to get the release notes the first time the page is opened
AT_FIRST_TIME {
static HttpRequest request ( " GET " , GitHubApiURL + std : : string ( " /releases/tags/v " ) + ImHexApi : : System : : getImHexVersion ( false ) ) ;
2021-01-14 17:01:44 +01:00
2023-11-05 19:57:29 +01:00
this - > m_releaseNoteRequest = request . execute ( ) ;
} ;
2021-01-14 17:01:44 +01:00
2023-11-05 19:57:29 +01:00
// Wait for the request to finish and parse the response
if ( this - > m_releaseNoteRequest . valid ( ) ) {
if ( this - > m_releaseNoteRequest . wait_for ( std : : chrono : : seconds ( 0 ) ) = = std : : future_status : : ready ) {
auto response = this - > m_releaseNoteRequest . get ( ) ;
nlohmann : : json json ;
if ( response . isSuccess ( ) ) {
// A valid response was received, parse it
try {
json = nlohmann : : json : : parse ( response . getData ( ) ) ;
// Get the release title
releaseTitle = json [ " name " ] . get < std : : string > ( ) ;
2021-12-12 13:35:07 +01:00
2023-11-05 19:57:29 +01:00
// Get the release notes and split it into lines
auto body = json [ " body " ] . get < std : : string > ( ) ;
releaseNotes = wolv : : util : : splitString ( body , " \r \n " ) ;
} catch ( std : : exception & e ) {
releaseNotes . push_back ( " ## Error: " + std : : string ( e . what ( ) ) ) ;
2022-01-24 00:45:46 +01:00
}
2023-11-05 19:57:29 +01:00
} else {
// An error occurred, display it
releaseNotes . push_back ( " ## HTTP Error: " + std : : to_string ( response . getStatusCode ( ) ) ) ;
2021-05-23 23:35:04 +02:00
}
2023-11-05 19:57:29 +01:00
} else {
// Draw a spinner while the release notes are loading
2023-11-16 22:24:06 +01:00
ImGuiExt : : TextSpinner ( " hex.builtin.common.loading " _lang ) ;
2023-11-05 19:57:29 +01:00
}
}
2021-05-23 23:35:04 +02:00
2023-11-05 19:57:29 +01:00
// Function to handle drawing of a regular text line
static const auto drawRegularLine = [ ] ( const std : : string & line ) {
ImGui : : Bullet ( ) ;
ImGui : : SameLine ( ) ;
// Check if the line contains bold text
auto boldStart = line . find ( " ** " ) ;
if ( boldStart ! = std : : string : : npos ) {
// Find the end of the bold text
auto boldEnd = line . find ( " ** " , boldStart + 2 ) ;
// Draw the line with the bold text highlighted
ImGui : : TextUnformatted ( line . substr ( 0 , boldStart ) . c_str ( ) ) ;
ImGui : : SameLine ( 0 , 0 ) ;
2023-11-16 22:24:06 +01:00
ImGuiExt : : TextFormattedColored ( ImGuiExt : : GetCustomColorVec4 ( ImGuiCustomCol_Highlight ) , " {} " , line . substr ( boldStart + 2 , boldEnd - boldStart - 2 ) . c_str ( ) ) ;
2023-11-05 19:57:29 +01:00
ImGui : : SameLine ( 0 , 0 ) ;
ImGui : : TextUnformatted ( line . substr ( boldEnd + 2 ) . c_str ( ) ) ;
} else {
// Draw the line normally
ImGui : : TextUnformatted ( line . c_str ( ) ) ;
}
} ;
// Draw the release title
if ( ! releaseTitle . empty ( ) ) {
auto title = hex : : format ( " v{}: {} " , ImHexApi : : System : : getImHexVersion ( false ) , releaseTitle ) ;
2023-11-16 22:24:06 +01:00
ImGuiExt : : Header ( title . c_str ( ) , true ) ;
2023-11-05 19:57:29 +01:00
ImGui : : Separator ( ) ;
}
// Draw the release notes and format them using parts of the GitHub Markdown syntax
// This is not a full implementation of the syntax, but it's enough to make the release notes look good.
for ( const auto & line : releaseNotes ) {
if ( line . starts_with ( " ## " ) ) {
// Draw H2 Header
2023-11-16 22:24:06 +01:00
ImGuiExt : : Header ( line . substr ( 3 ) . c_str ( ) ) ;
2023-11-05 19:57:29 +01:00
} else if ( line . starts_with ( " ### " ) ) {
// Draw H3 Header
2023-11-16 22:24:06 +01:00
ImGuiExt : : Header ( line . substr ( 4 ) . c_str ( ) ) ;
2023-11-05 19:57:29 +01:00
} else if ( line . starts_with ( " - " ) ) {
// Draw bullet point
drawRegularLine ( line . substr ( 2 ) ) ;
} else if ( line . starts_with ( " - " ) ) {
// Draw further indented bullet point
ImGui : : Indent ( ) ;
ImGui : : Indent ( ) ;
drawRegularLine ( line . substr ( 6 ) ) ;
ImGui : : Unindent ( ) ;
ImGui : : Unindent ( ) ;
}
}
}
void ViewAbout : : drawCommitHistoryPage ( ) {
struct Commit {
std : : string hash ;
std : : string message ;
std : : string description ;
std : : string author ;
std : : string date ;
std : : string url ;
} ;
static std : : vector < Commit > commits ;
// Set up the request to get the commit history the first time the page is opened
AT_FIRST_TIME {
static HttpRequest request ( " GET " , GitHubApiURL + std : : string ( " /commits?per_page=100 " ) ) ;
this - > m_commitHistoryRequest = request . execute ( ) ;
} ;
// Wait for the request to finish and parse the response
if ( this - > m_commitHistoryRequest . valid ( ) ) {
if ( this - > m_commitHistoryRequest . wait_for ( std : : chrono : : seconds ( 0 ) ) = = std : : future_status : : ready ) {
auto response = this - > m_commitHistoryRequest . get ( ) ;
nlohmann : : json json ;
if ( response . isSuccess ( ) ) {
// A valid response was received, parse it
try {
json = nlohmann : : json : : parse ( response . getData ( ) ) ;
for ( auto & commit : json ) {
const auto message = commit [ " commit " ] [ " message " ] . get < std : : string > ( ) ;
// Split commit title and description. They're separated by two newlines.
const auto messageEnd = message . find ( " \n \n " ) ;
auto commitTitle = messageEnd = = std : : string : : npos ? message : message . substr ( 0 , messageEnd ) ;
auto commitDescription = messageEnd = = std : : string : : npos ? " " : message . substr ( commitTitle . size ( ) + 2 ) ;
auto url = commit [ " html_url " ] . get < std : : string > ( ) ;
auto sha = commit [ " sha " ] . get < std : : string > ( ) ;
auto date = commit [ " commit " ] [ " author " ] [ " date " ] . get < std : : string > ( ) ;
auto author = hex : : format ( " {} <{}> " ,
commit [ " commit " ] [ " author " ] [ " name " ] . get < std : : string > ( ) ,
commit [ " commit " ] [ " author " ] [ " email " ] . get < std : : string > ( )
) ;
// Move the commit data into the list of commits
commits . emplace_back (
std : : move ( sha ) ,
std : : move ( commitTitle ) ,
std : : move ( commitDescription ) ,
std : : move ( author ) ,
std : : move ( date ) ,
std : : move ( url )
) ;
}
} catch ( std : : exception & e ) {
commits . emplace_back (
" hex.builtin.common.error " _lang ,
e . what ( ) ,
" " ,
" " ,
" "
) ;
2022-01-24 00:45:46 +01:00
}
2023-11-05 19:57:29 +01:00
} else {
// An error occurred, display it
commits . emplace_back (
" hex.builtin.common.error " _lang ,
" HTTP " + std : : to_string ( response . getStatusCode ( ) ) ,
" " ,
" " ,
" "
) ;
2021-12-12 13:35:07 +01:00
}
2023-11-05 19:57:29 +01:00
} else {
// Draw a spinner while the commits are loading
2023-11-16 22:24:06 +01:00
ImGuiExt : : TextSpinner ( " hex.builtin.common.loading " _lang ) ;
2023-11-05 19:57:29 +01:00
}
}
2021-05-23 23:35:04 +02:00
2023-11-05 19:57:29 +01:00
// Draw commits table
if ( ! commits . empty ( ) ) {
2023-11-25 00:43:03 +01:00
ImGui : : PushStyleVar ( ImGuiStyleVar_WindowPadding , ImVec2 ( ) ) ;
ImGuiExt : : BeginSubWindow ( " Commits " , ImGui : : GetContentRegionAvail ( ) ) ;
{
if ( ImGui : : BeginTable ( " ##commits " , 2 , ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY ) ) {
// Draw commits
for ( const auto & commit : commits ) {
ImGui : : PushID ( commit . hash . c_str ( ) ) ;
ImGui : : TableNextRow ( ) ;
// Draw hover tooltip
ImGui : : TableNextColumn ( ) ;
if ( ImGui : : Selectable ( " ##commit " , false , ImGuiSelectableFlags_SpanAllColumns ) ) {
hex : : openWebpage ( commit . url ) ;
}
2023-11-05 19:57:29 +01:00
2023-11-25 00:43:03 +01:00
if ( ImGui : : IsItemHovered ( ) ) {
if ( ImGui : : BeginTooltip ( ) ) {
// Draw author and commit date
ImGuiExt : : TextFormattedColored ( ImGuiExt : : GetCustomColorVec4 ( ImGuiCustomCol_Highlight ) , " {} " , commit . author ) ;
ImGui : : SameLine ( ) ;
ImGuiExt : : TextFormatted ( " @ {} " , commit . date . c_str ( ) ) ;
// Draw description if there is one
if ( ! commit . description . empty ( ) ) {
ImGui : : Separator ( ) ;
ImGuiExt : : TextFormatted ( " {} " , commit . description ) ;
}
2020-11-14 21:16:03 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : EndTooltip ( ) ;
2023-11-05 19:57:29 +01:00
}
}
2023-11-25 00:43:03 +01:00
// Draw commit hash
ImGui : : SameLine ( 0 , 0 ) ;
ImGuiExt : : TextFormattedColored ( ImGuiExt : : GetCustomColorVec4 ( ImGuiCustomCol_Highlight ) , " {} " , commit . hash . substr ( 0 , 7 ) ) ;
2023-11-05 19:57:29 +01:00
2023-11-25 00:43:03 +01:00
// Draw the commit message
ImGui : : TableNextColumn ( ) ;
2023-11-05 19:57:29 +01:00
2023-11-25 00:43:03 +01:00
const ImColor color = [ & ] {
if ( commit . hash = = ImHexApi : : System : : getCommitHash ( true ) )
return ImGui : : GetStyleColorVec4 ( ImGuiCol_HeaderActive ) ;
else
return ImGui : : GetStyleColorVec4 ( ImGuiCol_Text ) ;
} ( ) ;
ImGuiExt : : TextFormattedColored ( color , commit . message ) ;
2023-11-05 19:57:29 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : PopID ( ) ;
}
2023-11-05 19:57:29 +01:00
2023-11-25 00:43:03 +01:00
ImGui : : EndTable ( ) ;
2021-12-12 13:35:07 +01:00
}
2023-11-05 19:57:29 +01:00
}
2023-11-25 00:43:03 +01:00
ImGuiExt : : EndSubWindow ( ) ;
ImGui : : PopStyleVar ( ) ;
2023-11-05 19:57:29 +01:00
}
}
void ViewAbout : : drawLicensePage ( ) {
2023-11-16 22:24:06 +01:00
ImGuiExt : : TextFormattedWrapped ( " {} " , romfs : : get ( " licenses/LICENSE " ) . string ( ) ) ;
2023-11-05 19:57:29 +01:00
}
void ViewAbout : : drawAboutPopup ( ) {
struct Tab {
using Function = void ( ViewAbout : : * ) ( ) ;
const char * unlocalizedName ;
Function function ;
} ;
constexpr std : : array Tabs = {
Tab { " ImHex " , & ViewAbout : : drawAboutMainPage } ,
Tab { " hex.builtin.view.help.about.contributor " , & ViewAbout : : drawContributorPage } ,
Tab { " hex.builtin.view.help.about.libs " , & ViewAbout : : drawLibraryCreditsPage } ,
Tab { " hex.builtin.view.help.about.paths " , & ViewAbout : : drawPathsPage } ,
Tab { " hex.builtin.view.help.about.release_notes " , & ViewAbout : : drawReleaseNotesPage } ,
Tab { " hex.builtin.view.help.about.commits " , & ViewAbout : : drawCommitHistoryPage } ,
Tab { " hex.builtin.view.help.about.license " , & ViewAbout : : drawLicensePage } ,
} ;
2023-11-21 13:47:50 +01:00
// Allow the window to be closed by pressing ESC
if ( ImGui : : IsKeyDown ( ImGui : : GetKeyIndex ( ImGuiKey_Escape ) ) )
ImGui : : CloseCurrentPopup ( ) ;
2023-11-05 19:57:29 +01:00
2023-11-21 13:47:50 +01:00
if ( ImGui : : BeginTabBar ( " about_tab_bar " ) ) {
// Draw all tabs
for ( const auto & [ unlocalizedName , function ] : Tabs ) {
2023-11-21 14:38:01 +01:00
if ( ImGui : : BeginTabItem ( Lang ( unlocalizedName ) ) ) {
2023-11-21 13:47:50 +01:00
ImGui : : NewLine ( ) ;
2023-11-05 19:57:29 +01:00
2023-11-21 13:47:50 +01:00
if ( ImGui : : BeginChild ( 1 ) ) {
( this - > * function ) ( ) ;
2022-01-24 00:45:46 +01:00
}
2023-11-21 13:47:50 +01:00
ImGui : : EndChild ( ) ;
2022-01-22 23:11:28 +01:00
2023-11-21 13:47:50 +01:00
ImGui : : EndTabItem ( ) ;
}
2021-12-12 13:35:07 +01:00
}
2020-11-30 21:44:40 +01:00
2023-11-21 13:47:50 +01:00
ImGui : : EndTabBar ( ) ;
2020-11-14 21:16:03 +01:00
}
}
2022-03-04 19:06:29 +01:00
void ViewAbout : : drawContent ( ) {
2020-11-17 13:59:16 +01:00
this - > drawAboutPopup ( ) ;
2020-11-14 21:16:03 +01:00
}
2021-08-25 19:54:59 +02:00
}