Create a new module for the room info drawer QML. This also requires moving some QML to LibNeoChat common with other modules. Finally all QML in roominfo is modifed to not depend on app.
303 lines
9.9 KiB
QML
303 lines
9.9 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.libneochat
|
|
|
|
/**
|
|
* @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 UserListModel userListModel
|
|
|
|
/**
|
|
* @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")
|
|
|
|
signal resolveResource(string idOrUri, string action)
|
|
|
|
// 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()
|
|
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: pinnedMessagesButton
|
|
visible: !root.room.isSpace
|
|
icon.name: "pin-symbolic"
|
|
text: i18nc("@action:button", "Pinned messages")
|
|
activeFocusOnTab: true
|
|
|
|
Layout.fillWidth: true
|
|
|
|
onClicked: {
|
|
pageStack.pushDialogLayer(Qt.createComponent('org.kde.neochat', 'RoomPinnedMessagesPage'), {
|
|
room: root.room
|
|
}, {
|
|
title: i18nc("@title", "Pinned Messages")
|
|
});
|
|
}
|
|
}
|
|
|
|
Delegates.RoundedItemDelegate {
|
|
id: leaveButton
|
|
icon.name: "arrow-left-symbolic"
|
|
text: root.room.isSpace ? i18nc("@action:button", "Leave this space") : 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: root.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 url 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: {
|
|
root.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
|
|
|
|
onResolveResource: (idOrUri, action) => root.resolveResource(idOrUri, action)
|
|
}
|
|
}
|
|
|
|
onRoomChanged: {
|
|
if (userList.headerItem) {
|
|
userList.headerItem.userListSearchField.text = "";
|
|
}
|
|
userList.currentIndex = -1;
|
|
}
|
|
}
|