init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
220
Telegram/SourceFiles/data/data_history_messages.cpp
Normal file
220
Telegram/SourceFiles/data/data_history_messages.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "data/data_history_messages.h"
|
||||
|
||||
#include "apiwrap.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_sparse_ids.h"
|
||||
#include "history/history.h"
|
||||
#include "main/main_session.h"
|
||||
|
||||
namespace Data {
|
||||
|
||||
void HistoryMessages::addNew(MsgId messageId) {
|
||||
_chat.addNew(messageId);
|
||||
}
|
||||
|
||||
void HistoryMessages::addExisting(MsgId messageId, MsgRange noSkipRange) {
|
||||
_chat.addExisting(messageId, noSkipRange);
|
||||
}
|
||||
|
||||
void HistoryMessages::addSlice(
|
||||
std::vector<MsgId> &&messageIds,
|
||||
MsgRange noSkipRange,
|
||||
std::optional<int> count) {
|
||||
_chat.addSlice(std::move(messageIds), noSkipRange, count);
|
||||
}
|
||||
|
||||
void HistoryMessages::removeOne(MsgId messageId) {
|
||||
_chat.removeOne(messageId);
|
||||
_oneRemoved.fire_copy(messageId);
|
||||
}
|
||||
|
||||
void HistoryMessages::removeAll() {
|
||||
_chat.removeAll();
|
||||
_allRemoved.fire({});
|
||||
}
|
||||
|
||||
void HistoryMessages::invalidateBottom() {
|
||||
_chat.invalidateBottom();
|
||||
_bottomInvalidated.fire({});
|
||||
}
|
||||
|
||||
Storage::SparseIdsListResult HistoryMessages::snapshot(
|
||||
const Storage::SparseIdsListQuery &query) const {
|
||||
return _chat.snapshot(query);
|
||||
}
|
||||
|
||||
auto HistoryMessages::sliceUpdated() const
|
||||
-> rpl::producer<Storage::SparseIdsSliceUpdate> {
|
||||
return _chat.sliceUpdated();
|
||||
}
|
||||
|
||||
rpl::producer<MsgId> HistoryMessages::oneRemoved() const {
|
||||
return _oneRemoved.events();
|
||||
}
|
||||
|
||||
rpl::producer<> HistoryMessages::allRemoved() const {
|
||||
return _allRemoved.events();
|
||||
}
|
||||
|
||||
rpl::producer<> HistoryMessages::bottomInvalidated() const {
|
||||
return _bottomInvalidated.events();
|
||||
}
|
||||
|
||||
rpl::producer<SparseIdsSlice> HistoryViewer(
|
||||
not_null<History*> history,
|
||||
MsgId aroundId,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
Expects(IsServerMsgId(aroundId) || (aroundId == 0));
|
||||
Expects((aroundId != 0) || (limitBefore == 0 && limitAfter == 0));
|
||||
|
||||
return [=](auto consumer) {
|
||||
auto lifetime = rpl::lifetime();
|
||||
|
||||
const auto messages = &history->messages();
|
||||
|
||||
auto builder = lifetime.make_state<SparseIdsSliceBuilder>(
|
||||
aroundId,
|
||||
limitBefore,
|
||||
limitAfter);
|
||||
using RequestAroundInfo = SparseIdsSliceBuilder::AroundData;
|
||||
builder->insufficientAround(
|
||||
) | rpl::on_next([=](const RequestAroundInfo &info) {
|
||||
if (!info.aroundId) {
|
||||
// Ignore messages-count-only requests, because we perform
|
||||
// them with non-zero limit of messages and end up adding
|
||||
// a broken slice with several last messages from the chat
|
||||
// with a non-skip range starting at zero.
|
||||
return;
|
||||
}
|
||||
history->session().api().requestHistory(
|
||||
history,
|
||||
info.aroundId,
|
||||
info.direction);
|
||||
}, lifetime);
|
||||
|
||||
auto pushNextSnapshot = [=] {
|
||||
consumer.put_next(builder->snapshot());
|
||||
};
|
||||
|
||||
using SliceUpdate = Storage::SparseIdsSliceUpdate;
|
||||
messages->sliceUpdated(
|
||||
) | rpl::filter([=](const SliceUpdate &update) {
|
||||
return builder->applyUpdate(update);
|
||||
}) | rpl::on_next(pushNextSnapshot, lifetime);
|
||||
|
||||
messages->oneRemoved(
|
||||
) | rpl::filter([=](MsgId messageId) {
|
||||
return builder->removeOne(messageId);
|
||||
}) | rpl::on_next(pushNextSnapshot, lifetime);
|
||||
|
||||
messages->allRemoved(
|
||||
) | rpl::filter([=] {
|
||||
return builder->removeAll();
|
||||
}) | rpl::on_next(pushNextSnapshot, lifetime);
|
||||
|
||||
messages->bottomInvalidated(
|
||||
) | rpl::filter([=] {
|
||||
return builder->invalidateBottom();
|
||||
}) | rpl::on_next(pushNextSnapshot, lifetime);
|
||||
|
||||
const auto snapshot = messages->snapshot({
|
||||
aroundId,
|
||||
limitBefore,
|
||||
limitAfter,
|
||||
});
|
||||
if (snapshot.count || !snapshot.messageIds.empty()) {
|
||||
if (builder->applyInitial(snapshot)) {
|
||||
pushNextSnapshot();
|
||||
}
|
||||
}
|
||||
builder->checkInsufficient();
|
||||
|
||||
return lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
rpl::producer<SparseIdsMergedSlice> HistoryMergedViewer(
|
||||
not_null<History*> history,
|
||||
/*Universal*/MsgId universalAroundId,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
const auto migrateFrom = history->peer->migrateFrom();
|
||||
auto createSimpleViewer = [=](
|
||||
PeerId peerId,
|
||||
MsgId topicRootId,
|
||||
PeerId monoforumPeerId,
|
||||
SparseIdsSlice::Key simpleKey,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
const auto chosen = (history->peer->id == peerId)
|
||||
? history
|
||||
: history->owner().history(peerId);
|
||||
return HistoryViewer(chosen, simpleKey, limitBefore, limitAfter);
|
||||
};
|
||||
const auto peerId = history->peer->id;
|
||||
const auto migratedPeerId = migrateFrom ? migrateFrom->id : PeerId(0);
|
||||
using Key = SparseIdsMergedSlice::Key;
|
||||
return SparseIdsMergedSlice::CreateViewer(
|
||||
Key(peerId, MsgId(), PeerId(), migratedPeerId, universalAroundId),
|
||||
limitBefore,
|
||||
limitAfter,
|
||||
std::move(createSimpleViewer));
|
||||
}
|
||||
|
||||
rpl::producer<MessagesSlice> HistoryMessagesViewer(
|
||||
not_null<History*> history,
|
||||
MessagePosition aroundId,
|
||||
int limitBefore,
|
||||
int limitAfter) {
|
||||
const auto computeUnreadAroundId = [&] {
|
||||
if (const auto migrated = history->migrateFrom()) {
|
||||
if (const auto around = migrated->loadAroundId()) {
|
||||
return MsgId(around - ServerMaxMsgId);
|
||||
}
|
||||
}
|
||||
if (const auto around = history->loadAroundId()) {
|
||||
return around;
|
||||
}
|
||||
return MsgId(ServerMaxMsgId - 1);
|
||||
};
|
||||
const auto messageId = (aroundId.fullId.msg == ShowAtUnreadMsgId)
|
||||
? computeUnreadAroundId()
|
||||
: ((aroundId.fullId.msg == ShowAtTheEndMsgId)
|
||||
|| (aroundId == MaxMessagePosition))
|
||||
? (ServerMaxMsgId - 1)
|
||||
: (aroundId.fullId.peer == history->peer->id)
|
||||
? aroundId.fullId.msg
|
||||
: (aroundId.fullId.msg - ServerMaxMsgId);
|
||||
return HistoryMergedViewer(
|
||||
history,
|
||||
messageId,
|
||||
limitBefore,
|
||||
limitAfter
|
||||
) | rpl::map([=](SparseIdsMergedSlice &&slice) {
|
||||
auto result = Data::MessagesSlice();
|
||||
result.fullCount = slice.fullCount();
|
||||
result.skippedAfter = slice.skippedAfter();
|
||||
result.skippedBefore = slice.skippedBefore();
|
||||
const auto count = slice.size();
|
||||
result.ids.reserve(count);
|
||||
if (const auto msgId = slice.nearest(messageId)) {
|
||||
result.nearestToAround = *msgId;
|
||||
}
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
result.ids.push_back(slice[i]);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
Reference in New Issue
Block a user