diff --git a/launcher/include/charactersync.h b/launcher/include/charactersync.h index c40dae9..ce915ba 100644 --- a/launcher/include/charactersync.h +++ b/launcher/include/charactersync.h @@ -27,7 +27,7 @@ public: private: QCoro::Task uploadCharacterData(const QDir &dir, const QString &id); - QCoro::Task downloadCharacterData(const QDir &dir, const QString &id, const QString &contentUri); + QCoro::Task downloadCharacterData(const QDir &dir, const QString &id, const QString &contentUri); LauncherCore &launcher; Account &m_account; diff --git a/launcher/include/syncmanager.h b/launcher/include/syncmanager.h index 0ba471a..02fe709 100644 --- a/launcher/include/syncmanager.h +++ b/launcher/include/syncmanager.h @@ -105,12 +105,12 @@ Q_SIGNALS: void loginError(const QString &message); private: + void invokeLogin(); QString roomId() const; void setRoomId(const QString &roomId); QCoro::Task<> findRoom(); - QCoro::Task<> beginInitialSync(); Quotient::AccountRegistry m_accountRegistry; Quotient::Room *m_currentRoom = nullptr; -}; \ No newline at end of file +}; diff --git a/launcher/src/charactersync.cpp b/launcher/src/charactersync.cpp index 5d03ce5..b953d0c 100644 --- a/launcher/src/charactersync.cpp +++ b/launcher/src/charactersync.cpp @@ -33,6 +33,9 @@ QCoro::Task CharacterSync::sync(const bool initialSync) co_return false; } + // Perform a manual sync just in case + co_await syncManager->sync(); + if (!syncManager->isReady()) { Q_EMIT launcher.stageChanged(i18n("Waiting for sync connection...")); @@ -42,9 +45,6 @@ QCoro::Task CharacterSync::sync(const bool initialSync) Q_EMIT launcher.stageChanged(i18n("Synchronizing character data...")); - // Perform a manual sync just in case - co_await syncManager->sync(); - // On game boot, check if we need the lock. Otherwise break it when we clean up. if (initialSync) { if (const auto hostname = co_await syncManager->checkLock(); hostname.has_value()) { @@ -110,10 +110,15 @@ QCoro::Task CharacterSync::sync(const bool initialSync) const bool needsDownload = areFilesDifferent; if (needsUpload) { + qCDebug(ASTRA_LOG) << id << "uploading character data"; // if we didn't upload character data yet, upload it now co_await uploadCharacterData(dir.absoluteFilePath(), id); } else if (needsDownload) { - co_await downloadCharacterData(dir.absoluteFilePath(), id, previousData->mxcUri); + qCDebug(ASTRA_LOG) << id << "downloading character data"; + if (!co_await downloadCharacterData(dir.absoluteFilePath(), id, previousData->mxcUri)) { + Q_EMIT launcher.loginError(i18n("Failed to sync character data from the server. Please do another initial sync under Settings and try again.")); + co_return false; + } } } @@ -149,7 +154,7 @@ QCoro::Task CharacterSync::uploadCharacterData(const QDir &dir, const QStr co_return; } -QCoro::Task CharacterSync::downloadCharacterData(const QDir &dir, const QString &id, const QString &contentUri) +QCoro::Task CharacterSync::downloadCharacterData(const QDir &dir, const QString &id, const QString &contentUri) { const QTemporaryDir tempDir; @@ -160,17 +165,27 @@ QCoro::Task CharacterSync::downloadCharacterData(const QDir &dir, const QS auto zip = new KZip(tempZipPath); zip->setCompression(KZip::DeflateCompression); zip->open(QIODevice::ReadOnly); + if (zip->isOpen()) { + qCDebug(ASTRA_LOG) << "contents:" << zip->directory()->entries(); - qCDebug(ASTRA_LOG) << "contents:" << zip->directory()->entries(); + if (auto file = zip->directory()->file(gearsetFilename); file != nullptr) { + Q_UNUSED(file->copyTo(dir.absolutePath())) - Q_UNUSED(zip->directory()->file(gearsetFilename)->copyTo(dir.absolutePath())) + qCDebug(ASTRA_LOG) << "Extracted character data!"; - qCDebug(ASTRA_LOG) << "Extracted character data!"; + zip->close(); + delete zip; + + co_return true; + } + } zip->close(); delete zip; - co_return; + qCDebug(ASTRA_LOG) << "Failed to read character ZIP!"; + + co_return false; } #include "moc_charactersync.cpp" diff --git a/launcher/src/syncmanager.cpp b/launcher/src/syncmanager.cpp index 551cbb5..bb496a3 100644 --- a/launcher/src/syncmanager.cpp +++ b/launcher/src/syncmanager.cpp @@ -33,7 +33,7 @@ using namespace Quotient; SyncManager::SyncManager(QObject *parent) : QObject(parent) { - m_accountRegistry.invokeLogin(); // TODO: port from invokeLogin + invokeLogin(); connect(&m_accountRegistry, &AccountRegistry::rowsInserted, this, [this]() { connection()->setCacheState(false); connection()->setLazyLoading(false); @@ -43,8 +43,6 @@ SyncManager::SyncManager(QObject *parent) Q_EMIT connectedChanged(); Q_EMIT userIdChanged(); Q_EMIT connectionChanged(); - - beginInitialSync(); }); connect(&m_accountRegistry, &AccountRegistry::rowsRemoved, this, [this]() { Q_EMIT connectedChanged(); @@ -117,7 +115,11 @@ QCoro::Task<> SyncManager::sync() auto connection = m_accountRegistry.accounts().first(); connection->sync(); co_await qCoro(connection, &Connection::syncDone); - m_accountRegistry.accounts().first()->stopSync(); + + if (!m_currentRoom) { + co_await findRoom(); + } + co_return; } @@ -132,6 +134,18 @@ QCoro::Task SyncManager::findRoom() // If we have no room id set, we need to find the correct room type const bool needsFirstTimeRoom = roomId.isEmpty(); + if (!needsFirstTimeRoom) { + auto room = m_accountRegistry.accounts().first()->room(roomId); + if (room) { + qCDebug(ASTRA_LOG) << "Found pre-existing room!"; + + m_currentRoom = room; + Q_EMIT isReadyChanged(); + + co_return; + } + } + // Try to find our room auto rooms = m_accountRegistry.accounts().first()->rooms(Quotient::JoinState::Join); for (auto room : rooms) { @@ -151,15 +165,6 @@ QCoro::Task SyncManager::findRoom() Q_EMIT isReadyChanged(); } } - } else { - if (room->id() == roomId) { - qCDebug(ASTRA_LOG) << "Found pre-existing room!"; - - m_currentRoom = room; - Q_EMIT isReadyChanged(); - - co_return; - } } } @@ -190,6 +195,28 @@ QCoro::Task SyncManager::findRoom() co_return; } +void SyncManager::invokeLogin() +{ + // Simplified from libQuotient, but this can be simplified even more + const auto accounts = SettingsGroup("Accounts"_L1).childGroups(); + for (const auto &accountId : accounts) { + AccountSettings account{accountId}; + + if (account.homeserver().isEmpty()) + continue; + + auto accessTokenLoadingJob = new QKeychain::ReadPasswordJob(qAppName(), this); + accessTokenLoadingJob->setKey(accountId); + connect(accessTokenLoadingJob, &QKeychain::Job::finished, this, [accountId, this, accessTokenLoadingJob]() { + AccountSettings account{accountId}; + auto connection = new Connection(account.homeserver()); + connection->assumeIdentity(account.userId(), account.deviceId(), QString::fromUtf8(accessTokenLoadingJob->binaryData())); + m_accountRegistry.add(connection); + }); + accessTokenLoadingJob->start(); + } +} + QString SyncManager::roomId() const { return KSharedConfig::openStateConfig()->group(QStringLiteral("Sync")).readEntry(QStringLiteral("RoomId")); @@ -204,6 +231,7 @@ void SyncManager::setRoomId(const QString &roomId) bool SyncManager::isReady() const { + qInfo() << connected() << m_currentRoom; return connected() && m_currentRoom; } @@ -294,12 +322,4 @@ QCoro::Task<> SyncManager::breakLock() co_return; } -QCoro::Task<> SyncManager::beginInitialSync() -{ - co_await sync(); - - // Find the room we need to sync with - findRoom(); -} - #include "moc_syncmanager.cpp"