rich delete all + ban almost done in supergroups (need to clear messages on the client side as well)

This commit is contained in:
John Preston 2016-03-10 18:42:01 +03:00
parent efa5fc443a
commit 98e2700764
11 changed files with 279 additions and 22 deletions

View File

@ -668,6 +668,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_in_dlg_sticker" = "Sticker";
"lng_in_dlg_sticker_emoji" = "{emoji} (sticker)";
"lng_ban_user" = "Ban User";
"lng_delete_all_from" = "Delete all from this user";
"lng_report_spam" = "Report Spam";
"lng_report_spam_hide" = "Hide";
"lng_report_spam_thanks" = "Thank you for your report!";

View File

@ -512,7 +512,7 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
UserData *u = App::user(userId);
if (bots) {
if (u->botInfo) {
peer->mgInfo->bots.insert(u, true);
peer->mgInfo->bots.insert(u);
botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
if (!u->botInfo->inited) {
needBotsInfos = true;
@ -524,9 +524,9 @@ void ApiWrap::lastParticipantsDone(ChannelData *peer, const MTPchannels_ChannelP
} else {
if (peer->mgInfo->lastParticipants.indexOf(u) < 0) {
peer->mgInfo->lastParticipants.push_back(u);
if (admin) peer->mgInfo->lastAdmins.insert(u, true);
if (admin) peer->mgInfo->lastAdmins.insert(u);
if (u->botInfo) {
peer->mgInfo->bots.insert(u, true);
peer->mgInfo->bots.insert(u);
if (peer->mgInfo->botStatus != 0 && peer->mgInfo->botStatus < 2) {
peer->mgInfo->botStatus = 2;
}

View File

@ -664,10 +664,10 @@ namespace App {
if (user) {
chat->participants[user] = pversion;
if (inviter == MTP::authedId()) {
chat->invitedByMe[user] = true;
chat->invitedByMe.insert(user);
}
if (i->type() == mtpc_chatParticipantAdmin) {
chat->admins[user] = true;
chat->admins.insert(user);
if (user->isSelf()) {
chat->flags |= MTPDchat::flag_admin;
}
@ -736,7 +736,7 @@ namespace App {
} else if (chat->participants.find(user) == chat->participants.end()) {
chat->participants[user] = (chat->participants.isEmpty() ? 1 : chat->participants.begin().value());
if (d.vinviter_id.v == MTP::authedId()) {
chat->invitedByMe[user] = true;
chat->invitedByMe.insert(user);
} else {
chat->invitedByMe.remove(user);
}
@ -876,7 +876,7 @@ namespace App {
if (chat->noParticipantInfo()) {
App::api()->requestFullPeer(chat);
} else {
chat->admins.insert(user, true);
chat->admins.insert(user);
}
} else {
if (user->isSelf()) {

View File

@ -434,3 +434,175 @@ bool PinMessageBox::pinFail(const RPCError &error) {
Ui::hideLayer();
return true;
}
RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId) : AbstractBox(st::boxWidth)
, _channel(channel)
, _from(from)
, _msgId(msgId)
, _text(this, lang(lng_selected_delete_sure_this), st::boxLabel)
, _banUser(this, lang(lng_ban_user), false)
, _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) {
_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());
connect(&_delete, SIGNAL(clicked()), this, SLOT(onDelete()));
connect(&_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
}
void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) {
_text.moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_banUser.moveToLeft(st::boxPadding.left(), _text.y() + _text.height() + st::boxMediumSkip);
_reportSpam.moveToLeft(st::boxPadding.left(), _banUser.y() + _banUser.height() + st::boxLittleSkip);
_deleteAll.moveToLeft(st::boxPadding.left(), _reportSpam.y() + _reportSpam.height() + st::boxLittleSkip);
_delete.moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete.height());
_cancel.moveToRight(st::boxButtonPadding.right() + _delete.width() + st::boxButtonPadding.left(), _delete.y());
}
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;
}
QVector<MTPint> toDelete(1, MTP_int(item->id));
History *h = item->history();
bool wasOnServer = (item->id > 0), wasLast = (h->lastMsg == item);
bool banUser = _banUser.checked(), reportSpam = _reportSpam.checked(), deleteAll = _deleteAll.checked();
item->destroy();
if (!wasOnServer && wasLast && !h->lastMsg) {
App::main()->checkPeerHistory(h->peer);
}
Notify::historyItemsResized();
if (wasOnServer) {
_deleteRequestId = MTP::send(MTPchannels_DeleteMessages(_channel->inputChannel, MTP_vector<MTPint>(1, MTP_int(item->id))), rpcDone(&RichDeleteMessageBox::deleteDone), rpcFail(&RichDeleteMessageBox::deleteFail));
}
if (banUser) {
_banRequestId = MTP::send(MTPchannels_KickFromChannel(_channel->inputChannel, _from->inputUser, MTP_boolTrue()), rpcDone(&RichDeleteMessageBox::banDone), rpcFail(&RichDeleteMessageBox::deleteFail));
}
if (reportSpam) {
_reportRequestId = MTP::send(MTPchannels_ReportSpam(_channel->inputChannel, _from->inputUser, MTP_vector<MTPint>(1, MTP_int(item->id))), rpcDone(&RichDeleteMessageBox::reportDone), rpcFail(&RichDeleteMessageBox::deleteFail));
}
if (deleteAll) {
_deleteAllRequestId = MTP::send(MTPchannels_DeleteUserHistory(_channel->inputChannel, _from->inputUser), rpcDone(&RichDeleteMessageBox::deleteAllPart), rpcFail(&RichDeleteMessageBox::deleteFail));
}
}
void RichDeleteMessageBox::showAll() {
_text.show();
_banUser.show();
_reportSpam.show();
_deleteAll.show();
_delete.show();
_cancel.show();
}
void RichDeleteMessageBox::hideAll() {
_text.hide();
_banUser.hide();
_reportSpam.hide();
_deleteAll.hide();
_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) {
if (History *h = App::historyLoaded(_channel->id)) {
if (!h->lastMsg && App::main()) {
App::main()->checkPeerHistory(_channel);
}
}
checkFinished();
return;
}
_deleteAllRequestId = MTP::send(MTPchannels_DeleteUserHistory(_channel->inputChannel, _from->inputUser), rpcDone(&RichDeleteMessageBox::deleteAllPart), rpcFail(&RichDeleteMessageBox::deleteFail));
}
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();
}

View File

@ -198,4 +198,46 @@ private:
mtpRequestId _requestId;
};
};
class RichDeleteMessageBox : public AbstractBox, public RPCSender {
Q_OBJECT
public:
RichDeleteMessageBox(ChannelData *channel, UserData *from, MsgId msgId);
void resizeEvent(QResizeEvent *e);
public slots:
void onDelete();
protected:
void showAll();
void hideAll();
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;
FlatLabel _text;
Checkbox _banUser, _reportSpam, _deleteAll;
BoxButton _delete, _cancel;
mtpRequestId _deleteRequestId, _banRequestId, _reportRequestId, _deleteAllRequestId;
};

View File

@ -1669,7 +1669,7 @@ void ContactsBox::setAdminDone(UserData *user, const MTPBool &result) {
if (_inner.chat()->noParticipantInfo()) {
App::api()->requestFullPeer(_inner.chat());
} else {
_inner.chat()->admins.insert(user, true);
_inner.chat()->admins.insert(user);
}
}
--_saveRequestId;
@ -2182,6 +2182,16 @@ void MembersInner::membersReceived(const MTPchannels_ChannelParticipants &result
_datas.push_back(0);
}
}
// update admins if we got all of them
if (_filter == MembersFilterAdmins && _channel->isMegagroup() && _rows.size() < Global::ChatSizeMax()) {
_channel->mgInfo->lastAdmins.clear();
for (int32 i = 0, l = _rows.size(); i != l; ++i) {
if (_roles.at(i) == MemberRoleCreator || _roles.at(i) == MemberRoleEditor) {
_channel->mgInfo->lastAdmins.insert(_rows.at(i));
}
}
}
}
if (_rows.isEmpty()) {
_rows.push_back(App::self());

View File

@ -1409,7 +1409,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
}
if (user->botInfo) {
peer->asChannel()->mgInfo->bots.insert(user, true);
peer->asChannel()->mgInfo->bots.insert(user);
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
peer->asChannel()->mgInfo->botStatus = 2;
}
@ -1427,7 +1427,7 @@ HistoryItem *History::createItem(HistoryBlock *block, const MTPMessage &msg, boo
peer->asChannel()->mgInfo->lastParticipants.push_front(result->from()->asUser());
}
if (result->from()->asUser()->botInfo) {
peer->asChannel()->mgInfo->bots.insert(result->from()->asUser(), true);
peer->asChannel()->mgInfo->bots.insert(result->from()->asUser());
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
peer->asChannel()->mgInfo->botStatus = 2;
}
@ -1742,7 +1742,7 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a
} else if (peer->isMegagroup()) {
lastAuthors = &peer->asChannel()->mgInfo->lastParticipants;
if (adding->from()->asUser()->botInfo) {
peer->asChannel()->mgInfo->bots.insert(adding->from()->asUser(), true);
peer->asChannel()->mgInfo->bots.insert(adding->from()->asUser());
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
peer->asChannel()->mgInfo->botStatus = 2;
}
@ -1763,14 +1763,14 @@ HistoryItem *History::addNewItem(HistoryBlock *to, bool newBlock, HistoryItem *a
if (adding->hasReplyMarkup()) {
int32 markupFlags = App::replyMarkup(channelId(), adding->id).flags;
if (!(markupFlags & MTPDreplyKeyboardMarkup::flag_selective) || adding->mentionsMe()) {
QMap<PeerData*, bool> *markupSenders = 0;
OrderedSet<PeerData*> *markupSenders = 0;
if (peer->isChat()) {
markupSenders = &peer->asChat()->markupSenders;
} else if (peer->isMegagroup()) {
markupSenders = &peer->asChannel()->mgInfo->markupSenders;
}
if (markupSenders) {
markupSenders->insert(adding->from(), true);
markupSenders->insert(adding->from());
}
if (markupFlags & MTPDreplyKeyboardMarkup_flag_ZERO) { // zero markup means replyKeyboardHide
if (lastKeyboardFrom == adding->from()->id || (!lastKeyboardInited && !peer->isChat() && !peer->isMegagroup() && !adding->out())) {
@ -1977,7 +1977,7 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
bool channel = isChannel();
int32 mask = 0;
QList<UserData*> *lastAuthors = 0;
QMap<PeerData*, bool> *markupSenders = 0;
OrderedSet<PeerData*> *markupSenders = 0;
if (peer->isChat()) {
lastAuthors = &peer->asChat()->lastAuthors;
markupSenders = &peer->asChat()->markupSenders;
@ -2007,7 +2007,7 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice, const QVector<MTPM
if (!(markupFlags & MTPDreplyKeyboardMarkup::flag_selective) || item->mentionsMe()) {
bool wasKeyboardHide = markupSenders->contains(item->author());
if (!wasKeyboardHide) {
markupSenders->insert(item->author(), true);
markupSenders->insert(item->author());
}
if (!(markupFlags & MTPDreplyKeyboardMarkup_flag_ZERO)) {
if (!lastKeyboardInited) {
@ -2931,6 +2931,9 @@ void HistoryItem::destroy() {
detach();
if (history()->isChannel()) {
history()->asChannelHistory()->messageDeleted(this);
if (history()->peer->isMegagroup() && history()->peer->asChannel()->mgInfo->pinnedMsgId == id) {
history()->peer->asChannel()->mgInfo->pinnedMsgId = 0;
}
}
if (history()->lastMsg == this) {
history()->fixLastMessage(wasAtBottom);

View File

@ -6258,6 +6258,9 @@ void HistoryWidget::itemRemoved(HistoryItem *item) {
if (item == _replyReturn) {
calcNextReplyReturn();
}
if (_pinnedBar && item->id == _pinnedBar->msgId) {
pinnedMsgVisibilityUpdated();
}
if (_kbReplyTo && item == _kbReplyTo) {
onKbToggle();
_kbReplyTo = 0;

View File

@ -907,6 +907,15 @@ 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));
return;
}
}
}
QString str((selectedCount < 0) ? lang(selectedCount < -1 ? lng_selected_cancel_sure_this : lng_selected_delete_sure_this) : lng_selected_delete_sure(lt_count, selectedCount));
QString btn(lang((selectedCount < -1) ? lng_selected_upload_stop : lng_box_delete)), cancel(lang((selectedCount < -1) ? lng_continue : lng_cancel));
ConfirmBox *box = new ConfirmBox(str, btn, st::defaultBoxButton, cancel);

View File

@ -992,6 +992,22 @@ void ProfileInner::paintEvent(QPaintEvent *e) {
int32 partfrom = top;
if (!_participants.isEmpty()) {
if (App::self()) {
if (_peerChat) {
if (_peerChat->amAdmin() && _peerChat->admins.constFind(App::self()) == _peerChat->admins.cend()) {
_peerChat->admins.insert(App::self());
} else if (!_peerChat->amAdmin() && _peerChat->admins.constFind(App::self()) != _peerChat->admins.cend()) {
_peerChat->admins.remove(App::self());
}
} else if (_peerChannel && _peerChannel->isMegagroup()) {
if ((_peerChannel->amCreator() || _peerChannel->amEditor()) && _peerChannel->mgInfo->lastAdmins.constFind(App::self()) == _peerChannel->mgInfo->lastAdmins.cend()) {
_peerChannel->mgInfo->lastAdmins.insert(App::self());
} else if (!_peerChannel->amCreator() && !_peerChannel->amEditor() && _peerChannel->mgInfo->lastAdmins.constFind(App::self()) != _peerChannel->mgInfo->lastAdmins.cend()) {
_peerChannel->mgInfo->lastAdmins.remove(App::self());
}
}
}
int32 cnt = 0, fullCnt = _participants.size();
for (Participants::const_iterator i = _participants.cbegin(), e = _participants.cend(); i != e; ++i, ++cnt) {
int32 top = partfrom + cnt * _pHeight;

View File

@ -457,13 +457,13 @@ public:
}
typedef QMap<UserData*, int32> Participants;
Participants participants;
typedef QMap<UserData*, bool> InvitedByMe;
typedef OrderedSet<UserData*> InvitedByMe;
InvitedByMe invitedByMe;
typedef QMap<UserData*, bool> Admins;
typedef OrderedSet<UserData*> Admins;
Admins admins;
typedef QList<UserData*> LastAuthors;
LastAuthors lastAuthors;
typedef QMap<PeerData*, bool> MarkupSenders;
typedef OrderedSet<PeerData*> MarkupSenders;
MarkupSenders markupSenders;
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
// ImagePtr photoFull;
@ -542,11 +542,11 @@ struct MegagroupInfo {
}
typedef QList<UserData*> LastParticipants;
LastParticipants lastParticipants;
typedef QMap<UserData*, bool> LastAdmins;
typedef OrderedSet<UserData*> LastAdmins;
LastAdmins lastAdmins;
typedef QMap<PeerData*, bool> MarkupSenders;
typedef OrderedSet<PeerData*> MarkupSenders;
MarkupSenders markupSenders;
typedef QMap<UserData*, bool> Bots;
typedef OrderedSet<UserData*> Bots;
Bots bots;
int32 botStatus; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other