Skip to content
Snippets Groups Projects
TimelineView.qml 10.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Werner's avatar
    Nicolas Werner committed
    // SPDX-FileCopyrightText: 2021 Nheko Contributors
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    // SPDX-License-Identifier: GPL-3.0-or-later
    
    
    import "./delegates"
    import "./device-verification"
    import "./emoji"
    
    import "./voip"
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    import Qt.labs.platform 1.1 as Platform
    
    import QtGraphicalEffects 1.0
    
    import QtQuick.Controls 2.3
    
    import QtQuick.Layouts 1.3
    import QtQuick.Window 2.2
    
    import im.nheko.EmojiModel 1.0
    
        id: timelineRoot
    
    
        palette: Nheko.colors
    
    
        FontMetrics {
            id: fontMetrics
        }
    
        EmojiPicker {
            id: emojiPopup
    
            colors: palette
    
            model: TimelineManager.completerFor("allemoji", "")
    
        Component {
            id: userProfileComponent
    
            UserProfile {
            }
    
        }
    
    
    Jedi18's avatar
    Jedi18 committed
        Component {
            id: roomSettingsComponent
    
            RoomSettings {
            }
    
        }
    
    
        Component {
            id: mobileCallInviteDialog
    
            CallInvite {
            }
    
        Component {
            id: quickSwitcherComponent
    
            QuickSwitcher {
            }
    
    targetakhil's avatar
    targetakhil committed
        Component {
    
            id: forwardCompleterComponent
    
            ForwardCompleter {
    
    targetakhil's avatar
    targetakhil committed
            }
    
    Jedi18's avatar
    Jedi18 committed
            sequence: "Ctrl+K"
    
            onActivated: {
                var quickSwitch = quickSwitcherComponent.createObject(timelineRoot);
    
                TimelineManager.focusTimeline();
    
    Nicolas Werner's avatar
    Nicolas Werner committed
        Platform.Menu {
    
            id: messageContextMenu
    
            property string eventId
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            property string link
    
            property string text
    
            property int eventType
            property bool isEncrypted
    
            property bool isEditable
    
            function show(eventId_, eventType_, isSender_, isEncrypted_, isEditable_, link_, text_, showAt_) {
    
                eventId = eventId_;
                eventType = eventType_;
                isEncrypted = isEncrypted_;
    
                isEditable = isEditable_;
    
                if (text_)
                    text = text_;
                else
                    text = "";
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                if (link_)
                    link = link_;
                else
                    link = "";
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                if (showAt_)
                    open(showAt_);
                else
                    open();
    
            Platform.MenuItem {
                visible: messageContextMenu.text
                enabled: visible
                text: qsTr("Copy")
                onTriggered: Clipboard.text = messageContextMenu.text
            }
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
                visible: messageContextMenu.link
                enabled: visible
    
                text: qsTr("Copy link location")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: Clipboard.text = messageContextMenu.link
            }
    
    
            Platform.MenuItem {
                id: reactionOption
    
    
                visible: TimelineManager.timeline ? TimelineManager.timeline.permissions.canSend(MtxEvent.Reaction) : false
    
                text: qsTr("React")
    
                onTriggered: emojiPopup.show(null, function(emoji) {
    
                    TimelineManager.queueReactionMessage(messageContextMenu.eventId, emoji);
                })
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                visible: TimelineManager.timeline ? TimelineManager.timeline.permissions.canSend(MtxEvent.TextMessage) : false
    
                text: qsTr("Reply")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: TimelineManager.timeline.replyAction(messageContextMenu.eventId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                visible: messageContextMenu.isEditable && (TimelineManager.timeline ? TimelineManager.timeline.permissions.canSend(MtxEvent.TextMessage) : false)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                enabled: visible
    
                text: qsTr("Edit")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: TimelineManager.timeline.editAction(messageContextMenu.eventId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                text: qsTr("Read receipts")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: TimelineManager.timeline.readReceiptsAction(messageContextMenu.eventId)
    
    targetakhil's avatar
    targetakhil committed
            Platform.MenuItem {
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker || messageContextMenu.eventType == MtxEvent.TextMessage || messageContextMenu.eventType == MtxEvent.LocationMessage || messageContextMenu.eventType == MtxEvent.EmoteMessage || messageContextMenu.eventType == MtxEvent.NoticeMessage
    
    targetakhil's avatar
    targetakhil committed
                text: qsTr("Forward")
                onTriggered: {
    
                    var forwardMess = forwardCompleterComponent.createObject(timelineRoot);
    
                    forwardMess.setMessageEventId(messageContextMenu.eventId);
    
    targetakhil's avatar
    targetakhil committed
                    forwardMess.open();
                }
            }
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                text: qsTr("Mark as read")
            }
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                text: qsTr("View raw message")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: TimelineManager.timeline.viewRawMessage(messageContextMenu.eventId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                // TODO(Nico): Fix this still being iterated over, when using keyboard to select options
    
                visible: messageContextMenu.isEncrypted
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                enabled: visible
    
                text: qsTr("View decrypted raw message")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: TimelineManager.timeline.viewDecryptedRawMessage(messageContextMenu.eventId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                visible: (TimelineManager.timeline ? TimelineManager.timeline.permissions.canRedact() : false) || messageContextMenu.isSender
    
                text: qsTr("Remove message")
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                onTriggered: TimelineManager.timeline.redactEvent(messageContextMenu.eventId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                enabled: visible
    
                text: qsTr("Save as")
                onTriggered: TimelineManager.timeline.saveMedia(messageContextMenu.eventId)
            }
    
    
    Nicolas Werner's avatar
    Nicolas Werner committed
            Platform.MenuItem {
    
                visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                enabled: visible
    
                text: qsTr("Open in external program")
                onTriggered: TimelineManager.timeline.openMedia(messageContextMenu.eventId)
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
            Platform.MenuItem {
                visible: messageContextMenu.eventId
                enabled: visible
                text: qsTr("Copy link to event")
                onTriggered: TimelineManager.timeline.copyLinkToEvent(messageContextMenu.eventId)
    
    
        }
    
        Rectangle {
            anchors.fill: parent
    
            color: Nheko.colors.window
    
    
            Component {
                id: deviceVerificationDialog
    
                DeviceVerification {
                }
    
            }
    
            Connections {
    
                target: TimelineManager
                onNewDeviceVerificationRequest: {
    
                    var dialog = deviceVerificationDialog.createObject(timelineRoot, {
                        "flow": flow
                    });
                    dialog.show();
                }
    
                onOpenProfile: {
    
                    var userProfile = userProfileComponent.createObject(timelineRoot, {
                        "profile": profile
                    });
                    userProfile.show();
                }
            }
    
    
    Jedi18's avatar
    Jedi18 committed
            Connections {
    
                target: TimelineManager.timeline
    
    Jedi18's avatar
    Jedi18 committed
                onOpenRoomSettingsDialog: {
    
                    var roomSettings = roomSettingsComponent.createObject(timelineRoot, {
    
                        "roomSettings": settings
    
    Jedi18's avatar
    Jedi18 committed
                    roomSettings.show();
                }
            }
    
    
            Connections {
                target: CallManager
                onNewInviteState: {
                    if (CallManager.haveCallInvite && Settings.mobileMode) {
                        var dialog = mobileCallInviteDialog.createObject(msgView);
                        dialog.open();
                    }
                }
            }
    
    
            Label {
                visible: !TimelineManager.timeline && !TimelineManager.isInitialSync
                anchors.centerIn: parent
                text: qsTr("No room open")
                font.pointSize: 24
    
                color: Nheko.colors.text
    
            }
    
            BusyIndicator {
                visible: running
                anchors.centerIn: parent
                running: TimelineManager.isInitialSync
                height: 200
                width: 200
                z: 3
            }
    
            ColumnLayout {
    
                id: timelineLayout
    
    Joe Donofry's avatar
    Joe Donofry committed
    
    
                visible: TimelineManager.timeline != null
    
                anchors.fill: parent
    
                spacing: 0
    
                Rectangle {
    
                    Layout.fillWidth: true
    
                    height: 1
    
                    z: 3
    
                    color: Nheko.colors.mid
    
                Rectangle {
    
                    id: msgView
    
                    Layout.fillWidth: true
                    Layout.fillHeight: true
    
                    color: Nheko.colors.base
    
    trilene's avatar
    trilene committed
    
    
                        anchors.fill: parent
    
    trilene's avatar
    trilene committed
    
    
                            Connections {
                                function onActiveTimelineChanged() {
                                    stackLayout.currentIndex = 0;
    
    Nicolas Werner's avatar
    Nicolas Werner committed
    
                                target: TimelineManager
    
                            MessageView {
                                Layout.fillWidth: true
                                Layout.fillHeight: true
    
                                source: CallManager.isOnCall && CallManager.callType != CallType.VOICE ? "voip/VideoCall.qml" : ""
    
                                onLoaded: TimelineManager.setVideoCallItem()
    
    trilene's avatar
    trilene committed
                            }
    
    trilene's avatar
    trilene committed
                        }
    
                CallInviteBar {
                    id: callInviteBar
    
                    Layout.fillWidth: true
                    z: 3
                }
    
    
                ActiveCallBar {
                    Layout.fillWidth: true
                    z: 3
                }
    
    
                Rectangle {
    
                    Layout.fillWidth: true
                    z: 3
    
                    height: 1
    
                    color: Nheko.colors.mid
    
    Nicolas Werner's avatar
    Nicolas Werner committed
                MessageInput {
                }
    
            NhekoDropArea {
    
                anchors.fill: parent
    
                roomid: TimelineManager.timeline ? TimelineManager.timeline.roomId() : ""
    
        PrivacyScreen {
            anchors.fill: parent
            visible: Settings.privacyScreen
            screenTimeout: Settings.privacyScreenTimeout
            timelineRoot: timelineLayout