Skip to content
Snippets Groups Projects
RoomList.qml 19.2 KiB
Newer Older
// 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 {
            onActiveTimelineChanged: {
                roomlist.positionViewAtIndex(Rooms.roomidToIndex(Rooms.currentRoom.roomId), ListView.Contain);
                console.log("Test" + Rooms.currentRoom.roomId + " " + Rooms.roomidToIndex(Rooms.currentRoom.roomId));
Nicolas Werner's avatar
Nicolas Werner committed
            }
            target: TimelineManager
        }

        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.MenuItem {
                text: qsTr("Leave room")
                onTriggered: Rooms.leave(roomContextMenu.roomid)
            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
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
                    }

                }
            ]
            TapHandler {
                margin: -Nheko.paddingSmall
                acceptedButtons: Qt.RightButton
                    if (!TimelineManager.isInvite)
                        roomContextMenu.show(roomId, tags);
                gesturePolicy: TapHandler.ReleaseWithinBounds
            }

                margin: -Nheko.paddingSmall
                onSingleTapped: Rooms.setCurrentRoom(roomId)
                    if (!isInvite)
                        roomContextMenu.show(roomId, tags);
            HoverHandler {
                id: hovered

                margin: -Nheko.paddingSmall
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

                    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 : ""
                    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
                }

                ImageButton {
                    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()