diff --git a/src/spectralroom.cpp b/src/spectralroom.cpp index c4954c8..7934c2a 100644 --- a/src/spectralroom.cpp +++ b/src/spectralroom.cpp @@ -18,7 +18,8 @@ #include "utils.h" -SpectralRoom::SpectralRoom(Connection* connection, QString roomId, +SpectralRoom::SpectralRoom(Connection* connection, + QString roomId, JoinState joinState) : Room(connection, std::move(roomId), joinState) { connect(this, &SpectralRoom::notificationCountChanged, this, @@ -73,18 +74,25 @@ void SpectralRoom::chooseAndUploadFile() { void SpectralRoom::saveFileAs(QString eventId) { auto fileName = QFileDialog::getSaveFileName(Q_NULLPTR, tr("Save File as"), fileNameToDownload(eventId)); - if (!fileName.isEmpty()) downloadFile(eventId, QUrl::fromLocalFile(fileName)); + if (!fileName.isEmpty()) + downloadFile(eventId, QUrl::fromLocalFile(fileName)); } -void SpectralRoom::acceptInvitation() { connection()->joinRoom(id()); } +void SpectralRoom::acceptInvitation() { + connection()->joinRoom(id()); +} -void SpectralRoom::forget() { connection()->forgetRoom(id()); } +void SpectralRoom::forget() { + connection()->forgetRoom(id()); +} bool SpectralRoom::hasUsersTyping() { QList users = usersTyping(); - if (users.isEmpty()) return false; + if (users.isEmpty()) + return false; int count = users.length(); - if (users.contains(localUser())) count--; + if (users.contains(localUser())) + count--; return count != 0; } @@ -104,7 +112,8 @@ void SpectralRoom::sendTypingNotification(bool isTyping) { } QString SpectralRoom::lastEvent() { - if (timelineSize() == 0) return ""; + if (timelineSize() == 0) + return ""; const RoomEvent* lastEvent = messageEvents().rbegin()->get(); return user(lastEvent->senderId())->displayname() + ": " + utils::removeReply(eventToString(*lastEvent)); @@ -116,7 +125,8 @@ bool SpectralRoom::isEventHighlighted(const RoomEvent* e) const { void SpectralRoom::checkForHighlights(const QMatrixClient::TimelineItem& ti) { auto localUserId = localUser()->id(); - if (ti->senderId() == localUserId) return; + if (ti->senderId() == localUserId) + return; if (auto* e = ti.viewAs()) { const auto& text = e->plainBody(); if (text.contains(localUserId) || @@ -142,8 +152,10 @@ void SpectralRoom::countChanged() { } } -void SpectralRoom::sendReply(QString userId, QString eventId, - QString replyContent, QString sendContent) { +void SpectralRoom::sendReply(QString userId, + QString eventId, + QString replyContent, + QString sendContent) { QJsonObject json{ {"msgtype", "m.text"}, {"body", "> <" + userId + "> " + replyContent + "\n\n" + sendContent}, @@ -159,7 +171,8 @@ void SpectralRoom::sendReply(QString userId, QString eventId, } QDateTime SpectralRoom::lastActiveTime() { - if (timelineSize() == 0) return QDateTime(); + if (timelineSize() == 0) + return QDateTime(); return messageEvents().rbegin()->get()->timestamp(); } @@ -205,15 +218,19 @@ QVariantList SpectralRoom::getUsers(const QString& prefix) { } QString SpectralRoom::postMarkdownText(const QString& markdown) { - unsigned char *sequence = (unsigned char *) qstrdup(markdown.toUtf8().constData()); - qint64 length = strlen((char *) sequence); + unsigned char* sequence = + (unsigned char*)qstrdup(markdown.toUtf8().constData()); + qint64 length = strlen((char*)sequence); - hoedown_renderer* renderer = hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 32); - hoedown_extensions extensions = (hoedown_extensions) ((HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN | HOEDOWN_EXT_MATH_EXPLICIT) & ~HOEDOWN_EXT_QUOTE); + hoedown_renderer* renderer = + hoedown_html_renderer_new(HOEDOWN_HTML_USE_XHTML, 32); + hoedown_extensions extensions = (hoedown_extensions)( + (HOEDOWN_EXT_BLOCK | HOEDOWN_EXT_SPAN | HOEDOWN_EXT_MATH_EXPLICIT) & + ~HOEDOWN_EXT_QUOTE); hoedown_document* document = hoedown_document_new(renderer, extensions, 32); hoedown_buffer* html = hoedown_buffer_new(length); hoedown_document_render(document, html, sequence, length); - QString result = QString::fromUtf8((char *) html->data, html->size); + QString result = QString::fromUtf8((char*)html->data, html->size); free(sequence); hoedown_buffer_free(html); diff --git a/src/spectralroom.h b/src/spectralroom.h index 917f3c1..ceb5428 100644 --- a/src/spectralroom.h +++ b/src/spectralroom.h @@ -8,12 +8,12 @@ #include #include -#include #include #include -#include -#include #include +#include +#include +#include using namespace QMatrixClient; @@ -30,7 +30,8 @@ class SpectralRoom : public Room { Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) public: - explicit SpectralRoom(Connection* connection, QString roomId, + explicit SpectralRoom(Connection* connection, + QString roomId, JoinState joinState = {}); const QString& cachedInput() const { return m_cachedInput; } @@ -89,147 +90,140 @@ class SpectralRoom : public Room { bool prettyPrint = (format == Qt::RichText); using namespace QMatrixClient; - return visit(evt - , [this, prettyPrint] (const RoomMessageEvent& e) { - using namespace MessageEventContent; + return visit( + evt, + [this, prettyPrint](const RoomMessageEvent& e) { + using namespace MessageEventContent; - if (e.hasTextContent() && e.mimeType().name() != "text/plain") - return static_cast(e.content())->body; - if (e.hasFileContent()) - { - auto fileCaption = - e.content()->fileInfo()->originalName.toHtmlEscaped(); - if (fileCaption.isEmpty()) - fileCaption = this->prettyPrint(e.plainBody()); - return !fileCaption.isEmpty() ? fileCaption : tr("a file"); + if (prettyPrint && e.hasTextContent() && + e.mimeType().name() != "text/plain") + return static_cast(e.content())->body; + if (e.hasFileContent()) { + auto fileCaption = + e.content()->fileInfo()->originalName.toHtmlEscaped(); + if (fileCaption.isEmpty()) { + if (prettyPrint) + fileCaption = this->prettyPrint(e.plainBody()); + else + fileCaption = e.plainBody(); } - return this->prettyPrint(e.plainBody()); - } - , [this] (const RoomMemberEvent& e) { - // FIXME: Rewind to the name that was at the time of this event - auto subjectName = this->user(e.userId())->displayname(); - // The below code assumes senderName output in AuthorRole - switch( e.membership() ) - { - case MembershipType::Invite: - if (e.repeatsState()) - return tr("reinvited %1 to the room").arg(subjectName); - FALLTHROUGH; - case MembershipType::Join: - { - if (e.repeatsState()) - return tr("joined the room (repeated)"); - if (!e.prevContent() || - e.membership() != e.prevContent()->membership) - { - return e.membership() == MembershipType::Invite - ? tr("invited %1 to the room").arg(subjectName) - : tr("joined the room"); - } - QString text {}; - if (e.isRename()) - { - if (e.displayName().isEmpty()) - text = tr("cleared the display name"); - else - text = tr("changed the display name to %1") - .arg(e.displayName().toHtmlEscaped()); - } - if (e.isAvatarUpdate()) - { - if (!text.isEmpty()) - text += " and "; - if (e.avatarUrl().isEmpty()) - text += tr("cleared the avatar"); - else - text += tr("updated the avatar"); - } - return text; - } - case MembershipType::Leave: - if (e.prevContent() && - e.prevContent()->membership == MembershipType::Invite) - { - return (e.senderId() != e.userId()) - ? tr("withdrew %1's invitation").arg(subjectName) - : tr("rejected the invitation"); - } + return !fileCaption.isEmpty() ? fileCaption : tr("a file"); + } + return prettyPrint ? this->prettyPrint(e.plainBody()) : e.plainBody(); + }, + [this](const RoomMemberEvent& e) { + // FIXME: Rewind to the name that was at the time of this event + auto subjectName = this->user(e.userId())->displayname(); + // The below code assumes senderName output in AuthorRole + switch (e.membership()) { + case MembershipType::Invite: + if (e.repeatsState()) + return tr("reinvited %1 to the room").arg(subjectName); + FALLTHROUGH; + case MembershipType::Join: { + if (e.repeatsState()) + return tr("joined the room (repeated)"); + if (!e.prevContent() || + e.membership() != e.prevContent()->membership) { + return e.membership() == MembershipType::Invite + ? tr("invited %1 to the room").arg(subjectName) + : tr("joined the room"); + } + QString text{}; + if (e.isRename()) { + if (e.displayName().isEmpty()) + text = tr("cleared the display name"); + else + text = tr("changed the display name to %1") + .arg(e.displayName().toHtmlEscaped()); + } + if (e.isAvatarUpdate()) { + if (!text.isEmpty()) + text += " and "; + if (e.avatarUrl().isEmpty()) + text += tr("cleared the avatar"); + else + text += tr("updated the avatar"); + } + return text; + } + case MembershipType::Leave: + if (e.prevContent() && + e.prevContent()->membership == MembershipType::Invite) { + return (e.senderId() != e.userId()) + ? tr("withdrew %1's invitation").arg(subjectName) + : tr("rejected the invitation"); + } - if (e.prevContent() && - e.prevContent()->membership == MembershipType::Ban) - { - return (e.senderId() != e.userId()) - ? tr("unbanned %1").arg(subjectName) - : tr("self-unbanned"); - } - return (e.senderId() != e.userId()) - ? tr("has put %1 out of the room: %2") - .arg(subjectName, - e.contentJson()["reason"_ls] - .toString().toHtmlEscaped()) - : tr("left the room"); - case MembershipType::Ban: - return (e.senderId() != e.userId()) - ? tr("banned %1 from the room: %2") - .arg(subjectName, - e.contentJson()["reason"_ls] - .toString().toHtmlEscaped()) - : tr("self-banned from the room"); - case MembershipType::Knock: - return tr("knocked"); - default: - ; - } - return tr("made something unknown"); - } - , [] (const RoomAliasesEvent& e) { - return tr("has set room aliases on server %1 to: %2") - .arg(e.stateKey(), - QLocale().createSeparatedList(e.aliases())); - } - , [] (const RoomCanonicalAliasEvent& e) { - return (e.alias().isEmpty()) - ? tr("cleared the room main alias") - : tr("set the room main alias to: %1").arg(e.alias()); - } - , [] (const RoomNameEvent& e) { - return (e.name().isEmpty()) - ? tr("cleared the room name") - : tr("set the room name to: %1") - .arg(e.name().toHtmlEscaped()); - } - , [this] (const RoomTopicEvent& e) { - return (e.topic().isEmpty()) - ? tr("cleared the topic") - : tr("set the topic to: %1") - .arg(this->prettyPrint(e.topic())); - } - , [] (const RoomAvatarEvent&) { - return tr("changed the room avatar"); - } - , [] (const EncryptionEvent&) { - return tr("activated End-to-End Encryption"); - } - , [] (const RoomCreateEvent& e) { - return (e.isUpgrade() - ? tr("upgraded the room to version %1") - : tr("created the room, version %1") - ).arg(e.version().isEmpty() - ? "1" : e.version().toHtmlEscaped()); - } - , [] (const StateEventBase& e) { - // A small hack for state events from TWIM bot - return e.stateKey() == "twim" - ? tr("updated the database", "TWIM bot updated the database") - : e.stateKey().isEmpty() - ? tr("updated %1 state", "%1 - Matrix event type") - .arg(e.matrixType()) - : tr("updated %1 state for %2", - "%1 - Matrix event type, %2 - state key") - .arg(e.matrixType(), e.stateKey().toHtmlEscaped()); - } - , tr("Unknown event") - ); + if (e.prevContent() && + e.prevContent()->membership == MembershipType::Ban) { + return (e.senderId() != e.userId()) + ? tr("unbanned %1").arg(subjectName) + : tr("self-unbanned"); + } + return (e.senderId() != e.userId()) + ? tr("has put %1 out of the room: %2") + .arg(subjectName, e.contentJson()["reason"_ls] + .toString() + .toHtmlEscaped()) + : tr("left the room"); + case MembershipType::Ban: + return (e.senderId() != e.userId()) + ? tr("banned %1 from the room: %2") + .arg(subjectName, e.contentJson()["reason"_ls] + .toString() + .toHtmlEscaped()) + : tr("self-banned from the room"); + case MembershipType::Knock: + return tr("knocked"); + default:; + } + return tr("made something unknown"); + }, + [](const RoomAliasesEvent& e) { + return tr("has set room aliases on server %1 to: %2") + .arg(e.stateKey(), QLocale().createSeparatedList(e.aliases())); + }, + [](const RoomCanonicalAliasEvent& e) { + return (e.alias().isEmpty()) + ? tr("cleared the room main alias") + : tr("set the room main alias to: %1").arg(e.alias()); + }, + [](const RoomNameEvent& e) { + return (e.name().isEmpty()) ? tr("cleared the room name") + : tr("set the room name to: %1") + .arg(e.name().toHtmlEscaped()); + }, + [this, prettyPrint](const RoomTopicEvent& e) { + return (e.topic().isEmpty()) + ? tr("cleared the topic") + : tr("set the topic to: %1") + .arg(prettyPrint ? this->prettyPrint(e.topic()) + : e.topic()); + }, + [](const RoomAvatarEvent&) { return tr("changed the room avatar"); }, + [](const EncryptionEvent&) { + return tr("activated End-to-End Encryption"); + }, + [](const RoomCreateEvent& e) { + return (e.isUpgrade() ? tr("upgraded the room to version %1") + : tr("created the room, version %1")) + .arg(e.version().isEmpty() ? "1" : e.version().toHtmlEscaped()); + }, + [](const StateEventBase& e) { + // A small hack for state events from TWIM bot + return e.stateKey() == "twim" + ? tr("updated the database", + "TWIM bot updated the database") + : e.stateKey().isEmpty() + ? tr("updated %1 state", "%1 - Matrix event type") + .arg(e.matrixType()) + : tr("updated %1 state for %2", + "%1 - Matrix event type, %2 - state key") + .arg(e.matrixType(), + e.stateKey().toHtmlEscaped()); + }, + tr("Unknown event")); } private: @@ -261,7 +255,9 @@ class SpectralRoom : public Room { void acceptInvitation(); void forget(); void sendTypingNotification(bool isTyping); - void sendReply(QString userId, QString eventId, QString replyContent, + void sendReply(QString userId, + QString eventId, + QString replyContent, QString sendContent); }; diff --git a/src/utils.h b/src/utils.h index f94cd2c..dc36648 100644 --- a/src/utils.h +++ b/src/utils.h @@ -26,7 +26,6 @@ static const QRegularExpression userPillRegExp{ QString removeReply(const QString& text); QString cleanHTML(const QString& text, QMatrixClient::Room* room); - } // namespace utils #endif