aboutsummaryrefslogtreecommitdiff
path: root/qml/ChatPage.qml
blob: b7548bd4bae0ce5eaf46fabde819fbf858fe1592 (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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.Page {
    id: chatPage

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

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

    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)
        }
    }

    signal chatModified()
    onChatModified: {
        console.log("CHAT MODIFIED!")
    }

    signal incomingEvent()
    onIncomingEvent: {
        console.log("EVENT!")
    }

    ListModel {
        id: messagelistModel
    }

    signal incomingMessage()
    onIncomingMessage: {
        console.log("Incoming message for chat " + chatId)

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

    signal messagesChanged(var accountId, int chatId, int msgId)
    onMessagesChanged: {
        console.log("Messages changed for chat " + chatId)

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

    Component.onCompleted: {
        eventEmitter.onIncomingEvent.connect(incomingEvent)
        eventEmitter.onChatModified.connect(chatModified)
        eventEmitter.onIncomingMessage.connect(incomingMessage)
        eventEmitter.onMessagesChanged.connect(messagesChanged)

        updateMessagelist()
    }

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

    Component {
        id: composePane

        Pane {
            Layout.fillWidth: true

            RowLayout {
                width: parent.width

                TextField {
                    id: messageField

                    Layout.fillWidth: true
                    placeholderText: qsTr("Message")
                    wrapMode: TextArea.Wrap
                    selectByMouse: true
                }

                Button {
                    id: sendButton

                    icon.name: "document-send"
                    text: qsTr("Send")
                    enabled: messageField.length > 0
                    onClicked: {
                        context.sendTextMessage(chatId, messageField.text)
                        messageField.text = ""
                    }
                }
            }
        }
    }

    ListView {
        id: messageListView

        anchors.fill: parent
        spacing: 10

        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: context.getMessage(msgId)}

        ScrollBar.vertical: ScrollBar {}
    }

    footer: Loader {
        sourceComponent: composePane
        Layout.fillWidth: true
        visible: chat && chat.canSend
    }
}