Files
neochat/src/qml/RoomInformation.qml
2024-09-21 12:11:14 +00:00

281 lines
9.1 KiB
QML

// 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 ComponentBehavior: Bound
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 KirigamiComponents
import org.kde.kitemmodels
import org.kde.neochat
/**
* @brief Component for visualising the room information.
*
* The component has a header section which changes between group rooms and direct
* chats with information like the avatar and topic. Followed by the allowed actions
* and finally a user list.
*
* @note This component is only the contents, it will need to be placed in either
* a drawer (desktop) or page (mobile) to be used.
*
* @sa RoomDrawer, RoomDrawerPage
*/
QQC2.ScrollView {
id: root
/**
* @brief The current room that user is viewing.
*/
required property NeoChatRoom room
required property NeoChatConnection connection
/**
* @brief The title that should be displayed for this component if available.
*/
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
ListView {
id: userList
header: ColumnLayout {
id: columnLayout
property alias userListSearchField: userListSearchField
spacing: 0
width: ListView.view ? ListView.view.width - ListView.view.leftMargin - ListView.view.rightMargin : 0
Loader {
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();
}
}
Kirigami.ListSectionHeader {
visible: !root.room.isSpace
label: i18nc("Room actions", "Actions")
activeFocusOnTab: false
Layout.fillWidth: true
}
Delegates.RoundedItemDelegate {
id: searchButton
visible: !root.room.isSpace
icon.name: "search"
text: i18n("Search in this room")
activeFocusOnTab: true
Layout.fillWidth: true
onClicked: {
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomSearchPage'), {
room: root.room
}, {
title: i18nc("@action:title", "Search")
});
}
}
Delegates.RoundedItemDelegate {
visible: root.room.isDirectChat() && Controller.csSupported
icon.name: "security-low-symbolic"
text: i18nc("@action:button", "Verify user")
onClicked: root.room.startVerification()
Layout.fillWidth: true
}
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("Favorite this room")
onClicked: root.room.isFavourite ? root.room.removeTag("m.favourite") : root.room.addTag("m.favourite", 1.0)
activeFocusOnTab: true
Layout.fillWidth: true
}
Delegates.RoundedItemDelegate {
id: locationsButton
visible: !root.room.isSpace
icon.name: "map-flat"
text: i18n("Show locations for this room")
activeFocusOnTab: true
onClicked: pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'LocationsPage'), {
room: root.room
}, {
title: i18nc("Locations on a map", "Locations")
})
Layout.fillWidth: true
}
Delegates.RoundedItemDelegate {
id: leaveButton
icon.name: "arrow-left-symbolic"
text: i18nc("@action:button", "Leave this room")
activeFocusOnTab: true
Layout.fillWidth: true
onClicked: {
Qt.createComponent('org.kde.neochat', 'ConfirmLeaveDialog').createObject(root.QQC2.ApplicationWindow.window, {
room: root.room
}).open();
}
}
Kirigami.ListSectionHeader {
label: i18n("Members")
activeFocusOnTab: false
spacing: 0
visible: !root.room.isDirectChat()
Layout.fillWidth: true
QQC2.ToolButton {
visible: root.room.canSendState("invite")
icon.name: "list-add-user"
onClicked: {
applicationWindow().pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'InviteUserPage'), {
room: root.room
}, {
title: i18nc("@title", "Invite a User")
});
}
QQC2.ToolTip.text: i18n("Invite user to room")
QQC2.ToolTip.visible: hovered
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
}
QQC2.Label {
Layout.alignment: Qt.AlignRight
text: root.room ? i18np("%1 member", "%1 members", root.room.joinedCount) : i18n("No member count")
}
}
Kirigami.SearchField {
id: userListSearchField
visible: !root.room.isDirectChat()
onVisibleChanged: if (visible) {
forceActiveFocus();
}
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
Layout.bottomMargin: Kirigami.Units.smallSpacing
focusSequence: "Ctrl+Shift+F"
onAccepted: userFilterModel.filterText = text
}
}
model: root.room.isDirectChat() ? 0 : userFilterModel
UserFilterModel {
id: userFilterModel
sourceModel: RoomManager.userListModel
allowEmpty: true
}
clip: true
focus: true
section.property: "powerLevelString"
section.delegate: Kirigami.ListSectionHeader {
required property string section
width: ListView.view.width
text: section
}
delegate: Delegates.RoundedItemDelegate {
id: userDelegate
required property int index
required property string name
required property string userId
required property string avatar
required property int powerLevel
required property string powerLevelString
implicitHeight: Kirigami.Units.gridUnit * 2
text: name
KeyNavigation.tab: navigationBar.tabGroup.checkedButton
KeyNavigation.backtab: index === 0 ? userList.headerItem.userListSearchField : null
onClicked: {
RoomManager.resolveResource(userDelegate.userId, "mention");
}
contentItem: RowLayout {
KirigamiComponents.Avatar {
implicitWidth: height
sourceSize {
height: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5
width: Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing * 2.5
}
source: userDelegate.avatar
name: userDelegate.userId
Layout.fillHeight: true
}
QQC2.Label {
text: userDelegate.name
textFormat: Text.PlainText
elide: Text.ElideRight
Layout.fillWidth: true
}
}
}
}
Component {
id: groupChatDrawerHeader
GroupChatDrawerHeader {
room: root.room
}
}
Component {
id: directChatDrawerHeader
DirectChatDrawerHeader {
room: root.room
}
}
onRoomChanged: {
if (userList.headerItem) {
userList.headerItem.userListSearchField.text = "";
}
userList.currentIndex = -1;
}
}