Skip to content

Commit

Permalink
✨ If versions have not been fetched yet, wait before trying to instal…
Browse files Browse the repository at this point in the history
…l it
  • Loading branch information
JulesFouchy committed Dec 22, 2024
1 parent 3763344 commit 8547176
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Lab
Submodule Lab updated 2 files
+1 −1 Cool
+1 −1 lib/cpp-httplib
1 change: 1 addition & 0 deletions src/Task_CheckForLongPathsEnabled.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Task_CheckForLongPathsEnabled : public Cool::Task {
void do_work() override;
void cancel() override {}
auto needs_user_confirmation_to_cancel_when_closing_app() const -> bool override { return false; }
auto name() const -> std::string override { return "Checking if Long Paths are enabled in the Windows settings"; }

private:
std::optional<ImGuiNotify::NotificationId> _notification_id{};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "Task_FindVersionsAvailableOnline.hpp"
#include "Task_FetchListOfVersions.hpp"
#include "Cool/DebugOptions/DebugOptions.h"
#include "Cool/Log/ToUser.h"
#include "Cool/Task/TaskManager.hpp"
Expand All @@ -24,7 +24,7 @@ auto is_zip_download(std::string const& download_url) -> bool
return download_url.find(get_OS() + ".zip") != std::string::npos;
}

void Task_FindVersionsAvailableOnline::do_work()
void Task_FetchListOfVersions::do_work()
{
auto cli = httplib::Client{"https://api.github.com"};
cli.set_follow_location(true);
Expand Down Expand Up @@ -76,7 +76,7 @@ void Task_FindVersionsAvailableOnline::do_work()
ImGuiNotify::close_immediately(*_warning_notification_id);
}

void Task_FindVersionsAvailableOnline::handle_error(httplib::Result const& res)
void Task_FetchListOfVersions::handle_error(httplib::Result const& res)
{
if (Cool::DebugOptions::log_debug_warnings())
{
Expand Down Expand Up @@ -123,5 +123,5 @@ void Task_FindVersionsAvailableOnline::handle_error(httplib::Result const& res)
ImGuiNotify::change(*_warning_notification_id, notification);

if (!res || message) // Only retry if we failed because we don't have an Internet connection, or because we hit the max number of requests to Github. There is no point in retrying if the service is unavailable, it's probably not gonna get fixed soon, and if we make too many requests to their API, Github will block us
Cool::task_manager().submit_in(message ? duration_until_reset : 1s, std::make_shared<Task_FindVersionsAvailableOnline>(_warning_notification_id));
Cool::task_manager().submit_in(message ? duration_until_reset : 1s, std::make_shared<Task_FetchListOfVersions>(_warning_notification_id));
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
#include "Cool/Task/Task.hpp"
#include "ImGuiNotify/ImGuiNotify.hpp"

class Task_FindVersionsAvailableOnline : public Cool::Task {
class Task_FetchListOfVersions : public Cool::Task {
public:
explicit Task_FindVersionsAvailableOnline(std::optional<ImGuiNotify::NotificationId> warning_notification_id = {})
explicit Task_FetchListOfVersions(std::optional<ImGuiNotify::NotificationId> warning_notification_id = {})
: _warning_notification_id{warning_notification_id}
{}

void do_work() override;
void cancel() override { _cancel.store(true); }
auto needs_user_confirmation_to_cancel_when_closing_app() const -> bool override { return false; }
auto name() const -> std::string override { return "Fetching the list of versions that are available online"; }

private:
void handle_error(httplib::Result const& res);
Expand Down
50 changes: 27 additions & 23 deletions src/Version/Task_InstallVersion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,42 +137,46 @@ static auto make_file_executable(std::filesystem::path const& path) -> tl::expec
return {};
}

Task_InstallVersion::Task_InstallVersion(VersionName name, std::string download_url)
: _name{std::move(name)}
Task_InstallVersion::Task_InstallVersion(VersionName version_name, std::string download_url, ImGuiNotify::NotificationId notification_id)
: _version_name{std::move(version_name)}
, _download_url{std::move(download_url)}
, _notification_id{notification_id}
{
_notification_id = ImGuiNotify::send({
.type = ImGuiNotify::Type::Info,
.title = fmt::format("Installing {}", _name.as_string()),
.custom_imgui_content = [data = _data]() {
Cool::ImGuiExtras::disabled_if(data->cancel.load(), "", [&]() {
ImGui::ProgressBar(data->download_progress.load() * 0.9f + 0.1f * data->extraction_progress.load());
if (ImGui::Button("Cancel"))
data->cancel.store(true);
});
},
.duration = std::nullopt,
.is_closable = false,
});
ImGuiNotify::change(
_notification_id,
{
.type = ImGuiNotify::Type::Info,
.title = name(),
.custom_imgui_content = [data = _data]() {
Cool::ImGuiExtras::disabled_if(data->cancel.load(), "", [&]() {
ImGui::ProgressBar(data->download_progress.load() * 0.9f + 0.1f * data->extraction_progress.load());
if (ImGui::Button("Cancel"))
data->cancel.store(true);
});
},
.duration = std::nullopt,
.is_closable = false,
}
);
}

void Task_InstallVersion::on_success()
{
version_manager().set_installation_status(_name, InstallationStatus::Installed);
version_manager().set_installation_status(_version_name, InstallationStatus::Installed);
ImGuiNotify::change(
_notification_id,
{
.type = ImGuiNotify::Type::Success,
.title = fmt::format("Installed {}", _name.as_string()),
.title = fmt::format("Installed {}", _version_name.as_string()),
.content = "Success",
}
);
}

void Task_InstallVersion::on_version_not_installed()
{
version_manager().set_installation_status(_name, InstallationStatus::NotInstalled);
Cool::File::remove_folder(installation_path(_name)); // Cleanup any files that we might have started to extract from the zip
version_manager().set_installation_status(_version_name, InstallationStatus::NotInstalled);
Cool::File::remove_folder(installation_path(_version_name)); // Cleanup any files that we might have started to extract from the zip
}

void Task_InstallVersion::on_cancel()
Expand All @@ -188,7 +192,7 @@ void Task_InstallVersion::on_error(std::string const& error_message)
_notification_id,
{
.type = ImGuiNotify::Type::Error,
.title = fmt::format("Installation failed ({})", _name.as_string()),
.title = fmt::format("Installation failed ({})", _version_name.as_string()),
.content = error_message,
.duration = std::nullopt,
}
Expand All @@ -197,7 +201,7 @@ void Task_InstallVersion::on_error(std::string const& error_message)

void Task_InstallVersion::do_work()
{
version_manager().set_installation_status(_name, InstallationStatus::Installing); // TODO(Launcher) should be done in constructor
version_manager().set_installation_status(_version_name, InstallationStatus::Installing); // TODO(Launcher) should be done in constructor

auto const zip = download_zip(_download_url, _data->download_progress, _data->cancel);
if (_data->cancel.load())
Expand All @@ -211,7 +215,7 @@ void Task_InstallVersion::do_work()
return;
}
{
auto const success = extract_zip(*zip, installation_path(_name), _data->extraction_progress, _data->cancel);
auto const success = extract_zip(*zip, installation_path(_version_name), _data->extraction_progress, _data->cancel);
if (_data->cancel.load())
{
on_cancel();
Expand All @@ -224,7 +228,7 @@ void Task_InstallVersion::do_work()
}
}
{
auto const success = make_file_executable(executable_path(_name));
auto const success = make_file_executable(executable_path(_version_name));
if (!success.has_value())
{
on_error(success.error());
Expand Down
5 changes: 3 additions & 2 deletions src/Version/Task_InstallVersion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

class Task_InstallVersion : public Cool::Task {
public:
Task_InstallVersion(VersionName name, std::string download_url);
Task_InstallVersion(VersionName version_name, std::string download_url, ImGuiNotify::NotificationId notification_id);

void do_work() override;
void cancel() override { _data->cancel.store(true); }
auto needs_user_confirmation_to_cancel_when_closing_app() const -> bool override { return true; }
auto name() const -> std::string override { return fmt::format("Installing {}", _version_name.as_string()); }

private:
void on_success();
Expand All @@ -18,7 +19,7 @@ class Task_InstallVersion : public Cool::Task {
void on_version_not_installed();

private:
VersionName _name;
VersionName _version_name;
std::string _download_url{};
ImGuiNotify::NotificationId _notification_id{};

Expand Down
43 changes: 43 additions & 0 deletions src/Version/Task_WaitForDownloadUrlToInstallVersion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "Task_WaitForDownloadUrlToInstallVersion.hpp"
#include <ImGuiNotify/ImGuiNotify.hpp>
#include <optional>
#include "Cool/Task/TaskManager.hpp"
#include "Task_InstallVersion.hpp"
#include "VersionManager.hpp"

Task_WaitForDownloadUrlToInstallVersion::Task_WaitForDownloadUrlToInstallVersion(VersionName version_name, ImGuiNotify::NotificationId notification_id, std::shared_ptr<std::atomic<bool>> do_cancel)
: _version_name{std::move(version_name)}
, _notification_id{notification_id}
, _cancel{std::move(do_cancel)}
{
if (_notification_id == ImGuiNotify::NotificationId{})
{
_notification_id = ImGuiNotify::send({
.type = ImGuiNotify::Type::Info,
.title = name(),
.content = "You are offline\nWaiting for an Internet connection",
.custom_imgui_content = [cancel = _cancel]() {
if (ImGui::Button("Cancel"))
cancel->store(true);
},
.duration = std::nullopt,
.is_closable = false,
});
}
}

void Task_WaitForDownloadUrlToInstallVersion::do_work()
{
if (_cancel->load())
{
ImGuiNotify::close_immediately(_notification_id);
return;
}

version_manager().with_version_found(_version_name, [&](Version const& version) {
if (version.download_url.has_value())
Cool::task_manager().submit(std::make_shared<Task_InstallVersion>(version.name, *version.download_url, _notification_id));
else
Cool::task_manager().run_small_task_in(100ms, std::make_shared<Task_WaitForDownloadUrlToInstallVersion>(_version_name, _notification_id, _cancel));
});
}
23 changes: 23 additions & 0 deletions src/Version/Task_WaitForDownloadUrlToInstallVersion.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once
#include "Cool/Task/Task.hpp"
#include "ImGuiNotify/ImGuiNotify.hpp"
#include "VersionName.hpp"

class Task_WaitForDownloadUrlToInstallVersion : public Cool::Task {
public:
explicit Task_WaitForDownloadUrlToInstallVersion(VersionName version_name, ImGuiNotify::NotificationId = {}, std::shared_ptr<std::atomic<bool>> = std::make_unique<std::atomic<bool>>(false));

void do_work() override;
void cancel() override
{
_cancel->store(true);
ImGuiNotify::close_immediately(_notification_id);
}
auto needs_user_confirmation_to_cancel_when_closing_app() const -> bool override { return true; }
auto name() const -> std::string override { return fmt::format("Installing {}", _version_name.as_string()); }

private:
VersionName _version_name;
ImGuiNotify::NotificationId _notification_id{};
std::shared_ptr<std::atomic<bool>> _cancel;
};
16 changes: 6 additions & 10 deletions src/Version/VersionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include "Cool/ImGui/ImGuiExtras_dropdown.hpp"
#include "Cool/Task/TaskManager.hpp"
#include "Path.hpp"
#include "Task_FindVersionsAvailableOnline.hpp"
#include "Task_InstallVersion.hpp"
#include "Task_FetchListOfVersions.hpp"
#include "Task_WaitForDownloadUrlToInstallVersion.hpp"
#include "Version.hpp"
#include "VersionName.hpp"
#include "VersionRef.hpp"
Expand Down Expand Up @@ -65,7 +65,7 @@ VersionManager::VersionManager()
: _versions{get_all_known_versions()}
{
// TODO(Launcher) make sure to not send a request if we know which project to launch, and we already have that version, to save on the number of requests allowed by Github
Cool::task_manager().submit(std::make_shared<Task_FindVersionsAvailableOnline>());
Cool::task_manager().submit(std::make_shared<Task_FetchListOfVersions>());
}

void VersionManager::install_ifn_and_launch(VersionRef const& version_ref, std::optional<std::filesystem::path> const& project_file_path)
Expand Down Expand Up @@ -94,7 +94,7 @@ void VersionManager::install_ifn_and_launch(VersionRef const& version_ref, std::
}

{
auto lock = std::unique_lock{_project_to_launch_after_version_installed_mutex};
auto lock2 = std::unique_lock{_project_to_launch_after_version_installed_mutex};
if (version->installation_status == InstallationStatus::Installed)
{
launch(version->name, project_file_path);
Expand Down Expand Up @@ -124,10 +124,7 @@ void VersionManager::install(Version const& version)
assert(false);
return;
}

// if (!version.download_url)
// return tl::make_unexpected("Version not found"); // TODO(Launcher) wait for get_all_versions request to finish. If no internet, tell people to connect to internet
Cool::task_manager().submit(std::make_shared<Task_InstallVersion>(version.name, *version.download_url));
Cool::task_manager().run_small_task_in(0s, std::make_shared<Task_WaitForDownloadUrlToInstallVersion>(version.name));
}

void VersionManager::uninstall(Version& version)
Expand Down Expand Up @@ -307,12 +304,11 @@ void VersionManager::imgui_versions_dropdown(VersionRef& ref)
return _label.c_str();
},
[](VersionName const& name) {
return name.as_string().c_str(); // TODO indicate if this is installed or not, with a small icon
return name.as_string().c_str(); // TODO(Launcher) indicate if this is installed or not, with a small icon
}
},
_value
);
return _label.c_str();
}

void apply_value()
Expand Down
5 changes: 3 additions & 2 deletions src/Version/VersionManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ class VersionManager {
void install(Version const&);
void uninstall(Version&);

public: // TODO
public: // TODO(Launcher)
auto latest_version_no_locking() -> Version*;
auto latest_installed_version_no_locking() -> Version*;

private:
friend class Task_FindVersionsAvailableOnline;
friend class Task_FetchListOfVersions;
friend class Task_WaitForDownloadUrlToInstallVersion;
friend class Task_InstallVersion;

void set_download_url(VersionName const&, std::string download_url);
Expand Down
1 change: 0 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ auto main(int argc, char** argv) -> int
argc, argv,
{
.windows_configs = {{
.title = "Coollab Launcher",
.maximize_on_startup_if = false,
}},
.imgui_ini_version = 0,
Expand Down

0 comments on commit 8547176

Please sign in to comment.