// SPDX-FileCopyrightText: 2022 Snehit Sah // SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL #include "spacehierarchycache.h" #include #include #include #include #include "neochatconnection.h" #include "neochatroom.h" using namespace Quotient; SpaceHierarchyCache::SpaceHierarchyCache(QObject *parent) : QObject{parent} { } void SpaceHierarchyCache::cacheSpaceHierarchy() { if (!m_connection) { return; } const auto &roomList = m_connection->allRooms(); for (const auto &room : roomList) { const auto neoChatRoom = static_cast(room); if (neoChatRoom->isSpace()) { populateSpaceHierarchy(neoChatRoom->id()); } else { connect( neoChatRoom, &Room::baseStateLoaded, neoChatRoom, [this, neoChatRoom]() { if (neoChatRoom->isSpace()) { populateSpaceHierarchy(neoChatRoom->id()); } }, Qt::SingleShotConnection); } connect(neoChatRoom, &NeoChatRoom::unreadStatsChanged, this, [this, neoChatRoom]() { if (neoChatRoom != nullptr) { const auto parents = parentSpaces(neoChatRoom->id()); if (parents.count() > 0) { Q_EMIT spaceNotifcationCountChanged(parents); } } }); } } void SpaceHierarchyCache::populateSpaceHierarchy(const QString &spaceId) { if (!m_connection) { return; } m_nextBatchTokens[spaceId] = QString(); auto job = m_connection->callApi(spaceId, std::nullopt, std::nullopt, std::nullopt, *m_nextBatchTokens[spaceId]); auto group = KConfigGroup(KSharedConfig::openStateConfig("SpaceHierarchy"_ls), "Cache"_ls); m_spaceHierarchy.insert(spaceId, group.readEntry(spaceId, QStringList())); connect(job, &BaseJob::success, this, [this, job, spaceId]() { addBatch(spaceId, job); }); } void SpaceHierarchyCache::addBatch(const QString &spaceId, Quotient::GetSpaceHierarchyJob *job) { const auto rooms = job->rooms(); QStringList roomList = m_spaceHierarchy[spaceId]; for (unsigned long i = 0; i < rooms.size(); ++i) { for (const auto &state : rooms[i].childrenState) { if (!roomList.contains(state->stateKey())) { roomList.push_back(state->stateKey()); } } } m_spaceHierarchy.insert(spaceId, roomList); Q_EMIT spaceHierarchyChanged(); auto group = KConfigGroup(KSharedConfig::openStateConfig("SpaceHierarchy"_ls), "Cache"_ls); group.writeEntry(spaceId, roomList); group.sync(); const auto nextBatchToken = job->nextBatch(); if (!nextBatchToken.isEmpty() && nextBatchToken != *m_nextBatchTokens[spaceId] && m_connection) { *m_nextBatchTokens[spaceId] = nextBatchToken; auto nextJob = m_connection->callApi(spaceId, std::nullopt, std::nullopt, std::nullopt, *m_nextBatchTokens[spaceId]); connect(nextJob, &BaseJob::success, this, [this, nextJob, spaceId]() { addBatch(spaceId, nextJob); }); } else { m_nextBatchTokens[spaceId].reset(); } } void SpaceHierarchyCache::addSpaceToHierarchy(Quotient::Room *room) { connect( room, &Quotient::Room::baseStateLoaded, this, [this, room]() { const auto neoChatRoom = static_cast(room); if (neoChatRoom->isSpace()) { populateSpaceHierarchy(neoChatRoom->id()); } }, Qt::SingleShotConnection); } void SpaceHierarchyCache::removeSpaceFromHierarchy(Quotient::Room *room) { const auto neoChatRoom = static_cast(room); if (neoChatRoom->isSpace()) { m_spaceHierarchy.remove(neoChatRoom->id()); } } QStringList SpaceHierarchyCache::parentSpaces(const QString &roomId) { auto spaces = m_spaceHierarchy.keys(); QStringList parents; for (const auto &space : spaces) { if (m_spaceHierarchy[space].contains(roomId)) { parents += space; } } return parents; } bool SpaceHierarchyCache::isSpaceChild(const QString &spaceId, const QString &roomId) { return getRoomListForSpace(spaceId, false).contains(roomId); } QList &SpaceHierarchyCache::getRoomListForSpace(const QString &spaceId, bool updateCache) { if (updateCache) { populateSpaceHierarchy(spaceId); } return m_spaceHierarchy[spaceId]; } qsizetype SpaceHierarchyCache::notificationCountForSpace(const QString &spaceId) { qsizetype notifications = 0; auto children = m_spaceHierarchy[spaceId]; QStringList added; for (const auto &childId : children) { if (const auto child = static_cast(m_connection->room(childId))) { if (!added.contains(child->id())) { notifications += child->contextAwareNotificationCount(); added += child->id(); } } } return notifications; } bool SpaceHierarchyCache::spaceHasHighlightNotifications(const QString &spaceId) { auto children = m_spaceHierarchy[spaceId]; for (const auto &childId : children) { if (const auto child = static_cast(m_connection->room(childId))) { if (child->highlightCount() > 0) { return true; } } } return false; } bool SpaceHierarchyCache::isChild(const QString &roomId) const { const auto childrens = m_spaceHierarchy.values(); for (const auto &children : childrens) { if (children.contains(roomId)) { return true; } } return false; } NeoChatConnection *SpaceHierarchyCache::connection() const { return m_connection; } void SpaceHierarchyCache::setConnection(NeoChatConnection *connection) { if (m_connection == connection) { return; } m_connection = connection; Q_EMIT connectionChanged(); m_spaceHierarchy.clear(); cacheSpaceHierarchy(); connect(connection, &Connection::joinedRoom, this, &SpaceHierarchyCache::addSpaceToHierarchy); connect(connection, &Connection::aboutToDeleteRoom, this, &SpaceHierarchyCache::removeSpaceFromHierarchy); } QString SpaceHierarchyCache::recommendedSpaceId() const { return KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("RecommendedSpace")).readEntry(QStringLiteral("Id"), {}); } QString SpaceHierarchyCache::recommendedSpaceAvatar() const { return KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("RecommendedSpace")).readEntry(QStringLiteral("Avatar"), {}); } QString SpaceHierarchyCache::recommendedSpaceDisplayName() const { return KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("RecommendedSpace")).readEntry(QStringLiteral("DisplayName"), {}); } QString SpaceHierarchyCache::recommendedSpaceDescription() const { return KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("RecommendedSpace")).readEntry(QStringLiteral("Description"), {}); } bool SpaceHierarchyCache::recommendedSpaceHidden() const { KConfigGroup group(KSharedConfig::openStateConfig(), QStringLiteral("RecommendedSpace")); return group.readEntry(QStringLiteral("hidden"), false); } void SpaceHierarchyCache::setRecommendedSpaceHidden(bool hidden) { KConfigGroup group(KSharedConfig::openStateConfig(), QStringLiteral("RecommendedSpace")); group.writeEntry(QStringLiteral("hidden"), hidden); group.sync(); Q_EMIT recommendedSpaceHiddenChanged(); } #include "moc_spacehierarchycache.cpp"