pts handled for channels now

This commit is contained in:
John Preston 2015-09-13 11:41:27 +03:00
parent e41e68b8b3
commit ae6bc3852a
17 changed files with 570 additions and 184 deletions

View File

@ -165,6 +165,12 @@ void ApiWrap::gotReplyTo(ChannelData *channel, const MTPmessages_Messages &msgs,
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(msgs.c_messages_channelMessages());
if (channel) {
channel->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in ApiWrap::gotReplyTo when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
App::feedMsgs(d.vmessages, -1);
@ -566,11 +572,11 @@ void ApiWrap::resolveWebPages() {
}
}
mtpRequestId req = ids.isEmpty() ? 0 : MTP::send(MTPmessages_GetMessages(MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotWebPages), RPCFailHandlerPtr(), 0, 5);
mtpRequestId req = ids.isEmpty() ? 0 : MTP::send(MTPmessages_GetMessages(MTP_vector<MTPint>(ids)), rpcDone(&ApiWrap::gotWebPages, (ChannelData*)0), RPCFailHandlerPtr(), 0, 5);
typedef QVector<mtpRequestId> RequestIds;
RequestIds reqsByIndex(idsByChannel.size(), 0);
for (MessageIdsByChannel::const_iterator i = idsByChannel.cbegin(), e = idsByChannel.cend(); i != e; ++i) {
reqsByIndex[i.value().first] = MTP::send(MTPmessages_GetChannelMessages(i.key()->input, MTP_vector<MTPint>(i.value().second)), rpcDone(&ApiWrap::gotWebPages), RPCFailHandlerPtr(), 0, 5);
reqsByIndex[i.value().first] = MTP::send(MTPmessages_GetChannelMessages(i.key()->input, MTP_vector<MTPint>(i.value().second)), rpcDone(&ApiWrap::gotWebPages, i.key()), RPCFailHandlerPtr(), 0, 5);
}
if (req || !reqsByIndex.isEmpty()) {
for (WebPagesPending::iterator i = _webPagesPending.begin(); i != _webPagesPending.cend(); ++i) {
@ -588,7 +594,7 @@ void ApiWrap::resolveWebPages() {
if (m < INT_MAX) _webPagesTimer.start(m * 1000);
}
void ApiWrap::gotWebPages(const MTPmessages_Messages &msgs, mtpRequestId req) {
void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &msgs, mtpRequestId req) {
const QVector<MTPMessage> *v = 0;
switch (msgs.type()) {
case mtpc_messages_messages: {
@ -607,6 +613,12 @@ void ApiWrap::gotWebPages(const MTPmessages_Messages &msgs, mtpRequestId req) {
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(msgs.c_messages_channelMessages());
if (channel) {
channel->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in ApiWrap::gotWebPages when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
v = &d.vmessages.c_vector().v;

View File

@ -83,7 +83,7 @@ private:
bool gotPeerFailed(PeerData *peer, const RPCError &err);
PeerRequests _peerRequests;
void gotWebPages(const MTPmessages_Messages &result, mtpRequestId req);
void gotWebPages(ChannelData *channel, const MTPmessages_Messages &result, mtpRequestId req);
typedef QMap<WebPageData*, mtpRequestId> WebPagesPending;
WebPagesPending _webPagesPending;
SingleTimer _webPagesTimer;

View File

@ -48,7 +48,7 @@ _text(100) {
void ConfirmBox::init(const QString &text) {
_text.setText(st::boxFont, text, (_infoMsg ? _confirmBoxTextOptions : _textPlainOptions));
_textWidth = st::boxWidth - st::boxPadding.left() - st::boxPadding.right();
_textWidth = st::boxWidth + 10 - st::boxPadding.left() - st::boxPadding.right();
_textHeight = qMin(_text.countHeight(_textWidth), 16 * st::boxFont->height);
setMaxHeight(st::boxPadding.top() + _textHeight + st::boxPadding.bottom() + (_infoMsg ? _close.height() : _confirm.height()));

View File

@ -59,6 +59,8 @@ enum {
MTPPingSendAfterAuto = 30, // send new ping starting from 30 seconds (add to existing container)
MTPPingSendAfter = 45, // send new ping after 45 seconds without ping
MTPChannelGetDifferenceLimit = 100,
MaxSelectedItems = 100,
MaxPhoneTailLength = 18, // rest of the phone number, without country code (seen 12 at least)

View File

@ -772,6 +772,9 @@ void DialogsListWidget::dialogsReceived(const QVector<MTPDialog> &added) {
case mtpc_dialogChannel: {
const MTPDdialogChannel &d(i->c_dialogChannel());
History *history = App::historyFromDialog(peerFromMTP(d.vpeer), d.vunread_important_count.v, d.vread_inbox_max_id.v);
if (history->peer->isChannel()) {
history->peer->asChannel()->ptsReceived(d.vpts.v);
}
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, history);
} break;
}
@ -964,28 +967,6 @@ void DialogsListWidget::clearFilter() {
}
}
void DialogsListWidget::addDialog(const MTPDdialog &dialog) {
History *history = App::historyFromDialog(peerFromMTP(dialog.vpeer), dialog.vunread_count.v, dialog.vread_inbox_max_id.v);
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
history->dialogs = links;
contactsNoDialogs.del(history->peer);
App::main()->applyNotifySetting(MTP_notifyPeer(dialog.vpeer), dialog.vnotify_settings, history);
}
void DialogsListWidget::addDialogChannel(const MTPDdialogChannel &dialogChannel) {
History *history = App::historyFromDialog(peerFromMTP(dialogChannel.vpeer), dialogChannel.vunread_important_count.v, dialogChannel.vread_inbox_max_id.v);
if (!history->lastMsgDate.isNull()) addSavedPeersAfter(history->lastMsgDate);
History::DialogLinks links = dialogs.addToEnd(history);
history->dialogs = links;
contactsNoDialogs.del(history->peer);
App::main()->applyNotifySetting(MTP_notifyPeer(dialogChannel.vpeer), dialogChannel.vnotify_settings, history);
}
void DialogsListWidget::selectSkip(int32 direction) {
if (_state == DefaultState) {
if (!sel) {
@ -1628,6 +1609,9 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
const MTPDdialogChannel &d(i->c_dialogChannel());
Histories::iterator j = App::histories().find(peerFromMTP(d.vpeer));
if (j != App::histories().end()) {
if (j.value()->peer->isChannel()) {
j.value()->peer->asChannel()->ptsReceived(d.vpts.v);
}
App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, j.value());
if (d.vunread_important_count.v >= j.value()->unreadCount) {
j.value()->setUnreadCount(d.vunread_important_count.v, false);
@ -1722,9 +1706,11 @@ bool DialogsWidget::onSearchMessages(bool searchCache) {
QString q = _filter.getLastText().trimmed();
if (q.isEmpty()) {
if (_searchRequest) {
MTP::cancel(_searchRequest);
_searchRequest = 0;
}
if (_peopleRequest) {
MTP::cancel(_peopleRequest);
_peopleRequest = 0;
}
return true;
@ -1734,7 +1720,10 @@ bool DialogsWidget::onSearchMessages(bool searchCache) {
if (i != _searchCache.cend()) {
_searchQuery = q;
_searchFull = false;
_searchRequest = 0;
if (_searchRequest) {
MTP::cancel(_searchRequest);
_searchRequest = 0;
}
searchReceived(true, i.value(), 0);
return true;
}
@ -1742,6 +1731,9 @@ bool DialogsWidget::onSearchMessages(bool searchCache) {
_searchQuery = q;
_searchFull = false;
int32 flags = (_searchInPeer && _searchInPeer->isChannel()) ? MTPmessages_Search_flag_only_important : 0;
if (_searchRequest) {
MTP::cancel(_searchRequest);
}
_searchRequest = MTP::send(MTPmessages_Search(MTP_int(flags), _searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed));
_searchQueries.insert(_searchRequest, _searchQuery);
}
@ -1862,6 +1854,12 @@ void DialogsWidget::searchReceived(bool fromStart, const MTPmessages_Messages &r
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(result.c_messages_channelMessages());
if (_searchInPeer && _searchInPeer->isChannel()) {
_searchInPeer->asChannel()->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in DialogsWidget::searchReceived when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
const QVector<MTPMessage> &msgs(d.vmessages.c_vector().v);
@ -2204,6 +2202,10 @@ void DialogsWidget::onNewGroup() {
bool DialogsWidget::onCancelSearch() {
bool clearing = !_filter.getLastText().isEmpty();
if (_searchRequest) {
MTP::cancel(_searchRequest);
_searchRequest = 0;
}
if (_searchInPeer && !clearing) {
if (!cWideMode()) {
App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId);
@ -2220,6 +2222,10 @@ bool DialogsWidget::onCancelSearch() {
}
void DialogsWidget::onCancelSearchInPeer() {
if (_searchRequest) {
MTP::cancel(_searchRequest);
_searchRequest = 0;
}
if (_searchInPeer) {
if (!cWideMode()) {
App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId);

View File

@ -128,8 +128,6 @@ signals:
private:
void addDialog(const MTPDdialog &dialog);
void addDialogChannel(const MTPDdialogChannel &dialogChannel);
void clearSearchResults(bool clearPeople = true);
DialogsIndexed dialogs;

View File

@ -597,22 +597,8 @@ inline bool isImportantChannelMessage(int32 flags) {
}
HistoryItem *Histories::addToBack(const MTPmessage &msg, int msgState) {
PeerId from_id = 0, to_id = 0;
int32 flags = 0;
switch (msg.type()) {
case mtpc_message:
from_id = msg.c_message().has_from_id() ? peerFromUser(msg.c_message().vfrom_id) : 0;
to_id = peerFromMTP(msg.c_message().vto_id);
flags = msg.c_message().vflags.v;
break;
case mtpc_messageService:
from_id = msg.c_messageService().has_from_id() ? peerFromUser(msg.c_messageService().vfrom_id) : 0;
to_id = peerFromMTP(msg.c_messageService().vto_id);
flags = msg.c_messageService().vflags.v;
break;
}
PeerId peer = (from_id && peerToUser(to_id) == MTP::authedId()) ? from_id : to_id;
PeerId peer = peerFromMessage(msg, &flags);
if (!peer) return 0;
iterator h = find(peer);
@ -1477,6 +1463,10 @@ void History::getReadyFor(MsgId msgId) {
}
}
void History::setNotLoadedAtBottom() {
newLoaded = false;
}
namespace {
uint32 _dialogsPosToTopShift = 0x80000000UL;
}

View File

@ -208,6 +208,7 @@ struct History : public QList<HistoryBlock*> {
void clearNotifications();
bool loadedAtBottom() const; // last message is in the list
void setNotLoadedAtBottom();
bool loadedAtTop() const; // nothing was added after loading history back
bool isReadyFor(MsgId msgId, bool check = false) const; // has messages for showing history at msgId
void getReadyFor(MsgId msgId);

View File

@ -3273,7 +3273,7 @@ bool HistoryWidget::messagesFailed(const RPCError &error, mtpRequestId requestId
return true;
}
void HistoryWidget::messagesReceived(const MTPmessages_Messages &messages, mtpRequestId requestId) {
void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages &messages, mtpRequestId requestId) {
if (!_history) {
_preloadRequest = _preloadDownRequest = _firstLoadRequest = _delayedShowAtRequest = 0;
return;
@ -3298,6 +3298,12 @@ void HistoryWidget::messagesReceived(const MTPmessages_Messages &messages, mtpRe
} break;
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &data(messages.c_messages_channelMessages());
if (peer && peer->isChannel()) {
peer->asChannel()->ptsReceived(data.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in HistoryWidget::messagesReceived when no channel was passed!"));
}
App::feedUsers(data.vusers);
App::feedChats(data.vchats);
histList = &data.vmessages.c_vector().v;
@ -3405,9 +3411,9 @@ void HistoryWidget::firstLoadMessages() {
from = _showAtMsgId;
}
if (_peer->isChannel()) {
_firstLoadRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_firstLoadRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
} else {
_firstLoadRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_firstLoadRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
}
}
@ -3417,9 +3423,9 @@ void HistoryWidget::loadMessages() {
MsgId min = _history->minMsgId();
int32 offset = 0, loadCount = min ? MessagesPerPage : MessagesFirstLoad;
if (_peer->isChannel()) {
_preloadRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(min), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_preloadRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(min), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
} else {
_preloadRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(min), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_preloadRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(min), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
}
}
@ -3431,9 +3437,9 @@ void HistoryWidget::loadMessagesDown() {
int32 loadCount = MessagesPerPage, offset = -loadCount - 1;
if (_peer->isChannel()) {
_preloadDownRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(max + 1), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_preloadDownRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(max + 1), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
} else {
_preloadDownRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(max + 1), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_preloadDownRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(max + 1), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
}
}
@ -3459,9 +3465,9 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
offset = -loadCount / 2;
}
if (_peer->isChannel()) {
_delayedShowAtRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_delayedShowAtRequest = MTP::send(MTPmessages_GetImportantHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
} else {
_delayedShowAtRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived), rpcFail(&HistoryWidget::messagesFailed));
_delayedShowAtRequest = MTP::send(MTPmessages_GetHistory(_peer->input, MTP_int(from), MTP_int(offset), MTP_int(loadCount), MTP_int(0), MTP_int(0)), rpcDone(&HistoryWidget::messagesReceived, _peer), rpcFail(&HistoryWidget::messagesFailed));
}
}

View File

@ -383,7 +383,7 @@ public:
void start();
void messagesReceived(const MTPmessages_Messages &messages, mtpRequestId requestId);
void messagesReceived(PeerData *peer, const MTPmessages_Messages &messages, mtpRequestId requestId);
void historyLoaded();
void windowShown();
@ -517,6 +517,7 @@ public:
void clearAllLoadRequests();
void contactsReceived();
void updateToEndVisibility();
~HistoryWidget();
@ -662,8 +663,6 @@ private:
void countHistoryShowFrom();
void updateToEndVisibility();
void stickersGot(const MTPmessages_AllStickers &stickers);
bool stickersFailed(const RPCError &error);

View File

@ -366,11 +366,12 @@ _started(0), failedObjId(0), _toForwardNameVersion(0), _dialogsWidth(st::dlgMinW
dialogs(this), history(this), profile(0), overview(0), _player(this), _topBar(this),
_forwardConfirm(0), _hider(0), _peerInStack(0), _msgIdInStack(0),
_playerHeight(0), _contentScrollAddToY(0), _mediaType(this), _mediaTypeMask(0),
updGoodPts(0), updLastPts(0), updPtsCount(0), updDate(0), updQts(-1), updSeq(0), updInited(false), updSkipPtsUpdateLevel(0),
updDate(0), updQts(-1), updSeq(0), _getDifferenceTimeByPts(0), _getDifferenceTimeAfterFail(0),
_onlineRequest(0), _lastWasOnline(false), _lastSetOnline(0), _isIdle(false),
_failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _background(0), _api(new ApiWrap(this)) {
setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
_ptsWaiter.setRequesting(true);
updateScrollColors();
connect(window, SIGNAL(resized(const QSize &)), this, SLOT(onParentResize(const QSize &)));
@ -382,8 +383,8 @@ _failDifferenceTimeout(1), _lastUpdateTime(0), _cachedX(0), _cachedY(0), _backgr
connect(&_onlineUpdater, SIGNAL(timeout()), this, SLOT(updateOnlineDisplay()));
connect(&_idleFinishTimer, SIGNAL(timeout()), this, SLOT(checkIdleFinish()));
connect(&_bySeqTimer, SIGNAL(timeout()), this, SLOT(getDifference()));
connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(getDifference()));
connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(getDifferenceForce()));
connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeByPts()));
connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail()));
connect(_api, SIGNAL(fullPeerUpdated(PeerData*)), this, SIGNAL(peerUpdated(PeerData*)));
connect(this, SIGNAL(peerUpdated(PeerData*)), &history, SLOT(peerUpdated(PeerData*)));
connect(&_topBar, SIGNAL(clicked()), this, SLOT(onTopBarClick()));
@ -774,7 +775,7 @@ void MainWidget::deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updat
void MainWidget::deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result) {
const MTPDmessages_affectedHistory &d(result.c_messages_affectedHistory());
updPtsUpdated(d.vpts.v, d.vpts_count.v);
ptsUpdated(d.vpts.v, d.vpts_count.v);
int32 offset = d.voffset.v;
if (!MTP::authedId()) return;
@ -888,8 +889,14 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu
v = &d.vmessages.c_vector().v;
} break;
case mtpc_messages_channelMessages: { // CHANNELS_TODO - all mtpc_messages_channelMessages handle!
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(result.c_messages_channelMessages());
if (peer && peer->isChannel()) {
peer->asChannel()->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in MainWidget::checkedHistory when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
v = &d.vmessages.c_vector().v;
@ -1253,6 +1260,12 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(result.c_messages_channelMessages());
if (peer && peer->isChannel()) {
peer->asChannel()->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in MainWidget::overviewPreloaded when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
h->_overviewCount[type] = d.vcount.v;
@ -1454,6 +1467,12 @@ void MainWidget::photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpR
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(msgs.c_messages_channelMessages());
if (h && h->peer->isChannel()) {
h->peer->asChannel()->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in MainWidget::photosLoaded when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
h->_overviewCount[type] = d.vcount.v;
@ -1491,7 +1510,7 @@ void MainWidget::sendReadRequest(PeerData *peer, MsgId upTo) {
if (peer->isChannel()) {
_readRequests.insert(peer, MTP::send(MTPmessages_ReadChannelHistory(peer->input, MTP_int(upTo)), rpcDone(&MainWidget::channelWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)));
} else {
//_readRequests.insert(peer, MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo), MTP_int(0)), rpcDone(&MainWidget::partWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)));
_readRequests.insert(peer, MTP::send(MTPmessages_ReadHistory(peer->input, MTP_int(upTo), MTP_int(0)), rpcDone(&MainWidget::partWasRead, peer), rpcFail(&MainWidget::readRequestFail, peer)));
}
}
@ -1501,7 +1520,7 @@ void MainWidget::channelWasRead(PeerData *peer, const MTPBool &result) {
void MainWidget::partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result) {
const MTPDmessages_affectedHistory &d(result.c_messages_affectedHistory());
updPtsUpdated(d.vpts.v, d.vpts_count.v);
ptsUpdated(d.vpts.v, d.vpts_count.v);
int32 offset = d.voffset.v;
if (!MTP::authedId() || offset <= 0 || true) {
@ -1530,9 +1549,9 @@ void MainWidget::readRequestDone(PeerData *peer) {
void MainWidget::messagesAffected(PeerData *peer, const MTPmessages_AffectedMessages &result) {
const MTPDmessages_affectedMessages &d(result.c_messages_affectedMessages());
if (peer && peer->isChannel()) {
// CHANNELS_TODO
peer->asChannel()->ptsUpdated(d.vpts.v, d.vpts_count.v);
} else {
updPtsUpdated(d.vpts.v, d.vpts_count.v);
ptsUpdated(d.vpts.v, d.vpts_count.v);
}
}
@ -1931,6 +1950,8 @@ void MainWidget::serviceHistoryDone(const MTPmessages_Messages &msgs) {
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(msgs.c_messages_channelMessages());
LOG(("App Error: received messages.channelMessages in MainWidget::serviceHistoryDone!"));
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
App::feedMsgs(d.vmessages);
@ -2731,7 +2752,7 @@ bool MainWidget::updateFail(const RPCError &e) {
}
void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
if (pts) updGoodPts = updLastPts = updPtsCount = pts;
if (pts) _ptsWaiter.init(pts);
if (updDate < date) updDate = date;
if (qts && updQts < qts) {
updQts = qts;
@ -2755,6 +2776,78 @@ void MainWidget::updSetState(int32 pts, int32 date, int32 qts, int32 seq) {
}
}
void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) {
_channelFailDifferenceTimeout.remove(channel);
int32 timeout = 0, flags = 0;
switch (diff.type()) {
case mtpc_updates_channelDifferenceEmpty: {
const MTPDupdates_channelDifferenceEmpty &d(diff.c_updates_channelDifferenceEmpty());
if (d.has_timeout()) timeout = d.vtimeout.v;
flags = d.vflags.v;
channel->ptsReceived(d.vpts.v);
} break;
case mtpc_updates_channelDifferenceTooLong: {
const MTPDupdates_channelDifferenceTooLong &d(diff.c_updates_channelDifferenceTooLong());
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
App::feedMsgs(d.vmessages);
if (History *h = App::historyLoaded(channel->id)) {
if (HistoryItem *item = App::histItemById(peerToChannel(channel->id), d.vtop_important_message.v)) {
h->setLastMessage(item);
}
if (d.vunread_important_count.v >= h->unreadCount) {
h->setUnreadCount(d.vunread_important_count.v, false);
h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
}
h->setNotLoadedAtBottom();
if (history.peer() == channel) {
history.updateToEndVisibility();
}
}
if (d.has_timeout()) timeout = d.vtimeout.v;
flags = d.vflags.v;
channel->ptsReceived(d.vpts.v);
} break;
case mtpc_updates_channelDifference: {
const MTPDupdates_channelDifference &d(diff.c_updates_channelDifference());
App::feedUsers(d.vusers);
App::feedChats(d.vchats, false);
feedMessageIds(d.vother_updates);
App::feedMsgs(d.vnew_messages, 1);
feedUpdates(d.vother_updates, true);
if (d.has_timeout()) timeout = d.vtimeout.v;
flags = d.vflags.v;
channel->ptsReceived(d.vpts.v);
} break;
}
channel->ptsSetRequesting(false);
if (flags & MTPupdates_ChannelDifference_flag_final) {
MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received }%1").arg(cTestMode() ? " TESTMODE" : ""));
getChannelDifference(channel);
} else if (timeout) {
QTimer::singleShot(timeout * 1000, this, SLOT(getDifference()));
}
App::emitPeerUpdated();
}
bool MainWidget::failChannelDifference(ChannelData *channel, const RPCError &error) {
if (mtpIsFlood(error)) return false;
LOG(("RPC Error in getChannelDifference: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description()));
failDifferenceStartTimerFor(channel);
return true;
}
void MainWidget::gotState(const MTPupdates_State &state) {
const MTPDupdates_state &d(state.c_updates_state());
updSetState(d.vpts.v, d.vdate.v, d.vqts.v, d.vseq.v);
@ -2762,7 +2855,7 @@ void MainWidget::gotState(const MTPupdates_State &state) {
MTP::setGlobalDoneHandler(rpcDone(&MainWidget::updateReceived));
_lastUpdateTime = getms(true);
noUpdatesTimer.start(NoUpdatesTimeout);
updInited = true;
_ptsWaiter.setRequesting(false);
dialogs.loadDialogs();
updateOnline();
@ -2776,13 +2869,13 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
switch (diff.type()) {
case mtpc_updates_differenceEmpty: {
const MTPDupdates_differenceEmpty &d(diff.c_updates_differenceEmpty());
updSetState(updGoodPts, d.vdate.v, updQts, d.vseq.v);
updSetState(_ptsWaiter.current(), d.vdate.v, updQts, d.vseq.v);
MTP::setGlobalDoneHandler(rpcDone(&MainWidget::updateReceived));
_lastUpdateTime = getms(true);
noUpdatesTimer.start(NoUpdatesTimeout);
updInited = true;
_ptsWaiter.setRequesting(false);
App::emitPeerUpdated();
} break;
@ -2793,7 +2886,7 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
const MTPDupdates_state &s(d.vintermediate_state.c_updates_state());
updSetState(s.vpts.v, s.vdate.v, s.vqts.v, s.vseq.v);
updInited = true;
_ptsWaiter.setRequesting(false);
MTP_LOG(0, ("getDifference { good - after a slice of difference was received }%1").arg(cTestMode() ? " TESTMODE" : ""));
getDifference();
@ -2809,49 +2902,85 @@ void MainWidget::gotDifference(const MTPupdates_Difference &diff) {
};
}
uint64 MainWidget::ptsKey(PtsSkippedQueue queue) {
return _byPtsQueue.insert(uint64(uint32(updLastPts)) << 32 | uint64(uint32(updPtsCount)), queue).key();
}
void MainWidget::applySkippedPtsUpdates() {
if (_byPtsTimer.isActive()) _byPtsTimer.stop();
if (_byPtsQueue.isEmpty()) return;
++updSkipPtsUpdateLevel;
for (QMap<uint64, PtsSkippedQueue>::const_iterator i = _byPtsQueue.cbegin(), e = _byPtsQueue.cend(); i != e; ++i) {
switch (i.value()) {
case SkippedUpdate: feedUpdate(_byPtsUpdate.value(i.key())); break;
case SkippedUpdates: handleUpdates(_byPtsUpdates.value(i.key())); break;
// case SkippedSentMessage: sentDataReceived(0, _byPtsSentMessage.value(i.key())); break;
bool MainWidget::getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, uint64 &curTime) {
if (channel) {
if (ms <= 0) {
ChannelGetDifferenceTime::iterator i = channelCurTime.find(channel);
if (i != channelCurTime.cend()) {
channelCurTime.erase(i);
} else {
return false;
}
} else {
uint64 when = getms(true) + ms;
ChannelGetDifferenceTime::iterator i = channelCurTime.find(channel);
if (i != channelCurTime.cend()) {
if (i.value() > when) {
i.value() = when;
} else {
return false;
}
} else {
channelCurTime.insert(channel, when);
}
}
} else {
if (ms <= 0) {
if (curTime) {
curTime = 0;
} else {
return false;
}
} else {
uint64 when = getms(true) + ms;
if (!curTime || curTime > when) {
curTime = when;
} else {
return false;
}
}
}
--updSkipPtsUpdateLevel;
clearSkippedPtsUpdates();
App::emitPeerUpdated();
return true;
}
void MainWidget::clearSkippedPtsUpdates() {
_byPtsQueue.clear();
_byPtsUpdate.clear();
_byPtsUpdates.clear();
// _byPtsSentMessage.clear();
updSkipPtsUpdateLevel = 0;
}
bool MainWidget::updPtsUpdated(int pts, int ptsCount) { // return false if need to save that update and apply later
if (!updInited || updSkipPtsUpdateLevel) return true;
updLastPts = qMax(updLastPts, pts);
updPtsCount += ptsCount;
if (updLastPts == updPtsCount) {
applySkippedPtsUpdates();
updGoodPts = updLastPts;
return true;
} else if (updLastPts < updPtsCount) {
_byPtsTimer.startIfNotActive(1);
} else {
_byPtsTimer.startIfNotActive(WaitForSkippedTimeout);
void MainWidget::ptsWaiterStartTimerFor(ChannelData *channel, int32 ms) {
if (getDifferenceTimeChanged(channel, ms, _channelGetDifferenceTimeByPts, _getDifferenceTimeByPts)) {
onGetDifferenceTimeByPts();
}
return !ptsCount;
}
void MainWidget::failDifferenceStartTimerFor(ChannelData *channel) {
int32 ms = 0;
ChannelFailDifferenceTimeout::iterator i;
if (channel) {
i = _channelFailDifferenceTimeout.find(channel);
if (i == _channelFailDifferenceTimeout.cend()) {
i = _channelFailDifferenceTimeout.insert(channel, 1);
}
ms = i.value() * 1000;
} else {
ms = _failDifferenceTimeout * 1000;
}
if (getDifferenceTimeChanged(channel, ms, _channelGetDifferenceTimeAfterFail, _getDifferenceTimeAfterFail)) {
onGetDifferenceTimeAfterFail();
}
if (channel) {
if (i.value() < 64) i.value() *= 2;
} else {
if (_failDifferenceTimeout < 64) _failDifferenceTimeout *= 2;
}
}
bool MainWidget::ptsUpdated(int32 pts, int32 ptsCount) { // return false if need to save that update and apply later
return _ptsWaiter.updated(0, pts, ptsCount);
}
bool MainWidget::ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdates &updates) {
return _ptsWaiter.updated(0, pts, ptsCount, updates);
}
bool MainWidget::ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdate &update) {
return _ptsWaiter.updated(0, pts, ptsCount, update);
}
void MainWidget::feedDifference(const MTPVector<MTPUser> &users, const MTPVector<MTPChat> &chats, const MTPVector<MTPMessage> &msgs, const MTPVector<MTPUpdate> &other) {
@ -2865,41 +2994,110 @@ void MainWidget::feedDifference(const MTPVector<MTPUser> &users, const MTPVector
}
bool MainWidget::failDifference(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
if (mtpIsFlood(error)) return false;
LOG(("RPC Error: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description()));
_failDifferenceTimer.start(_failDifferenceTimeout * 1000);
if (_failDifferenceTimeout < 64) _failDifferenceTimeout *= 2;
LOG(("RPC Error in getDifference: %1 %2: %3").arg(error.code()).arg(error.type()).arg(error.description()));
failDifferenceStartTimerFor(0);
return true;
}
void MainWidget::getDifferenceForce() {
if (MTP::authedId()) {
updInited = true;
MTP_LOG(0, ("getDifference { force - after get difference failed }%1").arg(cTestMode() ? " TESTMODE" : ""));
getDifference();
void MainWidget::onGetDifferenceTimeByPts() {
if (!MTP::authedId()) return;
uint64 now = getms(true), wait = 0;
if (_getDifferenceTimeByPts) {
if (_getDifferenceTimeByPts > now) {
wait = _getDifferenceTimeByPts - now;
} else {
getDifference();
}
}
for (ChannelGetDifferenceTime::iterator i = _channelGetDifferenceTimeByPts.begin(); i != _channelGetDifferenceTimeByPts.cend();) {
if (i.value() > now) {
wait = qMin(wait, i.value() - now);
++i;
} else {
getChannelDifference(i.key());
i = _channelGetDifferenceTimeByPts.erase(i);
}
}
if (wait) {
_byPtsTimer.start(wait);
} else {
_byPtsTimer.stop();
}
}
void MainWidget::onGetDifferenceTimeAfterFail() {
if (!MTP::authedId()) return;
uint64 now = getms(true), wait = 0;
if (_getDifferenceTimeAfterFail) {
if (_getDifferenceTimeAfterFail > now) {
wait = _getDifferenceTimeAfterFail - now;
} else {
_ptsWaiter.setRequesting(false);
MTP_LOG(0, ("getDifference { force - after get difference failed }%1").arg(cTestMode() ? " TESTMODE" : ""));
getDifference();
}
}
for (ChannelGetDifferenceTime::iterator i = _channelGetDifferenceTimeAfterFail.begin(); i != _channelGetDifferenceTimeAfterFail.cend();) {
if (i.value() > now) {
wait = qMin(wait, i.value() - now);
++i;
} else {
getChannelDifference(i.key());
i = _channelGetDifferenceTimeAfterFail.erase(i);
}
}
if (wait) {
_failDifferenceTimer.start(wait);
} else {
_failDifferenceTimer.stop();
}
}
void MainWidget::getDifference() {
if (this != App::main()) return;
_getDifferenceTimeByPts = 0;
LOG(("Getting difference! no updates timer: %1, remains: %2").arg(noUpdatesTimer.isActive() ? 1 : 0).arg(noUpdatesTimer.remainingTime()));
if (!updInited) return;
if (_ptsWaiter.requesting()) return;
_bySeqUpdates.clear();
_bySeqTimer.stop();
clearSkippedPtsUpdates();
_byPtsTimer.stop();
_ptsWaiter.clearSkippedUpdates();
noUpdatesTimer.stop();
_failDifferenceTimer.stop();
_getDifferenceTimeAfterFail = 0;
LOG(("Getting difference for %1, %2").arg(updGoodPts).arg(updDate));
updInited = false;
LOG(("Getting difference for %1, %2").arg(_ptsWaiter.current()).arg(updDate));
_ptsWaiter.setRequesting(true);
MTP::setGlobalDoneHandler(RPCDoneHandlerPtr(0));
MTP::send(MTPupdates_GetDifference(MTP_int(updGoodPts), MTP_int(updDate), MTP_int(updQts)), rpcDone(&MainWidget::gotDifference), rpcFail(&MainWidget::failDifference));
MTP::send(MTPupdates_GetDifference(MTP_int(_ptsWaiter.current()), MTP_int(updDate), MTP_int(updQts)), rpcDone(&MainWidget::gotDifference), rpcFail(&MainWidget::failDifference));
}
void MainWidget::getChannelDifference(ChannelData *channel, GetChannelDifferenceFrom from) {
if (this != App::main() || !channel) return;
if (from != GetChannelDifferenceFromPtsGap) {
_channelGetDifferenceTimeByPts.remove(channel);
}
LOG(("Getting channel difference!"));
if (!channel->ptsInited() || channel->ptsRequesting()) return;
channel->ptsClearSkippedUpdates();
if (from != GetChannelDifferenceFromFail) {
_channelGetDifferenceTimeAfterFail.remove(channel);
}
LOG(("Getting channel difference for %1").arg(channel->pts()));
channel->ptsSetRequesting(true);
MTP::send(MTPupdates_GetChannelDifference(channel->input, MTP_channelMessagesFilterCollapsed(), MTP_int(channel->pts()), MTP_int(MTPChannelGetDifferenceLimit)), rpcDone(&MainWidget::gotChannelDifference, channel), rpcFail(&MainWidget::failChannelDifference, channel));
}
void MainWidget::mtpPing() {
@ -3504,8 +3702,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
MTP_LOG(0, ("getDifference { good - getting user for updateShortMessage }%1").arg(cTestMode() ? " TESTMODE" : ""));
return getDifference();
}
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdates.insert(ptsKey(SkippedUpdates), updates);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, updates)) {
return;
}
int32 flags = d.vflags.v | MTPDmessage::flag_from_id;
@ -3526,8 +3723,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
if (noFrom) App::api()->requestFullPeer(App::chatLoaded(d.vchat_id.v));
return getDifference();
}
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdates.insert(ptsKey(SkippedUpdates), updates);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, updates)) {
return;
}
int32 flags = d.vflags.v | MTPDmessage::flag_from_id;
@ -3568,8 +3764,7 @@ void MainWidget::handleUpdates(const MTPUpdates &updates, uint64 randomId) {
}
}
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdates.insert(ptsKey(SkippedUpdates), updates);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, updates)) {
return;
}
@ -3589,8 +3784,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
switch (update.type()) {
case mtpc_updateNewMessage: {
const MTPDupdateNewMessage &d(update.c_updateNewMessage());
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links overview
@ -3642,8 +3836,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadMessagesContents: {
const MTPDupdateReadMessagesContents &d(update.c_updateReadMessagesContents());
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
const QVector<MTPint> &v(d.vmessages.c_vector().v);
@ -3662,8 +3855,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadHistoryInbox: {
const MTPDupdateReadHistoryInbox &d(update.c_updateReadHistoryInbox());
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
App::feedInboxRead(peerFromMTP(d.vpeer), d.vmax_id.v);
@ -3671,8 +3863,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadHistoryOutbox: {
const MTPDupdateReadHistoryOutbox &d(update.c_updateReadHistoryOutbox());
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
PeerId id = peerFromMTP(d.vpeer);
@ -3682,8 +3873,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateWebPage: {
const MTPDupdateWebPage &d(update.c_updateWebPage());
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
App::feedWebPage(d.vwebpage);
@ -3693,8 +3883,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateDeleteMessages: {
const MTPDupdateDeleteMessages &d(update.c_updateDeleteMessages());
if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) {
_byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
if (!ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
App::feedWereDeleted(NoChannel, d.vmessages.c_vector().v);
@ -3893,10 +4082,12 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateNewChannelMessage: {
const MTPDupdateNewChannelMessage &d(update.c_updateNewChannelMessage());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
PeerId peer = peerFromMessage(d.vmessage);
if (ChannelData *channel = App::channelLoaded(peerToChannel(peer))) {
if (!channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
}
if (d.vmessage.type() == mtpc_message) { // index forwarded messages to links overview
App::checkEntitiesUpdate(d.vmessage.c_message());
}
@ -3909,29 +4100,44 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateReadChannelInbox: {
const MTPDupdateReadChannelInbox &d(update.c_updateReadChannelInbox());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
App::feedInboxRead(peerFromMTP(d.vpeer), d.vmax_id.v);
} break;
case mtpc_updateDeleteChannelMessages: {
const MTPDupdateDeleteChannelMessages &d(update.c_updateDeleteChannelMessages());
//if (!updPtsUpdated(d.vpts.v, d.vpts_count.v)) { // CHANNELS_TODO
// _byPtsUpdate.insert(ptsKey(SkippedUpdate), update);
// return;
//}
App::feedWereDeleted(peerToChannel(peerFromMTP(d.vpeer)), d.vmessages.c_vector().v);
PeerId peer = peerFromMTP(d.vpeer);
if (ChannelData *channel = App::channelLoaded(peerToChannel(peer))) {
if (!channel->ptsUpdated(d.vpts.v, d.vpts_count.v, update)) {
return;
}
}
App::feedWereDeleted(peerToChannel(peer), d.vmessages.c_vector().v);
history.peerMessagesUpdated();
} break;
case mtpc_updateChannelGroup: {
const MTPDupdateChannelGroup &d(update.c_updateChannelGroup());
if (ChannelData *channel = App::channelLoaded(d.vchannel_id.v)) {
if (d.vgroup.type() == mtpc_messageGroup) {
const MTPDmessageGroup &data(d.vgroup.c_messageGroup());
}
}
} break;
case mtpc_updateChannelTooLong: {
const MTPDupdateChannelTooLong &d(update.c_updateChannelTooLong());
if (ChannelData *channel = App::channelLoaded(d.vchannel_id.v)) {
getChannelDifference(channel);
}
} break;
case mtpc_updateChannelMessageViews: {
const MTPDupdateChannelMessageViews &d(update.c_updateChannelMessageViews());
if (HistoryItem *item = App::histItemById(peerToChannel(peerFromMTP(d.vpeer)), d.vid.v)) {
if (item->from()->id == peerFromMTP(d.vpeer) && item->channelId() != NoChannel) {
// CHANNELS_TODO
}
}
} break;
}

View File

@ -380,6 +380,10 @@ public:
void contactsReceived();
void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer
void handleUpdates(const MTPUpdates &updates, uint64 randomId = 0);
void feedUpdate(const MTPUpdate &update);
~MainWidget();
signals:
@ -414,8 +418,9 @@ public slots:
void onParentResize(const QSize &newSize);
void getDifference();
void onGetDifferenceTimeByPts();
void onGetDifferenceTimeAfterFail();
void mtpPing();
void getDifferenceForce();
void updateOnline(bool gotOtherOffline = false);
void checkIdleFinish();
@ -476,18 +481,25 @@ private:
SingleTimer _updateMutedTimer;
enum GetChannelDifferenceFrom {
GetChannelDifferenceFromUnknown,
GetChannelDifferenceFromPtsGap,
GetChannelDifferenceFromFail,
};
void getChannelDifference(ChannelData *channel, GetChannelDifferenceFrom from = GetChannelDifferenceFromUnknown);
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 feedUpdates(const MTPVector<MTPUpdate> &updates, bool skipMessageIds = false);
void feedMessageIds(const MTPVector<MTPUpdate> &updates);
void feedUpdate(const MTPUpdate &update);
void updateReceived(const mtpPrime *from, const mtpPrime *end);
void handleUpdates(const MTPUpdates &updates, uint64 randomId = 0);
bool updateFail(const RPCError &e);
void usernameResolveDone(QPair<bool, QString> toProfileStartToken, const MTPcontacts_ResolvedPeer &result);
@ -529,12 +541,25 @@ private:
Dropdown _mediaType;
int32 _mediaTypeMask;
int updGoodPts, updLastPts, updPtsCount;
int updDate, updQts, updSeq;
bool updInited;
int updSkipPtsUpdateLevel;
int32 updDate, updQts, updSeq;
SingleTimer noUpdatesTimer;
bool ptsUpdated(int32 pts, int32 ptsCount);
bool ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdates &updates);
bool ptsUpdated(int32 pts, int32 ptsCount, const MTPUpdate &update);
PtsWaiter _ptsWaiter;
typedef QMap<ChannelData*, uint64> ChannelGetDifferenceTime;
ChannelGetDifferenceTime _channelGetDifferenceTimeByPts, _channelGetDifferenceTimeAfterFail;
uint64 _getDifferenceTimeByPts, _getDifferenceTimeAfterFail;
bool getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, uint64 &curTime);
SingleTimer _byPtsTimer;
QMap<int32, MTPUpdates> _bySeqUpdates;
SingleTimer _bySeqTimer;
mtpRequestId _onlineRequest;
SingleTimer _onlineTimer, _onlineUpdater, _idleFinishTimer;
bool _lastWasOnline;
@ -552,27 +577,9 @@ private:
typedef QMap<PeerData*, mtpRequestId> OverviewsPreload;
OverviewsPreload _overviewPreload[OverviewCount], _overviewLoad[OverviewCount];
enum PtsSkippedQueue {
SkippedUpdate,
SkippedUpdates,
// SkippedSentMessage,
SkippedStatedMessage,
SkippedStatedMessages
};
uint64 ptsKey(PtsSkippedQueue queue);
void applySkippedPtsUpdates();
void clearSkippedPtsUpdates();
bool updPtsUpdated(int pts, int ptsCount);
QMap<uint64, PtsSkippedQueue> _byPtsQueue;
QMap<uint64, MTPUpdate> _byPtsUpdate;
QMap<uint64, MTPUpdates> _byPtsUpdates;
// QMap<uint64, MTPmessages_SentMessage> _byPtsSentMessage;
SingleTimer _byPtsTimer;
QMap<int32, MTPUpdates> _bySeqUpdates;
SingleTimer _bySeqTimer;
int32 _failDifferenceTimeout; // growing timeout for getDifference calls, if it fails
typedef QMap<ChannelData*, int32> ChannelFailDifferenceTimeout;
ChannelFailDifferenceTimeout _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails
SingleTimer _failDifferenceTimer;
uint64 _lastUpdateTime;

View File

@ -1950,6 +1950,8 @@ void MTProtoConnectionPrivate::socketStart(bool afterConfig) {
}
void MTProtoConnectionPrivate::restart(bool maybeBadKey) {
_needSessionReset = true;
QReadLocker lockFinished(&sessionDataMutex);
if (!sessionData) return;

View File

@ -29,7 +29,7 @@ mtpRequestId MTProtoSession::send(const TRequest &request, RPCResponseHandler ca
reqSerialized->msDate = getms(true); // > 0 - can send without container
reqSerialized->needsLayer = needsLayer;
if (after) reqSerialized->after = _mtp_internal::getRequest(after);
// if (after) reqSerialized->after = _mtp_internal::getRequest(after);
requestId = _mtp_internal::storeRequest(reqSerialized, callbacks);
sendPrepared(reqSerialized, msCanWait);

View File

@ -325,6 +325,12 @@ void OverviewInner::searchReceived(bool fromStart, const MTPmessages_Messages &r
case mtpc_messages_channelMessages: {
const MTPDmessages_channelMessages &d(result.c_messages_channelMessages());
if (_peer && _peer->isChannel()) {
_peer->asChannel()->ptsReceived(d.vpts.v);
} else {
LOG(("App Error: received messages.channelMessages in OverviewInner::searchReceived when no channel was passed!"));
}
App::feedUsers(d.vusers);
App::feedChats(d.vchats);
messages = &d.vmessages.c_vector().v;

View File

@ -362,6 +362,71 @@ void ChannelData::setName(const QString &newName, const QString &usern) {
}
}
uint64 PtsWaiter::ptsKey(PtsSkippedQueue queue) {
return _queue.insert(uint64(uint32(_last)) << 32 | uint64(uint32(_count)), queue).key();
}
void PtsWaiter::applySkippedUpdates(ChannelData *channel) {
if (!App::main()) return;
App::main()->ptsWaiterStartTimerFor(channel, -1);
if (_queue.isEmpty()) return;
++_applySkippedLevel;
for (QMap<uint64, PtsSkippedQueue>::const_iterator i = _queue.cbegin(), e = _queue.cend(); i != e; ++i) {
switch (i.value()) {
case SkippedUpdate: App::main()->feedUpdate(_updateQueue.value(i.key())); break;
case SkippedUpdates: App::main()->handleUpdates(_updatesQueue.value(i.key())); break;
}
}
--_applySkippedLevel;
clearSkippedUpdates();
App::emitPeerUpdated();
}
void PtsWaiter::clearSkippedUpdates() {
_queue.clear();
_updateQueue.clear();
_updatesQueue.clear();
_applySkippedLevel = 0;
}
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 count) { // return false if need to save that update and apply later
if (_requesting || _applySkippedLevel) return true;
if (!inited()) {
init(pts);
return true;
}
_last = qMax(_last, pts);
_count += count;
if (_last == _count) {
applySkippedUpdates(channel);
_good = _last;
return true;
} else if (_last < _count) {
if (App::main()) App::main()->ptsWaiterStartTimerFor(channel, 1);
} else {
if (App::main()) App::main()->ptsWaiterStartTimerFor(channel, WaitForSkippedTimeout);
}
return !count;
}
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 ptsCount, const MTPUpdates &updates) {
if (!updated(channel, pts, ptsCount)) {
_updatesQueue.insert(ptsKey(SkippedUpdates), updates);
return false;
}
return true;
}
bool PtsWaiter::updated(ChannelData *channel, int32 pts, int32 ptsCount, const MTPUpdate &update) {
if (!updated(channel, pts, ptsCount)) {
_updateQueue.insert(ptsKey(SkippedUpdate), update);
return false;
}
return true;
}
void PhotoLink::onClick(Qt::MouseButton button) const {
if (button == Qt::LeftButton) {
App::wnd()->showPhoto(this, App::hoveredLinkItem());

View File

@ -86,6 +86,22 @@ inline MTPpeer peerToMTP(const PeerId &id) {
}
return MTP_peerUser(MTP_int(0));
}
inline PeerId peerFromMessage(const MTPmessage &msg, int32 *msgFlags = 0) {
PeerId from_id = 0, to_id = 0;
switch (msg.type()) {
case mtpc_message:
from_id = msg.c_message().has_from_id() ? peerFromUser(msg.c_message().vfrom_id) : 0;
to_id = peerFromMTP(msg.c_message().vto_id);
if (msgFlags) *msgFlags = msg.c_message().vflags.v;
break;
case mtpc_messageService:
from_id = msg.c_messageService().has_from_id() ? peerFromUser(msg.c_messageService().vfrom_id) : 0;
to_id = peerFromMTP(msg.c_messageService().vto_id);
if (msgFlags) *msgFlags = msg.c_messageService().vflags.v;
break;
}
return (from_id && peerToUser(to_id) == MTP::authedId()) ? from_id : to_id;
}
typedef uint64 PhotoId;
typedef uint64 VideoId;
@ -355,6 +371,47 @@ public:
QString invitationUrl;
};
enum PtsSkippedQueue {
SkippedUpdate,
SkippedUpdates,
};
class PtsWaiter {
public:
PtsWaiter() : _good(0), _last(0), _count(0), _applySkippedLevel(0), _requesting(false) {
}
void init(int32 pts) {
_good = _last = _count = pts;
clearSkippedUpdates();
}
bool inited() const {
return _good > 0;
}
void setRequesting(bool isRequesting) {
_requesting = isRequesting;
}
bool requesting() const {
return _requesting;
}
int32 current() const{
return _good;
}
bool updated(ChannelData *channel, int32 pts, int32 count);
bool updated(ChannelData *channel, int32 pts, int32 count, const MTPUpdates &updates);
bool updated(ChannelData *channel, int32 pts, int32 count, const MTPUpdate &update);
void applySkippedUpdates(ChannelData *channel);
void clearSkippedUpdates();
private:
uint64 ptsKey(PtsSkippedQueue queue);
QMap<uint64, PtsSkippedQueue> _queue;
QMap<uint64, MTPUpdate> _updateQueue;
QMap<uint64, MTPUpdates> _updatesQueue;
int32 _good, _last, _count;
int32 _applySkippedLevel;
bool _requesting;
};
class ChannelData : public PeerData {
public:
@ -378,6 +435,35 @@ public:
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
// ImagePtr photoFull;
QString invitationUrl;
void ptsReceived(int32 pts) {
_ptsWaiter.updated(this, pts, 0);
}
bool ptsUpdated(int32 pts, int32 count) {
return _ptsWaiter.updated(this, pts, count);
}
bool ptsUpdated(int32 pts, int32 count, const MTPUpdate &update) {
return _ptsWaiter.updated(this, pts, count, update);
}
int32 pts() const {
return _ptsWaiter.current();
}
bool ptsInited() const {
return _ptsWaiter.inited();
}
bool ptsRequesting() const {
return _ptsWaiter.requesting();
}
void ptsSetRequesting(bool isRequesting) {
return _ptsWaiter.setRequesting(isRequesting);
}
void ptsClearSkippedUpdates() {
return _ptsWaiter.clearSkippedUpdates();
}
private:
PtsWaiter _ptsWaiter;
};
inline UserData *PeerData::asUser() {