summary refs log tree commit diff
path: root/src/timeline/CommunitiesModel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/timeline/CommunitiesModel.cpp')
-rw-r--r--src/timeline/CommunitiesModel.cpp164
1 files changed, 163 insertions, 1 deletions
diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp
index 7b267bcb..6d60c2b9 100644
--- a/src/timeline/CommunitiesModel.cpp
+++ b/src/timeline/CommunitiesModel.cpp
@@ -5,20 +5,29 @@
 
 #include "CommunitiesModel.h"
 
+#include <mtx/responses/common.hpp>
 #include <set>
 
 #include "Cache.h"
 #include "Cache_p.h"
 #include "ChatPage.h"
 #include "Logging.h"
+#include "MatrixClient.h"
+#include "Permissions.h"
 #include "UserSettingsPage.h"
 #include "Utils.h"
+#include "timeline/TimelineModel.h"
+
+Q_DECLARE_METATYPE(SpaceItem)
 
 CommunitiesModel::CommunitiesModel(QObject *parent)
   : QAbstractListModel(parent)
   , hiddenTagIds_{UserSettings::instance()->hiddenTags()}
   , mutedTagIds_{UserSettings::instance()->mutedTags()}
-{}
+{
+    static auto ignore = qRegisterMetaType<SpaceItem>();
+    (void)ignore;
+}
 
 QHash<int, QByteArray>
 CommunitiesModel::roleNames() const
@@ -723,3 +732,156 @@ FilteredCommunitiesModel::filterAcceptsRow(int sourceRow, const QModelIndex &) c
 
     return true;
 }
+
+QVariantList
+CommunitiesModel::spaceChildrenListFromIndex(QString room, int idx) const
+{
+    if (idx < -1)
+        return {};
+
+    auto room_ = room.toStdString();
+
+    int begin = idx + 1;
+    int end   = idx >= 0 ? this->spaceOrder_.lastChild(idx) + 1 : this->spaceOrder_.size();
+    QVariantList ret;
+
+    bool canSendParent = Permissions(room).canChange(qml_mtx_events::SpaceParent);
+
+    for (int i = begin; i < end; i++) {
+        const auto &e = spaceOrder_.tree[i];
+        if (e.depth == spaceOrder_.tree[begin].depth && spaces_.count(e.id)) {
+            bool canSendChild = Permissions(e.id).canChange(qml_mtx_events::SpaceChild);
+            auto spaceId      = e.id.toStdString();
+            auto child =
+              cache::client()->getStateEvent<mtx::events::state::space::Child>(spaceId, room_);
+            auto parent =
+              cache::client()->getStateEvent<mtx::events::state::space::Parent>(room_, spaceId);
+
+            bool childValid =
+              child && !child->content.via.value_or(std::vector<std::string>{}).empty();
+            bool parentValid =
+              parent && !parent->content.via.value_or(std::vector<std::string>{}).empty();
+            bool canonical = parent && parent->content.canonical;
+
+            if (e.id == room) {
+                canonical = parentValid = childValid = canSendChild = canSendParent = false;
+            }
+
+            ret.push_back(
+              QVariant::fromValue(SpaceItem(e.id,
+                                            QString::fromStdString(spaces_.at(e.id).name),
+                                            i,
+                                            childValid,
+                                            parentValid,
+                                            canonical,
+                                            canSendChild,
+                                            canSendParent)));
+        }
+    }
+
+    nhlog::ui()->critical("Returning {} spaces", ret.size());
+    return ret;
+}
+
+void
+CommunitiesModel::updateSpaceStatus(QString space,
+                                    QString room,
+                                    bool setParent,
+                                    bool setChild,
+                                    bool canonical) const
+{
+    nhlog::ui()->critical("Setting space {} children {}: {} {} {}",
+                          space.toStdString(),
+                          room.toStdString(),
+                          setParent,
+                          setChild,
+                          canonical);
+    auto child =
+      cache::client()
+        ->getStateEvent<mtx::events::state::space::Child>(space.toStdString(), room.toStdString())
+        .value_or(mtx::events::StateEvent<mtx::events::state::space::Child>{})
+        .content;
+    auto parent =
+      cache::client()
+        ->getStateEvent<mtx::events::state::space::Parent>(room.toStdString(), space.toStdString())
+        .value_or(mtx::events::StateEvent<mtx::events::state::space::Parent>{})
+        .content;
+
+    if (setChild) {
+        if (!child.via || child.via->empty()) {
+            child.via       = utils::roomVias(room.toStdString());
+            child.suggested = true;
+
+            http::client()->send_state_event(
+              space.toStdString(),
+              room.toStdString(),
+              child,
+              [space, room](mtx::responses::EventId, mtx::http::RequestErr err) {
+                  if (err) {
+                      ChatPage::instance()->showNotification(
+                        tr("Failed to update space child: %1")
+                          .arg(QString::fromStdString(err->matrix_error.error)));
+                      nhlog::net()->error("Failed to update child {} of {}: {}",
+                                          room.toStdString(),
+                                          space.toStdString());
+                  }
+              });
+        }
+    } else {
+        if (child.via && !child.via->empty()) {
+            http::client()->send_state_event(
+              space.toStdString(),
+              room.toStdString(),
+              mtx::events::state::space::Child{},
+              [space, room](mtx::responses::EventId, mtx::http::RequestErr err) {
+                  if (err) {
+                      ChatPage::instance()->showNotification(
+                        tr("Failed to delete space child: %1")
+                          .arg(QString::fromStdString(err->matrix_error.error)));
+                      nhlog::net()->error("Failed to delete child {} of {}: {}",
+                                          room.toStdString(),
+                                          space.toStdString());
+                  }
+              });
+        }
+    }
+
+    if (setParent) {
+        if (!parent.via || parent.via->empty() || canonical != parent.canonical) {
+            parent.via       = utils::roomVias(room.toStdString());
+            parent.canonical = canonical;
+
+            http::client()->send_state_event(
+              room.toStdString(),
+              space.toStdString(),
+              parent,
+              [space, room](mtx::responses::EventId, mtx::http::RequestErr err) {
+                  if (err) {
+                      ChatPage::instance()->showNotification(
+                        tr("Failed to update space parent: %1")
+                          .arg(QString::fromStdString(err->matrix_error.error)));
+                      nhlog::net()->error("Failed to update parent {} of {}: {}",
+                                          space.toStdString(),
+                                          room.toStdString());
+                  }
+              });
+        }
+    } else {
+        if (parent.via && !parent.via->empty()) {
+            http::client()->send_state_event(
+              room.toStdString(),
+              space.toStdString(),
+              mtx::events::state::space::Parent{},
+              [space, room](mtx::responses::EventId, mtx::http::RequestErr err) {
+                  if (err) {
+                      ChatPage::instance()->showNotification(
+                        tr("Failed to delete space parent: %1")
+                          .arg(QString::fromStdString(err->matrix_error.error)));
+                      nhlog::net()->error("Failed to delete parent {} of {}: {}",
+                                          space.toStdString(),
+                                          room.toStdString());
+                  }
+              });
+        }
+    }
+}