From e5032c686a46bc229700d2dbffdaf90668bb54e2 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Wed, 25 Dec 2019 00:02:01 +0800 Subject: [PATCH] Public room directory. --- CMakeLists.txt | 1 + .../Spectral/Dialog/AccountDetailDialog.qml | 2 +- imports/Spectral/Dialog/JoinRoomDialog.qml | 72 +++++++++++++-- include/SortFilterProxyModel | 2 +- include/libQuotient | 2 +- src/controller.cpp | 29 +++--- src/controller.h | 15 ++-- src/main.cpp | 7 +- src/publicroomlistmodel.cpp | 89 +++++++++++++++++++ src/publicroomlistmodel.h | 43 +++++++++ src/roomlistmodel.cpp | 2 +- src/userlistmodel.cpp | 10 +-- 12 files changed, 230 insertions(+), 44 deletions(-) create mode 100644 src/publicroomlistmodel.cpp create mode 100644 src/publicroomlistmodel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b84fd9b2..51810bf10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ set(spectral_SRCS src/spectraluser.cpp src/trayicon.cpp src/userlistmodel.cpp + src/publicroomlistmodel.cpp src/utils.cpp src/main.cpp ) diff --git a/imports/Spectral/Dialog/AccountDetailDialog.qml b/imports/Spectral/Dialog/AccountDetailDialog.qml index efce8f041..ca37a7ff2 100644 --- a/imports/Spectral/Dialog/AccountDetailDialog.qml +++ b/imports/Spectral/Dialog/AccountDetailDialog.qml @@ -111,7 +111,7 @@ Dialog { RippleEffect { anchors.fill: parent - onPrimaryClicked: joinRoomDialog.createObject(ApplicationWindow.overlay).open() + onPrimaryClicked: joinRoomDialog.createObject(ApplicationWindow.overlay, {"controller": spectralController, "connection": spectralController.connection}).open() } } diff --git a/imports/Spectral/Dialog/JoinRoomDialog.qml b/imports/Spectral/Dialog/JoinRoomDialog.qml index e819cf53c..791db0303 100644 --- a/imports/Spectral/Dialog/JoinRoomDialog.qml +++ b/imports/Spectral/Dialog/JoinRoomDialog.qml @@ -3,10 +3,17 @@ import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import Spectral.Component 2.0 +import Spectral.Setting 0.1 + +import Spectral 0.1 Dialog { + property var controller + property var connection + anchors.centerIn: parent width: 360 + height: window.height - 100 id: root @@ -20,19 +27,66 @@ Dialog { placeholderText: "Room Alias/User ID" } - } - standardButtons: Dialog.Ok | Dialog.Cancel + MenuSeparator { + Layout.fillWidth: true + } - onAccepted: { - var identifier = identifierField.text - var firstChar = identifier.charAt(0) - if (firstChar == "@") { - spectralController.createDirectChat(spectralController.connection, identifier) - } else if (firstChar == "!" || firstChar == "#") { - spectralController.joinRoom(spectralController.connection, identifier) + AutoListView { + Layout.fillWidth: true + Layout.fillHeight: true + + id: publicRoomsListView + + spacing: 8 + + model: PublicRoomListModel { + connection: root.connection + } + + delegate: ColumnLayout { + width: publicRoomsListView.width + + Label { + Layout.fillWidth: true + + text: name ? name : "No name" + color: MPalette.foreground + font.pixelSize: 13 + textFormat: Text.PlainText + elide: Text.ElideRight + wrapMode: Text.NoWrap + } + + Label { + Layout.fillWidth: true + + visible: text + + text: topic ? topic.replace(/(\r\n\t|\n|\r\t)/gm," ") : "" + color: MPalette.lighter + font.pixelSize: 10 + textFormat: Text.PlainText + elide: Text.ElideRight + wrapMode: Text.NoWrap + } + } + + ScrollBar.vertical: ScrollBar {} } } +// standardButtons: Dialog.Ok | Dialog.Cancel + +// onAccepted: { +// var identifier = identifierField.text +// var firstChar = identifier.charAt(0) +// if (firstChar == "@") { +// spectralController.createDirectChat(spectralController.connection, identifier) +// } else if (firstChar == "!" || firstChar == "#") { +// spectralController.joinRoom(spectralController.connection, identifier) +// } +// } + onClosed: destroy() } diff --git a/include/SortFilterProxyModel b/include/SortFilterProxyModel index 770789ee4..36befddf5 160000 --- a/include/SortFilterProxyModel +++ b/include/SortFilterProxyModel @@ -1 +1 @@ -Subproject commit 770789ee484abf69c230cbf1b64f39823e79a181 +Subproject commit 36befddf5d57faad990e72c88c5844794f274145 diff --git a/include/libQuotient b/include/libQuotient index 5937127b7..04960510d 160000 --- a/include/libQuotient +++ b/include/libQuotient @@ -1 +1 @@ -Subproject commit 5937127b73a82fc86f6546397373ce9dbaf4e560 +Subproject commit 04960510df6058b4f25d3c41001a519e9fc5ba4a diff --git a/src/controller.cpp b/src/controller.cpp index 8b5d85e35..371d517f7 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -1,19 +1,6 @@ #include "controller.h" -#include "settings.h" -#include "spectralroom.h" -#include "spectraluser.h" - -#include "events/eventcontent.h" -#include "events/roommessageevent.h" - -#include "csapi/account-data.h" -#include "csapi/content-repo.h" -#include "csapi/joining.h" -#include "csapi/logout.h" -#include "csapi/profile.h" - -#include "utils.h" +#include #include #include @@ -33,7 +20,17 @@ #include #include -#include +#include "csapi/account-data.h" +#include "csapi/content-repo.h" +#include "csapi/joining.h" +#include "csapi/logout.h" +#include "csapi/profile.h" +#include "events/eventcontent.h" +#include "events/roommessageevent.h" +#include "settings.h" +#include "spectralroom.h" +#include "spectraluser.h" +#include "utils.h" Controller::Controller(QObject* parent) : QObject(parent) { QApplication::setQuitOnLastWindowClosed(false); @@ -386,7 +383,7 @@ void Controller::changeAvatar(Connection* conn, QUrl localFile) { } void Controller::markAllMessagesAsRead(Connection* conn) { - for (auto room : conn->roomMap().values()) { + for (auto room : conn->allRooms()) { room->markAllMessagesAsRead(); } } diff --git a/src/controller.h b/src/controller.h index 11f6e0541..09130e9d7 100644 --- a/src/controller.h +++ b/src/controller.h @@ -1,12 +1,6 @@ #ifndef CONTROLLER_H #define CONTROLLER_H -#include "connection.h" -#include "notifications/manager.h" -#include "room.h" -#include "settings.h" -#include "user.h" - #include #include #include @@ -14,7 +8,14 @@ #include #include -using namespace QMatrixClient; +#include "connection.h" +#include "csapi/list_public_rooms.h" +#include "notifications/manager.h" +#include "room.h" +#include "settings.h" +#include "user.h" + +using namespace Quotient; class Controller : public QObject { Q_OBJECT diff --git a/src/main.cpp b/src/main.cpp index afd72b531..f7e12b45d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,11 +7,14 @@ #include "accountlistmodel.h" #include "controller.h" +#include "csapi/joining.h" +#include "csapi/leaving.h" #include "emojimodel.h" #include "imageclipboard.h" #include "matriximageprovider.h" #include "messageeventmodel.h" #include "notifications/manager.h" +#include "publicroomlistmodel.h" #include "room.h" #include "roomlistmodel.h" #include "spectralroom.h" @@ -19,9 +22,6 @@ #include "trayicon.h" #include "userlistmodel.h" -#include "csapi/joining.h" -#include "csapi/leaving.h" - using namespace QMatrixClient; int main(int argc, char* argv[]) { @@ -41,6 +41,7 @@ int main(int argc, char* argv[]) { qmlRegisterType("Spectral", 0, 1, "RoomListModel"); qmlRegisterType("Spectral", 0, 1, "UserListModel"); qmlRegisterType("Spectral", 0, 1, "MessageEventModel"); + qmlRegisterType("Spectral", 0, 1, "PublicRoomListModel"); qmlRegisterType("Spectral", 0, 1, "EmojiModel"); qmlRegisterType("Spectral", 0, 1, "NotificationsManager"); diff --git a/src/publicroomlistmodel.cpp b/src/publicroomlistmodel.cpp new file mode 100644 index 000000000..621386209 --- /dev/null +++ b/src/publicroomlistmodel.cpp @@ -0,0 +1,89 @@ +#include "publicroomlistmodel.h" + +#include "csapi/list_public_rooms.h" + +PublicRoomListModel::PublicRoomListModel(QObject* parent) + : QAbstractListModel(parent) {} + +void PublicRoomListModel::setConnection(Connection* conn) { + if (m_connection == conn) + return; + + beginResetModel(); + + nextBatch = ""; + attempted = false; + rooms.clear(); + + if (m_connection) { + m_connection->disconnect(this); + } + + endResetModel(); + + m_connection = conn; + + if (m_connection) { + next(); + } + + emit connectionChanged(); +} + +void PublicRoomListModel::next(int count) { + if (count < 1) + return; + + if (attempted && nextBatch.isEmpty()) + return; + + auto job = m_connection->callApi(count, nextBatch); + + connect(job, &BaseJob::success, this, [=] { + auto resp = job->data(); + nextBatch = resp.nextBatch; + + this->beginInsertRows({}, rooms.count(), + rooms.count() + resp.chunk.count()); + rooms.append(resp.chunk); + this->endInsertRows(); + }); + + connect(job, &BaseJob::finished, this, [=] { attempted = true; }); +} + +QVariant PublicRoomListModel::data(const QModelIndex& index, int role) const { + if (!index.isValid()) + return QVariant(); + + if (index.row() >= rooms.count()) { + qDebug() << "PublicRoomListModel, something's wrong: index.row() >= " + "rooms.count()"; + return {}; + } + auto room = rooms.at(index.row()); + if (role == NameRole) { + return room.name; + } + if (role == TopicRole) { + return room.topic; + } + + return {}; +} + +QHash PublicRoomListModel::roleNames() const { + QHash roles; + + roles[NameRole] = "name"; + roles[TopicRole] = "topic"; + + return roles; +} + +int PublicRoomListModel::rowCount(const QModelIndex& parent) const { + if (parent.isValid()) + return 0; + + return rooms.count(); +} diff --git a/src/publicroomlistmodel.h b/src/publicroomlistmodel.h new file mode 100644 index 000000000..b0cebe06a --- /dev/null +++ b/src/publicroomlistmodel.h @@ -0,0 +1,43 @@ +#ifndef PUBLICROOMLISTMODEL_H +#define PUBLICROOMLISTMODEL_H + +#include +#include + +#include "connection.h" +#include "csapi/definitions/public_rooms_response.h" + +using namespace Quotient; + +class PublicRoomListModel : public QAbstractListModel { + Q_OBJECT + Q_PROPERTY(Connection* connection READ connection WRITE setConnection NOTIFY connectionChanged) + + public: + enum EventRoles { NameRole = Qt::DisplayRole + 1, TopicRole }; + + PublicRoomListModel(QObject* parent = nullptr); + + QVariant data(const QModelIndex& index, int role = NameRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + QHash roleNames() const override; + + Connection* connection() const { return m_connection; } + void setConnection(Connection* value); + + Q_INVOKABLE void next(int count = 50); + + private: + Connection* m_connection = nullptr; + + bool attempted = false; + QString nextBatch; + + QVector rooms; + +signals: + void connectionChanged(); +}; + +#endif // PUBLICROOMLISTMODEL_H diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index 8460c080f..6f02312ba 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -59,7 +59,7 @@ void RoomListModel::setConnection(Connection* connection) { void RoomListModel::doResetModel() { beginResetModel(); m_rooms.clear(); - for (auto r : m_connection->roomMap()) { + for (auto r : m_connection->allRooms()) { doAddRoom(r); } endResetModel(); diff --git a/src/userlistmodel.cpp b/src/userlistmodel.cpp index e7d088a22..016cb0bfc 100644 --- a/src/userlistmodel.cpp +++ b/src/userlistmodel.cpp @@ -1,13 +1,13 @@ #include "userlistmodel.h" -#include -#include -#include - #include #include #include +#include +#include +#include + #include "spectraluser.h" UserListModel::UserListModel(QObject* parent) @@ -17,7 +17,7 @@ void UserListModel::setRoom(QMatrixClient::Room* room) { if (m_currentRoom == room) return; - using namespace QMatrixClient; + using namespace Quotient; beginResetModel(); if (m_currentRoom) { m_currentRoom->disconnect(this);