Moved views increment scheduler from MainWidget to separate file.

This commit is contained in:
23rd 2021-09-29 00:23:58 +03:00
parent 51e80170e2
commit 21aa1f49d7
8 changed files with 200 additions and 123 deletions

View File

@ -139,6 +139,8 @@ PRIVATE
api/api_updates.h
api/api_user_privacy.cpp
api/api_user_privacy.h
api/api_views.cpp
api/api_views.h
api/api_who_read.cpp
api/api_who_read.h
boxes/filters/edit_filter_box.cpp

View File

@ -0,0 +1,134 @@
/*
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 "api/api_views.h"
#include "apiwrap.h"
#include "data/data_peer.h"
#include "data/data_peer_id.h"
#include "data/data_session.h"
#include "history/history.h"
#include "history/history_item.h"
#include "main/main_session.h"
namespace Api {
namespace {
// Send channel views each second.
constexpr auto kSendViewsTimeout = crl::time(1000);
} // namespace
ViewsManager::ViewsManager(not_null<ApiWrap*> api)
: _session(&api->session())
, _api(&api->instance()) {
}
void ViewsManager::scheduleIncrement(not_null<HistoryItem*> item) {
auto peer = item->history()->peer;
auto i = _incremented.find(peer);
if (i != _incremented.cend()) {
if (i->second.contains(item->id)) {
return;
}
} else {
i = _incremented.emplace(peer).first;
}
i->second.emplace(item->id);
auto j = _toIncrement.find(peer);
if (j == _toIncrement.cend()) {
j = _toIncrement.emplace(peer).first;
_incrementTimer.callOnce(kSendViewsTimeout);
}
j->second.emplace(item->id);
}
void ViewsManager::removeIncremented(not_null<PeerData*> peer) {
_incremented.remove(peer);
}
void ViewsManager::viewsIncrement() {
for (auto i = _toIncrement.begin(); i != _toIncrement.cend();) {
if (_incrementRequests.contains(i->first)) {
++i;
continue;
}
QVector<MTPint> ids;
ids.reserve(i->second.size());
for (const auto msgId : i->second) {
ids.push_back(MTP_int(msgId));
}
const auto requestId = _api.request(MTPmessages_GetMessagesViews(
i->first->input,
MTP_vector<MTPint>(ids),
MTP_bool(true)
)).done([=](
const MTPmessages_MessageViews &result,
mtpRequestId requestId) {
done(ids, result, requestId);
}).fail([=](const MTP::Error &error, mtpRequestId requestId) {
fail(error, requestId);
}).afterDelay(5).send();
_incrementRequests.emplace(i->first, requestId);
i = _toIncrement.erase(i);
}
}
void ViewsManager::done(
QVector<MTPint> ids,
const MTPmessages_MessageViews &result,
mtpRequestId requestId) {
const auto &data = result.c_messages_messageViews();
auto &owner = _session->data();
owner.processUsers(data.vusers());
owner.processChats(data.vchats());
auto &v = data.vviews().v;
if (ids.size() == v.size()) {
for (const auto &[peer, id] : _incrementRequests) {
if (id != requestId) {
continue;
}
const auto channel = peerToChannel(peer->id);
for (auto j = 0, l = int(ids.size()); j < l; ++j) {
if (const auto item = owner.message(channel, ids[j].v)) {
v[j].match([&](const MTPDmessageViews &data) {
if (const auto views = data.vviews()) {
item->setViewsCount(views->v);
}
if (const auto forwards = data.vforwards()) {
item->setForwardsCount(forwards->v);
}
if (const auto replies = data.vreplies()) {
item->setReplies(*replies);
}
});
}
}
_incrementRequests.erase(peer);
break;
}
}
if (!_toIncrement.empty() && !_incrementTimer.isActive()) {
_incrementTimer.callOnce(kSendViewsTimeout);
}
}
void ViewsManager::fail(const MTP::Error &error, mtpRequestId requestId) {
for (const auto &[peer, id] : _incrementRequests) {
if (id == requestId) {
_incrementRequests.erase(peer);
break;
}
}
if (!_toIncrement.empty() && !_incrementTimer.isActive()) {
_incrementTimer.callOnce(kSendViewsTimeout);
}
}
} // namespace Api

View File

@ -0,0 +1,49 @@
/*
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
*/
#pragma once
#include "mtproto/sender.h"
#include "base/timer.h"
class ApiWrap;
class PeerData;
namespace Main {
class Session;
} // namespace Main
namespace Api {
class ViewsManager final {
public:
explicit ViewsManager(not_null<ApiWrap*> api);
void scheduleIncrement(not_null<HistoryItem*> item);
void removeIncremented(not_null<PeerData*> peer);
private:
void viewsIncrement();
void done(
QVector<MTPint> ids,
const MTPmessages_MessageViews &result,
mtpRequestId requestId);
void fail(const MTP::Error &error, mtpRequestId requestId);
const not_null<Main::Session*> _session;
MTP::Sender _api;
base::flat_map<not_null<PeerData*>, base::flat_set<MsgId>> _incremented;
base::flat_map<not_null<PeerData*>, base::flat_set<MsgId>> _toIncrement;
base::flat_map<not_null<PeerData*>, mtpRequestId> _incrementRequests;
base::flat_map<mtpRequestId, not_null<PeerData*>> _incrementByRequest;
base::Timer _incrementTimer;
};
} // namespace Api

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_global_privacy.h"
#include "api/api_updates.h"
#include "api/api_user_privacy.h"
#include "api/api_views.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h"
#include "data/data_changes.h"
@ -141,7 +142,8 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
, _sensitiveContent(std::make_unique<Api::SensitiveContent>(this))
, _globalPrivacy(std::make_unique<Api::GlobalPrivacy>(this))
, _userPrivacy(std::make_unique<Api::UserPrivacy>(this))
, _inviteLinks(std::make_unique<Api::InviteLinks>(this)) {
, _inviteLinks(std::make_unique<Api::InviteLinks>(this))
, _views(std::make_unique<Api::ViewsManager>(this)) {
crl::on_main(session, [=] {
// You can't use _session->lifetime() in the constructor,
// only queued, because it is not constructed yet.
@ -4733,6 +4735,10 @@ Api::InviteLinks &ApiWrap::inviteLinks() {
return *_inviteLinks;
}
Api::ViewsManager &ApiWrap::views() {
return *_views;
}
void ApiWrap::createPoll(
const PollData &data,
const SendAction &action,

View File

@ -62,6 +62,7 @@ class SensitiveContent;
class GlobalPrivacy;
class UserPrivacy;
class InviteLinks;
class ViewsManager;
namespace details {
@ -400,6 +401,7 @@ public:
[[nodiscard]] Api::GlobalPrivacy &globalPrivacy();
[[nodiscard]] Api::UserPrivacy &userPrivacy();
[[nodiscard]] Api::InviteLinks &inviteLinks();
[[nodiscard]] Api::ViewsManager &views();
void createPoll(
const PollData &data,
@ -720,6 +722,7 @@ private:
const std::unique_ptr<Api::GlobalPrivacy> _globalPrivacy;
const std::unique_ptr<Api::UserPrivacy> _userPrivacy;
const std::unique_ptr<Api::InviteLinks> _inviteLinks;
const std::unique_ptr<Api::ViewsManager> _views;
base::flat_map<FullMsgId, mtpRequestId> _pollVotesRequestIds;
base::flat_map<FullMsgId, mtpRequestId> _pollCloseRequestIds;

View File

@ -58,6 +58,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_attached_stickers.h"
#include "api/api_toggling_media.h"
#include "api/api_who_read.h"
#include "api/api_views.h"
#include "lang/lang_keys.h"
#include "data/data_session.h"
#include "data/data_media_types.h"
@ -677,7 +678,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
view->draw(p, context);
if (item->hasViews()) {
_controller->content()->scheduleViewIncrement(item);
session().api().views().scheduleIncrement(item);
}
if (item->isUnreadMention() && !item->isUnreadMedia()) {
readMentions.insert(item);
@ -737,7 +738,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
if (_visibleAreaBottom >= middle
&& _visibleAreaTop <= middle) {
if (item->hasViews()) {
_controller->content()->scheduleViewIncrement(item);
session().api().views().scheduleIncrement(item);
}
if (item->isUnreadMention() && !item->isUnreadMedia()) {
readMentions.insert(item);

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h"
#include "api/api_updates.h"
#include "api/api_views.h"
#include "data/data_photo.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
@ -116,13 +117,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QCoreApplication>
#include <QtCore/QMimeData>
namespace {
// Send channel views each second.
constexpr auto kSendViewsTimeout = crl::time(1000);
} // namespace
enum StackItemType {
HistoryStackItem,
SectionStackItem,
@ -235,7 +229,6 @@ MainWidget::MainWidget(
, _dialogs(this, _controller)
, _history(this, _controller)
, _playerPlaylist(this, _controller)
, _viewsIncrementTimer([=] { viewsIncrement(); })
, _changelogs(Core::Changelogs::Create(&controller->session())) {
setupConnectingWidget();
@ -1221,100 +1214,6 @@ void MainWidget::setInnerFocus() {
}
}
void MainWidget::scheduleViewIncrement(HistoryItem *item) {
PeerData *peer = item->history()->peer;
auto i = _viewsIncremented.find(peer);
if (i != _viewsIncremented.cend()) {
if (i->second.contains(item->id)) return;
} else {
i = _viewsIncremented.emplace(peer).first;
}
i->second.emplace(item->id);
auto j = _viewsToIncrement.find(peer);
if (j == _viewsToIncrement.cend()) {
j = _viewsToIncrement.emplace(peer).first;
_viewsIncrementTimer.callOnce(kSendViewsTimeout);
}
j->second.emplace(item->id);
}
void MainWidget::viewsIncrement() {
for (auto i = _viewsToIncrement.begin(); i != _viewsToIncrement.cend();) {
if (_viewsIncrementRequests.contains(i->first)) {
++i;
continue;
}
QVector<MTPint> ids;
ids.reserve(i->second.size());
for (const auto msgId : i->second) {
ids.push_back(MTP_int(msgId));
}
const auto requestId = _api.request(MTPmessages_GetMessagesViews(
i->first->input,
MTP_vector<MTPint>(ids),
MTP_bool(true)
)).done([=](const MTPmessages_MessageViews &result, mtpRequestId requestId) {
viewsIncrementDone(ids, result, requestId);
}).fail([=](const MTP::Error &error, mtpRequestId requestId) {
viewsIncrementFail(error, requestId);
}).afterDelay(5).send();
_viewsIncrementRequests.emplace(i->first, requestId);
i = _viewsToIncrement.erase(i);
}
}
void MainWidget::viewsIncrementDone(
QVector<MTPint> ids,
const MTPmessages_MessageViews &result,
mtpRequestId requestId) {
const auto &data = result.c_messages_messageViews();
session().data().processUsers(data.vusers());
session().data().processChats(data.vchats());
auto &v = data.vviews().v;
if (ids.size() == v.size()) {
for (auto i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) {
if (i->second == requestId) {
const auto peer = i->first;
const auto channel = peerToChannel(peer->id);
for (int32 j = 0, l = ids.size(); j < l; ++j) {
if (const auto item = session().data().message(channel, ids[j].v)) {
v[j].match([&](const MTPDmessageViews &data) {
if (const auto views = data.vviews()) {
item->setViewsCount(views->v);
}
if (const auto forwards = data.vforwards()) {
item->setForwardsCount(forwards->v);
}
if (const auto replies = data.vreplies()) {
item->setReplies(*replies);
}
});
}
}
_viewsIncrementRequests.erase(i);
break;
}
}
}
if (!_viewsToIncrement.empty() && !_viewsIncrementTimer.isActive()) {
_viewsIncrementTimer.callOnce(kSendViewsTimeout);
}
}
void MainWidget::viewsIncrementFail(const MTP::Error &error, mtpRequestId requestId) {
for (auto i = _viewsIncrementRequests.begin(); i != _viewsIncrementRequests.cend(); ++i) {
if (i->second == requestId) {
_viewsIncrementRequests.erase(i);
break;
}
}
if (!_viewsToIncrement.empty() && !_viewsIncrementTimer.isActive()) {
_viewsIncrementTimer.callOnce(kSendViewsTimeout);
}
}
void MainWidget::choosePeer(PeerId peerId, MsgId showAtMsgId) {
if (selectingPeer()) {
_hider->offerPeer(peerId);
@ -1505,7 +1404,7 @@ void MainWidget::ui_showPeerHistory(
} else {
const auto nowActivePeer = _controller->activeChatCurrent().peer();
if (nowActivePeer && nowActivePeer != wasActivePeer) {
_viewsIncremented.remove(nowActivePeer);
session().api().views().removeIncremented(nowActivePeer);
}
if (isOneColumn() && !_dialogs->isHidden()) {
_dialogs->hide();

View File

@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/timer.h"
#include "base/weak_ptr.h"
#include "chat_helpers/bot_command.h"
#include "ui/rp_widget.h"
@ -201,8 +200,6 @@ public:
void ctrlEnterSubmitUpdated();
void setInnerFocus();
void scheduleViewIncrement(HistoryItem *item);
bool contentOverlapped(const QRect &globalRect);
void searchInChat(Dialogs::Key chat);
@ -245,8 +242,6 @@ protected:
bool eventFilter(QObject *o, QEvent *e) override;
private:
void viewsIncrement();
void animationCallback();
void handleAdaptiveLayoutUpdate();
void updateWindowAdaptiveLayout();
@ -313,12 +308,6 @@ private:
void floatPlayerDoubleClickEvent(
not_null<const HistoryItem*> item) override;
void viewsIncrementDone(
QVector<MTPint> ids,
const MTPmessages_MessageViews &result,
mtpRequestId requestId);
void viewsIncrementFail(const MTP::Error &error, mtpRequestId requestId);
void refreshResizeAreas();
template <typename MoveCallback, typename FinishCallback>
void createResizeArea(
@ -389,12 +378,6 @@ private:
PhotoData *_deletingPhoto = nullptr;
base::flat_map<not_null<PeerData*>, base::flat_set<MsgId>> _viewsIncremented;
base::flat_map<not_null<PeerData*>, base::flat_set<MsgId>> _viewsToIncrement;
base::flat_map<not_null<PeerData*>, mtpRequestId> _viewsIncrementRequests;
base::flat_map<mtpRequestId, not_null<PeerData*>> _viewsIncrementByRequest;
base::Timer _viewsIncrementTimer;
struct SettingBackground;
std::unique_ptr<SettingBackground> _background;