From c602f01062f592be9dacda748dd113e816d4ba2d Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Thu, 22 Aug 2024 18:46:45 -0400 Subject: [PATCH] Move fetchAvatar from Account to LauncherCore This is to head towards removing the LauncherCore dependency inside of Account (and by extension, AccountManager.) This function should really belong here anyway, since it uses a lot of functionality from LauncherCore. --- launcher/include/account.h | 3 +- launcher/include/accountmanager.h | 2 + launcher/include/launchercore.h | 3 ++ launcher/src/account.cpp | 64 ++++--------------------------- launcher/src/accountmanager.cpp | 4 ++ launcher/src/launchercore.cpp | 55 ++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 57 deletions(-) diff --git a/launcher/include/account.h b/launcher/include/account.h index 1ce7b91..851adfc 100644 --- a/launcher/include/account.h +++ b/launcher/include/account.h @@ -74,6 +74,8 @@ public: Q_INVOKABLE QString getPassword(); void setPassword(const QString &password); + void setAvatarUrl(const QString &url); + Q_INVOKABLE QString getOTP(); Q_INVOKABLE void setOTPSecret(const QString &secret); @@ -101,7 +103,6 @@ Q_SIGNALS: bool needsPasswordChanged(); private: - void fetchAvatar(); QCoro::Task<> fetchPassword(); /** diff --git a/launcher/include/accountmanager.h b/launcher/include/accountmanager.h index 1b2c25b..8e374fe 100644 --- a/launcher/include/accountmanager.h +++ b/launcher/include/accountmanager.h @@ -43,6 +43,8 @@ public: Q_SIGNALS: void accountsChanged(); + void accountAdded(Account *account); + void accountLodestoneIdChanged(Account *account); private: void insertAccount(Account *account); diff --git a/launcher/include/launchercore.h b/launcher/include/launchercore.h index d272152..a41ae45 100755 --- a/launcher/include/launchercore.h +++ b/launcher/include/launchercore.h @@ -99,7 +99,10 @@ public: Q_INVOKABLE BenchmarkInstaller *createBenchmarkInstaller(Profile *profile); Q_INVOKABLE BenchmarkInstaller *createBenchmarkInstallerFromExisting(Profile *profile, const QString &filePath); + /// Fetches the avatar for @p account + void fetchAvatar(Account *account); Q_INVOKABLE void clearAvatarCache(); + Q_INVOKABLE void refreshNews(); Q_INVOKABLE void refreshLogoImage(); diff --git a/launcher/src/account.cpp b/launcher/src/account.cpp index e306ce6..159b264 100644 --- a/launcher/src/account.cpp +++ b/launcher/src/account.cpp @@ -21,7 +21,6 @@ Account::Account(LauncherCore &launcher, const QString &key, QObject *parent) , m_key(key) , m_launcher(launcher) { - fetchAvatar(); fetchPassword(); } @@ -68,7 +67,6 @@ void Account::setLodestoneId(const QString &id) if (m_config.lodestoneId() != id) { m_config.setLodestoneId(id); m_config.save(); - fetchAvatar(); Q_EMIT lodestoneIdChanged(); } } @@ -191,6 +189,14 @@ void Account::setPassword(const QString &password) } } +void Account::setAvatarUrl(const QString &url) +{ + if (m_avatarUrl != url) { + m_avatarUrl = url; + Q_EMIT avatarUrlChanged(); + } +} + QString Account::getOTP() { const auto otpSecret = QCoro::waitFor(getKeychainValue(QStringLiteral("otp-secret"))); @@ -227,60 +233,6 @@ QString Account::getConfigPath() const return getConfigDir().absolutePath(); } -void Account::fetchAvatar() -{ - if (lodestoneId().isEmpty()) { - return; - } - - const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars"); - Utility::createPathIfNeeded(cacheLocation); - - const QString filename = QStringLiteral("%1/%2.jpg").arg(cacheLocation, lodestoneId()); - if (!QFile(filename).exists()) { - qDebug(ASTRA_LOG) << "Did not find lodestone character " << lodestoneId() << " in cache, fetching from Lodestone."; - - QUrl url; - url.setScheme(m_launcher.settings()->preferredProtocol()); - url.setHost(QStringLiteral("na.%1").arg(m_launcher.settings()->mainServer())); // TODO: NA isnt the only thing in the world... - url.setPath(QStringLiteral("/lodestone/character/%1").arg(lodestoneId())); - - const QNetworkRequest request(url); - Utility::printRequest(QStringLiteral("GET"), request); - - const auto reply = m_launcher.mgr()->get(request); - connect(reply, &QNetworkReply::finished, [this, filename, reply] { - const QString document = QString::fromUtf8(reply->readAll()); - if (!document.isEmpty()) { - const static QRegularExpression re( - QStringLiteral(R"lit(]*class=["|']frame__chara__face["|'][^>]*>\s*]*src=["|']([^"']*))lit")); - const QRegularExpressionMatch match = re.match(document); - - if (match.hasCaptured(1)) { - const QString newAvatarUrl = match.captured(1); - - const auto avatarRequest = QNetworkRequest(QUrl(newAvatarUrl)); - Utility::printRequest(QStringLiteral("GET"), avatarRequest); - - auto avatarReply = m_launcher.mgr()->get(avatarRequest); - connect(avatarReply, &QNetworkReply::finished, [this, filename, avatarReply] { - QFile file(filename); - file.open(QIODevice::ReadWrite); - file.write(avatarReply->readAll()); - file.close(); - - m_avatarUrl = QStringLiteral("file:///%1").arg(filename); - Q_EMIT avatarUrlChanged(); - }); - } - } - }); - } else { - m_avatarUrl = QStringLiteral("file:///%1").arg(filename); - Q_EMIT avatarUrlChanged(); - } -} - void Account::setKeychainValue(const QString &key, const QString &value) { if (m_launcher.isSteamDeck()) { diff --git a/launcher/src/accountmanager.cpp b/launcher/src/accountmanager.cpp index ec174cd..aa896a6 100644 --- a/launcher/src/accountmanager.cpp +++ b/launcher/src/accountmanager.cpp @@ -111,10 +111,14 @@ void AccountManager::deleteAccount(Account *account) void AccountManager::insertAccount(Account *account) { + connect(account, &Account::avatarUrlChanged, this, [this, account] { + Q_EMIT accountLodestoneIdChanged(account); + }); beginInsertRows(QModelIndex(), static_cast(m_accounts.size()), static_cast(m_accounts.size())); m_accounts.append(account); endInsertRows(); Q_EMIT accountsChanged(); + Q_EMIT accountAdded(account); } bool AccountManager::hasAnyAccounts() const diff --git a/launcher/src/launchercore.cpp b/launcher/src/launchercore.cpp index d8fed35..cd3d89f 100755 --- a/launcher/src/launchercore.cpp +++ b/launcher/src/launchercore.cpp @@ -40,6 +40,9 @@ LauncherCore::LauncherCore() m_accountManager = new AccountManager(*this, this); m_runner = new GameRunner(*this, this); + connect(m_accountManager, &AccountManager::accountAdded, this, &LauncherCore::fetchAvatar); + connect(m_accountManager, &AccountManager::accountLodestoneIdChanged, this, &LauncherCore::fetchAvatar); + connect(this, &LauncherCore::gameClosed, this, &LauncherCore::handleGameExit); #ifdef BUILD_SYNC @@ -154,6 +157,58 @@ BenchmarkInstaller *LauncherCore::createBenchmarkInstallerFromExisting(Profile * return new BenchmarkInstaller(*this, *profile, filePath, this); } +void LauncherCore::fetchAvatar(Account *account) +{ + if (account->lodestoneId().isEmpty()) { + return; + } + + const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars"); + Utility::createPathIfNeeded(cacheLocation); + + const QString filename = QStringLiteral("%1/%2.jpg").arg(cacheLocation, account->lodestoneId()); + if (!QFile(filename).exists()) { + qDebug(ASTRA_LOG) << "Did not find lodestone character " << account->lodestoneId() << " in cache, fetching from Lodestone."; + + QUrl url; + url.setScheme(settings()->preferredProtocol()); + url.setHost(QStringLiteral("na.%1").arg(settings()->mainServer())); // TODO: NA isnt the only thing in the world... + url.setPath(QStringLiteral("/lodestone/character/%1").arg(account->lodestoneId())); + + const QNetworkRequest request(url); + Utility::printRequest(QStringLiteral("GET"), request); + + const auto reply = mgr()->get(request); + connect(reply, &QNetworkReply::finished, [this, filename, reply, account] { + const QString document = QString::fromUtf8(reply->readAll()); + if (!document.isEmpty()) { + const static QRegularExpression re( + QStringLiteral(R"lit(]*class=["|']frame__chara__face["|'][^>]*>\s*]*src=["|']([^"']*))lit")); + const QRegularExpressionMatch match = re.match(document); + + if (match.hasCaptured(1)) { + const QString newAvatarUrl = match.captured(1); + + const auto avatarRequest = QNetworkRequest(QUrl(newAvatarUrl)); + Utility::printRequest(QStringLiteral("GET"), avatarRequest); + + auto avatarReply = mgr()->get(avatarRequest); + connect(avatarReply, &QNetworkReply::finished, [this, filename, avatarReply, account] { + QFile file(filename); + file.open(QIODevice::ReadWrite); + file.write(avatarReply->readAll()); + file.close(); + + account->setAvatarUrl(QStringLiteral("file:///%1").arg(filename)); + }); + } + } + }); + } else { + account->setAvatarUrl(QStringLiteral("file:///%1").arg(filename)); + } +} + void LauncherCore::clearAvatarCache() { const QString cacheLocation = QStandardPaths::standardLocations(QStandardPaths::CacheLocation)[0] + QStringLiteral("/avatars");