Allow supergroup members to clear history.

This commit is contained in:
John Preston 2017-11-21 20:38:17 +04:00
parent 75d8d01b17
commit 2387b66e86
12 changed files with 105 additions and 53 deletions

View File

@ -1257,6 +1257,52 @@ int ApiWrap::onlineTillFromStatus(const MTPUserStatus &status, int currentOnline
Unexpected("Bad UserStatus type.");
}
void ApiWrap::clearHistory(not_null<PeerData*> peer) {
auto lastMsgId = MsgId(0);
if (auto history = App::historyLoaded(peer->id)) {
if (history->lastMsg) {
lastMsgId = history->lastMsg->id;
Local::addSavedPeer(history->peer, history->lastMsg->date);
}
history->clear();
history->newLoaded = history->oldLoaded = true;
}
if (auto channel = peer->asChannel()) {
if (auto migrated = peer->migrateFrom()) {
clearHistory(migrated);
}
if (IsServerMsgId(lastMsgId)) {
request(MTPchannels_DeleteHistory(
channel->inputChannel,
MTP_int(lastMsgId)
)).send();
}
} else {
request(MTPmessages_DeleteHistory(
MTP_flags(MTPmessages_DeleteHistory::Flag::f_just_clear),
peer->input,
MTP_int(0)
)).done([=](const MTPmessages_AffectedHistory &result) {
auto offset = applyAffectedHistory(peer, result);
if (offset > 0) {
clearHistory(peer);
}
}).send();
}
}
int ApiWrap::applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result) {
auto &d = result.c_messages_affectedHistory();
if (peer && peer->isChannel()) {
peer->asChannel()->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
} else {
App::main()->ptsUpdateAndApply(d.vpts.v, d.vpts_count.v);
}
return d.voffset.v;
}
void ApiWrap::saveDraftsToCloud() {
for (auto i = _draftsSaveRequestIds.begin(), e = _draftsSaveRequestIds.end(); i != e; ++i) {
if (i.value()) continue; // sent already

View File

@ -100,6 +100,8 @@ public:
void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules);
int onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill);
void clearHistory(not_null<PeerData*> peer);
base::Observable<PeerData*> &fullPeerUpdated() {
return _fullPeerUpdated;
}
@ -202,6 +204,10 @@ private:
void saveChatAdmins(not_null<ChatData*> chat);
void sendSaveChatAdminsRequests(not_null<ChatData*> chat);
int applyAffectedHistory(
not_null<PeerData*> peer,
const MTPmessages_AffectedHistory &result);
void sharedMediaDone(
not_null<PeerData*> peer,
SharedMediaType type,

View File

@ -1059,22 +1059,21 @@ namespace {
return false;
}
template <typename TMTPDclass>
void updateEditedMessage(const TMTPDclass &m) {
auto peerId = peerFromMTP(m.vto_id);
if (m.has_from_id() && peerId == Auth().userPeerId()) {
peerId = peerFromUser(m.vfrom_id);
}
if (auto existing = App::histItemById(peerToChannel(peerId), m.vid.v)) {
existing->applyEdition(m);
}
}
void updateEditedMessage(const MTPMessage &m) {
auto apply = [](const auto &data) {
auto peerId = peerFromMTP(data.vto_id);
if (data.has_from_id() && peerId == Auth().userPeerId()) {
peerId = peerFromUser(data.vfrom_id);
}
if (auto existing = App::histItemById(peerToChannel(peerId), data.vid.v)) {
existing->applyEdition(data);
}
};
if (m.type() == mtpc_message) { // apply message edit
App::updateEditedMessage(m.c_message());
apply(m.c_message());
} else if (m.type() == mtpc_messageService) {
App::updateEditedMessage(m.c_messageService());
apply(m.c_messageService());
}
}

View File

@ -1335,9 +1335,7 @@ bool EditChannelBox::onSaveFail(const RPCError &error, mtpRequestId req) {
} else if (req == _saveDescriptionRequestId) {
_saveDescriptionRequestId = 0;
if (err == qstr("CHAT_ABOUT_NOT_MODIFIED")) {
if (_channel->setAbout(_sentDescription)) {
Auth().api().fullPeerUpdated().notify(_channel);
}
_channel->setAbout(_sentDescription);
saveSign();
return true;
} else {
@ -1367,9 +1365,7 @@ void EditChannelBox::onSaveTitleDone(const MTPUpdates &result) {
void EditChannelBox::onSaveDescriptionDone(const MTPBool &result) {
_saveDescriptionRequestId = 0;
if (_channel->setAbout(_sentDescription)) {
Auth().api().fullPeerUpdated().notify(_channel);
}
_channel->setAbout(_sentDescription);
saveSign();
}

View File

@ -1035,9 +1035,7 @@ void Controller::saveDescription() {
return continueSave();
}
auto successCallback = [this] {
if (_channel->setAbout(*_savingData.description)) {
Auth().api().fullPeerUpdated().notify(_channel);
}
_channel->setAbout(*_savingData.description);
continueSave();
};
request(MTPchannels_EditAbout(

View File

@ -134,9 +134,9 @@ TimeId fromServerTime(const MTPint &serverTime) {
return serverTime.v - unixtimeDelta;
}
void toServerTime(const TimeId &clientTime, MTPint &outServerTime) {
MTPint toServerTime(const TimeId &clientTime) {
QReadLocker locker(&unixtimeLock);
outServerTime = MTP_int(clientTime + unixtimeDelta);
return MTP_int(clientTime + unixtimeDelta);
}
QDateTime dateFromServerTime(TimeId time) {

View File

@ -240,7 +240,7 @@ void unixtimeInit();
void unixtimeSet(TimeId servertime, bool force = false);
TimeId unixtime();
TimeId fromServerTime(const MTPint &serverTime);
void toServerTime(const TimeId &clientTime, MTPint &outServerTime);
MTPint toServerTime(const TimeId &clientTime);
uint64 msgid();
int32 reqid();

View File

@ -1403,8 +1403,7 @@ void History::newItemAdded(HistoryItem *item) {
if (item->from() == item->author()) {
unregSendAction(item->from()->asUser());
}
MTPint itemServerTime;
toServerTime(item->date.toTime_t(), itemServerTime);
auto itemServerTime = toServerTime(item->date.toTime_t());
item->from()->asUser()->madeAction(itemServerTime.v);
}
if (item->out()) {
@ -2386,6 +2385,19 @@ void History::clearUpTill(MsgId availableMinId) {
auto item = blocks.front()->items.front();
auto itemId = item->id;
if (IsServerMsgId(itemId) && itemId >= availableMinId) {
if (itemId == availableMinId) {
auto fromId = 0;
auto replyToId = 0;
item->applyEdition(MTP_messageService(
MTP_flags(0),
MTP_int(itemId),
MTP_int(fromId),
peerToMTP(peer->id),
MTP_int(replyToId),
toServerTime(item->date.toTime_t()),
MTP_messageActionHistoryClear()
).c_messageService());
}
break;
}
item->destroy();

View File

@ -435,7 +435,7 @@ void ActionsFiller::addClearHistoryAction(not_null<UserData*> user) {
App::peerName(user));
auto confirmCallback = [user] {
Ui::hideLayer();
App::main()->clearHistory(user);
Auth().api().clearHistory(user);
Ui::showPeerHistory(user, ShowAtUnreadMsgId);
};
auto box = Box<ConfirmBox>(

View File

@ -1215,19 +1215,6 @@ void MainWidget::deleteAllFromUserPart(DeleteAllFromUserParams params, const MTP
}
}
void MainWidget::clearHistory(PeerData *peer) {
if (History *h = App::historyLoaded(peer->id)) {
if (h->lastMsg) {
Local::addSavedPeer(h->peer, h->lastMsg->date);
}
h->clear();
h->newLoaded = h->oldLoaded = true;
}
auto flags = MTPmessages_DeleteHistory::Flag::f_just_clear;
DeleteHistoryRequest request = { peer, true };
MTP::send(MTPmessages_DeleteHistory(MTP_flags(flags), peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, request));
}
void MainWidget::addParticipants(PeerData *chatOrChannel, const std::vector<not_null<UserData*>> &users) {
if (chatOrChannel->isChat()) {
auto chat = chatOrChannel->asChat();

View File

@ -210,7 +210,6 @@ public:
void deletedContact(UserData *user, const MTPcontacts_Link &result);
void deleteConversation(PeerData *peer, bool deleteHistory = true);
void deleteAndExit(ChatData *chat);
void clearHistory(PeerData *peer);
void deleteAllFromUser(ChannelData *channel, UserData *from);
void addParticipants(PeerData *chatOrChannel, const std::vector<not_null<UserData*>> &users);
@ -320,6 +319,10 @@ public:
bool contentOverlapped(const QRect &globalRect);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount);
void documentLoadProgress(DocumentData *document);
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col);
@ -534,9 +537,6 @@ private:
RectPart side) const;
RectPart getFloatPlayerSide(QPoint center) const;
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdates &updates);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount, const MTPUpdate &update);
bool ptsUpdateAndApply(int32 pts, int32 ptsCount);
bool getDifferenceTimeChanged(ChannelData *channel, int32 ms, ChannelGetDifferenceTime &channelCurTime, TimeMs &curTime);
void viewsIncrementDone(QVector<MTPint> ids, const MTPVector<MTPint> &result, mtpRequestId req);

View File

@ -87,12 +87,14 @@ History *FindWastedPin() {
auto ClearHistoryHandler(not_null<PeerData*> peer) {
return [peer] {
auto text = peer->isUser() ? lng_sure_delete_history(lt_contact, peer->name) : lng_sure_delete_group_history(lt_group, peer->name);
auto text = peer->isUser()
? lng_sure_delete_history(lt_contact, peer->name)
: lng_sure_delete_group_history(lt_group, peer->name);
Ui::show(Box<ConfirmBox>(text, lang(lng_box_delete), st::attentionBoxButton, [peer] {
if (!App::main()) return;
Ui::hideLayer();
App::main()->clearHistory(peer);
Auth().api().clearHistory(peer);
}));
};
}
@ -363,9 +365,10 @@ void Filler::addChatActions(not_null<ChatData*> chat) {
}
void Filler::addChannelActions(not_null<ChannelData*> channel) {
auto isGroup = channel->isMegagroup();
if (_source != PeerMenuSource::ChatsList) {
if (ManagePeerBox::Available(channel)) {
auto text = lang(channel->isMegagroup()
auto text = lang(isGroup
? lng_manage_group_title
: lng_manage_channel_title);
_addAction(text, [channel] {
@ -379,21 +382,26 @@ void Filler::addChannelActions(not_null<ChannelData*> channel) {
}
}
if (channel->amIn()) {
auto leaveText = lang(channel->isMegagroup()
if (isGroup && !channel->isPublic()) {
_addAction(
lang(lng_profile_clear_history),
ClearHistoryHandler(channel));
}
auto text = lang(isGroup
? lng_profile_leave_group
: lng_profile_leave_channel);
_addAction(leaveText, DeleteAndLeaveHandler(channel));
_addAction(text, DeleteAndLeaveHandler(channel));
} else {
auto joinText = lang(channel->isMegagroup()
auto text = lang(isGroup
? lng_profile_join_group
: lng_profile_join_channel);
_addAction(
joinText,
text,
[channel] { Auth().api().joinChannel(channel); });
}
if (_source != PeerMenuSource::ChatsList) {
auto needReport = !channel->amCreator()
&& (!channel->isMegagroup() || channel->isPublic());
&& (!isGroup || channel->isPublic());
if (needReport) {
_addAction(lang(lng_profile_report), [channel] {
Ui::show(Box<ReportBox>(channel));