Skip to content
Snippets Groups Projects
RoomList.qml 20.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • // SPDX-FileCopyrightText: 2021 Nheko Contributors
    //
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    
    import "./dialogs"
    
    import Qt.labs.platform 1.1 as Platform
    
    import QtQml 2.12
    
    import QtQuick 2.15
    import QtQuick.Controls 2.15
    
    import QtQuick.Layouts 1.3
    import im.nheko 1.0
    
    Page {
    
        //leftPadding: Nheko.paddingSmall
        //rightPadding: Nheko.paddingSmall
    
        property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3)
        property bool collapsed: false
    
    Nicolas Werner's avatar
    Nicolas Werner committed
        ListView {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            id: roomlist
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            anchors.left: parent.left
            anchors.right: parent.right
            height: parent.height
            model: Rooms
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
            ScrollHelper {
                flickable: parent
                anchors.fill: parent
                enabled: !Settings.mobileMode
            }
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Connections {
    
                function onCurrentRoomChanged() {
    
                    if (Rooms.currentRoom)
                        roomlist.positionViewAtIndex(Rooms.roomidToIndex(Rooms.currentRoom.roomId), ListView.Contain);
    
    
                target: Rooms
    
            Platform.Menu {
                id: roomContextMenu
    
                property string roomid
                property var tags
    
                function show(roomid_, tags_) {
                    roomid = roomid_;
                    tags = tags_;
                    open();
                }
    
                InputDialog {
                    id: newTag
    
                    title: qsTr("New tag")
                    prompt: qsTr("Enter the tag you want to use:")
                    onAccepted: function(text) {
                        Rooms.toggleTag(roomContextMenu.roomid, "u." + text, true);
                    }
                }
    
    
                Platform.MessageDialog {
                    id: leaveRoomDialog
    
                    title: qsTr("Leave Room")
                    text: qsTr("Are you sure you want to leave this room?")
    
                    modality: Qt.ApplicationModal
    
                    onAccepted: Rooms.leave(roomContextMenu.roomid)
                    buttons: Dialog.Ok | Dialog.Cancel
                }
    
    
                Platform.MenuItem {
                    text: qsTr("Leave room")
    
                    onTriggered: leaveRoomDialog.open()
    
                Platform.MenuSeparator {
                    text: qsTr("Tag room as:")
    
                    model: Communities.tagsWithDefault
    
                    onObjectAdded: roomContextMenu.insertItem(index + 2, object)
                    onObjectRemoved: roomContextMenu.removeItem(object)
    
                    delegate: Platform.MenuItem {
                        property string t: modelData
    
    
                        text: {
                            switch (t) {
                            case "m.favourite":
                                return qsTr("Favourite");
                            case "m.lowpriority":
                                return qsTr("Low priority");
                            case "m.server_notice":
                                return qsTr("Server notice");
                            default:
                                return t.substring(2);
                            }
                        }
                        checkable: true
    
                        checked: roomContextMenu.tags !== undefined && roomContextMenu.tags.includes(t)
    
                        onTriggered: Rooms.toggleTag(roomContextMenu.roomid, t, checked)
                    }
    
                }
    
    
                Platform.MenuItem {
                    text: qsTr("Create new tag...")
                    onTriggered: newTag.show()
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            delegate: Rectangle {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                id: roomItem
    
                property color background: Nheko.colors.window
                property color importantText: Nheko.colors.text
                property color unimportantText: Nheko.colors.buttonText
                property color bubbleBackground: Nheko.colors.highlight
                property color bubbleText: Nheko.colors.highlightedText
    
                required property string roomName
                required property string roomId
                required property string avatarUrl
                required property string time
                required property string lastMessage
                required property var tags
                required property bool isInvite
                required property bool isSpace
                required property int notificationCount
                required property bool hasLoudNotification
                required property bool hasUnreadMessages
    
                required property bool isDirect
    
                required property string directChatAvatarMxid
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                color: background
    
                height: avatarSize + 2 * Nheko.paddingMedium
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                width: ListView.view.width
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                state: "normal"
    
                ToolTip.visible: hovered.hovered && collapsed
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                states: [
                    State {
                        name: "highlight"
    
                        when: hovered.hovered && !((Rooms.currentRoom && roomId == Rooms.currentRoom.roomId) || Rooms.currentRoomPreview.roomid == roomId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                        PropertyChanges {
                            target: roomItem
                            background: Nheko.colors.dark
                            importantText: Nheko.colors.brightText
                            unimportantText: Nheko.colors.brightText
                            bubbleBackground: Nheko.colors.highlight
                            bubbleText: Nheko.colors.highlightedText
                        }
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                    },
                    State {
                        name: "selected"
    
                        when: (Rooms.currentRoom && roomId == Rooms.currentRoom.roomId) || Rooms.currentRoomPreview.roomid == roomId
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                        PropertyChanges {
                            target: roomItem
                            background: Nheko.colors.highlight
                            importantText: Nheko.colors.highlightedText
                            unimportantText: Nheko.colors.highlightedText
                            bubbleBackground: Nheko.colors.highlightedText
                            bubbleText: Nheko.colors.highlight
                        }
    
                    }
                ]
    
                // NOTE(Nico): We want to prevent the touch areas from overlapping. For some reason we need to add 1px of padding for that...
                Item {
                    anchors.fill: parent
                    anchors.margins: 1
    
                    TapHandler {
                        acceptedButtons: Qt.RightButton
                        onSingleTapped: {
                            if (!TimelineManager.isInvite)
                                roomContextMenu.show(roomId, tags);
    
                        }
                        gesturePolicy: TapHandler.ReleaseWithinBounds
    
                        acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad
    
                    TapHandler {
                        margin: -Nheko.paddingSmall
    
                        onSingleTapped: {
                            if (!Rooms.currentRoom || Rooms.currentRoom.roomId !== roomId)
                                Rooms.setCurrentRoom(roomId);
                            else
                                Rooms.resetCurrentRoom();
                        }
    
                        onLongPressed: {
                            if (!isInvite)
                                roomContextMenu.show(roomId, tags);
    
                    HoverHandler {
                        id: hovered
    
    
                        acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus | PointerDevice.TouchPad
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                }
    
                RowLayout {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                    spacing: Nheko.paddingMedium
                    anchors.fill: parent
                    anchors.margins: Nheko.paddingMedium
    
                    Avatar {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        // In the future we could show an online indicator by setting the userid for the avatar
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        //userid: Nheko.currentUser.userid
    
                        id: avatar
    
    
                        enabled: false
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        Layout.alignment: Qt.AlignVCenter
    
                        height: avatarSize
                        width: avatarSize
    
                        url: avatarUrl.replace("mxc://", "image://MxcImage/")
                        displayName: roomName
    
                        userid: isDirect ? directChatAvatarMxid : undefined
                        roomid: roomId
    
    
                        Rectangle {
                            id: collapsedNotificationBubble
    
                            anchors.right: parent.right
                            anchors.bottom: parent.bottom
                            anchors.margins: -Nheko.paddingSmall
    
                            visible: collapsed && notificationCount > 0
    
                            enabled: false
                            Layout.alignment: Qt.AlignRight
                            height: fontMetrics.averageCharacterWidth * 3
                            width: height
                            radius: height / 2
    
                            color: hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground
    
    
                            Label {
                                anchors.centerIn: parent
                                width: parent.width * 0.8
                                height: parent.height * 0.8
                                horizontalAlignment: Text.AlignHCenter
                                verticalAlignment: Text.AlignVCenter
                                fontSizeMode: Text.Fit
                                font.bold: true
                                font.pixelSize: fontMetrics.font.pixelSize * 0.8
    
                                color: hasLoudNotification ? "white" : roomItem.bubbleText
                                text: notificationCount > 99 ? "99+" : notificationCount
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                    }
    
                    ColumnLayout {
                        id: textContent
    
    
                        visible: !collapsed
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        Layout.alignment: Qt.AlignLeft
                        Layout.fillWidth: true
                        Layout.minimumWidth: 100
                        width: parent.width - avatar.width
                        Layout.preferredWidth: parent.width - avatar.width
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        spacing: Nheko.paddingSmall
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                        RowLayout {
                            Layout.fillWidth: true
                            spacing: 0
    
                            ElidedLabel {
                                Layout.alignment: Qt.AlignBottom
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                color: roomItem.importantText
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                elideWidth: textContent.width - timestamp.width - Nheko.paddingMedium
    
                                textFormat: Text.RichText
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            }
    
                            Item {
                                Layout.fillWidth: true
                            }
    
                            Label {
                                id: timestamp
    
                                visible: !isInvite && !isSpace
    
                                width: visible ? 0 : undefined
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                Layout.alignment: Qt.AlignRight | Qt.AlignBottom
                                font.pixelSize: fontMetrics.font.pixelSize * 0.9
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                color: roomItem.unimportantText
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            }
    
                        }
    
                        RowLayout {
                            Layout.fillWidth: true
                            spacing: 0
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            height: visible ? 0 : undefined
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                            ElidedLabel {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                color: roomItem.unimportantText
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                font.pixelSize: fontMetrics.font.pixelSize * 0.9
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                elideWidth: textContent.width - (notificationBubble.visible ? notificationBubble.width : 0) - Nheko.paddingSmall
    
                                textFormat: Text.RichText
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            }
    
                            Item {
                                Layout.fillWidth: true
                            }
    
                            Rectangle {
                                id: notificationBubble
    
    
                                visible: notificationCount > 0
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                Layout.alignment: Qt.AlignRight
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                height: fontMetrics.averageCharacterWidth * 3
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                width: height
                                radius: height / 2
    
                                color: hasLoudNotification ? Nheko.theme.red : roomItem.bubbleBackground
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                                Label {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                    anchors.centerIn: parent
                                    width: parent.width * 0.8
                                    height: parent.height * 0.8
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                    horizontalAlignment: Text.AlignHCenter
                                    verticalAlignment: Text.AlignVCenter
                                    fontSizeMode: Text.Fit
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                    font.bold: true
                                    font.pixelSize: fontMetrics.font.pixelSize * 0.8
    
                                    color: hasLoudNotification ? "white" : roomItem.bubbleText
                                    text: notificationCount > 99 ? "99+" : notificationCount
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                                }
    
                            }
    
                        }
    
                    }
    
                }
    
                Rectangle {
                    anchors.left: parent.left
                    anchors.verticalCenter: parent.verticalCenter
                    height: parent.height - Nheko.paddingSmall * 2
                    width: 3
                    color: Nheko.colors.highlight
    
    
        background: Rectangle {
            color: Nheko.theme.sidebarBackground
        }
    
        header: ColumnLayout {
            spacing: 0
    
            Rectangle {
    
                id: userInfoPanel
    
                function openUserProfile() {
                    Nheko.updateUserProfile();
                    var userProfile = userProfileComponent.createObject(timelineRoot, {
                        "profile": Nheko.currentUser
                    });
                    userProfile.show();
                }
    
    
                color: Nheko.colors.window
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignBottom
                Layout.preferredHeight: userInfoGrid.implicitHeight + 2 * Nheko.paddingMedium
                Layout.minimumHeight: 40
    
    
                InputDialog {
    
                    id: statusDialog
    
                    title: qsTr("Status Message")
    
                    prompt: qsTr("Enter your status message:")
                    onAccepted: function(text) {
                        Nheko.setStatusMessage(text);
    
                    }
                }
    
                Platform.Menu {
                    id: userInfoMenu
    
                    Platform.MenuItem {
                        text: qsTr("Profile settings")
                        onTriggered: userInfoPanel.openUserProfile()
                    }
    
                    Platform.MenuItem {
                        text: qsTr("Set status message")
                        onTriggered: statusDialog.show()
                    }
    
                }
    
                TapHandler {
    
                    margin: -Nheko.paddingSmall
    
                    acceptedButtons: Qt.LeftButton
                    onSingleTapped: userInfoPanel.openUserProfile()
                    onLongPressed: userInfoMenu.open()
                    gesturePolicy: TapHandler.ReleaseWithinBounds
                }
    
                TapHandler {
    
                    margin: -Nheko.paddingSmall
    
                    acceptedButtons: Qt.RightButton
                    onSingleTapped: userInfoMenu.open()
                    gesturePolicy: TapHandler.ReleaseWithinBounds
    
                RowLayout {
                    id: userInfoGrid
    
    
                    property var profile: Nheko.currentUser
    
    
                    spacing: Nheko.paddingMedium
                    anchors.fill: parent
                    anchors.margins: Nheko.paddingMedium
    
                    Avatar {
                        id: avatar
    
                        Layout.alignment: Qt.AlignVCenter
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        Layout.preferredWidth: fontMetrics.lineSpacing * 2
                        Layout.preferredHeight: fontMetrics.lineSpacing * 2
    
                        url: (userInfoGrid.profile ? userInfoGrid.profile.avatarUrl : "").replace("mxc://", "image://MxcImage/")
                        displayName: userInfoGrid.profile ? userInfoGrid.profile.displayName : ""
                        userid: userInfoGrid.profile ? userInfoGrid.profile.userid : ""
    
                        enabled: false
    
                        visible: !collapsed
    
                        Layout.alignment: Qt.AlignLeft
                        Layout.fillWidth: true
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        width: parent.width - avatar.width - logoutButton.width - Nheko.paddingMedium * 2
                        Layout.preferredWidth: parent.width - avatar.width - logoutButton.width - Nheko.paddingMedium * 2
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        ElidedLabel {
    
                            Layout.alignment: Qt.AlignBottom
                            font.pointSize: fontMetrics.font.pointSize * 1.1
                            font.weight: Font.DemiBold
    
                            fullText: userInfoGrid.profile ? userInfoGrid.profile.displayName : ""
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            elideWidth: col.width
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        ElidedLabel {
    
                            Layout.alignment: Qt.AlignTop
                            color: Nheko.colors.buttonText
                            font.pointSize: fontMetrics.font.pointSize * 0.9
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            elideWidth: col.width
    
                            fullText: userInfoGrid.profile ? userInfoGrid.profile.userid : ""
    
                        visible: !collapsed
    
                        Layout.alignment: Qt.AlignVCenter
                        image: ":/icons/icons/ui/power-button-off.png"
                        ToolTip.visible: hovered
                        ToolTip.text: qsTr("Logout")
    
                        onClicked: Nheko.openLogoutDialog()
    
                    }
    
                }
    
            }
    
            Rectangle {
                color: Nheko.theme.separator
                height: 2
                Layout.fillWidth: true
            }
    
        }
    
        footer: ColumnLayout {
            spacing: 0
    
            Rectangle {
                color: Nheko.theme.separator
                height: 1
                Layout.fillWidth: true
            }
    
            Rectangle {
                color: Nheko.colors.window
                Layout.fillWidth: true
                Layout.alignment: Qt.AlignBottom
                Layout.preferredHeight: buttonRow.implicitHeight
                Layout.minimumHeight: 40
    
                RowLayout {
                    id: buttonRow
    
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.margins: Nheko.paddingMedium
    
                    ImageButton {
    
    Loren Burkholder's avatar
    Loren Burkholder committed
                        Layout.fillWidth: true
    
                        hoverEnabled: true
                        width: 22
                        height: 22
                        image: ":/icons/icons/ui/plus-black-symbol.png"
                        ToolTip.visible: hovered
                        ToolTip.text: qsTr("Start a new chat")
                        Layout.margins: Nheko.paddingMedium
    
                        onClicked: roomJoinCreateMenu.open(parent)
    
                        Platform.Menu {
                            id: roomJoinCreateMenu
    
                            Platform.MenuItem {
                                text: qsTr("Join a room")
                                onTriggered: Nheko.openJoinRoomDialog()
                            }
    
                            Platform.MenuItem {
                                text: qsTr("Create a new room")
                                onTriggered: Nheko.openCreateRoomDialog()
                            }
    
                        }
    
                        visible: !collapsed
    
    Loren Burkholder's avatar
    Loren Burkholder committed
                        Layout.fillWidth: true
    
                        hoverEnabled: true
                        width: 22
                        height: 22
                        image: ":/icons/icons/ui/speech-bubbles-comment-option.png"
                        ToolTip.visible: hovered
                        ToolTip.text: qsTr("Room directory")
                        Layout.margins: Nheko.paddingMedium
    
                            var win = roomDirectoryComponent.createObject(timelineRoot);
                            win.show();
    
                        visible: !collapsed
    
    Loren Burkholder's avatar
    Loren Burkholder committed
                        Layout.fillWidth: true
    
                        hoverEnabled: true
                        width: 22
                        height: 22
                        image: ":/icons/icons/ui/settings.png"
                        ToolTip.visible: hovered
                        ToolTip.text: qsTr("User settings")
                        Layout.margins: Nheko.paddingMedium
    
                        onClicked: Nheko.showUserSettingsPage()