From 75686f15d497a93e8902de038f2dec4ed8a0a7b4 Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Fri, 8 Nov 2024 22:06:50 +0000 Subject: [PATCH] Fix up sample and add build scripts --- samples/CPlusPlusWidgets/.gitignore | 1 + samples/CPlusPlusWidgets/CMakeLists.txt | 11 +- samples/CPlusPlusWidgets/build-unix.sh | 28 +++++ samples/CPlusPlusWidgets/build-win.bat | 23 ++++ samples/CPlusPlusWidgets/main.cpp | 156 ++++++++++++++++-------- 5 files changed, 161 insertions(+), 58 deletions(-) create mode 100644 samples/CPlusPlusWidgets/build-unix.sh create mode 100644 samples/CPlusPlusWidgets/build-win.bat diff --git a/samples/CPlusPlusWidgets/.gitignore b/samples/CPlusPlusWidgets/.gitignore index 40683bd4..2e78d319 100644 --- a/samples/CPlusPlusWidgets/.gitignore +++ b/samples/CPlusPlusWidgets/.gitignore @@ -1,5 +1,6 @@ build build-dbg +build-rel .DS_Store cmake-build-debug cmake-build-release diff --git a/samples/CPlusPlusWidgets/CMakeLists.txt b/samples/CPlusPlusWidgets/CMakeLists.txt index 22f50512..610b46b7 100644 --- a/samples/CPlusPlusWidgets/CMakeLists.txt +++ b/samples/CPlusPlusWidgets/CMakeLists.txt @@ -20,15 +20,8 @@ FetchContent_MakeAvailable(wxWidgets) # include the Velopack library (headers + precompiled lib) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib-cpp/include") -if(CMAKE_BUILD_TYPE STREQUAL "Release") - message(STATUS "Building in Release mode") - set(VELOPACK_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/velopack_libc.dll.lib") - set(VELOPACK_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/velopack_libc.dll") -else() - message(STATUS "Building in Debug mode") - set(VELOPACK_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug/velopack_libc.dll.lib") - set(VELOPACK_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug/velopack_libc.dll") -endif() +set(VELOPACK_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug/velopack_libc.dll.lib") +set(VELOPACK_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../target/debug/velopack_libc.dll") # add sources and executable set(SRCS main.cpp) diff --git a/samples/CPlusPlusWidgets/build-unix.sh b/samples/CPlusPlusWidgets/build-unix.sh new file mode 100644 index 00000000..1e8b36e3 --- /dev/null +++ b/samples/CPlusPlusWidgets/build-unix.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Find the absolute path of the script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Check if version parameter is provided +if [ "$#" -ne 1 ]; then + echo "Version number is required." + echo "Usage: ./build.sh [version]" + exit 1 +fi + +BUILD_VERSION="$1" +RELEASE_DIR="$SCRIPT_DIR/releases" +PUBLISH_DIR="$SCRIPT_DIR/build-rel/Release" + +echo "" +echo "Compiling velopack_libc..." +cargo build -p velopack_libc + +echo "" +echo "Compiling VelopackCppWidgetsSample with cmake..." +cmake -S. -Bbuild-rel -DCMAKE_BUILD_TYPE=Release +cmake --build build-rel -j + +echo "" +echo "Building Velopack Release v$BUILD_VERSION" +vpk pack -u VelopackCSharpAvalonia -v $BUILD_VERSION -o "$RELEASE_DIR" -p "$PUBLISH_DIR" -e main \ No newline at end of file diff --git a/samples/CPlusPlusWidgets/build-win.bat b/samples/CPlusPlusWidgets/build-win.bat new file mode 100644 index 00000000..fbbed480 --- /dev/null +++ b/samples/CPlusPlusWidgets/build-win.bat @@ -0,0 +1,23 @@ +@echo off +setlocal enabledelayedexpansion + +if "%~1"=="" ( + echo Version number is required. + echo Usage: build.bat [version] [extra_args...] + exit /b 1 +) + +set "version=%~1" + +echo. +echo Compiling velopack_libc... +cargo build -p velopack_libc + +echo. +echo Compiling VelopackCppWidgetsSample with cmake... +cmake -S . -B build-rel +cmake --build build-rel -j --config Release + +echo. +echo Building Velopack Release v%version% +vpk pack -u VelopackCppWidgetsSample -o %~dp0releases -p %~dp0build-rel\Release -e main.exe -v %* \ No newline at end of file diff --git a/samples/CPlusPlusWidgets/main.cpp b/samples/CPlusPlusWidgets/main.cpp index 63642db9..113eb024 100644 --- a/samples/CPlusPlusWidgets/main.cpp +++ b/samples/CPlusPlusWidgets/main.cpp @@ -1,38 +1,18 @@ #include #include #include +#include #include "Velopack.h" using namespace Velopack; -std::optional updateManager; -std::optional updateInfo; -std::string logBuffer; - -std::optional get_or_create_update_manager() -{ - try - { - updateManager = UpdateManager(RELEASES_DIR); - } - catch (std::exception& ex) - { - std::string message = std::string("\n") + ex.what(); - logBuffer.append(message); - } - return updateManager; -} - -std::string get_status() -{ - return ""; -} - class MyFrame : public wxFrame { public: MyFrame() : wxFrame(nullptr, wxID_ANY, "VelopackCppWidgetsSample", wxDefaultPosition, wxSize(600, 600)) { + vpkc_set_logger(&MyFrame::HandleVpkcLogStatic, this); + // Set background color to white SetBackgroundColour(*wxWHITE); @@ -41,16 +21,20 @@ public: // Auto-wrapping text topText = new wxStaticText(this, wxID_ANY, - "This is a sample text that will automatically wrap based on the width of the window. " - "Resize the window to see the text wrap around."); - topText->Wrap(380); // Set wrap width close to the window width + "This is a sample text that will automatically wrap based on the width of the window. " + "Resize the window to see the text wrap around."); + topText->Wrap(380); // Set wrap width close to the window width mainSizer->Add(topText, 0, wxALL | wxEXPAND, 10); // Create a horizontal sizer for the buttons wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL); wxButton* button1 = new wxButton(this, wxID_ANY, "Check for Updates"); - wxButton* button2 = new wxButton(this, wxID_ANY, "Button 2"); - wxButton* button3 = new wxButton(this, wxID_ANY, "Button 3"); + wxButton* button2 = new wxButton(this, wxID_ANY, "Download Update"); + wxButton* button3 = new wxButton(this, wxID_ANY, "Restart & Apply"); + + button1->Bind(wxEVT_BUTTON, &MyFrame::OnCheckForUpdates, this); + button2->Bind(wxEVT_BUTTON, &MyFrame::OnDownloadUpdates, this); + button3->Bind(wxEVT_BUTTON, &MyFrame::OnApplyUpdates, this); // Add buttons to the button sizer buttonSizer->Add(button1, 0, wxALL, 5); @@ -69,34 +53,105 @@ public: SetSizer(mainSizer); mainSizer->Fit(this); - // Set up a timer for periodic updates - timer = new wxTimer(this); - Bind(wxEVT_TIMER, &MyFrame::OnTimer, this); - timer->Start(1000); // Trigger updates every second - } - - ~MyFrame() - { - timer->Stop(); - delete timer; + // initialise velopack + try + { + updateManager = std::make_unique(RELEASES_DIR); + topText->SetLabel("Current Version: " + updateManager->GetCurrentVersion()); + } + catch (std::exception& ex) + { + std::string message = ex.what() + std::string("\n"); + textArea->AppendText(message); + topText->SetLabel(message); + } } private: wxStaticText* topText; wxTextCtrl* textArea; - wxTimer* timer; - int updateCount = 0; + std::unique_ptr updateManager; + std::optional updateInfo; + bool downloaded = false; - void OnTimer(wxTimerEvent&) + void OnCheckForUpdates(wxCommandEvent& event) { - // Update the static text - topText->SetLabel(wxString::Format("Updated Text - %d", updateCount)); - topText->Wrap(380); // Re-wrap after changing text + if (!updateManager) + { + textArea->AppendText("Cannot check for updates. Install the app first.\n"); + return; + } - // Update the scrollable text area - textArea->AppendText(wxString::Format("Log Entry %d\n", updateCount)); + downloaded = false; + updateInfo = updateManager->CheckForUpdates(); - updateCount++; + if (updateInfo.has_value()) + { + topText->SetLabel("Update Found: " + updateInfo.value().TargetFullRelease.Version); + } + else + { + topText->SetLabel("No Update Found."); + } + } + + void OnDownloadUpdates(wxCommandEvent& event) + { + if (!updateManager || !updateInfo.has_value()) + { + textArea->AppendText("Cannot download updates. Check for updates first.\n"); + return; + } + + // start download on new thread + std::thread([this]() + { + updateManager->DownloadUpdates(updateInfo.value(), &MyFrame::HandleProgressCallbackStatic, this); + downloaded = true; + wxTheApp->CallAfter([this]() + { + topText->SetLabel("Download Complete."); + }); + }).detach(); + } + + void OnApplyUpdates(wxCommandEvent& event) + { + if (!updateManager || !downloaded) + { + textArea->AppendText("Cannot apply updates. Download updates first.\n"); + return; + } + + updateManager->WaitExitThenApplyUpdate(updateInfo.value()); + exit(0); + } + + void HandleVpkcLog(const char* pszLevel, const char* pszMessage) + { + std::string level(pszLevel); + std::string message(pszMessage); + textArea->AppendText(level + ": " + message + "\n"); + } + + static void HandleVpkcLogStatic(void* context, const char* pszLevel, const char* pszMessage) + { + MyFrame* instance = static_cast(context); + instance->HandleVpkcLog(pszLevel, pszMessage); + } + + void HandleProgressCallback(size_t progress) + { + wxTheApp->CallAfter([this, progress]() + { + topText->SetLabel("Download Progress: " + std::to_string(progress)); + }); + } + + static void HandleProgressCallbackStatic(void* pUserData, size_t progress) + { + MyFrame* instance = static_cast(pUserData); + instance->HandleProgressCallback(progress); } }; @@ -105,11 +160,14 @@ class MyApp : public wxApp public: virtual bool OnInit() { - get_or_create_update_manager(); + // Velopack should be the first thing to run in app startup, before any UI + // has been shown. Velopack may need to quit/restart the application at this point. + VelopackApp::Build().Run(); + MyFrame* frame = new MyFrame(); frame->Show(true); return true; } }; -wxIMPLEMENT_APP(MyApp); \ No newline at end of file +wxIMPLEMENT_APP(MyApp);