First chat message list :)

This commit is contained in:
Sebastian J. Wolf 2020-08-22 21:43:20 +02:00
parent 2750764de9
commit ca7abb2a2f
6 changed files with 218 additions and 28 deletions

View file

@ -31,10 +31,19 @@ function getSimpleMessageText(message) {
return qsTr("Sticker: %1").arg(message.content.sticker.emoji); return qsTr("Sticker: %1").arg(message.content.sticker.emoji);
} }
if (message.content['@type'] === 'messagePhoto') { if (message.content['@type'] === 'messagePhoto') {
return (typeof message.content.caption) ? qsTr("Picture: %1").arg(message.content.caption.text) : qsTr("Picture"); return (message.content.caption.text !== "") ? qsTr("Picture: %1").arg(message.content.caption.text) : qsTr("shared a picture");
} }
if (message.content['@type'] === 'messageVideo') { if (message.content['@type'] === 'messageVideo') {
return (typeof message.content.caption) ? qsTr("Video: %1").arg(message.content.caption.text) : qsTr("Video"); return (message.content.caption.text !== "") ? qsTr("Video: %1").arg(message.content.caption.text) : qsTr("shared a video");
}
if (message.content['@type'] === 'messageAudio') {
return (message.content.caption.text !== "") ? qsTr("Audio: %1").arg(message.content.caption.text) : qsTr("shared an audio");
}
if (message.content['@type'] === 'messageVoiceNote') {
return (message.content.caption.text !== "") ? qsTr("Voice Note: %1").arg(message.content.caption.text) : qsTr("shared a voice note");
}
if (message.content['@type'] === 'messageLocation') {
return qsTr("shared their location");
} }
if (message.content['@type'] === 'messageContactRegistered') { if (message.content['@type'] === 'messageContactRegistered') {
return qsTr("has registered with Telegram"); return qsTr("has registered with Telegram");

View file

@ -30,6 +30,7 @@ Page {
allowedOrientations: Orientation.All allowedOrientations: Orientation.All
property bool loading: true; property bool loading: true;
property int myUserId: tdLibWrapper.getUserInformation().id;
property variant chatInformation; property variant chatInformation;
property bool isPrivateChat: false; property bool isPrivateChat: false;
property bool isBasicGroup: false; property bool isBasicGroup: false;
@ -84,6 +85,7 @@ Page {
function initializePage() { function initializePage() {
tdLibWrapper.openChat(chatInformation.id); tdLibWrapper.openChat(chatInformation.id);
chatModel.initialize(chatInformation.id);
var chatType = chatInformation.type['@type']; var chatType = chatInformation.type['@type'];
isPrivateChat = ( chatType === "chatTypePrivate" ); isPrivateChat = ( chatType === "chatTypePrivate" );
isBasicGroup = ( chatType === "chatTypeBasicGroup" ); isBasicGroup = ( chatType === "chatTypeBasicGroup" );
@ -144,6 +146,13 @@ Page {
} }
} }
Connections {
target: chatModel
onMessagesReceived: {
chatView.positionViewAtEnd();
}
}
Timer { Timer {
id: chatContactTimeUpdater id: chatContactTimeUpdater
interval: 60000 interval: 60000
@ -170,7 +179,7 @@ Page {
Row { Row {
id: headerRow id: headerRow
width: parent.width - (3 * Theme.horizontalPageMargin) width: parent.width - (3 * Theme.horizontalPageMargin)
height: chatOverviewColumn.height + Theme.horizontalPageMargin height: chatOverviewColumn.height + ( 2 * Theme.horizontalPageMargin )
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.paddingMedium spacing: Theme.paddingMedium
@ -180,13 +189,13 @@ Page {
replacementStringHint: chatNameText.text replacementStringHint: chatNameText.text
width: chatOverviewColumn.height width: chatOverviewColumn.height
height: chatOverviewColumn.height height: chatOverviewColumn.height
anchors.bottom: parent.bottom anchors.verticalCenter: parent.verticalCenter
} }
Column { Column {
id: chatOverviewColumn id: chatOverviewColumn
width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium width: parent.width - chatPictureThumbnail.width - Theme.paddingMedium
anchors.bottom: parent.bottom anchors.verticalCenter: parent.verticalCenter
Text { Text {
id: chatNameText id: chatNameText
text: chatInformation.title !== "" ? Emoji.emojify(chatInformation.title, font.pixelSize) : qsTr("Unknown") text: chatInformation.title !== "" ? Emoji.emojify(chatInformation.title, font.pixelSize) : qsTr("Unknown")
@ -228,16 +237,72 @@ Page {
height: parent.height - ( 2 * Theme.paddingMedium ) - headerRow.height - newMessageRow.height height: parent.height - ( 2 * Theme.paddingMedium ) - headerRow.height - newMessageRow.height
clip: true clip: true
// visible: count > 0 visible: count > 0
// model: chatListModel model: chatModel
delegate: ListItem { delegate: ListItem {
id: chatItem id: messageListItem
contentHeight: messageTextItem.height + Theme.paddingMedium
//contentHeight: chatListRow.height + chatListSeparator.height + 2 * Theme.paddingMedium
contentWidth: parent.width contentWidth: parent.width
Column {
id: messageTextItem
spacing: Theme.paddingSmall
width: parent.width
height: messageText.height + messageDateText.height + Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
Text {
anchors {
left: parent.left
leftMargin: (chatPage.myUserId === display.sender_user_id) ? 4 * Theme.horizontalPageMargin : Theme.horizontalPageMargin
right: parent.right
rightMargin: (chatPage.myUserId === display.sender_user_id) ? Theme.horizontalPageMargin : 4 * Theme.horizontalPageMargin
}
id: messageText
text: Emoji.emojify(Functions.getSimpleMessageText(display), font.pixelSize)
font.pixelSize: Theme.fontSizeSmall
color: chatPage.myUserId === display.sender_user_id ? Theme.highlightColor : Theme.primaryColor
wrapMode: Text.Wrap
textFormat: Text.StyledText
onLinkActivated: {
// Functions.handleLink(link);
}
horizontalAlignment: (chatPage.myUserId === display.sender_user_id) ? Text.AlignRight : Text.AlignLeft
linkColor: Theme.highlightColor
}
Timer {
id: messageDateUpdater
interval: 60000
running: true
repeat: true
onTriggered: {
messageDateText.text = Functions.getDateTimeElapsed(display.date);
}
}
Text {
anchors {
left: parent.left
leftMargin: (chatPage.myUserId === display.sender_user_id) ? 4 * Theme.horizontalPageMargin : Theme.horizontalPageMargin
right: parent.right
rightMargin: (chatPage.myUserId === display.sender_user_id) ? Theme.horizontalPageMargin : 4 * Theme.horizontalPageMargin
}
id: messageDateText
text: Functions.getDateTimeElapsed(display.date)
font.pixelSize: Theme.fontSizeTiny
color: chatPage.myUserId === display.sender_user_id ? Theme.highlightColor : Theme.primaryColor
horizontalAlignment: (chatPage.myUserId === display.sender_user_id) ? Text.AlignRight : Text.AlignLeft
}
}
} }
VerticalScrollDecorator {} VerticalScrollDecorator {}

View file

@ -1,8 +1,12 @@
#include "chatmodel.h" #include "chatmodel.h"
#include <QListIterator>
ChatModel::ChatModel(TDLibWrapper *tdLibWrapper) ChatModel::ChatModel(TDLibWrapper *tdLibWrapper)
{ {
this->tdLibWrapper = tdLibWrapper; this->tdLibWrapper = tdLibWrapper;
this->inReload = false;
connect(this->tdLibWrapper, SIGNAL(messagesReceived(QVariantList)), this, SLOT(handleMessagesReceived(QVariantList)));
} }
ChatModel::~ChatModel() ChatModel::~ChatModel()
@ -27,7 +31,9 @@ bool ChatModel::insertRows(int row, int count, const QModelIndex &parent)
{ {
qDebug() << "[ChatModel] Inserting at " << row << ", row count: " << count; qDebug() << "[ChatModel] Inserting at " << row << ", row count: " << count;
beginInsertRows(parent, row, row + count - 1); beginInsertRows(parent, row, row + count - 1);
this->messages.insert(row, this->messagesToBeAdded); for (int i = 0; i < count; i++) {
this->messages.insert(row + i, this->messagesToBeAdded.at(i));
}
this->messageIndexMap.clear(); this->messageIndexMap.clear();
for (int i = 0; i < this->messages.size(); i++) { for (int i = 0; i < this->messages.size(); i++) {
this->messageIndexMap.insert(this->messages.at(i).toMap().value("id").toString(), i); this->messageIndexMap.insert(this->messages.at(i).toMap().value("id").toString(), i);
@ -35,3 +41,63 @@ bool ChatModel::insertRows(int row, int count, const QModelIndex &parent)
endInsertRows(); endInsertRows();
return true; return true;
} }
void ChatModel::initialize(const QString &chatId)
{
this->chatId = chatId;
this->messages.clear();
this->messageIndexMap.clear();
this->messagesToBeAdded.clear();
}
bool compareMessages(const QVariant &message1, const QVariant &message2)
{
QVariantMap messageMap1 = message1.toMap();
QVariantMap messageMap2 = message2.toMap();
if (messageMap1.value("id").toLongLong() < messageMap2.value("id").toLongLong()) {
return true;
} else {
return false;
}
}
void ChatModel::handleMessagesReceived(const QVariantList &messages)
{
qDebug() << "[ChatModel] Receiving new messages :)";
this->messagesMutex.lock();
this->messagesToBeAdded.clear();
QListIterator<QVariant> messagesIterator(messages);
while (messagesIterator.hasNext()) {
QVariantMap currentMessage = messagesIterator.next().toMap();
if (currentMessage.value("chat_id").toString() == this->chatId) {
this->messagesToBeAdded.append(currentMessage);
}
}
std::sort(this->messagesToBeAdded.begin(), this->messagesToBeAdded.end(), compareMessages);
if (this->messages.isEmpty()) {
beginResetModel();
this->messages.append(this->messagesToBeAdded);
endResetModel();
} else {
// There is only an append or a prepend, tertium non datur! (probably ;))
if (this->messages.last().toMap().value("id").toLongLong() < this->messagesToBeAdded.first().toMap().value("id").toLongLong()) {
// Append
this->insertRows(rowCount(QModelIndex()), this->messagesToBeAdded.size());
} else {
// Prepend
this->insertRows(0, this->messagesToBeAdded.size());
}
}
this->messagesMutex.unlock();
// First call only returns one message, we need to get a little more than that...
if (this->messagesToBeAdded.size() == 1 && !this->inReload) {
qDebug() << "[ChatModel] Only one message received in first call, loading more...";
this->inReload = true;
this->tdLibWrapper->getChatHistory(this->chatId, this->messagesToBeAdded.first().toMap().value("id").toLongLong());
} else {
qDebug() << "[ChatModel] Messages loaded, notifying chat UI...";
this->inReload = false;
emit messagesReceived();
}
}

View file

@ -17,13 +17,23 @@ public:
virtual QVariant data(const QModelIndex &index, int role) const override; virtual QVariant data(const QModelIndex &index, int role) const override;
virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
Q_INVOKABLE void initialize(const QString &chatId);
signals:
void messagesReceived();
public slots:
void handleMessagesReceived(const QVariantList &messages);
private: private:
TDLibWrapper *tdLibWrapper; TDLibWrapper *tdLibWrapper;
QVariantList messages; QVariantList messages;
QVariantList messagesToBeAdded; QVariantList messagesToBeAdded;
QVariantMap messageIndexMap; QVariantMap messageIndexMap;
QMutex chatListMutex; QMutex messagesMutex;
QString chatId;
bool inReload;
}; };
#endif // CHATMODEL_H #endif // CHATMODEL_H

View file

@ -258,10 +258,6 @@
<source>Video: %1</source> <source>Video: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Video</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>has registered with Telegram</source> <source>has registered with Telegram</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -270,10 +266,6 @@
<source>Picture: %1</source> <source>Picture: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Picture</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Sticker: %1</source> <source>Sticker: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -290,5 +282,33 @@
<source>left this chat.</source> <source>left this chat.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Audio: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Voice Note: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared a picture</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared a video</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared an audio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared a voice note</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared their location</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -258,10 +258,6 @@
<source>Video: %1</source> <source>Video: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Video</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>has registered with Telegram</source> <source>has registered with Telegram</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -270,10 +266,6 @@
<source>Picture: %1</source> <source>Picture: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Picture</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Sticker: %1</source> <source>Sticker: %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -290,5 +282,33 @@
<source>left this chat.</source> <source>left this chat.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Audio: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Voice Note: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared a picture</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared a video</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared an audio</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared a voice note</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shared their location</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
</TS> </TS>