aboutsummaryrefslogtreecommitdiff
path: root/qml/ChatPage.qml
blob: 944231de2b9204238357ddc39b02d1c083631f4e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQml.Models 2.1
import org.kde.kirigami 2.12 as Kirigami

import DeltaChat 1.0

Kirigami.ScrollablePage {
    id: chatPage

    title: chat ? chat.name : qsTr("Chat")

    required property DcContext context
    required property DcAccountsEventEmitter eventEmitter

    required property var chatId
    property DcChat chat: context.getChat(chatId)

    contextualActions: [
        Kirigami.Action {
            text: "Accept contact request"
            onTriggered: chatPage.context.acceptChat(chatPage.chatId)
            visible: chatPage.chat && chatPage.chat.isContactRequest
        },
        Kirigami.Action {
            text: "Block contact request"
            onTriggered: chatPage.context.blockChat(chatPage.chatId)
            visible: chatPage.chat && chatPage.chat.isContactRequest
        }
    ]

    function updateMessagelist() {
        // Reverse message list, because it is laid out from bottom to top.
        let messagelist = context.getMsgIdList(chatId).reverse()

        for (let i = 0; i < messagelist.length; i++) {
            const msgId = messagelist[i]

            const item = {
                msgId: msgId
            }

            let j;
            for (j = i; j < messagelistModel.count; j++) {
                if (messagelistModel.get(j).msgId == msgId) {
                    messagelistModel.move(j, i, 1)
                    messagelistModel.set(i, item)
                    break
                }
            }

            if (j == messagelistModel.count) {
                messagelistModel.insert(i, item)
            }
        }

        if (messagelistModel.count > messagelist.length) {
            messagelistModel.remove(messagelist.length,
                                    messagelistModel.count - messagelist.length)
        }
    }

    ListModel {
        id: messagelistModel
    }

    Connections {
        target: chatPage.eventEmitter

        function onChatModified() {
            console.log("CHAT MODIFIED!")
            chatPage.chat = context.getChat(chatId)
        }
        function onIncomingMessage(accountId, chatId, msgId) {
            console.log("Incoming message for chat " + chatId)

            if (chatId == chatPage.chatId) {
                chatPage.updateMessagelist()
            }
        }
        function onMessagesChanged(accountId, chatId, msgId) {
            console.log("Messages changed for chat " + chatId)

            if (chatId == chatPage.chatId || chatId == 0) {
                chatPage.updateMessagelist()
            }
        }
    }

    Component.onCompleted: {
        chatPage.updateMessagelist()
    }

    background: Rectangle {
        color: Kirigami.Theme.alternateBackgroundColor
        anchors.fill: parent
    }

    ListView {
        id: messageListView

        anchors.fill: parent
        spacing: Kirigami.Units.largeSpacing

        model: messagelistModel

        /*
         * Messages are laid out bottom to top, because their height
         * is not known in advance.
         *
         * Attempts to lay out messages top to bottom and scroll to the
         * bottom of the list with ListView.positionViewAtEnd() result in
         * imprecise scrollbar position, because this method estimates
         * item height from the height of currently visible messages.
         */
        verticalLayoutDirection: ListView.BottomToTop

        delegate: Message {
            message: chatPage.context.getMessage(msgId)
            context: chatPage.context
            width: ListView.view.width
        }
    }

    footer: ComposePane {
        context: chatPage.context
        chatId: chatPage.chatId

        Layout.fillWidth: true
        visible: chatPage.chat && chatPage.chat.canSend
    }
}