New notifications API, defaults for users/chats.

This commit is contained in:
John Preston 2018-04-09 21:48:29 +04:00
parent 4b4e22d59d
commit 734c410879
32 changed files with 724 additions and 541 deletions

View File

@ -304,17 +304,10 @@ auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorizat
inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
inputNotifyUsers#193b4417 = InputNotifyPeer;
inputNotifyChats#4a95e84e = InputNotifyPeer;
inputNotifyAll#a429b886 = InputNotifyPeer;
inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents;
inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents;
inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = InputPeerNotifySettings;
inputPeerNotifySettings#38935eb2 flags:# show_previews:flags.0?true silent:flags.1?true mute_until:int sound:string = InputPeerNotifySettings;
peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents;
peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents;
peerNotifySettings#9acda4c0 flags:# show_previews:flags.0?true silent:flags.1?true mute_until:int sound:string = PeerNotifySettings;
peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings;
peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings;
@ -515,7 +508,6 @@ help.support#17c6b5f6 phone_number:string user:User = help.Support;
notifyPeer#9fd40bd8 peer:Peer = NotifyPeer;
notifyUsers#b4c83b4c = NotifyPeer;
notifyChats#c007cec3 = NotifyPeer;
notifyAll#74d07c60 = NotifyPeer;
sendMessageTypingAction#16bf744e = SendMessageAction;
sendMessageCancelAction#fd5ec8f5 = SendMessageAction;
@ -568,7 +560,7 @@ documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
documentAttributeHasStickers#9801d2f7 = DocumentAttribute;
messages.stickersNotModified#f1749a22 = messages.Stickers;
messages.stickers#8a8ecd32 hash:string stickers:Vector<Document> = messages.Stickers;
messages.stickers#e4599bbd hash:int stickers:Vector<Document> = messages.Stickers;
stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;
@ -697,7 +689,7 @@ messages.savedGifs#2e0709a5 hash:int gifs:Vector<Document> = messages.SavedGifs;
inputBotInlineMessageMediaAuto#3380c786 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageText#3dcd7a87 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaGeo#c1b15d65 flags:# geo_point:InputGeoPoint period:int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaVenue#aaafadc8 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaContact#2daf01a7 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
@ -709,7 +701,7 @@ inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:Input
botInlineMessageMediaAuto#764cf810 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaVenue#4366232e flags:# geo:GeoPoint title:string address:string provider:string venue_id:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#35edb4d4 flags:# phone_number:string first_name:string last_name:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
@ -848,6 +840,8 @@ webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vect
inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;
inputWebFileLocation#c239d686 url:string access_hash:long = InputWebFileLocation;
inputWebFileGeoPointLocation#66275a62 geo_point:InputGeoPoint w:int h:int zoom:int scale:int = InputWebFileLocation;
inputWebFileGeoMessageLocation#553f32eb peer:InputPeer msg_id:int w:int h:int zoom:int scale:int = InputWebFileLocation;
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
@ -975,7 +969,6 @@ initConnection#785188b8 {X:Type} flags:# api_id:int device_model:string system_v
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
auth.checkPhone#6fe51dfb phone_number:string = auth.CheckedPhone;
auth.sendCode#86aef0ec flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool api_id:int api_hash:string = auth.SentCode;
auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization;
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
@ -1078,7 +1071,7 @@ messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long da
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool;
messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages;
messages.getStickers#85cb5182 flags:# exclude_featured:flags.0?true emoticon:string hash:string = messages.Stickers;
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
@ -1102,8 +1095,8 @@ messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_p
messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool;
messages.sendInlineBotResult#b16e06fe flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates;
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
messages.editMessage#5d1b8dd flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true peer:InputPeer id:int message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Updates;
messages.editInlineBotMessage#b0e08243 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Bool;
messages.editMessage#c000e4c8 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Updates;
messages.editInlineBotMessage#adc3e828 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Bool;
messages.getBotCallbackAnswer#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer;
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
@ -1165,7 +1158,7 @@ help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getInviteText#4d392343 = help.InviteText;
help.getSupport#9cdf08cd = help.Support;
help.getAppChangelog#9010ef6f prev_app_version:string = Updates;
help.getTermsOfService#350170f3 = help.TermsOfService;
help.getTermsOfService#8e59b7e7 country_iso2:string = help.TermsOfService;
help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool;
help.getCdnConfig#52029342 = CdnConfig;
help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls;
@ -1233,4 +1226,4 @@ langpack.getStrings#2e1ee318 lang_code:string keys:Vector<string> = Vector<LangP
langpack.getDifference#b2e4d7d from_version:int = LangPackDifference;
langpack.getLanguages#800fd57d = Vector<LangPackLanguage>;
// LAYER 78
// LAYER 79

View File

@ -62,6 +62,7 @@ constexpr auto kReadFeaturedSetsTimeout = TimeMs(1000);
constexpr auto kFileLoaderQueueStopTimeout = TimeMs(5000);
constexpr auto kFeedReadTimeout = TimeMs(1000);
constexpr auto kStickersByEmojiInvalidateTimeout = TimeMs(60 * 60 * 1000);
constexpr auto kNotifySettingSaveTimeout = TimeMs(1000);
bool IsSilentPost(not_null<HistoryItem*> item, bool silent) {
const auto history = item->history();
@ -128,7 +129,7 @@ FileLoadTo FileLoadTaskOptions(const ApiWrap::SendOptions &options) {
const auto peer = options.history->peer;
return FileLoadTo(
peer->id,
peer->notifySilentPosts(),
Auth().data().notifySilentPosts(peer),
options.replyTo);
}
@ -142,7 +143,8 @@ ApiWrap::ApiWrap(not_null<AuthSession*> session)
, _featuredSetsReadTimer([=] { readFeaturedSets(); })
, _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout))
, _feedReadTimer([=] { readFeeds(); })
, _proxyPromotionTimer([=] { refreshProxyPromotion(); }) {
, _proxyPromotionTimer([=] { refreshProxyPromotion(); })
, _updateNotifySettingsTimer([=] { sendNotifySettingsUpdates(); }) {
}
void ApiWrap::requestChangelog(
@ -273,7 +275,7 @@ void ApiWrap::savePinnedOrder() {
// )).done([=](const MTPUpdates &result) {
// applyUpdates(result);
// if (group) {
// channel->setFeed(Auth().data().feed(feedId));
// channel->setFeed(_session->data().feed(feedId));
// } else {
// channel->clearFeed();
// }
@ -542,7 +544,7 @@ void ApiWrap::applyPeerDialogs(const MTPmessages_PeerDialogs &dialogs) {
//case mtpc_dialogFeed: { // #feed
// const auto &fields = dialog.c_dialogFeed();
// const auto feed = Auth().data().feed(fields.vfeed_id.v);
// const auto feed = _session->data().feed(fields.vfeed_id.v);
// feed->applyDialog(fields);
//} break;
}
@ -1376,7 +1378,7 @@ void ApiWrap::deleteAllFromUser(
}
}
Auth().data().sendHistoryChangeNotifications();
_session->data().sendHistoryChangeNotifications();
deleteAllFromUserSend(channel, from);
}
@ -1393,7 +1395,7 @@ void ApiWrap::deleteAllFromUserSend(
deleteAllFromUserSend(channel, from);
} else if (const auto history = App::historyLoaded(channel)) {
if (!history->lastMessageKnown()) {
Auth().api().requestDialogEntry(history);
requestDialogEntry(history);
}
}
}).send();
@ -1637,83 +1639,137 @@ void ApiWrap::leaveChannel(not_null<ChannelData*> channel) {
}
}
void ApiWrap::blockUser(UserData *user) {
void ApiWrap::blockUser(not_null<UserData*> user) {
if (user->isBlocked()) {
Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserIsBlocked);
} else if (!_blockRequests.contains(user)) {
} else if (_blockRequests.find(user) == end(_blockRequests)) {
auto requestId = request(MTPcontacts_Block(user->inputUser)).done([this, user](const MTPBool &result) {
_blockRequests.remove(user);
_blockRequests.erase(user);
user->setBlockStatus(UserData::BlockStatus::Blocked);
}).fail([this, user](const RPCError &error) {
_blockRequests.remove(user);
_blockRequests.erase(user);
}).send();
_blockRequests.insert(user, requestId);
_blockRequests.emplace(user, requestId);
}
}
void ApiWrap::unblockUser(UserData *user) {
void ApiWrap::unblockUser(not_null<UserData*> user) {
if (!user->isBlocked()) {
Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserIsBlocked);
} else if (!_blockRequests.contains(user)) {
} else if (_blockRequests.find(user) == end(_blockRequests)) {
auto requestId = request(MTPcontacts_Unblock(user->inputUser)).done([this, user](const MTPBool &result) {
_blockRequests.remove(user);
_blockRequests.erase(user);
user->setBlockStatus(UserData::BlockStatus::NotBlocked);
}).fail([this, user](const RPCError &error) {
_blockRequests.remove(user);
_blockRequests.erase(user);
}).send();
_blockRequests.insert(user, requestId);
_blockRequests.emplace(user, requestId);
}
}
void ApiWrap::exportInviteLink(PeerData *peer) {
if (_exportInviteRequests.contains(peer)) {
void ApiWrap::exportInviteLink(not_null<PeerData*> peer) {
if (_exportInviteRequests.find(peer) != end(_exportInviteRequests)) {
return;
}
auto sendRequest = [this, peer] {
auto exportFail = [this, peer](const RPCError &error) {
_exportInviteRequests.remove(peer);
const auto sendRequest = [this, peer] {
const auto exportFail = [this, peer](const RPCError &error) {
_exportInviteRequests.erase(peer);
};
if (auto chat = peer->asChat()) {
return request(MTPmessages_ExportChatInvite(chat->inputChat)).done([this, chat](const MTPExportedChatInvite &result) {
_exportInviteRequests.remove(chat);
chat->setInviteLink((result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString());
if (const auto chat = peer->asChat()) {
return request(MTPmessages_ExportChatInvite(
chat->inputChat
)).done([=](const MTPExportedChatInvite &result) {
_exportInviteRequests.erase(chat);
chat->setInviteLink(
(result.type() == mtpc_chatInviteExported
? qs(result.c_chatInviteExported().vlink)
: QString()));
}).fail(exportFail).send();
} else if (auto channel = peer->asChannel()) {
return request(MTPchannels_ExportInvite(channel->inputChannel)).done([this, channel](const MTPExportedChatInvite &result) {
_exportInviteRequests.remove(channel);
channel->setInviteLink((result.type() == mtpc_chatInviteExported) ? qs(result.c_chatInviteExported().vlink) : QString());
} else if (const auto channel = peer->asChannel()) {
return request(MTPchannels_ExportInvite(
channel->inputChannel
)).done([=](const MTPExportedChatInvite &result) {
_exportInviteRequests.erase(channel);
channel->setInviteLink(
(result.type() == mtpc_chatInviteExported
? qs(result.c_chatInviteExported().vlink)
: QString()));
}).fail(exportFail).send();
}
return 0;
};
if (auto requestId = sendRequest()) {
_exportInviteRequests.insert(peer, requestId);
if (const auto requestId = sendRequest()) {
_exportInviteRequests.emplace(peer, requestId);
}
}
void ApiWrap::requestNotifySetting(PeerData *peer) {
if (_notifySettingRequests.contains(peer)) return;
auto notifyPeer = MTP_inputNotifyPeer(peer->input);
auto requestId = request(MTPaccount_GetNotifySettings(notifyPeer)).done([this, notifyPeer, peer](const MTPPeerNotifySettings &result) {
notifySettingReceived(notifyPeer, result);
_notifySettingRequests.remove(peer);
}).fail([this, notifyPeer, peer](const RPCError &error) {
notifySettingReceived(notifyPeer, MTP_peerNotifySettings(
MTP_flags(MTPDpeerNotifySettings::Flag::f_show_previews),
MTP_int(0),
MTP_string("default")));
_notifySettingRequests.remove(peer);
void ApiWrap::requestNotifySettings(const MTPInputNotifyPeer &peer) {
const auto key = [&] {
switch (peer.type()) {
case mtpc_inputNotifyUsers: return peerFromUser(0);
case mtpc_inputNotifyChats: return peerFromChat(0);
case mtpc_inputNotifyPeer: {
const auto &inner = peer.c_inputNotifyPeer().vpeer;
switch (inner.type()) {
case mtpc_inputPeerSelf:
return _session->userPeerId();
case mtpc_inputPeerEmpty:
return PeerId(0);
case mtpc_inputPeerChannel:
return peerFromChannel(
inner.c_inputPeerChannel().vchannel_id);
case mtpc_inputPeerChat:
return peerFromChat(inner.c_inputPeerChat().vchat_id);
case mtpc_inputPeerUser:
return peerFromUser(inner.c_inputPeerUser().vuser_id);
}
Unexpected("Type in ApiRequest::requestNotifySettings peer.");
} break;
}
Unexpected("Type in ApiRequest::requestNotifySettings.");
}();
if (_notifySettingRequests.find(key) != end(_notifySettingRequests)) {
return;
}
auto requestId = request(MTPaccount_GetNotifySettings(
peer
)).done([=](const MTPPeerNotifySettings &result) {
notifySettingReceived(peer, result);
_notifySettingRequests.erase(key);
}).fail([=](const RPCError &error) {
notifySettingReceived(peer, MTP_peerNotifySettings(
MTP_flags(0),
MTPBool(),
MTPBool(),
MTPint(),
MTPstring()));
_notifySettingRequests.erase(key);
}).send();
_notifySettingRequests.insert(peer, requestId);
_notifySettingRequests.emplace(key, requestId);
}
void ApiWrap::saveDraftToCloudDelayed(History *history) {
_draftsSaveRequestIds.insert(history, 0);
void ApiWrap::updateNotifySettingsDelayed(not_null<const PeerData*> peer) {
_updateNotifySettingsPeers.emplace(peer);
_updateNotifySettingsTimer.callOnce(kNotifySettingSaveTimeout);
}
void ApiWrap::sendNotifySettingsUpdates() {
while (!_updateNotifySettingsPeers.empty()) {
const auto peer = *_updateNotifySettingsPeers.begin();
_updateNotifySettingsPeers.erase(_updateNotifySettingsPeers.begin());
request(MTPaccount_UpdateNotifySettings(
MTP_inputNotifyPeer(peer->input),
peer->notifySerialize()
)).afterDelay(_updateNotifySettingsPeers.empty() ? 0 : 10).send();
}
}
void ApiWrap::saveDraftToCloudDelayed(not_null<History*> history) {
_draftsSaveRequestIds.emplace(history, 0);
if (!_draftsSaveTimer.isActive()) {
_draftsSaveTimer.callOnce(kSaveCloudDraftTimeout);
}
@ -1729,6 +1785,7 @@ void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacy
auto requestId = request(MTPaccount_SetPrivacy(key, MTP_vector<MTPInputPrivacyRule>(std::move(rules)))).done([this, keyTypeId](const MTPaccount_PrivacyRules &result) {
Expects(result.type() == mtpc_account_privacyRules);
auto &rules = result.c_account_privacyRules();
App::feedUsers(rules.vusers);
_privacySaveRequests.remove(keyTypeId);
@ -1904,9 +1961,9 @@ void ApiWrap::applyAffectedMessages(
void ApiWrap::saveDraftsToCloud() {
for (auto i = _draftsSaveRequestIds.begin(), e = _draftsSaveRequestIds.end(); i != e; ++i) {
if (i.value()) continue; // sent already
if (i->second) continue; // sent already
auto history = i.key();
auto history = i->first;
auto cloudDraft = history->cloudDraft();
auto localDraft = history->localDraft();
if (cloudDraft && cloudDraft->saveRequestId) {
@ -1935,8 +1992,8 @@ void ApiWrap::saveDraftsToCloud() {
}
}
auto i = _draftsSaveRequestIds.find(history);
if (i != _draftsSaveRequestIds.cend() && i.value() == requestId) {
_draftsSaveRequestIds.remove(history);
if (i != _draftsSaveRequestIds.cend() && i->second == requestId) {
_draftsSaveRequestIds.erase(history);
checkQuitPreventFinished();
}
}).fail([this, history](const RPCError &error, mtpRequestId requestId) {
@ -1946,18 +2003,18 @@ void ApiWrap::saveDraftsToCloud() {
}
}
auto i = _draftsSaveRequestIds.find(history);
if (i != _draftsSaveRequestIds.cend() && i.value() == requestId) {
_draftsSaveRequestIds.remove(history);
if (i != _draftsSaveRequestIds.cend() && i->second == requestId) {
_draftsSaveRequestIds.erase(history);
checkQuitPreventFinished();
}
}).send();
i.value() = cloudDraft->saveRequestId;
i->second = cloudDraft->saveRequestId;
}
}
bool ApiWrap::isQuitPrevent() {
if (_draftsSaveRequestIds.isEmpty()) {
if (_draftsSaveRequestIds.empty()) {
return false;
}
LOG(("ApiWrap prevents quit, saving drafts..."));
@ -1966,7 +2023,7 @@ bool ApiWrap::isQuitPrevent() {
}
void ApiWrap::checkQuitPreventFinished() {
if (_draftsSaveRequestIds.isEmpty()) {
if (_draftsSaveRequestIds.empty()) {
if (App::quitting()) {
LOG(("ApiWrap doesn't prevent quit any more."));
}
@ -1974,41 +2031,43 @@ void ApiWrap::checkQuitPreventFinished() {
}
}
PeerData *ApiWrap::notifySettingReceived(
void ApiWrap::notifySettingReceived(
MTPInputNotifyPeer notifyPeer,
const MTPPeerNotifySettings &settings) {
PeerData *requestedPeer = nullptr;
switch (notifyPeer.type()) {
case mtpc_inputNotifyAll:
App::main()->applyNotifySetting(MTP_notifyAll(), settings);
break;
case mtpc_inputNotifyUsers:
App::main()->applyNotifySetting(MTP_notifyUsers(), settings);
_session->data().applyNotifySetting(MTP_notifyUsers(), settings);
break;
case mtpc_inputNotifyChats:
App::main()->applyNotifySetting(MTP_notifyChats(), settings);
_session->data().applyNotifySetting(MTP_notifyChats(), settings);
break;
case mtpc_inputNotifyPeer: {
auto &peer = notifyPeer.c_inputNotifyPeer().vpeer;
switch (peer.type()) {
case mtpc_inputPeerEmpty: App::main()->applyNotifySetting(
MTP_notifyPeer(MTP_peerUser(MTP_int(0))),
settings);
break;
case mtpc_inputPeerSelf: requestedPeer = App::self(); break;
case mtpc_inputPeerUser: requestedPeer = App::user(peerFromUser(peer.c_inputPeerUser().vuser_id)); break;
case mtpc_inputPeerChat: requestedPeer = App::chat(peerFromChat(peer.c_inputPeerChat().vchat_id)); break;
case mtpc_inputPeerChannel: requestedPeer = App::channel(peerFromChannel(peer.c_inputPeerChannel().vchannel_id)); break;
}
if (requestedPeer) {
App::main()->applyNotifySetting(
MTP_notifyPeer(peerToMTP(requestedPeer->id)),
const auto apply = [&](PeerId peerId) {
_session->data().applyNotifySetting(
MTP_notifyPeer(peerToMTP(peerId)),
settings);
};
switch (peer.type()) {
case mtpc_inputPeerEmpty:
apply(0);
break;
case mtpc_inputPeerSelf:
apply(_session->userPeerId());
break;
case mtpc_inputPeerUser:
apply(peerFromUser(peer.c_inputPeerUser().vuser_id));
break;
case mtpc_inputPeerChat:
apply(peerFromChat(peer.c_inputPeerChat().vchat_id));
break;
case mtpc_inputPeerChannel:
apply(peerFromChannel(peer.c_inputPeerChannel().vchannel_id));
break;
}
} break;
}
_session->notifications().checkDelayed();
return requestedPeer;
}
void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) {
@ -2325,11 +2384,10 @@ std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
if (sendRequest) {
const auto hash = (it != _stickersByEmoji.end())
? it->second.hash
: QString();
: int32(0);
request(MTPmessages_GetStickers(
MTP_flags(MTPmessages_GetStickers::Flag::f_exclude_featured),
MTP_string(emoji->text()),
MTP_string(hash)
MTP_int(hash)
)).done([=](const MTPmessages_Stickers &result) {
if (result.type() == mtpc_messages_stickersNotModified) {
return;
@ -2340,12 +2398,12 @@ std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
entry.list.clear();
entry.list.reserve(data.vstickers.v.size());
for (const auto &sticker : data.vstickers.v) {
const auto document = Auth().data().document(sticker);
const auto document = _session->data().document(sticker);
if (document->sticker()) {
entry.list.push_back(document);
}
}
entry.hash = qs(data.vhash);
entry.hash = data.vhash.v;
entry.received = getms(true);
_session->data().notifyStickersUpdated();
}).send();
@ -3490,7 +3548,8 @@ void ApiWrap::forwardMessages(
readServerHistory(history);
const auto channelPost = peer->isChannel() && !peer->isMegagroup();
const auto silentPost = channelPost && peer->notifySilentPosts();
const auto silentPost = channelPost
&& _session->data().notifySilentPosts(peer);
auto flags = MTPDmessage::Flags(0);
auto sendFlags = MTPmessages_ForwardMessages::Flags(0);
@ -3665,7 +3724,7 @@ void ApiWrap::sendSharedContact(
MTP_string(phone),
MTP_string(firstName),
MTP_string(lastName));
sendMedia(item, media, peer->notifySilentPosts());
sendMedia(item, media, _session->data().notifySilentPosts(peer));
if (const auto main = App::main()) {
_session->data().sendHistoryChangeNotifications();

View File

@ -137,13 +137,13 @@ public:
void joinChannel(not_null<ChannelData*> channel);
void leaveChannel(not_null<ChannelData*> channel);
void blockUser(UserData *user);
void unblockUser(UserData *user);
void blockUser(not_null<UserData*> user);
void unblockUser(not_null<UserData*> user);
void exportInviteLink(PeerData *peer);
void requestNotifySetting(PeerData *peer);
void saveDraftToCloudDelayed(History *history);
void exportInviteLink(not_null<PeerData*> peer);
void requestNotifySettings(const MTPInputNotifyPeer &peer);
void updateNotifySettingsDelayed(not_null<const PeerData*> peer);
void saveDraftToCloudDelayed(not_null<History*> history);
void savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules);
void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules);
@ -285,7 +285,7 @@ private:
struct StickersByEmoji {
std::vector<not_null<DocumentData*>> list;
QString hash;
int32 hash = 0;
TimeMs received = 0;
};
@ -338,7 +338,7 @@ private:
MsgRange range,
const MTPupdates_ChannelDifference &result);
PeerData *notifySettingReceived(
void notifySettingReceived(
MTPInputNotifyPeer peer,
const MTPPeerNotifySettings &settings);
@ -440,6 +440,8 @@ private:
void getProxyPromotionDelayed(TimeId now, TimeId next);
void proxyPromotionDone(const MTPhelp_ProxyData &proxy);
void sendNotifySettingsUpdates();
not_null<AuthSession*> _session;
MessageDataRequests _messageDataRequests;
@ -480,12 +482,10 @@ private:
QMap<uint64, QPair<uint64, mtpRequestId> > _stickerSetRequests;
QMap<ChannelData*, mtpRequestId> _channelAmInRequests;
QMap<UserData*, mtpRequestId> _blockRequests;
QMap<PeerData*, mtpRequestId> _exportInviteRequests;
QMap<PeerData*, mtpRequestId> _notifySettingRequests;
QMap<History*, mtpRequestId> _draftsSaveRequestIds;
std::map<not_null<UserData*>, mtpRequestId> _blockRequests;
std::map<not_null<PeerData*>, mtpRequestId> _exportInviteRequests;
std::map<PeerId, mtpRequestId> _notifySettingRequests;
std::map<not_null<History*>, mtpRequestId> _draftsSaveRequestIds;
base::Timer _draftsSaveTimer;
base::flat_set<mtpRequestId> _stickerSetDisenableRequests;
@ -575,5 +575,7 @@ private:
TimeId _proxyPromotionNextRequestTime = TimeId(0);
base::Timer _proxyPromotionTimer;
base::flat_set<not_null<const PeerData*>> _updateNotifySettingsPeers;
base::Timer _updateNotifySettingsTimer;
};

View File

@ -53,9 +53,6 @@ namespace {
using PeersData = QHash<PeerId, PeerData*>;
PeersData peersData;
using MutedPeers = QMap<not_null<PeerData*>, bool>;
MutedPeers mutedPeers;
using LocationsData = QHash<LocationCoords, LocationData*>;
LocationsData locationsData;
@ -1153,14 +1150,23 @@ namespace {
return i.value();
}
void enumerateUsers(base::lambda<void(UserData*)> action) {
for_const (auto peer, peersData) {
if (auto user = peer->asUser()) {
void enumerateUsers(base::lambda<void(not_null<UserData*>)> action) {
for_const (const auto peer, peersData) {
if (const auto user = peer->asUser()) {
action(user);
}
}
}
void enumerateChatsChannels(
base::lambda<void(not_null<PeerData*>)> action) {
for_const (const auto peer, peersData) {
if (!peer->isUser()) {
action(peer);
}
}
}
UserData *self() {
return ::self;
}
@ -1309,7 +1315,6 @@ namespace {
void historyClearItems() {
randomData.clear();
sentData.clear();
mutedPeers.clear();
cSetSavedPeers(SavedPeers());
cSetSavedPeersByTime(SavedPeersByTime());
cSetRecentInlineBots(RecentInlineBots());
@ -1748,38 +1753,6 @@ namespace {
return QPixmap::fromImage(std::move(image), Qt::ColorOnly);
}
void regMuted(not_null<PeerData*> peer, TimeMs changeIn) {
::mutedPeers.insert(peer, true);
App::main()->updateMutedIn(changeIn);
}
void unregMuted(not_null<PeerData*> peer) {
::mutedPeers.remove(peer);
}
void updateMuted() {
auto changeInMin = TimeMs(0);
for (auto i = ::mutedPeers.begin(); i != ::mutedPeers.end();) {
const auto history = App::historyLoaded(i.key()->id);
const auto muteFinishesIn = i.key()->notifyMuteFinishesIn();
if (muteFinishesIn > 0) {
if (history) {
history->changeMute(true);
}
if (!changeInMin || muteFinishesIn < changeInMin) {
changeInMin = muteFinishesIn;
}
++i;
} else {
if (history) {
history->changeMute(false);
}
i = ::mutedPeers.erase(i);
}
}
if (changeInMin) App::main()->updateMutedIn(changeInMin);
}
void rectWithCorners(Painter &p, QRect rect, const style::color &bg, RoundCorners index, RectParts corners) {
auto parts = RectPart::Top
| RectPart::NoTopBottom

View File

@ -135,7 +135,9 @@ namespace App {
inline ChannelData *channelLoaded(ChannelId channelId) {
return channel(channelId, PeerData::FullLoaded);
}
void enumerateUsers(base::lambda<void(UserData*)> action);
void enumerateUsers(base::lambda<void(not_null<UserData*>)> action);
void enumerateChatsChannels(
base::lambda<void(not_null<PeerData*>)> action);
UserData *self();
PeerData *peerByName(const QString &username);
@ -221,10 +223,6 @@ namespace App {
QImage readImage(const QString &file, QByteArray *format = nullptr, bool opaque = true, bool *animated = nullptr, QByteArray *content = 0);
QPixmap pixmapFromImageInPlace(QImage &&image);
void regMuted(not_null<PeerData*> peer, TimeMs changeIn);
void unregMuted(not_null<PeerData*> peer);
void updateMuted();
void complexOverlayRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);
void complexLocationRect(Painter &p, QRect rect, ImageRoundRadius radius, RectParts corners);

View File

@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/crash_reports.h"
#include "messenger.h"
#include "base/timer.h"
#include "base/qthelp_url.h"
#include "base/qthelp_regex.h"
#include "core/update_checker.h"
#include "core/crash_report_window.h"

View File

@ -372,6 +372,7 @@ void EditCaptionBox::save() {
item->history()->peer->input,
MTP_int(item->id),
MTP_string(sending.text),
MTPInputMedia(),
MTPnullMarkup,
sentEntities,
MTP_inputGeoPointEmpty()),

View File

@ -8,7 +8,8 @@ Copyright (C) 2017, Nicholas Guriev <guriev-ns@ya.ru>
#include "boxes/mute_settings_box.h"
#include "lang/lang_keys.h"
#include "mainwidget.h"
#include "auth_session.h"
#include "data/data_session.h"
#include "styles/style_boxes.h"
#include "ui/special_buttons.h"
#include "ui/widgets/checkbox.h"
@ -69,10 +70,8 @@ void MuteSettingsBox::prepare() {
addButton(langFactory(lng_box_ok), [this, group] {
auto muteForSeconds = group->value() * 3600;
App::main()->updateNotifySettings(
Auth().data().updateNotifySettings(
_peer,
Data::NotifySettings::MuteChange::Mute,
Data::NotifySettings::SilentPostsChange::Ignore,
muteForSeconds);
closeBox();
});

View File

@ -55,8 +55,8 @@ addChildParentFlags('MTPDchannelForbidden', 'MTPDchannel');
parentFlagsCheck = {};
countedTypeIdExceptions = {};
countedTypeIdExceptions[77] = countedTypeIdExceptions[78] = {}
countedTypeIdExceptions[77]['channel'] = countedTypeIdExceptions[78]['channel'] = True
countedTypeIdExceptions[77] = countedTypeIdExceptions[78] = countedTypeIdExceptions[79] = {}
countedTypeIdExceptions[77]['channel'] = countedTypeIdExceptions[78]['channel'] = countedTypeIdExceptions[79]['channel'] = True
countedTypeIdExceptions['ipPortSecret'] = True
countedTypeIdExceptions['accessPointRule'] = True
countedTypeIdExceptions['help_configSimple'] = True

View File

@ -275,7 +275,6 @@ enum {
WaitForChannelGetDifference = 1000, // 1s wait after show channel history before sending getChannelDifference
MemoryForImageCache = 64 * 1024 * 1024, // after 64mb of unpacked images we try to clear some memory
NotifySettingSaveTimeout = 1000, // wait 1 second before saving notify setting to server
IdleMsecs = 60 * 1000, // after 60secs without user input we think we are idle
SendViewsTimeout = 1000, // send views each second

View File

@ -12,11 +12,12 @@ namespace {
MTPinputPeerNotifySettings DefaultSettings() {
const auto flags = MTPDpeerNotifySettings::Flag::f_show_previews;
const auto muteValue = TimeId(0);
return MTP_inputPeerNotifySettings(
MTP_flags(mtpCastFlags(flags)),
MTP_int(muteValue),
MTP_string("default"));
MTP_flags(0),
MTPBool(),
MTPBool(),
MTPint(),
MTPstring());
}
} // namespace
@ -25,98 +26,121 @@ class NotifySettingsValue {
public:
NotifySettingsValue(const MTPDpeerNotifySettings &data);
using MuteChange = NotifySettings::MuteChange;
using SilentPostsChange = NotifySettings::SilentPostsChange;
bool change(const MTPDpeerNotifySettings &data);
bool change(
MuteChange mute,
SilentPostsChange silent,
int muteForSeconds);
TimeMs muteFinishesIn() const;
bool silentPosts() const;
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts);
base::optional<TimeId> muteUntil() const;
base::optional<bool> silentPosts() const;
MTPinputPeerNotifySettings serialize() const;
private:
bool change(
MTPDpeerNotifySettings::Flags flags,
TimeId mute,
QString sound);
base::optional<int> mute,
base::optional<QString> sound,
base::optional<bool> showPreviews,
base::optional<bool> silentPosts);
MTPDpeerNotifySettings::Flags _flags;
TimeId _mute;
QString _sound;
base::optional<TimeId> _mute;
base::optional<QString> _sound;
base::optional<bool> _silent;
base::optional<bool> _showPreviews;
};
NotifySettingsValue::NotifySettingsValue(const MTPDpeerNotifySettings &data)
: _flags(data.vflags.v)
, _mute(data.vmute_until.v)
, _sound(qs(data.vsound)) {
}
bool NotifySettingsValue::silentPosts() const {
return _flags & MTPDpeerNotifySettings::Flag::f_silent;
NotifySettingsValue::NotifySettingsValue(
const MTPDpeerNotifySettings &data) {
change(data);
}
bool NotifySettingsValue::change(const MTPDpeerNotifySettings &data) {
return change(data.vflags.v, data.vmute_until.v, qs(data.vsound));
return change(data.has_mute_until()
? base::make_optional(data.vmute_until.v)
: base::none, data.has_sound()
? base::make_optional(qs(data.vsound))
: base::none, data.has_show_previews()
? base::make_optional(mtpIsTrue(data.vshow_previews))
: base::none, data.has_silent()
? base::make_optional(mtpIsTrue(data.vsilent))
: base::none);
}
bool NotifySettingsValue::change(
MuteChange mute,
SilentPostsChange silent,
int muteForSeconds) {
const auto newFlags = [&] {
auto result = _flags;
if (silent == SilentPostsChange::Silent) {
result |= MTPDpeerNotifySettings::Flag::f_silent;
} else if (silent == SilentPostsChange::Notify) {
result &= ~MTPDpeerNotifySettings::Flag::f_silent;
}
return result;
}();
const auto newMute = (mute == MuteChange::Mute)
? (unixtime() + muteForSeconds)
: (mute == MuteChange::Ignore) ? _mute : 0;
const auto newSound = (newMute == 0 && _sound.isEmpty())
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts) {
const auto now = unixtime();
const auto notMuted = muteForSeconds
? !(*muteForSeconds)
: (!_mute || *_mute <= now);
return change(muteForSeconds
? base::make_optional((*muteForSeconds > 0)
? (now + *muteForSeconds)
: 0)
: base::none, (_sound && _sound->isEmpty() && notMuted)
? qsl("default")
: _sound;
return change(newFlags, newMute, newSound);
: _sound, _showPreviews, silentPosts
? base::make_optional(*silentPosts)
: base::none);
}
bool NotifySettingsValue::change(
MTPDpeerNotifySettings::Flags flags,
TimeId mute,
QString sound) {
if (_flags == flags && _mute == mute && _sound == sound) {
base::optional<int> mute,
base::optional<QString> sound,
base::optional<bool> showPreviews,
base::optional<bool> silentPosts) {
if (_mute == mute
&& _sound == sound
&& _showPreviews == showPreviews
&& _silent == silentPosts) {
return false;
}
_flags = flags;
_mute = mute;
_sound = sound;
_showPreviews = showPreviews;
_silent = silentPosts;
return true;
}
TimeMs NotifySettingsValue::muteFinishesIn() const {
auto now = unixtime();
if (_mute > now) {
return (_mute - now + 1) * 1000LL;
}
return 0;
base::optional<TimeId> NotifySettingsValue::muteUntil() const {
return _mute;
}
base::optional<bool> NotifySettingsValue::silentPosts() const {
return _silent;
}
MTPinputPeerNotifySettings NotifySettingsValue::serialize() const {
using Flag = MTPDinputPeerNotifySettings::Flag;
const auto flag = [](auto &&optional, Flag flag) {
return optional.has_value() ? flag : Flag(0);
};
return MTP_inputPeerNotifySettings(
MTP_flags(mtpCastFlags(_flags)),
MTP_int(_mute),
MTP_string(_sound));
MTP_flags(flag(_mute, Flag::f_mute_until)
| flag(_sound, Flag::f_sound)
| flag(_silent, Flag::f_silent)
| flag(_showPreviews, Flag::f_show_previews)),
MTP_bool(_showPreviews ? *_showPreviews : true),
MTP_bool(_silent ? *_silent : false),
MTP_int(_mute ? *_mute : false),
MTP_string(_sound ? *_sound : QString()));
}
NotifySettings::NotifySettings() = default;
bool NotifySettings::change(const MTPPeerNotifySettings &settings) {
Expects(settings.type() == mtpc_peerNotifySettings);
auto &data = settings.c_peerNotifySettings();
const auto empty = !data.vflags.v;
if (empty) {
if (!_known || _value) {
_known = true;
_value = nullptr;
return true;
}
return false;
}
if (_value) {
return _value->change(data);
}
@ -125,47 +149,42 @@ bool NotifySettings::change(const MTPPeerNotifySettings &settings) {
return true;
}
NotifySettings::NotifySettings() = default;
bool NotifySettings::change(
MuteChange mute,
SilentPostsChange silent,
int muteForSeconds) {
Expects(mute != MuteChange::Mute || muteForSeconds > 0);
if (mute == MuteChange::Ignore && silent == SilentPostsChange::Ignore) {
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts) {
if (!muteForSeconds && !silentPosts) {
return false;
} else if (_value) {
return _value->change(muteForSeconds, silentPosts);
}
if (_value) {
return _value->change(mute, silent, muteForSeconds);
}
const auto flags = MTPDpeerNotifySettings::Flag::f_show_previews
| ((silent == SilentPostsChange::Silent)
? MTPDpeerNotifySettings::Flag::f_silent
: MTPDpeerNotifySettings::Flag(0));
const auto muteUntil = (mute == MuteChange::Mute)
? (unixtime() + muteForSeconds)
using Flag = MTPDpeerNotifySettings::Flag;
const auto flags = (muteForSeconds ? Flag::f_mute_until : Flag(0))
| (silentPosts ? Flag::f_silent : Flag(0));
const auto muteUntil = muteForSeconds
? (unixtime() + *muteForSeconds)
: 0;
return change(MTP_peerNotifySettings(
MTP_flags(flags),
MTP_int(muteUntil),
MTP_string("default")));
MTPBool(),
silentPosts ? MTP_bool(*silentPosts) : MTPBool(),
muteForSeconds ? MTP_int(unixtime() + *muteForSeconds) : MTPint(),
MTPstring()));
}
TimeMs NotifySettings::muteFinishesIn() const {
base::optional<TimeId> NotifySettings::muteUntil() const {
return _value
? _value->muteFinishesIn()
: 0LL;
? _value->muteUntil()
: base::none;
}
bool NotifySettings::settingsUnknown() const {
return !_known;
}
bool NotifySettings::silentPosts() const {
base::optional<bool> NotifySettings::silentPosts() const {
return _value
? _value->silentPosts()
: false;
: base::none;
}
MTPinputPeerNotifySettings NotifySettings::serialize() const {

View File

@ -15,25 +15,16 @@ class NotifySettings {
public:
NotifySettings();
enum class MuteChange {
Ignore,
Mute,
Unmute,
};
enum class SilentPostsChange {
Ignore,
Silent,
Notify,
};
static constexpr auto kDefaultMutePeriod = 86400 * 365;
bool change(const MTPPeerNotifySettings &settings);
bool change(
MuteChange mute,
SilentPostsChange silent,
int muteForSeconds);
TimeMs muteFinishesIn() const;
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts);
bool settingsUnknown() const;
bool silentPosts() const;
base::optional<TimeId> muteUntil() const;
base::optional<bool> silentPosts() const;
MTPinputPeerNotifySettings serialize() const;
~NotifySettings();

View File

@ -68,30 +68,26 @@ public:
bool isVerified() const;
bool isMegagroup() const;
TimeMs notifyMuteFinishesIn() const {
return _notify.muteFinishesIn();
base::optional<TimeId> notifyMuteUntil() const {
return _notify.muteUntil();
}
bool notifyChange(const MTPPeerNotifySettings &settings) {
return _notify.change(settings);
}
bool notifyChange(
Data::NotifySettings::MuteChange mute,
Data::NotifySettings::SilentPostsChange silent,
int muteForSeconds) {
return _notify.change(mute, silent, muteForSeconds);
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts) {
return _notify.change(muteForSeconds, silentPosts);
}
bool notifySettingsUnknown() const {
return _notify.settingsUnknown();
}
bool notifySilentPosts() const {
base::optional<bool> notifySilentPosts() const {
return _notify.silentPosts();
}
MTPinputPeerNotifySettings notifySerialize() const {
return _notify.serialize();
}
bool isMuted() const {
return (notifyMuteFinishesIn() > 0);
}
bool canWrite() const;
UserData *asUser();

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "observer_peer.h"
#include "auth_session.h"
#include "apiwrap.h"
#include "window/notifications_manager.h"
#include "history/history.h"
#include "history/history_item_components.h"
#include "history/history_media.h"
@ -26,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data {
namespace {
constexpr auto kMaxNotifyCheckDelay = 24 * 3600 * TimeMs(1000);
using ViewElement = HistoryView::Element;
// s: box 100x100
@ -59,7 +62,8 @@ void UpdateImage(ImagePtr &old, ImagePtr now) {
Session::Session(not_null<AuthSession*> session)
: _session(session)
, _groups(this) {
, _groups(this)
, _unmuteByFinishedTimer([=] { unmuteByFinished(); }) {
setupContactViewsViewer();
setupChannelLeavingViewer();
}
@ -545,6 +549,77 @@ void Session::setIsPinned(const Dialogs::Key &key, bool pinned) {
}
}
NotifySettings &Session::defaultNotifySettings(
not_null<const PeerData*> peer) {
return peer->isUser()
? _defaultUserNotifySettings
: _defaultChatNotifySettings;
}
const NotifySettings &Session::defaultNotifySettings(
not_null<const PeerData*> peer) const {
return peer->isUser()
? _defaultUserNotifySettings
: _defaultChatNotifySettings;
}
void Session::updateNotifySettingsLocal(not_null<PeerData*> peer) {
const auto history = App::historyLoaded(peer->id);
auto changesIn = TimeMs(0);
const auto muted = notifyIsMuted(peer, &changesIn);
if (history && history->changeMute(muted)) {
// Notification already sent.
} else {
Notify::peerUpdatedDelayed(
peer,
Notify::PeerUpdate::Flag::NotificationsEnabled);
}
if (muted) {
_mutedPeers.emplace(peer);
unmuteByFinishedDelayed(changesIn);
if (history) {
_session->notifications().clearFromHistory(history);
}
} else {
_mutedPeers.erase(peer);
}
}
void Session::unmuteByFinishedDelayed(TimeMs delay) {
accumulate_max(delay, kMaxNotifyCheckDelay);
if (!_unmuteByFinishedTimer.isActive()
|| _unmuteByFinishedTimer.remainingTime() > delay) {
_unmuteByFinishedTimer.callOnce(delay);
}
}
void Session::unmuteByFinished() {
auto changesInMin = TimeMs(0);
for (auto i = begin(_mutedPeers); i != end(_mutedPeers);) {
const auto history = App::historyLoaded((*i)->id);
auto changesIn = TimeMs(0);
const auto muted = notifyIsMuted(*i, &changesIn);
if (muted) {
if (history) {
history->changeMute(true);
}
if (!changesInMin || changesInMin > changesIn) {
changesInMin = changesIn;
}
++i;
} else {
if (history) {
history->changeMute(false);
}
i = _mutedPeers.erase(i);
}
}
if (changesInMin) {
unmuteByFinishedDelayed(changesInMin);
}
}
not_null<PhotoData*> Session::photo(PhotoId id) {
auto i = _photos.find(id);
if (i == _photos.end()) {
@ -1579,6 +1654,148 @@ rpl::producer<FeedId> Session::defaultFeedIdValue() const {
return _defaultFeedId.value();
}
void Session::requestNotifySettings(not_null<PeerData*> peer) {
if (peer->notifySettingsUnknown()) {
_session->api().requestNotifySettings(
MTP_inputNotifyPeer(peer->input));
}
if (defaultNotifySettings(peer).settingsUnknown()) {
_session->api().requestNotifySettings(peer->isUser()
? MTP_inputNotifyUsers()
: MTP_inputNotifyChats());
}
}
void Session::applyNotifySetting(
const MTPNotifyPeer &notifyPeer,
const MTPPeerNotifySettings &settings) {
switch (notifyPeer.type()) {
case mtpc_notifyUsers: {
if (_defaultUserNotifySettings.change(settings)) {
_defaultUserNotifyUpdates.fire({});
App::enumerateUsers([&](not_null<UserData*> user) {
if (!user->notifySettingsUnknown()
&& ((!user->notifyMuteUntil()
&& _defaultUserNotifySettings.muteUntil())
|| (!user->notifySilentPosts()
&& _defaultUserNotifySettings.silentPosts()))) {
updateNotifySettingsLocal(user);
}
});
}
} break;
case mtpc_notifyChats: {
if (_defaultChatNotifySettings.change(settings)) {
_defaultChatNotifyUpdates.fire({});
App::enumerateChatsChannels([&](not_null<PeerData*> peer) {
if (!peer->notifySettingsUnknown()
&& ((!peer->notifyMuteUntil()
&& _defaultUserNotifySettings.muteUntil())
|| (!peer->notifySilentPosts()
&& _defaultUserNotifySettings.silentPosts()))) {
if (!peer->notifyMuteUntil()) {
int a = 0;
}
updateNotifySettingsLocal(peer);
}
});
}
} break;
case mtpc_notifyPeer: {
const auto &data = notifyPeer.c_notifyPeer();
if (const auto peer = App::peerLoaded(peerFromMTP(data.vpeer))) {
if (peer->notifyChange(settings)) {
updateNotifySettingsLocal(peer);
}
}
} break;
}
}
void Session::updateNotifySettings(
not_null<PeerData*> peer,
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts) {
if (peer->notifyChange(muteForSeconds, silentPosts)) {
updateNotifySettingsLocal(peer);
_session->api().updateNotifySettingsDelayed(peer);
}
}
bool Session::notifyIsMuted(
not_null<const PeerData*> peer,
TimeMs *changesIn) const {
const auto resultFromUntil = [&](TimeId until) {
const auto now = unixtime();
const auto result = (until > now) ? (until - now) : 0;
if (changesIn) {
*changesIn = (result > 0)
? std::min(result * TimeMs(1000), kMaxNotifyCheckDelay)
: kMaxNotifyCheckDelay;
}
return (result > 0);
};
if (const auto until = peer->notifyMuteUntil()) {
return resultFromUntil(*until);
}
const auto &settings = defaultNotifySettings(peer);
if (const auto until = settings.muteUntil()) {
return resultFromUntil(*until);
}
return false;
}
bool Session::notifySilentPosts(not_null<const PeerData*> peer) const {
if (const auto silent = peer->notifySilentPosts()) {
return *silent;
}
const auto &settings = defaultNotifySettings(peer);
if (const auto silent = settings.silentPosts()) {
return *silent;
}
return false;
}
bool Session::notifyMuteUnknown(not_null<const PeerData*> peer) const {
if (peer->notifySettingsUnknown()) {
return true;
} else if (const auto nonDefault = peer->notifyMuteUntil()) {
return false;
}
return defaultNotifySettings(peer).settingsUnknown();
}
bool Session::notifySilentPostsUnknown(
not_null<const PeerData*> peer) const {
if (peer->notifySettingsUnknown()) {
return true;
} else if (const auto nonDefault = peer->notifySilentPosts()) {
return false;
}
return defaultNotifySettings(peer).settingsUnknown();
}
bool Session::notifySettingsUnknown(not_null<const PeerData*> peer) const {
return notifyMuteUnknown(peer) || notifySilentPostsUnknown(peer);
}
rpl::producer<> Session::defaultUserNotifyUpdates() const {
return _defaultUserNotifyUpdates.events();
}
rpl::producer<> Session::defaultChatNotifyUpdates() const {
return _defaultChatNotifyUpdates.events();
}
rpl::producer<> Session::defaultNotifyUpdates(
not_null<const PeerData*> peer) const {
return peer->isUser()
? defaultUserNotifyUpdates()
: defaultChatNotifyUpdates();
}
void Session::forgetMedia() {
for (const auto &[id, photo] : _photos) {
photo->forget();

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers.h"
#include "dialogs/dialogs_key.h"
#include "data/data_groups.h"
#include "base/timer.h"
class HistoryItem;
@ -358,6 +359,26 @@ public:
FeedId defaultFeedId() const;
rpl::producer<FeedId> defaultFeedIdValue() const;
void requestNotifySettings(not_null<PeerData*> peer);
void applyNotifySetting(
const MTPNotifyPeer &notifyPeer,
const MTPPeerNotifySettings &settings);
void updateNotifySettings(
not_null<PeerData*> peer,
base::optional<int> muteForSeconds,
base::optional<bool> silentPosts = base::none);
bool notifyIsMuted(
not_null<const PeerData*> peer,
TimeMs *changesIn = nullptr) const;
bool notifySilentPosts(not_null<const PeerData*> peer) const;
bool notifyMuteUnknown(not_null<const PeerData*> peer) const;
bool notifySilentPostsUnknown(not_null<const PeerData*> peer) const;
bool notifySettingsUnknown(not_null<const PeerData*> peer) const;
rpl::producer<> defaultUserNotifyUpdates() const;
rpl::producer<> defaultChatNotifyUpdates() const;
rpl::producer<> defaultNotifyUpdates(
not_null<const PeerData*> peer) const;
void forgetMedia();
void setMimeForwardIds(MessageIdsList &&list);
@ -453,6 +474,14 @@ private:
void clearPinnedDialogs();
void setIsPinned(const Dialogs::Key &key, bool pinned);
NotifySettings &defaultNotifySettings(not_null<const PeerData*> peer);
const NotifySettings &defaultNotifySettings(
not_null<const PeerData*> peer) const;
void unmuteByFinished();
void unmuteByFinishedDelayed(TimeMs delay);
void updateNotifySettingsLocal(not_null<PeerData*> peer);
void sendNotifySettingsUpdates();
template <typename Method>
void enumerateItemViews(
not_null<const HistoryItem*> item,
@ -548,6 +577,13 @@ private:
PeerData *_proxyPromoted = nullptr;
NotifySettings _defaultUserNotifySettings;
NotifySettings _defaultChatNotifySettings;
rpl::event_stream<> _defaultUserNotifyUpdates;
rpl::event_stream<> _defaultChatNotifyUpdates;
std::unordered_set<not_null<const PeerData*>> _mutedPeers;
base::Timer _unmuteByFinishedTimer;
MessageIdsList _mimeForwardIds;
rpl::lifetime _lifetime;

View File

@ -224,7 +224,7 @@ History::History(const PeerId &peerId)
: Entry(this)
, peer(App::peer(peerId))
, cloudDraftTextCache(st::dialogsTextWidthMin)
, _mute(peer->isMuted())
, _mute(Auth().data().notifyIsMuted(peer))
, _sendActionText(st::dialogsTextWidthMin) {
if (const auto user = peer->asUser()) {
if (user->botInfo) {
@ -2194,10 +2194,9 @@ void History::applyDialog(const MTPDdialog &data) {
}
}
}
App::main()->applyNotifySetting(
Auth().data().applyNotifySetting(
MTP_notifyPeer(data.vpeer),
data.vnotify_settings,
this);
data.vnotify_settings);
if (data.has_draft() && data.vdraft.type() == mtpc_draftMessage) {
Data::applyPeerCloudDraft(peer->id, data.vdraft.c_draftMessage());
}

View File

@ -610,7 +610,7 @@ bool HistoryMessage::allowsEdit(TimeId now) const {
return true;
}
if (out()) {
return !isPost() || channel->canPublish();
return isPost() ? channel->canPublish() : channel->canWrite();
}
}
return out();

View File

@ -665,7 +665,7 @@ HistoryWidget::HistoryWidget(
}
}
if (update.flags & UpdateFlag::NotificationsEnabled) {
updateNotifySettings();
updateNotifyControls();
}
if (update.flags & UpdateFlag::RestrictionReasonChanged) {
auto restriction = _peer->restrictionReason();
@ -699,6 +699,12 @@ HistoryWidget::HistoryWidget(
}
}
}));
rpl::merge(
Auth().data().defaultUserNotifyUpdates(),
Auth().data().defaultChatNotifyUpdates()
) | rpl::start_with_next([=] {
updateNotifyControls();
}, lifetime());
subscribe(Auth().data().queryItemVisibility(), [this](const Data::Session::ItemVisibilityQuery &query) {
if (_a_show.animating()
|| _history != query.item->history()
@ -1848,10 +1854,8 @@ void HistoryWidget::showHistory(const PeerId &peerId, MsgId showAtMsgId, bool re
updateTopBarSelection();
if (_channel) {
updateNotifySettings();
if (_peer->notifySettingsUnknown()) {
Auth().api().requestNotifySetting(_peer);
}
updateNotifyControls();
Auth().data().requestNotifySettings(_peer);
refreshSilentToggle();
}
@ -1955,15 +1959,15 @@ void HistoryWidget::updateFieldSubmitSettings() {
_field->setSubmitSettings(settings);
}
void HistoryWidget::updateNotifySettings() {
void HistoryWidget::updateNotifyControls() {
if (!_peer || !_peer->isChannel()) return;
_muteUnmute->setText(lang(_history->mute()
? lng_channel_unmute
: lng_channel_mute).toUpper());
if (!_peer->notifySettingsUnknown()) {
if (!Auth().data().notifySilentPostsUnknown(_peer)) {
if (_silent) {
_silent->setChecked(_peer->notifySilentPosts());
_silent->setChecked(Auth().data().notifySilentPosts(_peer));
} else if (hasSilentToggle()) {
refreshSilentToggle();
updateControlsGeometry();
@ -2925,6 +2929,7 @@ void HistoryWidget::saveEditMsg() {
_history->peer->input,
MTP_int(_editMsgId),
MTP_string(sending.text),
MTPInputMedia(),
MTPnullMarkup,
sentEntities,
MTP_inputGeoPointEmpty()),
@ -3078,10 +3083,10 @@ void HistoryWidget::onJoinChannel() {
}
void HistoryWidget::onMuteUnmute() {
const auto muteState = _history->mute()
? Data::NotifySettings::MuteChange::Unmute
: Data::NotifySettings::MuteChange::Mute;
App::main()->updateNotifySettings(_peer, muteState);
const auto muteForSeconds = _history->mute()
? 0
: Data::NotifySettings::kDefaultMutePeriod;
Auth().data().updateNotifySettings(_peer, muteForSeconds);
}
void HistoryWidget::onBroadcastSilentChange() {
@ -3633,7 +3638,7 @@ bool HistoryWidget::hasSilentToggle() const {
&& _peer->isChannel()
&& !_peer->isMegagroup()
&& _peer->canWrite()
&& !_peer->notifySettingsUnknown();
&& !Auth().data().notifySilentPostsUnknown(_peer);
}
void HistoryWidget::inlineBotResolveDone(
@ -4094,7 +4099,7 @@ void HistoryWidget::updateFieldPlaceholder() {
const auto peer = _history ? _history->peer.get() : nullptr;
_field->setPlaceholder(langFactory(
(peer && peer->isChannel() && !peer->isMegagroup())
? (peer->notifySilentPosts()
? (Auth().data().notifySilentPosts(peer)
? lng_broadcast_silent_ph
: lng_broadcast_ph)
: lng_message_ph));
@ -4412,7 +4417,9 @@ void HistoryWidget::sendFileConfirmed(
flags |= MTPDmessage::Flag::f_grouped_id;
}
auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
auto messagePostAuthor = channelPost
? App::peerName(Auth().user())
: QString();
if (file->type == SendMediaType::Photo) {
auto photoFlags = MTPDmessageMediaPhoto::Flag::f_photo | 0;
auto photo = MTP_messageMediaPhoto(
@ -5385,7 +5392,7 @@ void HistoryWidget::onInlineResultSend(
sendFlags |= MTPmessages_SendInlineBotResult::Flag::f_reply_to_msg_id;
}
bool channelPost = _peer->isChannel() && !_peer->isMegagroup();
bool silentPost = channelPost && _peer->notifySilentPosts();
bool silentPost = channelPost && Auth().data().notifySilentPosts(_peer);
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -5403,7 +5410,9 @@ void HistoryWidget::onInlineResultSend(
}
auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
auto messagePostAuthor = channelPost
? App::peerName(Auth().user())
: QString();
MTPint messageDate = MTP_int(unixtime());
UserId messageViaBotId = bot ? peerToUser(bot->id) : 0;
MsgId messageId = newId.msg;
@ -5594,7 +5603,7 @@ bool HistoryWidget::sendExistingDocument(
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
bool channelPost = _peer->isChannel() && !_peer->isMegagroup();
bool silentPost = channelPost && _peer->notifySilentPosts();
bool silentPost = channelPost && Auth().data().notifySilentPosts(_peer);
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -5608,7 +5617,8 @@ bool HistoryWidget::sendExistingDocument(
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
auto messagePostAuthor = channelPost
? App::peerName(Auth().user()) : QString();
TextUtilities::Trim(caption);
auto sentEntities = TextUtilities::EntitiesToMTP(
@ -5690,7 +5700,7 @@ void HistoryWidget::sendExistingPhoto(
sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to_msg_id;
}
bool channelPost = _peer->isChannel() && !_peer->isMegagroup();
bool silentPost = channelPost && _peer->notifySilentPosts();
bool silentPost = channelPost && Auth().data().notifySilentPosts(_peer);
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -5704,7 +5714,9 @@ void HistoryWidget::sendExistingPhoto(
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
}
auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
auto messagePostAuthor = channelPost
? App::peerName(Auth().user())
: QString();
TextUtilities::Trim(caption);
auto sentEntities = TextUtilities::EntitiesToMTP(

View File

@ -318,7 +318,7 @@ public:
void setInnerFocus();
void updateNotifySettings();
void updateNotifyControls();
void saveGif(DocumentData *doc);

View File

@ -212,18 +212,17 @@ base::unique_qptr<Ui::PopupMenu> ChannelsController::rowContextMenu(
void NotificationsController::Start(not_null<Data::Feed*> feed) {
const auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_settings_save), [=] {
const auto main = App::main();
const auto count = box->peerListFullRowsCount();
for (auto i = 0; i != count; ++i) {
const auto row = box->peerListRowAt(i);
const auto peer = row->peer();
const auto muted = !row->checked();
if (muted != peer->isMuted()) {
main->updateNotifySettings(
if (muted != Auth().data().notifyIsMuted(peer)) {
Auth().data().updateNotifySettings(
peer,
(muted
? Data::NotifySettings::MuteChange::Mute
: Data::NotifySettings::MuteChange::Unmute));
? Data::NotifySettings::kDefaultMutePeriod
: 0));
}
}
box->closeBox();
@ -320,7 +319,7 @@ void NotificationsController::applyFeedDialogs(
auto notMutedChannels = ranges::view::all(
channels
) | ranges::view::filter([](not_null<ChannelData*> channel) {
return !channel->isMuted();
return !Auth().data().notifyIsMuted(channel);
});
delegate()->peerListAddSelectedRows(notMutedChannels);
for (const auto channel : channels) {

View File

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_peer_menu.h"
#include "boxes/peer_list_box.h"
#include "auth_session.h"
#include "data/data_session.h"
#include "mainwidget.h"
#include "lang/lang_keys.h"
#include "styles/style_info.h"
@ -449,10 +450,10 @@ void WrapWidget::addProfileNotificationsButton() {
? st::infoLayerTopBarNotifications
: st::infoTopBarNotifications)));
notifications->addClickHandler([peer] {
const auto muteState = peer->isMuted()
? Data::NotifySettings::MuteChange::Unmute
: Data::NotifySettings::MuteChange::Mute;
App::main()->updateNotifySettings(peer, muteState);
const auto muteForSeconds = Auth().data().notifyIsMuted(peer)
? 0
: Data::NotifySettings::kDefaultMutePeriod;
Auth().data().updateNotifySettings(peer, muteForSeconds);
});
Profile::NotificationsEnabledValue(
peer

View File

@ -310,10 +310,10 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupMuteToggle() {
result->toggleOn(
NotificationsEnabledValue(peer)
)->addClickHandler([=] {
const auto muteState = peer->isMuted()
? Data::NotifySettings::MuteChange::Unmute
: Data::NotifySettings::MuteChange::Mute;
App::main()->updateNotifySettings(peer, muteState);
const auto muteForSeconds = Auth().data().notifyIsMuted(peer)
? 0
: Data::NotifySettings::kDefaultMutePeriod;
Auth().data().updateNotifySettings(peer, muteForSeconds);
});
object_ptr<FloatingIcon>(
result,

View File

@ -115,11 +115,14 @@ rpl::producer<QString> LinkValue(
rpl::producer<bool> NotificationsEnabledValue(
not_null<PeerData*> peer) {
return Notify::PeerUpdateValue(
return rpl::merge(
Notify::PeerUpdateValue(
peer,
Notify::PeerUpdate::Flag::NotificationsEnabled
) | rpl::map([] { return rpl::empty_value(); }),
Auth().data().defaultNotifyUpdates(peer)
) | rpl::map([peer] {
return !peer->isMuted();
return !Auth().data().notifyIsMuted(peer);
}) | rpl::distinct_until_changed();
}

View File

@ -106,22 +106,22 @@ void PhoneWidget::hidePhoneError() {
}
}
void PhoneWidget::showSignup() {
showPhoneError(langFactory(lng_bad_phone_noreg));
if (!_signup) {
auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink());
auto inner = object_ptr<Ui::FlatLabel>(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription);
_signup.create(this, std::move(inner));
_signup->entity()->setLink(1, std::make_shared<UrlClickHandler>(qsl("https://telegram.org"), false));
_signup->entity()->setLink(2, std::make_shared<LambdaClickHandler>([this] {
toSignUp();
}));
_signup->hide(anim::type::instant);
updateSignupGeometry();
}
_signup->show(anim::type::normal);
hideDescription();
}
//void PhoneWidget::showSignup() {
// showPhoneError(langFactory(lng_bad_phone_noreg));
// if (!_signup) {
// auto signupText = lng_phone_notreg(lt_link_start, textcmdStartLink(1), lt_link_end, textcmdStopLink(), lt_signup_start, textcmdStartLink(2), lt_signup_end, textcmdStopLink());
// auto inner = object_ptr<Ui::FlatLabel>(this, signupText, Ui::FlatLabel::InitType::Rich, st::introDescription);
// _signup.create(this, std::move(inner));
// _signup->entity()->setLink(1, std::make_shared<UrlClickHandler>(qsl("https://telegram.org"), false));
// _signup->entity()->setLink(2, std::make_shared<LambdaClickHandler>([this] {
// toSignUp();
// }));
// _signup->hide(anim::type::instant);
// updateSignupGeometry();
// }
// _signup->show(anim::type::normal);
// hideDescription();
//}
void PhoneWidget::countryChanged() {
if (!_changed) {
@ -149,7 +149,8 @@ void PhoneWidget::submit() {
_sentPhone = fullNumber();
Messenger::Instance().mtp()->setUserPhone(_sentPhone);
_sentRequest = MTP::send(MTPauth_CheckPhone(MTP_string(_sentPhone)), rpcDone(&PhoneWidget::phoneCheckDone), rpcFail(&PhoneWidget::phoneSubmitFail));
//_sentRequest = MTP::send(MTPauth_CheckPhone(MTP_string(_sentPhone)), rpcDone(&PhoneWidget::phoneCheckDone), rpcFail(&PhoneWidget::phoneSubmitFail));
_sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail));
}
void PhoneWidget::stopCheck() {
@ -168,22 +169,22 @@ void PhoneWidget::onCheckRequest() {
stopCheck();
}
}
void PhoneWidget::phoneCheckDone(const MTPauth_CheckedPhone &result) {
stopCheck();
auto &d = result.c_auth_checkedPhone();
if (mtpIsTrue(d.vphone_registered)) {
hidePhoneError();
_checkRequest->start(1000);
_sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail));
} else {
showSignup();
_sentRequest = 0;
}
}
//
//void PhoneWidget::phoneCheckDone(const MTPauth_CheckedPhone &result) {
// stopCheck();
//
// auto &d = result.c_auth_checkedPhone();
// if (mtpIsTrue(d.vphone_registered)) {
// hidePhoneError();
//
// _checkRequest->start(1000);
//
// _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail));
// } else {
// showSignup();
// _sentRequest = 0;
// }
//}
void PhoneWidget::phoneSubmitDone(const MTPauth_SentCode &result) {
stopCheck();
@ -209,13 +210,13 @@ void PhoneWidget::phoneSubmitDone(const MTPauth_SentCode &result) {
goNext(new Intro::CodeWidget(parentWidget(), getData()));
}
void PhoneWidget::toSignUp() {
hideError(); // Hide error, but leave the signup label visible.
_checkRequest->start(1000);
_sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail));
}
//void PhoneWidget::toSignUp() {
// hideError(); // Hide error, but leave the signup label visible.
//
// _checkRequest->start(1000);
//
// _sentRequest = MTP::send(MTPauth_SendCode(MTP_flags(0), MTP_string(_sentPhone), MTPBool(), MTP_int(ApiId), MTP_string(ApiHash)), rpcDone(&PhoneWidget::phoneSubmitDone), rpcFail(&PhoneWidget::phoneSubmitFail));
//}
bool PhoneWidget::phoneSubmitFail(const RPCError &error) {
if (MTP::isFloodError(error)) {

View File

@ -48,18 +48,18 @@ private:
void updateSignupGeometry();
void countryChanged();
void phoneCheckDone(const MTPauth_CheckedPhone &result);
//void phoneCheckDone(const MTPauth_CheckedPhone &result);
void phoneSubmitDone(const MTPauth_SentCode &result);
bool phoneSubmitFail(const RPCError &error);
void toSignUp();
//void toSignUp();
QString fullNumber() const;
void stopCheck();
void showPhoneError(base::lambda<QString()> textFactory);
void hidePhoneError();
void showSignup();
//void showSignup();
bool _changed = false;

View File

@ -228,7 +228,6 @@ MainWidget::MainWidget(
connect(&_byPtsTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeByPts()));
connect(&_byMinChannelTimer, SIGNAL(timeout()), this, SLOT(getDifference()));
connect(&_failDifferenceTimer, SIGNAL(timeout()), this, SLOT(onGetDifferenceTimeAfterFail()));
connect(&updateNotifySettingTimer, SIGNAL(timeout()), this, SLOT(onUpdateNotifySettings()));
subscribe(Media::Player::Updated(), [this](const AudioMsgId &audioId) {
if (audioId.type() != AudioMsgId::Type::Video) {
handleAudioUpdate(audioId);
@ -268,7 +267,6 @@ MainWidget::MainWidget(
QCoreApplication::instance()->installEventFilter(this);
connect(&_updateMutedTimer, SIGNAL(timeout()), this, SLOT(onUpdateMuted()));
connect(&_viewsIncrementTimer, SIGNAL(timeout()), this, SLOT(onViewsIncrement()));
using Update = Window::Theme::BackgroundUpdate;
@ -715,20 +713,9 @@ void MainWidget::finishForwarding(not_null<History*> history) {
dialogsToUp();
}
void MainWidget::updateMutedIn(TimeMs delay) {
accumulate_min(delay, 24 * 3600 * 1000LL);
if (!_updateMutedTimer.isActive()
|| _updateMutedTimer.remainingTime() > delay) {
_updateMutedTimer.start(delay);
}
}
void MainWidget::onUpdateMuted() {
App::updateMuted();
}
bool MainWidget::onSendPaths(const PeerId &peerId) {
Expects(peerId != 0);
auto peer = App::peer(peerId);
if (!peer->canWrite()) {
Ui::show(Box<InformBox>(lang(lng_forward_send_files_cant)));
@ -1296,7 +1283,8 @@ void MainWidget::sendMessage(const MessageToSend &message) {
flags |= MTPDmessage::Flag::f_media;
}
bool channelPost = peer->isChannel() && !peer->isMegagroup();
bool silentPost = channelPost && peer->notifySilentPosts();
bool silentPost = channelPost
&& Auth().data().notifySilentPosts(peer);
if (channelPost) {
flags |= MTPDmessage::Flag::f_views;
flags |= MTPDmessage::Flag::f_post;
@ -1319,7 +1307,9 @@ void MainWidget::sendMessage(const MessageToSend &message) {
history->clearCloudDraft();
}
auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
auto messagePostAuthor = channelPost
? App::peerName(Auth().user())
: QString();
lastMessage = history->addNewMessage(
MTP_message(
MTP_flags(flags),
@ -3307,22 +3297,6 @@ void MainWidget::searchInChat(Dialogs::Key chat) {
}
}
void MainWidget::onUpdateNotifySettings() {
if (this != App::main()) return;
while (!updateNotifySettingPeers.empty()) {
auto peer = *updateNotifySettingPeers.begin();
updateNotifySettingPeers.erase(updateNotifySettingPeers.begin());
MTP::send(
MTPaccount_UpdateNotifySettings(
MTP_inputNotifyPeer(peer->input),
peer->notifySerialize()),
RPCResponseHandler(),
0,
updateNotifySettingPeers.empty() ? 0 : 10);
}
}
void MainWidget::feedUpdateVector(
const MTPVector<MTPUpdate> &updates,
bool skipMessageIds) {
@ -3996,62 +3970,6 @@ void MainWidget::startWithSelf(const MTPUserFull &result) {
}
}
void MainWidget::applyNotifySetting(
const MTPNotifyPeer &notifyPeer,
const MTPPeerNotifySettings &settings,
History *history) {
if (notifyPeer.type() != mtpc_notifyPeer) {
// Ignore those for now, they were not ever used.
return;
}
const auto &data = notifyPeer.c_notifyPeer();
const auto peer = App::peerLoaded(peerFromMTP(data.vpeer));
if (!peer || !peer->notifyChange(settings)) {
return;
}
updateNotifySettingsLocal(peer, history);
}
void MainWidget::updateNotifySettings(
not_null<PeerData*> peer,
Data::NotifySettings::MuteChange mute,
Data::NotifySettings::SilentPostsChange silent,
int muteForSeconds) {
if (peer->notifyChange(mute, silent, muteForSeconds)) {
updateNotifySettingsLocal(peer);
updateNotifySettingPeers.insert(peer);
updateNotifySettingTimer.start(NotifySettingSaveTimeout);
}
}
void MainWidget::updateNotifySettingsLocal(
not_null<PeerData*> peer,
History *history) {
if (!history) {
history = App::historyLoaded(peer->id);
}
const auto muteFinishesIn = peer->notifyMuteFinishesIn();
const auto muted = (muteFinishesIn > 0);
if (history && history->changeMute(muted)) {
// Notification already sent.
} else {
Notify::peerUpdatedDelayed(
peer,
Notify::PeerUpdate::Flag::NotificationsEnabled);
}
if (muted) {
App::regMuted(peer, muteFinishesIn);
if (history) {
Auth().notifications().clearFromHistory(history);
}
} else {
App::unregMuted(peer);
}
}
void MainWidget::incrementSticker(DocumentData *sticker) {
if (!sticker || !sticker->sticker()) return;
if (sticker->sticker()->set.type() == mtpc_inputStickerSetEmpty) return;
@ -4940,7 +4858,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateNotifySettings: {
auto &d = update.c_updateNotifySettings();
applyNotifySetting(d.vpeer, d.vnotify_settings);
Auth().data().applyNotifySetting(d.vpeer, d.vnotify_settings);
} break;
case mtpc_updateDcOptions: {

View File

@ -93,17 +93,6 @@ public:
void stickersBox(const MTPInputStickerSet &set);
bool started();
void applyNotifySetting(
const MTPNotifyPeer &notifyPeer,
const MTPPeerNotifySettings &settings,
History *history = 0);
void updateNotifySettings(
not_null<PeerData*> peer,
Data::NotifySettings::MuteChange mute,
Data::NotifySettings::SilentPostsChange silent
= Data::NotifySettings::SilentPostsChange::Ignore,
int muteForSeconds = 86400 * 365);
void incrementSticker(DocumentData *sticker);
@ -275,8 +264,6 @@ public:
void cancelForwarding(not_null<History*> history);
void finishForwarding(not_null<History*> history);
void updateMutedIn(TimeMs delay);
// Does offerPeer or showPeerHistory.
void choosePeer(PeerId peerId, MsgId showAtMsgId);
void clearBotStartToken(PeerData *peer);
@ -355,14 +342,10 @@ public slots:
void updateOnline(bool gotOtherOffline = false);
void checkIdleFinish();
void onUpdateNotifySettings();
void onCacheBackground();
void onInviteImport();
void onUpdateMuted();
void onViewsIncrement();
protected:
@ -535,15 +518,9 @@ private:
void ensureFirstColumnResizeAreaCreated();
void ensureThirdColumnResizeAreaCreated();
void updateNotifySettingsLocal(
not_null<PeerData*> peer,
History *history = nullptr);
not_null<Window::Controller*> _controller;
bool _started = false;
SingleTimer _updateMutedTimer;
QString _inviteHash;
Animation _a_show;
@ -607,9 +584,6 @@ private:
TimeMs _lastSetOnline = 0;
bool _isIdle = false;
base::flat_set<not_null<PeerData*>> updateNotifySettingPeers;
SingleTimer updateNotifySettingTimer;
int32 _failDifferenceTimeout = 1; // growing timeout for getDifference calls, if it fails
typedef QMap<ChannelData*, int32> ChannelFailDifferenceTimeout;
ChannelFailDifferenceTimeout _channelFailDifferenceTimeout; // growing timeout for getChannelDifference calls, if it fails

View File

@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <memory>

View File

@ -918,8 +918,8 @@ QPoint FeedUserpicButton::countInnerPosition() const {
SilentToggle::SilentToggle(QWidget *parent, not_null<ChannelData*> channel)
: IconButton(parent, st::historySilentToggle)
, _channel(channel)
, _checked(_channel->notifySilentPosts()) {
Expects(!_channel->notifySettingsUnknown());
, _checked(Auth().data().notifySilentPosts(_channel)) {
Expects(!Auth().data().notifySilentPostsUnknown(_channel));
if (_checked) {
refreshIconOverrides();
@ -962,13 +962,10 @@ void SilentToggle::mouseReleaseEvent(QMouseEvent *e) {
setChecked(!_checked);
IconButton::mouseReleaseEvent(e);
Ui::Tooltip::Show(0, this);
const auto silentState = _checked
? Data::NotifySettings::SilentPostsChange::Silent
: Data::NotifySettings::SilentPostsChange::Notify;
App::main()->updateNotifySettings(
Auth().data().updateNotifySettings(
_channel,
Data::NotifySettings::MuteChange::Ignore,
silentState);
base::none,
_checked);
}
QString SilentToggle::tooltipText() const {

View File

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_components.h"
#include "history/feed/history_feed_section.h"
#include "lang/lang_keys.h"
#include "data/data_session.h"
#include "window/window_controller.h"
#include "mainwindow.h"
#include "mainwidget.h"
@ -59,7 +60,7 @@ void System::createManager() {
void System::schedule(History *history, HistoryItem *item) {
if (App::quitting() || !history->currentNotification() || !AuthSession::Exists()) return;
auto notifyByFrom = (!history->peer->isUser() && item->mentionsMe())
const auto notifyBy = (!history->peer->isUser() && item->mentionsMe())
? item->from().get()
: nullptr;
@ -68,35 +69,31 @@ void System::schedule(History *history, HistoryItem *item) {
return;
}
auto haveSetting = !history->peer->notifySettingsUnknown();
if (haveSetting) {
if (history->peer->isMuted()) {
if (notifyByFrom) {
haveSetting = !item->from()->notifySettingsUnknown();
if (haveSetting) {
if (notifyByFrom->isMuted()) {
history->popNotification(item);
return;
}
} else {
Auth().api().requestNotifySetting(notifyByFrom);
Auth().data().requestNotifySettings(history->peer);
if (notifyBy) {
Auth().data().requestNotifySettings(notifyBy);
}
auto haveSetting = !Auth().data().notifyMuteUnknown(history->peer);
if (haveSetting && Auth().data().notifyIsMuted(history->peer)) {
if (notifyBy) {
haveSetting = !Auth().data().notifyMuteUnknown(notifyBy);
if (haveSetting) {
if (Auth().data().notifyIsMuted(notifyBy)) {
history->popNotification(item);
return;
}
} else {
history->popNotification(item);
return;
}
} else {
history->popNotification(item);
return;
}
} else {
if (notifyByFrom && notifyByFrom->notifySettingsUnknown()) {
Auth().api().requestNotifySetting(notifyByFrom);
}
Auth().api().requestNotifySetting(history->peer);
}
if (!item->notificationReady()) {
haveSetting = false;
}
int delay = item->Has<HistoryMessageForwarded>() ? 500 : 100, t = unixtime();
auto delay = item->Has<HistoryMessageForwarded>() ? 500 : 100;
auto t = unixtime();
auto ms = getms(true);
bool isOnline = App::main()->lastWasOnline(), otherNotOld = ((cOtherOnline() * 1000LL) + Global::OnlineCloudTimeout() > t * 1000LL);
bool otherLaterThanMe = (cOtherOnline() * 1000LL + (ms - App::main()->lastSetOnline()) > t * 1000LL);
@ -107,7 +104,7 @@ void System::schedule(History *history, HistoryItem *item) {
}
auto when = ms + delay;
_whenAlerts[history].insert(when, notifyByFrom);
_whenAlerts[history].insert(when, notifyBy);
if (Global::DesktopNotify() && !Platform::Notifications::SkipToast()) {
auto &whenMap = _whenMaps[history];
if (whenMap.constFind(item->id) == whenMap.cend()) {
@ -117,7 +114,7 @@ void System::schedule(History *history, HistoryItem *item) {
auto &addTo = haveSetting ? _waiters : _settingWaiters;
auto it = addTo.constFind(history);
if (it == addTo.cend() || it->when > when) {
addTo.insert(history, Waiter(item->id, when, notifyByFrom));
addTo.insert(history, Waiter(item->id, when, notifyBy));
}
}
if (haveSetting) {
@ -171,12 +168,12 @@ void System::checkDelayed() {
const auto peer = history->peer;
auto loaded = false;
auto muted = false;
if (!peer->notifySettingsUnknown()) {
if (!peer->isMuted()) {
if (!Auth().data().notifyMuteUnknown(peer)) {
if (!Auth().data().notifyIsMuted(peer)) {
loaded = true;
} else if (const auto from = i.value().notifyByFrom) {
if (!from->notifySettingsUnknown()) {
if (!from->isMuted()) {
} else if (const auto from = i.value().notifyBy) {
if (!Auth().data().notifyMuteUnknown(from)) {
if (!Auth().data().notifyIsMuted(from)) {
loaded = true;
} else {
loaded = muted = true;
@ -220,11 +217,14 @@ void System::showNext() {
for (auto i = _whenAlerts.begin(); i != _whenAlerts.end();) {
while (!i.value().isEmpty() && i.value().begin().key() <= ms) {
const auto peer = i.key()->peer;
const auto peerUnknown = peer->notifySettingsUnknown();
const auto peerAlert = peerUnknown ? false : !peer->isMuted();
const auto peerUnknown = Auth().data().notifyMuteUnknown(peer);
const auto peerAlert = !peerUnknown
&& !Auth().data().notifyIsMuted(peer);
const auto from = i.value().begin().value();
const auto fromUnknown = (!from || from->notifySettingsUnknown());
const auto fromAlert = fromUnknown ? false : !from->isMuted();
const auto fromUnknown = (!from
|| Auth().data().notifyMuteUnknown(from));
const auto fromAlert = !fromUnknown
&& !Auth().data().notifyIsMuted(from);
if (peerAlert || fromAlert) {
alert = true;
}

View File

@ -83,14 +83,14 @@ private:
QMap<History*, QMap<MsgId, TimeMs>> _whenMaps;
struct Waiter {
Waiter(MsgId msg, TimeMs when, PeerData *notifyByFrom)
: msg(msg)
, when(when)
, notifyByFrom(notifyByFrom) {
Waiter(MsgId msg, TimeMs when, PeerData *notifyBy)
: msg(msg)
, when(when)
, notifyBy(notifyBy) {
}
MsgId msg;
TimeMs when;
PeerData *notifyByFrom;
PeerData *notifyBy;
};
using Waiters = QMap<History*, Waiter>;
Waiters _waiters;

View File

@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/info_memento.h"
#include "info/info_controller.h"
#include "info/feed/info_feed_channels_controllers.h"
#include "info/profile/info_profile_values.h"
#include "data/data_session.h"
#include "data/data_feed.h"
#include "dialogs/dialogs_key.h"
@ -634,32 +635,24 @@ void PeerMenuAddChannelMembers(not_null<ChannelData*> channel) {
void PeerMenuAddMuteAction(
not_null<PeerData*> peer,
const PeerMenuCallback &addAction) {
if (peer->notifySettingsUnknown()) {
Auth().api().requestNotifySetting(peer);
}
auto muteText = [](bool isMuted) {
Auth().data().requestNotifySettings(peer);
const auto muteText = [](bool isMuted) {
return lang(isMuted
? lng_enable_notifications_from_tray
: lng_disable_notifications_from_tray);
};
auto muteAction = addAction(muteText(peer->isMuted()), [=] {
if (!peer->isMuted()) {
const auto muteAction = addAction(QString("-"), [=] {
if (!Auth().data().notifyIsMuted(peer)) {
Ui::show(Box<MuteSettingsBox>(peer));
} else {
App::main()->updateNotifySettings(
peer,
Data::NotifySettings::MuteChange::Unmute);
Auth().data().updateNotifySettings(peer, 0);
}
});
auto lifetime = Notify::PeerUpdateViewer(
peer,
Notify::PeerUpdate::Flag::NotificationsEnabled
) | rpl::map([=] {
return peer->isMuted();
}) | rpl::distinct_until_changed(
) | rpl::start_with_next([=](bool muted) {
muteAction->setText(muteText(muted));
auto lifetime = Info::Profile::NotificationsEnabledValue(
peer
) | rpl::start_with_next([=](bool enabled) {
muteAction->setText(muteText(!enabled));
});
Ui::AttachAsChild(muteAction, std::move(lifetime));