From 6f499927bed635299f6aeef4e2fa9ca0fff545f3 Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Mon, 5 May 2025 15:39:15 -0400 Subject: [PATCH] Prompt for updates before actually downloading them This is to prevent "surprise" situations, such as: * You have a limited internet connection, and the game updates out of the blue. * Your installation is invalid, and Astra decides to suddenly redownload the entire game. --- launcher/include/launchercore.h | 2 ++ launcher/src/squareenixlogin.cpp | 34 ++++++++++++++++++++++++++++---- launcher/ui/Pages/StatusPage.qml | 16 +++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/launcher/include/launchercore.h b/launcher/include/launchercore.h index 3b322d4..cb70283 100755 --- a/launcher/include/launchercore.h +++ b/launcher/include/launchercore.h @@ -163,6 +163,8 @@ Q_SIGNALS: void autoLoginProfileChanged(); void cachedLogoImageChanged(); void showWindow(); + void requiresUpdate(QString message); + void updateDecided(bool allowUpdate); protected: friend class Patcher; diff --git a/launcher/src/squareenixlogin.cpp b/launcher/src/squareenixlogin.cpp index ea791d3..55539d4 100644 --- a/launcher/src/squareenixlogin.cpp +++ b/launcher/src/squareenixlogin.cpp @@ -3,8 +3,10 @@ #include "squareenixlogin.h" +#include #include #include +#include #include #include #include @@ -187,15 +189,27 @@ QCoro::Task SquareEnixLogin::checkBootUpdates() if (!patchList.isEmpty()) { qDebug(ASTRA_LOG) << "Boot patch list:" << patchList; + const std::string patchListStd = patchList.toStdString(); + const auto parsedPatchList = physis_parse_patchlist(PatchListType::Boot, patchListStd.c_str()); + if (!m_info->profile->config()->allowPatching()) { Q_EMIT m_launcher.loginError( i18n("You require an update to play, but you have the “Allow Updates” option checked - so the login was canceled.")); co_return false; } + const qint64 neededSpace = parsedPatchList.patch_length; + KFormat format; + QString neededSpaceStr = format.formatByteSize(neededSpace); + Q_EMIT m_launcher.requiresUpdate( + i18n("The boot components require an update, which will download %1 of data. Do you still want to continue?", neededSpaceStr)); + const bool wantsToUpdate = co_await qCoro(&m_launcher, &LauncherCore::updateDecided); + if (!wantsToUpdate) { + co_return false; + } + m_patcher = new Patcher(m_launcher, m_info->profile->config()->gamePath() + QStringLiteral("/boot"), *m_info->profile->bootData(), this); - const std::string patchListStd = patchList.toStdString(); - const bool hasPatched = co_await m_patcher->patch(physis_parse_patchlist(PatchListType::Boot, patchListStd.c_str())); + const bool hasPatched = co_await m_patcher->patch(parsedPatchList); if (hasPatched) { // update game version information m_info->profile->readGameVersion(); @@ -394,9 +408,21 @@ QCoro::Task SquareEnixLogin::registerSession() co_return false; } - m_patcher = new Patcher(m_launcher, m_info->profile->config()->gamePath() + QStringLiteral("/game"), *m_info->profile->gameData(), this); std::string bodyStd = body.toStdString(); - const bool hasPatched = co_await m_patcher->patch(physis_parse_patchlist(PatchListType::Game, bodyStd.c_str())); + const auto parsedPatchList = physis_parse_patchlist(PatchListType::Game, bodyStd.c_str()); + + const qint64 neededSpace = parsedPatchList.patch_length; + KFormat format; + QString neededSpaceStr = format.formatByteSize(neededSpace); + Q_EMIT m_launcher.requiresUpdate( + i18n("The game require an update, which will download %1 of data. Do you still want to continue?", neededSpaceStr)); + const bool wantsToUpdate = co_await qCoro(&m_launcher, &LauncherCore::updateDecided); + if (!wantsToUpdate) { + co_return false; + } + + m_patcher = new Patcher(m_launcher, m_info->profile->config()->gamePath() + QStringLiteral("/game"), *m_info->profile->gameData(), this); + const bool hasPatched = co_await m_patcher->patch(parsedPatchList); m_patcher->deleteLater(); if (!hasPatched) { co_return false; diff --git a/launcher/ui/Pages/StatusPage.qml b/launcher/ui/Pages/StatusPage.qml index c355202..b1e8b90 100644 --- a/launcher/ui/Pages/StatusPage.qml +++ b/launcher/ui/Pages/StatusPage.qml @@ -55,6 +55,16 @@ Kirigami.Page { onRejected: applicationWindow().checkSetup() } + Kirigami.PromptDialog { + id: updateRequiredDialog + + showCloseButton: false + standardButtons: Kirigami.Dialog.Yes | Kirigami.Dialog.Cancel + + onAccepted: LauncherCore.updateDecided(true) + onRejected: LauncherCore.updateDecided(false) + } + Connections { target: LauncherCore @@ -90,5 +100,11 @@ Kirigami.Page { dalamudErrorDialog.subtitle = i18n("An error occurred while updating Dalamud:\n\n%1.\n\nWould you like to disable Dalamud?", message); dalamudErrorDialog.open(); } + + function onRequiresUpdate(message: string): void { + updateDialog.title = i18n("Update Required"); + updateDialog.subtitle = message; + updateDialog.open(); + } } }