Handle ttl_period locally.

This commit is contained in:
John Preston 2021-02-02 20:38:30 +04:00
parent 046a3906c4
commit 6a6e355af4
13 changed files with 282 additions and 69 deletions

View file

@ -1331,14 +1331,7 @@ void Updates::applyUpdates(
item->id,
ApiWrap::RequestMessageDataCallback());
}
item->updateSentContent({
sent.text,
Api::EntitiesFromMTP(&session(), list.value_or_empty())
}, d.vmedia());
item->contributeToSlowmode(d.vdate().v);
if (!wasAlready) {
item->indexAsNewItem();
}
item->applySentMessage(sent.text, d, wasAlready);
}
}
@ -1829,7 +1822,14 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updatePeerHistoryTTL: {
const auto &d = update.c_updatePeerHistoryTTL();
// #TODO ttl
const auto peerId = peerFromMTP(d.vpeer());
if (const auto peer = session().data().peerLoaded(peerId)) {
if (const auto ttl = d.vttl()) {
peer->applyMessagesTTL(*ttl);
} else {
peer->setMessagesTTL(0, 0, false);
}
}
} break;
case mtpc_updateNewEncryptedMessage: {

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "boxes/add_contact_box.h"
#include "boxes/confirm_box.h"
#include "boxes/single_choice_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/peers/edit_participants_box.h"
#include "boxes/peers/edit_peer_type_box.h"
@ -307,13 +308,14 @@ private:
Ui::UserpicButton *photo = nullptr;
rpl::lifetime initialPhotoImageWaiting;
Ui::VerticalLayout *buttonsLayout = nullptr;
Ui::SlideWrap<Ui::RpWidget> *historyVisibilityWrap = nullptr;
Ui::SlideWrap<> *historyVisibilityWrap = nullptr;
};
struct Saving {
std::optional<QString> username;
std::optional<QString> title;
std::optional<QString> description;
std::optional<bool> hiddenPreHistory;
std::optional<TimeId> messagesTTL;
std::optional<bool> signatures;
std::optional<ChannelData*> linkedChat;
};
@ -335,6 +337,7 @@ private:
//void fillInviteLinkButton();
void fillSignaturesButton();
void fillHistoryVisibilityButton();
void fillSetMessagesTTLButton();
void fillManageSection();
void submitTitle();
@ -348,6 +351,7 @@ private:
bool validateTitle(Saving &to) const;
bool validateDescription(Saving &to) const;
bool validateHistoryVisibility(Saving &to) const;
bool validateMessagesTTL(Saving &to) const;
bool validateSignatures(Saving &to) const;
void save();
@ -356,6 +360,7 @@ private:
void saveTitle();
void saveDescription();
void saveHistoryVisibility();
void saveMessagesTTL();
void saveSignatures();
void savePhoto();
void pushSaveStage(FnMut<void()> &&lambda);
@ -372,6 +377,7 @@ private:
void migrate(not_null<ChannelData*> channel);
std::optional<Privacy> _privacySavedValue;
std::optional<TimeId> _ttlSavedValue;
std::optional<ChannelData*> _linkedChatSavedValue;
ChannelData *_linkedChatOriginalValue = nullptr;
bool _channelHasLocationOriginalValue = false;
@ -637,7 +643,7 @@ void Controller::refreshHistoryVisibility(anim::type animated) {
&& !_channelHasLocationOriginalValue
&& (!_linkedChatSavedValue || !*_linkedChatSavedValue)),
animated);
};
}
void Controller::showEditPeerTypeBox(
std::optional<rpl::producer<QString>> error) {
@ -880,6 +886,68 @@ void Controller::fillHistoryVisibilityButton() {
refreshHistoryVisibility(anim::type::instant);
}
void Controller::fillSetMessagesTTLButton() {
Expects(_controls.buttonsLayout != nullptr);
_ttlSavedValue = _peer->messagesTTL();
const auto updateMessagesTTL =
std::make_shared<rpl::event_stream<TimeId>>();
const auto boxCallback = crl::guard(this, [=](TimeId value) {
updateMessagesTTL->fire_copy(value);
_ttlSavedValue = value;
});
const auto buttonCallback = [=] {
Ui::show(Box([=](not_null<Ui::GenericBox*> box) {
const auto options = {
tr::lng_manage_messages_ttl_never(tr::now),
tr::lng_manage_messages_ttl_after1(tr::now),
tr::lng_manage_messages_ttl_after2(tr::now),
u"5 seconds"_q, AssertIsDebug()
};
const auto initial = !*_ttlSavedValue
? 0
: (*_ttlSavedValue == 5) AssertIsDebug()
? 3 AssertIsDebug()
: (*_ttlSavedValue < 3 * 86400)
? 1
: 2;
const auto callback = [=](int option) {
boxCallback(!option
? 0
: (option == 1)
? 86400
: (option == 3) AssertIsDebug()
? 5 AssertIsDebug()
: 7 * 86400);
};
SingleChoiceBox(box, {
.title = tr::lng_manage_messages_ttl_title(),
.options = options,
.initialSelection = initial,
.callback = callback,
});
}), Ui::LayerOption::KeepOther);
};
AddButtonWithText(
_controls.buttonsLayout,
tr::lng_manage_messages_ttl_title(),
updateMessagesTTL->events(
) | rpl::map([](TimeId value) {
return !value
? tr::lng_manage_messages_ttl_never()
: (value == 5) AssertIsDebug()
? rpl::single<QString>("5 seconds") AssertIsDebug()
: (value < 3 * 86400)
? tr::lng_manage_messages_ttl_after1()
: tr::lng_manage_messages_ttl_after2();
}) | rpl::flatten_latest(),
buttonCallback);
updateMessagesTTL->fire_copy(*_ttlSavedValue);
}
void Controller::fillManageSection() {
Expects(_controls.buttonsLayout != nullptr);
@ -903,6 +971,11 @@ void Controller::fillManageSection() {
? channel->canEditPreHistoryHidden()
: chat->canEditPreHistoryHidden();
}();
const auto canSetMessagesTTL = [&] {
return isChannel
? channel->canDeleteMessages()
: chat->canDeleteMessages();
}();
const auto canEditPermissions = [&] {
return isChannel
@ -965,17 +1038,21 @@ void Controller::fillManageSection() {
if (canViewOrEditLinkedChat) {
fillLinkedChatButton();
}
if (canEditSignatures) {
fillSignaturesButton();
}
if (canEditPreHistoryHidden) {
fillHistoryVisibilityButton();
}
if (canSetMessagesTTL) {
fillSetMessagesTTLButton();
}
if (canEditSignatures) {
fillSignaturesButton();
}
if (canEditPreHistoryHidden
|| canEditSignatures
|| canEditInviteLinks
|| canViewOrEditLinkedChat
|| canEditUsername) {
|| canEditUsername
|| canSetMessagesTTL) {
AddSkip(
_controls.buttonsLayout,
st::editPeerTopButtonsLayoutSkip,
@ -1132,6 +1209,7 @@ std::optional<Controller::Saving> Controller::validate() const {
&& validateTitle(result)
&& validateDescription(result)
&& validateHistoryVisibility(result)
&& validateMessagesTTL(result)
&& validateSignatures(result)) {
return result;
}
@ -1199,6 +1277,14 @@ bool Controller::validateHistoryVisibility(Saving &to) const {
return true;
}
bool Controller::validateMessagesTTL(Saving &to) const {
if (!_ttlSavedValue) {
return true;
}
to.messagesTTL = _ttlSavedValue;
return true;
}
bool Controller::validateSignatures(Saving &to) const {
if (!_signaturesSavedValue.has_value()) {
return true;
@ -1220,6 +1306,7 @@ void Controller::save() {
pushSaveStage([=] { saveTitle(); });
pushSaveStage([=] { saveDescription(); });
pushSaveStage([=] { saveHistoryVisibility(); });
pushSaveStage([=] { saveMessagesTTL(); });
pushSaveStage([=] { saveSignatures(); });
pushSaveStage([=] { savePhoto(); });
continueSave();
@ -1427,6 +1514,24 @@ void Controller::saveHistoryVisibility() {
[=] { cancelSave(); });
}
void Controller::saveMessagesTTL() {
if (!_savingData.messagesTTL
|| *_savingData.messagesTTL == _peer->messagesTTL()) {
return continueSave();
}
using Flag = MTPmessages_SetHistoryTTL::Flag;
_api.request(MTPmessages_SetHistoryTTL(
MTP_flags(_peer->oneSideTTL() ? Flag::f_pm_oneside : Flag(0)),
_peer->input,
MTP_int(*_savingData.messagesTTL)
)).done([=](const MTPUpdates &result) {
_peer->session().api().applyUpdates(result);
continueSave();
}).fail([=](const RPCError &error) {
cancelSave();
}).send();
}
void Controller::togglePreHistoryHidden(
not_null<ChannelData*> channel,
bool hidden,

View file

@ -749,6 +749,9 @@ void ApplyChannelUpdate(
channel->clearGroupCall();
}
if (const auto ttl = update.vttl()) {
channel->applyMessagesTTL(*ttl);
}
channel->setFullFlags(update.vflags().v);
channel->setUserpicPhoto(update.vchat_photo());
if (const auto migratedFrom = update.vmigrated_from_chat_id()) {

View file

@ -84,6 +84,11 @@ bool ChatData::canEditPreHistoryHidden() const {
return amCreator();
}
bool ChatData::canDeleteMessages() const {
return amCreator()
|| (adminRights() & AdminRight::f_delete_messages);
}
bool ChatData::canAddMembers() const {
return amIn() && !amRestricted(Restriction::f_invite_users);
}
@ -372,6 +377,9 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
chat->clearGroupCall();
}
if (const auto ttl = update.vttl()) {
chat->applyMessagesTTL(*ttl);
}
if (const auto info = update.vbot_info()) {
for (const auto &item : info->v) {
item.match([&](const MTPDbotInfo &data) {

View file

@ -128,16 +128,17 @@ public:
[[nodiscard]] AdminRights defaultAdminRights(not_null<UserData*> user);
// Like in ChannelData.
bool canWrite() const;
bool canEditInformation() const;
bool canEditPermissions() const;
bool canEditUsername() const;
bool canEditPreHistoryHidden() const;
bool canAddMembers() const;
bool canAddAdmins() const;
bool canBanMembers() const;
bool canSendPolls() const;
bool anyoneCanAddMembers() const;
[[nodiscard]] bool canWrite() const;
[[nodiscard]] bool canEditInformation() const;
[[nodiscard]] bool canEditPermissions() const;
[[nodiscard]] bool canEditUsername() const;
[[nodiscard]] bool canEditPreHistoryHidden() const;
[[nodiscard]] bool canDeleteMessages() const;
[[nodiscard]] bool canAddMembers() const;
[[nodiscard]] bool canAddAdmins() const;
[[nodiscard]] bool canBanMembers() const;
[[nodiscard]] bool canSendPolls() const;
[[nodiscard]] bool anyoneCanAddMembers() const;
void applyEditAdmin(not_null<UserData*> user, bool isAdmin);

View file

@ -945,6 +945,35 @@ void PeerData::setLoadedStatus(LoadedStatus status) {
_loadedStatus = status;
}
TimeId PeerData::messagesTTL() const {
return (_ttlMyPeriod && _ttlPeerPeriod)
? std::min(_ttlMyPeriod, _ttlPeerPeriod)
: std::max(_ttlMyPeriod, _ttlPeerPeriod);
}
void PeerData::setMessagesTTL(
TimeId myPeriod,
TimeId peerPeriod,
bool oneSide) {
_ttlMyPeriod = myPeriod;
_ttlPeerPeriod = peerPeriod;
_ttlOneSide = oneSide;
}
void PeerData::applyMessagesTTL(const MTPPeerHistoryTTL &ttl) {
ttl.match([&](const MTPDpeerHistoryTTL &data) {
setMessagesTTL(
data.vttl_period().v,
data.vttl_period().v,
false);
}, [&](const MTPDpeerHistoryTTLPM &data) {
setMessagesTTL(
data.vmy_ttl_period().value_or_empty(),
data.vpeer_ttl_period().value_or_empty(),
data.is_my_oneside());
});
}
namespace Data {
std::vector<ChatRestrictions> ListOfRestrictions() {

View file

@ -17,6 +17,11 @@ class UserData;
class ChatData;
class ChannelData;
using ChatAdminRight = MTPDchatAdminRights::Flag;
using ChatRestriction = MTPDchatBannedRights::Flag;
using ChatAdminRights = MTPDchatAdminRights::Flags;
using ChatRestrictions = MTPDchatBannedRights::Flags;
namespace Ui {
class EmptyUserpic;
} // namespace Ui
@ -30,23 +35,13 @@ namespace Data {
class Session;
class GroupCall;
class CloudImageView;
int PeerColorIndex(PeerId peerId);
int PeerColorIndex(int32 bareId);
style::color PeerUserpicColor(PeerId peerId);
PeerId FakePeerIdForJustName(const QString &name);
} // namespace Data
using ChatAdminRight = MTPDchatAdminRights::Flag;
using ChatRestriction = MTPDchatBannedRights::Flag;
using ChatAdminRights = MTPDchatAdminRights::Flags;
using ChatRestrictions = MTPDchatBannedRights::Flags;
namespace Data {
class CloudImageView;
class RestrictionCheckResult {
public:
[[nodiscard]] static RestrictionCheckResult Allowed() {
@ -386,6 +381,19 @@ public:
}
void setLoadedStatus(LoadedStatus status);
[[nodiscard]] TimeId myMessagesTTL() const {
return _ttlMyPeriod;
}
[[nodiscard]] TimeId peerMessagesTTL() const {
return _ttlPeerPeriod;
}
[[nodiscard]] bool oneSideTTL() const {
return _ttlOneSide;
}
[[nodiscard]] TimeId messagesTTL() const;
void setMessagesTTL(TimeId myPeriod, TimeId peerPeriod, bool oneSide);
void applyMessagesTTL(const MTPPeerHistoryTTL &ttl);
[[nodiscard]] Data::GroupCall *groupCall() const;
const PeerId id;
@ -429,6 +437,10 @@ private:
base::flat_set<QChar> _nameFirstLetters;
crl::time _lastFullUpdate = 0;
TimeId _ttlMyPeriod = 0;
TimeId _ttlPeerPeriod = 0;
bool _ttlOneSide = false;
bool _hasPinnedMessages = false;
Settings _settings = { kSettingsUnknown };

View file

@ -1846,33 +1846,7 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
if (!existing) {
return false;
}
existing->updateSentContent({
qs(data.vmessage()),
Api::EntitiesFromMTP(
&session(),
data.ventities().value_or_empty())
}, data.vmedia());
existing->updateReplyMarkup(data.vreply_markup());
existing->updateForwardedInfo(data.vfwd_from());
existing->setViewsCount(data.vviews().value_or(-1));
if (const auto replies = data.vreplies()) {
existing->setReplies(*replies);
} else {
existing->clearReplies();
}
existing->setForwardsCount(data.vforwards().value_or(-1));
if (const auto reply = data.vreply_to()) {
reply->match([&](const MTPDmessageReplyHeader &data) {
existing->setReplyToTop(
data.vreply_to_top_id().value_or(
data.vreply_to_msg_id().v));
});
}
existing->setPostAuthor(data.vpost_author().value_or_empty());
existing->indexAsNewItem();
existing->contributeToSlowmode(data.vdate().v);
requestItemTextRefresh(existing);
updateDependentMessages(existing);
existing->applySentMessage(data);
const auto result = (existing->mainView() != nullptr);
if (result) {
stickers().checkSavedGif(existing);

View file

@ -256,6 +256,9 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
MTP_inputNotifyPeer(user->input),
update.vnotify_settings());
if (const auto ttl = update.vttl()) {
user->applyMessagesTTL(*ttl);
}
if (const auto info = update.vbot_info()) {
user->setBotInfo(*info);
} else {

View file

@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "core/crash_reports.h"
#include "base/unixtime.h"
#include "api/api_text_entities.h"
#include "data/data_scheduled_messages.h" // kScheduledUntilOnlineTimestamp
#include "data/data_changes.h"
#include "data/data_session.h"
@ -490,6 +491,52 @@ void HistoryItem::applyEditionToHistoryCleared() {
).c_messageService());
}
void HistoryItem::applySentMessage(const MTPDmessage &data) {
updateSentContent({
qs(data.vmessage()),
Api::EntitiesFromMTP(
&history()->session(),
data.ventities().value_or_empty())
}, data.vmedia());
updateReplyMarkup(data.vreply_markup());
updateForwardedInfo(data.vfwd_from());
setViewsCount(data.vviews().value_or(-1));
if (const auto replies = data.vreplies()) {
setReplies(*replies);
} else {
clearReplies();
}
setForwardsCount(data.vforwards().value_or(-1));
if (const auto reply = data.vreply_to()) {
reply->match([&](const MTPDmessageReplyHeader &data) {
setReplyToTop(
data.vreply_to_top_id().value_or(
data.vreply_to_msg_id().v));
});
}
setPostAuthor(data.vpost_author().value_or_empty());
contributeToSlowmode(data.vdate().v);
indexAsNewItem();
history()->owner().requestItemTextRefresh(this);
history()->owner().updateDependentMessages(this);
}
void HistoryItem::applySentMessage(
const QString &text,
const MTPDupdateShortSentMessage &data,
bool wasAlready) {
updateSentContent({
text,
Api::EntitiesFromMTP(
&history()->session(),
data.ventities().value_or_empty())
}, data.vmedia());
contributeToSlowmode(data.vdate().v);
if (!wasAlready) {
indexAsNewItem();
}
}
void HistoryItem::indexAsNewItem() {
if (IsServerMsgId(id)) {
addToUnreadMentions(UnreadMentionType::New);
@ -629,9 +676,7 @@ bool HistoryItem::canDeleteForEveryone(TimeId now) const {
}
if (!out()) {
if (const auto chat = peer->asChat()) {
if (!chat->amCreator()
&& !(chat->adminRights()
& ChatAdminRight::f_delete_messages)) {
if (!chat->canDeleteMessages()) {
return false;
}
} else if (peer->isUser()) {

View file

@ -262,6 +262,12 @@ public:
}
[[nodiscard]] virtual Storage::SharedMediaTypesMask sharedMediaTypes() const = 0;
virtual void applySentMessage(const MTPDmessage &data);
virtual void applySentMessage(
const QString &text,
const MTPDupdateShortSentMessage &data,
bool wasAlready);
void indexAsNewItem();
[[nodiscard]] virtual QString notificationHeader() const {

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_message.h"
#include "base/openssl_help.h"
#include "base/unixtime.h"
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "mainwindow.h"
@ -50,9 +51,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_chat.h"
#include "styles/style_window.h"
#include "base/call_delayed.h" // #TODO ttl
#include "base/unixtime.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
@ -976,6 +974,29 @@ bool HistoryMessage::updateDependencyItem() {
return true;
}
void HistoryMessage::applySentMessage(const MTPDmessage &data) {
HistoryItem::applySentMessage(data);
if (const auto period = data.vttl_period(); period && period->v > 0) {
applyTTL(data.vdate().v + period->v);
} else {
applyTTL(0);
}
}
void HistoryMessage::applySentMessage(
const QString &text,
const MTPDupdateShortSentMessage &data,
bool wasAlready) {
HistoryItem::applySentMessage(text, data, wasAlready);
if (const auto period = data.vttl_period(); period && period->v > 0) {
applyTTL(data.vdate().v + period->v);
} else {
applyTTL(0);
}
}
bool HistoryMessage::allowsForward() const {
if (id < 0 || !isHistoryEntry()) {
return false;

View file

@ -188,6 +188,12 @@ public:
return replyToId();
}
void applySentMessage(const MTPDmessage &data) override;
void applySentMessage(
const QString &text,
const MTPDupdateShortSentMessage &data,
bool wasAlready) override;
[[nodiscard]] TimeId ttlDestroyAt() const override {
return _ttlDestroyAt;
}