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. 
This commit is contained in:
@@ -2,44 +2,225 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-or-later OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
import org.kde.kirigamiaddons.labs.components as Components
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
title: i18nc("@title", "Create a Room")
|
||||
property string parentId: ""
|
||||
|
||||
property bool isSpace: false
|
||||
|
||||
property bool showChildType: false
|
||||
|
||||
property bool showCreateChoice: false
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
signal addChild(string childId, bool setChildParent)
|
||||
signal newChild(string childName)
|
||||
|
||||
title: isSpace ? i18nc("@title", "Create a Space") : i18nc("@title", "Create a Room")
|
||||
|
||||
Component.onCompleted: roomNameField.forceActiveFocus()
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Room Information")
|
||||
title: root.isSpace ? i18n("New Space Information") : i18n("New Room Information")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormComboBoxDelegate {
|
||||
id: roomTypeCombo
|
||||
property bool isInitialising: true
|
||||
|
||||
visible: root.showChildType
|
||||
|
||||
text: i18n("Select type")
|
||||
model: ListModel {
|
||||
id: roomTypeModel
|
||||
}
|
||||
textRole: "text"
|
||||
valueRole: "isSpace"
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = indexOfValue(root.isSpace)
|
||||
roomTypeModel.append({"text": i18n("Room"), "isSpace": false});
|
||||
roomTypeModel.append({"text": i18n("Space"), "isSpace": true});
|
||||
roomTypeCombo.currentIndex = 0
|
||||
roomTypeCombo.isInitialising = false
|
||||
}
|
||||
onCurrentValueChanged: {
|
||||
if (!isInitialising) {
|
||||
root.isSpace = currentValue
|
||||
}
|
||||
}
|
||||
}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: roomNameField
|
||||
label: i18n("Room name:")
|
||||
label: i18n("Name:")
|
||||
onAccepted: if (roomNameField.text.length > 0) roomTopicField.forceActiveFocus();
|
||||
}
|
||||
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: roomTopicField
|
||||
label: i18n("Room topic:")
|
||||
label: i18n("Topic:")
|
||||
onAccepted: ok.clicked()
|
||||
}
|
||||
|
||||
FormCard.FormCheckDelegate {
|
||||
id: newOfficialCheck
|
||||
visible: root.parentId.length > 0
|
||||
text: i18n("Make this parent official")
|
||||
checked: true
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
id: ok
|
||||
text: i18nc("@action:button", "Ok")
|
||||
enabled: roomNameField.text.length > 0
|
||||
onClicked: {
|
||||
root.connection.createRoom(roomNameField.text, roomTopicField.text);
|
||||
if (root.isSpace) {
|
||||
root.connection.createSpace(roomNameField.text, roomTopicField.text, root.parentId, newOfficialCheck.checked);
|
||||
} else {
|
||||
root.connection.createRoom(roomNameField.text, roomTopicField.text, root.parentId, newOfficialCheck.checked);
|
||||
}
|
||||
root.newChild(roomNameField.text)
|
||||
root.closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
FormCard.FormHeader {
|
||||
visible: root.showChildType
|
||||
title: i18n("Select Exisiting Room")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
visible: root.showChildType
|
||||
FormCard.FormButtonDelegate {
|
||||
visible: !chosenRoomDelegate.visible
|
||||
text: i18nc("@action:button", "Pick room")
|
||||
onClicked: {
|
||||
let dialog = pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/JoinRoomPage.qml", {connection: root.connection}, {title: i18nc("@title", "Explore Rooms")})
|
||||
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
|
||||
chosenRoomDelegate.roomId = roomId;
|
||||
chosenRoomDelegate.displayName = displayName;
|
||||
chosenRoomDelegate.avatarUrl = avatarUrl;
|
||||
chosenRoomDelegate.alias = alias;
|
||||
chosenRoomDelegate.topic = topic;
|
||||
chosenRoomDelegate.memberCount = memberCount;
|
||||
chosenRoomDelegate.isJoined = isJoined;
|
||||
chosenRoomDelegate.visible = true;
|
||||
})
|
||||
}
|
||||
}
|
||||
FormCard.AbstractFormDelegate {
|
||||
id: chosenRoomDelegate
|
||||
property string roomId
|
||||
property string displayName
|
||||
property url avatarUrl
|
||||
property string alias
|
||||
property string topic
|
||||
property int memberCount
|
||||
property bool isJoined
|
||||
|
||||
visible: false
|
||||
|
||||
contentItem: RowLayout {
|
||||
Components.Avatar {
|
||||
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
||||
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
||||
|
||||
source: chosenRoomDelegate.avatarUrl
|
||||
name: chosenRoomDelegate.displayName
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
level: 4
|
||||
text: chosenRoomDelegate.displayName
|
||||
font.bold: true
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
QQC2.Label {
|
||||
visible: chosenRoomDelegate.isJoined
|
||||
text: i18n("Joined")
|
||||
color: Kirigami.Theme.linkColor
|
||||
}
|
||||
}
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
visible: text
|
||||
text: chosenRoomDelegate.topic ? chosenRoomDelegate.topic.replace(/(\r\n\t|\n|\r\t)/gm," ") : ""
|
||||
textFormat: Text.PlainText
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Kirigami.Icon {
|
||||
source: "user"
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
implicitHeight: Kirigami.Units.iconSizes.small
|
||||
implicitWidth: Kirigami.Units.iconSizes.small
|
||||
}
|
||||
QQC2.Label {
|
||||
text: chosenRoomDelegate.memberCount + " " + (chosenRoomDelegate.alias ?? chosenRoomDelegate.roomId)
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
let dialog = pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/JoinRoomPage.qml", {connection: root.connection}, {title: i18nc("@title", "Explore Rooms")})
|
||||
dialog.roomSelected.connect((roomId, displayName, avatarUrl, alias, topic, memberCount, isJoined) => {
|
||||
chosenRoomDelegate.roomId = roomId;
|
||||
chosenRoomDelegate.displayName = displayName;
|
||||
chosenRoomDelegate.avatarUrl = avatarUrl;
|
||||
chosenRoomDelegate.alias = alias;
|
||||
chosenRoomDelegate.topic = topic;
|
||||
chosenRoomDelegate.memberCount = memberCount;
|
||||
chosenRoomDelegate.isJoined = isJoined;
|
||||
chosenRoomDelegate.visible = true;
|
||||
})
|
||||
}
|
||||
}
|
||||
FormCard.FormCheckDelegate {
|
||||
id: exisitingOfficialCheck
|
||||
visible: root.parentId.length > 0
|
||||
text: i18n("Make this parent official")
|
||||
description: enabled ? i18n("You have the required privilege level in the child to set this state") : i18n("You do not have a high enough privilege level in the child to set this state")
|
||||
checked: enabled
|
||||
|
||||
enabled: {
|
||||
if (chosenRoomDelegate.visible) {
|
||||
let room = root.connection.room(chosenRoomDelegate.roomId);
|
||||
if (room) {
|
||||
if (room.canSendState("m.space.parent")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18nc("@action:button", "Ok")
|
||||
enabled: chosenRoomDelegate.visible
|
||||
onClicked: {
|
||||
root.addChild(chosenRoomDelegate.roomId, exisitingOfficialCheck.checked);
|
||||
root.closeDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
import org.kde.neochat
|
||||
import org.kde.kirigamiaddons.formcard as FormCard
|
||||
|
||||
FormCard.FormCardPage {
|
||||
id: root
|
||||
|
||||
required property NeoChatConnection connection
|
||||
|
||||
title: i18n("Create a Space")
|
||||
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18nc("@title", "Create a Space")
|
||||
}
|
||||
FormCard.FormCard {
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: nameDelegate
|
||||
label: i18n("Space name")
|
||||
}
|
||||
FormCard.FormTextFieldDelegate {
|
||||
id: topicDelegate
|
||||
label: i18n("Space topic (optional)")
|
||||
}
|
||||
FormCard.FormButtonDelegate {
|
||||
text: i18n("Create space")
|
||||
onClicked: {
|
||||
root.connection.createSpace(nameDelegate.text, topicDelegate.text)
|
||||
root.close()
|
||||
root.destroy()
|
||||
}
|
||||
enabled: nameDelegate.text.length > 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ RowLayout {
|
||||
text: i18n("Create a Space")
|
||||
icon.name: "list-add"
|
||||
onTriggered: {
|
||||
pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/CreateSpaceDialog.qml", {connection: root.connection}, {title: i18nc("@title", "Create a Space")})
|
||||
pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/CreateRoomDialog.qml", {connection: root.connection, isSpace: true, title: i18nc("@title", "Create a Space")}, {title: i18nc("@title", "Create a Space")})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,10 @@ import org.kde.neochat
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
/**
|
||||
* @brief The current room that user is viewing.
|
||||
*/
|
||||
required property NeoChatRoom room
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -26,8 +30,8 @@ ColumnLayout {
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.large
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.large
|
||||
|
||||
name: room ? room.displayName : ""
|
||||
source: room && room.avatarMediaId ? ("image://mxc/" + room.avatarMediaId) : ""
|
||||
name: root.room ? root.room.displayName : ""
|
||||
source: root.room && root.room.avatarMediaId ? ("image://mxc/" + root.room.avatarMediaId) : ""
|
||||
|
||||
Rectangle {
|
||||
visible: room.usesEncryption
|
||||
@@ -58,7 +62,7 @@ ColumnLayout {
|
||||
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
text: room ? room.displayName : i18n("No name")
|
||||
text: root.room ? root.room.displayName : i18n("No name")
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
@@ -67,8 +71,8 @@ ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
font: Kirigami.Theme.smallFont
|
||||
textFormat: TextEdit.PlainText
|
||||
visible: room && room.canonicalAlias
|
||||
text: room && room.canonicalAlias ? room.canonicalAlias : ""
|
||||
visible: root.room && root.room.canonicalAlias
|
||||
text: root.room && root.room.canonicalAlias ? root.room.canonicalAlias : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +82,7 @@ ColumnLayout {
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
|
||||
text: room && room.topic ? room.topic.replace(replaceLinks, "<a href=\"$1\">$1</a>") : i18n("No Topic")
|
||||
text: root.room && root.room.topic ? root.room.topic.replace(replaceLinks, "<a href=\"$1\">$1</a>") : i18n("No Topic")
|
||||
readonly property var replaceLinks: /(http[s]?:\/\/[^ \r\n]*)/g
|
||||
textFormat: TextEdit.MarkdownText
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
@@ -136,6 +136,7 @@ Kirigami.OverlayDrawer {
|
||||
Kirigami.NavigationTabBar {
|
||||
id: navigationBar
|
||||
Layout.fillWidth: true
|
||||
visible: !root.room.isSpace
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ Kirigami.Page {
|
||||
|
||||
footer: Kirigami.NavigationTabBar {
|
||||
id: navigationBar
|
||||
visible: !root.room.isSpace
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.Window
|
||||
Kirigami.Theme.inherit: false
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ QQC2.ScrollView {
|
||||
/**
|
||||
* @brief The title that should be displayed for this component if available.
|
||||
*/
|
||||
readonly property string title: i18nc("@action:title", "Room information")
|
||||
readonly property string title: root.room.isSpace ? i18nc("@action:title", "Space Members") : i18nc("@action:title", "Room information")
|
||||
|
||||
// HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890)
|
||||
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
|
||||
@@ -57,6 +57,7 @@ QQC2.ScrollView {
|
||||
active: true
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
visible: !root.room.isSpace
|
||||
sourceComponent: root.room.isDirectChat() ? directChatDrawerHeader : groupChatDrawerHeader
|
||||
onItemChanged: if (item) {
|
||||
userList.positionViewAtBeginning();
|
||||
@@ -64,6 +65,7 @@ QQC2.ScrollView {
|
||||
}
|
||||
|
||||
Kirigami.ListSectionHeader {
|
||||
visible: !root.room.isSpace
|
||||
label: i18n("Options")
|
||||
activeFocusOnTab: false
|
||||
|
||||
@@ -75,7 +77,7 @@ QQC2.ScrollView {
|
||||
|
||||
icon.name: "tools"
|
||||
text: i18n("Open developer tools")
|
||||
visible: Config.developerTools
|
||||
visible: Config.developerTools && !root.room.isSpace
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -86,7 +88,7 @@ QQC2.ScrollView {
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: searchButton
|
||||
|
||||
visible: !root.room.isSpace
|
||||
icon.name: "search"
|
||||
text: i18n("Search in this room")
|
||||
|
||||
@@ -104,7 +106,7 @@ QQC2.ScrollView {
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: favouriteButton
|
||||
|
||||
visible: !root.room.isSpace
|
||||
icon.name: root.room && root.room.isFavourite ? "rating" : "rating-unrated"
|
||||
text: root.room && root.room.isFavourite ? i18n("Remove room from favorites") : i18n("Make room favorite")
|
||||
|
||||
@@ -115,7 +117,7 @@ QQC2.ScrollView {
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: locationsButton
|
||||
|
||||
visible: !root.room.isSpace
|
||||
icon.name: "map-flat"
|
||||
text: i18n("Show locations for this room")
|
||||
|
||||
@@ -240,7 +242,9 @@ QQC2.ScrollView {
|
||||
|
||||
Component {
|
||||
id: groupChatDrawerHeader
|
||||
GroupChatDrawerHeader {}
|
||||
GroupChatDrawerHeader {
|
||||
room: root.room
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
|
||||
131
src/qml/SpaceHierarchyDelegate.qml
Normal file
131
src/qml/SpaceHierarchyDelegate.qml
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates as Delegates
|
||||
import org.kde.kirigamiaddons.labs.components as Components
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Item {
|
||||
id: root
|
||||
required property TreeView treeView
|
||||
required property bool isTreeNode
|
||||
required property bool expanded
|
||||
required property int hasChildren
|
||||
required property int depth
|
||||
required property string roomId
|
||||
required property string displayName
|
||||
required property url avatarUrl
|
||||
required property bool isSpace
|
||||
required property int memberCount
|
||||
required property string topic
|
||||
required property bool isJoined
|
||||
required property bool canAddChildren
|
||||
|
||||
signal createRoom()
|
||||
signal enterRoom()
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
anchors.centerIn: root
|
||||
width: sizeHelper.currentWidth
|
||||
|
||||
contentItem: RowLayout {
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
RowLayout {
|
||||
spacing: 0
|
||||
Item {
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium * (root.depth + (root.isSpace ? 0 : 1))
|
||||
}
|
||||
Kirigami.Icon {
|
||||
visible: root.isSpace
|
||||
implicitWidth: Kirigami.Units.iconSizes.smallMedium
|
||||
implicitHeight: Kirigami.Units.iconSizes.smallMedium
|
||||
source: root.hasChildren ? (root.expanded ? "go-up" : "go-down") : "go-next"
|
||||
}
|
||||
}
|
||||
Components.Avatar {
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: height
|
||||
implicitWidth: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
|
||||
implicitHeight: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing * 2
|
||||
source: root.avatarUrl
|
||||
name: root.displayName
|
||||
}
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
QQC2.Label {
|
||||
id: label
|
||||
text: root.displayName
|
||||
elide: Text.ElideRight
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
QQC2.Label {
|
||||
visible: root.isJoined
|
||||
text: i18n("Joined")
|
||||
color: Kirigami.Theme.linkColor
|
||||
}
|
||||
}
|
||||
QQC2.Label {
|
||||
id: subtitle
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
|
||||
text: root.memberCount + (root.topic !== "" ? i18nc("number of room members", " members - ") + root.topic : i18nc("number of room members", " members"))
|
||||
elide: Text.ElideRight
|
||||
font: Kirigami.Theme.smallFont
|
||||
textFormat: Text.PlainText
|
||||
maximumLineCount: 1
|
||||
}
|
||||
}
|
||||
QQC2.ToolButton {
|
||||
visible: root.isSpace && root.canAddChildren
|
||||
text: i18nc("@button", "Add new child")
|
||||
icon.name: "list-add"
|
||||
onClicked: root.createRoom()
|
||||
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
TapHandler {
|
||||
onTapped: {
|
||||
if (root.isSpace) {
|
||||
root.treeView.toggleExpanded(row)
|
||||
} else {
|
||||
if (root.isJoined) {
|
||||
root.enterRoom()
|
||||
} else {
|
||||
Controller.joinRoom(root.roomId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DelegateSizeHelper {
|
||||
id: sizeHelper
|
||||
startBreakpoint: Kirigami.Units.gridUnit * 46
|
||||
endBreakpoint: Kirigami.Units.gridUnit * 66
|
||||
startPercentWidth: 100
|
||||
endPercentWidth: 85
|
||||
maxWidth: Kirigami.Units.gridUnit * 60
|
||||
|
||||
parentWidth: root.treeView ? root.treeView.width : 0
|
||||
}
|
||||
}
|
||||
178
src/qml/SpaceHomePage.qml
Normal file
178
src/qml/SpaceHomePage.qml
Normal file
@@ -0,0 +1,178 @@
|
||||
// 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
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Controls as QQC2
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
Kirigami.Page {
|
||||
id: root
|
||||
|
||||
readonly property NeoChatRoom currentRoom: RoomManager.currentRoom
|
||||
|
||||
padding: 0
|
||||
|
||||
ColumnLayout {
|
||||
id: columnLayout
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
id: headerItem
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
implicitHeight: headerColumn.implicitHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: headerColumn
|
||||
anchors.centerIn: headerItem
|
||||
width: sizeHelper.currentWidth
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
GroupChatDrawerHeader {
|
||||
id: header
|
||||
Layout.fillWidth: true
|
||||
room: root.currentRoom
|
||||
}
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
QQC2.Button {
|
||||
visible: root.currentRoom.canSendState("invite")
|
||||
text: i18nc("@button", "Invite user to space")
|
||||
icon.name: "list-add-user"
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/InviteUserPage.qml", {room: root.currentRoom}, {title: i18nc("@title", "Invite a User")})
|
||||
}
|
||||
QQC2.Button {
|
||||
visible: root.currentRoom.canSendState("m.space.child")
|
||||
text: i18nc("@button", "Add new child")
|
||||
icon.name: "list-add"
|
||||
onClicked: _private.createRoom(root.currentRoom.id)
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@button", "Leave the space")
|
||||
icon.name: "go-previous"
|
||||
onClicked: RoomManager.leaveRoom(root.currentRoom)
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
QQC2.Button {
|
||||
text: i18nc("@button", "Space settings")
|
||||
icon.name: "settings-configure"
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
onClicked: applicationWindow().pageStack.pushDialogLayer('qrc:/org/kde/neochat/qml/Categories.qml', {room: root.currentRoom, connection: root.currentRoom.connection}, { title: i18n("Room Settings") })
|
||||
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
QQC2.ToolTip.visible: hovered
|
||||
}
|
||||
}
|
||||
Kirigami.SearchField {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||
onTextChanged: spaceChildSortFilterModel.filterText = text
|
||||
}
|
||||
}
|
||||
DelegateSizeHelper {
|
||||
id: sizeHelper
|
||||
startBreakpoint: Kirigami.Units.gridUnit * 46
|
||||
endBreakpoint: Kirigami.Units.gridUnit * 66
|
||||
startPercentWidth: 100
|
||||
endPercentWidth: 85
|
||||
maxWidth: Kirigami.Units.gridUnit * 60
|
||||
|
||||
parentWidth: columnLayout.width
|
||||
}
|
||||
}
|
||||
Kirigami.Separator {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
QQC2.ScrollView {
|
||||
id: hierarchyScrollView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
visible: !spaceChildrenModel.loading
|
||||
|
||||
TreeView {
|
||||
id: spaceTree
|
||||
columnWidthProvider: function (column) { return spaceTree.width }
|
||||
|
||||
clip: true
|
||||
|
||||
model: SpaceChildSortFilterModel {
|
||||
id: spaceChildSortFilterModel
|
||||
sourceModel: SpaceChildrenModel {
|
||||
id: spaceChildrenModel
|
||||
space: root.currentRoom
|
||||
}
|
||||
}
|
||||
|
||||
delegate: SpaceHierarchyDelegate {
|
||||
onCreateRoom: _private.createRoom(roomId)
|
||||
onEnterRoom: _private.enterRoom(roomId)
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
visible: spaceChildrenModel.loading
|
||||
|
||||
Loader {
|
||||
active: spaceChildrenModel.loading
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: Kirigami.LoadingPlaceholder {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
Kirigami.Theme.inherit: false
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: _private
|
||||
function createRoom(parentId) {
|
||||
let dialog = applicationWindow().pageStack.pushDialogLayer("qrc:/org/kde/neochat/qml/CreateRoomDialog.qml", {
|
||||
title: i18nc("@title", "Create a Child"),
|
||||
connection: root.currentRoom.connection,
|
||||
parentId : parentId,
|
||||
showChildType: true,
|
||||
showCreateChoice: true
|
||||
}, {
|
||||
title: i18nc("@title", "Create a Child")
|
||||
})
|
||||
dialog.addChild.connect((childId, setChildParent) => {
|
||||
// We have to get a room object from the connection as we may not
|
||||
// be adding to the top level parent.
|
||||
let parent = root.currentRoom.connection.room(parentId)
|
||||
if (parent) {
|
||||
parent.addChild(childId, setChildParent)
|
||||
}
|
||||
})
|
||||
dialog.newChild.connect(childName => {spaceChildrenModel.addPendingChild(childName)})
|
||||
}
|
||||
|
||||
function enterRoom(roomId) {
|
||||
let room = root.currentRoom.connection.room(roomId)
|
||||
if (room) {
|
||||
RoomManager.enterRoom(room)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ Loader {
|
||||
QQC2.MenuItem {
|
||||
text: i18nc("'Space' is a matrix space", "View Space")
|
||||
icon.name: "view-list-details"
|
||||
onTriggered: RoomManager.enterRoom(room);
|
||||
onTriggered: RoomManager.enterSpaceHome(room);
|
||||
}
|
||||
|
||||
QQC2.MenuItem {
|
||||
|
||||
@@ -21,6 +21,7 @@ Kirigami.ApplicationWindow {
|
||||
property bool roomListLoaded: false
|
||||
|
||||
property RoomPage roomPage
|
||||
property SpaceHomePage spaceHomePage
|
||||
|
||||
property NeoChatConnection connection: Controller.activeConnection
|
||||
|
||||
@@ -96,15 +97,36 @@ Kirigami.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
function onPushSpaceHome(room) {
|
||||
root.spaceHomePage = pageStack.push("qrc:/org/kde/neochat/qml/SpaceHomePage.qml");
|
||||
root.spaceHomePage.forceActiveFocus();
|
||||
}
|
||||
|
||||
function onReplaceRoom(room, event) {
|
||||
const roomItem = pageStack.get(pageStack.depth - 1);
|
||||
pageStack.currentIndex = pageStack.depth - 1;
|
||||
if (root.roomPage) {
|
||||
pageStack.currentIndex = pageStack.depth - 1;
|
||||
} else {
|
||||
pageStack.pop();
|
||||
root.roomPage = pageStack.push("qrc:/org/kde/neochat/qml/RoomPage.qml", {connection: root.connection});
|
||||
root.spaceHomePage = null;
|
||||
}
|
||||
root.roomPage.forceActiveFocus();
|
||||
if (event.length > 0) {
|
||||
roomItem.goToEvent(event);
|
||||
root.roomPage.goToEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
function onReplaceSpaceHome(room) {
|
||||
if (root.spaceHomePage) {
|
||||
pageStack.currentIndex = pageStack.depth - 1;
|
||||
} else {
|
||||
pageStack.pop();
|
||||
root.spaceHomePage = pageStack.push("qrc:/org/kde/neochat/qml/SpaceHomePage.qml");
|
||||
root.roomPage = null;
|
||||
}
|
||||
root.spaceHomePage.forceActiveFocus();
|
||||
}
|
||||
|
||||
function goToEvent(event) {
|
||||
if (event.length > 0) {
|
||||
roomItem.goToEvent(event);
|
||||
@@ -335,13 +357,6 @@ Kirigami.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: createSpaceDialog
|
||||
CreateSpaceDialog {
|
||||
connection: root.connection
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: roomWindow
|
||||
RoomWindow {}
|
||||
|
||||
Reference in New Issue
Block a user