diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 42676c7dc..d225d9e38 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3273,6 +3273,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_replies_discussion_started" = "Discussion started"; "lng_replies_no_comments" = "No comments here yet..."; +"lng_verification_codes" = "Verification Codes"; + "lng_archived_name" = "Archived chats"; "lng_archived_add" = "Archive"; "lng_archived_remove" = "Unarchive"; diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 6352c5b51..c9a9055e1 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -356,11 +356,12 @@ void PrivacyExceptionsBoxController::rowClicked(not_null row) { auto PrivacyExceptionsBoxController::createRow(not_null history) -> std::unique_ptr { - if (history->peer->isSelf() || history->peer->isRepliesChat()) { + const auto peer = history->peer; + if (peer->isSelf() || peer->isRepliesChat() || peer->isVerifyCodes()) { return nullptr; - } else if (!history->peer->isUser() - && !history->peer->isChat() - && !history->peer->isMegagroup()) { + } else if (!peer->isUser() + && !peer->isChat() + && !peer->isMegagroup()) { return nullptr; } auto result = std::make_unique(history); diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp index dd694585c..239b0e446 100644 --- a/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp +++ b/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp @@ -131,10 +131,13 @@ ExceptionRow::ExceptionRow(not_null history) : Row(history) { } QString ExceptionRow::generateName() { - return peer()->isSelf() + const auto peer = this->peer(); + return peer->isSelf() ? tr::lng_saved_messages(tr::now) - : peer()->isRepliesChat() + : peer->isRepliesChat() ? tr::lng_replies_messages(tr::now) + : peer->isVerifyCodes() + ? tr::lng_verification_codes(tr::now) : Row::generateName(); } @@ -147,15 +150,19 @@ PaintRoundImageCallback ExceptionRow::generatePaintUserpicCallback( const auto peer = this->peer(); const auto saved = peer->isSelf(); const auto replies = peer->isRepliesChat(); + const auto verifyCodes = peer->isVerifyCodes(); auto userpic = saved ? Ui::PeerUserpicView() : ensureUserpicView(); if (forceRound && peer->isForum()) { return ForceRoundUserpicCallback(peer); } return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { + using namespace Ui; if (saved) { - Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); + EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); } else if (replies) { - Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); + EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); + } else if (verifyCodes) { + EmptyUserpic::PaintVerifyCodes(p, x, y, outerWidth, size); } else { peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size); } diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_chats_preview.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_chats_preview.cpp index 3e2efb87e..4539fdcfe 100644 --- a/Telegram/SourceFiles/boxes/filters/edit_filter_chats_preview.cpp +++ b/Telegram/SourceFiles/boxes/filters/edit_filter_chats_preview.cpp @@ -122,9 +122,11 @@ void FilterChatsPreview::paintEvent(QPaintEvent *e) { top += st.height; } for (auto &[history, userpic, name, button] : _removePeer) { - const auto savedMessages = history->peer->isSelf(); - const auto repliesMessages = history->peer->isRepliesChat(); - if (savedMessages || repliesMessages) { + const auto peer = history->peer; + const auto savedMessages = peer->isSelf(); + const auto repliesMessages = peer->isRepliesChat(); + const auto verifyCodes = peer->isVerifyCodes(); + if (savedMessages || repliesMessages || verifyCodes) { if (savedMessages) { Ui::EmptyUserpic::PaintSavedMessages( p, @@ -132,13 +134,20 @@ void FilterChatsPreview::paintEvent(QPaintEvent *e) { top + iconTop, width(), st.photoSize); - } else { + } else if (repliesMessages) { Ui::EmptyUserpic::PaintRepliesMessages( p, iconLeft, top + iconTop, width(), st.photoSize); + } else { + Ui::EmptyUserpic::PaintVerifyCodes( + p, + iconLeft, + top + iconTop, + width(), + st.photoSize); } p.setPen(st::contactsNameFg); p.drawTextLeft( @@ -147,7 +156,9 @@ void FilterChatsPreview::paintEvent(QPaintEvent *e) { width(), (savedMessages ? tr::lng_saved_messages(tr::now) - : tr::lng_replies_messages(tr::now))); + : repliesMessages + ? tr::lng_replies_messages(tr::now) + : tr::lng_verification_codes(tr::now))); } else { history->peer->paintUserpicLeft( p, diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp index aaeda8ae1..4b0a5254d 100644 --- a/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp +++ b/Telegram/SourceFiles/boxes/filters/edit_filter_links.cpp @@ -328,6 +328,7 @@ PaintRoundImageCallback ChatRow::generatePaintUserpicCallback( const auto peer = this->peer(); const auto saved = peer->isSelf(); const auto replies = peer->isRepliesChat(); + const auto verifyCodes = peer->isVerifyCodes(); auto userpic = (saved || replies) ? Ui::PeerUserpicView() : ensureUserpicView(); @@ -337,12 +338,15 @@ PaintRoundImageCallback ChatRow::generatePaintUserpicCallback( int y, int outerWidth, int size) mutable { + using namespace Ui; if (forceRound && peer->isForum()) { ForceRoundUserpicCallback(peer)(p, x, y, outerWidth, size); } else if (saved) { - Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); + EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); } else if (replies) { - Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); + EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); + } else if (verifyCodes) { + EmptyUserpic::PaintVerifyCodes(p, x, y, outerWidth, size); } else { peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size); } diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index fc4a2d77a..789f7df50 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -55,6 +55,10 @@ PaintRoundImageCallback PaintUserpicCallback( return [](QPainter &p, int x, int y, int outerWidth, int size) { Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); }; + } else if (peer->isVerifyCodes()) { + return [](QPainter &p, int x, int y, int outerWidth, int size) { + Ui::EmptyUserpic::PaintVerifyCodes(p, x, y, outerWidth, size); + }; } } auto userpic = Ui::PeerUserpicView(); @@ -447,6 +451,8 @@ void PeerListBox::addSelectItem( ? tr::lng_saved_short(tr::now) : (respect && peer->isRepliesChat()) ? tr::lng_replies_messages(tr::now) + : (respect && peer->isVerifyCodes()) + ? tr::lng_verification_codes(tr::now) : peer->shortName(); addSelectItem( peer->id.value, @@ -625,6 +631,8 @@ void PeerListRow::refreshName(const style::PeerListItem &st) { ? tr::lng_saved_messages(tr::now) : _isRepliesMessagesChat ? tr::lng_replies_messages(tr::now) + : _isVerifyCodesChat + ? tr::lng_verification_codes(tr::now) : generateName(); _name.setText(st.nameStyle, text, Ui::NameTextOptions()); } @@ -695,6 +703,8 @@ QString PeerListRow::generateShortName() { ? tr::lng_saved_short(tr::now) : _isRepliesMessagesChat ? tr::lng_replies_messages(tr::now) + : _isVerifyCodesChat + ? tr::lng_verification_codes(tr::now) : peer()->shortName(); } @@ -709,16 +719,20 @@ PaintRoundImageCallback PeerListRow::generatePaintUserpicCallback( bool forceRound) { const auto saved = !_savedMessagesStatus.isEmpty(); const auto replies = _isRepliesMessagesChat; + const auto verifyCodes = _isVerifyCodesChat; const auto peer = this->peer(); auto userpic = saved ? Ui::PeerUserpicView() : ensureUserpicView(); if (forceRound && peer->isForum()) { return ForceRoundUserpicCallback(peer); } return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { + using namespace Ui; if (saved) { - Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); + EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); } else if (replies) { - Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); + EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size); + } else if (verifyCodes) { + EmptyUserpic::PaintVerifyCodes(p, x, y, outerWidth, size); } else { peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size); } @@ -759,7 +773,8 @@ int PeerListRow::paintNameIconGetWidth( bool selected) { if (special() || !_savedMessagesStatus.isEmpty() - || _isRepliesMessagesChat) { + || _isRepliesMessagesChat + || _isVerifyCodesChat) { return 0; } return _bagde.drawGetWidth( @@ -874,12 +889,15 @@ void PeerListRow::paintDisabledCheckUserpic( auto iconBorderPen = st.checkbox.check.border->p; iconBorderPen.setWidth(st.checkbox.selectWidth); + const auto size = userpicRadius * 2; if (!_savedMessagesStatus.isEmpty()) { - Ui::EmptyUserpic::PaintSavedMessages(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); + Ui::EmptyUserpic::PaintSavedMessages(p, userpicLeft, userpicTop, outerWidth, size); } else if (_isRepliesMessagesChat) { - Ui::EmptyUserpic::PaintRepliesMessages(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); + Ui::EmptyUserpic::PaintRepliesMessages(p, userpicLeft, userpicTop, outerWidth, size); + } else if (_isVerifyCodesChat) { + Ui::EmptyUserpic::PaintVerifyCodes(p, userpicLeft, userpicTop, outerWidth, size); } else { - peer()->paintUserpicLeft(p, _userpic, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); + peer()->paintUserpicLeft(p, _userpic, userpicLeft, userpicTop, outerWidth, size); } { @@ -1069,10 +1087,13 @@ void PeerListContent::setRowHidden(not_null row, bool hidden) { void PeerListContent::addRowEntry(not_null row) { const auto savedMessagesStatus = _controller->savedMessagesChatStatus(); if (!savedMessagesStatus.isEmpty() && !row->special()) { - if (row->peer()->isSelf()) { + const auto peer = row->peer(); + if (peer->isSelf()) { row->setSavedMessagesChatStatus(savedMessagesStatus); - } else if (row->peer()->isRepliesChat()) { + } else if (peer->isRepliesChat()) { row->setIsRepliesMessagesChat(true); + } else if (peer->isVerifyCodes()) { + row->setIsVerifyCodesChat(true); } } _rowsById.emplace(row->id(), row); diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index aa24856e2..c23e2013f 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -200,6 +200,9 @@ public: void setIsRepliesMessagesChat(bool isRepliesMessagesChat) { _isRepliesMessagesChat = isRepliesMessagesChat; } + void setIsVerifyCodesChat(bool isVerifyCodesChat) { + _isVerifyCodesChat = isVerifyCodesChat; + } template void setChecked( @@ -299,6 +302,7 @@ private: bool _initialized : 1 = false; bool _isSearchResult : 1 = false; bool _isRepliesMessagesChat : 1 = false; + bool _isVerifyCodesChat : 1 = false; }; diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 7063372d9..53d56080a 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -842,6 +842,7 @@ auto ChooseRecipientBoxController::createRow( ? !_filter(history) : ((peer->isBroadcast() && !Data::CanSendAnything(peer)) || peer->isRepliesChat() + || peer->isVerifyCodes() || (peer->isUser() && (_premiumRequiredError ? !peer->asUser()->canSendIgnoreRequirePremium() : !Data::CanSendAnything(peer)))); diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp index bf30fe544..ab48b6b8d 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.cpp @@ -269,7 +269,8 @@ PaintRoundImageCallback ForbiddenRow::generatePaintUserpicCallback( const auto peer = this->peer(); const auto saved = peer->isSelf(); const auto replies = peer->isRepliesChat(); - auto userpic = (saved || replies) + const auto verifyCodes = peer->isVerifyCodes(); + auto userpic = (saved || replies || verifyCodes) ? Ui::PeerUserpicView() : ensureUserpicView(); auto paint = [=]( @@ -302,6 +303,7 @@ PaintRoundImageCallback ForbiddenRow::generatePaintUserpicCallback( repaint = (_paletteVersion != style::PaletteVersion()) || (!saved && !replies + && !verifyCodes && (_userpicKey != peer->userpicUniqueKey(userpic))); } if (repaint) { diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 9498c4478..d2891c984 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -838,6 +838,8 @@ void ShareBox::Inner::updateChatName(not_null chat) { ? tr::lng_saved_messages(tr::now) : peer->isRepliesChat() ? tr::lng_replies_messages(tr::now) + : peer->isVerifyCodes() + ? tr::lng_verification_codes(tr::now) : peer->name(); chat->name.setText(_st.item.nameStyle, text, Ui::NameTextOptions()); } diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index 10152d6cd..231d01972 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -367,17 +367,6 @@ void MonospaceClickHandler::onClick(ClickContext context) const { } const auto my = context.other.value(); if (const auto controller = my.sessionWindow.get()) { - auto &data = controller->session().data(); - const auto item = data.message(my.itemId); - const auto hasCopyRestriction = item - && (!item->history()->peer->allowsForwarding() - || item->forbidsForward()); - if (hasCopyRestriction) { - controller->showToast(item->history()->peer->isBroadcast() - ? tr::lng_error_nocopy_channel(tr::now) - : tr::lng_error_nocopy_group(tr::now)); - return; - } controller->showToast(tr::lng_text_copied(tr::now)); } TextUtilities::SetClipboardText(TextForMimeData::Simple(_text.trimmed())); diff --git a/Telegram/SourceFiles/data/data_chat_participant_status.cpp b/Telegram/SourceFiles/data/data_chat_participant_status.cpp index 6644254d5..38fa1a27e 100644 --- a/Telegram/SourceFiles/data/data_chat_participant_status.cpp +++ b/Telegram/SourceFiles/data/data_chat_participant_status.cpp @@ -112,7 +112,9 @@ bool CanSendAnyOf( ChatRestrictions rights, bool forbidInForums) { if (const auto user = peer->asUser()) { - if (user->isInaccessible() || user->isRepliesChat()) { + if (user->isInaccessible() + || user->isRepliesChat() + || user->isVerifyCodes()) { return false; } else if (user->meRequiresPremiumToWrite() && !user->session().premium()) { diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 35e43b158..b191c7ae8 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -628,7 +628,8 @@ bool PeerData::canCreatePolls() const { if (const auto user = asUser()) { return user->isBot() && !user->isSupport() - && !user->isRepliesChat(); + && !user->isRepliesChat() + && !user->isVerifyCodes(); } return Data::CanSend(this, ChatRestriction::SendPolls); } @@ -664,7 +665,7 @@ bool PeerData::canEditMessagesIndefinitely() const { } bool PeerData::canExportChatHistory() const { - if (isRepliesChat() || !allowsForwarding()) { + if (isRepliesChat() || isVerifyCodes() || !allowsForwarding()) { return false; } else if (const auto channel = asChannel()) { if (!channel->amIn() && channel->invitePeekExpires()) { @@ -865,6 +866,13 @@ void PeerData::fillNames() { if (localized != english) { appendToIndex(localized); } + } else if (isVerifyCodes()) { + const auto english = u"Verification Codes"_q; + const auto localized = tr::lng_verification_codes(tr::now); + appendToIndex(english); + if (localized != english) { + appendToIndex(localized); + } } } else if (const auto channel = asChannel()) { appendToIndex(channel->username()); @@ -1202,8 +1210,13 @@ bool PeerData::isRepliesChat() const { : kTestId) == id; } +bool PeerData::isVerifyCodes() const { + constexpr auto kVerifyCodesId = peerFromUser(489000); + return (id == kVerifyCodesId); +} + bool PeerData::sharedMediaInfo() const { - return isSelf() || isRepliesChat(); + return isSelf() || isRepliesChat() || isVerifyCodes(); } bool PeerData::savedSublistsInfo() const { diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 5433ced7f..354bac4a5 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -227,6 +227,7 @@ public: [[nodiscard]] bool isForum() const; [[nodiscard]] bool isGigagroup() const; [[nodiscard]] bool isRepliesChat() const; + [[nodiscard]] bool isVerifyCodes() const; [[nodiscard]] bool sharedMediaInfo() const; [[nodiscard]] bool savedSublistsInfo() const; [[nodiscard]] bool hasStoriesHidden() const; diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp index c5e26bb0f..73d041c08 100644 --- a/Telegram/SourceFiles/data/data_peer_values.cpp +++ b/Telegram/SourceFiles/data/data_peer_values.cpp @@ -216,7 +216,7 @@ inline auto DefaultRestrictionValue( ChatRestrictions rights, bool forbidInForums) { if (const auto user = peer->asUser()) { - if (user->isRepliesChat()) { + if (user->isRepliesChat() || user->isVerifyCodes()) { return rpl::single(false); } using namespace rpl::mappers; diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 77a20da6e..62a8e933b 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -452,7 +452,7 @@ bool UserData::requirePremiumToWriteKnown() const { } bool UserData::canSendIgnoreRequirePremium() const { - return !isInaccessible() && !isRepliesChat(); + return !isInaccessible() && !isRepliesChat() && !isVerifyCodes(); } bool UserData::readDatesPrivate() const { diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index bb90a581d..dae0ce036 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -604,6 +604,8 @@ std::unique_ptr CustomEmojiManager::userpic( image = Ui::MakeSavedMessagesThumbnail(); } else if (v[0] == u"replies"_q) { image = Ui::MakeRepliesThumbnail(); + } else if (v[0] == u"verify_codes"_q) { + image = Ui::MakeVerifyCodesThumbnail(); } else { const auto id = PeerId(v[0].toULongLong()); image = Ui::MakeUserpicThumbnail(_owner->peer(id)); @@ -1017,6 +1019,8 @@ QString CustomEmojiManager::registerInternalEmoji( ? u"self"_q : peer->isRepliesChat() ? u"replies"_q + : peer->isVerifyCodes() + ? u"verify_codes"_q : QString::number(peer->id.value); return UserpicEmojiPrefix() + id + InternalPadding(padding); } diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index f34114397..2c474b0bd 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -355,6 +355,7 @@ dialogsForumIcon: ThreeStateIcon { } dialogsArchiveUserpic: icon {{ "archive_userpic", historyPeerUserpicFg }}; dialogsRepliesUserpic: icon {{ "replies_userpic", historyPeerUserpicFg }}; +dialogsVerifyCodesUserpic: icon {{ "replies_userpic", historyPeerUserpicFg }}; dialogsInaccessibleUserpic: icon {{ "dialogs/inaccessible_userpic", historyPeerUserpicFg }}; dialogsHiddenAuthorUserpic: icon {{ "dialogs/avatar_hidden", premiumButtonFg }}; dialogsMyNotesUserpic: icon {{ "dialogs/avatar_notes", historyPeerUserpicFg }}; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index f1431ad9d..f4e6466d1 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -49,7 +49,10 @@ namespace { const auto kPsaBadgePrefix = "cloud_lng_badge_psa_"; [[nodiscard]] bool ShowUserBotIcon(not_null user) { - return user->isBot() && !user->isSupport() && !user->isRepliesChat(); + return user->isBot() + && !user->isSupport() + && !user->isRepliesChat() + && !user->isVerifyCodes(); } [[nodiscard]] bool ShowSendActionInDialogs(Data::Thread *thread) { @@ -245,10 +248,11 @@ void PaintFolderEntryText( enum class Flag { SavedMessages = 0x008, RepliesMessages = 0x010, - AllowUserOnline = 0x020, - TopicJumpRipple = 0x040, - HiddenAuthor = 0x080, - MyNotes = 0x100, + VerifyCodes = 0x020, + AllowUserOnline = 0x040, + TopicJumpRipple = 0x080, + HiddenAuthor = 0x100, + MyNotes = 0x200, }; inline constexpr bool is_flag_type(Flag) { return true; } @@ -307,6 +311,13 @@ void PaintRow( context.st->padding.top(), context.width, context.st->photoSize); + } else if (flags & Flag::VerifyCodes) { + EmptyUserpic::PaintVerifyCodes( + p, + context.st->padding.left(), + context.st->padding.top(), + context.width, + context.st->photoSize); } else if (flags & Flag::HiddenAuthor) { EmptyUserpic::PaintHiddenAuthor( p, @@ -615,12 +626,15 @@ void PaintRow( if (flags & (Flag::SavedMessages | Flag::RepliesMessages + | Flag::VerifyCodes | Flag::HiddenAuthor | Flag::MyNotes)) { auto text = (flags & Flag::SavedMessages) ? tr::lng_saved_messages(tr::now) : (flags & Flag::RepliesMessages) ? tr::lng_replies_messages(tr::now) + : (flags & Flag::VerifyCodes) + ? tr::lng_verification_codes(tr::now) : (flags & Flag::MyNotes) ? tr::lng_my_notes(tr::now) : tr::lng_hidden_author_messages(tr::now); @@ -806,6 +820,9 @@ void RowPainter::Paint( | ((from && from->isRepliesChat()) ? Flag::RepliesMessages : Flag(0)) + | ((from && from->isVerifyCodes()) + ? Flag::VerifyCodes + : Flag(0)) | ((sublist && from->isSavedHiddenAuthor()) ? Flag::HiddenAuthor : Flag(0)) @@ -962,8 +979,12 @@ void RowPainter::Paint( const auto showRepliesMessages = history && history->peer->isRepliesChat() && !row->searchInChat(); + const auto showVerifyCodes = history + && history->peer->isVerifyCodes() + && !row->searchInChat(); const auto flags = (showSavedMessages ? Flag::SavedMessages : Flag(0)) - | (showRepliesMessages ? Flag::RepliesMessages : Flag(0)); + | (showRepliesMessages ? Flag::RepliesMessages : Flag(0)) + | (showVerifyCodes ? Flag::VerifyCodes : Flag(0)); PaintRow( p, row, diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp index c005c7e4c..13f52f944 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp @@ -183,7 +183,7 @@ void FillEntryMenu( RecentRow::RecentRow(not_null peer) : PeerListRow(peer) , _history(peer->owner().history(peer)) { - if (peer->isSelf() || peer->isRepliesChat()) { + if (peer->isSelf() || peer->isRepliesChat() || peer->isVerifyCodes()) { setCustomStatus(u" "_q); } else if (const auto chat = peer->asChat()) { if (chat->count > 0) { @@ -286,7 +286,9 @@ bool RecentRow::rightActionDisabled() const { const style::PeerListItem &RecentRow::computeSt( const style::PeerListItem &st) const { - return (peer()->isSelf() || peer()->isRepliesChat()) + return (peer()->isSelf() + || peer()->isRepliesChat() + || peer()->isVerifyCodes()) ? st::recentPeersSpecialName : st; } @@ -789,7 +791,9 @@ void RecentsController::subscribeToEvents() { } else if (update.flags & Flag::Notifications) { refreshed = static_cast(row)->refreshBadge(); } - if (!peer->isRepliesChat() && (update.flags & Flag::OnlineStatus)) { + if (!peer->isRepliesChat() + && !peer->isVerifyCodes() + && (update.flags & Flag::OnlineStatus)) { row->clearCustomStatus(); refreshed = true; } diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 7bd2d3515..0301f1ce4 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -1086,6 +1086,10 @@ User ParseUser(const MTPUser &data) { } if (data.is_self()) { result.isSelf = true; + } else if (data.vid().v == 1271266957) { + result.isReplies = true; + } else if (data.vid().v == 489000) { + result.isVerifyCodes = true; } result.input = MTP_inputUser( data.vid(), @@ -2080,6 +2084,8 @@ DialogInfo::Type DialogTypeFromUser(const User &user) { ? DialogInfo::Type::Self : user.isReplies ? DialogInfo::Type::Replies + : user.isVerifyCodes + ? DialogInfo::Type::VerifyCodes : user.isBot ? DialogInfo::Type::Bot : DialogInfo::Type::Personal; diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index e07554974..72e823d21 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -253,6 +253,7 @@ struct User { bool isBot = false; bool isSelf = false; bool isReplies = false; + bool isVerifyCodes = false; MTPInputUser input = MTP_inputUserEmpty(); @@ -866,6 +867,7 @@ struct DialogInfo { Unknown, Self, Replies, + VerifyCodes, Personal, Bot, PrivateGroup, diff --git a/Telegram/SourceFiles/export/export_controller.cpp b/Telegram/SourceFiles/export/export_controller.cpp index b3d543f4c..a6e12d28d 100644 --- a/Telegram/SourceFiles/export/export_controller.cpp +++ b/Telegram/SourceFiles/export/export_controller.cpp @@ -635,6 +635,8 @@ void ControllerObject::fillMessagesState( ? ProcessingState::EntityType::SavedMessages : (dialog->type == Data::DialogInfo::Type::Replies) ? ProcessingState::EntityType::RepliesMessages + : (dialog->type == Data::DialogInfo::Type::VerifyCodes) + ? ProcessingState::EntityType::VerifyCodes : ProcessingState::EntityType::Chat; result.itemIndex = _messagesWritten + progress.itemIndex; result.itemCount = std::max(_messagesCount, result.itemIndex); diff --git a/Telegram/SourceFiles/export/export_controller.h b/Telegram/SourceFiles/export/export_controller.h index fae4b54a1..b486a6d09 100644 --- a/Telegram/SourceFiles/export/export_controller.h +++ b/Telegram/SourceFiles/export/export_controller.h @@ -48,6 +48,7 @@ struct ProcessingState { Chat, SavedMessages, RepliesMessages, + VerifyCodes, Other, }; diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp index 61f122b8d..4bdb71eb3 100644 --- a/Telegram/SourceFiles/export/output/export_output_html.cpp +++ b/Telegram/SourceFiles/export/output/export_output_html.cpp @@ -3226,6 +3226,7 @@ Result HtmlWriter::writeDialogEnd() { case Type::Unknown: return "unknown"; case Type::Self: case Type::Replies: + case Type::VerifyCodes: case Type::Personal: return "private"; case Type::Bot: return "bot"; case Type::PrivateGroup: @@ -3241,6 +3242,7 @@ Result HtmlWriter::writeDialogEnd() { case Type::Unknown: case Type::Self: case Type::Replies: + case Type::VerifyCodes: case Type::Personal: case Type::Bot: return "Deleted Account"; case Type::PrivateGroup: @@ -3257,6 +3259,8 @@ Result HtmlWriter::writeDialogEnd() { return "Saved messages"; } else if (dialog.type == Type::Replies) { return "Replies"; + } else if (dialog.type == Type::VerifyCodes) { + return "Verification Codes"; } return dialog.name; }; @@ -3277,7 +3281,9 @@ Result HtmlWriter::writeDialogEnd() { + (outgoing ? " outgoing messages" : " messages"); }; auto userpic = UserpicData{ - ((_dialog.type == Type::Self || _dialog.type == Type::Replies) + ((_dialog.type == Type::Self + || _dialog.type == Type::Replies + || _dialog.type == Type::VerifyCodes) ? kSavedMessagesColorIndex : Data::PeerColorIndex(_dialog.peerId)), kEntryUserpicSize diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index a91c07dbd..14fe04b34 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -1465,6 +1465,7 @@ Result JsonWriter::writeDialogStart(const Data::DialogInfo &data) { case Type::Unknown: return ""; case Type::Self: return "saved_messages"; case Type::Replies: return "replies"; + case Type::VerifyCodes: return "verification_codes"; case Type::Personal: return "personal_chat"; case Type::Bot: return "bot_chat"; case Type::PrivateGroup: return "private_group"; @@ -1480,7 +1481,9 @@ Result JsonWriter::writeDialogStart(const Data::DialogInfo &data) { ? QByteArray() : prepareArrayItemStart(); block.append(pushNesting(Context::kObject)); - if (data.type != Type::Self && data.type != Type::Replies) { + if (data.type != Type::Self + && data.type != Type::Replies + && data.type != Type::VerifyCodes) { block.append(prepareObjectItemStart("name") + StringAllowNull(data.name)); } diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 8c47894c8..b324d7e5c 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -809,6 +809,7 @@ bool HistoryInner::canHaveFromUserpics() const { if (_peer->isUser() && !_peer->isSelf() && !_peer->isRepliesChat() + && !_peer->isVerifyCodes() && !_isChatWide) { return false; } else if (const auto channel = _peer->asBroadcast()) { diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index cf2b78295..46e9c52e3 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -94,7 +94,7 @@ template } [[nodiscard]] TextWithEntities SpoilerLoginCode(TextWithEntities text) { - const auto r = QRegularExpression(u"([\\d\\-]{5,7})"_q); + const auto r = QRegularExpression(u"([\\d\\-]{4,8})"_q); const auto m = r.match(text.text); if (!m.hasMatch()) { return text; @@ -2793,7 +2793,10 @@ bool HistoryItem::showForwardsFromSender( not_null forwarded) const { const auto peer = history()->peer; return !forwarded->story - && (peer->isSelf() || peer->isRepliesChat() || forwarded->imported); + && (peer->isSelf() + || peer->isRepliesChat() + || peer->isVerifyCodes() + || forwarded->imported); } not_null HistoryItem::fromOriginal() const { @@ -3433,7 +3436,8 @@ TextWithEntities HistoryItem::notificationText( }(); if (options.spoilerLoginCode && !out() - && history()->peer->isNotificationsUser()) { + && (history()->peer->isNotificationsUser() + || history()->peer->isVerifyCodes())) { result = SpoilerLoginCode(std::move(result)); } if (result.text.size() <= kNotificationTextLimit) { @@ -3472,7 +3476,8 @@ ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const { }(); if (options.spoilerLoginCode && !out() - && history()->peer->isNotificationsUser()) { + && (history()->peer->isNotificationsUser() + || history()->peer->isVerifyCodes())) { result.text = SpoilerLoginCode(std::move(result.text)); } const auto fromSender = [](not_null sender) { @@ -3510,7 +3515,8 @@ ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const { return fromSender(from); } return fromForwarded(); - } else if (_history->peer->isSelf()) { + } else if (_history->peer->isSelf() + || _history->peer->isVerifyCodes()) { return fromForwarded(); } return {}; @@ -3573,8 +3579,10 @@ void HistoryItem::createComponents(CreateConfig &&config) { if (savedFrom && savedFrom->isChannel()) { mask |= HistoryMessageSigned::Bit(); } - } else if ((_history->peer->isSelf() || _history->peer->isRepliesChat()) - && !config.originalPostAuthor.isEmpty()) { + } else if (!config.originalPostAuthor.isEmpty() + && (_history->peer->isSelf() + || _history->peer->isRepliesChat() + || _history->peer->isVerifyCodes())) { mask |= HistoryMessageSigned::Bit(); } if (config.editDate != TimeId(0)) { diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index e8f531b50..9a7e588f6 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -2367,7 +2367,7 @@ void HistoryWidget::showHistory( updateNotifyControls(); session().data().notifySettings().request(_peer); refreshSilentToggle(); - } else if (_peer->isRepliesChat()) { + } else if (_peer->isRepliesChat() || _peer->isVerifyCodes()) { updateNotifyControls(); } refreshScheduledToggle(); @@ -2753,7 +2753,7 @@ void HistoryWidget::updateFieldSubmitSettings() { } void HistoryWidget::updateNotifyControls() { - if (!_peer || (!_peer->isChannel() && !_peer->isRepliesChat())) { + if (!_peer || (!_peer->isChannel() && !_peer->isRepliesChat() && !_peer->isVerifyCodes())) { return; } @@ -4874,7 +4874,8 @@ bool HistoryWidget::isMuteUnmute() const { return _peer && ((_peer->isBroadcast() && !_peer->asChannel()->canPostMessages()) || (_peer->isGigagroup() && !Data::CanSendAnything(_peer)) - || _peer->isRepliesChat()); + || _peer->isRepliesChat() + || _peer->isVerifyCodes()); } bool HistoryWidget::isSearching() const { diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 1828f56ce..42174145c 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -496,7 +496,10 @@ Element::Element( } if (data->isFakeAboutView()) { const auto user = data->history()->peer->asUser(); - if (user && user->isBot() && !user->isRepliesChat()) { + if (user + && user->isBot() + && !user->isRepliesChat() + && !user->isVerifyCodes()) { AddComponents(FakeBotAboutTop::Bit()); } } @@ -1124,8 +1127,10 @@ bool Element::computeIsAttachToPrevious(not_null previous) { if (possible) { const auto forwarded = item->Get(); const auto prevForwarded = prev->Get(); - if (item->history()->peer->isSelf() - || item->history()->peer->isRepliesChat() + const auto peer = item->history()->peer; + if (peer->isSelf() + || peer->isRepliesChat() + || peer->isVerifyCodes() || (forwarded && forwarded->imported) || (prevForwarded && prevForwarded->imported)) { return IsAttachedToPreviousInSavedMessages( diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 9f8c3111f..a447d5ff1 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -2378,6 +2378,8 @@ bool Message::hasFromPhoto() const { return false; } else if (delegate()->elementIsChatWide()) { return true; + } else if (item->history()->peer->isVerifyCodes()) { + return !hasOutLayout(); } else if (const auto forwarded = item->Get()) { const auto peer = item->history()->peer; if (peer->isSelf() || peer->isRepliesChat()) { diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 0a241055d..b9445e75e 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -521,7 +521,7 @@ void TopBarWidget::paintTopBar(Painter &p) { p.drawTextLeft(nameleft, statustop, width(), _customTitleText); } } else if (folder - || (peer && peer->sharedMediaInfo()) + || (peer && (peer->sharedMediaInfo() || peer->isVerifyCodes())) || (_activeChat.section == Section::Scheduled) || (_activeChat.section == Section::Pinned)) { auto text = (_activeChat.section == Section::Scheduled) @@ -536,6 +536,8 @@ void TopBarWidget::paintTopBar(Painter &p) { ? tr::lng_saved_messages(tr::now) : peer->isRepliesChat() ? tr::lng_replies_messages(tr::now) + : peer->isVerifyCodes() + ? tr::lng_verification_codes(tr::now) : peer->name(); const auto textWidth = st::historySavedFont->width(text); if (availableWidth < textWidth) { diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index 3c6fc0e7f..a35609c38 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -562,6 +562,7 @@ void Cover::refreshUploadPhotoOverlay() { || user->isSelf() || user->isInaccessible() || user->isRepliesChat() + || user->isVerifyCodes() || (user->botInfo && user->botInfo->canEditInformation) || user->isServiceUser()) { return false; diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 2f0b8a5a3..624b488f0 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -302,7 +302,10 @@ rpl::producer IsContactValue(not_null user) { [[nodiscard]] rpl::producer InviteToChatButton( not_null user) { - if (!user->isBot() || user->isRepliesChat() || user->isSupport()) { + if (!user->isBot() + || user->isRepliesChat() + || user->isVerifyCodes() + || user->isSupport()) { return rpl::single(QString()); } using Flag = Data::PeerUpdate::Flag; @@ -323,7 +326,10 @@ rpl::producer IsContactValue(not_null user) { [[nodiscard]] rpl::producer InviteToChatAbout( not_null user) { - if (!user->isBot() || user->isRepliesChat() || user->isSupport()) { + if (!user->isBot() + || user->isRepliesChat() + || user->isVerifyCodes() + || user->isSupport()) { return rpl::single(QString()); } using Flag = Data::PeerUpdate::Flag; diff --git a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm index ca4f88dad..387a99be0 100644 --- a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm +++ b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm @@ -56,6 +56,10 @@ inline bool IsRepliesPeer(PeerData *peer) { return peer && peer->isRepliesChat(); } +inline bool IsVerifyCodesPeer(PeerData *peer) { + return peer && peer->isVerifyCodes(); +} + QImage PrepareImage() { const auto s = kCircleDiameter * style::DevicePixelRatio(); auto result = QImage(QSize(s, s), QImage::Format_ARGB32_Premultiplied); @@ -81,6 +85,15 @@ QImage RepliesMessagesUserpic() { return result; } +QImage VerifyCodesUserpic() { + auto result = PrepareImage(); + Painter paint(&result); + + const auto s = result.width(); + Ui::EmptyUserpic::PaintVerifyCodes(paint, 0, 0, s, s); + return result; +} + QImage ArchiveUserpic(not_null folder) { auto result = PrepareImage(); Painter paint(&result); @@ -174,11 +187,13 @@ NSRect PeerRectByIndex(int index) { std::vector> _pins; QImage _savedMessages; QImage _repliesMessages; + QImage _verifyCodes; QImage _archive; bool _hasArchive; bool _selfUnpinned; bool _repliesUnpinned; + bool _verifyCodesUnpinned; rpl::event_stream> _touches; rpl::event_stream> _gestures; @@ -462,6 +477,7 @@ NSRect PeerRectByIndex(int index) { _hasArchive = _selfUnpinned = false; _savedMessages = SavedMessagesUserpic(); _repliesMessages = RepliesMessagesUserpic(); + _verifyCodes = VerifyCodesUserpic(); auto *gesture = [[[NSPressGestureRecognizer alloc] initWithTarget:self @@ -511,6 +527,9 @@ NSRect PeerRectByIndex(int index) { } else if (IsRepliesPeer(pin->peer)) { pin->userpic = _repliesMessages; return; + } else if (IsVerifyCodesPeer(pin->peer)) { + pin->userpic = _verifyCodes; + return; } auto userpic = PrepareImage(); Painter p(&userpic); @@ -635,6 +654,7 @@ NSRect PeerRectByIndex(int index) { }) | ranges::to_vector; _selfUnpinned = ranges::none_of(peers, &PeerData::isSelf); _repliesUnpinned = ranges::none_of(peers, &PeerData::isRepliesChat); + _verifyCodesUnpinned = ranges::none_of(peers, &PeerData::isVerifyCodes); peerChangedLifetime->destroy(); for (const auto &pin : _pins) { @@ -714,6 +734,7 @@ NSRect PeerRectByIndex(int index) { } _savedMessages = SavedMessagesUserpic(); _repliesMessages = RepliesMessagesUserpic(); + _verifyCodes = VerifyCodesUserpic(); updateUserpics(); }); }, _lifetime); @@ -782,6 +803,8 @@ NSRect PeerRectByIndex(int index) { return _savedMessages; } else if (_repliesUnpinned) { return _repliesMessages; + } else if (_verifyCodesUnpinned) { + return _verifyCodes; } } return _pins[i]->userpic; diff --git a/Telegram/SourceFiles/settings/settings_global_ttl.cpp b/Telegram/SourceFiles/settings/settings_global_ttl.cpp index 99dea5b2d..0e5d3387d 100644 --- a/Telegram/SourceFiles/settings/settings_global_ttl.cpp +++ b/Telegram/SourceFiles/settings/settings_global_ttl.cpp @@ -128,11 +128,12 @@ void TTLChatsBoxController::rowClicked(not_null row) { std::unique_ptr TTLChatsBoxController::createRow( not_null history) { - if (history->peer->isSelf() || history->peer->isRepliesChat()) { + const auto peer = history->peer; + if (peer->isSelf() || peer->isRepliesChat() || peer->isVerifyCodes()) { return nullptr; - } else if (history->peer->isChat() && history->peer->asChat()->amIn()) { - } else if (history->peer->isMegagroup()) { - } else if (!TTLMenu::TTLValidator(nullptr, history->peer).can()) { + } else if (peer->isChat() && peer->asChat()->amIn()) { + } else if (peer->isMegagroup()) { + } else if (!TTLMenu::TTLValidator(nullptr, peer).can()) { return nullptr; } if (session().data().contactsNoChatsList()->contains({ history })) { @@ -140,7 +141,7 @@ std::unique_ptr TTLChatsBoxController::createRow( } auto result = std::make_unique(history); const auto applyStatus = [=, raw = result.get()] { - const auto ttl = history->peer->messagesTTL(); + const auto ttl = peer->messagesTTL(); raw->setCustomStatus( ttl ? tr::lng_settings_ttl_select_chats_status( diff --git a/Telegram/SourceFiles/settings/settings_notifications_type.cpp b/Telegram/SourceFiles/settings/settings_notifications_type.cpp index 802a82ee6..df18b65ee 100644 --- a/Telegram/SourceFiles/settings/settings_notifications_type.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications_type.cpp @@ -185,9 +185,11 @@ base::unique_qptr AddExceptionBoxController::rowContextMenu( auto AddExceptionBoxController::createRow(not_null history) -> std::unique_ptr { - if (Data::DefaultNotifyType(history->peer) != _type - || history->peer->isSelf() - || history->peer->isRepliesChat()) { + const auto peer = history->peer; + if (Data::DefaultNotifyType(peer) != _type + || peer->isSelf() + || peer->isRepliesChat() + || peer->isVerifyCodes()) { return nullptr; } return std::make_unique(history); diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index ba656c552..dc9a7bcc3 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -142,14 +142,16 @@ void BlockPeerBoxController::rowClicked(not_null row) { auto BlockPeerBoxController::createRow(not_null history) -> std::unique_ptr { - if (!history->peer->isUser() - || history->peer->isServiceUser() - || history->peer->isSelf() - || history->peer->isRepliesChat()) { + const auto peer = history->peer; + if (!peer->isUser() + || peer->isServiceUser() + || peer->isSelf() + || peer->isRepliesChat() + || peer->isVerifyCodes()) { return nullptr; } auto row = std::make_unique(history); - updateIsBlocked(row.get(), history->peer); + updateIsBlocked(row.get(), peer); return row; } diff --git a/Telegram/SourceFiles/ui/controls/userpic_button.cpp b/Telegram/SourceFiles/ui/controls/userpic_button.cpp index ea0bfa937..6bc8ac56e 100644 --- a/Telegram/SourceFiles/ui/controls/userpic_button.cpp +++ b/Telegram/SourceFiles/ui/controls/userpic_button.cpp @@ -495,6 +495,13 @@ void UserpicButton::paintEvent(QPaintEvent *e) { photoPosition.y(), width(), _st.photoSize); + } else if (showVerifyCodes()) { + Ui::EmptyUserpic::PaintVerifyCodes( + p, + photoPosition.x(), + photoPosition.y(), + width(), + _st.photoSize); } else { if (_a_appearance.animating()) { p.drawPixmapLeft(photoPosition, width(), _oldUserpic); @@ -898,6 +905,10 @@ bool UserpicButton::showRepliesMessages() const { return _showSavedMessagesOnSelf && _peer && _peer->isRepliesChat(); } +bool UserpicButton::showVerifyCodes() const { + return _showSavedMessagesOnSelf && _peer && _peer->isVerifyCodes(); +} + void UserpicButton::startChangeOverlayAnimation() { auto over = isOver() || isDown(); _changeOverlayShown.start( diff --git a/Telegram/SourceFiles/ui/controls/userpic_button.h b/Telegram/SourceFiles/ui/controls/userpic_button.h index 8d2eb2adf..182b13828 100644 --- a/Telegram/SourceFiles/ui/controls/userpic_button.h +++ b/Telegram/SourceFiles/ui/controls/userpic_button.h @@ -136,8 +136,9 @@ private: void setCursorInChangeOverlay(bool inOverlay); void updateCursor(); void updateVideo(); - bool showSavedMessages() const; - bool showRepliesMessages() const; + [[nodiscard]] bool showSavedMessages() const; + [[nodiscard]] bool showRepliesMessages() const; + [[nodiscard]] bool showVerifyCodes() const; void checkStreamedIsStarted(); bool createStreamingObjects(not_null photo); void clearStreaming(); diff --git a/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp b/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp index 868e95cb5..12e489a50 100644 --- a/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp +++ b/Telegram/SourceFiles/ui/dynamic_thumbnails.cpp @@ -157,6 +157,19 @@ private: }; +class VerifyCodesUserpic final : public DynamicImage { +public: + std::shared_ptr clone() override; + + QImage image(int size) override; + void subscribeToUpdates(Fn callback) override; + +private: + QImage _frame; + int _paletteVersion = 0; + +}; + class HiddenAuthorUserpic final : public DynamicImage { public: std::shared_ptr clone() override; @@ -495,6 +508,37 @@ void RepliesUserpic::subscribeToUpdates(Fn callback) { } } +std::shared_ptr VerifyCodesUserpic::clone() { + return std::make_shared(); +} + +QImage VerifyCodesUserpic::image(int size) { + const auto good = (_frame.width() == size * _frame.devicePixelRatio()); + const auto paletteVersion = style::PaletteVersion(); + if (!good || _paletteVersion != paletteVersion) { + _paletteVersion = paletteVersion; + + const auto ratio = style::DevicePixelRatio(); + if (!good) { + _frame = QImage( + QSize(size, size) * ratio, + QImage::Format_ARGB32_Premultiplied); + _frame.setDevicePixelRatio(ratio); + } + _frame.fill(Qt::transparent); + + auto p = Painter(&_frame); + Ui::EmptyUserpic::PaintVerifyCodes(p, 0, 0, size, size); + } + return _frame; +} + +void VerifyCodesUserpic::subscribeToUpdates(Fn callback) { + if (!callback) { + _frame = {}; + } +} + std::shared_ptr HiddenAuthorUserpic::clone() { return std::make_shared(); } @@ -623,6 +667,10 @@ std::shared_ptr MakeRepliesThumbnail() { return std::make_shared(); } +std::shared_ptr MakeVerifyCodesThumbnail() { + return std::make_shared(); +} + std::shared_ptr MakeHiddenAuthorThumbnail() { return std::make_shared(); } diff --git a/Telegram/SourceFiles/ui/dynamic_thumbnails.h b/Telegram/SourceFiles/ui/dynamic_thumbnails.h index 9876d3df8..82a91fe33 100644 --- a/Telegram/SourceFiles/ui/dynamic_thumbnails.h +++ b/Telegram/SourceFiles/ui/dynamic_thumbnails.h @@ -23,6 +23,7 @@ class DynamicImage; bool forceRound = false); [[nodiscard]] std::shared_ptr MakeSavedMessagesThumbnail(); [[nodiscard]] std::shared_ptr MakeRepliesThumbnail(); +[[nodiscard]] std::shared_ptr MakeVerifyCodesThumbnail(); [[nodiscard]] std::shared_ptr MakeHiddenAuthorThumbnail(); [[nodiscard]] std::shared_ptr MakeStoryThumbnail( not_null story); diff --git a/Telegram/SourceFiles/ui/empty_userpic.cpp b/Telegram/SourceFiles/ui/empty_userpic.cpp index 1eebf7a11..3e892aaed 100644 --- a/Telegram/SourceFiles/ui/empty_userpic.cpp +++ b/Telegram/SourceFiles/ui/empty_userpic.cpp @@ -226,6 +226,22 @@ void PaintInaccessibleAccountInner( } } +void PaintVerifyCodesInner( + QPainter &p, + int x, + int y, + int size, + const style::color &fg) { + PaintIconInner( + p, + x, + y, + size, + st::defaultDialogRow.photoSize, + st::dialogsVerifyCodesUserpic, + fg); +} + [[nodiscard]] QImage Generate(int size, Fn callback) { auto result = QImage( QSize(size, size) * style::DevicePixelRatio(), @@ -429,6 +445,45 @@ QImage EmptyUserpic::GenerateRepliesMessages(int size) { }); } +void EmptyUserpic::PaintVerifyCodes( + QPainter &p, + int x, + int y, + int outerWidth, + int size) { + auto bg = QLinearGradient(x, y, x, y + size); + bg.setStops({ + { 0., st::historyPeerSavedMessagesBg->c }, + { 1., st::historyPeerSavedMessagesBg2->c } + }); + const auto &fg = st::historyPeerUserpicFg; + PaintVerifyCodes(p, x, y, outerWidth, size, QBrush(bg), fg); +} + +void EmptyUserpic::PaintVerifyCodes( + QPainter &p, + int x, + int y, + int outerWidth, + int size, + QBrush bg, + const style::color &fg) { + x = style::RightToLeft() ? (outerWidth - x - size) : x; + + PainterHighQualityEnabler hq(p); + p.setBrush(bg); + p.setPen(Qt::NoPen); + p.drawEllipse(x, y, size, size); + + PaintVerifyCodesInner(p, x, y, size, fg); +} + +QImage EmptyUserpic::GenerateVerifyCodes(int size) { + return Generate(size, [&](QPainter &p) { + PaintVerifyCodes(p, 0, 0, size, size); + }); +} + void EmptyUserpic::PaintHiddenAuthor( QPainter &p, int x, diff --git a/Telegram/SourceFiles/ui/empty_userpic.h b/Telegram/SourceFiles/ui/empty_userpic.h index 7d293db54..bd7daa8fe 100644 --- a/Telegram/SourceFiles/ui/empty_userpic.h +++ b/Telegram/SourceFiles/ui/empty_userpic.h @@ -81,6 +81,22 @@ public: const style::color &fg); [[nodiscard]] static QImage GenerateRepliesMessages(int size); + static void PaintVerifyCodes( + QPainter &p, + int x, + int y, + int outerWidth, + int size); + static void PaintVerifyCodes( + QPainter &p, + int x, + int y, + int outerWidth, + int size, + QBrush bg, + const style::color &fg); + [[nodiscard]] static QImage GenerateVerifyCodes(int size); + static void PaintHiddenAuthor( QPainter &p, int x, diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 05b46f74c..60f6df58a 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -870,6 +870,9 @@ void Notification::updateNotifyDisplay() { } else if (_history->peer->isRepliesChat()) { Ui::EmptyUserpic::PaintRepliesMessages(p, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width(), st::notifyPhotoSize); _userpicLoaded = true; + } else if (_history->peer->isVerifyCodes()) { + Ui::EmptyUserpic::PaintVerifyCodes(p, st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), width(), st::notifyPhotoSize); + _userpicLoaded = true; } else { _userpicView = _history->peer->createUserpicView(); _history->peer->loadUserpic(); diff --git a/Telegram/SourceFiles/window/notifications_utilities.cpp b/Telegram/SourceFiles/window/notifications_utilities.cpp index e2ef49fed..f69f72b9c 100644 --- a/Telegram/SourceFiles/window/notifications_utilities.cpp +++ b/Telegram/SourceFiles/window/notifications_utilities.cpp @@ -28,6 +28,8 @@ QImage GenerateUserpic(not_null peer, Ui::PeerUserpicView &view) { ? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize) : peer->isRepliesChat() ? Ui::EmptyUserpic::GenerateRepliesMessages(st::notifyMacPhotoSize) + : peer->isVerifyCodes() + ? Ui::EmptyUserpic::GenerateVerifyCodes(st::notifyMacPhotoSize) : PeerData::GenerateUserpicImage(peer, view, st::notifyMacPhotoSize); } diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 6820f4ab0..2bc8dbd29 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -566,7 +566,10 @@ void Filler::addSupportInfo() { } void Filler::addInfo() { - if (_peer && (_peer->isSelf() || _peer->isRepliesChat())) { + if (_peer + && (_peer->isSelf() + || _peer->isRepliesChat() + || _peer->isVerifyCodes())) { return; } else if (!_thread) { return; @@ -805,7 +808,8 @@ void Filler::addBlockUser() { if (!user || user->isInaccessible() || user->isSelf() - || user->isRepliesChat()) { + || user->isRepliesChat() + || user->isVerifyCodes()) { return; } const auto window = &_controller->window(); @@ -1227,6 +1231,7 @@ void Filler::addGiftPremium() { || user->isNotificationsUser() || !user->canReceiveGifts() || user->isRepliesChat() + || user->isVerifyCodes() || !user->session().premiumCanBuy()) { return; }