From a243d6069aa88dcfbd0aa229270ba6159c0733db Mon Sep 17 00:00:00 2001 From: Black Hat Date: Mon, 6 Aug 2018 20:13:51 +0800 Subject: [PATCH] Update libqmatrixclient. --- include/libqmatrixclient | 2 +- src/messageeventmodel.cpp | 104 +++++++++++++++++++++++++++++++++----- src/messageeventmodel.h | 5 +- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/include/libqmatrixclient b/include/libqmatrixclient index 8bd8aaf..c0e75a5 160000 --- a/include/libqmatrixclient +++ b/include/libqmatrixclient @@ -1 +1 @@ -Subproject commit 8bd8aaf0858bb0a0ebcac8c3d29cfbb20279164d +Subproject commit c0e75a52504a3d31bcca0d4c39745d4d6c1fe917 diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp index 01aefbe..30deb33 100644 --- a/src/messageeventmodel.cpp +++ b/src/messageeventmodel.cpp @@ -97,8 +97,7 @@ void MessageEventModel::setRoom(QMatrixClient::Room* room) { } refreshRow(timelineBaseIndex()); // Refresh the looks if (m_currentRoom->timelineSize() > 1) // Refresh above - refreshEventRoles(timelineBaseIndex() + 1/*, - {ReadMarkerRole}*/); + refreshEventRoles(timelineBaseIndex() + 1, {ReadMarkerRole}); if (timelineBaseIndex() > 0) // Refresh below, see #312 refreshEventRoles(timelineBaseIndex() - 1, {AboveAuthorRole, AboveSectionRole}); @@ -111,10 +110,9 @@ void MessageEventModel::setRoom(QMatrixClient::Room* room) { &MessageEventModel::endRemoveRows); connect(m_currentRoom, &Room::readMarkerMoved, this, [this] { refreshEventRoles( - std::exchange(lastReadEventId, - m_currentRoom->readMarkerEventId())/*, - {ReadMarkerRole}*/); - refreshEventRoles(lastReadEventId /*, {ReadMarkerRole}*/); + std::exchange(lastReadEventId, m_currentRoom->readMarkerEventId()), + {ReadMarkerRole}); + refreshEventRoles(lastReadEventId, {ReadMarkerRole}); }); connect( m_currentRoom, &Room::replacedEvent, this, @@ -200,6 +198,66 @@ QString MessageEventModel::renderDate(QDateTime timestamp) const { return date.toString(Qt::DefaultLocaleShortDate); } +bool MessageEventModel::isUserActivityNotable( + const QMatrixClient::Room::rev_iter_t& baseIt) const { + const auto& senderId = (*baseIt)->senderId(); + // TODO: Go up and down the timeline (limit to 100 events for + // the sake of performance) and collect all messages of + // this author; find out if there's anything besides joins, leaves + // and redactions; if not, double-check whether the current event is + // a part of a re-join without following redactions. + using namespace QMatrixClient; + bool joinFound = false, redactionsFound = false; + // Find the nearest join of this user above, or a no-nonsense event. + for (auto it = baseIt, + limit = + baseIt + std::min(m_currentRoom->timelineEdge() - baseIt, 100); + it != limit; ++it) { + const auto& e = **it; + if (e.senderId() != senderId) continue; + if (e.isRedacted()) { + redactionsFound = true; + continue; + } + if (auto* me = it->viewAs()) { + if (me->isJoin()) { + joinFound = true; + break; + } + continue; + } + return true; // Consider all other events notable + } + // Find the nearest leave of this user below, or a no-nonsense event + bool leaveFound = false; + for (auto it = baseIt.base() - 1, + limit = + baseIt.base() + + std::min(m_currentRoom->messageEvents().end() - baseIt.base(), + 100); + it != limit; ++it) { + const auto& e = **it; + if (e.senderId() != senderId) continue; + if (e.isRedacted()) { + redactionsFound = true; + continue; + } + if (auto* me = it->viewAs()) { + if (me->isLeave() || me->membership() == MembershipType::Ban) { + leaveFound = true; + break; + } + continue; + } + return true; + } + // If we are here, it means that no notable events have been found in + // the timeline vicinity, and probably redactions are there. Doesn't look + // notable but let's give some benefit of doubt. + if (redactionsFound) return false; // Join + redactions or redactions + leave + return !(joinFound && leaveFound); // Join + (maybe profile changes) + leave +} + int MessageEventModel::rowCount(const QModelIndex& parent) const { if (!m_currentRoom || parent.isValid()) return 0; return m_currentRoom->timelineSize(); @@ -218,7 +276,7 @@ QVariant MessageEventModel::data(const QModelIndex& idx, int role) const { std::max(0, row - timelineBaseIndex()); const auto pendingIt = m_currentRoom->pendingEvents().crbegin() + std::min(row, timelineBaseIndex()); - const auto& evt = isPending ? *pendingIt->event() : *timelineIt->event(); + const auto& evt = isPending ? **pendingIt : **timelineIt; using namespace QMatrixClient; if (role == Qt::DisplayRole) { @@ -262,14 +320,14 @@ QVariant MessageEventModel::data(const QModelIndex& idx, int role) const { : tr("joined the room"); } QString text{}; - if (e.displayName() != e.prevContent()->displayName) { + 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()); } - if (e.avatarUrl() != e.prevContent()->avatarUrl) { + if (e.isAvatarUpdate()) { if (!text.isEmpty()) text += " and "; if (e.avatarUrl().isEmpty()) text += tr("cleared the avatar"); @@ -485,14 +543,36 @@ QVariant MessageEventModel::data(const QModelIndex& idx, int role) const { if (role == SpecialMarksRole) { if (isPending) return pendingIt->deliveryStatus(); + if (is(evt)) return EventStatus::Hidden; + auto* memberEvent = timelineIt->viewAs(); + if (memberEvent) { + if ((memberEvent->isJoin() || memberEvent->isLeave()) && + !Settings().value("UI/show_joinleave", true).toBool()) + return EventStatus::Hidden; + } + if (evt.isRedacted() || memberEvent) { + if (evt.senderId() == m_currentRoom->localUser()->id() || + Settings().value("UI/show_spammy").toBool()) { + return EventStatus::Normal; + } + QElapsedTimer et; + et.start(); + auto hide = !isUserActivityNotable(timelineIt); + qDebug() << "Checked user activity for" << evt.id() << "in" << et; + if (hide) return EventStatus::Hidden; + } + if (evt.isStateEvent() && static_cast(evt).repeatsState() && - !Settings().value("UI/show_noop_events", false).toBool()) + !Settings().value("UI/show_noop_events").toBool()) return EventStatus::Hidden; - if (is(evt)) return EventStatus::Hidden; + if (evt.isRedacted()) + return Settings().value("UI/show_redacted").toBool() + ? EventStatus::Redacted + : EventStatus::Hidden; - return evt.isRedacted() ? EventStatus::Redacted : EventStatus::Normal; + return EventStatus::Normal; } if (role == EventIdRole) diff --git a/src/messageeventmodel.h b/src/messageeventmodel.h index 2ab5b85..c4f21b8 100644 --- a/src/messageeventmodel.h +++ b/src/messageeventmodel.h @@ -38,7 +38,8 @@ class MessageEventModel : public QAbstractListModel { void setRoom(QMatrixClient::Room* room); int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; QHash roleNames() const; private slots: @@ -55,6 +56,8 @@ class MessageEventModel : public QAbstractListModel { QDateTime makeMessageTimestamp( const QMatrixClient::Room::rev_iter_t& baseIt) const; QString renderDate(QDateTime timestamp) const; + bool isUserActivityNotable(const QMatrixClient::Room::rev_iter_t& baseIt) const; + void refreshEventRoles(int row, const QVector& roles = {}); void refreshEventRoles(const QString& eventId, const QVector& roles = {});