Room Drawer Mobile
Push the room drawer as a page rather than a drawer when on mobile or the window is thin. This also lays some foundations for having multiple different pages in the drawer by separating the room information into it's own component which could be switched out to show other things like highlights or media.
This commit is contained in:
@@ -27,6 +27,14 @@ Kirigami.Page {
|
||||
focus: true
|
||||
padding: 0
|
||||
|
||||
actions {
|
||||
main: Kirigami.Action {
|
||||
visible: Kirigami.Settings.isMobile || !applicationWindow().pageStack.wideMode
|
||||
icon.name: "view-right-new"
|
||||
onTriggered: applicationWindow().openRoomDrawer()
|
||||
}
|
||||
}
|
||||
|
||||
KeyNavigation.left: pageStack.get(0)
|
||||
|
||||
onCurrentRoomChanged: {
|
||||
|
||||
@@ -1,367 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
|
||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates 1.0 as Delegates
|
||||
import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
|
||||
import org.kde.kitemmodels 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.OverlayDrawer {
|
||||
id: roomDrawer
|
||||
readonly property NeoChatRoom room: RoomManager.currentRoom
|
||||
|
||||
width: actualWidth
|
||||
|
||||
readonly property int minWidth: Kirigami.Units.gridUnit * 15
|
||||
readonly property int maxWidth: Kirigami.Units.gridUnit * 25
|
||||
readonly property int defaultWidth: Kirigami.Units.gridUnit * 20
|
||||
property int actualWidth: {
|
||||
if (Config.roomDrawerWidth === -1) {
|
||||
return Kirigami.Units.gridUnit * 20;
|
||||
} else {
|
||||
return Config.roomDrawerWidth
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: undefined
|
||||
width: 2
|
||||
z: 500
|
||||
cursorShape: !Kirigami.Settings.isMobile ? Qt.SplitHCursor : undefined
|
||||
enabled: true
|
||||
visible: true
|
||||
onPressed: _lastX = mapToGlobal(mouseX, mouseY).x
|
||||
onReleased: {
|
||||
Config.roomDrawerWidth = roomDrawer.actualWidth;
|
||||
Config.save();
|
||||
}
|
||||
property real _lastX: -1
|
||||
|
||||
onPositionChanged: {
|
||||
if (_lastX === -1) {
|
||||
return;
|
||||
}
|
||||
if (Qt.application.layoutDirection === Qt.RightToLeft) {
|
||||
roomDrawer.actualWidth = Math.min(roomDrawer.maxWidth, Math.max(roomDrawer.minWidth, Config.roomDrawerWidth - _lastX + mapToGlobal(mouseX, mouseY).x))
|
||||
} else {
|
||||
roomDrawer.actualWidth = Math.min(roomDrawer.maxWidth, Math.max(roomDrawer.minWidth, Config.roomDrawerWidth + _lastX - mapToGlobal(mouseX, mouseY).x))
|
||||
}
|
||||
}
|
||||
}
|
||||
enabled: true
|
||||
|
||||
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
|
||||
|
||||
// If modal has been changed and the drawer is closed automatically then dim on popup open will have been switched off in main.qml so switch it back on after the animation completes.
|
||||
// This is to avoid dim being active for a split second when the drawer is switched to modal which looks terrible.
|
||||
onAnimatingChanged: if (dim === false) dim = undefined
|
||||
|
||||
topPadding: 0
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
contentItem: Loader {
|
||||
id: loader
|
||||
active: roomDrawer.drawerOpen
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
readonly property string userSearchText: userListView.headerItem ? userListView.headerItem.userListSearchField.text : ''
|
||||
property alias highlightedUser: userListView.currentIndex
|
||||
|
||||
spacing: 0
|
||||
|
||||
function clearSearch() {
|
||||
userListView.headerItem.userListSearchField.text = ""
|
||||
}
|
||||
|
||||
QQC2.ToolBar {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Layout.preferredHeight: pageStack.globalToolBar.preferredHeight
|
||||
|
||||
contentItem: RowLayout {
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
text: i18n("Room information")
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: settingsButton
|
||||
|
||||
icon.name: "settings-configure"
|
||||
text: i18n("Room settings")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
onClicked: QQC2.ApplicationWindow.window.pageStack.pushDialogLayer('qrc:/Categories.qml', {room: room}, { title: i18n("Room Settings") })
|
||||
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
QQC2.ToolTip.visible: hovered
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
// HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890)
|
||||
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
|
||||
|
||||
ListView {
|
||||
id: userListView
|
||||
|
||||
header: ColumnLayout {
|
||||
id: columnLayout
|
||||
|
||||
property alias userListSearchField: userListSearchField
|
||||
|
||||
spacing: 0
|
||||
width: userListView.width
|
||||
|
||||
Loader {
|
||||
active: true
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
sourceComponent: room.isDirectChat() ? directChatDrawerHeader : groupChatDrawerHeader
|
||||
onItemChanged: if (item) {
|
||||
userListView.positionViewAtBeginning();
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.ListSectionHeader {
|
||||
label: i18n("Options")
|
||||
activeFocusOnTab: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: devtoolsButton
|
||||
|
||||
icon.name: "tools"
|
||||
text: i18n("Open developer tools")
|
||||
visible: Config.developerTools
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
applicationWindow().pageStack.pushDialogLayer("qrc:/DevtoolsPage.qml", {room: room}, {title: i18n("Developer Tools")})
|
||||
}
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: searchButton
|
||||
|
||||
icon.name: "search"
|
||||
text: i18n("Search in this room")
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
pageStack.pushDialogLayer("qrc:/SearchPage.qml", {
|
||||
currentRoom: room
|
||||
}, {
|
||||
title: i18nc("@action:title", "Search")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: favouriteButton
|
||||
|
||||
icon.name: room && room.isFavourite ? "rating" : "rating-unrated"
|
||||
text: room && room.isFavourite ? i18n("Remove room from favorites") : i18n("Make room favorite")
|
||||
|
||||
onClicked: room.isFavourite ? room.removeTag("m.favourite") : room.addTag("m.favourite", 1.0)
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: locationsButton
|
||||
|
||||
icon.name: "map-flat"
|
||||
text: i18n("Show locations for this room")
|
||||
|
||||
onClicked: pageStack.pushDialogLayer("qrc:/LocationsPage.qml", {
|
||||
room: room
|
||||
}, {
|
||||
title: i18nc("Locations on a map", "Locations")
|
||||
})
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Kirigami.ListSectionHeader {
|
||||
label: i18n("Members")
|
||||
activeFocusOnTab: false
|
||||
spacing: 0
|
||||
visible: !room.isDirectChat()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: memberSearchToggle
|
||||
checkable: true
|
||||
icon.name: "search"
|
||||
QQC2.ToolTip.text: i18n("Search user in room")
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
onToggled: {
|
||||
userListSearchField.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
visible: roomDrawer.room.canSendState("invite")
|
||||
icon.name: "list-add-user"
|
||||
|
||||
onClicked: {
|
||||
applicationWindow().pageStack.pushDialogLayer("qrc:/InviteUserPage.qml", {room: roomDrawer.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: room ? i18np("%1 member", "%1 members", room.joinedCount) : i18n("No member count")
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.SearchField {
|
||||
id: userListSearchField
|
||||
visible: memberSearchToggle.checked
|
||||
|
||||
onVisibleChanged: if (visible) forceActiveFocus()
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing - 1
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing - 1
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
focusSequence: "Ctrl+Shift+F"
|
||||
|
||||
onAccepted: sortedMessageEventModel.filterString = text;
|
||||
}
|
||||
}
|
||||
|
||||
KSortFilterProxyModel {
|
||||
id: sortedMessageEventModel
|
||||
|
||||
sourceModel: UserListModel {
|
||||
room: roomDrawer.room
|
||||
}
|
||||
|
||||
sortRole: "powerLevel"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
filterRole: "name"
|
||||
filterCaseSensitivity: Qt.CaseInsensitive
|
||||
}
|
||||
|
||||
model: room.isDirectChat() ? 0 : sortedMessageEventModel
|
||||
|
||||
clip: true
|
||||
activeFocusOnTab: true
|
||||
|
||||
delegate: Delegates.RoundedItemDelegate {
|
||||
id: userDelegate
|
||||
|
||||
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
|
||||
|
||||
onClicked: {
|
||||
userDelegate.highlighted = true;
|
||||
const popup = userDetailDialog.createObject(QQC2.ApplicationWindow.overlay, {
|
||||
room: room,
|
||||
user: room.getUser(userDelegate.userId)
|
||||
});
|
||||
popup.closed.connect(() => {
|
||||
userDelegate.highlighted = false;
|
||||
});
|
||||
if (roomDrawer.modal) {
|
||||
roomDrawer.close();
|
||||
}
|
||||
popup.open();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
visible: userDelegate.powerLevel > 0
|
||||
|
||||
text: userDelegate.powerLevelString
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onRoomChanged: {
|
||||
if (loader.active) {
|
||||
loader.item.clearSearch()
|
||||
loader.item.highlightedUser = -1
|
||||
}
|
||||
if (room == null) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: userDetailDialog
|
||||
|
||||
UserDetailDialog {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: groupChatDrawerHeader
|
||||
GroupChatDrawerHeader {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: directChatDrawerHeader
|
||||
DirectChatDrawerHeader {}
|
||||
}
|
||||
}
|
||||
121
src/qml/RoomDrawer/RoomDrawer.qml
Normal file
121
src/qml/RoomDrawer/RoomDrawer.qml
Normal file
@@ -0,0 +1,121 @@
|
||||
// SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
|
||||
// SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates 1.0 as Delegates
|
||||
import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
|
||||
import org.kde.kitemmodels 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
Kirigami.OverlayDrawer {
|
||||
id: root
|
||||
readonly property NeoChatRoom room: RoomManager.currentRoom
|
||||
|
||||
width: actualWidth
|
||||
|
||||
readonly property int minWidth: Kirigami.Units.gridUnit * 15
|
||||
readonly property int maxWidth: Kirigami.Units.gridUnit * 25
|
||||
readonly property int defaultWidth: Kirigami.Units.gridUnit * 20
|
||||
property int actualWidth: {
|
||||
if (Config.roomDrawerWidth === -1) {
|
||||
return Kirigami.Units.gridUnit * 20;
|
||||
} else {
|
||||
return Config.roomDrawerWidth
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: undefined
|
||||
width: 2
|
||||
z: 500
|
||||
cursorShape: !Kirigami.Settings.isMobile ? Qt.SplitHCursor : undefined
|
||||
enabled: true
|
||||
visible: true
|
||||
onPressed: _lastX = mapToGlobal(mouseX, mouseY).x
|
||||
onReleased: {
|
||||
Config.roomDrawerWidth = root.actualWidth;
|
||||
Config.save();
|
||||
}
|
||||
property real _lastX: -1
|
||||
|
||||
onPositionChanged: {
|
||||
if (_lastX === -1) {
|
||||
return;
|
||||
}
|
||||
if (Qt.application.layoutDirection === Qt.RightToLeft) {
|
||||
root.actualWidth = Math.min(root.maxWidth, Math.max(root.minWidth, Config.roomDrawerWidth - _lastX + mapToGlobal(mouseX, mouseY).x))
|
||||
} else {
|
||||
root.actualWidth = Math.min(root.maxWidth, Math.max(root.minWidth, Config.roomDrawerWidth + _lastX - mapToGlobal(mouseX, mouseY).x))
|
||||
}
|
||||
}
|
||||
}
|
||||
enabled: true
|
||||
|
||||
edge: Qt.application.layoutDirection == Qt.RightToLeft ? Qt.LeftEdge : Qt.RightEdge
|
||||
|
||||
// If modal has been changed and the drawer is closed automatically then dim on popup open will have been switched off in main.qml so switch it back on after the animation completes.
|
||||
// This is to avoid dim being active for a split second when the drawer is switched to modal which looks terrible.
|
||||
onAnimatingChanged: if (dim === false) dim = undefined
|
||||
|
||||
topPadding: 0
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
contentItem: Loader {
|
||||
id: loader
|
||||
active: root.drawerOpen
|
||||
|
||||
sourceComponent: ColumnLayout {
|
||||
spacing: 0
|
||||
|
||||
QQC2.ToolBar {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Layout.preferredHeight: pageStack.globalToolBar.preferredHeight
|
||||
|
||||
contentItem: RowLayout {
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
text: i18n("Room information")
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: settingsButton
|
||||
|
||||
icon.name: "settings-configure"
|
||||
text: i18n("Room settings")
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
|
||||
onClicked: QQC2.ApplicationWindow.window.pageStack.pushDialogLayer('qrc:/Categories.qml', {room: room}, { title: i18n("Room Settings") })
|
||||
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
QQC2.ToolTip.visible: hovered
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
// HACK: Hide unnecessary horizontal scrollbar (https://bugreports.qt.io/browse/QTBUG-83890)
|
||||
QQC2.ScrollBar.horizontal.policy: QQC2.ScrollBar.AlwaysOff
|
||||
|
||||
RoomInformation {
|
||||
id: roomInformation
|
||||
room: root.room
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/qml/RoomDrawer/RoomDrawerPage.qml
Normal file
60
src/qml/RoomDrawer/RoomDrawerPage.qml
Normal file
@@ -0,0 +1,60 @@
|
||||
// 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 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates 1.0 as Delegates
|
||||
import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
|
||||
import org.kde.kitemmodels 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
/**
|
||||
* @brief Page for holding a room drawer component.
|
||||
*
|
||||
* This the companion component to RoomDrawer and is designed to be used on mobile
|
||||
* where we want the room drawer to be pushed as a page as thin drawer doesn't
|
||||
* look good.
|
||||
*
|
||||
* @sa RoomDrawer
|
||||
*/
|
||||
Kirigami.ScrollablePage {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* @brief The current room that user is viewing.
|
||||
*/
|
||||
readonly property NeoChatRoom room: RoomManager.currentRoom
|
||||
|
||||
title: roomInformation.title
|
||||
|
||||
actions {
|
||||
main: Kirigami.Action {
|
||||
icon.name: "settings-configure"
|
||||
onTriggered: applicationWindow().pageStack.pushDialogLayer('qrc:/Categories.qml', {room: root.room}, { title: i18n("Room Settings") })
|
||||
}
|
||||
}
|
||||
|
||||
RoomInformation {
|
||||
id: roomInformation
|
||||
room: root.room
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: applicationWindow().pageStack
|
||||
onWideModeChanged: {
|
||||
if (applicationWindow().pageStack.wideMode) {
|
||||
console.log("widemode pop")
|
||||
applicationWindow().pageStack.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onBackRequested: event => {
|
||||
event.accepted = true;
|
||||
applicationWindow().pageStack.pop()
|
||||
}
|
||||
}
|
||||
272
src/qml/RoomDrawer/RoomInformation.qml
Normal file
272
src/qml/RoomDrawer/RoomInformation.qml
Normal file
@@ -0,0 +1,272 @@
|
||||
// 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 2.15
|
||||
import QtQuick.Controls 2.15 as QQC2
|
||||
import QtQuick.Layouts 1.15
|
||||
|
||||
import org.kde.kirigami 2.20 as Kirigami
|
||||
import org.kde.kirigamiaddons.delegates 1.0 as Delegates
|
||||
import org.kde.kirigamiaddons.labs.components 1.0 as KirigamiComponents
|
||||
import org.kde.kitemmodels 1.0
|
||||
|
||||
import org.kde.neochat 1.0
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
ListView {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* @brief The current room that user is viewing.
|
||||
*/
|
||||
required property NeoChatRoom room
|
||||
|
||||
/**
|
||||
* @brief The title that should be displayed for this component if available.
|
||||
*/
|
||||
readonly property string title: i18nc("@action:title", "Room information")
|
||||
|
||||
header: ColumnLayout {
|
||||
id: columnLayout
|
||||
|
||||
property alias userListSearchField: userListSearchField
|
||||
|
||||
spacing: 0
|
||||
width: root.width
|
||||
|
||||
Loader {
|
||||
active: true
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Kirigami.Units.smallSpacing
|
||||
sourceComponent: root.room.isDirectChat() ? directChatDrawerHeader : groupChatDrawerHeader
|
||||
onItemChanged: if (item) {
|
||||
root.positionViewAtBeginning();
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.ListSectionHeader {
|
||||
label: i18n("Options")
|
||||
activeFocusOnTab: false
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: devtoolsButton
|
||||
|
||||
icon.name: "tools"
|
||||
text: i18n("Open developer tools")
|
||||
visible: Config.developerTools
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
applicationWindow().pageStack.pushDialogLayer("qrc:/DevtoolsPage.qml", {room: root.room}, {title: i18n("Developer Tools")})
|
||||
}
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: searchButton
|
||||
|
||||
icon.name: "search"
|
||||
text: i18n("Search in this room")
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: {
|
||||
pageStack.pushDialogLayer("qrc:/SearchPage.qml", {
|
||||
currentRoom: root.room
|
||||
}, {
|
||||
title: i18nc("@action:title", "Search")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: favouriteButton
|
||||
|
||||
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")
|
||||
|
||||
onClicked: root.room.isFavourite ? root.room.removeTag("m.favourite") : root.room.addTag("m.favourite", 1.0)
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Delegates.RoundedItemDelegate {
|
||||
id: locationsButton
|
||||
|
||||
icon.name: "map-flat"
|
||||
text: i18n("Show locations for this room")
|
||||
|
||||
onClicked: pageStack.pushDialogLayer("qrc:/LocationsPage.qml", {
|
||||
room: root.room
|
||||
}, {
|
||||
title: i18nc("Locations on a map", "Locations")
|
||||
})
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Kirigami.ListSectionHeader {
|
||||
label: i18n("Members")
|
||||
activeFocusOnTab: false
|
||||
spacing: 0
|
||||
visible: !root.room.isDirectChat()
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
QQC2.ToolButton {
|
||||
id: memberSearchToggle
|
||||
checkable: true
|
||||
icon.name: "search"
|
||||
QQC2.ToolTip.text: i18n("Search user in room")
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
onToggled: {
|
||||
userListSearchField.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
visible: root.room.canSendState("invite")
|
||||
icon.name: "list-add-user"
|
||||
|
||||
onClicked: {
|
||||
applicationWindow().pageStack.pushDialogLayer("qrc:/InviteUserPage.qml", {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: memberSearchToggle.checked
|
||||
|
||||
onVisibleChanged: if (visible) forceActiveFocus()
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing - 1
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing - 1
|
||||
Layout.bottomMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
focusSequence: "Ctrl+Shift+F"
|
||||
|
||||
onAccepted: sortedMessageEventModel.filterString = text;
|
||||
}
|
||||
}
|
||||
|
||||
KSortFilterProxyModel {
|
||||
id: sortedMessageEventModel
|
||||
|
||||
sourceModel: UserListModel {
|
||||
room: root.room
|
||||
}
|
||||
|
||||
sortRole: "powerLevel"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
filterRole: "name"
|
||||
filterCaseSensitivity: Qt.CaseInsensitive
|
||||
}
|
||||
|
||||
model: root.room.isDirectChat() ? 0 : sortedMessageEventModel
|
||||
|
||||
clip: true
|
||||
activeFocusOnTab: true
|
||||
|
||||
delegate: Delegates.RoundedItemDelegate {
|
||||
id: userDelegate
|
||||
|
||||
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
|
||||
|
||||
onClicked: {
|
||||
userDelegate.highlighted = true;
|
||||
const popup = userDetailDialog.createObject(QQC2.ApplicationWindow.overlay, {
|
||||
room: root.room,
|
||||
user: root.room.getUser(userDelegate.userId)
|
||||
});
|
||||
popup.closed.connect(() => {
|
||||
userDelegate.highlighted = false;
|
||||
});
|
||||
popup.open();
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
visible: userDelegate.powerLevel > 0
|
||||
|
||||
text: userDelegate.powerLevelString
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: groupChatDrawerHeader
|
||||
GroupChatDrawerHeader {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: directChatDrawerHeader
|
||||
DirectChatDrawerHeader {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: userDetailDialog
|
||||
UserDetailDialog {}
|
||||
}
|
||||
|
||||
onRoomChanged: {
|
||||
if (root.headerItem) {
|
||||
root.headerItem.userListSearchField.text = "";
|
||||
}
|
||||
root.currentIndex = -1
|
||||
}
|
||||
}
|
||||
@@ -132,6 +132,10 @@ Kirigami.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
function openRoomDrawer() {
|
||||
pageStack.push("qrc:/RoomDrawerPage.qml")
|
||||
}
|
||||
|
||||
contextDrawer: RoomDrawer {
|
||||
id: contextDrawer
|
||||
|
||||
@@ -147,7 +151,7 @@ Kirigami.ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
modal: !root.wideScreen || !enabled
|
||||
modal: (!root.wideScreen || !enabled)
|
||||
onEnabledChanged: drawerOpen = enabled && !modal
|
||||
onModalChanged: {
|
||||
if (Config.autoRoomInfoDrawer) {
|
||||
@@ -155,7 +159,7 @@ Kirigami.ApplicationWindow {
|
||||
dim = false
|
||||
}
|
||||
}
|
||||
enabled: RoomManager.hasOpenRoom && pageStack.layers.depth < 2 && pageStack.depth < 3 && (pageStack.visibleItems.length > 1 || pageStack.currentIndex > 0)
|
||||
enabled: RoomManager.hasOpenRoom && pageStack.layers.depth < 2 && pageStack.depth < 3 && (pageStack.visibleItems.length > 1 || pageStack.currentIndex > 0) && !Kirigami.Settings.isMobile && root.pageStack.wideMode
|
||||
handleVisible: enabled
|
||||
}
|
||||
|
||||
|
||||
@@ -71,9 +71,6 @@
|
||||
<file alias="Homeserver.qml">qml/Component/Login/Homeserver.qml</file>
|
||||
<file alias="LoginMethod.qml">qml/Component/Login/LoginMethod.qml</file>
|
||||
<file alias="Sso.qml">qml/Component/Login/Sso.qml</file>
|
||||
<file alias="RoomDrawer.qml">qml/Panel/RoomDrawer.qml</file>
|
||||
<file alias="DirectChatDrawerHeader.qml">qml/Panel/DirectChatDrawerHeader.qml</file>
|
||||
<file alias="GroupChatDrawerHeader.qml">qml/Panel/GroupChatDrawerHeader.qml</file>
|
||||
<file alias="UserDetailDialog.qml">qml/Dialog/UserDetailDialog.qml</file>
|
||||
<file alias="CreateRoomDialog.qml">qml/Dialog/CreateRoomDialog.qml</file>
|
||||
<file alias="CreateSpaceDialog.qml">qml/Dialog/CreateSpaceDialog.qml</file>
|
||||
@@ -133,5 +130,10 @@
|
||||
<file alias="FullScreenMap.qml">qml/Component/FullScreenMap.qml</file>
|
||||
<file alias="LocationsPage.qml">qml/Component/LocationPage.qml</file>
|
||||
<file alias="LocationMapItem.qml">qml/Component/LocationMapItem.qml</file>
|
||||
<file alias="RoomDrawer.qml">qml/RoomDrawer/RoomDrawer.qml</file>
|
||||
<file alias="RoomDrawerPage.qml">qml/RoomDrawer/RoomDrawerPage.qml</file>
|
||||
<file alias="DirectChatDrawerHeader.qml">qml/RoomDrawer/DirectChatDrawerHeader.qml</file>
|
||||
<file alias="GroupChatDrawerHeader.qml">qml/RoomDrawer/GroupChatDrawerHeader.qml</file>
|
||||
<file alias="RoomInformation.qml">qml/RoomDrawer/RoomInformation.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Reference in New Issue
Block a user