Page MenuHomePhorge

matrix-room-timeline.cpp
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

matrix-room-timeline.cpp

/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
#include <cmath>
#include <lager/lenses/optional.hpp>
#include <QTimer>
#include <cursorutil.hpp>
#include "matrix-room-timeline.hpp"
#include "matrix-event.hpp"
#include "helper.hpp"
#include "kazv-log.hpp"
using namespace Kazv;
MatrixRoomTimeline::MatrixRoomTimeline(Kazv::Room room, QObject *parent)
: QAbstractListModel(parent)
, m_room(room)
, m_timelineEventIds(m_room.timelineEventIds())
, m_messagesMap(m_room.messagesMap())
, m_internalCount(0)
, m_localEchoes(m_room.localEchoes())
, m_timelineGaps(m_room.timelineGaps())
, LAGER_QT(count)(lager::with(
m_timelineEventIds.xform(containerSize),
m_localEchoes.xform(containerSize)
).map([](const auto &tlSize, const auto &localSize) { return tlSize + localSize; }))
, LAGER_QT(gaps)(m_timelineGaps.map([](auto g) {
QSet<QString> res{};
for (const auto &[k, _v] : g) {
res.insert(QString::fromStdString(k));
}
return res;
}))
{
connect(this, &MatrixRoomTimeline::countChanged, this, &MatrixRoomTimeline::updateInternalCount);
// HACK: If internally the count is set to its full count at the beginning,
// ListView will instantiate everything in the timeline.
// I don't know why it is the case, so I keep the internal count as 0
// when it is constructed, and update it in the next tick.
QTimer::singleShot(0, this, [this] { Q_EMIT countChanged(count()); });
}
MatrixRoomTimeline::~MatrixRoomTimeline() = default;
MatrixEvent *MatrixRoomTimeline::at(int index) const
{
return new MatrixEvent(lager::with(m_timelineEventIds, m_messagesMap, m_localEchoes, LAGER_QT(count))
.map([index](const auto &tlEventIds, const auto &messagesMap, const auto &localEchoes, const auto &count) -> std::variant<Kazv::Event, Kazv::LocalEchoDesc> {
auto rIndex = count - index - 1;
if (static_cast<unsigned int>(rIndex) < tlEventIds.size()) {
return messagesMap[tlEventIds[rIndex]];
} else {
auto remainingIndex = rIndex - tlEventIds.size();
if (remainingIndex < localEchoes.size()) {
return localEchoes[remainingIndex];
} else {
return Event();
}
}
}), m_room);
}
int MatrixRoomTimeline::rowCount(const QModelIndex &index) const
{
if (index.isValid()) {
return 0;
} else {
return m_internalCount;
}
}
QVariant MatrixRoomTimeline::data(const QModelIndex &, int) const
{
return QVariant();
}
int MatrixRoomTimeline::indexOfEvent(const QString &eventId) const
{
auto eventMap = m_messagesMap.get();
auto eventIdStd = eventId.toStdString();
if (eventMap.count(eventIdStd) == 0) {
return -1;
}
auto eventIds = m_timelineEventIds.get();
auto it = std::lower_bound(eventIds.begin(), eventIds.end(), eventIdStd,
[eventMap](const auto &idA, const auto &idB) {
auto a = std::make_pair(eventMap[idA].originServerTs(), idA);
auto b = std::make_pair(eventMap[idB].originServerTs(), idB);
return a < b;
}
);
if (it == eventIds.end()) {
return -1;
} else {
// suppose there are A events and B local echoes
// forward index:
// [0, 1, ..., A-1] [A, A+1, ..., A+B-1]
// reverse index:
// [A+B-1, A+B-2, ..., B] [B-1, B-2 , 0]
// forward = it.index()
// forward + reverse = A+B-1 = count() - 1
return count() - it.index() - 1;
}
}
void MatrixRoomTimeline::updateInternalCount()
{
auto curCount = count();
auto oldCount = m_internalCount;
auto diff = std::abs(curCount - oldCount);
if (curCount > oldCount) {
beginInsertRows(QModelIndex(), 0, diff - 1);
m_internalCount = curCount;
endInsertRows();
} else if (curCount < oldCount) {
beginRemoveRows(QModelIndex(), 0, diff - 1);
m_internalCount = curCount;
endRemoveRows();
}
}

File Metadata

Mime Type
text/x-c
Expires
Sat, Nov 23, 1:09 AM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38784
Default Alt Text
matrix-room-timeline.cpp (4 KB)

Event Timeline