| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /*
- 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::start_with_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::start_with_next(pushNextSnapshot, lifetime);
- messages->oneRemoved(
- ) | rpl::filter([=](MsgId messageId) {
- return builder->removeOne(messageId);
- }) | rpl::start_with_next(pushNextSnapshot, lifetime);
- messages->allRemoved(
- ) | rpl::filter([=] {
- return builder->removeAll();
- }) | rpl::start_with_next(pushNextSnapshot, lifetime);
- messages->bottomInvalidated(
- ) | rpl::filter([=] {
- return builder->invalidateBottom();
- }) | rpl::start_with_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,
- 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 topicRootId = MsgId();
- const auto migratedPeerId = migrateFrom ? migrateFrom->id : PeerId(0);
- using Key = SparseIdsMergedSlice::Key;
- return SparseIdsMergedSlice::CreateViewer(
- Key(peerId, topicRootId, 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
|