Update libqmatrixclient.

square-messages
Black Hat 2018-08-06 20:13:51 +08:00
parent 640e3712a2
commit a243d6069a
3 changed files with 97 additions and 14 deletions

@ -1 +1 @@
Subproject commit 8bd8aaf0858bb0a0ebcac8c3d29cfbb20279164d
Subproject commit c0e75a52504a3d31bcca0d4c39745d4d6c1fe917

View File

@ -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<int>(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<QMatrixClient::RoomMemberEvent>()) {
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<int>(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<RoomMemberEvent>()) {
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<RedactionEvent>(evt)) return EventStatus::Hidden;
auto* memberEvent = timelineIt->viewAs<RoomMemberEvent>();
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<const StateEventBase&>(evt).repeatsState() &&
!Settings().value("UI/show_noop_events", false).toBool())
!Settings().value("UI/show_noop_events").toBool())
return EventStatus::Hidden;
if (is<RedactionEvent>(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)

View File

@ -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<int, QByteArray> 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<int>& roles = {});
void refreshEventRoles(const QString& eventId,
const QVector<int>& roles = {});