mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-28 07:47:03 -05:00
feat: Add option to check for updates to the Extras menu
This commit is contained in:
@@ -680,6 +680,12 @@ EXPORT_MODULE namespace hex {
|
||||
*/
|
||||
bool isNightlyBuild();
|
||||
|
||||
/**
|
||||
* @brief Checks if there's an update available for the current version of ImHex
|
||||
* @return Optional string returning the version string of the new version, or std::nullopt if no update is available
|
||||
*/
|
||||
std::optional<std::string> checkForUpdate();
|
||||
|
||||
enum class UpdateType {
|
||||
Stable,
|
||||
Nightly
|
||||
|
||||
@@ -26,8 +26,11 @@
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <hex/api_urls.hpp>
|
||||
#include <hex/helpers/http_requests.hpp>
|
||||
|
||||
#include <hex/helpers/utils_macos.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
#include <windows.h>
|
||||
@@ -941,6 +944,73 @@ namespace hex {
|
||||
return getImHexVersion().nightly();
|
||||
}
|
||||
|
||||
std::optional<std::string> checkForUpdate() {
|
||||
#if defined(OS_WEB)
|
||||
return std::nullopt;
|
||||
#else
|
||||
if (ImHexApi::System::isNightlyBuild()) {
|
||||
HttpRequest request("GET", GitHubApiURL + std::string("/releases/tags/nightly"));
|
||||
request.setTimeout(10000);
|
||||
|
||||
// Query the GitHub API for the latest release version
|
||||
auto response = request.execute().get();
|
||||
if (response.getStatusCode() != 200)
|
||||
return std::nullopt;
|
||||
|
||||
nlohmann::json releases;
|
||||
try {
|
||||
releases = nlohmann::json::parse(response.getData());
|
||||
} catch (const std::exception &) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Check if the response is valid
|
||||
if (!releases.contains("assets") || !releases["assets"].is_array())
|
||||
return std::nullopt;
|
||||
|
||||
const auto firstAsset = releases["assets"].front();
|
||||
if (!firstAsset.is_object() || !firstAsset.contains("updated_at"))
|
||||
return std::nullopt;
|
||||
|
||||
const auto nightlyUpdateTime = hex::parseTime("%Y-%m-%dT%H:%M:%SZ", firstAsset["updated_at"].get<std::string>());
|
||||
const auto imhexBuildTime = ImHexApi::System::getBuildTime();
|
||||
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime) {
|
||||
return "Nightly";
|
||||
}
|
||||
} else {
|
||||
HttpRequest request("GET", GitHubApiURL + std::string("/releases/latest"));
|
||||
|
||||
// Query the GitHub API for the latest release version
|
||||
auto response = request.execute().get();
|
||||
if (response.getStatusCode() != 200)
|
||||
return std::nullopt;
|
||||
|
||||
nlohmann::json releases;
|
||||
try {
|
||||
releases = nlohmann::json::parse(response.getData());
|
||||
} catch (const std::exception &) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Check if the response is valid
|
||||
if (!releases.contains("tag_name") || !releases["tag_name"].is_string())
|
||||
return std::nullopt;
|
||||
|
||||
// Convert the current version string to a format that can be compared to the latest release
|
||||
auto currVersion = "v" + ImHexApi::System::getImHexVersion().get(false);
|
||||
|
||||
// Get the latest release version string
|
||||
auto latestVersion = releases["tag_name"].get<std::string>();
|
||||
|
||||
// Check if the latest release is different from the current version
|
||||
if (latestVersion != currVersion)
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool updateImHex(UpdateType updateType) {
|
||||
#if defined(OS_WEB)
|
||||
switch (updateType) {
|
||||
|
||||
@@ -128,6 +128,7 @@
|
||||
"hex.builtin.view.hex_editor.menu.edit.redo": "Redo",
|
||||
"hex.builtin.view.hex_editor.menu.edit.undo": "Undo",
|
||||
"hex.builtin.menu.extras": "Extras",
|
||||
"hex.builtin.menu.extras.check_for_update": "Check for Updates",
|
||||
"hex.builtin.menu.extras.switch_to_stable": "Downgrade to Release",
|
||||
"hex.builtin.menu.extras.switch_to_nightly": "Update to Nightly",
|
||||
"hex.builtin.menu.file": "File",
|
||||
@@ -411,6 +412,8 @@
|
||||
"hex.builtin.popup.blocking_task.desc": "A task is currently executing.",
|
||||
"hex.builtin.popup.save_layout.title": "Save Layout",
|
||||
"hex.builtin.popup.save_layout.desc": "Enter a name under which to save the current layout.",
|
||||
"hex.builtin.popup.no_update_available": "No new update available",
|
||||
"hex.builtin.popup.update_available": "A new version of ImHex is available!\n\nWould you like to update to '{0}'?",
|
||||
"hex.builtin.popup.waiting_for_tasks.desc": "There are still tasks running in the background.\nImHex will close after they are finished.",
|
||||
"hex.builtin.provider.rename": "Rename",
|
||||
"hex.builtin.provider.rename.desc": "Enter a name for this data source.",
|
||||
|
||||
@@ -33,67 +33,9 @@ namespace hex::plugin::builtin {
|
||||
|
||||
// Check if we should check for updates
|
||||
TaskManager::createBackgroundTask("Update Check", [] {
|
||||
std::string updateString;
|
||||
if (ImHexApi::System::isNightlyBuild()) {
|
||||
HttpRequest request("GET", GitHubApiURL + "/releases/tags/nightly"s);
|
||||
request.setTimeout(10000);
|
||||
const auto updateString = ImHexApi::System::checkForUpdate();
|
||||
|
||||
// Query the GitHub API for the latest release version
|
||||
auto response = request.execute().get();
|
||||
if (response.getStatusCode() != 200)
|
||||
return;
|
||||
|
||||
nlohmann::json releases;
|
||||
try {
|
||||
releases = nlohmann::json::parse(response.getData());
|
||||
} catch (const std::exception &) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the response is valid
|
||||
if (!releases.contains("assets") || !releases["assets"].is_array())
|
||||
return;
|
||||
|
||||
const auto firstAsset = releases["assets"].front();
|
||||
if (!firstAsset.is_object() || !firstAsset.contains("updated_at"))
|
||||
return;
|
||||
|
||||
const auto nightlyUpdateTime = hex::parseTime("%Y-%m-%dT%H:%M:%SZ", firstAsset["updated_at"].get<std::string>());
|
||||
const auto imhexBuildTime = ImHexApi::System::getBuildTime();
|
||||
if (nightlyUpdateTime.has_value() && imhexBuildTime.has_value() && *nightlyUpdateTime > *imhexBuildTime) {
|
||||
updateString = "Nightly";
|
||||
}
|
||||
} else {
|
||||
HttpRequest request("GET", GitHubApiURL + "/releases/latest"s);
|
||||
|
||||
// Query the GitHub API for the latest release version
|
||||
auto response = request.execute().get();
|
||||
if (response.getStatusCode() != 200)
|
||||
return;
|
||||
|
||||
nlohmann::json releases;
|
||||
try {
|
||||
releases = nlohmann::json::parse(response.getData());
|
||||
} catch (const std::exception &) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the response is valid
|
||||
if (!releases.contains("tag_name") || !releases["tag_name"].is_string())
|
||||
return;
|
||||
|
||||
// Convert the current version string to a format that can be compared to the latest release
|
||||
auto currVersion = "v" + ImHexApi::System::getImHexVersion().get(false);
|
||||
|
||||
// Get the latest release version string
|
||||
auto latestVersion = releases["tag_name"].get<std::string_view>();
|
||||
|
||||
// Check if the latest release is different from the current version
|
||||
if (latestVersion != currVersion)
|
||||
updateString = latestVersion;
|
||||
}
|
||||
|
||||
if (updateString.empty())
|
||||
if (!updateString.has_value())
|
||||
return;
|
||||
|
||||
TaskManager::doLater([updateString] {
|
||||
@@ -101,7 +43,7 @@ namespace hex::plugin::builtin {
|
||||
ImHexApi::System::updateImHex(ImHexApi::System::isNightlyBuild() ? ImHexApi::System::UpdateType::Nightly : ImHexApi::System::UpdateType::Stable);
|
||||
});
|
||||
|
||||
ui::ToastInfo::open(fmt::format("hex.builtin.welcome.update.desc"_lang, updateString));
|
||||
ui::ToastInfo::open(fmt::format("hex.builtin.welcome.update.desc"_lang, *updateString));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <hex/helpers/menu_items.hpp>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <popups/popup_question.hpp>
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
using namespace wolv::literals;
|
||||
@@ -634,6 +635,22 @@ namespace hex::plugin::builtin {
|
||||
static void createExtrasMenu() {
|
||||
ContentRegistry::Interface::registerMainMenuItem("hex.builtin.menu.extras", 5000);
|
||||
|
||||
ContentRegistry::Interface::addMenuItemSeparator({ "hex.builtin.menu.extras" }, 2600);
|
||||
|
||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.extras", "hex.builtin.menu.extras.check_for_update" }, ICON_VS_SYNC, 2700, Shortcut::None, [] {
|
||||
TaskManager::createBackgroundTask("Checking for updates", [] {
|
||||
auto versionString = ImHexApi::System::checkForUpdate();
|
||||
if (!versionString.has_value()) {
|
||||
ui::ToastInfo::open("hex.builtin.popup.no_update_available"_lang);
|
||||
return;
|
||||
}
|
||||
|
||||
ui::PopupQuestion::open(fmt::format(fmt::runtime("hex.builtin.popup.update_available"_lang.get()), versionString.value()), [] {
|
||||
ImHexApi::System::updateImHex(ImHexApi::System::isNightlyBuild() ? ImHexApi::System::UpdateType::Nightly : ImHexApi::System::UpdateType::Stable);
|
||||
}, [] { });
|
||||
});
|
||||
});
|
||||
|
||||
if (ImHexApi::System::isNightlyBuild()) {
|
||||
ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.extras", "hex.builtin.menu.extras.switch_to_stable" }, ICON_VS_ROCKET, 2750, Shortcut::None, [] {
|
||||
ImHexApi::System::updateImHex(ImHexApi::System::UpdateType::Stable);
|
||||
|
||||
Reference in New Issue
Block a user