Move updates handling MainWidget -> Api::Updates.

This commit is contained in:
John Preston 2020-06-11 13:41:03 +04:00
parent ee43027bea
commit 0b028b959b
30 changed files with 2526 additions and 2218 deletions

View File

@ -167,6 +167,8 @@ PRIVATE
api/api_single_message_search.h
api/api_text_entities.cpp
api/api_text_entities.h
api/api_updates.cpp
api/api_updates.h
boxes/filters/edit_filter_box.cpp
boxes/filters/edit_filter_box.h
boxes/filters/edit_filter_chats_list.cpp

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,172 @@
/*
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/mtproto_rpc_sender.h"
#include "data/data_pts_waiter.h"
#include "base/timer.h"
class ApiWrap;
class History;
namespace Main {
class Session;
} // namespace Main
namespace Api {
class Updates final {
public:
explicit Updates(not_null<Main::Session*> session);
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] ApiWrap &api() const;
void applyUpdates(
const MTPUpdates &updates,
uint64 sentMessageRandomId = 0);
void applyUpdatesNoPtsCheck(const MTPUpdates &updates);
void applyUpdateNoPtsCheck(const MTPUpdate &update);
void updateOnline();
[[nodiscard]] bool isIdle() const;
void checkIdleFinish();
bool lastWasOnline() const;
crl::time lastSetOnline() const;
bool isQuitPrevent();
bool updateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
bool updateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
bool updateAndApply(int32 pts, int32 ptsCount);
void checkLastUpdate(bool afterSleep);
// ms <= 0 - stop timer
void ptsWaiterStartTimerFor(ChannelData *channel, crl::time ms);
void getDifference();
void requestChannelRangeDifference(not_null<History*> history);
void addActiveChat(rpl::producer<PeerData*> chat);
private:
enum class ChannelDifferenceRequest {
Unknown,
PtsGapOrShortPoll,
AfterFail,
};
struct ActiveChatTracker {
PeerData *peer = nullptr;
rpl::lifetime lifetime;
};
void channelRangeDifferenceSend(
not_null<ChannelData*> channel,
MsgRange range,
int32 pts);
void channelRangeDifferenceDone(
not_null<ChannelData*> channel,
MsgRange range,
const MTPupdates_ChannelDifference &result);
void updateOnline(bool gotOtherOffline);
void sendPing();
void getDifferenceByPts();
void getDifferenceAfterFail();
[[nodiscard]] bool requestingDifference() const {
return _ptsWaiter.requesting();
}
void getChannelDifference(
not_null<ChannelData*> channel,
ChannelDifferenceRequest from = ChannelDifferenceRequest::Unknown);
void differenceDone(const MTPupdates_Difference &result);
void differenceFail(const RPCError &error);
void feedDifference(
const MTPVector<MTPUser> &users,
const MTPVector<MTPChat> &chats,
const MTPVector<MTPMessage> &msgs,
const MTPVector<MTPUpdate> &other);
void stateDone(const MTPupdates_State &state);
void setState(int32 pts, int32 date, int32 qts, int32 seq);
void channelDifferenceDone(
not_null<ChannelData*> channel,
const MTPupdates_ChannelDifference &diff);
void channelDifferenceFail(
not_null<ChannelData*> channel,
const RPCError &error);
void failDifferenceStartTimerFor(ChannelData *channel);
void feedChannelDifference(const MTPDupdates_channelDifference &data);
void mtpUpdateReceived(const MTPUpdates &updates);
void mtpNewSessionCreated();
void feedUpdateVector(
const MTPVector<MTPUpdate> &updates,
bool skipMessageIds = false);
// Doesn't call sendHistoryChangeNotifications itself.
void feedMessageIds(const MTPVector<MTPUpdate> &updates);
// Doesn't call sendHistoryChangeNotifications itself.
void feedUpdate(const MTPUpdate &update);
bool whenGetDiffChanged(
ChannelData *channel,
int32 ms,
base::flat_map<not_null<ChannelData*>, crl::time> &whenMap,
crl::time &curTime);
const not_null<Main::Session*> _session;
int32 _updatesDate = 0;
int32 _updatesQts = -1;
int32 _updatesSeq = 0;
base::Timer _noUpdatesTimer;
base::Timer _onlineTimer;
PtsWaiter _ptsWaiter;
base::flat_map<not_null<ChannelData*>, crl::time> _whenGetDiffByPts;
base::flat_map<not_null<ChannelData*>, crl::time> _whenGetDiffAfterFail;
crl::time _getDifferenceTimeByPts = 0;
crl::time _getDifferenceTimeAfterFail = 0;
base::Timer _byPtsTimer;
base::flat_map<int32, MTPUpdates> _bySeqUpdates;
base::Timer _bySeqTimer;
base::Timer _byMinChannelTimer;
// growing timeout for getDifference calls, if it fails
crl::time _failDifferenceTimeout = 1;
// growing timeout for getChannelDifference calls, if it fails
base::flat_map<
not_null<ChannelData*>,
crl::time> _channelFailDifferenceTimeout;
base::Timer _failDifferenceTimer;
base::flat_map<
not_null<ChannelData*>,
mtpRequestId> _rangeDifferenceRequests;
crl::time _lastUpdateTime = 0;
bool _handlingChannelDifference = false;
base::flat_map<int, ActiveChatTracker> _activeChats;
mtpRequestId _onlineRequest = 0;
base::Timer _idleFinishTimer;
crl::time _lastSetOnline = 0;
bool _lastWasOnline = false;
bool _isIdle = false;
rpl::lifetime _lifetime;
};
} // namespace Api

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_text_entities.h"
#include "api/api_self_destruct.h"
#include "api/api_sensitive_content.h"
#include "api/api_updates.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h"
#include "data/data_photo.h"
@ -272,6 +273,10 @@ Storage::Account &ApiWrap::local() const {
return _session->local();
}
Api::Updates &ApiWrap::updates() const {
return _session->updates();
}
void ApiWrap::setupSupportMode() {
if (!_session->supportMode()) {
return;
@ -491,12 +496,6 @@ void ApiWrap::importChatInvite(const QString &hash) {
}).send();
}
void ApiWrap::applyUpdates(
const MTPUpdates &updates,
uint64 sentMessageRandomId) {
App::main()->feedUpdates(updates, sentMessageRandomId);
}
void ApiWrap::savePinnedOrder(Data::Folder *folder) {
const auto &order = _session->data().pinnedChatsOrder(
folder,
@ -2321,8 +2320,8 @@ void ApiWrap::deleteConversation(not_null<PeerData*> peer, bool revoke) {
request(MTPmessages_DeleteChatUser(
chat->inputChat,
_session->user()->inputUser
)).done([=](const MTPUpdates &updates) {
applyUpdates(updates);
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
deleteHistory(peer, false, revoke);
}).fail([=](const RPCError &error) {
deleteHistory(peer, false, revoke);
@ -2392,6 +2391,12 @@ void ApiWrap::deleteHistory(
}
}
void ApiWrap::applyUpdates(
const MTPUpdates &updates,
uint64 sentMessageRandomId) {
this->updates().applyUpdates(updates, sentMessageRandomId);
}
int ApiWrap::applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result) {
@ -2399,7 +2404,7 @@ int ApiWrap::applyAffectedHistory(
if (const auto channel = peer->asChannel()) {
channel->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v);
} else {
App::main()->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v);
updates().updateAndApply(data.vpts().v, data.vpts_count().v);
}
return data.voffset().v;
}
@ -2418,7 +2423,26 @@ void ApiWrap::applyAffectedMessages(
void ApiWrap::applyAffectedMessages(
const MTPmessages_AffectedMessages &result) {
const auto &data = result.c_messages_affectedMessages();
App::main()->ptsUpdateAndApply(data.vpts().v, data.vpts_count().v);
updates().updateAndApply(data.vpts().v, data.vpts_count().v);
}
void ApiWrap::saveCurrentDraftToCloud() {
Core::App().saveCurrentDraftsToHistories();
for (const auto controller : session().windows()) {
if (const auto peer = controller->activeChatCurrent().peer()) {
if (const auto history = session().data().historyLoaded(peer)) {
session().local().writeDrafts(history);
const auto localDraft = history->localDraft();
const auto cloudDraft = history->cloudDraft();
if (!Data::draftsAreEqual(localDraft, cloudDraft)
&& !session().supportMode()) {
saveDraftToCloudDelayed(history);
}
}
}
}
}
void ApiWrap::saveDraftsToCloud() {
@ -2713,98 +2737,6 @@ void ApiWrap::requestParticipantsCountDelayed(
[=] { channel->updateFullForced(); });
}
void ApiWrap::requestChannelRangeDifference(not_null<History*> history) {
Expects(history->isChannel());
const auto channel = history->peer->asChannel();
if (const auto requestId = _rangeDifferenceRequests.take(channel)) {
request(*requestId).cancel();
}
const auto range = history->rangeForDifferenceRequest();
if (!(range.from < range.till) || !channel->pts()) {
return;
}
MTP_LOG(0, ("getChannelDifference { good - "
"after channelDifferenceTooLong was received, "
"validating history part }%1").arg(cTestMode() ? " TESTMODE" : ""));
channelRangeDifferenceSend(channel, range, channel->pts());
}
void ApiWrap::channelRangeDifferenceSend(
not_null<ChannelData*> channel,
MsgRange range,
int32 pts) {
Expects(range.from < range.till);
const auto limit = range.till - range.from;
const auto filter = MTP_channelMessagesFilter(
MTP_flags(0),
MTP_vector<MTPMessageRange>(1, MTP_messageRange(
MTP_int(range.from),
MTP_int(range.till - 1))));
const auto requestId = request(MTPupdates_GetChannelDifference(
MTP_flags(MTPupdates_GetChannelDifference::Flag::f_force),
channel->inputChannel,
filter,
MTP_int(pts),
MTP_int(limit)
)).done([=](const MTPupdates_ChannelDifference &result) {
_rangeDifferenceRequests.remove(channel);
channelRangeDifferenceDone(channel, range, result);
}).fail([=](const RPCError &error) {
_rangeDifferenceRequests.remove(channel);
}).send();
_rangeDifferenceRequests.emplace(channel, requestId);
}
void ApiWrap::channelRangeDifferenceDone(
not_null<ChannelData*> channel,
MsgRange range,
const MTPupdates_ChannelDifference &result) {
auto nextRequestPts = int32(0);
auto isFinal = true;
switch (result.type()) {
case mtpc_updates_channelDifferenceEmpty: {
const auto &d = result.c_updates_channelDifferenceEmpty();
nextRequestPts = d.vpts().v;
isFinal = d.is_final();
} break;
case mtpc_updates_channelDifferenceTooLong: {
const auto &d = result.c_updates_channelDifferenceTooLong();
_session->data().processUsers(d.vusers());
_session->data().processChats(d.vchats());
nextRequestPts = d.vdialog().match([&](const MTPDdialog &data) {
return data.vpts().value_or_empty();
}, [&](const MTPDdialogFolder &data) {
return 0;
});
isFinal = d.is_final();
} break;
case mtpc_updates_channelDifference: {
const auto &d = result.c_updates_channelDifference();
App::main()->feedChannelDifference(d);
nextRequestPts = d.vpts().v;
isFinal = d.is_final();
} break;
}
if (!isFinal && nextRequestPts) {
MTP_LOG(0, ("getChannelDifference { "
"good - after not final channelDifference was received, "
"validating history part }%1"
).arg(cTestMode() ? " TESTMODE" : ""));
channelRangeDifferenceSend(channel, range, nextRequestPts);
}
}
template <typename Request>
void ApiWrap::requestFileReference(
Data::FileOrigin origin,
@ -3418,224 +3350,6 @@ void ApiWrap::parseRecentChannelParticipants(
}, std::move(callbackNotModified));
}
void ApiWrap::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
switch (updates.type()) {
case mtpc_updateShortMessage: {
const auto &d = updates.c_updateShortMessage();
const auto flags = mtpCastFlags(d.vflags().v)
| MTPDmessage::Flag::f_from_id;
const auto peerUserId = d.is_out()
? d.vuser_id()
: MTP_int(_session->userId());
const auto fwd = d.vfwd_from();
_session->data().addNewMessage(
MTP_message(
MTP_flags(flags),
d.vid(),
d.is_out() ? MTP_int(_session->userId()) : d.vuser_id(),
MTP_peerUser(peerUserId),
fwd ? (*fwd) : MTPMessageFwdHeader(),
MTP_int(d.vvia_bot_id().value_or_empty()),
MTP_int(d.vreply_to_msg_id().value_or_empty()),
d.vdate(),
d.vmessage(),
MTP_messageMediaEmpty(),
MTPReplyMarkup(),
MTP_vector<MTPMessageEntity>(d.ventities().value_or_empty()),
MTPint(),
MTPint(),
MTPstring(),
MTPlong(),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>()),
MTPDmessage_ClientFlags(),
NewMessageType::Unread);
} break;
case mtpc_updateShortChatMessage: {
const auto &d = updates.c_updateShortChatMessage();
const auto flags = mtpCastFlags(d.vflags().v) | MTPDmessage::Flag::f_from_id;
const auto fwd = d.vfwd_from();
_session->data().addNewMessage(
MTP_message(
MTP_flags(flags),
d.vid(),
d.vfrom_id(),
MTP_peerChat(d.vchat_id()),
fwd ? (*fwd) : MTPMessageFwdHeader(),
MTP_int(d.vvia_bot_id().value_or_empty()),
MTP_int(d.vreply_to_msg_id().value_or_empty()),
d.vdate(),
d.vmessage(),
MTP_messageMediaEmpty(),
MTPReplyMarkup(),
MTP_vector<MTPMessageEntity>(d.ventities().value_or_empty()),
MTPint(),
MTPint(),
MTPstring(),
MTPlong(),
//MTPMessageReactions(),
MTPVector<MTPRestrictionReason>()),
MTPDmessage_ClientFlags(),
NewMessageType::Unread);
} break;
case mtpc_updateShortSentMessage: {
auto &d = updates.c_updateShortSentMessage();
Q_UNUSED(d); // Sent message data was applied anyway.
} break;
default: Unexpected("Type in applyUpdatesNoPtsCheck()");
}
}
void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) {
switch (update.type()) {
case mtpc_updateNewMessage: {
auto &d = update.c_updateNewMessage();
auto needToAdd = true;
if (d.vmessage().type() == mtpc_message) { // index forwarded messages to links _overview
const auto &data = d.vmessage().c_message();
if (_session->data().checkEntitiesAndViewsUpdate(data)) { // already in blocks
LOG(("Skipping message, because it is already in blocks!"));
needToAdd = false;
}
if (needToAdd && !data.is_from_scheduled()) {
// If we still need to add a new message,
// we should first check if this message is in
// the list of scheduled messages.
// This is necessary to correctly update the file reference.
// Note that when a message is scheduled until online
// while the recipient is already online, the server sends
// an ordinary new message with skipped "from_scheduled" flag.
_session->data().scheduledMessages().checkEntitiesAndUpdate(
data);
}
}
if (needToAdd) {
_session->data().addNewMessage(
d.vmessage(),
MTPDmessage_ClientFlags(),
NewMessageType::Unread);
}
} break;
case mtpc_updateReadMessagesContents: {
const auto &d = update.c_updateReadMessagesContents();
auto possiblyReadMentions = base::flat_set<MsgId>();
for (const auto &msgId : d.vmessages().v) {
if (const auto item = _session->data().message(NoChannel, msgId.v)) {
if (item->isUnreadMedia() || item->isUnreadMention()) {
item->markMediaRead();
_session->data().requestItemRepaint(item);
if (item->out()
&& item->history()->peer->isUser()
&& !App::main()->requestingDifference()) {
item->history()->peer->asUser()->madeAction(base::unixtime::now());
}
}
} else {
// Perhaps it was an unread mention!
possiblyReadMentions.insert(msgId.v);
}
}
checkForUnreadMentions(possiblyReadMentions);
} break;
case mtpc_updateReadHistoryInbox: {
const auto &d = update.c_updateReadHistoryInbox();
const auto peer = peerFromMTP(d.vpeer());
if (const auto history = _session->data().historyLoaded(peer)) {
const auto folderId = d.vfolder_id().value_or_empty();
history->applyInboxReadUpdate(
folderId,
d.vmax_id().v,
d.vstill_unread_count().v);
}
} break;
case mtpc_updateReadHistoryOutbox: {
const auto &d = update.c_updateReadHistoryOutbox();
const auto peer = peerFromMTP(d.vpeer());
if (const auto history = _session->data().historyLoaded(peer)) {
history->outboxRead(d.vmax_id().v);
if (!App::main()->requestingDifference()) {
if (const auto user = history->peer->asUser()) {
user->madeAction(base::unixtime::now());
}
}
}
} break;
case mtpc_updateWebPage: {
auto &d = update.c_updateWebPage();
Q_UNUSED(d); // Web page was updated anyway.
} break;
case mtpc_updateFolderPeers: {
const auto &data = update.c_updateFolderPeers();
auto &owner = _session->data();
for (const auto &peer : data.vfolder_peers().v) {
peer.match([&](const MTPDfolderPeer &data) {
const auto peerId = peerFromMTP(data.vpeer());
if (const auto history = owner.historyLoaded(peerId)) {
if (const auto folderId = data.vfolder_id().v) {
history->setFolder(owner.folder(folderId));
} else {
history->clearFolder();
}
}
});
}
} break;
case mtpc_updateDeleteMessages: {
auto &d = update.c_updateDeleteMessages();
_session->data().processMessagesDeleted(NoChannel, d.vmessages().v);
} break;
case mtpc_updateNewChannelMessage: {
auto &d = update.c_updateNewChannelMessage();
auto needToAdd = true;
if (d.vmessage().type() == mtpc_message) { // index forwarded messages to links _overview
if (_session->data().checkEntitiesAndViewsUpdate(d.vmessage().c_message())) { // already in blocks
LOG(("Skipping message, because it is already in blocks!"));
needToAdd = false;
}
}
if (needToAdd) {
_session->data().addNewMessage(
d.vmessage(),
MTPDmessage_ClientFlags(),
NewMessageType::Unread);
}
} break;
case mtpc_updateEditChannelMessage: {
auto &d = update.c_updateEditChannelMessage();
_session->data().updateEditedMessage(d.vmessage());
} break;
case mtpc_updateEditMessage: {
auto &d = update.c_updateEditMessage();
_session->data().updateEditedMessage(d.vmessage());
} break;
case mtpc_updateChannelWebPage: {
auto &d = update.c_updateChannelWebPage();
Q_UNUSED(d); // Web page was updated anyway.
} break;
case mtpc_updateDeleteChannelMessages: {
auto &d = update.c_updateDeleteChannelMessages();
_session->data().processMessagesDeleted(d.vchannel_id().v, d.vmessages().v);
} break;
default: Unexpected("Type in applyUpdateNoPtsCheck()");
}
}
void ApiWrap::jumpToDate(Dialogs::Key chat, const QDate &date) {
if (const auto peer = chat.peer()) {
jumpToHistoryDate(peer, date);
@ -4346,9 +4060,8 @@ void ApiWrap::forwardMessages(
MTP_vector<MTPlong>(randomIds),
peer->input,
MTP_int(action.options.scheduled)
)).done([=](
const MTPUpdates &updates) {
applyUpdates(updates);
)).done([=](const MTPUpdates &result) {
applyUpdates(result);
if (shared && !--shared->requestsLeft) {
shared->callback();
}

View File

@ -66,6 +66,8 @@ inline QString ToString(uint64 value) {
} // namespace details
class Updates;
template <
typename ...Types,
typename = std::enable_if_t<(sizeof...(Types) > 0)>>
@ -139,6 +141,7 @@ public:
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] Storage::Account &local() const;
[[nodiscard]] Api::Updates &updates() const;
void applyUpdates(
const MTPUpdates &updates,
@ -154,6 +157,8 @@ public:
MTPInputNotifyPeer peer,
const MTPPeerNotifySettings &settings);
void saveCurrentDraftToCloud();
void savePinnedOrder(Data::Folder *folder);
void toggleHistoryArchived(
not_null<History*> history,
@ -194,7 +199,6 @@ public:
void requestBots(not_null<ChannelData*> channel);
void requestAdmins(not_null<ChannelData*> channel);
void requestParticipantsCountDelayed(not_null<ChannelData*> channel);
void requestChannelRangeDifference(not_null<History*> history);
using UpdatedFileReferences = Data::UpdatedFileReferences;
using FileReferencesHandler = FnMut<void(const UpdatedFileReferences&)>;
@ -310,9 +314,6 @@ public:
bool isQuitPrevent();
void applyUpdatesNoPtsCheck(const MTPUpdates &updates);
void applyUpdateNoPtsCheck(const MTPUpdate &update);
void jumpToDate(Dialogs::Key chat, const QDate &date);
void preloadEnoughUnreadMentions(not_null<History*> history);
@ -554,15 +555,6 @@ private:
mtpRequestId req);
void gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result);
void channelRangeDifferenceSend(
not_null<ChannelData*> channel,
MsgRange range,
int32 pts);
void channelRangeDifferenceDone(
not_null<ChannelData*> channel,
MsgRange range,
const MTPupdates_ChannelDifference &result);
void stickerSetDisenabled(mtpRequestId requestId);
void stickersSaveOrder();
@ -709,10 +701,6 @@ private:
base::flat_set<not_null<ChannelData*>> _selfParticipantRequests;
base::flat_map<
not_null<ChannelData*>,
mtpRequestId> _rangeDifferenceRequests;
QMap<WebPageData*, mtpRequestId> _webPagesPending;
base::Timer _webPagesTimer;

View File

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "api/api_updates.h"
#include "calls/calls_instance.h"
#include "lang/lang_file_parser.h"
#include "lang/lang_translator.h"
@ -464,13 +465,14 @@ void Application::forceLogOut(const TextWithEntities &explanation) {
}
void Application::checkLocalTime() {
if (crl::adjust_time()) {
const auto adjusted = crl::adjust_time();
if (adjusted) {
base::Timer::Adjust();
base::ConcurrentTimerEnvironment::Adjust();
base::unixtime::http_invalidate();
if (App::main()) App::main()->checkLastUpdate(true);
} else {
if (App::main()) App::main()->checkLastUpdate(false);
}
if (activeAccount().sessionExists()) {
activeAccount().session().updates().checkLastUpdate(adjusted);
}
}
@ -697,6 +699,9 @@ bool Application::passcodeLocked() const {
void Application::updateNonIdle() {
_lastNonIdleTime = crl::now();
if (activeAccount().sessionExists()) {
activeAccount().session().updates().checkIdleFinish();
}
}
crl::time Application::lastNonIdleTime() const {
@ -794,6 +799,25 @@ rpl::producer<bool> Application::lockValue() const {
_1 || _2);
}
bool Application::hasActiveWindow(not_null<Main::Session*> session) const {
if (App::quitting() || !_window) {
return false;
} else if (const auto controller = _window->sessionController()) {
if (&controller->session() == session) {
return _window->widget()->isActive();
}
}
return false;
}
void Application::saveCurrentDraftsToHistories() {
if (!_window) {
return;
} else if (const auto controller = _window->sessionController()) {
controller->content()->saveFieldToHistoryLocalDraft();
}
}
Window::Controller *Application::activeWindow() const {
return _window.get();
}
@ -897,10 +921,8 @@ void Application::QuitAttempt() {
if (IsAppLaunched()
&& App().activeAccount().sessionExists()
&& !Sandbox::Instance().isSavingSession()) {
if (const auto mainwidget = App::main()) {
if (mainwidget->isQuitPrevent()) {
prevents = true;
}
if (App().activeAccount().session().updates().isQuitPrevent()) {
prevents = true;
}
if (App().activeAccount().session().api().isQuitPrevent()) {
prevents = true;

View File

@ -37,6 +37,7 @@ void quit();
namespace Main {
class Account;
class Session;
} // namespace Main
namespace Ui {
@ -96,6 +97,8 @@ public:
}
// Windows interface.
bool hasActiveWindow(not_null<Main::Session*> session) const;
void saveCurrentDraftsToHistories();
[[nodiscard]] Window::Controller *activeWindow() const;
bool closeActiveWindow();
bool minimizeActiveWindow();

View File

@ -46,7 +46,7 @@ void MegagroupInfo::setLocation(const ChannelLocation &location) {
ChannelData::ChannelData(not_null<Data::Session*> owner, PeerId id)
: PeerData(owner, id)
, inputChannel(MTP_inputChannel(MTP_int(bareId()), MTP_long(0)))
, _ptsWaiter(&owner->session()) {
, _ptsWaiter(&owner->session().updates()) {
Data::PeerFlagValue(
this,
MTPDchannel::Flag::f_megagroup

View File

@ -7,12 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/data_pts_waiter.h"
#include "mainwidget.h"
#include "main/main_session.h"
#include "apiwrap.h"
#include "app.h"
#include "api/api_updates.h"
PtsWaiter::PtsWaiter(not_null<Main::Session*> session) : _session(session) {
PtsWaiter::PtsWaiter(not_null<Api::Updates*> owner) : _owner(owner) {
}
uint64 PtsWaiter::ptsKey(PtsSkippedQueue queue, int32 pts) {
@ -22,11 +19,9 @@ uint64 PtsWaiter::ptsKey(PtsSkippedQueue queue, int32 pts) {
).first->first;
}
void PtsWaiter::setWaitingForSkipped(ChannelData *channel, int32 ms) {
void PtsWaiter::setWaitingForSkipped(ChannelData *channel, crl::time ms) {
if (ms >= 0) {
if (App::main()) {
App::main()->ptsWaiterStartTimerFor(channel, ms);
}
_owner->ptsWaiterStartTimerFor(channel, ms);
_waitingForSkipped = true;
} else {
_waitingForSkipped = false;
@ -34,11 +29,9 @@ void PtsWaiter::setWaitingForSkipped(ChannelData *channel, int32 ms) {
}
}
void PtsWaiter::setWaitingForShortPoll(ChannelData *channel, int32 ms) {
void PtsWaiter::setWaitingForShortPoll(ChannelData *channel, crl::time ms) {
if (ms >= 0) {
if (App::main()) {
App::main()->ptsWaiterStartTimerFor(channel, ms);
}
_owner->ptsWaiterStartTimerFor(channel, ms);
_waitingForShortPoll = true;
} else {
_waitingForShortPoll = false;
@ -47,8 +40,8 @@ void PtsWaiter::setWaitingForShortPoll(ChannelData *channel, int32 ms) {
}
void PtsWaiter::checkForWaiting(ChannelData *channel) {
if (!_waitingForSkipped && !_waitingForShortPoll && App::main()) {
App::main()->ptsWaiterStartTimerFor(channel, -1);
if (!_waitingForSkipped && !_waitingForShortPoll) {
_owner->ptsWaiterStartTimerFor(channel, -1);
}
}
@ -67,10 +60,10 @@ void PtsWaiter::applySkippedUpdates(ChannelData *channel) {
for (auto i = _queue.cbegin(), e = _queue.cend(); i != e; ++i) {
switch (i->second) {
case SkippedUpdate: {
_session->api().applyUpdateNoPtsCheck(_updateQueue[i->first]);
_owner->applyUpdateNoPtsCheck(_updateQueue[i->first]);
} break;
case SkippedUpdates: {
_session->api().applyUpdatesNoPtsCheck(_updatesQueue[i->first]);
_owner->applyUpdatesNoPtsCheck(_updatesQueue[i->first]);
} break;
}
}
@ -136,7 +129,7 @@ bool PtsWaiter::updateAndApply(
}
if (!_waitingForSkipped || _queue.empty()) {
// Optimization - no need to put in queue and back.
_session->api().applyUpdatesNoPtsCheck(updates);
_owner->applyUpdatesNoPtsCheck(updates);
} else {
_updatesQueue.emplace(ptsKey(SkippedUpdates, pts), updates);
applySkippedUpdates(channel);
@ -154,7 +147,7 @@ bool PtsWaiter::updateAndApply(
}
if (!_waitingForSkipped || _queue.empty()) {
// Optimization - no need to put in queue and back.
_session->api().applyUpdateNoPtsCheck(update);
_owner->applyUpdateNoPtsCheck(update);
} else {
_updateQueue.emplace(ptsKey(SkippedUpdate, pts), update);
applySkippedUpdates(channel);

View File

@ -7,9 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Main {
class Session;
} // namespace Main
namespace Api {
class Updates;
} // namespace Api
enum PtsSkippedQueue {
SkippedUpdate,
@ -18,7 +18,7 @@ enum PtsSkippedQueue {
class PtsWaiter {
public:
explicit PtsWaiter(not_null<Main::Session*> session);
explicit PtsWaiter(not_null<Api::Updates*> owner);
// 1s wait for skipped seq or pts in updates.
static constexpr auto kWaitForSkippedTimeout = 1000;
@ -45,8 +45,8 @@ public:
bool waitingForShortPoll() const {
return _waitingForShortPoll;
}
void setWaitingForSkipped(ChannelData *channel, int32 ms); // < 0 - not waiting
void setWaitingForShortPoll(ChannelData *channel, int32 ms); // < 0 - not waiting
void setWaitingForSkipped(ChannelData *channel, crl::time ms); // < 0 - not waiting
void setWaitingForShortPoll(ChannelData *channel, crl::time ms); // < 0 - not waiting
int32 current() const{
return _good;
}
@ -88,7 +88,7 @@ private:
uint64 ptsKey(PtsSkippedQueue queue, int32 pts);
void checkForWaiting(ChannelData *channel);
const not_null<Main::Session*> _session;
const not_null<Api::Updates*> _owner;
base::flat_map<uint64, PtsSkippedQueue> _queue;
base::flat_map<uint64, MTPUpdate> _updateQueue;
base::flat_map<uint64, MTPUpdates> _updatesQueue;

View File

@ -3272,6 +3272,7 @@ void Session::notifyPollUpdateDelayed(not_null<PollData*> poll) {
void Session::sendWebPageGamePollNotifications() {
for (const auto page : base::take(_webpagesUpdated)) {
_webpageUpdates.fire_copy(page);
const auto i = _webpageViews.find(page);
if (i != _webpageViews.end()) {
for (const auto view : i->second) {
@ -3295,6 +3296,26 @@ void Session::sendWebPageGamePollNotifications() {
}
}
rpl::producer<not_null<WebPageData*>> Session::webPageUpdates() const {
return _webpageUpdates.events();
}
void Session::channelDifferenceTooLong(not_null<ChannelData*> channel) {
_channelDifferenceTooLong.fire_copy(channel);
}
rpl::producer<not_null<ChannelData*>> Session::channelDifferenceTooLong() const {
return _channelDifferenceTooLong.events();
}
void Session::historyOutboxRead(not_null<History*> history) {
_historyOutboxReads.fire_copy(history);
}
rpl::producer<not_null<History*>> Session::historyOutboxReads() const {
return _historyOutboxReads.events();
}
void Session::registerItemView(not_null<ViewElement*> view) {
_views[view->data()].push_back(view);
}

View File

@ -549,8 +549,15 @@ public:
void notifyWebPageUpdateDelayed(not_null<WebPageData*> page);
void notifyGameUpdateDelayed(not_null<GameData*> game);
void notifyPollUpdateDelayed(not_null<PollData*> poll);
bool hasPendingWebPageGamePollNotification() const;
[[nodiscard]] bool hasPendingWebPageGamePollNotification() const;
void sendWebPageGamePollNotifications();
[[nodiscard]] rpl::producer<not_null<WebPageData*>> webPageUpdates() const;
void channelDifferenceTooLong(not_null<ChannelData*> channel);
[[nodiscard]] rpl::producer<not_null<ChannelData*>> channelDifferenceTooLong() const;
void historyOutboxRead(not_null<History*> history);
[[nodiscard]] rpl::producer<not_null<History*>> historyOutboxReads() const;
void registerItemView(not_null<ViewElement*> view);
void unregisterItemView(not_null<ViewElement*> view);
@ -868,6 +875,10 @@ private:
base::flat_set<not_null<GameData*>> _gamesUpdated;
base::flat_set<not_null<PollData*>> _pollsUpdated;
rpl::event_stream<not_null<WebPageData*>> _webpageUpdates;
rpl::event_stream<not_null<ChannelData*>> _channelDifferenceTooLong;
rpl::event_stream<not_null<History*>> _historyOutboxReads;
base::flat_multi_map<TimeId, not_null<PollData*>> _pollsClosings;
base::Timer _pollsClosingTimer;

View File

@ -320,6 +320,24 @@ Widget::Widget(
}, lifetime());
}
void Widget::setGeometryWithTopMoved(
const QRect &newGeometry,
int topDelta) {
_topDelta = topDelta;
bool willBeResized = (size() != newGeometry.size());
if (geometry() != newGeometry) {
auto weak = Ui::MakeWeak(this);
setGeometry(newGeometry);
if (!weak) {
return;
}
}
if (!willBeResized) {
resizeEvent(nullptr);
}
_topDelta = 0;
}
void Widget::setupScrollUpButton() {
_scrollToTop->setClickedCallback([=] {
if (_scrollToAnimation.animating()) {
@ -707,8 +725,10 @@ void Widget::escape() {
void Widget::refreshLoadMoreButton(bool mayBlock, bool isBlocked) {
if (!mayBlock) {
_loadMoreChats.destroy();
updateControlsGeometry();
if (_loadMoreChats) {
_loadMoreChats.destroy();
updateControlsGeometry();
}
return;
}
if (!_loadMoreChats) {
@ -1560,8 +1580,7 @@ void Widget::updateControlsGeometry() {
right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y());
auto scrollTop = filterAreaTop + filterAreaHeight;
auto addToScroll = controller()->content()->contentScrollAddToY();
auto newScrollTop = _scroll->scrollTop() + addToScroll;
auto newScrollTop = _scroll->scrollTop() + _topDelta;
auto scrollHeight = height() - scrollTop;
const auto putBottomButton = [&](object_ptr<BottomButton> &button) {
if (button && !button->isHidden()) {
@ -1582,7 +1601,7 @@ void Widget::updateControlsGeometry() {
if (scrollHeight != wasScrollHeight) {
controller()->floatPlayerAreaUpdated().notify(true);
}
if (addToScroll) {
if (_topDelta) {
_scroll->scrollToY(newScrollTop);
} else {
onListScroll();

View File

@ -55,6 +55,11 @@ class Widget : public Window::AbstractSectionWidget, public RPCSender {
public:
Widget(QWidget *parent, not_null<Window::SessionController*> controller);
// When resizing the widget with top edge moved up or down and we
// want to add this top movement to the scroll position, so inner
// content will not move.
void setGeometryWithTopMoved(const QRect &newGeometry, int topDelta);
void updateDragInScroll(bool inScroll);
void searchInChat(Key chat);
@ -233,6 +238,8 @@ private:
object_ptr<QTimer> _draggingScrollTimer = { nullptr };
int _draggingScrollDelta = 0;
int _topDelta = 0;
};
} // namespace Dialogs

View File

@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "storage/storage_account.h"
//#include "storage/storage_feed_messages.h" // #feed
#include "support/support_helper.h"
#include "ui/image/image.h"
@ -336,7 +337,7 @@ void History::clearEditDraft() {
void History::draftSavedToCloud() {
updateChatListEntry();
if (App::main()) App::main()->writeDrafts(this);
session().local().writeDrafts(this);
}
HistoryItemsList History::validateForwardDraft() {
@ -1760,6 +1761,7 @@ void History::outboxRead(MsgId upTo) {
}
}
updateChatListEntry();
session().data().historyOutboxRead(this);
}
void History::outboxRead(not_null<const HistoryItem*> wasRead) {

View File

@ -198,6 +198,12 @@ HistoryInner::HistoryInner(
}) | rpl::start_with_next([this](not_null<const Element*> view) {
mouseActionUpdate();
}, lifetime());
session().data().historyOutboxReads(
) | rpl::filter([=](not_null<History*> history) {
return (_history == history);
}) | rpl::start_with_next([=] {
update();
}, lifetime());
}
Main::Session &HistoryInner::session() const {

View File

@ -512,6 +512,21 @@ HistoryWidget::HistoryWidget(
}
}, lifetime());
session().data().webPageUpdates(
) | rpl::filter([=](not_null<WebPageData*> page) {
return (_previewData == page.get());
}) | rpl::start_with_next([=] {
updatePreview();
}, lifetime());
session().data().channelDifferenceTooLong(
) | rpl::filter([=](not_null<ChannelData*> channel) {
return _peer == channel.get();
}) | rpl::start_with_next([=] {
updateHistoryDownVisibility();
preloadHistoryIfNeeded();
}, lifetime());
session().data().userIsBotChanges(
) | rpl::filter([=](not_null<UserData*> user) {
return (_peer == user.get());
@ -681,6 +696,24 @@ HistoryWidget::HistoryWidget(
setupShortcuts();
}
void HistoryWidget::setGeometryWithTopMoved(
const QRect &newGeometry,
int topDelta) {
_topDelta = topDelta;
bool willBeResized = (size() != newGeometry.size());
if (geometry() != newGeometry) {
auto weak = Ui::MakeWeak(this);
setGeometry(newGeometry);
if (!weak) {
return;
}
}
if (!willBeResized) {
resizeEvent(nullptr);
}
_topDelta = 0;
}
void HistoryWidget::refreshTabbedPanel() {
if (_peer && controller()->hasTabbedSelectorOwnership()) {
createTabbedPanel();
@ -1230,7 +1263,7 @@ void HistoryWidget::saveFieldToHistoryLocalDraft() {
}
void HistoryWidget::onCloudDraftSave() {
controller()->content()->saveDraftToCloud();
controller()->session().api().saveCurrentDraftToCloud();
}
void HistoryWidget::writeDrafts(Data::Draft **localDraft, Data::Draft **editDraft) {
@ -1735,7 +1768,7 @@ void HistoryWidget::showHistory(
// Removing focus from list clears selected and updates top bar.
setFocus();
}
controller()->content()->saveDraftToCloud();
controller()->session().api().saveCurrentDraftToCloud();
if (_migrated) {
_migrated->clearLocalDraft(); // use migrated draft only once
_migrated->clearEditDraft();
@ -2550,7 +2583,7 @@ bool HistoryWidget::doWeReadMentions() const {
&& !_firstLoadRequest
&& !_delayedShowAtRequest
&& !_a_show.animating()
&& App::wnd()->doWeMarkAsRead();
&& controller()->widget()->doWeMarkAsRead();
}
void HistoryWidget::checkHistoryActivation() {
@ -3022,7 +3055,7 @@ void HistoryWidget::saveEditMsgDone(History *history, const MTPUpdates &updates,
if (auto editDraft = history->editDraft()) {
if (editDraft->saveRequestId == req) {
history->clearEditDraft();
controller()->content()->writeDrafts(history);
session().local().writeDrafts(history);
}
}
}
@ -5028,7 +5061,7 @@ void HistoryWidget::updateControlsGeometry() {
}
}
updateHistoryGeometry(false, false, { ScrollChangeAdd, controller()->content()->contentScrollAddToY() });
updateHistoryGeometry(false, false, { ScrollChangeAdd, _topDelta });
updateFieldSize();

View File

@ -112,6 +112,11 @@ public:
void historyLoaded();
// When resizing the widget with top edge moved up or down and we
// want to add this top movement to the scroll position, so inner
// content will not move.
void setGeometryWithTopMoved(const QRect &newGeometry, int topDelta);
void windowShown();
[[nodiscard]] bool doWeReadServerHistory() const;
[[nodiscard]] bool doWeReadMentions() const;
@ -820,4 +825,6 @@ private:
object_ptr<Ui::PlainShadow> _topShadow;
bool _inGrab = false;
int _topDelta = 0;
};

View File

@ -20,6 +20,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/image/image.h"
#include "mainwidget.h"
#include "observer_peer.h"
#include "api/api_updates.h"
#include "apiwrap.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
#include "facades.h"
@ -353,9 +355,11 @@ void Account::startMtp() {
Global::RefConnectionTypeChanged().notify();
}
});
_mtp->setSessionResetHandler([](MTP::ShiftedDcId shiftedDcId) {
if (App::main() && shiftedDcId == MTP::maindc()) {
App::main()->getDifference();
_mtp->setSessionResetHandler([=](MTP::ShiftedDcId shiftedDcId) {
if (sessionExists()) {
if (shiftedDcId == session().api().instance()->mainDcId()) {
session().updates().getDifference();
}
}
});

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "apiwrap.h"
#include "api/api_updates.h"
#include "core/application.h"
#include "core/changelogs.h"
#include "main/main_account.h"
@ -22,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_user.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "window/themes/window_theme.h"
//#include "platform/platform_specific.h"
#include "calls/calls_instance.h"
@ -48,6 +50,7 @@ Session::Session(
, _settings(std::move(settings))
, _saveSettingsTimer([=] { local().writeSettings(); })
, _api(std::make_unique<ApiWrap>(this))
, _updates(std::make_unique<Api::Updates>(this))
, _calls(std::make_unique<Calls::Instance>(this))
, _downloader(std::make_unique<Storage::DownloadManagerMtproto>(_api.get()))
, _uploader(std::make_unique<Storage::Uploader>(_api.get()))
@ -176,4 +179,20 @@ void Session::saveSettingsNowIfNeeded() {
}
}
void Session::addWindow(not_null<Window::SessionController*> controller) {
_windows.emplace(controller);
controller->lifetime().add([=] {
_windows.remove(controller);
});
updates().addActiveChat(controller->activeChatChanges(
) | rpl::map([=](const Dialogs::Key &chat) {
return chat.peer();
}) | rpl::distinct_until_changed());
}
auto Session::windows() const
-> const base::flat_set<not_null<Window::SessionController*>> & {
return _windows;
}
} // namespace Main

View File

@ -15,6 +15,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class ApiWrap;
namespace Api {
class Updates;
} // namespace Api
namespace MTP {
class Instance;
} // namespace MTP
@ -39,6 +43,7 @@ namespace Window {
namespace Notifications {
class System;
} // namespace Notifications
class SessionController;
} // namespace Window
namespace Calls {
@ -81,13 +86,16 @@ public:
}
bool validateSelf(const MTPUser &user);
[[nodiscard]] Storage::DownloadManagerMtproto &downloader() {
[[nodiscard]] Api::Updates &updates() const {
return *_updates;
}
[[nodiscard]] Storage::DownloadManagerMtproto &downloader() const {
return *_downloader;
}
[[nodiscard]] Storage::Uploader &uploader() {
[[nodiscard]] Storage::Uploader &uploader() const {
return *_uploader;
}
[[nodiscard]] Storage::Facade &storage() {
[[nodiscard]] Storage::Facade &storage() const {
return *_storage;
}
[[nodiscard]] Stickers::EmojiPack &emojiStickersPack() const {
@ -112,6 +120,10 @@ public:
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
void saveSettingsNowIfNeeded();
void addWindow(not_null<Window::SessionController*> controller);
[[nodiscard]] auto windows() const
-> const base::flat_set<not_null<Window::SessionController*>> &;
[[nodiscard]] not_null<MTP::Instance*> mtp();
[[nodiscard]] ApiWrap &api() {
return *_api;
@ -143,6 +155,7 @@ private:
base::Timer _saveSettingsTimer;
const std::unique_ptr<ApiWrap> _api;
const std::unique_ptr<Api::Updates> _updates;
const std::unique_ptr<Calls::Instance> _calls;
const std::unique_ptr<Storage::DownloadManagerMtproto> _downloader;
const std::unique_ptr<Storage::Uploader> _uploader;
@ -162,6 +175,8 @@ private:
const std::unique_ptr<Support::Helper> _supportHelper;
base::flat_set<not_null<Window::SessionController*>> _windows;
rpl::lifetime _lifetime;
};

File diff suppressed because it is too large Load Diff

View File

@ -111,6 +111,7 @@ public:
MainWidget(
QWidget *parent,
not_null<Window::SessionController*> controller);
~MainWidget();
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] not_null<Window::SessionController*> controller() const;
@ -118,8 +119,6 @@ public:
[[nodiscard]] bool isMainSectionShown() const;
[[nodiscard]] bool isThirdSectionShown() const;
[[nodiscard]] int contentScrollAddToY() const;
void returnTabbedSelector();
void showAnimated(const QPixmap &bgAnimCache, bool back = false);
@ -146,10 +145,6 @@ public:
void windowShown();
void sentUpdatesReceived(uint64 randomId, const MTPUpdates &updates);
void sentUpdatesReceived(const MTPUpdates &updates) {
return sentUpdatesReceived(0, updates);
}
void historyToDown(History *hist);
void dialogsToUp();
void checkHistoryActivation();
@ -174,16 +169,11 @@ public:
const std::optional<FullMsgId> &oldId);
bool onSendSticker(DocumentData *sticker);
void updateOnlineDisplayIn(int32 msecs);
bool isActive() const;
[[nodiscard]] bool doWeMarkAsRead() const;
bool lastWasOnline() const;
crl::time lastSetOnline() const;
void saveDraftToCloud();
void applyCloudDraft(History *history);
void writeDrafts(History *history);
void saveFieldToHistoryLocalDraft();
int32 dlgsWidth() const;
@ -222,10 +212,6 @@ public:
void searchMessages(const QString &query, Dialogs::Key inChat);
void itemEdited(not_null<HistoryItem*> item);
void checkLastUpdate(bool afterSleep);
bool isIdle() const;
QPixmap cachedBackground(const QRect &forRect, int &x, int &y);
void updateScrollColors();
@ -248,31 +234,13 @@ public:
void choosePeer(PeerId peerId, MsgId showAtMsgId);
void clearBotStartToken(PeerData *peer);
void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer
void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0);
void ctrlEnterSubmitUpdated();
void setInnerFocus();
void scheduleViewIncrement(HistoryItem *item);
void feedChannelDifference(const MTPDupdates_channelDifference &data);
// Made public for ApiWrap, while it is still here.
// Better would be for this to be moved to ApiWrap.
bool requestingDifference() const {
return _ptsWaiter.requesting();
}
void getDifference();
void updateOnline(bool gotOtherOffline = false);
void checkIdleFinish();
bool contentOverlapped(const QRect &globalRect);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount);
void searchInChat(Dialogs::Key chat);
void app_sendBotCallback(
@ -293,10 +261,6 @@ public:
void closeBothPlayers();
bool isQuitPrevent();
~MainWidget();
signals:
void dialogsUpdated();
@ -313,27 +277,7 @@ protected:
bool eventFilter(QObject *o, QEvent *e) override;
private:
using ChannelGetDifferenceTime = QMap<ChannelData*, crl::time>;
enum class ChannelDifferenceRequest {
Unknown,
PtsGapOrShortPoll,
AfterFail,
};
struct DeleteHistoryRequest {
PeerData *peer;
bool justClearHistory;
};
struct DeleteAllFromUserParams {
ChannelData *channel;
UserData *from;
};
void viewsIncrement();
void sendPing();
void getDifferenceByPts();
void getDifferenceAfterFail();
void animationCallback();
void handleAdaptiveLayoutUpdate();
@ -349,7 +293,6 @@ private:
[[nodiscard]] bool saveThirdSectionToStackBack() const;
[[nodiscard]] auto thirdSectionForCurrentMainSection(Dialogs::Key key)
-> std::unique_ptr<Window::SectionMemento>;
void userIsContactUpdated(not_null<UserData*> user);
void setupConnectingWidget();
void createPlayer();
@ -381,28 +324,6 @@ private:
void saveSectionInStack();
void getChannelDifference(
not_null<ChannelData*> channel,
ChannelDifferenceRequest from = ChannelDifferenceRequest::Unknown);
void gotDifference(const MTPupdates_Difference &diff);
bool failDifference(const RPCError &e);
void feedDifference(const MTPVector<MTPUser> &users, const MTPVector<MTPChat> &chats, const MTPVector<MTPMessage> &msgs, const MTPVector<MTPUpdate> &other);
void gotState(const MTPupdates_State &state);
void updSetState(int32 pts, int32 date, int32 qts, int32 seq);
void gotChannelDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff);
bool failChannelDifference(ChannelData *channel, const RPCError &err);
void failDifferenceStartTimerFor(ChannelData *channel);
void mtpUpdateReceived(const MTPUpdates &updates);
void mtpNewSessionCreated();
void feedUpdateVector(
const MTPVector<MTPUpdate> &updates,
bool skipMessageIds = false);
// Doesn't call sendHistoryChangeNotifications itself.
void feedMessageIds(const MTPVector<MTPUpdate> &updates);
// Doesn't call sendHistoryChangeNotifications itself.
void feedUpdate(const MTPUpdate &update);
void usernameResolveDone(QPair<MsgId, QString> msgIdAndStartToken, const MTPcontacts_ResolvedPeer &result);
bool usernameResolveFail(QString name, const RPCError &error);
@ -427,14 +348,9 @@ private:
bool floatPlayerIsVisible(not_null<HistoryItem*> item) override;
void floatPlayerClosed(FullMsgId itemId);
bool getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, crl::time &curTime);
void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req);
bool viewsIncrementFail(const RPCError &error, mtpRequestId req);
void updateStatusDone(const MTPBool &result);
bool updateStatusFail(const RPCError &error);
void refreshResizeAreas();
template <typename MoveCallback, typename FinishCallback>
void createResizeArea(
@ -498,38 +414,6 @@ private:
int _exportTopBarHeight = 0;
int _contentScrollAddToY = 0;
int32 updDate = 0;
int32 updQts = -1;
int32 updSeq = 0;
base::Timer _noUpdatesTimer;
PtsWaiter _ptsWaiter;
ChannelGetDifferenceTime _channelGetDifferenceTimeByPts, _channelGetDifferenceTimeAfterFail;
crl::time _getDifferenceTimeByPts = 0;
crl::time _getDifferenceTimeAfterFail = 0;
base::Timer _byPtsTimer;
QMap<int32, MTPUpdates> _bySeqUpdates;
base::Timer _bySeqTimer;
base::Timer _byMinChannelTimer;
mtpRequestId _onlineRequest = 0;
base::Timer _onlineTimer;
base::Timer _idleFinishTimer;
bool _lastWasOnline = false;
crl::time _lastSetOnline = 0;
bool _isIdle = false;
int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails
QMap<ChannelData*, int32> _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails
base::Timer _failDifferenceTimer;
crl::time _lastUpdateTime = 0;
bool _handlingChannelDifference = false;
QPixmap _cachedBackground;
QRect _cachedFor, _willCacheFor;
int _cachedX = 0;

View File

@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_account.h"
#include "storage/localstorage.h"
#include "apiwrap.h"
#include "api/api_updates.h"
#include "settings/settings_intro.h"
#include "platform/platform_notifications_manager.h"
#include "base/platform/base_platform_info.h"
@ -556,9 +557,12 @@ bool MainWindow::eventFilter(QObject *object, QEvent *e) {
case QEvent::MouseMove: {
const auto position = static_cast<QMouseEvent*>(e)->globalPos();
if (_main && _main->isIdle() && _lastMousePosition != position) {
Core::App().updateNonIdle();
_main->checkIdleFinish();
if (_lastMousePosition != position) {
if (const auto controller = sessionController()) {
if (controller->session().updates().isIdle()) {
Core::App().updateNonIdle();
}
}
}
_lastMousePosition = position;
} break;
@ -1007,7 +1011,9 @@ void MainWindow::sendPaths() {
}
void MainWindow::updateIsActiveHook() {
if (_main) _main->updateOnline();
if (const auto controller = sessionController()) {
controller->session().updates().updateOnline();
}
}
MainWindow::~MainWindow() {

View File

@ -271,7 +271,9 @@ public:
public:
void cancel() {
_sender->senderRequestCancel(_requestId);
if (_requestId) {
_sender->senderRequestCancel(_requestId);
}
}
private:

View File

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "media/audio/media_audio_track.h"
#include "settings/settings_common.h"
#include "api/api_updates.h"
#include "facades.h"
namespace Settings {
@ -87,8 +88,8 @@ auto GenerateCodes() {
}));
});
codes.emplace(qsl("getdifference"), [](SessionController *window) {
if (auto main = App::main()) {
main->getDifference();
if (window) {
window->session().updates().getDifference();
}
});
codes.emplace(qsl("loadcolors"), [](SessionController *window) {

View File

@ -968,6 +968,35 @@ void Account::readMtpData() {
applyReadContext(std::move(context));
}
void Account::writeDrafts(not_null<History*> history) {
Storage::MessageDraft storedLocalDraft, storedEditDraft;
MessageCursor localCursor, editCursor;
if (const auto localDraft = history->localDraft()) {
if (_owner->session().supportMode()
|| !Data::draftsAreEqual(localDraft, history->cloudDraft())) {
storedLocalDraft = Storage::MessageDraft{
localDraft->msgId,
localDraft->textWithTags,
localDraft->previewCancelled
};
localCursor = localDraft->cursor;
}
}
if (const auto editDraft = history->editDraft()) {
storedEditDraft = Storage::MessageDraft{
editDraft->msgId,
editDraft->textWithTags,
editDraft->previewCancelled
};
editCursor = editDraft->cursor;
}
writeDrafts(
history->peer->id,
storedLocalDraft,
storedEditDraft);
writeDraftCursors(history->peer->id, localCursor, editCursor);
}
void Account::writeDrafts(
const PeerId &peer,
const MessageDraft &localDraft,

View File

@ -71,6 +71,7 @@ public:
void writeBackground(const Data::WallPaper &paper, const QImage &image);
bool readBackground();
void writeDrafts(not_null<History*> history);
void writeDrafts(
const PeerId &peer,
const MessageDraft &localDraft,

View File

@ -21,7 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "core/application.h"
#include "mainwindow.h"
#include "mainwidget.h"
#include "api/api_updates.h"
#include "apiwrap.h"
#include "main/main_session.h"
#include "facades.h"
@ -120,9 +120,10 @@ void System::schedule(not_null<HistoryItem*> item) {
auto delay = item->Has<HistoryMessageForwarded>() ? 500 : 100;
const auto t = base::unixtime::now();
const auto ms = crl::now();
const bool isOnline = App::main()->lastWasOnline();
const auto &updates = history->session().updates();
const bool isOnline = updates.lastWasOnline();
const auto otherNotOld = ((cOtherOnline() * 1000LL) + Global::OnlineCloudTimeout() > t * 1000LL);
const bool otherLaterThanMe = (cOtherOnline() * 1000LL + (ms - App::main()->lastSetOnline()) > t * 1000LL);
const bool otherLaterThanMe = (cOtherOnline() * 1000LL + (ms - updates.lastSetOnline()) > t * 1000LL);
if (!isOnline && otherNotOld && otherLaterThanMe) {
delay = Global::NotifyCloudDelay();
} else if (cOtherOnline() >= t) {

View File

@ -144,6 +144,8 @@ SessionController::SessionController(
refreshFiltersMenu();
});
}, session->lifetime());
session->addWindow(this);
}
not_null<::MainWindow*> SessionController::widget() const {