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:
James Graham
2023-08-26 08:42:39 +00:00
parent 5c72bd4ab7
commit 43715486e5
9 changed files with 472 additions and 372 deletions

View File

@@ -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: {

View File

@@ -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 {}
}
}

View 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
}
}
}
}
}

View 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()
}
}

View 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
}
}

View File

@@ -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
}

View File

@@ -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>