mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Optimize updates subscription in topics.
This commit is contained in:
parent
9d4840c0de
commit
a21c73facd
5 changed files with 108 additions and 39 deletions
|
@ -151,7 +151,7 @@ ForumTopic::ForumTopic(not_null<Forum*> forum, MsgId rootId)
|
||||||
: Thread(&forum->history()->owner(), Type::ForumTopic)
|
: Thread(&forum->history()->owner(), Type::ForumTopic)
|
||||||
, _forum(forum)
|
, _forum(forum)
|
||||||
, _list(_forum->topicsList())
|
, _list(_forum->topicsList())
|
||||||
, _replies(std::make_shared<RepliesList>(history(), rootId))
|
, _replies(std::make_shared<RepliesList>(history(), rootId, this))
|
||||||
, _sendActionPainter(owner().sendActionManager().repliesPainter(
|
, _sendActionPainter(owner().sendActionManager().repliesPainter(
|
||||||
history(),
|
history(),
|
||||||
rootId))
|
rootId))
|
||||||
|
|
|
@ -60,38 +60,24 @@ struct RepliesList::Viewer {
|
||||||
bool scheduled = false;
|
bool scheduled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
RepliesList::RepliesList(not_null<History*> history, MsgId rootId)
|
RepliesList::RepliesList(
|
||||||
|
not_null<History*> history,
|
||||||
|
MsgId rootId,
|
||||||
|
ForumTopic *owningTopic)
|
||||||
: _history(history)
|
: _history(history)
|
||||||
|
, _owningTopic(owningTopic)
|
||||||
, _rootId(rootId)
|
, _rootId(rootId)
|
||||||
, _creating(IsCreating(history, rootId))
|
, _creating(IsCreating(history, rootId))
|
||||||
, _readRequestTimer([=] { sendReadTillRequest(); }) {
|
, _readRequestTimer([=] { sendReadTillRequest(); }) {
|
||||||
_history->owner().repliesReadTillUpdates(
|
if (_owningTopic) {
|
||||||
) | rpl::filter([=](const RepliesReadTillUpdate &update) {
|
_owningTopic->destroyed(
|
||||||
return (update.id.msg == _rootId)
|
) | rpl::start_with_next([=] {
|
||||||
&& (update.id.peer == _history->peer->id);
|
_owningTopic = nullptr;
|
||||||
}) | rpl::start_with_next([=](const RepliesReadTillUpdate &update) {
|
subscribeToUpdates();
|
||||||
if (update.out) {
|
}, _lifetime);
|
||||||
setOutboxReadTill(update.readTillId);
|
} else {
|
||||||
} else if (update.readTillId >= _inboxReadTillId) {
|
subscribeToUpdates();
|
||||||
setInboxReadTill(
|
}
|
||||||
update.readTillId,
|
|
||||||
computeUnreadCountLocally(update.readTillId));
|
|
||||||
}
|
|
||||||
}, _lifetime);
|
|
||||||
|
|
||||||
_history->session().changes().messageUpdates(
|
|
||||||
MessageUpdate::Flag::NewAdded
|
|
||||||
| MessageUpdate::Flag::NewMaybeAdded
|
|
||||||
| MessageUpdate::Flag::ReplyToTopAdded
|
|
||||||
| MessageUpdate::Flag::Destroyed
|
|
||||||
) | rpl::filter([=](const MessageUpdate &update) {
|
|
||||||
return applyUpdate(update);
|
|
||||||
}) | rpl::to_empty | rpl::start_to_stream(_instantChanges, _lifetime);
|
|
||||||
|
|
||||||
_history->owner().channelDifferenceTooLong(
|
|
||||||
) | rpl::filter([=](not_null<ChannelData*> channel) {
|
|
||||||
return applyDifferenceTooLong(channel);
|
|
||||||
}) | rpl::to_empty | rpl::start_to_stream(_listChanges, _lifetime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RepliesList::~RepliesList() {
|
RepliesList::~RepliesList() {
|
||||||
|
@ -105,6 +91,48 @@ RepliesList::~RepliesList() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RepliesList::subscribeToUpdates() {
|
||||||
|
_history->owner().repliesReadTillUpdates(
|
||||||
|
) | rpl::filter([=](const RepliesReadTillUpdate &update) {
|
||||||
|
return (update.id.msg == _rootId)
|
||||||
|
&& (update.id.peer == _history->peer->id);
|
||||||
|
}) | rpl::start_with_next([=](const RepliesReadTillUpdate &update) {
|
||||||
|
apply(update);
|
||||||
|
}, _lifetime);
|
||||||
|
|
||||||
|
_history->session().changes().messageUpdates(
|
||||||
|
MessageUpdate::Flag::NewAdded
|
||||||
|
| MessageUpdate::Flag::NewMaybeAdded
|
||||||
|
| MessageUpdate::Flag::ReplyToTopAdded
|
||||||
|
| MessageUpdate::Flag::Destroyed
|
||||||
|
) | rpl::start_with_next([=](const MessageUpdate &update) {
|
||||||
|
apply(update);
|
||||||
|
}, _lifetime);
|
||||||
|
|
||||||
|
_history->owner().channelDifferenceTooLong(
|
||||||
|
) | rpl::start_with_next([=](not_null<ChannelData*> channel) {
|
||||||
|
if (channel == _history->peer) {
|
||||||
|
applyDifferenceTooLong();
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepliesList::apply(const RepliesReadTillUpdate &update) {
|
||||||
|
if (update.out) {
|
||||||
|
setOutboxReadTill(update.readTillId);
|
||||||
|
} else if (update.readTillId >= _inboxReadTillId) {
|
||||||
|
setInboxReadTill(
|
||||||
|
update.readTillId,
|
||||||
|
computeUnreadCountLocally(update.readTillId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RepliesList::apply(const MessageUpdate &update) {
|
||||||
|
if (applyUpdate(update)) {
|
||||||
|
_instantChanges.fire({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rpl::producer<MessagesSlice> RepliesList::source(
|
rpl::producer<MessagesSlice> RepliesList::source(
|
||||||
MessagePosition aroundId,
|
MessagePosition aroundId,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
|
@ -426,14 +454,11 @@ bool RepliesList::applyUpdate(const MessageUpdate &update) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RepliesList::applyDifferenceTooLong(not_null<ChannelData*> channel) {
|
void RepliesList::applyDifferenceTooLong() {
|
||||||
if (_creating
|
if (!_creating && _skippedAfter.has_value()) {
|
||||||
|| _history->peer != channel
|
_skippedAfter = std::nullopt;
|
||||||
|| !_skippedAfter.has_value()) {
|
_listChanges.fire({});
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
_skippedAfter = std::nullopt;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RepliesList::changeUnreadCountByPost(MsgId id, int delta) {
|
void RepliesList::changeUnreadCountByPost(MsgId id, int delta) {
|
||||||
|
|
|
@ -15,16 +15,25 @@ class HistoryService;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
class ForumTopic;
|
||||||
class Histories;
|
class Histories;
|
||||||
struct MessagePosition;
|
struct MessagePosition;
|
||||||
struct MessagesSlice;
|
struct MessagesSlice;
|
||||||
struct MessageUpdate;
|
struct MessageUpdate;
|
||||||
|
struct RepliesReadTillUpdate;
|
||||||
|
|
||||||
class RepliesList final : public base::has_weak_ptr {
|
class RepliesList final : public base::has_weak_ptr {
|
||||||
public:
|
public:
|
||||||
RepliesList(not_null<History*> history, MsgId rootId);
|
RepliesList(
|
||||||
|
not_null<History*> history,
|
||||||
|
MsgId rootId,
|
||||||
|
ForumTopic *owningTopic = nullptr);
|
||||||
~RepliesList();
|
~RepliesList();
|
||||||
|
|
||||||
|
void apply(const RepliesReadTillUpdate &update);
|
||||||
|
void apply(const MessageUpdate &update);
|
||||||
|
void applyDifferenceTooLong();
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<MessagesSlice> source(
|
[[nodiscard]] rpl::producer<MessagesSlice> source(
|
||||||
MessagePosition aroundId,
|
MessagePosition aroundId,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
|
@ -66,6 +75,7 @@ private:
|
||||||
HistoryItem *lookupRoot();
|
HistoryItem *lookupRoot();
|
||||||
[[nodiscard]] Histories &histories();
|
[[nodiscard]] Histories &histories();
|
||||||
|
|
||||||
|
void subscribeToUpdates();
|
||||||
[[nodiscard]] rpl::producer<MessagesSlice> sourceFromServer(
|
[[nodiscard]] rpl::producer<MessagesSlice> sourceFromServer(
|
||||||
MessagePosition aroundId,
|
MessagePosition aroundId,
|
||||||
int limitBefore,
|
int limitBefore,
|
||||||
|
@ -77,8 +87,6 @@ private:
|
||||||
not_null<Viewer*> viewer,
|
not_null<Viewer*> viewer,
|
||||||
not_null<HistoryItem*> item);
|
not_null<HistoryItem*> item);
|
||||||
[[nodiscard]] bool applyUpdate(const MessageUpdate &update);
|
[[nodiscard]] bool applyUpdate(const MessageUpdate &update);
|
||||||
[[nodiscard]] bool applyDifferenceTooLong(
|
|
||||||
not_null<ChannelData*> channel);
|
|
||||||
void injectRootMessageAndReverse(not_null<Viewer*> viewer);
|
void injectRootMessageAndReverse(not_null<Viewer*> viewer);
|
||||||
void injectRootMessage(not_null<Viewer*> viewer);
|
void injectRootMessage(not_null<Viewer*> viewer);
|
||||||
void injectRootDivider(
|
void injectRootDivider(
|
||||||
|
@ -97,6 +105,7 @@ private:
|
||||||
void reloadUnreadCountIfNeeded();
|
void reloadUnreadCountIfNeeded();
|
||||||
|
|
||||||
const not_null<History*> _history;
|
const not_null<History*> _history;
|
||||||
|
ForumTopic *_owningTopic = nullptr;
|
||||||
const MsgId _rootId = 0;
|
const MsgId _rootId = 0;
|
||||||
const bool _creating = false;
|
const bool _creating = false;
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_wall_paper.h"
|
#include "data/data_wall_paper.h"
|
||||||
#include "data/data_game.h"
|
#include "data/data_game.h"
|
||||||
#include "data/data_poll.h"
|
#include "data/data_poll.h"
|
||||||
|
#include "data/data_replies_list.h"
|
||||||
#include "data/data_chat_filters.h"
|
#include "data/data_chat_filters.h"
|
||||||
#include "data/data_scheduled_messages.h"
|
#include "data/data_scheduled_messages.h"
|
||||||
#include "data/data_send_action.h"
|
#include "data/data_send_action.h"
|
||||||
|
@ -292,6 +293,8 @@ Session::Session(not_null<Main::Session*> session)
|
||||||
}
|
}
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
|
|
||||||
|
subscribeForTopicRepliesLists();
|
||||||
|
|
||||||
crl::on_main(_session, [=] {
|
crl::on_main(_session, [=] {
|
||||||
AmPremiumValue(
|
AmPremiumValue(
|
||||||
_session
|
_session
|
||||||
|
@ -307,6 +310,37 @@ Session::Session(not_null<Main::Session*> session)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Session::subscribeForTopicRepliesLists() {
|
||||||
|
repliesReadTillUpdates(
|
||||||
|
) | rpl::start_with_next([=](const RepliesReadTillUpdate &update) {
|
||||||
|
if (const auto peer = peerLoaded(update.id.peer)) {
|
||||||
|
if (const auto topic = peer->forumTopicFor(update.id.msg)) {
|
||||||
|
topic->replies()->apply(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
|
||||||
|
session().changes().messageUpdates(
|
||||||
|
MessageUpdate::Flag::NewAdded
|
||||||
|
| MessageUpdate::Flag::NewMaybeAdded
|
||||||
|
| MessageUpdate::Flag::ReplyToTopAdded
|
||||||
|
| MessageUpdate::Flag::Destroyed
|
||||||
|
) | rpl::start_with_next([=](const MessageUpdate &update) {
|
||||||
|
if (const auto topic = update.item->topic()) {
|
||||||
|
topic->replies()->apply(update);
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
|
||||||
|
channelDifferenceTooLong(
|
||||||
|
) | rpl::start_with_next([=](not_null<ChannelData*> channel) {
|
||||||
|
if (const auto forum = channel->forum()) {
|
||||||
|
forum->enumerateTopics([](not_null<ForumTopic*> topic) {
|
||||||
|
topic->replies()->applyDifferenceTooLong();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
void Session::clear() {
|
void Session::clear() {
|
||||||
// Optimization: clear notifications before destroying items.
|
// Optimization: clear notifications before destroying items.
|
||||||
Core::App().notifications().clearFromSession(_session);
|
Core::App().notifications().clearFromSession(_session);
|
||||||
|
|
|
@ -143,6 +143,7 @@ public:
|
||||||
return ++_nonHistoryEntryId;
|
return ++_nonHistoryEntryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void subscribeForTopicRepliesLists();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void keepAlive(std::shared_ptr<PhotoMedia> media);
|
void keepAlive(std::shared_ptr<PhotoMedia> media);
|
||||||
|
|
Loading…
Add table
Reference in a new issue