mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-23 11:28:49 +03:00
Begin adding space child management
This commit is contained in:
parent
d3c6bcd43c
commit
cf09a6aa2f
16 changed files with 518 additions and 4 deletions
|
@ -375,6 +375,7 @@ set(SRC_FILES
|
||||||
src/SSOHandler.cpp
|
src/SSOHandler.cpp
|
||||||
src/CombinedImagePackModel.cpp
|
src/CombinedImagePackModel.cpp
|
||||||
src/SingleImagePackModel.cpp
|
src/SingleImagePackModel.cpp
|
||||||
|
src/SpaceChildrenModel.cpp
|
||||||
src/ImagePackListModel.cpp
|
src/ImagePackListModel.cpp
|
||||||
src/TrayIcon.cpp
|
src/TrayIcon.cpp
|
||||||
src/UserSettingsPage.cpp
|
src/UserSettingsPage.cpp
|
||||||
|
@ -570,6 +571,7 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||||
src/RoomsModel.h
|
src/RoomsModel.h
|
||||||
src/SSOHandler.h
|
src/SSOHandler.h
|
||||||
src/SingleImagePackModel.h
|
src/SingleImagePackModel.h
|
||||||
|
src/SpaceChildrenModel.h
|
||||||
src/TrayIcon.h
|
src/TrayIcon.h
|
||||||
src/UserSettingsPage.h
|
src/UserSettingsPage.h
|
||||||
src/UsersModel.h
|
src/UsersModel.h
|
||||||
|
|
|
@ -59,6 +59,14 @@ Pane {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: spaceChildrenComponent
|
||||||
|
|
||||||
|
SpaceChildren {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: roomMembersComponent
|
id: roomMembersComponent
|
||||||
|
|
||||||
|
@ -265,6 +273,15 @@ Pane {
|
||||||
destroyOnClose(roomSettings);
|
destroyOnClose(roomSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onOpenSpaceChildrenDialog(spaceChildren, nonChildren) {
|
||||||
|
var spaceChildrenDialog = spaceChildrenComponent.createObject(timelineRoot, {
|
||||||
|
"spaceChildren": spaceChildren,
|
||||||
|
"nonChildren": nonChildren
|
||||||
|
});
|
||||||
|
spaceChildrenDialog.show();
|
||||||
|
destroyOnClose(spaceChildrenDialog);
|
||||||
|
}
|
||||||
|
|
||||||
function onOpenInviteUsersDialog(invitees) {
|
function onOpenInviteUsersDialog(invitees) {
|
||||||
var dialog = inviteDialog.createObject(timelineRoot, {
|
var dialog = inviteDialog.createObject(timelineRoot, {
|
||||||
"roomId": Rooms.currentRoom.roomId,
|
"roomId": Rooms.currentRoom.roomId,
|
||||||
|
|
|
@ -362,6 +362,18 @@ ApplicationWindow {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignRight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: roomSettings.isSpace
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
visible: roomSettings.isSpace
|
||||||
|
text: qsTr("Manage space children")
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
onClicked: TimelineManager.openSpaceChildren(roomSettings.roomId)
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
// for adding extra space between sections
|
// for adding extra space between sections
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
188
resources/qml/dialogs/SpaceChildren.qml
Normal file
188
resources/qml/dialogs/SpaceChildren.qml
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Nheko Contributors
|
||||||
|
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
import ".."
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtQuick.Window 2.13
|
||||||
|
import im.nheko 1.0
|
||||||
|
|
||||||
|
ApplicationWindow {
|
||||||
|
id: spaceChildrenDialog
|
||||||
|
|
||||||
|
property SpaceChildrenModel spaceChildren
|
||||||
|
property NonSpaceChildrenModel nonChildren
|
||||||
|
|
||||||
|
minimumWidth: 340
|
||||||
|
minimumHeight: 450
|
||||||
|
width: 450
|
||||||
|
height: 680
|
||||||
|
palette: Nheko.colors
|
||||||
|
color: Nheko.colors.window
|
||||||
|
modality: Qt.NonModal
|
||||||
|
flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
|
||||||
|
title: qsTr("Space children")
|
||||||
|
|
||||||
|
Shortcut {
|
||||||
|
sequence: StandardKey.Cancel
|
||||||
|
onActivated: spaceChildrenDialog.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollHelper {
|
||||||
|
flickable: flickable
|
||||||
|
anchors.fill: flickable
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: contentLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Nheko.paddingMedium
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
|
||||||
|
Label {
|
||||||
|
color: Nheko.colors.text
|
||||||
|
horizontalAlignment: Label.AlignHCenter
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Children of %1").arg(spaceChildren.space.roomName)
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
font.pointSize: fontMetrics.font.pointSize * 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: childrenList
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
model: spaceChildren
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollHelper {
|
||||||
|
flickable: parent
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: RowLayout {
|
||||||
|
id: childDel
|
||||||
|
|
||||||
|
required property string id
|
||||||
|
required property string roomName
|
||||||
|
required property string avatarUrl
|
||||||
|
required property string alias
|
||||||
|
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.rightMargin: Nheko.paddingMedium
|
||||||
|
width: Nheko.avatarSize
|
||||||
|
height: Nheko.avatarSize
|
||||||
|
url: childDel.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||||
|
roomid: childDel.id
|
||||||
|
displayName: childDel.roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
|
||||||
|
Label {
|
||||||
|
font.bold: true
|
||||||
|
text: childDel.roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: childDel.alias
|
||||||
|
visible: childDel.alias
|
||||||
|
color: Nheko.inactiveColors.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
image: ":/icons/icons/ui/delete.svg"
|
||||||
|
onClicked: Nheko.removeRoomFromSpace(childDel.id, spaceChildren.space.roomId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
color: Nheko.colors.text
|
||||||
|
horizontalAlignment: Label.AlignHCenter
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Add rooms to %1").arg(spaceChildren.space.roomName)
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
font.pointSize: fontMetrics.font.pointSize * 1.5
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: nonChildrenList
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
model: nonChildren
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollHelper {
|
||||||
|
flickable: parent
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: RowLayout {
|
||||||
|
id: nonChildDel
|
||||||
|
|
||||||
|
required property string id
|
||||||
|
required property string roomName
|
||||||
|
required property string avatarUrl
|
||||||
|
required property string alias
|
||||||
|
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.rightMargin: Nheko.paddingMedium
|
||||||
|
width: Nheko.avatarSize
|
||||||
|
height: Nheko.avatarSize
|
||||||
|
url: nonChildDel.avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||||
|
roomid: nonChildDel.id
|
||||||
|
displayName: nonChildDel.roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: Nheko.paddingMedium
|
||||||
|
|
||||||
|
Label {
|
||||||
|
font.bold: true
|
||||||
|
text: nonChildDel.roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: nonChildDel.alias
|
||||||
|
visible: nonChildDel.alias
|
||||||
|
color: Nheko.inactiveColors.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
image: ":/icons/icons/ui/add-square-button.svg"
|
||||||
|
onClicked: Nheko.addRoomToSpace(nonChildDel.id, spaceChildren.space.roomId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: DialogButtonBox {
|
||||||
|
standardButtons: DialogButtonBox.Ok
|
||||||
|
onAccepted: close()
|
||||||
|
}
|
||||||
|
}
|
|
@ -177,6 +177,7 @@
|
||||||
<file>qml/voip/PlaceCall.qml</file>
|
<file>qml/voip/PlaceCall.qml</file>
|
||||||
<file>qml/voip/ScreenShare.qml</file>
|
<file>qml/voip/ScreenShare.qml</file>
|
||||||
<file>qml/voip/VideoCall.qml</file>
|
<file>qml/voip/VideoCall.qml</file>
|
||||||
|
<file>qml/dialogs/SpaceChildren.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/media">
|
<qresource prefix="/media">
|
||||||
<file>media/ring.ogg</file>
|
<file>media/ring.ogg</file>
|
||||||
|
|
|
@ -747,6 +747,45 @@ ChatPage::joinRoomVia(const std::string &room_id,
|
||||||
reason.toStdString());
|
reason.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ChatPage::addRoomToSpace(const QString &roomId, const QString &spaceId)
|
||||||
|
{
|
||||||
|
// Make sure that the user isn't trying to create an infinite loop. Granted, this is not
|
||||||
|
// perfect, since you could have a loop of the form "a => b => a => ...", but this is sufficient
|
||||||
|
// for now.
|
||||||
|
if (roomId == spaceId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mtx::events::state::space::Child child;
|
||||||
|
child.via = {roomId.splitRef(QStringLiteral(":")).last().toString().toStdString()};
|
||||||
|
http::client()->send_state_event(
|
||||||
|
roomId.toStdString(),
|
||||||
|
child,
|
||||||
|
[this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
emit showNotification(tr("Failed to add room to space: %1")
|
||||||
|
.arg(QString::fromStdString(err->matrix_error.error)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ChatPage::removeRoomFromSpace(const QString &roomId, const QString &spaceId)
|
||||||
|
{
|
||||||
|
auto childEvent = cache::client()->getStateEvent<mtx::events::state::space::Child>(
|
||||||
|
spaceId.toStdString(), "m.space.child");
|
||||||
|
if (childEvent.has_value())
|
||||||
|
http::client()->redact_event(
|
||||||
|
roomId.toStdString(),
|
||||||
|
childEvent->event_id,
|
||||||
|
[this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err) {
|
||||||
|
emit showNotification(tr("Failed to remove room from space: %1")
|
||||||
|
.arg(QString::fromStdString(err->matrix_error.error)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ChatPage::createRoom(const mtx::requests::CreateRoom &req)
|
ChatPage::createRoom(const mtx::requests::CreateRoom &req)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,6 +94,9 @@ public slots:
|
||||||
bool promptForConfirmation = true,
|
bool promptForConfirmation = true,
|
||||||
const QString &reason = "");
|
const QString &reason = "");
|
||||||
|
|
||||||
|
void addRoomToSpace(const QString &roomId, const QString &spaceId);
|
||||||
|
void removeRoomFromSpace(const QString &roomId, const QString &spaceId);
|
||||||
|
|
||||||
void inviteUser(QString userid, QString reason);
|
void inviteUser(QString userid, QString reason);
|
||||||
void kickUser(QString userid, QString reason);
|
void kickUser(QString userid, QString reason);
|
||||||
void banUser(QString userid, QString reason);
|
void banUser(QString userid, QString reason);
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "RoomDirectoryModel.h"
|
#include "RoomDirectoryModel.h"
|
||||||
#include "RoomsModel.h"
|
#include "RoomsModel.h"
|
||||||
#include "SingleImagePackModel.h"
|
#include "SingleImagePackModel.h"
|
||||||
|
#include "SpaceChildrenModel.h"
|
||||||
#include "TrayIcon.h"
|
#include "TrayIcon.h"
|
||||||
#include "UserSettingsPage.h"
|
#include "UserSettingsPage.h"
|
||||||
#include "UsersModel.h"
|
#include "UsersModel.h"
|
||||||
|
@ -212,6 +213,18 @@ MainWindow::registerQmlTypes()
|
||||||
0,
|
0,
|
||||||
"SingleImagePackModel",
|
"SingleImagePackModel",
|
||||||
QStringLiteral("SingleImagePackModel needs to be instantiated on the C++ side"));
|
QStringLiteral("SingleImagePackModel needs to be instantiated on the C++ side"));
|
||||||
|
qmlRegisterUncreatableType<SpaceChildrenModel>(
|
||||||
|
"im.nheko",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
"SpaceChildrenModel",
|
||||||
|
"SpaceChildrenModel needs to be instantiated on the C++ side");
|
||||||
|
qmlRegisterUncreatableType<NonSpaceChildrenModel>(
|
||||||
|
"im.nheko",
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
"NonSpaceChildrenModel",
|
||||||
|
"NonSpaceChildrenModel needs to be instantiated on the C++ side");
|
||||||
qmlRegisterUncreatableType<InviteesModel>(
|
qmlRegisterUncreatableType<InviteesModel>(
|
||||||
"im.nheko",
|
"im.nheko",
|
||||||
1,
|
1,
|
||||||
|
|
106
src/SpaceChildrenModel.cpp
Normal file
106
src/SpaceChildrenModel.cpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "SpaceChildrenModel.h"
|
||||||
|
|
||||||
|
#include "Cache.h"
|
||||||
|
#include "Cache_p.h"
|
||||||
|
|
||||||
|
SpaceChildrenModel::SpaceChildrenModel(QSharedPointer<TimelineModel> space, QObject *parent)
|
||||||
|
: QAbstractListModel{parent}
|
||||||
|
, m_space{space}
|
||||||
|
{
|
||||||
|
auto joinedRooms = cache::joinedRooms();
|
||||||
|
for (const auto &child : cache::client()->getChildRoomIds(m_space->roomId().toStdString())) {
|
||||||
|
m_childIds.push_back(QString::fromStdString(child));
|
||||||
|
|
||||||
|
if (std::find(std::begin(joinedRooms), std::end(joinedRooms), child) !=
|
||||||
|
std::end(joinedRooms))
|
||||||
|
m_childInfos.push_back(cache::singleRoomInfo(child));
|
||||||
|
else // TODO: replace with code to fetch a non-joined room
|
||||||
|
m_childInfos.push_back(cache::singleRoomInfo(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray>
|
||||||
|
SpaceChildrenModel::roleNames() const
|
||||||
|
{
|
||||||
|
return {{Roles::Id, "id"},
|
||||||
|
{Roles::RoomName, "roomName"},
|
||||||
|
{Roles::AvatarUrl, "avatarUrl"},
|
||||||
|
{Roles::Alias, "alias"}};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
SpaceChildrenModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.row() >= (int)m_childIds.size() || index.row() < 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Roles::Id:
|
||||||
|
return m_childIds[index.row()];
|
||||||
|
case Roles::RoomName:
|
||||||
|
return QString::fromStdString(m_childInfos[index.row()].name);
|
||||||
|
case Roles::AvatarUrl:
|
||||||
|
return QString::fromStdString(m_childInfos[index.row()].avatar_url);
|
||||||
|
case Roles::Alias: {
|
||||||
|
auto aliases = cache::client()->getRoomAliases(m_childIds[index.row()].toStdString());
|
||||||
|
if (aliases.has_value())
|
||||||
|
return QString::fromStdString(aliases->alias);
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NonSpaceChildrenModel::NonSpaceChildrenModel(QSharedPointer<TimelineModel> space, QObject *parent)
|
||||||
|
: QAbstractListModel{parent}
|
||||||
|
, m_space{space}
|
||||||
|
{
|
||||||
|
auto children = cache::client()->getChildRoomIds(m_space->roomId().toStdString());
|
||||||
|
for (const auto &room : cache::joinedRooms()) {
|
||||||
|
if (room == space->roomId().toStdString() ||
|
||||||
|
std::find(std::begin(children), std::end(children), room) == std::end(children)) {
|
||||||
|
m_roomIds.push_back(QString::fromStdString(room));
|
||||||
|
m_roomInfos.push_back(cache::singleRoomInfo(room));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray>
|
||||||
|
NonSpaceChildrenModel::roleNames() const
|
||||||
|
{
|
||||||
|
return {{Roles::Id, "id"},
|
||||||
|
{Roles::RoomName, "roomName"},
|
||||||
|
{Roles::AvatarUrl, "avatarUrl"},
|
||||||
|
{Roles::Alias, "alias"}};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
NonSpaceChildrenModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.row() >= (int)m_roomIds.size() || index.row() < 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Roles::Id:
|
||||||
|
return m_roomIds[index.row()];
|
||||||
|
case Roles::RoomName:
|
||||||
|
return QString::fromStdString(m_roomInfos[index.row()].name);
|
||||||
|
case Roles::AvatarUrl:
|
||||||
|
return QString::fromStdString(m_roomInfos[index.row()].avatar_url);
|
||||||
|
case Roles::Alias: {
|
||||||
|
auto aliases = cache::client()->getRoomAliases(m_roomIds[index.row()].toStdString());
|
||||||
|
if (aliases.has_value())
|
||||||
|
return QString::fromStdString(aliases->alias);
|
||||||
|
else
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
79
src/SpaceChildrenModel.h
Normal file
79
src/SpaceChildrenModel.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Nheko Contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef SPACECHILDRENMODEL_H
|
||||||
|
#define SPACECHILDRENMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include "timeline/TimelineModel.h"
|
||||||
|
|
||||||
|
class SpaceChildrenModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(TimelineModel *space READ space CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles
|
||||||
|
{
|
||||||
|
Id,
|
||||||
|
RoomName,
|
||||||
|
AvatarUrl,
|
||||||
|
Alias,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit SpaceChildrenModel(QSharedPointer<TimelineModel> space, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
TimelineModel *space() const { return m_space.data(); }
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent) const override
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return m_childIds.size();
|
||||||
|
}
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<TimelineModel> m_space;
|
||||||
|
QStringList m_childIds;
|
||||||
|
QList<RoomInfo> m_childInfos;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NonSpaceChildrenModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(TimelineModel *space READ space CONSTANT)
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Roles
|
||||||
|
{
|
||||||
|
Id,
|
||||||
|
RoomName,
|
||||||
|
AvatarUrl,
|
||||||
|
Alias,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit NonSpaceChildrenModel(QSharedPointer<TimelineModel> space, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
TimelineModel *space() const { return m_space.data(); }
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent) const override
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return m_roomIds.size();
|
||||||
|
}
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSharedPointer<TimelineModel> m_space;
|
||||||
|
QStringList m_roomIds;
|
||||||
|
QList<RoomInfo> m_roomInfos;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SPACECHILDRENMODEL_H
|
|
@ -180,6 +180,16 @@ TimelineViewManager::openRoomSettings(QString room_id)
|
||||||
emit openRoomSettingsDialog(settings);
|
emit openRoomSettingsDialog(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineViewManager::openSpaceChildren(const QString &spaceId)
|
||||||
|
{
|
||||||
|
auto children = new SpaceChildrenModel{rooms_->getRoomById(spaceId)};
|
||||||
|
auto nonChildren = new NonSpaceChildrenModel{rooms_->getRoomById(spaceId)};
|
||||||
|
QQmlEngine::setObjectOwnership(children, QQmlEngine::JavaScriptOwnership);
|
||||||
|
QQmlEngine::setObjectOwnership(nonChildren, QQmlEngine::JavaScriptOwnership);
|
||||||
|
emit openSpaceChildrenDialog(children, nonChildren);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineViewManager::openInviteUsers(QString roomId)
|
TimelineViewManager::openInviteUsers(QString roomId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "Cache.h"
|
#include "Cache.h"
|
||||||
#include "JdenticonProvider.h"
|
#include "JdenticonProvider.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
#include "SpaceChildrenModel.h"
|
||||||
#include "TimelineModel.h"
|
#include "TimelineModel.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "emoji/EmojiModel.h"
|
#include "emoji/EmojiModel.h"
|
||||||
|
@ -65,6 +66,7 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE void openRoomMembers(TimelineModel *room);
|
Q_INVOKABLE void openRoomMembers(TimelineModel *room);
|
||||||
Q_INVOKABLE void openRoomSettings(QString room_id);
|
Q_INVOKABLE void openRoomSettings(QString room_id);
|
||||||
|
Q_INVOKABLE void openSpaceChildren(const QString &spaceId);
|
||||||
Q_INVOKABLE void openInviteUsers(QString roomId);
|
Q_INVOKABLE void openInviteUsers(QString roomId);
|
||||||
Q_INVOKABLE void openGlobalUserProfile(QString userId);
|
Q_INVOKABLE void openGlobalUserProfile(QString userId);
|
||||||
Q_INVOKABLE UserProfile *getGlobalUserProfile(QString userId);
|
Q_INVOKABLE UserProfile *getGlobalUserProfile(QString userId);
|
||||||
|
@ -86,6 +88,7 @@ signals:
|
||||||
void focusInput();
|
void focusInput();
|
||||||
void openRoomMembersDialog(MemberList *members, TimelineModel *room);
|
void openRoomMembersDialog(MemberList *members, TimelineModel *room);
|
||||||
void openRoomSettingsDialog(RoomSettings *settings);
|
void openRoomSettingsDialog(RoomSettings *settings);
|
||||||
|
void openSpaceChildrenDialog(SpaceChildrenModel *children, NonSpaceChildrenModel *nonChildren);
|
||||||
void openInviteUsersDialog(InviteesModel *invitees);
|
void openInviteUsersDialog(InviteesModel *invitees);
|
||||||
void openProfile(UserProfile *profile);
|
void openProfile(UserProfile *profile);
|
||||||
void showImagePackSettings(TimelineModel *room, ImagePackListModel *packlist);
|
void showImagePackSettings(TimelineModel *room, ImagePackListModel *packlist);
|
||||||
|
|
|
@ -128,7 +128,12 @@ Nheko::logout() const
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Nheko::createRoom(QString name, QString topic, QString aliasLocalpart, bool isEncrypted, bool isSpace, int preset)
|
Nheko::createRoom(QString name,
|
||||||
|
QString topic,
|
||||||
|
QString aliasLocalpart,
|
||||||
|
bool isEncrypted,
|
||||||
|
bool isSpace,
|
||||||
|
int preset)
|
||||||
{
|
{
|
||||||
mtx::requests::CreateRoom req;
|
mtx::requests::CreateRoom req;
|
||||||
|
|
||||||
|
@ -156,9 +161,21 @@ Nheko::createRoom(QString name, QString topic, QString aliasLocalpart, bool isEn
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSpace) {
|
if (isSpace) {
|
||||||
req.creation_content = mtx::events::state::Create{};
|
req.creation_content = mtx::events::state::Create{};
|
||||||
req.creation_content->type = "m.space";
|
req.creation_content->type = "m.space";
|
||||||
}
|
}
|
||||||
|
|
||||||
emit ChatPage::instance()->createRoom(req);
|
emit ChatPage::instance()->createRoom(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Nheko::addRoomToSpace(const QString &roomId, const QString &spaceId)
|
||||||
|
{
|
||||||
|
ChatPage::instance()->addRoomToSpace(roomId, spaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Nheko::removeRoomFromSpace(const QString &roomId, const QString &spaceId)
|
||||||
|
{
|
||||||
|
ChatPage::instance()->removeRoomFromSpace(roomId, spaceId);
|
||||||
|
}
|
||||||
|
|
|
@ -52,8 +52,14 @@ public:
|
||||||
Q_INVOKABLE void setStatusMessage(QString msg) const;
|
Q_INVOKABLE void setStatusMessage(QString msg) const;
|
||||||
Q_INVOKABLE void showUserSettingsPage() const;
|
Q_INVOKABLE void showUserSettingsPage() const;
|
||||||
Q_INVOKABLE void logout() const;
|
Q_INVOKABLE void logout() const;
|
||||||
Q_INVOKABLE void
|
Q_INVOKABLE void createRoom(QString name,
|
||||||
createRoom(QString name, QString topic, QString aliasLocalpart, bool isEncrypted, bool isSpace, int preset);
|
QString topic,
|
||||||
|
QString aliasLocalpart,
|
||||||
|
bool isEncrypted,
|
||||||
|
bool isSpace,
|
||||||
|
int preset);
|
||||||
|
Q_INVOKABLE void addRoomToSpace(const QString &roomId, const QString &spaceId);
|
||||||
|
Q_INVOKABLE void removeRoomFromSpace(const QString &roomId, const QString &spaceId);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateUserProfile();
|
void updateUserProfile();
|
||||||
|
|
|
@ -243,6 +243,19 @@ RoomSettings::canChangeAvatar() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RoomSettings::canSetSpaceChild() const
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return cache::hasEnoughPowerLevel(
|
||||||
|
{EventType::SpaceChild}, roomid_.toStdString(), utils::localUser().toStdString());
|
||||||
|
} catch (const lmdb::error &e) {
|
||||||
|
nhlog::db()->warn("lmdb error: {}", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RoomSettings::isEncryptionEnabled() const
|
RoomSettings::isEncryptionEnabled() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -37,6 +37,7 @@ class RoomSettings : public QObject
|
||||||
Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY roomNameChanged)
|
Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY roomNameChanged)
|
||||||
Q_PROPERTY(QString plainRoomTopic READ plainRoomTopic NOTIFY roomTopicChanged)
|
Q_PROPERTY(QString plainRoomTopic READ plainRoomTopic NOTIFY roomTopicChanged)
|
||||||
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
|
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
|
||||||
|
Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
|
||||||
Q_PROPERTY(int memberCount READ memberCount CONSTANT)
|
Q_PROPERTY(int memberCount READ memberCount CONSTANT)
|
||||||
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
|
Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
|
||||||
Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
|
Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
|
||||||
|
@ -45,6 +46,7 @@ class RoomSettings : public QObject
|
||||||
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
|
Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
|
||||||
Q_PROPERTY(bool canChangeName READ canChangeName CONSTANT)
|
Q_PROPERTY(bool canChangeName READ canChangeName CONSTANT)
|
||||||
Q_PROPERTY(bool canChangeTopic READ canChangeTopic CONSTANT)
|
Q_PROPERTY(bool canChangeTopic READ canChangeTopic CONSTANT)
|
||||||
|
Q_PROPERTY(bool canSetSpaceChild READ canSetSpaceChild CONSTANT)
|
||||||
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
|
Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
|
||||||
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
|
Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
|
||||||
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
|
Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
|
||||||
|
@ -59,6 +61,7 @@ public:
|
||||||
QString plainRoomTopic() const;
|
QString plainRoomTopic() const;
|
||||||
QString roomVersion() const;
|
QString roomVersion() const;
|
||||||
QString roomAvatarUrl();
|
QString roomAvatarUrl();
|
||||||
|
bool isSpace() const { return info_.is_space; }
|
||||||
int memberCount() const;
|
int memberCount() const;
|
||||||
int notifications();
|
int notifications();
|
||||||
int accessJoinRules();
|
int accessJoinRules();
|
||||||
|
@ -71,6 +74,8 @@ public:
|
||||||
bool canChangeTopic() const;
|
bool canChangeTopic() const;
|
||||||
//! Whether the user has enough power level to send m.room.avatar event.
|
//! Whether the user has enough power level to send m.room.avatar event.
|
||||||
bool canChangeAvatar() const;
|
bool canChangeAvatar() const;
|
||||||
|
//! Whether the user has enough power level to add children to a space.
|
||||||
|
bool canSetSpaceChild() const;
|
||||||
bool isEncryptionEnabled() const;
|
bool isEncryptionEnabled() const;
|
||||||
bool supportsKnocking() const;
|
bool supportsKnocking() const;
|
||||||
bool supportsRestricted() const;
|
bool supportsRestricted() const;
|
||||||
|
|
Loading…
Reference in a new issue