diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index 2470805..77d3830 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -26,6 +26,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/components/AudioPreview.qml \ qml/components/DocumentPreview.qml \ qml/components/ImagePreview.qml \ + qml/components/InReplyToRow.qml \ qml/js/functions.js \ qml/pages/ChatPage.qml \ qml/pages/CoverPage.qml \ diff --git a/qml/components/InReplyToRow.qml b/qml/components/InReplyToRow.qml new file mode 100644 index 0000000..33d87e8 --- /dev/null +++ b/qml/components/InReplyToRow.qml @@ -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 . +*/ +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(/\]+\/\>/g, ""); + } + } + } + } + +} diff --git a/qml/pages/ChatPage.qml b/qml/pages/ChatPage.qml index 3137cbc..a74dab3 100644 --- a/qml/pages/ChatPage.qml +++ b/qml/pages/ChatPage.qml @@ -239,7 +239,7 @@ Page { id: chatView 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 visible: count > 0 @@ -276,6 +276,16 @@ Page { property variant myMessage: display 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 { id: messageTextRow spacing: Theme.paddingSmall @@ -338,74 +348,8 @@ Page { visible: ( chatPage.isBasicGroup || chatPage.isSuperGroup ) && !chatPage.isChannel } - Row { - id: inReplyToRow - 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(/\]+\/\>/g, ""); - } - } - } - } - + InReplyToRow { + originalMessageId: display.reply_to_message_id } Text { @@ -495,41 +439,63 @@ Page { VerticalScrollDecorator {} } - Row { - id: newMessageRow - width: parent.width - Theme.horizontalPageMargin - height: sendMessageColumn.height + ( 2 * Theme.paddingLarge ) - anchors.left: parent.left + Column { + id: newMessageColumn spacing: Theme.paddingMedium - Column { - id: sendMessageColumn - width: parent.width - Theme.fontSizeMedium - ( 2 * Theme.paddingMedium ) - anchors.verticalCenter: parent.verticalCenter - TextArea { - id: newMessageTextField - width: parent.width - font.pixelSize: Theme.fontSizeSmall - placeholderText: qsTr("Your message") - labelVisible: false - } + width: parent.width - ( 2 * Theme.horizontalPageMargin ) + anchors.horizontalCenter: parent.horizontalCenter + + property string replyToMessageId: "0" + + InReplyToRow { + originalMessageId: newMessageColumn.replyToMessageId + anchors.horizontalCenter: parent.horizontalCenter } - Column { - width: Theme.fontSizeMedium - 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); - newMessageTextField.text = ""; - newMessageTextField.focus = false; + Row { + id: newMessageRow + width: parent.width + height: sendMessageColumn.height + ( 2 * Theme.paddingLarge ) + anchors.horizontalCenter: parent.horizontalCenter + spacing: Theme.paddingMedium + + Column { + id: sendMessageColumn + width: parent.width - newMessageSendButton.width - Theme.paddingMedium + anchors.verticalCenter: parent.verticalCenter + 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; + } } } } + } + } } diff --git a/src/tdlibwrapper.cpp b/src/tdlibwrapper.cpp index 1c5f5a6..ec245ad 100644 --- a/src/tdlibwrapper.cpp +++ b/src/tdlibwrapper.cpp @@ -187,12 +187,15 @@ void TDLibWrapper::viewMessage(const QString &chatId, const QString &messageId) 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; requestObject.insert("@type", "sendMessage"); requestObject.insert("chat_id", chatId); + if (replyToMessageId != "0") { + requestObject.insert("reply_to_message_id", replyToMessageId); + } QVariantMap inputMessageContent; inputMessageContent.insert("@type", "inputMessageText"); QVariantMap formattedText; diff --git a/src/tdlibwrapper.h b/src/tdlibwrapper.h index 7124590..880d3a7 100644 --- a/src/tdlibwrapper.h +++ b/src/tdlibwrapper.h @@ -81,7 +81,7 @@ public: 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 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); signals: diff --git a/translations/harbour-fernschreiber-de.ts b/translations/harbour-fernschreiber-de.ts index c7cbb32..69ffccf 100644 --- a/translations/harbour-fernschreiber-de.ts +++ b/translations/harbour-fernschreiber-de.ts @@ -145,6 +145,10 @@ You + + Reply to Message + + CoverPage @@ -215,6 +219,13 @@ + + InReplyToRow + + You + + + InitializationPage diff --git a/translations/harbour-fernschreiber.ts b/translations/harbour-fernschreiber.ts index c7cbb32..69ffccf 100644 --- a/translations/harbour-fernschreiber.ts +++ b/translations/harbour-fernschreiber.ts @@ -145,6 +145,10 @@ You + + Reply to Message + + CoverPage @@ -215,6 +219,13 @@ + + InReplyToRow + + You + + + InitializationPage