diff --git a/src/chatbar/SendBar.qml b/src/chatbar/SendBar.qml index 22f8ffcc7..c49116fc3 100644 --- a/src/chatbar/SendBar.qml +++ b/src/chatbar/SendBar.qml @@ -208,6 +208,7 @@ RowLayout { icon.name: "document-send" text: i18nc("@action:button", "Send message") display: QQC2.AbstractButton.IconOnly + enabled: root.contentModel.hasAnyContent onClicked: root.contentModel.postMessage(); QQC2.ToolTip.visible: hovered diff --git a/src/messagecontent/models/chatbarmessagecontentmodel.cpp b/src/messagecontent/models/chatbarmessagecontentmodel.cpp index 3a09ac72f..8933cc0b1 100644 --- a/src/messagecontent/models/chatbarmessagecontentmodel.cpp +++ b/src/messagecontent/models/chatbarmessagecontentmodel.cpp @@ -60,6 +60,9 @@ ChatBarMessageContentModel::ChatBarMessageContentModel(QObject *parent) initializeFromCache(); }); connect(m_markdownHelper, &ChatMarkdownHelper::unhandledBlockFormat, this, &ChatBarMessageContentModel::insertStyleAtCursor); + connect(this, &ChatBarMessageContentModel::modelReset, this, &ChatBarMessageContentModel::hasAnyContentChanged); + connect(this, &ChatBarMessageContentModel::rowsInserted, this, &ChatBarMessageContentModel::hasAnyContentChanged); + connect(this, &ChatBarMessageContentModel::rowsRemoved, this, &ChatBarMessageContentModel::hasAnyContentChanged); connectCache(); connectKeyHelper(); @@ -302,6 +305,7 @@ void ChatBarMessageContentModel::connectTextItem(ChatTextItemHelper *chattextite connect(chattextitemhelper, &ChatTextItemHelper::cleared, this, [this](ChatTextItemHelper *helper) { removeComponent(helper); }); + connect(chattextitemhelper, &ChatTextItemHelper::contentsChanged, this, &ChatBarMessageContentModel::hasAnyContentChanged); } ChatTextItemHelper *ChatBarMessageContentModel::textItemForComponent(const MessageComponent &component) const @@ -664,6 +668,28 @@ void ChatBarMessageContentModel::postMessage() refocusCurrentComponent(); } +bool ChatBarMessageContentModel::hasAnyContent() const +{ + // Shouldn't really be possible, but is true. + if (m_components.empty()) { + return false; + } + + // If there's more than one component naturally there is content. + if (m_components.size() > 1) { + return true; + } + + // There's usually at a minimum a TextComponent, we need to check if it's empty. + if (const auto textItem = textItemForComponent(m_components.constFirst())) { + if (textItem->isEmpty()) { + return false; + } + } + + return true; +} + std::optional ChatBarMessageContentModel::getReplyEventId() { if (!m_room) { diff --git a/src/messagecontent/models/chatbarmessagecontentmodel.h b/src/messagecontent/models/chatbarmessagecontentmodel.h index 7fa3d989a..24f9f0480 100644 --- a/src/messagecontent/models/chatbarmessagecontentmodel.h +++ b/src/messagecontent/models/chatbarmessagecontentmodel.h @@ -77,6 +77,11 @@ class ChatBarMessageContentModel : public MessageContentModel */ Q_PROPERTY(bool sendMessageWithEnter READ sendMessageWithEnter WRITE setSendMessageWithEnter NOTIFY sendMessageWithEnterChanged) + /** + * @brief Whether the model has any content, ideal for checking if there is anything to send. + */ + Q_PROPERTY(bool hasAnyContent READ hasAnyContent NOTIFY hasAnyContentChanged) + public: explicit ChatBarMessageContentModel(QObject *parent = nullptr); @@ -106,12 +111,15 @@ public: Q_INVOKABLE void postMessage(); + bool hasAnyContent() const; + Q_SIGNALS: void typeChanged(ChatBarType::Type oldType, ChatBarType::Type newType); void focusRowChanged(); void hasRichFormattingChanged(); void hasAttachmentChanged(); void sendMessageWithEnterChanged(); + void hasAnyContentChanged(); private: ChatBarType::Type m_type = ChatBarType::None;