From de3a8b9b6948ac199bf4ab3a9be113dd83c8ea70 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Sun, 21 Apr 2019 12:41:53 +0800 Subject: [PATCH] Add more event types in eventToString(). Move eventToString() to SpectralRoom. --- imports/Spectral/Panel/RoomListPanel.qml | 527 ++++------------------- qml/main.qml | 19 +- src/controller.h | 1 + src/messageeventmodel.cpp | 6 +- src/roomlistmodel.cpp | 2 +- src/spectralroom.cpp | 2 +- src/spectralroom.h | 156 +++++++ src/utils.h | 113 ----- 8 files changed, 270 insertions(+), 556 deletions(-) diff --git a/imports/Spectral/Panel/RoomListPanel.qml b/imports/Spectral/Panel/RoomListPanel.qml index 452186a..c382f61 100644 --- a/imports/Spectral/Panel/RoomListPanel.qml +++ b/imports/Spectral/Panel/RoomListPanel.qml @@ -88,462 +88,123 @@ Item { edge: Qt.LeftEdge - Component { - id: mainPage - - ColumnLayout { - readonly property string title: "Main" - - id: mainColumn - - spacing: 0 - - Control { - Layout.fillWidth: true - Layout.preferredHeight: 330 - - padding: 24 - - contentItem: ColumnLayout { - spacing: 4 - - Avatar { - Layout.preferredWidth: 200 - Layout.preferredHeight: 200 - Layout.margins: 12 - Layout.alignment: Qt.AlignHCenter - - source: root.user ? root.user.avatarMediaId : null - hint: root.user ? root.user.displayName : "?" - } - - Label { - Layout.alignment: Qt.AlignHCenter - - text: root.user ? root.user.displayName : "No Name" - color: "white" - font.pixelSize: 22 - } - - Label { - Layout.alignment: Qt.AlignHCenter - - text: root.user ? root.user.id : "@example:matrix.org" - color: "white" - opacity: 0.7 - font.pixelSize: 13 - } - } - - background: Rectangle { color: Material.primary } - - RippleEffect { - anchors.fill: parent - - onClicked: stackView.push(userPage) - } - } - - ScrollView { - Layout.fillWidth: true - Layout.fillHeight: true - - clip: true - - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ColumnLayout { - width: mainColumn.width - spacing: 0 - - Repeater { - model: AccountListModel { - controller: spectralController - } - - delegate: ItemDelegate { - Layout.fillWidth: true - - text: user.displayName - - onClicked: { - controller.connection = connection - drawer.close() - } - } - } - - ItemDelegate { - Layout.fillWidth: true - - text: "Add Account" - - onClicked: loginDialog.open() - } - - Rectangle { - Layout.fillWidth: true - Layout.preferredHeight: 1 - - color: MSettings.darkTheme ? "#424242" : "#e7ebeb" - } - - ItemDelegate { - Layout.fillWidth: true - - text: "Settings" - - onClicked: stackView.push(settingsPage) - } - - ItemDelegate { - Layout.fillWidth: true - - text: "Logout" - - onClicked: controller.logout(controller.connection) - } - - ItemDelegate { - Layout.fillWidth: true - - text: "Exit" - - onClicked: Qt.quit() - } - } - } - } - } - - Component { - id: userPage - - ScrollView { - readonly property string title: "User Info" - - id: main - - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ColumnLayout { - width: main.width - spacing: 0 - - ItemDelegate { - Layout.fillWidth: true - - padding: 24 - - contentItem: ColumnLayout { - spacing: 0 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: "Matrix ID" - font.pixelSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: root.user.id - color: "#5B7480" - font.pixelSize: 13 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - } - - ItemDelegate { - Layout.fillWidth: true - - padding: 24 - - contentItem: ColumnLayout { - spacing: 0 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: "Name" - font.pixelSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: root.user.name - color: "#5B7480" - font.pixelSize: 13 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - } - - ItemDelegate { - Layout.fillWidth: true - - padding: 24 - - contentItem: ColumnLayout { - spacing: 0 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: "Avatar" - font.pixelSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: root.user.avatarMediaId - color: "#5B7480" - font.pixelSize: 13 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - } - - ItemDelegate { - Layout.fillWidth: true - - padding: 24 - - contentItem: ColumnLayout { - spacing: 0 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: "Server" - font.pixelSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: root.controller.connection.accessToken - color: "#5B7480" - font.pixelSize: 13 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - } - - ItemDelegate { - Layout.fillWidth: true - - padding: 24 - - contentItem: ColumnLayout { - spacing: 0 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: "Device" - font.pixelSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: root.controller.connection.deviceId - color: "#5B7480" - font.pixelSize: 13 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - } - - ItemDelegate { - Layout.fillWidth: true - - padding: 24 - - contentItem: ColumnLayout { - spacing: 0 - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: "Token" - font.pixelSize: 16 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - - Label { - Layout.fillWidth: true - Layout.fillHeight: true - - text: root.controller.connection.accessToken - color: "#5B7480" - font.pixelSize: 13 - elide: Text.ElideRight - wrapMode: Text.NoWrap - } - } - } - } - } - } - - Component { - id: settingsPage - - ScrollView { - readonly property string title: "Settings" - - id: main - - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - padding: 32 - - ColumnLayout { - width: main.width - 64 - spacing: 0 - - Switch { - text: "Dark theme" - checked: MSettings.darkTheme - - onCheckedChanged: MSettings.darkTheme = checked - } - - Switch { - text: "Show notifications" - checked: MSettings.showNotification - - onCheckedChanged: MSettings.showNotification = checked - } - - Switch { - text: "Use press and hold instead of right click" - checked: MSettings.pressAndHold - - onCheckedChanged: MSettings.pressAndHold = checked - } - - Switch { - text: "Show tray icon" - checked: MSettings.showTray - - onCheckedChanged: MSettings.showTray = checked - } - - Switch { - text: "Enable timeline background" - checked: MSettings.enableTimelineBackground - - onCheckedChanged: MSettings.enableTimelineBackground = checked - } - - RowLayout { - Layout.fillWidth: true - - Label { - text: "DPI" - } - - Slider { - Layout.fillWidth: true - - value: controller.dpi() - from: 100 - to: 300 - stepSize: 25 - snapMode: Slider.SnapAlways - - ToolTip.visible: pressed - ToolTip.text: value - - onMoved: controller.setDpi(value) - } - } - } - } - } - ColumnLayout { anchors.fill: parent + id: mainColumn + spacing: 0 - Rectangle { + Control { Layout.fillWidth: true - Layout.preferredHeight: 64 + Layout.preferredHeight: 330 - visible: stackView.depth > 1 + padding: 24 - color: Material.primary + contentItem: ColumnLayout { + spacing: 4 - RowLayout { - anchors.fill: parent - anchors.margins: 4 + Avatar { + Layout.preferredWidth: 200 + Layout.preferredHeight: 200 + Layout.margins: 12 + Layout.alignment: Qt.AlignHCenter - ToolButton { - Layout.preferredWidth: height - Layout.fillHeight: true - - contentItem: MaterialIcon { - icon: "\ue5c4" - color: "white" - } - - onClicked: stackView.pop() + source: root.user ? root.user.avatarMediaId : null + hint: root.user ? root.user.displayName : "?" } + Label { - Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter - text: stackView.currentItem.title + text: root.user ? root.user.displayName : "No Name" color: "white" - font.pixelSize: 18 - elide: Label.ElideRight + font.pixelSize: 22 } + + Label { + Layout.alignment: Qt.AlignHCenter + + text: root.user ? root.user.id : "@example:matrix.org" + color: "white" + opacity: 0.7 + font.pixelSize: 13 + } + } + + background: Rectangle { color: Material.primary } + + RippleEffect { + anchors.fill: parent } } - StackView { + ScrollView { Layout.fillWidth: true Layout.fillHeight: true - id: stackView - clip: true - initialItem: mainPage + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + ColumnLayout { + width: mainColumn.width + spacing: 0 + + Repeater { + model: AccountListModel { + controller: spectralController + } + + delegate: ItemDelegate { + Layout.fillWidth: true + + text: user.displayName + + onClicked: { + controller.connection = connection + drawer.close() + } + } + } + + ItemDelegate { + Layout.fillWidth: true + + text: "Add Account" + + onClicked: loginDialog.open() + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + + color: MSettings.darkTheme ? "#424242" : "#e7ebeb" + } + + ItemDelegate { + Layout.fillWidth: true + + text: "Settings" + } + + ItemDelegate { + Layout.fillWidth: true + + text: "Logout" + + onClicked: controller.logout(controller.connection) + } + + ItemDelegate { + Layout.fillWidth: true + + text: "Exit" + + onClicked: Qt.quit() + } + } } } } diff --git a/qml/main.qml b/qml/main.qml index 0b7db72..6105c72 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -168,6 +168,15 @@ ApplicationWindow { } } + Dialog { + anchors.centerIn: parent + + width: 200 + height: 300 + + id: settingsDialog + } + SplitView { anchors.fill: parent @@ -212,9 +221,9 @@ ApplicationWindow { window.hide() } - Component.onCompleted: { - spectralController.initiated.connect(function() { - if (spectralController.accountCount == 0) loginDialog.open() - }) - } + Component.onCompleted: { + spectralController.initiated.connect(function() { + if (spectralController.accountCount == 0) loginDialog.open() + }) + } } diff --git a/src/controller.h b/src/controller.h index 32fc031..f31cc08 100644 --- a/src/controller.h +++ b/src/controller.h @@ -5,6 +5,7 @@ #include "notifications/manager.h" #include "settings.h" #include "user.h" +#include "room.h" #include #include diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp index d5e9799..30c3eca 100644 --- a/src/messageeventmodel.cpp +++ b/src/messageeventmodel.cpp @@ -256,11 +256,11 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const { const auto &evt = isPending ? **pendingIt : **timelineIt; if (role == Qt::DisplayRole) { - return utils::removeReply(utils::eventToString(evt, m_currentRoom, Qt::RichText)); + return utils::removeReply(m_currentRoom->eventToString(evt, Qt::RichText)); } if (role == MessageRole) { - return utils::removeReply(utils::eventToString(evt, m_currentRoom)); + return utils::removeReply(m_currentRoom->eventToString(evt)); } if (role == Qt::ToolTipRole) { @@ -382,7 +382,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const { case ReplyEventIdRole: return replyEventId; case ReplyDisplayRole: - return utils::removeReply(utils::eventToString(replyEvt, m_currentRoom, Qt::RichText)); + return utils::removeReply(m_currentRoom->eventToString(replyEvt, Qt::RichText)); case ReplyAuthorRole: return QVariant::fromValue( m_currentRoom->user(replyEvt.senderId())); diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index c1e5114..3eec7c1 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -85,7 +85,7 @@ void RoomListModel::connectRoomSignals(SpectralRoom* room) { if (sender == room->localUser()) return; emit newMessage( room->id(), lastEvent->id(), room->displayName(), - sender->displayname(), utils::eventToString(*lastEvent), + sender->displayname(), room->eventToString(*lastEvent), room->avatar(128)); }); } diff --git a/src/spectralroom.cpp b/src/spectralroom.cpp index 2dd1060..c4954c8 100644 --- a/src/spectralroom.cpp +++ b/src/spectralroom.cpp @@ -107,7 +107,7 @@ QString SpectralRoom::lastEvent() { if (timelineSize() == 0) return ""; const RoomEvent* lastEvent = messageEvents().rbegin()->get(); return user(lastEvent->senderId())->displayname() + ": " + - utils::removeReply(utils::eventToString(*lastEvent, this)); + utils::removeReply(eventToString(*lastEvent)); } bool SpectralRoom::isEventHighlighted(const RoomEvent* e) const { diff --git a/src/spectralroom.h b/src/spectralroom.h index 68722dc..917f3c1 100644 --- a/src/spectralroom.h +++ b/src/spectralroom.h @@ -8,6 +8,13 @@ #include #include +#include +#include +#include +#include +#include +#include + using namespace QMatrixClient; class SpectralRoom : public Room { @@ -76,6 +83,155 @@ class SpectralRoom : public Room { Q_INVOKABLE QString postMarkdownText(const QString& markdown); + template + QString eventToString(const BaseEventT& evt, + Qt::TextFormat format = Qt::PlainText) { + bool prettyPrint = (format == Qt::RichText); + + using namespace QMatrixClient; + 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"); + } + 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"); + } + + 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") + ); + } + private: QString m_cachedInput; QSet highlights; diff --git a/src/utils.h b/src/utils.h index cce426d..f94cd2c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -27,119 +27,6 @@ static const QRegularExpression userPillRegExp{ QString removeReply(const QString& text); QString cleanHTML(const QString& text, QMatrixClient::Room* room); -template -QString eventToString(const BaseEventT& evt, - QMatrixClient::Room* room = nullptr, - Qt::TextFormat format = Qt::PlainText) { - bool prettyPrint = (format == Qt::RichText); - - using namespace QMatrixClient; - return visit( - evt, - [room, prettyPrint](const RoomMessageEvent& e) { - using namespace MessageEventContent; - - if (prettyPrint && e.hasTextContent() && - e.mimeType().name() != "text/plain") { - return cleanHTML(static_cast(e.content())->body, - room); - } - if (e.hasFileContent()) { - auto fileCaption = e.content()->fileInfo()->originalName; - if (fileCaption.isEmpty()) - fileCaption = prettyPrint && room ? room->prettyPrint(e.plainBody()) - : e.plainBody(); - if (fileCaption.isEmpty()) return QObject::tr("a file"); - } - return prettyPrint && room ? room->prettyPrint(e.plainBody()) - : e.plainBody(); - }, - [room](const RoomMemberEvent& e) { - // FIXME: Rewind to the name that was at the time of this event - QString subjectName = - room ? room->roomMembername(e.userId()) : e.userId(); - // The below code assumes senderName output in AuthorRole - switch (e.membership()) { - case MembershipType::Invite: - if (e.repeatsState()) - return QObject::tr("reinvited %1 to the room").arg(subjectName); - FALLTHROUGH; - case MembershipType::Join: { - if (e.repeatsState()) - return QObject::tr("joined the room (repeated)"); - if (!e.prevContent() || - e.membership() != e.prevContent()->membership) { - return e.membership() == MembershipType::Invite - ? QObject::tr("invited %1 to the room") - .arg(subjectName) - : QObject::tr("joined the room"); - } - QString text{}; - if (e.isRename()) { - if (e.displayName().isEmpty()) - text = QObject::tr("cleared their display name"); - else - text = QObject::tr("changed their display name to %1") - .arg(e.displayName()); - } - if (e.isAvatarUpdate()) { - if (!text.isEmpty()) text += " and "; - if (e.avatarUrl().isEmpty()) - text += QObject::tr("cleared the avatar"); - else - text += QObject::tr("updated the avatar"); - } - return text; - } - case MembershipType::Leave: - if (e.prevContent() && - e.prevContent()->membership == MembershipType::Ban) { - return (e.senderId() != e.userId()) - ? QObject::tr("unbanned %1").arg(subjectName) - : QObject::tr("self-unbanned"); - } - return (e.senderId() != e.userId()) - ? QObject::tr("has kicked %1 from the room") - .arg(subjectName) - : QObject::tr("left the room"); - case MembershipType::Ban: - return (e.senderId() != e.userId()) - ? QObject::tr("banned %1 from the room ") - .arg(subjectName) - : QObject::tr(" self-banned from the room "); - case MembershipType::Knock: - return QObject::tr("knocked"); - default:; - } - return QObject::tr("made something unknown"); - }, - [](const RoomAliasesEvent& e) { - return QObject::tr("set aliases to: %1").arg(e.aliases().join(",")); - }, - [](const RoomCanonicalAliasEvent& e) { - return (e.alias().isEmpty()) - ? QObject::tr("cleared the room main alias") - : QObject::tr("set the room main alias to: %1") - .arg(e.alias()); - }, - [](const RoomNameEvent& e) { - return (e.name().isEmpty()) - ? QObject::tr("cleared the room name") - : QObject::tr("set the room name to: %1").arg(e.name()); - }, - [](const RoomTopicEvent& e) { - return (e.topic().isEmpty()) - ? QObject::tr("cleared the topic") - : QObject::tr("set the topic to: %1").arg(e.topic()); - }, - [](const RoomAvatarEvent&) { - return QObject::tr("changed the room avatar"); - }, - [](const EncryptionEvent&) { - return QObject::tr("activated End-to-End Encryption"); - }, - QObject::tr("Unknown Event")); -}; } // namespace utils #endif