Space Home Page

Add a space homepage with the ability to both create new room and add existing rooms to the space. This uses a tree model for the space hierarchy and will go to any number of levels. The user should only see the add options if they have appropriate permissions.

This MR also combines the create space and room pages and adds a lot of optional functionality for managing space children.

![image](/uploads/1764b0319241ff870dc39b18b39f5d51/image.png)
This commit is contained in:
James Graham
2023-09-28 17:36:23 +00:00
parent 08711fc927
commit ecdad9f965
24 changed files with 1486 additions and 80 deletions

View File

@@ -0,0 +1,139 @@
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
#pragma once
#include <QAbstractItemModel>
#include <QQmlEngine>
#include <Quotient/csapi/space_hierarchy.h>
#include <qtmetamacros.h>
#include "neochatroom.h"
#include "spacetreeitem.h"
/**
* @class SpaceChildrenModel
*
* Create a model that contains a list of the child rooms for any given space id.
*/
class SpaceChildrenModel : public QAbstractItemModel
{
Q_OBJECT
QML_ELEMENT
/**
* @brief The current space that the hierarchy is being generated for.
*/
Q_PROPERTY(NeoChatRoom *space READ space WRITE setSpace NOTIFY spaceChanged)
/**
* @brief Whether the model is loading the initial set of children.
*/
Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
public:
enum Roles {
DisplayNameRole = Qt::DisplayRole,
AvatarUrlRole,
TopicRole,
RoomIDRole,
AliasRole,
MemberCountRole,
AllowGuestsRole,
WorldReadableRole,
IsJoinedRole,
IsSpaceRole,
CanAddChildrenRole,
};
explicit SpaceChildrenModel(QObject *parent = nullptr);
~SpaceChildrenModel();
NeoChatRoom *space() const;
void setSpace(NeoChatRoom *space);
bool loading() const;
/**
* @brief Get the given role value at the given index.
*
* @sa QAbstractItemModel::data
*/
QVariant data(const QModelIndex &index, int role = DisplayNameRole) const override;
/**
* @brief Returns the index of the item in the model specified by the given row, column and parent index.
*
* @sa QAbstractItemModel::index
*/
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns the parent of the model item with the given index.
*
* If the item has no parent, an invalid QModelIndex is returned.
*
* @sa QAbstractItemModel::parent
*/
QModelIndex parent(const QModelIndex &index) const override;
/**
* @brief Number of rows in the model.
*
* @sa QAbstractItemModel::rowCount
*/
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Number of columns in the model.
*
* @sa QAbstractItemModel::columnCount
*/
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns a mapping from Role enum values to role names.
*
* @sa Roles, QAbstractItemModel::roleNames()
*/
QHash<int, QByteArray> roleNames() const override;
/**
* @brief Whether the room has been replaced.
*
* @note This information is only available if the local user is either a member
* of the replaced room or is a member of the successor room as currently
* there is no other way to obtain the required information.
*/
bool isRoomReplaced(const QString &roomId) const;
/**
* @brief Add the name of new child room that is expected to be added soon.
*
* A pending child is one where Quotient::Connection::createRoom has been called
* but the room hasn't synced with the server yet. This list is used to check
* whether a new room loading should trigger a refresh of the model, as we only
* want to trigger a refresh if the loading room is part of this space.
*/
Q_INVOKABLE void addPendingChild(const QString &childName);
Q_SIGNALS:
void spaceChanged();
void loadingChanged();
private:
NeoChatRoom *m_space = nullptr;
SpaceTreeItem *m_rootItem;
bool m_loading = false;
QList<QPointer<Quotient::GetSpaceHierarchyJob>> m_currentJobs;
QList<QString> m_pendingChildren;
QList<QString> m_replacedRooms;
SpaceTreeItem *getItem(const QModelIndex &index) const;
void refreshModel();
void insertChildren(std::vector<Quotient::GetSpaceHierarchyJob::ChildRoomsChunk> children, const QModelIndex &parent = QModelIndex());
};