Add possibility to send replies

This commit is contained in:
Sebastian J. Wolf 2020-08-28 17:40:25 +02:00
parent ecf4c859e8
commit 402c0ed671
7 changed files with 187 additions and 100 deletions

View file

@ -26,6 +26,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \
qml/components/AudioPreview.qml \ qml/components/AudioPreview.qml \
qml/components/DocumentPreview.qml \ qml/components/DocumentPreview.qml \
qml/components/ImagePreview.qml \ qml/components/ImagePreview.qml \
qml/components/InReplyToRow.qml \
qml/js/functions.js \ qml/js/functions.js \
qml/pages/ChatPage.qml \ qml/pages/ChatPage.qml \
qml/pages/CoverPage.qml \ qml/pages/CoverPage.qml \

View file

@ -0,0 +1,95 @@
/*
Copyright (C) 2020 Sebastian J. Wolf
This file is part of Fernschreiber.
Fernschreiber is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Fernschreiber is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtMultimedia 5.0
import "../components"
import "../js/functions.js" as Functions
import "../js/twemoji.js" as Emoji
Row {
id: inReplyToRow
spacing: Theme.paddingSmall
width: parent.width
visible: originalMessageId !== "0"
property string originalMessageId: "0";
property variant inReplyToMessage;
onOriginalMessageIdChanged: {
if (originalMessageId !== "0") {
tdLibWrapper.getMessage(chatInformation.id, originalMessageId);
}
}
Connections {
target: tdLibWrapper
onReceivedMessage: {
if (messageId === originalMessageId) {
inReplyToRow.inReplyToMessage = message;
inReplyToUserText.text = (inReplyToRow.inReplyToMessage.sender_user_id !== chatPage.myUserId) ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(inReplyToRow.inReplyToMessage.sender_user_id)), inReplyToUserText.font.pixelSize) : qsTr("You");
inReplyToMessageText.text = Emoji.emojify(Functions.getMessageText(inReplyToRow.inReplyToMessage, true), inReplyToMessageText.font.pixelSize);
}
}
}
Rectangle {
id: inReplyToMessageRectangle
height: inReplyToMessageColumn.height
width: Theme.paddingSmall
color: Theme.secondaryHighlightColor
border.width: 0
}
Column {
id: inReplyToMessageColumn
spacing: Theme.paddingSmall
width: parent.width - Theme.paddingSmall - inReplyToMessageRectangle.width
Text {
id: inReplyToUserText
width: parent.width
font.pixelSize: Theme.fontSizeExtraSmall
font.weight: Font.ExtraBold
color: Theme.primaryColor
maximumLineCount: 1
elide: Text.ElideRight
textFormat: Text.StyledText
horizontalAlignment: Text.AlignLeft
}
Text {
id: inReplyToMessageText
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
width: parent.width
elide: Text.ElideRight
textFormat: Text.StyledText
onTruncatedChanged: {
// There is obviously a bug in QML in truncating text with images.
// We simply remove Emojis then...
if (truncated) {
text = text.replace(/\<img [^>]+\/\>/g, "");
}
}
}
}
}

View file

@ -239,7 +239,7 @@ Page {
id: chatView id: chatView
width: parent.width width: parent.width
height: parent.height - ( 2 * Theme.paddingMedium ) - headerRow.height - newMessageRow.height height: parent.height - ( 2 * Theme.paddingMedium ) - headerRow.height - newMessageColumn.height
clip: true clip: true
visible: count > 0 visible: count > 0
@ -276,6 +276,16 @@ Page {
property variant myMessage: display property variant myMessage: display
property variant userInformation: tdLibWrapper.getUserInformation(display.sender_user_id) property variant userInformation: tdLibWrapper.getUserInformation(display.sender_user_id)
menu: ContextMenu {
MenuItem {
onClicked: {
newMessageColumn.replyToMessageId = display.id;
sendMessageColumn.focus = true;
}
text: qsTr("Reply to Message")
}
}
Row { Row {
id: messageTextRow id: messageTextRow
spacing: Theme.paddingSmall spacing: Theme.paddingSmall
@ -338,74 +348,8 @@ Page {
visible: ( chatPage.isBasicGroup || chatPage.isSuperGroup ) && !chatPage.isChannel visible: ( chatPage.isBasicGroup || chatPage.isSuperGroup ) && !chatPage.isChannel
} }
Row { InReplyToRow {
id: inReplyToRow originalMessageId: display.reply_to_message_id
spacing: Theme.paddingSmall
visible: display.reply_to_message_id !== 0
width: parent.width
property variant inReplyToMessage;
Component.onCompleted: {
if (visible) {
tdLibWrapper.getMessage(chatInformation.id, display.reply_to_message_id);
}
}
Connections {
target: tdLibWrapper
onReceivedMessage: {
if (messageId === display.reply_to_message_id.toString()) {
inReplyToRow.inReplyToMessage = message;
inReplyToUserText.text = (inReplyToRow.inReplyToMessage.sender_user_id !== chatPage.myUserId) ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(inReplyToRow.inReplyToMessage.sender_user_id)), inReplyToUserText.font.pixelSize) : qsTr("You");
inReplyToMessageText.text = Emoji.emojify(Functions.getMessageText(inReplyToRow.inReplyToMessage, true), inReplyToMessageText.font.pixelSize);
}
}
}
Rectangle {
id: inReplyToMessageRectangle
height: inReplyToMessageColumn.height
width: Theme.paddingSmall
color: Theme.secondaryHighlightColor
border.width: 0
}
Column {
id: inReplyToMessageColumn
spacing: Theme.paddingSmall
width: parent.width - Theme.paddingSmall - inReplyToMessageRectangle.width
Text {
id: inReplyToUserText
width: parent.width
font.pixelSize: Theme.fontSizeExtraSmall
font.weight: Font.ExtraBold
color: Theme.primaryColor
maximumLineCount: 1
elide: Text.ElideRight
textFormat: Text.StyledText
horizontalAlignment: Text.AlignLeft
}
Text {
id: inReplyToMessageText
font.pixelSize: Theme.fontSizeExtraSmall
color: Theme.primaryColor
width: parent.width
elide: Text.ElideRight
textFormat: Text.StyledText
onTruncatedChanged: {
// There is obviously a bug in QML in truncating text with images.
// We simply remove Emojis then...
if (truncated) {
text = text.replace(/\<img [^>]+\/\>/g, "");
}
}
}
}
} }
Text { Text {
@ -495,41 +439,63 @@ Page {
VerticalScrollDecorator {} VerticalScrollDecorator {}
} }
Row { Column {
id: newMessageRow id: newMessageColumn
width: parent.width - Theme.horizontalPageMargin
height: sendMessageColumn.height + ( 2 * Theme.paddingLarge )
anchors.left: parent.left
spacing: Theme.paddingMedium spacing: Theme.paddingMedium
Column { width: parent.width - ( 2 * Theme.horizontalPageMargin )
id: sendMessageColumn anchors.horizontalCenter: parent.horizontalCenter
width: parent.width - Theme.fontSizeMedium - ( 2 * Theme.paddingMedium )
anchors.verticalCenter: parent.verticalCenter property string replyToMessageId: "0"
TextArea {
id: newMessageTextField InReplyToRow {
width: parent.width originalMessageId: newMessageColumn.replyToMessageId
font.pixelSize: Theme.fontSizeSmall anchors.horizontalCenter: parent.horizontalCenter
placeholderText: qsTr("Your message")
labelVisible: false
}
} }
Column { Row {
width: Theme.fontSizeMedium id: newMessageRow
anchors.bottom: parent.bottom width: parent.width
anchors.bottomMargin: Theme.paddingLarge height: sendMessageColumn.height + ( 2 * Theme.paddingLarge )
IconButton { anchors.horizontalCenter: parent.horizontalCenter
id: newMessageSendButton spacing: Theme.paddingMedium
icon.source: "image://theme/icon-m-chat"
anchors.horizontalCenter: parent.horizontalCenter Column {
onClicked: { id: sendMessageColumn
tdLibWrapper.sendTextMessage(chatInformation.id, newMessageTextField.text); width: parent.width - newMessageSendButton.width - Theme.paddingMedium
newMessageTextField.text = ""; anchors.verticalCenter: parent.verticalCenter
newMessageTextField.focus = false; TextArea {
id: newMessageTextField
width: parent.width
font.pixelSize: Theme.fontSizeSmall
placeholderText: qsTr("Your message")
labelVisible: false
onFocusChanged: {
if (!focus) {
newMessageColumn.replyToMessageId = "0";
}
}
}
}
Column {
width: newMessageSendButton.width
anchors.bottom: parent.bottom
anchors.bottomMargin: Theme.paddingLarge
IconButton {
id: newMessageSendButton
icon.source: "image://theme/icon-m-chat"
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
tdLibWrapper.sendTextMessage(chatInformation.id, newMessageTextField.text, newMessageColumn.replyToMessageId);
newMessageTextField.text = "";
newMessageTextField.focus = false;
}
} }
} }
} }
} }
} }
} }

View file

@ -187,12 +187,15 @@ void TDLibWrapper::viewMessage(const QString &chatId, const QString &messageId)
this->sendRequest(requestObject); this->sendRequest(requestObject);
} }
void TDLibWrapper::sendTextMessage(const QString &chatId, const QString &message) void TDLibWrapper::sendTextMessage(const QString &chatId, const QString &message, const QString &replyToMessageId)
{ {
qDebug() << "[TDLibWrapper] Sending text message " << chatId << message; qDebug() << "[TDLibWrapper] Sending text message " << chatId << message << replyToMessageId;
QVariantMap requestObject; QVariantMap requestObject;
requestObject.insert("@type", "sendMessage"); requestObject.insert("@type", "sendMessage");
requestObject.insert("chat_id", chatId); requestObject.insert("chat_id", chatId);
if (replyToMessageId != "0") {
requestObject.insert("reply_to_message_id", replyToMessageId);
}
QVariantMap inputMessageContent; QVariantMap inputMessageContent;
inputMessageContent.insert("@type", "inputMessageText"); inputMessageContent.insert("@type", "inputMessageText");
QVariantMap formattedText; QVariantMap formattedText;

View file

@ -81,7 +81,7 @@ public:
Q_INVOKABLE void closeChat(const QString &chatId); Q_INVOKABLE void closeChat(const QString &chatId);
Q_INVOKABLE void getChatHistory(const QString &chatId, const qlonglong &fromMessageId = 0, const int &offset = 0, const int &limit = 50, const bool &onlyLocal = false); Q_INVOKABLE void getChatHistory(const QString &chatId, const qlonglong &fromMessageId = 0, const int &offset = 0, const int &limit = 50, const bool &onlyLocal = false);
Q_INVOKABLE void viewMessage(const QString &chatId, const QString &messageId); Q_INVOKABLE void viewMessage(const QString &chatId, const QString &messageId);
Q_INVOKABLE void sendTextMessage(const QString &chatId, const QString &message); Q_INVOKABLE void sendTextMessage(const QString &chatId, const QString &message, const QString &replyToMessageId = "0");
Q_INVOKABLE void getMessage(const QString &chatId, const QString &messageId); Q_INVOKABLE void getMessage(const QString &chatId, const QString &messageId);
signals: signals:

View file

@ -145,6 +145,10 @@
<source>You</source> <source>You</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Reply to Message</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -215,6 +219,13 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>InReplyToRow</name>
<message>
<source>You</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>InitializationPage</name> <name>InitializationPage</name>
<message> <message>

View file

@ -145,6 +145,10 @@
<source>You</source> <source>You</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Reply to Message</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>CoverPage</name> <name>CoverPage</name>
@ -215,6 +219,13 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>InReplyToRow</name>
<message>
<source>You</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>InitializationPage</name> <name>InitializationPage</name>
<message> <message>