summary refs log tree commit diff
path: root/src/timeline
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-06-09 23:52:28 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2021-06-09 23:52:28 +0200
commit2cd1a931c28d0fd8e8755e9622a7d8f56d1a24a0 (patch)
treeafb784e8479553904b64fe49abea031c6ff09879 /src/timeline
parentImplement switching in narrow mode (diff)
downloadnheko-2cd1a931c28d0fd8e8755e9622a7d8f56d1a24a0.tar.xz
Basic community list model
Diffstat (limited to 'src/timeline')
-rw-r--r--src/timeline/CommunitiesModel.cpp158
-rw-r--r--src/timeline/CommunitiesModel.h60
-rw-r--r--src/timeline/RoomlistModel.cpp23
-rw-r--r--src/timeline/RoomlistModel.h1
-rw-r--r--src/timeline/TimelineViewManager.cpp9
-rw-r--r--src/timeline/TimelineViewManager.h4
6 files changed, 230 insertions, 25 deletions
diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp
new file mode 100644
index 00000000..cedaacce
--- /dev/null
+++ b/src/timeline/CommunitiesModel.cpp
@@ -0,0 +1,158 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "CommunitiesModel.h"
+
+#include <set>
+
+#include "Cache.h"
+#include "UserSettingsPage.h"
+
+CommunitiesModel::CommunitiesModel(QObject *parent)
+  : QAbstractListModel(parent)
+{}
+
+QHash<int, QByteArray>
+CommunitiesModel::roleNames() const
+{
+        return {
+          {AvatarUrl, "avatarUrl"},
+          {DisplayName, "displayName"},
+          {Tooltip, "tooltip"},
+          {ChildrenHidden, "childrenHidden"},
+        };
+}
+
+QVariant
+CommunitiesModel::data(const QModelIndex &index, int role) const
+{
+        if (index.row() == 0) {
+                switch (role) {
+                case CommunitiesModel::Roles::AvatarUrl:
+                        return QString(":/icons/icons/ui/world.png");
+                case CommunitiesModel::Roles::DisplayName:
+                        return tr("All rooms");
+                case CommunitiesModel::Roles::Tooltip:
+                        return tr("Shows all rooms without filtering.");
+                case CommunitiesModel::Roles::ChildrenHidden:
+                        return false;
+                case CommunitiesModel::Roles::Id:
+                        return "";
+                }
+        } else if (index.row() - 1 < tags_.size()) {
+                auto tag = tags_.at(index.row() - 1);
+                if (tag == "m.favourite") {
+                        switch (role) {
+                        case CommunitiesModel::Roles::AvatarUrl:
+                                return QString(":/icons/icons/ui/star.png");
+                        case CommunitiesModel::Roles::DisplayName:
+                                return tr("Favourites");
+                        case CommunitiesModel::Roles::Tooltip:
+                                return tr("Rooms you have favourited.");
+                        }
+                } else if (tag == "m.lowpriority") {
+                        switch (role) {
+                        case CommunitiesModel::Roles::AvatarUrl:
+                                return QString(":/icons/icons/ui/star.png");
+                        case CommunitiesModel::Roles::DisplayName:
+                                return tr("Low Priority");
+                        case CommunitiesModel::Roles::Tooltip:
+                                return tr("Rooms with low priority.");
+                        }
+                } else if (tag == "m.server_notice") {
+                        switch (role) {
+                        case CommunitiesModel::Roles::AvatarUrl:
+                                return QString(":/icons/icons/ui/tag.png");
+                        case CommunitiesModel::Roles::DisplayName:
+                                return tr("Server Notices");
+                        case CommunitiesModel::Roles::Tooltip:
+                                return tr("Messages from your server or administrator.");
+                        }
+                } else {
+                        switch (role) {
+                        case CommunitiesModel::Roles::AvatarUrl:
+                                return QString(":/icons/icons/ui/tag.png");
+                        case CommunitiesModel::Roles::DisplayName:
+                                return tag.right(2);
+                        case CommunitiesModel::Roles::Tooltip:
+                                return tag.right(2);
+                        }
+                }
+
+                switch (role) {
+                case CommunitiesModel::Roles::ChildrenHidden:
+                        return UserSettings::instance()->hiddenTags().contains("tag:" + tag);
+                case CommunitiesModel::Roles::Id:
+                        return "tag:" + tag;
+                }
+        }
+        return QVariant();
+}
+
+void
+CommunitiesModel::initializeSidebar()
+{
+        std::set<std::string> ts;
+        for (const auto &e : cache::roomInfo()) {
+                for (const auto &t : e.tags) {
+                        if (t.find("u.") == 0 || t.find("m." == 0)) {
+                                ts.insert(t);
+                        }
+                }
+        }
+
+        beginResetModel();
+        tags_.clear();
+        for (const auto &t : ts)
+                tags_.push_back(QString::fromStdString(t));
+        endResetModel();
+
+        emit tagsChanged();
+}
+
+void
+CommunitiesModel::clear()
+{
+        beginResetModel();
+        tags_.clear();
+        endResetModel();
+
+        emit tagsChanged();
+}
+
+void
+CommunitiesModel::sync(const mtx::responses::Rooms &rooms)
+{
+        bool tagsUpdated = false;
+
+        for (const auto &[roomid, room] : rooms.join) {
+                (void)roomid;
+                for (const auto &e : room.account_data.events)
+                        if (std::holds_alternative<
+                              mtx::events::AccountDataEvent<mtx::events::account_data::Tags>>(e)) {
+                                tagsUpdated = true;
+                        }
+        }
+
+        if (tagsUpdated)
+                initializeSidebar();
+}
+
+void
+CommunitiesModel::setCurrentTagId(QString tagId)
+{
+        if (tagId.startsWith("tag:")) {
+                auto tag = tagId.remove(0, 4);
+                for (const auto &t : tags_) {
+                        if (t == tag) {
+                                this->currentTagId_ = tagId;
+                                emit currentTagIdChanged();
+                                return;
+                        }
+                }
+        }
+
+        this->currentTagId_ = "";
+        emit currentTagIdChanged();
+}
diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h
new file mode 100644
index 00000000..3f6a2a4c
--- /dev/null
+++ b/src/timeline/CommunitiesModel.h
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <QAbstractListModel>
+#include <QHash>
+#include <QString>
+#include <QStringList>
+
+#include <mtx/responses/sync.hpp>
+
+class CommunitiesModel : public QAbstractListModel
+{
+        Q_OBJECT
+        Q_PROPERTY(QString currentTagId READ currentTagId WRITE setCurrentTagId NOTIFY
+                     currentTagIdChanged RESET resetCurrentTagId)
+        Q_PROPERTY(QStringList tags READ tags NOTIFY tagsChanged)
+
+public:
+        enum Roles
+        {
+                AvatarUrl = Qt::UserRole,
+                DisplayName,
+                Tooltip,
+                ChildrenHidden,
+                Id,
+        };
+
+        CommunitiesModel(QObject *parent = nullptr);
+        QHash<int, QByteArray> roleNames() const override;
+        int rowCount(const QModelIndex &parent = QModelIndex()) const override
+        {
+                (void)parent;
+                return 1 + tags_.size();
+        }
+        QVariant data(const QModelIndex &index, int role) const override;
+
+public slots:
+        void initializeSidebar();
+        void sync(const mtx::responses::Rooms &rooms);
+        void clear();
+        QString currentTagId() const { return currentTagId_; }
+        void setCurrentTagId(QString tagId);
+        void resetCurrentTagId()
+        {
+                currentTagId_.clear();
+                emit currentTagIdChanged();
+        }
+        QStringList tags() const { return tags_; }
+
+signals:
+        void currentTagIdChanged();
+        void tagsChanged();
+
+private:
+        QStringList tags_;
+        QString currentTagId_;
+};
diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index 283224f1..4dd44b30 100644
--- a/src/timeline/RoomlistModel.cpp
+++ b/src/timeline/RoomlistModel.cpp
@@ -485,29 +485,6 @@ FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *pare
         sort(0);
 }
 
-QStringList
-FilteredRoomlistModel::tags()
-{
-        std::set<std::string> ts;
-        for (const auto &e : cache::roomInfo()) {
-                for (const auto &t : e.tags) {
-                        if (t.find("u.") == 0) {
-                                ts.insert(t);
-                        }
-                }
-        }
-
-        QStringList ret{{
-          "m.favourite",
-          "m.lowpriority",
-        }};
-
-        for (const auto &t : ts)
-                ret.push_back(QString::fromStdString(t));
-
-        return ret;
-}
-
 void
 FilteredRoomlistModel::toggleTag(QString roomid, QString tag, bool on)
 {
diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h
index fa991f6b..7ee0419f 100644
--- a/src/timeline/RoomlistModel.h
+++ b/src/timeline/RoomlistModel.h
@@ -119,7 +119,6 @@ public slots:
         void acceptInvite(QString roomid) { roomlistmodel->acceptInvite(roomid); }
         void declineInvite(QString roomid) { roomlistmodel->declineInvite(roomid); }
         void leave(QString roomid) { roomlistmodel->leave(roomid); }
-        QStringList tags();
         void toggleTag(QString roomid, QString tag, bool on);
 
         TimelineModel *currentRoom() const { return roomlistmodel->currentRoom(); }
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index dd623f2f..faf56b85 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -135,6 +135,7 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
   , blurhashProvider(new BlurhashProvider())
   , callManager_(callManager)
   , rooms_(new RoomlistModel(this))
+  , communities_(new CommunitiesModel(this))
 {
         qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>();
         qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>();
@@ -196,6 +197,12 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
           "im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * {
                   return new FilteredRoomlistModel(self->rooms_);
           });
+        qmlRegisterSingletonType<RoomlistModel>(
+          "im.nheko", 1, 0, "Communities", [](QQmlEngine *, QJSEngine *) -> QObject * {
+                  auto ptr = self->communities_;
+                  QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
+                  return ptr;
+          });
         qmlRegisterSingletonType<UserSettings>(
           "im.nheko", 1, 0, "Settings", [](QQmlEngine *, QJSEngine *) -> QObject * {
                   auto ptr = ChatPage::instance()->userSettings().data();
@@ -324,6 +331,7 @@ void
 TimelineViewManager::sync(const mtx::responses::Rooms &rooms_res)
 {
         this->rooms_->sync(rooms_res);
+        this->communities_->sync(rooms_res);
 
         if (isInitialSync_) {
                 this->isInitialSync_ = false;
@@ -486,6 +494,7 @@ void
 TimelineViewManager::initializeRoomlist()
 {
         rooms_->initializeRooms();
+        communities_->initializeSidebar();
 }
 
 void
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 68d9cd1b..556bcf4c 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -22,6 +22,7 @@
 #include "WebRTCSession.h"
 #include "emoji/EmojiModel.h"
 #include "emoji/Provider.h"
+#include "timeline/CommunitiesModel.h"
 #include "timeline/RoomlistModel.h"
 
 class MxcImageProvider;
@@ -131,7 +132,8 @@ private:
         bool isInitialSync_   = true;
         bool isWindowFocused_ = false;
 
-        RoomlistModel *rooms_ = nullptr;
+        RoomlistModel *rooms_          = nullptr;
+        CommunitiesModel *communities_ = nullptr;
 
         QHash<QString, QColor> userColors;