Skip to content
Snippets Groups Projects
TimelineView.qml 10.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Werner's avatar
    Nicolas Werner committed
    // SPDX-FileCopyrightText: 2021 Nheko Contributors
    
    // SPDX-FileCopyrightText: 2022 Nheko Contributors
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    
    import "./components"
    
    import "./delegates"
    import "./device-verification"
    import "./emoji"
    
    Joe Donofry's avatar
    Joe Donofry committed
    import "./ui"
    
    import "./voip"
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    import Qt.labs.platform 1.1 as Platform
    
    import QtQuick.Controls 2.5
    
    import QtQuick.Layouts 1.3
    
    Loren Burkholder's avatar
    Loren Burkholder committed
    import QtQuick.Particles 2.15
    
    import QtQuick.Window 2.13
    
    import im.nheko.EmojiModel 1.0
    
        property var room: null
    
        property var roomPreview: null
    
        property bool showBackButton: false
    
    Malte E's avatar
    Malte E committed
        clip: true
    
    Loren Burkholder's avatar
    Loren Burkholder committed
        onRoomChanged: if (room != null) room.triggerSpecialEffects()
    
    
        // focus message input on key press, but not on Ctrl-C and such.
        Keys.onPressed: if (event.text && !topBar.searchHasFocus) TimelineManager.focusMessageInput();
    
        Shortcut {
            sequence: StandardKey.Close
            onActivated: Rooms.resetCurrentRoom()
        }
    
    
            visible: !room && !TimelineManager.isInitialSync && (!roomPreview || !roomPreview.roomid)
    
            anchors.centerIn: parent
            text: qsTr("No room open")
            font.pointSize: 24
            color: Nheko.colors.text
    
    Joe Donofry's avatar
    Joe Donofry committed
        Spinner {
    
            visible: TimelineManager.isInitialSync
    
            foreground: Nheko.colors.mid
    
            running: TimelineManager.isInitialSync
    
    Joe Donofry's avatar
    Joe Donofry committed
            // height is somewhat arbitrary here... don't set width because width scales w/ height
            height: parent.height / 16
    
            opacity: hh.hovered ? 0.3 : 1
    
            Behavior on opacity {
                NumberAnimation { duration: 100; }
            }
    
            HoverHandler {
                id: hh
            }
    
        ColumnLayout {
            id: timelineLayout
    
            visible: room != null && !room.isSpace
            enabled: visible
    
            anchors.fill: parent
    
                showBackButton: timelineView.showBackButton
    
            Rectangle {
                Layout.fillWidth: true
                height: 1
    
                z: 3
    
                color: Nheko.theme.separator
    
    Joe Donofry's avatar
    Joe Donofry committed
    
    
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: Nheko.colors.base
    
                ColumnLayout {
                    anchors.fill: parent
                    spacing: 0
    
                    StackLayout {
                        id: stackLayout
    
                            function onRoomChanged() {
    
                                stackLayout.currentIndex = 0;
    
                            target: timelineView
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                        MessageView {
                            implicitHeight: msgView.height - typingIndicator.height
    
                            searchString: topBar.searchString
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                            Layout.fillWidth: true
                        }
    
                        Loader {
                            source: CallManager.isOnCall && CallManager.callType != CallType.VOICE ? "voip/VideoCall.qml" : ""
                            onLoaded: TimelineManager.setVideoCallItem()
    
    trilene's avatar
    trilene committed
                        }
    
                    TypingIndicator {
                        id: typingIndicator
                    }
    
            CallInviteBar {
                id: callInviteBar
    
            ActiveCallBar {
                Layout.fillWidth: true
                z: 3
            }
    
            Rectangle {
                Layout.fillWidth: true
                z: 3
                height: 1
    
                color: Nheko.theme.separator
    
        ColumnLayout {
    
            property string roomId: room ? room.roomId : (roomPreview ? roomPreview.roomid : "")
    
            property string roomName: room ? room.roomName : (roomPreview ? roomPreview.roomName : "")
            property string roomTopic: room ? room.roomTopic : (roomPreview ? roomPreview.roomTopic : "")
            property string avatarUrl: room ? room.roomAvatarUrl : (roomPreview ? roomPreview.roomAvatarUrl : "")
    
            visible: room != null && room.isSpace || roomPreview != null
    
            enabled: visible
            anchors.fill: parent
            anchors.margins: Nheko.paddingLarge
            spacing: Nheko.paddingLarge
    
    
            Item {
                Layout.fillHeight: true
            }
    
    
            Avatar {
    
                url: parent.avatarUrl.replace("mxc://", "image://MxcImage/")
    
                roomid: parent.roomId
    
                displayName: parent.roomName
    
                height: 130
                width: 130
                Layout.alignment: Qt.AlignHCenter
                enabled: false
            }
    
    Loren Burkholder's avatar
    Loren Burkholder committed
    
    
            RowLayout {
                spacing: Nheko.paddingMedium
    
                Layout.alignment: Qt.AlignHCenter
    
    
                MatrixText {
                    text: preview.roomName == "" ? qsTr("No preview available") : preview.roomName
                    font.pixelSize: 24
                }
    
                ImageButton {
                    image: ":/icons/icons/ui/settings.svg"
                    visible: !!room
                    hoverEnabled: true
                    ToolTip.visible: hovered
                    ToolTip.text: qsTr("Settings")
                    onClicked: TimelineManager.openRoomSettings(room.roomId)
                }
    
    
                visible: !!room
    
                spacing: Nheko.paddingMedium
    
                Layout.alignment: Qt.AlignHCenter
    
                    text: qsTr("%n member(s)", "", room ? room.roomMemberCount : 0)
    
                }
    
                ImageButton {
                    image: ":/icons/icons/ui/people.svg"
                    hoverEnabled: true
                    ToolTip.visible: hovered
    
                    ToolTip.text: qsTr("View members of %1").arg(room ? room.roomName : "")
    
                    onClicked: TimelineManager.openRoomMembers(room)
                }
    
    
            }
    
            ScrollView {
                Layout.alignment: Qt.AlignHCenter
    
                Layout.fillWidth: true
                Layout.leftMargin: Nheko.paddingLarge
                Layout.rightMargin: Nheko.paddingLarge
    
    
                TextArea {
    
                    text: TimelineManager.escapeEmoji(preview.roomTopic)
    
                    wrapMode: TextEdit.WordWrap
                    textFormat: TextEdit.RichText
                    readOnly: true
                    background: null
                    selectByMouse: true
                    color: Nheko.colors.text
                    horizontalAlignment: TextEdit.AlignHCenter
                    onLinkActivated: Nheko.openLink(link)
    
                    CursorShape {
                        anchors.fill: parent
                        cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
                    }
    
                }
    
            }
    
    
            FlatButton {
                visible: roomPreview && !roomPreview.isInvite
                Layout.alignment: Qt.AlignHCenter
                text: qsTr("join the conversation")
                onClicked: Rooms.joinPreview(roomPreview.roomid)
            }
    
            FlatButton {
                visible: roomPreview && roomPreview.isInvite
                Layout.alignment: Qt.AlignHCenter
                text: qsTr("accept invite")
                onClicked: Rooms.acceptInvite(roomPreview.roomid)
            }
    
            FlatButton {
                visible: roomPreview && roomPreview.isInvite
                Layout.alignment: Qt.AlignHCenter
                text: qsTr("decline invite")
                onClicked: Rooms.declineInvite(roomPreview.roomid)
            }
    
            Item {
                visible: room != null
                Layout.preferredHeight: Math.ceil(fontMetrics.lineSpacing * 2)
            }
    
    
            Item {
                Layout.fillHeight: true
            }
    
        }
    
    
        ImageButton {
            id: backToRoomsButton
    
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.margins: Nheko.paddingMedium
            width: Nheko.avatarSize
            height: Nheko.avatarSize
    
            visible: (room == null || room.isSpace) && showBackButton
    
            image: ":/icons/icons/ui/angle-arrow-left.svg"
    
            ToolTip.visible: hovered
            ToolTip.text: qsTr("Back to room list")
            onClicked: Rooms.resetCurrentRoom()
        }
    
    
    Loren Burkholder's avatar
    Loren Burkholder committed
        ParticleSystem { id: confettiParticleSystem }
    
        Emitter {
            id: confettiEmitter
    
            width: parent.width * 3/4
            enabled: false
            anchors.horizontalCenter: parent.horizontalCenter
            y: parent.height
            emitRate: Math.min(400 * Math.sqrt(parent.width * parent.height) / 870, 1000)
            lifeSpan: 15000
            system: confettiParticleSystem
            velocityFromMovement: 8
            size: 16
            sizeVariation: 4
            velocity: PointDirection {
                x: 0
                y: -Math.min(450 * parent.height / 700, 1000)
                xVariation: Math.min(4 * parent.width / 7, 450)
                yVariation: 250
            }
    
            ImageParticle {
                system: confettiParticleSystem
                source: "qrc:/confettiparticle.svg"
                rotationVelocity: 0
                rotationVelocityVariation: 360
                colorVariation: 1
                color: "white"
                entryEffect: ImageParticle.None
                xVector: PointDirection {
                    x: 1
                    y: 0
                    xVariation: 0.2
                    yVariation: 0.2
                }
                yVector: PointDirection {
                    x: 0
                    y: 0.5
                    xVariation: 0.2
                    yVariation: 0.2
                }
            }
        }
    
        Gravity {
            system: confettiParticleSystem
            anchors.fill: parent
            magnitude: 350
            angle: 90
        }
    
    
            anchors.fill: parent
    
            roomid: room ? room.roomId : ""
    
        Connections {
            function onOpenReadReceiptsDialog(rr) {
                var dialog = readReceiptsDialog.createObject(timelineRoot, {
                    "readReceipts": rr,
                    "room": room
                });
                dialog.show();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                timelineRoot.destroyOnClose(dialog);
    
            function onShowRawMessageDialog(rawMessage) {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                var dialog = Qt.createComponent("qrc:/qml/dialogs/RawMessageDialog.qml").createObject(timelineRoot, {
    
                    "rawMessage": rawMessage
                });
                dialog.show();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                timelineRoot.destroyOnClose(dialog);
    
    Loren Burkholder's avatar
    Loren Burkholder committed
            function onConfetti()
            {
                if (!Settings.fancyEffects)
                    return
    
                confettiEmitter.pulse(parent.height * 2)
                room.markSpecialEffectsDone()
            }