mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Add revoking of full history.
This commit is contained in:
parent
33069739ee
commit
eb1825defd
9 changed files with 130 additions and 113 deletions
|
@ -2446,6 +2446,30 @@ void ApiWrap::applyAffectedMessages(
|
|||
App::main()->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
|
||||
}
|
||||
|
||||
void ApiWrap::deleteMessages(
|
||||
not_null<PeerData*> peer,
|
||||
const QVector<MTPint> &ids,
|
||||
bool revoke) {
|
||||
const auto done = [=](const MTPmessages_AffectedMessages & result) {
|
||||
applyAffectedMessages(peer, result);
|
||||
if (const auto history = peer->owner().historyLoaded(peer)) {
|
||||
history->requestChatListMessage();
|
||||
}
|
||||
};
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
request(MTPchannels_DeleteMessages(
|
||||
channel->inputChannel,
|
||||
MTP_vector<MTPint>(ids)
|
||||
)).done(done).send();
|
||||
} else {
|
||||
using Flag = MTPmessages_DeleteMessages::Flag;
|
||||
request(MTPmessages_DeleteMessages(
|
||||
MTP_flags(revoke ? Flag::f_revoke : Flag(0)),
|
||||
MTP_vector<MTPint>(ids)
|
||||
)).done(done).send();
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::saveDraftsToCloud() {
|
||||
for (auto i = _draftsSaveRequestIds.begin(), e = _draftsSaveRequestIds.end(); i != e; ++i) {
|
||||
if (i->second) continue; // sent already
|
||||
|
|
|
@ -213,6 +213,10 @@ public:
|
|||
|
||||
void clearHistory(not_null<PeerData*> peer, bool revoke);
|
||||
void deleteConversation(not_null<PeerData*> peer, bool revoke);
|
||||
void deleteMessages(
|
||||
not_null<PeerData*> peer,
|
||||
const QVector<MTPint> &ids,
|
||||
bool revoke);
|
||||
|
||||
base::Observable<PeerData*> &fullPeerUpdated() {
|
||||
return _fullPeerUpdated;
|
||||
|
|
|
@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/image/image.h"
|
||||
#include "ui/empty_userpic.h"
|
||||
#include "core/click_handler_types.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_channel.h"
|
||||
|
@ -473,13 +474,52 @@ DeleteMessagesBox::DeleteMessagesBox(
|
|||
Expects(!_ids.empty());
|
||||
}
|
||||
|
||||
DeleteMessagesBox::DeleteMessagesBox(
|
||||
QWidget*,
|
||||
not_null<PeerData*> peer,
|
||||
bool justClear)
|
||||
: _wipeHistoryPeer(peer)
|
||||
, _wipeHistoryJustClear(justClear) {
|
||||
}
|
||||
|
||||
void DeleteMessagesBox::prepare() {
|
||||
auto details = TextWithEntities();
|
||||
const auto appendDetails = [&](TextWithEntities &&text) {
|
||||
TextUtilities::Append(details, { "\n\n" });
|
||||
TextUtilities::Append(details, std::move(text));
|
||||
};
|
||||
if (_moderateFrom) {
|
||||
auto deleteKey = lng_box_delete;
|
||||
auto deleteStyle = &st::defaultBoxButton;
|
||||
if (const auto peer = _wipeHistoryPeer) {
|
||||
if (_wipeHistoryJustClear) {
|
||||
details.text = peer->isSelf()
|
||||
? lang(lng_sure_delete_saved_messages)
|
||||
: peer->isUser()
|
||||
? lng_sure_delete_history(lt_contact, peer->name)
|
||||
: lng_sure_delete_group_history(lt_group, peer->name);
|
||||
deleteStyle = &st::attentionBoxButton;
|
||||
} else {
|
||||
details.text = peer->isSelf()
|
||||
? lang(lng_sure_delete_saved_messages)
|
||||
: peer->isUser()
|
||||
? lng_sure_delete_history(lt_contact, peer->name)
|
||||
: peer->isChat()
|
||||
? lng_sure_delete_and_exit(lt_group, peer->name)
|
||||
: lang(peer->isMegagroup()
|
||||
? lng_sure_leave_group
|
||||
: lng_sure_leave_channel);
|
||||
deleteKey = _wipeHistoryPeer->isUser()
|
||||
? lng_box_delete
|
||||
: lng_box_leave;
|
||||
deleteStyle = &(peer->isChannel()
|
||||
? st::defaultBoxButton
|
||||
: st::attentionBoxButton);
|
||||
}
|
||||
if (auto revoke = revokeText(peer)) {
|
||||
_revoke.create(this, revoke->checkbox, false, st::defaultBoxCheckbox);
|
||||
appendDetails(std::move(revoke->description));
|
||||
}
|
||||
} else if (_moderateFrom) {
|
||||
Assert(_moderateInChannel != nullptr);
|
||||
details.text = lang(lng_selected_delete_sure_this);
|
||||
if (_moderateBan) {
|
||||
|
@ -511,8 +551,11 @@ void DeleteMessagesBox::prepare() {
|
|||
}
|
||||
_text.create(this, rpl::single(std::move(details)), st::boxLabel);
|
||||
|
||||
addButton(langFactory(lng_box_delete), [this] { deleteAndClear(); });
|
||||
addButton(langFactory(lng_cancel), [this] { closeBox(); });
|
||||
addButton(
|
||||
langFactory(deleteKey),
|
||||
[=] { deleteAndClear(); },
|
||||
*deleteStyle);
|
||||
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||
|
||||
auto fullHeight = st::boxPadding.top() + _text->height() + st::boxPadding.bottom();
|
||||
if (_moderateFrom) {
|
||||
|
@ -547,6 +590,20 @@ PeerData *DeleteMessagesBox::checkFromSinglePeer() const {
|
|||
|
||||
auto DeleteMessagesBox::revokeText(not_null<PeerData*> peer) const
|
||||
-> std::optional<RevokeConfig> {
|
||||
auto result = RevokeConfig();
|
||||
if (peer == _wipeHistoryPeer) {
|
||||
if (!peer->canRevokeFullHistory()) {
|
||||
return std::nullopt;
|
||||
} else if (const auto user = peer->asUser()) {
|
||||
result.checkbox = lng_delete_for_other_check(
|
||||
lt_user,
|
||||
user->firstName);
|
||||
} else {
|
||||
result.checkbox = lang(lng_delete_for_everyone_check);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto items = ranges::view::all(
|
||||
_ids
|
||||
) | ranges::view::transform([](FullMsgId id) {
|
||||
|
@ -554,6 +611,7 @@ auto DeleteMessagesBox::revokeText(not_null<PeerData*> peer) const
|
|||
}) | ranges::view::filter([](HistoryItem *item) {
|
||||
return (item != nullptr);
|
||||
}) | ranges::to_vector;
|
||||
|
||||
if (items.size() != _ids.size()) {
|
||||
// We don't have information about all messages.
|
||||
return std::nullopt;
|
||||
|
@ -575,13 +633,14 @@ auto DeleteMessagesBox::revokeText(not_null<PeerData*> peer) const
|
|||
? -1
|
||||
: ranges::count_if(outgoing, canRevoke);
|
||||
|
||||
auto result = RevokeConfig();
|
||||
if (canRevokeAll) {
|
||||
result.checkbox = peer->isUser()
|
||||
? lng_delete_for_other_check(
|
||||
if (const auto user = peer->asUser()) {
|
||||
result.checkbox = lng_delete_for_other_check(
|
||||
lt_user,
|
||||
peer->asUser()->firstName)
|
||||
: lang(lng_delete_for_everyone_check);
|
||||
user->firstName);
|
||||
} else {
|
||||
result.checkbox = lang(lng_delete_for_everyone_check);
|
||||
}
|
||||
return result;
|
||||
} else if (canRevokeOutgoingCount > 0) {
|
||||
result.checkbox = lang(lng_delete_for_other_my);
|
||||
|
@ -645,6 +704,28 @@ void DeleteMessagesBox::keyPressEvent(QKeyEvent *e) {
|
|||
}
|
||||
|
||||
void DeleteMessagesBox::deleteAndClear() {
|
||||
const auto revoke = _revoke ? _revoke->checked() : false;
|
||||
if (const auto peer = _wipeHistoryPeer) {
|
||||
const auto justClear = _wipeHistoryJustClear;
|
||||
closeBox();
|
||||
|
||||
if (justClear) {
|
||||
peer->session().api().clearHistory(peer, revoke);
|
||||
} else {
|
||||
const auto controller = App::wnd()->controller();
|
||||
if (controller->activeChatCurrent().peer() == peer) {
|
||||
Ui::showChatsList();
|
||||
}
|
||||
// Don't delete old history by default,
|
||||
// because Android app doesn't.
|
||||
//
|
||||
//if (const auto from = peer->migrateFrom()) {
|
||||
// peer->session().api().deleteConversation(from, false);
|
||||
//}
|
||||
peer->session().api().deleteConversation(peer, revoke);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_moderateFrom) {
|
||||
if (_banUser && _banUser->checked()) {
|
||||
_moderateInChannel->session().api().kickParticipant(
|
||||
|
@ -688,9 +769,8 @@ void DeleteMessagesBox::deleteAndClear() {
|
|||
}
|
||||
}
|
||||
|
||||
const auto revoke = _revoke ? _revoke->checked() : false;
|
||||
for (const auto &[peer, ids] : idsByPeer) {
|
||||
App::main()->deleteMessages(peer, ids, revoke);
|
||||
peer->session().api().deleteMessages(peer, ids, revoke);
|
||||
}
|
||||
Ui::hideLayer();
|
||||
Auth().data().sendHistoryChangeNotifications();
|
||||
|
|
|
@ -151,7 +151,7 @@ public:
|
|||
not_null<HistoryItem*> item,
|
||||
bool suggestModerateActions);
|
||||
DeleteMessagesBox(QWidget*, MessageIdsList &&selected);
|
||||
DeleteMessagesBox(QWidget*, not_null<PeerData*> peer, bool deleteChat);
|
||||
DeleteMessagesBox(QWidget*, not_null<PeerData*> peer, bool justClear);
|
||||
|
||||
void setDeleteConfirmedCallback(Fn<void()> callback) {
|
||||
_deleteConfirmedCallback = std::move(callback);
|
||||
|
@ -172,6 +172,8 @@ private:
|
|||
PeerData *checkFromSinglePeer() const;
|
||||
std::optional<RevokeConfig> revokeText(not_null<PeerData*> peer) const;
|
||||
|
||||
PeerData * const _wipeHistoryPeer = nullptr;
|
||||
const bool _wipeHistoryJustClear = false;
|
||||
const MessageIdsList _ids;
|
||||
UserData *_moderateFrom = nullptr;
|
||||
ChannelData *_moderateInChannel = nullptr;
|
||||
|
|
|
@ -648,6 +648,12 @@ Data::RestrictionCheckResult PeerData::amRestricted(
|
|||
return Result::Allowed();
|
||||
}
|
||||
|
||||
bool PeerData::canRevokeFullHistory() const {
|
||||
return isUser()
|
||||
&& Global::RevokePrivateInbox()
|
||||
&& (Global::RevokePrivateTimeLimit() == 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
namespace Data {
|
||||
|
||||
std::vector<ChatRestrictions> ListOfRestrictions() {
|
||||
|
|
|
@ -160,6 +160,7 @@ public:
|
|||
[[nodiscard]] bool canWrite() const;
|
||||
[[nodiscard]] Data::RestrictionCheckResult amRestricted(
|
||||
ChatRestriction right) const;
|
||||
[[nodiscard]] bool canRevokeFullHistory() const;
|
||||
|
||||
[[nodiscard]] UserData *asUser();
|
||||
[[nodiscard]] const UserData *asUser() const;
|
||||
|
|
|
@ -899,26 +899,6 @@ void MainWidget::dialogsActivate() {
|
|||
_dialogs->activate();
|
||||
}
|
||||
|
||||
void MainWidget::deleteMessages(
|
||||
not_null<PeerData*> peer,
|
||||
const QVector<MTPint> &ids,
|
||||
bool revoke) {
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
MTP::send(
|
||||
MTPchannels_DeleteMessages(
|
||||
channel->inputChannel,
|
||||
MTP_vector<MTPint>(ids)),
|
||||
rpcDone(&MainWidget::messagesAffected, peer));
|
||||
} else {
|
||||
using Flag = MTPmessages_DeleteMessages::Flag;
|
||||
MTP::send(
|
||||
MTPmessages_DeleteMessages(
|
||||
MTP_flags(revoke ? Flag::f_revoke : Flag(0)),
|
||||
MTP_vector<MTPint>(ids)),
|
||||
rpcDone(&MainWidget::messagesAffected, peer));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::removeDialog(Dialogs::Key key) {
|
||||
_dialogs->removeDialog(key);
|
||||
}
|
||||
|
@ -1055,21 +1035,6 @@ void MainWidget::checkLastUpdate(bool afterSleep) {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::messagesAffected(
|
||||
not_null<PeerData*> peer,
|
||||
const MTPmessages_AffectedMessages &result) {
|
||||
const auto &data = result.c_messages_affectedMessages();
|
||||
if (const auto channel = peer->asChannel()) {
|
||||
channel->ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
|
||||
} else {
|
||||
ptsUpdateAndApply(data.vpts.v, data.vpts_count.v);
|
||||
}
|
||||
|
||||
if (const auto history = session().data().historyLoaded(peer)) {
|
||||
history->requestChatListMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::handleAudioUpdate(const Media::Player::TrackState &state) {
|
||||
using State = Media::Player::State;
|
||||
const auto document = state.id.audio();
|
||||
|
|
|
@ -195,11 +195,6 @@ public:
|
|||
|
||||
void deletePhotoLayer(PhotoData *photo);
|
||||
|
||||
void deleteMessages(
|
||||
not_null<PeerData*> peer,
|
||||
const QVector<MTPint> &ids,
|
||||
bool revoke);
|
||||
|
||||
bool sendMessageFail(const RPCError &error);
|
||||
|
||||
Dialogs::IndexedList *contactsList();
|
||||
|
@ -371,10 +366,6 @@ private:
|
|||
void destroyExportTopBar();
|
||||
void exportTopBarHeightUpdated();
|
||||
|
||||
void messagesAffected(
|
||||
not_null<PeerData*> peer,
|
||||
const MTPmessages_AffectedMessages &result);
|
||||
|
||||
Window::SectionSlideParams prepareShowAnimation(
|
||||
bool willHaveTopBarShadow);
|
||||
void showNewSection(
|
||||
|
|
|
@ -788,69 +788,13 @@ void PeerMenuAddMuteAction(
|
|||
|
||||
Fn<void()> ClearHistoryHandler(not_null<PeerData*> peer) {
|
||||
return [=] {
|
||||
const auto weak = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto text = peer->isSelf()
|
||||
? lang(lng_sure_delete_saved_messages)
|
||||
: peer->isUser()
|
||||
? lng_sure_delete_history(lt_contact, peer->name)
|
||||
: lng_sure_delete_group_history(lt_group, peer->name);
|
||||
const auto callback = [=] {
|
||||
if (const auto strong = *weak) {
|
||||
strong->closeBox();
|
||||
}
|
||||
peer->session().api().clearHistory(peer, false);
|
||||
};
|
||||
*weak = Ui::show(
|
||||
Box<ConfirmBox>(
|
||||
text,
|
||||
lang(lng_box_delete),
|
||||
st::attentionBoxButton,
|
||||
callback),
|
||||
LayerOption::KeepOther);
|
||||
Ui::show(Box<DeleteMessagesBox>(peer, true), LayerOption::KeepOther);
|
||||
};
|
||||
}
|
||||
|
||||
Fn<void()> DeleteAndLeaveHandler(not_null<PeerData*> peer) {
|
||||
return [=] {
|
||||
const auto weak = std::make_shared<QPointer<BoxContent>>();
|
||||
const auto text = peer->isSelf()
|
||||
? lang(lng_sure_delete_saved_messages)
|
||||
: peer->isUser()
|
||||
? lng_sure_delete_history(lt_contact, peer->name)
|
||||
: peer->isChat()
|
||||
? lng_sure_delete_and_exit(lt_group, peer->name)
|
||||
: lang(peer->isMegagroup()
|
||||
? lng_sure_leave_group
|
||||
: lng_sure_leave_channel);
|
||||
const auto confirm = lang(peer->isUser()
|
||||
? lng_box_delete
|
||||
: lng_box_leave);
|
||||
const auto &confirmStyle = peer->isChannel()
|
||||
? st::defaultBoxButton
|
||||
: st::attentionBoxButton;
|
||||
const auto callback = [=] {
|
||||
if (const auto strong = *weak) {
|
||||
strong->closeBox();
|
||||
}
|
||||
const auto controller = App::wnd()->controller();
|
||||
if (controller->activeChatCurrent().peer() == peer) {
|
||||
Ui::showChatsList();
|
||||
}
|
||||
// Don't delete old history by default,
|
||||
// because Android app doesn't.
|
||||
//
|
||||
//if (const auto from = peer->migrateFrom()) {
|
||||
// peer->session().api().deleteConversation(from, false);
|
||||
//}
|
||||
peer->session().api().deleteConversation(peer, false);
|
||||
};
|
||||
*weak = Ui::show(
|
||||
Box<ConfirmBox>(
|
||||
text,
|
||||
confirm,
|
||||
confirmStyle,
|
||||
callback),
|
||||
LayerOption::KeepOther);
|
||||
Ui::show(Box<DeleteMessagesBox>(peer, false), LayerOption::KeepOther);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue