summary refs log tree commit diff
path: root/src/RoomDirectoryModel.cpp
diff options
context:
space:
mode:
authorDeepBlueV7.X <nicolas.werner@hotmail.de>2021-08-17 11:56:47 +0000
committerGitHub <noreply@github.com>2021-08-17 11:56:47 +0000
commitb01496f9b48481cba71fc588c9f452c601d948ba (patch)
tree25403735cbfc5b645c039bd4f0e1f19a7a79ae61 /src/RoomDirectoryModel.cpp
parentRemove unneeded code (diff)
parentFormatting (diff)
downloadnheko-b01496f9b48481cba71fc588c9f452c601d948ba.tar.xz
Merge pull request #659 from kamathmanu/nhekoRoomDirectory
Nheko room directory
Diffstat (limited to 'src/RoomDirectoryModel.cpp')
-rw-r--r--src/RoomDirectoryModel.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/RoomDirectoryModel.cpp b/src/RoomDirectoryModel.cpp
new file mode 100644
index 00000000..61c3eb72
--- /dev/null
+++ b/src/RoomDirectoryModel.cpp
@@ -0,0 +1,194 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors

+//

+// SPDX-License-Identifier: GPL-3.0-or-later

+

+#include "RoomDirectoryModel.h"

+#include "Cache.h"

+#include "ChatPage.h"

+

+#include <algorithm>

+

+RoomDirectoryModel::RoomDirectoryModel(QObject *parent, const std::string &s)

+  : QAbstractListModel(parent)

+  , server_(s)

+{

+        connect(this,

+                &RoomDirectoryModel::fetchedRoomsBatch,

+                this,

+                &RoomDirectoryModel::displayRooms,

+                Qt::QueuedConnection);

+}

+

+QHash<int, QByteArray>

+RoomDirectoryModel::roleNames() const

+{

+        return {

+          {Roles::Name, "name"},

+          {Roles::Id, "roomid"},

+          {Roles::AvatarUrl, "avatarUrl"},

+          {Roles::Topic, "topic"},

+          {Roles::MemberCount, "numMembers"},

+          {Roles::Previewable, "canPreview"},

+        };

+}

+

+void

+RoomDirectoryModel::resetDisplayedData()

+{

+        beginResetModel();

+

+        prevBatch_    = "";

+        nextBatch_    = "";

+        canFetchMore_ = true;

+

+        publicRoomsData_.clear();

+

+        endResetModel();

+}

+

+void

+RoomDirectoryModel::setMatrixServer(const QString &s)

+{

+        server_ = s.toStdString();

+

+        nhlog::ui()->debug("Received matrix server: {}", server_);

+

+        resetDisplayedData();

+}

+

+void

+RoomDirectoryModel::setSearchTerm(const QString &f)

+{

+        userSearchString_ = f.toStdString();

+

+        nhlog::ui()->debug("Received user query: {}", userSearchString_);

+

+        resetDisplayedData();

+}

+

+bool

+RoomDirectoryModel::canJoinRoom(const QByteArray &room)

+{

+        const QString room_id(room);

+        return !room_id.isEmpty() && !cache::getRoomInfo({room_id.toStdString()}).count(room_id);

+}

+

+std::vector<std::string>

+RoomDirectoryModel::getViasForRoom(const std::vector<std::string> &aliases)

+{

+        std::vector<std::string> vias;

+

+        vias.reserve(aliases.size());

+

+        std::transform(aliases.begin(),

+                       aliases.end(),

+                       std::back_inserter(vias),

+                       [](const auto &alias) { return alias.substr(alias.find(":") + 1); });

+

+        return vias;

+}

+

+void

+RoomDirectoryModel::joinRoom(const int &index)

+{

+        if (index >= 0 && static_cast<size_t>(index) < publicRoomsData_.size()) {

+                const auto &chunk = publicRoomsData_[index];

+                nhlog::ui()->debug("'Joining room {}", chunk.room_id);

+                ChatPage::instance()->joinRoomVia(chunk.room_id, getViasForRoom(chunk.aliases));

+        }

+}

+

+QVariant

+RoomDirectoryModel::data(const QModelIndex &index, int role) const

+{

+        if (hasIndex(index.row(), index.column(), index.parent())) {

+                const auto &room_chunk = publicRoomsData_[index.row()];

+                switch (role) {

+                case Roles::Name:

+                        return QString::fromStdString(room_chunk.name);

+                case Roles::Id:

+                        return QString::fromStdString(room_chunk.room_id);

+                case Roles::AvatarUrl:

+                        return QString::fromStdString(room_chunk.avatar_url);

+                case Roles::Topic:

+                        return QString::fromStdString(room_chunk.topic);

+                case Roles::MemberCount:

+                        return QVariant::fromValue(room_chunk.num_joined_members);

+                case Roles::Previewable:

+                        return QVariant::fromValue(room_chunk.world_readable);

+                }

+        }

+        return {};

+}

+

+void

+RoomDirectoryModel::fetchMore(const QModelIndex &)

+{

+        if (!canFetchMore_)

+                return;

+

+        nhlog::net()->debug("Fetching more rooms from mtxclient...");

+

+        mtx::requests::PublicRooms req;

+        req.limit                      = limit_;

+        req.since                      = prevBatch_;

+        req.filter.generic_search_term = userSearchString_;

+        // req.third_party_instance_id = third_party_instance_id;

+        auto requested_server = server_;

+

+        reachedEndOfPagination_ = false;

+        emit reachedEndOfPaginationChanged();

+

+        loadingMoreRooms_ = true;

+        emit loadingMoreRoomsChanged();

+

+        http::client()->post_public_rooms(

+          req,

+          [requested_server, this, req](const mtx::responses::PublicRooms &res,

+                                        mtx::http::RequestErr err) {

+                  loadingMoreRooms_ = false;

+                  emit loadingMoreRoomsChanged();

+

+                  if (err) {

+                          nhlog::net()->error(

+                            "Failed to retrieve rooms from mtxclient - {} - {} - {}",

+                            mtx::errors::to_string(err->matrix_error.errcode),

+                            err->matrix_error.error,

+                            err->parse_error);

+                  } else if (req.filter.generic_search_term == this->userSearchString_ &&

+                             req.since == this->prevBatch_ && requested_server == this->server_) {

+                          nhlog::net()->debug("signalling chunk to GUI thread");

+                          emit fetchedRoomsBatch(res.chunk, res.next_batch);

+                  }

+          },

+          requested_server);

+}

+

+void

+RoomDirectoryModel::displayRooms(std::vector<mtx::responses::PublicRoomsChunk> fetched_rooms,

+                                 const std::string &next_batch)

+{

+        nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, next_batch);

+

+        if (fetched_rooms.empty()) {

+                nhlog::net()->error("mtxclient helper thread yielded empty chunk!");

+                return;

+        }

+

+        beginInsertRows(QModelIndex(),

+                        static_cast<int>(publicRoomsData_.size()),

+                        static_cast<int>(publicRoomsData_.size() + fetched_rooms.size()) - 1);

+        this->publicRoomsData_.insert(

+          this->publicRoomsData_.end(), fetched_rooms.begin(), fetched_rooms.end());

+        endInsertRows();

+

+        if (next_batch.empty()) {

+                canFetchMore_           = false;

+                reachedEndOfPagination_ = true;

+                emit reachedEndOfPaginationChanged();

+        }

+

+        prevBatch_ = next_batch;

+

+        nhlog::ui()->debug("Finished loading rooms");

+}