diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 6776ac1e54..f3c3c7e8c4 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2813,6 +2813,7 @@ void ApiWrap::forwardMessages( randomIds.push_back(MTP_long(randomId)); } sendAccumulated(); + _session->data().sendHistoryChangeNotifications(); } void ApiWrap::shareContact( @@ -2828,7 +2829,7 @@ void ApiWrap::shareContact( not_null user, const SendOptions &options) { const auto userId = peerToUser(user->id); - const auto phone = Auth().data().findContactPhone(user); + const auto phone = _session->data().findContactPhone(user); if (phone.isEmpty()) { return; } diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 972cb7f185..3b2eaaf6e9 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -238,6 +238,20 @@ rpl::producer> Session::historyCleared() const { return _historyCleared.events(); } +void Session::notifyHistoryChangeDelayed(not_null history) { + _historiesChanged.insert(history); +} + +rpl::producer> Session::historyChanged() const { + return _historyChanged.events(); +} + +void Session::sendHistoryChangeNotifications() { + for (const auto history : base::take(_historiesChanged)) { + _historyChanged.fire_copy(history); + } +} + void Session::removeMegagroupParticipant( not_null channel, not_null user) { diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index af827cf95f..27bbda6866 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -84,6 +84,9 @@ public: rpl::producer> itemRemoved() const; void notifyHistoryCleared(not_null history); rpl::producer> historyCleared() const; + void notifyHistoryChangeDelayed(not_null history); + rpl::producer> historyChanged() const; + void sendHistoryChangeNotifications(); using MegagroupParticipant = std::tuple< not_null, @@ -448,6 +451,8 @@ private: rpl::event_stream> _itemRemoved; rpl::event_stream> _historyUnloaded; rpl::event_stream> _historyCleared; + base::flat_set> _historiesChanged; + rpl::event_stream> _historyChanged; rpl::event_stream _megagroupParticipantRemoved; rpl::event_stream _megagroupParticipantAdded; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 607624c032..5c0a90ec32 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -671,7 +671,9 @@ void checkForSwitchInlineButton(HistoryItem *item) { } // namespace -HistoryItem *Histories::addNewMessage(const MTPMessage &msg, NewMessageType type) { +HistoryItem *Histories::addNewMessage( + const MTPMessage &msg, + NewMessageType type) { auto peer = peerFromMessage(msg); if (!peer) return nullptr; @@ -1204,6 +1206,7 @@ not_null History::addNewItem( newItemAdded(item); } + Auth().data().notifyHistoryChangeDelayed(this); return item; } diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 280d88287b..5333d5401c 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -295,7 +295,7 @@ void HistoryItem::removeMainView() { if (const auto channelHistory = _history->asChannelHistory()) { channelHistory->messageDetached(this); } - _history->setPendingResize(); + Auth().data().notifyHistoryChangeDelayed(_history); view->removeFromBlock(); _mainView = nullptr; } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 25292f21a4..16065c2419 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -563,6 +563,10 @@ HistoryWidget::HistoryWidget(QWidget *parent, not_null cont ) | rpl::start_with_next( [this](auto item) { repaintHistoryItem(item); }, lifetime()); + Auth().data().historyChanged( + ) | rpl::start_with_next( + [=](auto history) { handleHistoryChange(history); }, + lifetime()); subscribe(Auth().data().contactsLoaded(), [this](bool) { if (_peer) { updateReportSpamStatus(); @@ -4353,7 +4357,7 @@ void HistoryWidget::sendFileConfirmed( App::main()->historyToDown(_history); } App::main()->dialogsToUp(); - peerMessagesUpdated(file->to.peer); + Auth().data().sendHistoryChangeNotifications(); } void HistoryWidget::onPhotoUploaded( @@ -4495,17 +4499,26 @@ void HistoryWidget::onReportSpamClear() { controller()->showBackFromStack(); } -void HistoryWidget::peerMessagesUpdated(PeerId peer) { - if (_peer && _list && peer == _peer->id) { +void HistoryWidget::handleHistoryChange(not_null history) { + if (_list && (_history == history || _migrated == history)) { updateHistoryGeometry(); updateBotKeyboard(); if (!_scroll->isHidden()) { - bool unblock = isBlocked(), botStart = isBotStart(), joinChannel = isJoinChannel(), muteUnmute = isMuteUnmute(); - bool upd = (_unblock->isHidden() == unblock); - if (!upd && !unblock) upd = (_botStart->isHidden() == botStart); - if (!upd && !unblock && !botStart) upd = (_joinChannel->isHidden() == joinChannel); - if (!upd && !unblock && !botStart && !joinChannel) upd = (_muteUnmute->isHidden() == muteUnmute); - if (upd) { + const auto unblock = isBlocked(); + const auto botStart = isBotStart(); + const auto joinChannel = isJoinChannel(); + const auto muteUnmute = isMuteUnmute(); + const auto update = false + || (_unblock->isHidden() == unblock) + || (!unblock && _botStart->isHidden() == botStart) + || (!unblock + && !botStart + && _joinChannel->isHidden() == joinChannel) + || (!unblock + && !botStart + && !joinChannel + && _muteUnmute->isHidden() == muteUnmute); + if (update) { updateControlsVisibility(); updateControlsGeometry(); } @@ -4513,10 +4526,6 @@ void HistoryWidget::peerMessagesUpdated(PeerId peer) { } } -void HistoryWidget::peerMessagesUpdated() { - if (_list) peerMessagesUpdated(_peer->id); -} - void HistoryWidget::grapWithoutTopBarShadow() { grabStart(); _topShadow->hide(); @@ -4856,8 +4865,9 @@ int HistoryWidget::unreadBarTop() const { } return nullptr; }; - if (HistoryItem *bar = getUnreadBar()) { - int result = _list->itemTop(bar) + HistoryMessageUnreadBar::marginTop(); + if (const auto bar = getUnreadBar()) { + auto result = _list->itemTop(bar) + + HistoryMessageUnreadBar::marginTop(); if (bar->Has()) { result += bar->Get()->height(); } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 7abaee0653..b2ff35d254 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -199,8 +199,6 @@ public: void loadMessagesDown(); void firstLoadMessages(); void delayedShowAt(MsgId showAtMsgId); - void peerMessagesUpdated(PeerId peer); - void peerMessagesUpdated(); void newUnreadMsg(History *history, HistoryItem *item); void historyToDown(History *history); @@ -466,6 +464,7 @@ private: void handlePeerUpdate(); void setMembersShowAreaActive(bool active); void forwardItems(MessageIdsList &&items); + void handleHistoryChange(not_null history); void highlightMessage(MsgId universalMessageId); void adjustHighlightedMessageToMigrated(); @@ -746,7 +745,7 @@ private: int32 _debug_preloadDownLoadCount = 0; PeerId _debug_preloadDownPeer = 0; - MsgId _delayedShowAtMsgId = -1; // wtf? + MsgId _delayedShowAtMsgId = -1; mtpRequestId _delayedShowAtRequest = 0; object_ptr _topBar; @@ -754,8 +753,10 @@ private: QPointer _list; History *_migrated = nullptr; History *_history = nullptr; - bool _historyInited = false; // Initial updateHistoryGeometry() was called. - bool _updateHistoryGeometryRequired = false; // If updateListSize() was called without updateHistoryGeometry(). + // Initial updateHistoryGeometry() was called. + bool _historyInited = false; + // If updateListSize() was called without updateHistoryGeometry(). + bool _updateHistoryGeometryRequired = false; int _addToScroll = 0; int _lastScrollTop = 0; // gifs optimization diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 8615d13b40..d3d5664b05 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -674,16 +674,11 @@ void MainWidget::finishForwarding(not_null history) { if (!toForward.empty()) { auto options = ApiWrap::SendOptions(history); Auth().api().forwardMessages(std::move(toForward), options); - - if (_history->peer() == history->peer) { - _history->peerMessagesUpdated(); - } cancelForwarding(history); } historyToDown(history); dialogsToUp(); - _history->peerMessagesUpdated(history->peer->id); } void MainWidget::updateMutedIn(TimeMs delay) { @@ -1243,7 +1238,6 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu history->clear(true); history->addNewerSlice(QVector()); history->asChannelHistory()->insertJoinedMessage(true); - _history->peerMessagesUpdated(peer->id); } } } else { @@ -1261,12 +1255,12 @@ void MainWidget::checkedHistory(PeerData *peer, const MTPmessages_Messages &resu && channel->amIn()) { if (const auto from = App::userLoaded(channel->inviter)) { history->asChannelHistory()->insertJoinedMessage(true); - _history->peerMessagesUpdated(peer->id); } } } } } + Auth().data().sendHistoryChangeNotifications(); } bool MainWidget::sendMessageFail(const RPCError &error) { @@ -1857,9 +1851,7 @@ void MainWidget::insertCheckedServiceNotification(const TextWithEntities &messag MTPlong()), NewMessageUnread); } - if (item) { - _history->peerMessagesUpdated(item->history()->peer->id); - } + Auth().data().sendHistoryChangeNotifications(); } void MainWidget::serviceHistoryDone(const MTPmessages_Messages &msgs) { @@ -3457,11 +3449,14 @@ void MainWidget::onUpdateNotifySettings() { } } -void MainWidget::feedUpdateVector(const MTPVector &updates, bool skipMessageIds) { +void MainWidget::feedUpdateVector( + const MTPVector &updates, + bool skipMessageIds) { for_const (auto &update, updates.v) { if (skipMessageIds && update.type() == mtpc_updateMessageID) continue; feedUpdate(update); } + Auth().data().sendHistoryChangeNotifications(); } void MainWidget::feedMessageIds(const MTPVector &updates) { @@ -3603,7 +3598,9 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha } } -void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_ChannelDifference &diff) { +void MainWidget::gotRangeDifference( + ChannelData *channel, + const MTPupdates_ChannelDifference &diff) { int32 nextRequestPts = 0; bool isFinal = true; switch (diff.type()) { @@ -3641,9 +3638,13 @@ void MainWidget::gotRangeDifference(ChannelData *channel, const MTPupdates_Chann } if (!isFinal) { - if (History *h = App::historyLoaded(channel->id)) { - MTP_LOG(0, ("getChannelDifference { good - after not final channelDifference was received, validating history part }%1").arg(cTestMode() ? " TESTMODE" : "")); - h->asChannelHistory()->getRangeDifferenceNext(nextRequestPts); + if (const auto history = App::historyLoaded(channel->id)) { + MTP_LOG(0, ("getChannelDifference { " + "good - after not final channelDifference was received, " + "validating history part }%1" + ).arg(cTestMode() ? " TESTMODE" : "")); + history->asChannelHistory()->getRangeDifferenceNext( + nextRequestPts); } } } @@ -3787,14 +3788,17 @@ bool MainWidget::ptsUpdateAndApply(int32 pts, int32 ptsCount) { return _ptsWaiter.updateAndApply(nullptr, pts, ptsCount); } -void MainWidget::feedDifference(const MTPVector &users, const MTPVector &chats, const MTPVector &msgs, const MTPVector &other) { +void MainWidget::feedDifference( + const MTPVector &users, + const MTPVector &chats, + const MTPVector &msgs, + const MTPVector &other) { Auth().checkAutoLock(); App::feedUsers(users); App::feedChats(chats); feedMessageIds(other); App::feedMsgs(msgs, NewMessageUnread); feedUpdateVector(other, true); - _history->peerMessagesUpdated(); } bool MainWidget::failDifference(const RPCError &error) { @@ -4012,12 +4016,11 @@ void MainWidget::onSelfParticipantUpdated(ChannelData *channel) { checkPeerHistory(channel); } else { history->asChannelHistory()->checkJoinedMessage(true); - _history->peerMessagesUpdated(channel->id); } } else if (history) { history->asChannelHistory()->checkJoinedMessage(); - _history->peerMessagesUpdated(channel->id); } + Auth().data().sendHistoryChangeNotifications(); } bool MainWidget::contentOverlapped(const QRect &globalRect) { @@ -4599,7 +4602,9 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { case mtpc_updates: { auto &d = updates.c_updates(); if (d.vseq.v) { - if (d.vseq.v <= updSeq) return; + if (d.vseq.v <= updSeq) { + return; + } if (d.vseq.v > updSeq + 1) { _bySeqUpdates.insert(d.vseq.v, updates); return _bySeqTimer.start(WaitForSkippedTimeout); @@ -4616,7 +4621,9 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { case mtpc_updatesCombined: { auto &d = updates.c_updatesCombined(); if (d.vseq_start.v) { - if (d.vseq_start.v <= updSeq) return; + if (d.vseq_start.v <= updSeq) { + return; + } if (d.vseq_start.v > updSeq + 1) { _bySeqUpdates.insert(d.vseq_start.v, updates); return _bySeqTimer.start(WaitForSkippedTimeout); @@ -4647,10 +4654,6 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { return getDifference(); } if (ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, updates)) { - // We could've added an item. - // Better would be for history to be subscribed to new messages. - _history->peerMessagesUpdated(); - // Update date as well. updSetState(0, d.vdate.v, updQts, updSeq); } @@ -4671,10 +4674,6 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { return getDifference(); } if (ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, updates)) { - // We could've added an item. - // Better would be for history to be subscribed to new messages. - _history->peerMessagesUpdated(); - // Update date as well. updSetState(0, d.vdate.v, updQts, updSeq); } @@ -4724,6 +4723,7 @@ void MainWidget::feedUpdates(const MTPUpdates &updates, uint64 randomId) { return getDifference(); } break; } + Auth().data().sendHistoryChangeNotifications(); } void MainWidget::feedUpdate(const MTPUpdate &update) { @@ -4735,18 +4735,16 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { DataIsLoadedResult isDataLoaded = allDataLoadedForMessage(d.vmessage); if (!requestingDifference() && isDataLoaded != DataIsLoadedResult::Ok) { - MTP_LOG(0, ("getDifference { good - after not all data loaded in updateNewMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); + MTP_LOG(0, ("getDifference { good - " + "after not all data loaded in updateNewMessage }%1" + ).arg(cTestMode() ? " TESTMODE" : "")); // This can be if this update was created by grouping // some short message update into an updates vector. return getDifference(); } - if (ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update)) { - // We could've added an item. - // Better would be for history to be subscribed to new messages. - _history->peerMessagesUpdated(); - } + ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update); } break; case mtpc_updateNewChannelMessage: { @@ -4754,7 +4752,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { auto channel = App::channelLoaded(peerToChannel(peerFromMessage(d.vmessage))); auto isDataLoaded = allDataLoadedForMessage(d.vmessage); if (!requestingDifference() && (!channel || isDataLoaded != DataIsLoadedResult::Ok)) { - MTP_LOG(0, ("getDifference { good - after not all data loaded in updateNewChannelMessage }%1").arg(cTestMode() ? " TESTMODE" : "")); + MTP_LOG(0, ("getDifference { good - " + "after not all data loaded in updateNewChannelMessage }%1" + ).arg(cTestMode() ? " TESTMODE" : "")); // Request last active supergroup participants if the 'from' user was not loaded yet. // This will optimize similar getDifference() calls for almost all next messages. @@ -4772,17 +4772,10 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { if (channel && !_handlingChannelDifference) { if (channel->ptsRequesting()) { // skip global updates while getting channel difference return; - } else if (channel->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update)) { - // We could've added an item. - // Better would be for history to be subscribed to new messages. - _history->peerMessagesUpdated(); } + channel->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update); } else { Auth().api().applyUpdateNoPtsCheck(update); - - // We could've added an item. - // Better would be for history to be subscribed to new messages. - _history->peerMessagesUpdated(); } } break; @@ -4800,7 +4793,6 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { if (wasLast && !history->lastMsg) { checkPeerHistory(history->peer); } - _history->peerMessagesUpdated(); } else { if (existing) { existing->destroy(); @@ -4905,11 +4897,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateDeleteMessages: { auto &d = update.c_updateDeleteMessages(); - if (ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update)) { - // We could've removed some items. - // Better would be for history to be subscribed to removed messages. - _history->peerMessagesUpdated(); - } + ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update); } break; case mtpc_updateDeleteChannelMessages: { @@ -4919,16 +4907,9 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { if (channel && !_handlingChannelDifference) { if (channel->ptsRequesting()) { // skip global updates while getting channel difference return; - } else if (channel->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update)) { - // We could've removed some items. - // Better would be for history to be subscribed to removed messages. - _history->peerMessagesUpdated(); } + channel->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v, update); } else { - // We could've removed some items. - // Better would be for history to be subscribed to removed messages. - _history->peerMessagesUpdated(); - Auth().api().applyUpdateNoPtsCheck(update); } } break; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 4aa5df27a9..69b6a523bd 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -287,7 +287,6 @@ public: void ptsWaiterStartTimerFor(ChannelData *channel, int32 ms); // ms <= 0 - stop timer void feedUpdates(const MTPUpdates &updates, uint64 randomId = 0); - void feedUpdate(const MTPUpdate &update); void ctrlEnterSubmitUpdated(); void setInnerFocus(); @@ -477,8 +476,13 @@ private: bool failChannelDifference(ChannelData *channel, const RPCError &err); void failDifferenceStartTimerFor(ChannelData *channel); - void feedUpdateVector(const MTPVector &updates, bool skipMessageIds = false); + void feedUpdateVector( + const MTPVector &updates, + bool skipMessageIds = false); + // Doesn't call sendHistoryChangeNotifications itself. void feedMessageIds(const MTPVector &updates); + // Doesn't call sendHistoryChangeNotifications itself. + void feedUpdate(const MTPUpdate &update); void deleteHistoryPart(DeleteHistoryRequest request, const MTPmessages_AffectedHistory &result); void deleteAllFromUserPart(DeleteAllFromUserParams params, const MTPmessages_AffectedHistory &result);