diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 2b537dc3..97121d73 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -190,7 +190,7 @@ Item { Rectangle { id: chatFooter - height: Math.max(16, typingDisplay.height) + height: Math.max(Math.max(16, typingDisplay.height), replyPopup.height) anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom @@ -210,6 +210,104 @@ Item { textFormat: Text.RichText color: colors.windowText } + + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + id: replyPopup + + visible: timelineManager.replyingEvent && chat.model + width: parent.width + // Height of child, plus margins, plus border + height: replyContent.height + 10 + 1 + color: colors.window + + // For a border on the top. + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + height: 1 + width: parent.width + color: colors.mid + } + + RowLayout { + id: replyContent + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 10 + + Column { + Layout.fillWidth: true + Layout.alignment: Qt.AlignTop + spacing: 4 + Rectangle { + width: parent.width + height: replyContainer.height + anchors.leftMargin: 10 + anchors.rightMargin: 10 + + Rectangle { + id: colorLine + height: replyContainer.height + width: 4 + color: chat.model ? chat.model.userColor(reply.modelData.userId, colors.window) : colors.window + } + + Column { + id: replyContainer + anchors.left: colorLine.right + anchors.leftMargin: 4 + width: parent.width - 8 + + Text { + id: userName + text: chat.model ? chat.model.escapeEmoji(reply.modelData.userName) : "" + color: chat.model ? chat.model.userColor(reply.modelData.userId, colors.windowText) : colors.windowText + textFormat: Text.RichText + + MouseArea { + anchors.fill: parent + onClicked: chat.model.openUserProfile(reply.modelData.userId) + cursorShape: Qt.PointingHandCursor + } + } + + MessageDelegate { + id: reply + width: parent.width + modelData: chat.model ? chat.model.getDump(timelineManager.replyingEvent) : {} + } + } + + color: { var col = chat.model ? chat.model.userColor(reply.modelData.userId, colors.window) : colors.window; col.a = 0.2; return col } + + MouseArea { + anchors.fill: parent + onClicked: chat.positionViewAtIndex(chat.model.idToIndex(timelineManager.replyingEvent), ListView.Contain) + cursorShape: Qt.PointingHandCursor + } + } + } + ImageButton { + Layout.alignment: Qt.AlignRight | Qt.AlignTop + Layout.preferredHeight: 16 + id: closeReplyButton + + image: ":/icons/icons/ui/remove-symbol.png" + ToolTip { + visible: closeReplyButton.hovered + text: qsTr("Close") + palette: colors + } + + onClicked: timelineManager.updateReplyingEvent(undefined) + } + } + } } } } diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 125e229a..30b28120 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -504,6 +504,9 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) connect(this, &ChatPage::dropToLoginPageCb, this, &ChatPage::dropToLoginPage); connect(this, &ChatPage::messageReply, text_input_, &TextInputWidget::addReply); + connect(this, &ChatPage::messageReply, this, [this](const RelatedInfo &related) { + view_manager_->updateReplyingEvent(QString::fromStdString(related.related_event)); + }); instance_ = this; } diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index b6b51980..7f5da009 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -684,7 +684,7 @@ TextInputWidget::addReply(const RelatedInfo &related) // input_->setText(QString("> %1: %2\n\n").arg(username).arg(msg)); input_->setFocus(); - input_->showReplyPopup(related); + // input_->showReplyPopup(related); auto cursor = input_->textCursor(); cursor.movePosition(QTextCursor::End); input_->setTextCursor(cursor); diff --git a/src/popups/UserMentions.h b/src/popups/UserMentions.h index d7dfc575..d3877462 100644 --- a/src/popups/UserMentions.h +++ b/src/popups/UserMentions.h @@ -47,5 +47,4 @@ private: QScrollArea *all_scroll_area_; QWidget *all_scroll_widget_; }; - } \ No newline at end of file diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 63075649..3db55366 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -24,6 +24,8 @@ class TimelineViewManager : public QObject TimelineModel *timeline MEMBER timeline_ READ activeTimeline NOTIFY activeTimelineChanged) Q_PROPERTY( bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged) + Q_PROPERTY(QString replyingEvent READ getReplyingEvent WRITE updateReplyingEvent NOTIFY + replyingEventChanged) public: TimelineViewManager(QWidget *parent = 0); @@ -43,8 +45,17 @@ signals: void updateRoomsLastMessage(QString roomid, const DescInfo &info); void activeTimelineChanged(TimelineModel *timeline); void initialSyncChanged(bool isInitialSync); + void replyingEventChanged(QString replyingEvent); public slots: + void updateReplyingEvent(const QString &replyingEvent) + { + if (this->replyingEvent_ != replyingEvent) { + this->replyingEvent_ = replyingEvent; + emit replyingEventChanged(replyingEvent_); + } + } + QString getReplyingEvent() const { return replyingEvent_; } void updateReadReceipts(const QString &room_id, const std::vector &event_ids); void initWithMessages(const std::map &msgs); @@ -97,4 +108,5 @@ private: QHash> models; TimelineModel *timeline_ = nullptr; bool isInitialSync_ = true; + QString replyingEvent_; };