From 1cda4b778cd6131d9f9e6f0440e1c8e87d51feb0 Mon Sep 17 00:00:00 2001 From: Kaito Udagawa Date: Tue, 23 Apr 2024 03:26:28 +0900 Subject: [PATCH] Modest update notification (#178) * Fix * Fix * Fix * Fix * Format --- CMakeLists.txt | 12 +-- buildspec.json | 2 +- data/locale/en-US.ini | 3 + data/locale/ja-JP.ini | 3 + .../{CurlClient.cpp => CurlClient.hpp} | 26 +++--- src/UpdateChecker/CurlClient/CMakeLists.txt | 7 -- src/UpdateChecker/CurlClient/CurlClient.cpp | 44 ---------- src/UpdateChecker/GitHubClient.hpp | 70 +++++----------- .../URLSessionClient/CMakeLists.txt | 3 - .../URLSessionClient/URLSessionClient.mm | 41 ---------- src/UpdateChecker/UpdateChecker.cpp | 82 ------------------- src/UpdateChecker/UpdateChecker.h | 13 --- src/UpdateChecker/UpdateDialog.cpp | 58 ------------- src/UpdateChecker/UpdateDialog.hpp | 14 ---- .../WinRTHttpClient/CMakeLists.txt | 10 --- .../WinRTHttpClient/WinRTHttpClient.cpp | 41 ---------- src/plugin-main.c | 7 -- src/screen-source.cpp | 33 ++++++++ src/screen-source.hpp | 2 + 19 files changed, 78 insertions(+), 393 deletions(-) rename src/UpdateChecker/{CurlClient.cpp => CurlClient.hpp} (55%) delete mode 100644 src/UpdateChecker/CurlClient/CMakeLists.txt delete mode 100644 src/UpdateChecker/CurlClient/CurlClient.cpp delete mode 100644 src/UpdateChecker/URLSessionClient/CMakeLists.txt delete mode 100644 src/UpdateChecker/URLSessionClient/URLSessionClient.mm delete mode 100644 src/UpdateChecker/UpdateChecker.cpp delete mode 100644 src/UpdateChecker/UpdateChecker.h delete mode 100644 src/UpdateChecker/UpdateDialog.cpp delete mode 100644 src/UpdateChecker/UpdateDialog.hpp delete mode 100644 src/UpdateChecker/WinRTHttpClient/CMakeLists.txt delete mode 100644 src/UpdateChecker/WinRTHttpClient/WinRTHttpClient.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c88d865..21b5b2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,16 +34,8 @@ if(ENABLE_QT) AUTORCC ON) endif() -target_sources( - ${CMAKE_PROJECT_NAME} - PRIVATE src/plugin-main.c - src/screen-source.cpp - src/factory.cpp - src/ScreenBuilder/ActionHandler.cpp - src/ScreenBuilder/StateMachine.cpp - src/UpdateChecker/UpdateDialog.cpp - src/UpdateChecker/UpdateChecker.cpp - src/UpdateChecker/CurlClient.cpp) +target_sources(${CMAKE_PROJECT_NAME} PRIVATE src/plugin-main.c src/screen-source.cpp src/factory.cpp + src/ScreenBuilder/ActionHandler.cpp src/ScreenBuilder/StateMachine.cpp) include(cmake/FetchOpenCV.cmake) target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ${OpenCV_LIBS}) diff --git a/buildspec.json b/buildspec.json index ffe5662..a393b27 100644 --- a/buildspec.json +++ b/buildspec.json @@ -38,7 +38,7 @@ }, "name": "obs-pokemon-sv-screen-builder", "displayName": "OBS Pokémon SV Screen Builder", - "version": "0.7.4", + "version": "0.7.5", "author": "Kaito Udagawa", "website": "https://github.com/umireon/obs-pokemon-sv-screen-builder", "email": "umireon@gmail.com", diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index 134c72c..122e029 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -5,6 +5,9 @@ PokemonSVScreenBuilderOpponentRank="Pokémon SV (Opponent Rank)" PokemonSVScreenBuilderMyRank="Pokémon SV (My Rank)" GamePlaySource="Game Play Source" TimerSource="Timer Source" +VersionInfoTextLatest="OBS Pokémon SV Screen Builder 0.0.0 - This is the latest version" +VersionInfoTextUpdateAvailable="OBS Pokémon SV Screen Builder 0.0.0 - Update available!" +CustomDataDescription="Custom data" AddDefaultLayoutDescription="Add sources for default layout" MySelectionSource="My Selection" diff --git a/data/locale/ja-JP.ini b/data/locale/ja-JP.ini index 9f2f910..6f770a2 100644 --- a/data/locale/ja-JP.ini +++ b/data/locale/ja-JP.ini @@ -5,6 +5,9 @@ PokemonSVScreenBuilderOpponentRank="ポケモンSV(相手のランク)" PokemonSVScreenBuilderMyRank="ポケモンSV (自分のランク)" GamePlaySource="ゲーム画面ソース" TimerSource="タイマーソース" +VersionInfoTextLatest="OBSポケモンSVスクリーンビルダー 0.0.0 - 最新です" +VersionInfoTextUpdateAvailable="OBSポケモンSVスクリーンビルダー 0.0.0 - アップデートがあります!" +GoToDownloadPage="ダウンロードはこちら" AddDefaultLayoutDescription="デフォルトレイアウトのソースを追加" MySelectionSource="自分の選出" diff --git a/src/UpdateChecker/CurlClient.cpp b/src/UpdateChecker/CurlClient.hpp similarity index 55% rename from src/UpdateChecker/CurlClient.cpp rename to src/UpdateChecker/CurlClient.hpp index 4cd9f43..64e4242 100644 --- a/src/UpdateChecker/CurlClient.cpp +++ b/src/UpdateChecker/CurlClient.hpp @@ -1,4 +1,5 @@ -#include +#pragma once + #include #include @@ -7,38 +8,41 @@ #include "plugin-support.h" -const std::string userAgent = std::string(PLUGIN_NAME) + "/" + PLUGIN_VERSION; +namespace UpdateChecker { +static const std::string userAgent = + std::string(PLUGIN_NAME) + "/" + PLUGIN_VERSION; -static std::size_t writeFunc(void *ptr, std::size_t size, size_t nmemb, - std::string *data) +static std::size_t fetchStringFromUrlWriteFunc(void *ptr, std::size_t size, + size_t nmemb, std::string *data) { data->append(static_cast(ptr), size * nmemb); return size * nmemb; } -void fetchStringFromUrl(const char *urlString, - std::function callback) +static std::string fetchStringFromUrl(const char *urlString) { CURL *curl = curl_easy_init(); if (!curl) { obs_log(LOG_INFO, "Failed to initialize curl"); - callback("", CURL_LAST); - return; + return ""; } std::string responseBody; curl_easy_setopt(curl, CURLOPT_URL, urlString); curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, + fetchStringFromUrlWriteFunc); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseBody); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); CURLcode code = curl_easy_perform(curl); curl_easy_cleanup(curl); if (code == CURLE_OK) { - callback(responseBody, 0); + return responseBody; } else { obs_log(LOG_INFO, "Failed to get latest release info"); - callback("", code); + return ""; } } +} // namespace UpdateChecker diff --git a/src/UpdateChecker/CurlClient/CMakeLists.txt b/src/UpdateChecker/CurlClient/CMakeLists.txt deleted file mode 100644 index 601af8f..0000000 --- a/src/UpdateChecker/CurlClient/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_library(CurlClient CurlClient.cpp) -target_link_libraries(CurlClient PRIVATE OBS::libobs plugin-support) -target_include_directories(CurlClient PRIVATE "${CMAKE_SOURCE_DIR}/src") - -find_package(CURL REQUIRED) -target_link_libraries(CurlClient PRIVATE "${CURL_LIBRARIES}") -target_include_directories(CurlClient SYSTEM PRIVATE "${CURL_INCLUDE_DIRS}") diff --git a/src/UpdateChecker/CurlClient/CurlClient.cpp b/src/UpdateChecker/CurlClient/CurlClient.cpp deleted file mode 100644 index 4cd9f43..0000000 --- a/src/UpdateChecker/CurlClient/CurlClient.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -#include - -#include - -#include "plugin-support.h" - -const std::string userAgent = std::string(PLUGIN_NAME) + "/" + PLUGIN_VERSION; - -static std::size_t writeFunc(void *ptr, std::size_t size, size_t nmemb, - std::string *data) -{ - data->append(static_cast(ptr), size * nmemb); - return size * nmemb; -} - -void fetchStringFromUrl(const char *urlString, - std::function callback) -{ - CURL *curl = curl_easy_init(); - if (!curl) { - obs_log(LOG_INFO, "Failed to initialize curl"); - callback("", CURL_LAST); - return; - } - - std::string responseBody; - curl_easy_setopt(curl, CURLOPT_URL, urlString); - curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseBody); - - CURLcode code = curl_easy_perform(curl); - curl_easy_cleanup(curl); - - if (code == CURLE_OK) { - callback(responseBody, 0); - } else { - obs_log(LOG_INFO, "Failed to get latest release info"); - callback("", code); - } -} diff --git a/src/UpdateChecker/GitHubClient.hpp b/src/UpdateChecker/GitHubClient.hpp index 3da34cb..b9da3d4 100644 --- a/src/UpdateChecker/GitHubClient.hpp +++ b/src/UpdateChecker/GitHubClient.hpp @@ -2,61 +2,29 @@ #include -#include - #include #include "plugin-support.h" -void fetchStringFromUrl(const char *urlString, - std::function callback); - -class GitHubClient { -public: - struct LatestRelease { - std::string version; - std::string body; - bool error; - }; +#include "CurlClient.hpp" - void getLatestRelease(const char *latestReleaseUrl, - std::function callback) const - { - auto cb = [callback](std::string responseBody, int errorCode) { - if (errorCode != 0) { - obs_log(LOG_INFO, - "Failed to get the latest release info!"); - callback({"", "", true}); - return; - } - - obs_data_t *data = - obs_data_create_from_json(responseBody.c_str()); - if (!data) { - obs_log(LOG_INFO, - "Failed to parse the latest release info! %s", - responseBody.c_str()); - callback({"", "", true}); - return; - } +namespace UpdateChecker { +std::string getLatestReleaseVersion(const char *latestReleaseUrl) +{ + std::string responseBody = fetchStringFromUrl(latestReleaseUrl); + if (responseBody.empty()) { + obs_log(LOG_INFO, "Failed to get the latest release info!"); + return ""; + } - LatestRelease result; - const char *version = - obs_data_get_string(data, "tag_name"); - const char *body = obs_data_get_string(data, "body"); - if (!version || !body) { - obs_log(LOG_INFO, - "Malformed JSON from GitHub!"); - result.error = true; - } else { - result.version = - obs_data_get_string(data, "tag_name"); - result.body = obs_data_get_string(data, "body"); - result.error = false; - } - obs_data_release(data); - callback(result); - }; - fetchStringFromUrl(latestReleaseUrl, cb); + obs_data_t *data = obs_data_create_from_json(responseBody.c_str()); + const char *rawVersion = obs_data_get_string(data, "tag_name"); + if (!rawVersion) { + obs_log(LOG_INFO, "Malformed JSON from GitHub!"); + return ""; } -}; + std::string version = rawVersion; + obs_data_release(data); + return version; +} +} // namespace UpdateChecker diff --git a/src/UpdateChecker/URLSessionClient/CMakeLists.txt b/src/UpdateChecker/URLSessionClient/CMakeLists.txt deleted file mode 100644 index cc911cb..0000000 --- a/src/UpdateChecker/URLSessionClient/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_library(URLSessionClient URLSessionClient.mm) -target_link_libraries(URLSessionClient PRIVATE OBS::libobs plugin-support) -target_include_directories(URLSessionClient PRIVATE "${CMAKE_SOURCE_DIR}/src") diff --git a/src/UpdateChecker/URLSessionClient/URLSessionClient.mm b/src/UpdateChecker/URLSessionClient/URLSessionClient.mm deleted file mode 100644 index ed5cda5..0000000 --- a/src/UpdateChecker/URLSessionClient/URLSessionClient.mm +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include - -#include - -#include - -#include "plugin-support.h" - -void dispatch(const std::function &callback, std::string responseBody, int errorCode) -{ - dispatch_async(dispatch_get_main_queue(), ^{ - callback(responseBody, errorCode); - }); -} - -void fetchStringFromUrl(const char *urlString, std::function callback) -{ - NSString *urlNsString = [[NSString alloc] initWithUTF8String:urlString]; - NSURLSession *session = [NSURLSession sharedSession]; - NSURL *url = [NSURL URLWithString:urlNsString]; - NSURLSessionDataTask *task = [session - dataTaskWithURL:url - completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) { - if (error != NULL) { - dispatch(callback, "", 1); - } else if (response == NULL) { - dispatch(callback, "", 2); - } else if (data == NULL || data.length == 0) { - dispatch(callback, "", 3); - } else if (![response isKindOfClass:NSHTTPURLResponse.class]) { - dispatch(callback, "", 4); - } else { - std::string responseBody((const char *) data.bytes, data.length); - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response; - NSInteger code = httpResponse.statusCode; - dispatch(callback, responseBody, code < 200 || code > 299 ? 5 : 0); - } - }]; - [task resume]; -} diff --git a/src/UpdateChecker/UpdateChecker.cpp b/src/UpdateChecker/UpdateChecker.cpp deleted file mode 100644 index 3f95796..0000000 --- a/src/UpdateChecker/UpdateChecker.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include - -#include - -#include -#include -#include - -#include "UpdateDialog.hpp" -#include "GitHubClient.hpp" -#include - -#include "UpdateChecker.h" - -config_t *checkUpdateConfig = nullptr; -UpdateDialog *updateDialog = nullptr; - -static bool getIsSkipping(config_t *config, std::string latestVersion) -{ - if (latestVersion == PLUGIN_VERSION) { - return true; - } - - bool skip = config_get_bool(config, "check-update", "skip"); - if (!skip) { - return false; - } - - const char *skipVersion = - config_get_string(config, "check-update", "skip-version"); - return skipVersion != nullptr && skipVersion == latestVersion; -} - -void update_checker_check_update(const char *latest_release_url) -{ - std::string currentTag = std::string("v") + PLUGIN_VERSION; - GitHubClient client; - auto cb = [currentTag](GitHubClient::LatestRelease result) { - if (result.error) { - obs_log(LOG_INFO, - "Failed to fetch latest release info!"); - return; - } - if (result.version == currentTag) { - obs_log(LOG_INFO, "This plugin is latest!"); - return; - } - - char *configDirDstr = obs_module_config_path(""); - std::filesystem::create_directories(configDirDstr); - bfree(configDirDstr); - - char *configDstr = obs_module_config_path("update-checker.ini"); - int configResult = config_open(&checkUpdateConfig, configDstr, - CONFIG_OPEN_ALWAYS); - bfree(configDstr); - if (configResult != CONFIG_SUCCESS) { - obs_log(LOG_ERROR, - "Update checker config cennot be opened!"); - return; - } - if (getIsSkipping(checkUpdateConfig, result.version.c_str())) { - obs_log(LOG_INFO, "Checking update skipped!"); - return; - } - - obs_log(LOG_INFO, "Update available!"); - - updateDialog = new UpdateDialog( - result.version, result.body, checkUpdateConfig, - (QWidget *)obs_frontend_get_main_window()); - QTimer::singleShot(2000, updateDialog, &UpdateDialog::exec); - }; - client.getLatestRelease(latest_release_url, cb); -} - -void update_checker_close(void) -{ - if (checkUpdateConfig) { - config_close(checkUpdateConfig); - } -} diff --git a/src/UpdateChecker/UpdateChecker.h b/src/UpdateChecker/UpdateChecker.h deleted file mode 100644 index 7fdf092..0000000 --- a/src/UpdateChecker/UpdateChecker.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -void update_checker_check_update(const char *latest_release_url); - -void update_checker_close(void); - -#ifdef __cplusplus -} -#endif diff --git a/src/UpdateChecker/UpdateDialog.cpp b/src/UpdateChecker/UpdateDialog.cpp deleted file mode 100644 index e02e420..0000000 --- a/src/UpdateChecker/UpdateDialog.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include -#include - -#include "UpdateDialog.hpp" - -static QString dialogContent = - "

ポケモンSVスクリーンビルダー - {version}! 🚀

" - "

新バージョンが利用可能です!以下のURLをクリックするとダウンロードページが表示されます!" - "

https://github.com/umireon/obs-pokemon-sv-screen-builder/releases

" - "

更新履歴

"; - -UpdateDialog::UpdateDialog(std::string latestVersion, - std::string latestChangelog, config_t *config, - QWidget *parent = nullptr) - : QDialog(parent), - layout(new QVBoxLayout) -{ - setWindowTitle("ポケモンSVスクリーンビルダー - 更新が利用可能!"); - setLayout(layout); - QLabel *label = new QLabel(dialogContent.replace( - QString("{version}"), latestVersion.c_str())); - label->setOpenExternalLinks(true); - label->setTextInteractionFlags(Qt::TextBrowserInteraction); - label->setTextFormat(Qt::RichText); - label->setWordWrap(true); - layout->addWidget(label); - - QScrollArea *scrollArea = new QScrollArea; - QLabel *scrollAreaLabel = new QLabel(latestChangelog.c_str()); - scrollAreaLabel->setOpenExternalLinks(true); - scrollAreaLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - scrollAreaLabel->setTextFormat(Qt::MarkdownText); - scrollAreaLabel->setWordWrap(true); - scrollArea->setWidget(scrollAreaLabel); - scrollArea->setWidgetResizable(true); - layout->addWidget(scrollArea); - - // Add a checkbox to disable update checks - QCheckBox *disableCheckbox = new QCheckBox("更新通知をオフにする"); - layout->addWidget(disableCheckbox); - connect(disableCheckbox, &QCheckBox::stateChanged, - [this, latestVersion, config](int state) { - config_set_bool(config, "check-update", "skip", - state != Qt::Unchecked); - config_set_string(config, "check-update", - "skip-version", - latestVersion.c_str()); - config_save_safe(config, "tmp", nullptr); - }); - - // Add a button to close the dialog - QPushButton *closeButton = new QPushButton("Close"); - layout->addWidget(closeButton); - connect(closeButton, &QPushButton::clicked, this, &QDialog::close); -} diff --git a/src/UpdateChecker/UpdateDialog.hpp b/src/UpdateChecker/UpdateDialog.hpp deleted file mode 100644 index c5f7b94..0000000 --- a/src/UpdateChecker/UpdateDialog.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -#include - -class UpdateDialog : public QDialog { - Q_OBJECT -public: - UpdateDialog(std::string latestVersion, std::string latestChangelog, - config_t *config, QWidget *parent); - -private: - QVBoxLayout *layout; -}; diff --git a/src/UpdateChecker/WinRTHttpClient/CMakeLists.txt b/src/UpdateChecker/WinRTHttpClient/CMakeLists.txt deleted file mode 100644 index 7652824..0000000 --- a/src/UpdateChecker/WinRTHttpClient/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_library(WinRTHttpClient WinRTHttpClient.cpp) -set_target_properties( - WinRTHttpClient - PROPERTIES CXX_STANDARD 17 - CXX_STANDARD_REQUIRED ON - CXX_EXTENSIONS OFF - VS_GLOBAL_CppWinRTOptimized true - VS_GLOBAL_CppWinRTRootNamespaceAutoMerge true) -target_link_libraries(WinRTHttpClient PRIVATE OBS::libobs plugin-support) -target_include_directories(WinRTHttpClient PRIVATE "${CMAKE_SOURCE_DIR}/src") diff --git a/src/UpdateChecker/WinRTHttpClient/WinRTHttpClient.cpp b/src/UpdateChecker/WinRTHttpClient/WinRTHttpClient.cpp deleted file mode 100644 index 3deeca7..0000000 --- a/src/UpdateChecker/WinRTHttpClient/WinRTHttpClient.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include -#include -#include - -#include "plugin-support.h" - -using winrt::Windows::Foundation::Uri; -using winrt::Windows::Storage::Streams::IBuffer; -using winrt::Windows::Web::Http::HttpClient; -using winrt::Windows::Web::Http::HttpResponseMessage; -using winrt::Windows::Web::Http::IHttpContent; - -const winrt::hstring userAgent = winrt::to_hstring(PLUGIN_NAME) + L"/" + - winrt::to_hstring(PLUGIN_VERSION); - -void fetchStringFromUrl(const char *urlString, - std::function callback) -{ - HttpClient httpClient; - auto headers(httpClient.DefaultRequestHeaders()); - headers.UserAgent().TryParseAdd(userAgent); - Uri requestUri(winrt::to_hstring(urlString)); - HttpResponseMessage httpResponseMessage; - IBuffer httpResponseBuffer; - try { - httpResponseMessage = httpClient.GetAsync(requestUri).get(); - httpResponseMessage.EnsureSuccessStatusCode(); - IHttpContent httpContent = httpResponseMessage.Content(); - httpResponseBuffer = httpContent.ReadAsBufferAsync().get(); - - uint8_t *data = httpResponseBuffer.data(); - std::string str((const char *)data, - httpResponseBuffer.Length()); - callback(str, 0); - } catch (winrt::hresult_error const &ex) { - std::string str(winrt::to_string(ex.message())); - callback(str, 1); - } -} \ No newline at end of file diff --git a/src/plugin-main.c b/src/plugin-main.c index 9e404eb..581109e 100644 --- a/src/plugin-main.c +++ b/src/plugin-main.c @@ -2,8 +2,6 @@ #include -#include "UpdateChecker/UpdateChecker.h" - const char *screen_get_name(void *unused); void *screen_create(obs_data_t *settings, obs_source_t *source); void screen_destroy(void *data); @@ -36,15 +34,10 @@ bool obs_module_load(void) obs_log(LOG_INFO, "plugin loaded successfully (version %s)", PLUGIN_VERSION); - const char UPDATE_URL[] = - "https://api.github.com/repos/umireon/obs-pokemon-sv-screen-builder/releases/latest"; - update_checker_check_update(UPDATE_URL); - return true; } void obs_module_unload() { - update_checker_close(); obs_log(LOG_INFO, "plugin unloaded"); } diff --git a/src/screen-source.cpp b/src/screen-source.cpp index 51c5437..ff7d676 100644 --- a/src/screen-source.cpp +++ b/src/screen-source.cpp @@ -15,10 +15,17 @@ #include #include "screen-source.hpp" + #include "plugin-support.h" +#include "UpdateChecker/GitHubClient.hpp" namespace fs = std::filesystem; +const char LATEST_RELEASE_API_URL[] = + "https://api.github.com/repos/kaito-tokyo/obs-pokemon-sv-screen-builder/releases/latest"; +const char LATEST_RELEASE_LINK[] = + R"(https://github.com/kaito-tokyo/obs-pokemon-sv-screen-builder/releases/latest<>)"; + static void screen_main_render_callback(void *data, uint32_t cx, uint32_t cy) try { if (!data) { @@ -308,6 +315,8 @@ extern "C" obs_properties_t *screen_properties(void *data) return nullptr; } + screen_context *context = static_cast(data); + obs_properties_t *props = obs_properties_create(); obs_properties_add_button( @@ -335,6 +344,30 @@ extern "C" obs_properties_t *screen_properties(void *data) obs_module_text("CustomDataDescription"), OBS_TEXT_MULTILINE); + if (context->latestVersion.empty()) { + context->latestVersion = UpdateChecker::getLatestReleaseVersion( + LATEST_RELEASE_API_URL); + } + + std::string versionInfoText; + + if (context->latestVersion == PLUGIN_VERSION) { + versionInfoText = obs_module_text("VersionInfoTextLatest"); + } else { + versionInfoText = + obs_module_text("VersionInfoTextUpdateAvailable"); + } + + std::regex versionPattern(R"(0\.0\.0)"); + std::string replacedVersionInfoText = std::regex_replace( + versionInfoText, versionPattern, PLUGIN_VERSION); + + obs_properties_add_text(props, "version_info", + replacedVersionInfoText.c_str(), OBS_TEXT_INFO); + + obs_properties_add_text(props, "go_to_download_page", + LATEST_RELEASE_LINK, OBS_TEXT_INFO); + return props; } diff --git a/src/screen-source.hpp b/src/screen-source.hpp index de9d42f..23d7f29 100644 --- a/src/screen-source.hpp +++ b/src/screen-source.hpp @@ -22,6 +22,8 @@ struct screen_context { gs_stagesurf_t *stagesurface = nullptr; cv::Mat gameplayBGRA; + std::string latestVersion; + MyPokemonCropper myPokemonCropper; OpponentPokemonCropper opponentPokemonCropper; ResultCropper resultCropper;