diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 4fabd34d8..aeaaf5c87 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -144,6 +144,15 @@ namespace App { History *historyFromDialog(const PeerId &peer, int32 unreadCnt, int32 maxInboxRead); History *historyLoaded(const PeerId &peer); HistoryItem *histItemById(ChannelId channelId, MsgId itemId); + inline History *history(const PeerData *peer) { + return history(peer->id); + } + inline History *historyLoaded(const PeerData *peer) { + return historyLoaded(peer->id); + } + inline HistoryItem *histItemById(const ChannelData *channel, MsgId itemId) { + return histItemById(channel ? peerToChannel(channel->id) : 0, itemId); + } inline HistoryItem *histItemById(const FullMsgId &msgId) { return histItemById(msgId.channel, msgId.msg); } diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index 5c9e5f152..b73b15d89 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -444,11 +444,9 @@ RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, , _reportSpam(this, lang(lng_report_spam), false) , _deleteAll(this, lang(lng_delete_all_from), false) , _delete(this, lang(lng_box_delete), st::defaultBoxButton) -, _cancel(this, lang(lng_cancel), st::cancelBoxButton) -, _deleteRequestId(0) -, _banRequestId(0) -, _reportRequestId(0) -, _deleteAllRequestId(0) { +, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { + t_assert(_channel != nullptr); + _text.resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); setMaxHeight(st::boxPadding.top() + _text.height() + st::boxMediumSkip + _banUser.height() + st::boxLittleSkip + _reportSpam.height() + st::boxLittleSkip + _deleteAll.height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete.height() + st::boxButtonPadding.bottom()); @@ -466,54 +464,26 @@ void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) { } void RichDeleteMessageBox::onDelete() { - if (_deleteRequestId || _banRequestId || _reportRequestId || _deleteAllRequestId) return; - - HistoryItem *item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId); - if (!item || item->type() != HistoryItemMsg) { - Ui::hideLayer(); - return; + if (_banUser.checked()) { + MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), App::main()->rpcDone(&MainWidget::sentUpdatesReceived)); } - - QVector toDelete(1, MTP_int(item->id)); - History *h = item->history(); - bool deleteItem = (item->id > 0), lastDeleted = (h->lastMsg == item); - bool banUser = _banUser.checked(), reportSpam = _reportSpam.checked(), deleteAll = _deleteAll.checked(); - - item->destroy(); - if (deleteItem) { - _deleteRequestId = MTP::send(MTPchannels_DeleteMessages(_channel->inputChannel, MTP_vector(1, MTP_int(item->id))), rpcDone(&RichDeleteMessageBox::deleteDone), rpcFail(&RichDeleteMessageBox::deleteFail)); + if (_reportSpam.checked()) { + MTP::send(MTPchannels_ReportSpam(_channel->inputChannel, _from->inputUser, MTP_vector(1, MTP_int(_msgId)))); } - if (banUser) { - _banRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), rpcDone(&RichDeleteMessageBox::banDone), rpcFail(&RichDeleteMessageBox::deleteFail)); + if (_deleteAll.checked()) { + App::main()->deleteAllFromUser(_channel, _from); } - if (reportSpam) { - _reportRequestId = MTP::send(MTPchannels_ReportSpam(_channel->inputChannel, _from->inputUser, MTP_vector(1, MTP_int(item->id))), rpcDone(&RichDeleteMessageBox::reportDone), rpcFail(&RichDeleteMessageBox::deleteFail)); - } - if (deleteAll) { - QVector toDestroy; - for (History::Blocks::const_iterator i = h->blocks.cbegin(), e = h->blocks.cend(); i != e; ++i) { - for (HistoryBlock::Items::const_iterator j = (*i)->items.cbegin(), n = (*i)->items.cend(); j != n; ++j) { - if ((*j)->from() == _from && (*j)->type() == HistoryItemMsg && (*j)->canDelete()) { - toDestroy.push_back((*j)->id); - } - } + if (auto item = App::histItemById(_channel ? peerToChannel(_channel->id) : 0, _msgId)) { + bool wasLast = (item->history()->lastMsg == item); + item->destroy(); + if (_msgId > 0) { + App::main()->deleteMessages(_channel, QVector(1, MTP_int(_msgId))); + } else if (wasLast) { + App::main()->checkPeerHistory(_channel); } - for (QVector::const_iterator i = toDestroy.cbegin(), e = toDestroy.cend(); i != e; ++i) { - if (HistoryItem *item = App::histItemById(peerToChannel(_channel->id), *i)) { - if (item == h->lastMsg) { - lastDeleted = true; - } - item->destroy(); - } - } - _deleteAllRequestId = MTP::send(MTPchannels_DeleteUserHistory(_channel->inputChannel, _from->inputUser), rpcDone(&RichDeleteMessageBox::deleteAllPart), rpcFail(&RichDeleteMessageBox::deleteFail)); } - - if (!deleteItem && !deleteAll && lastDeleted && !h->lastMsg) { - App::main()->checkPeerHistory(h->peer); - } - Notify::historyItemsResized(); + Ui::hideLayer(); } void RichDeleteMessageBox::showAll() { @@ -533,93 +503,3 @@ void RichDeleteMessageBox::hideAll() { _delete.hide(); _cancel.hide(); } - -void RichDeleteMessageBox::deleteDone(const MTPmessages_AffectedMessages &result, mtpRequestId req) { - const MTPDmessages_affectedMessages &d(result.c_messages_affectedMessages()); - if (_channel->ptsUpdated(d.vpts.v, d.vpts_count.v)) { - _channel->ptsApplySkippedUpdates(); - App::emitPeerUpdated(); - } - if (History *h = App::historyLoaded(_channel->id)) { - if (!h->lastMsg && App::main()) { - App::main()->checkPeerHistory(_channel); - } - } - if (req == _deleteRequestId) { - _deleteRequestId = 0; - } else if (req == _banRequestId) { - _banRequestId = 0; - } else if (req == _reportRequestId) { - _reportRequestId = 0; - } else if (req == _deleteAllRequestId) { - _deleteAllRequestId = 0; - } - checkFinished(); -} - -void RichDeleteMessageBox::banDone(const MTPUpdates &result, mtpRequestId req) { - if (App::main()) { - App::main()->sentUpdatesReceived(result); - } - if (req == _banRequestId) { - _banRequestId = 0; - } - checkFinished(); -} - -void RichDeleteMessageBox::reportDone(const MTPBool &result, mtpRequestId req) { - if (req == _reportRequestId) { - _reportRequestId = 0; - } - checkFinished(); -} - -void RichDeleteMessageBox::deleteAllPart(const MTPmessages_AffectedHistory &result, mtpRequestId req) { - const MTPDmessages_affectedHistory &d(result.c_messages_affectedHistory()); - if (_channel->ptsUpdated(d.vpts.v, d.vpts_count.v)) { - _channel->ptsApplySkippedUpdates(); - App::emitPeerUpdated(); - } - if (req == _deleteRequestId) { - _deleteRequestId = 0; - } else if (req == _banRequestId) { - _banRequestId = 0; - } else if (req == _reportRequestId) { - _reportRequestId = 0; - } else if (req == _deleteAllRequestId) { - _deleteAllRequestId = 0; - } - - int32 offset = d.voffset.v; - if (offset > 0) { - _deleteAllRequestId = MTP::send(MTPchannels_DeleteUserHistory(_channel->inputChannel, _from->inputUser), rpcDone(&RichDeleteMessageBox::deleteAllPart), rpcFail(&RichDeleteMessageBox::deleteFail)); - return; - } - - if (History *h = App::historyLoaded(_channel->id)) { - if (!h->lastMsg && App::main()) { - App::main()->checkPeerHistory(_channel); - } - } - checkFinished(); -} - -bool RichDeleteMessageBox::deleteFail(const RPCError &error, mtpRequestId req) { - if (mtpIsFlood(error)) return false; - if (req == _deleteRequestId) { - _deleteRequestId = 0; - } else if (req == _banRequestId) { - _banRequestId = 0; - } else if (req == _reportRequestId) { - _reportRequestId = 0; - } else if (req == _deleteAllRequestId) { - _deleteAllRequestId = 0; - } - checkFinished(); - return true; -} - -void RichDeleteMessageBox::checkFinished() { - if (_deleteRequestId || _banRequestId || _reportRequestId || _deleteAllRequestId) return; - Ui::hideLayer(); -} \ No newline at end of file diff --git a/Telegram/SourceFiles/boxes/confirmbox.h b/Telegram/SourceFiles/boxes/confirmbox.h index 6937b2c10..05b8febf3 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.h +++ b/Telegram/SourceFiles/boxes/confirmbox.h @@ -220,15 +220,6 @@ protected: private: - void deleteDone(const MTPmessages_AffectedMessages &result, mtpRequestId req); - void banDone(const MTPUpdates &result, mtpRequestId req); - void reportDone(const MTPBool &result, mtpRequestId req); - void deleteAllPart(const MTPmessages_AffectedHistory &result, mtpRequestId req); - - bool deleteFail(const RPCError &error, mtpRequestId req); - - void checkFinished(); - ChannelData *_channel; UserData *_from; MsgId _msgId; @@ -238,6 +229,4 @@ private: BoxButton _delete, _cancel; - mtpRequestId _deleteRequestId, _banRequestId, _reportRequestId, _deleteAllRequestId; - }; diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h index abc72437f..928c2d9c4 100644 --- a/Telegram/SourceFiles/history.h +++ b/Telegram/SourceFiles/history.h @@ -1096,6 +1096,12 @@ public: bool canEdit(const QDateTime &cur) const; + bool suggestBanReportDeleteAll() const { + auto channel = history()->peer->asChannel(); + if (!channel || (!channel->amEditor() && !channel->amCreator())) return false; + return !isPost() && !out() && from()->isUser() && toHistoryMessage(); + } + bool hasDirectLink() const { return id > 0 && _history->peer->isChannel() && _history->peer->asChannel()->isPublic() && !_history->peer->isMegagroup(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 471d941f6..6b51634d3 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -909,10 +909,9 @@ void MainWidget::forwardLayer(int32 forwardSelected) { void MainWidget::deleteLayer(int32 selectedCount) { if (selectedCount == -1 && !overview) { - if (HistoryItem *item = App::contextItem()) { - ChannelData *channel = item->history()->peer->asChannel(); - if (channel && !item->isPost() && !item->out() && item->from()->isUser() && (channel->amCreator() || channel->amEditor())) { - Ui::showLayer(new RichDeleteMessageBox(channel, item->from()->asUser(), item->id)); + if (auto item = App::contextItem()) { + if (item->suggestBanReportDeleteAll()) { + Ui::showLayer(new RichDeleteMessageBox(item->history()->peer->asChannel(), item->from()->asUser(), item->id)); return; } } @@ -992,9 +991,16 @@ 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()); - if (ptsUpdated(d.vpts.v, d.vpts_count.v)) { - ptsApplySkippedUpdates(); - App::emitPeerUpdated(); + if (peer && peer->isChannel()) { + if (peer->asChannel()->ptsUpdated(d.vpts.v, d.vpts_count.v)) { + peer->asChannel()->ptsApplySkippedUpdates(); + App::emitPeerUpdated(); + } + } else { + if (ptsUpdated(d.vpts.v, d.vpts_count.v)) { + ptsApplySkippedUpdates(); + App::emitPeerUpdated(); + } } int32 offset = d.voffset.v; @@ -1057,6 +1063,45 @@ void MainWidget::deleteConversation(PeerData *peer, bool deleteHistory) { } } +void MainWidget::deleteAllFromUser(ChannelData *channel, UserData *from) { + t_assert(channel != nullptr && from != nullptr); + + QVector toDestroy; + if (auto history = App::historyLoaded(channel->id)) { + for (auto i = history->blocks.cbegin(), e = history->blocks.cend(); i != e; ++i) { + for (auto j = (*i)->items.cbegin(), n = (*i)->items.cend(); j != n; ++j) { + if ((*j)->from() == from && (*j)->type() == HistoryItemMsg && (*j)->canDelete()) { + toDestroy.push_back((*j)->id); + } + } + } + for (auto i = toDestroy.cbegin(), e = toDestroy.cend(); i != e; ++i) { + if (auto item = App::histItemById(peerToChannel(channel->id), *i)) { + item->destroy(); + } + } + } + MTP::send(MTPchannels_DeleteUserHistory(channel->inputChannel, from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, { channel, from })); +} + +void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTPmessages_AffectedHistory &result) { + const MTPDmessages_affectedHistory &d(result.c_messages_affectedHistory()); + if (params.channel->ptsUpdated(d.vpts.v, d.vpts_count.v)) { + params.channel->ptsApplySkippedUpdates(); + App::emitPeerUpdated(); + } + + int32 offset = d.voffset.v; + if (!MTP::authedId()) return; + if (offset > 0) { + MTP::send(MTPchannels_DeleteUserHistory(params.channel->inputChannel, params.from->inputUser), rpcDone(&MainWidget::deleteAllFromUserPart, params)); + } else if (auto h = App::historyLoaded(params.channel)) { + if (!h->lastMsg) { + checkPeerHistory(params.channel); + } + } +} + void MainWidget::clearHistory(PeerData *peer) { if (History *h = App::historyLoaded(peer->id)) { if (h->lastMsg) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index ada84278a..30e40dbc3 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -306,11 +306,11 @@ public: bool leaveChatFailed(PeerData *peer, const RPCError &e); void deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates); - void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result); void deleteMessages(PeerData *peer, const QVector &ids); void deletedContact(UserData *user, const MTPcontacts_Link &result); void deleteConversation(PeerData *peer, bool deleteHistory = true); void clearHistory(PeerData *peer); + void deleteAllFromUser(ChannelData *channel, UserData *from); void addParticipants(PeerData *chatOrChannel, const QVector &users); bool addParticipantFail(UserData *user, const RPCError &e); @@ -562,6 +562,13 @@ private: void feedUpdateVector(const MTPVector &updates, bool skipMessageIds = false); void feedMessageIds(const MTPVector &updates); + void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result); + struct DeleteAllFromUserParams { + ChannelData *channel; + UserData *from; + }; + void deleteAllFromUserPart(DeleteAllFromUserParams params, const MTPmessages_AffectedHistory &result); + void updateReceived(const mtpPrime *from, const mtpPrime *end); bool updateFail(const RPCError &e);