diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index e8f34931c..13cc7d2aa 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -42,6 +42,8 @@ class CloudImageView; int PeerColorIndex(PeerId peerId); int PeerColorIndex(BareId bareId); style::color PeerUserpicColor(PeerId peerId); + +// Must be used only for PeerColor-s. PeerId FakePeerIdForJustName(const QString &name); class RestrictionCheckResult { diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.cpp b/Telegram/SourceFiles/data/data_sponsored_messages.cpp index 6ef468191..c095c1220 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/data_sponsored_messages.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_text_entities.h" #include "apiwrap.h" #include "base/unixtime.h" +#include "data/data_user.h" #include "data/data_channel.h" #include "data/data_peer_id.h" #include "data/data_session.h" @@ -71,23 +72,10 @@ bool SponsoredMessages::append(not_null history) { return false; } - const auto flags = MessageFlags(0) - | (history->peer->isChannel() ? MessageFlag::Post : MessageFlags(0)) - | MessageFlag::HasFromId - | MessageFlag::IsSponsored - | MessageFlag::Local; - auto local = history->addNewLocalMessage( + entryIt->item.reset(history->addNewLocalMessage( _session->data().nextLocalMessageId(), - flags, - UserId(0), - MsgId(0), - HistoryItem::NewMessageDate(0), - entryIt->sponsored.fromId, - QString(), - entryIt->sponsored.textWithEntities, - MTP_messageMediaEmpty(), - HistoryMessageMarkupData()); - entryIt->item.reset(std::move(local)); + entryIt->sponsored.from, + entryIt->sponsored.textWithEntities)); return true; } @@ -163,36 +151,49 @@ void SponsoredMessages::append( }); const auto randomId = data.vrandom_id().v; const auto hash = qs(data.vchat_invite_hash().value_or_empty()); - const auto fromId = [&] { + const auto makeFrom = [](not_null peer) { + const auto channel = peer->asChannel(); + return SponsoredFrom{ + .peer = peer, + .title = peer->name, + .isBroadcast = (channel && channel->isBroadcast()), + .isMegagroup = (channel && channel->isMegagroup()), + .isChannel = (channel != nullptr), + .isPublic = (channel && channel->isPublic()), + .isBot = (peer->isUser() && peer->asUser()->isBot()), + }; + }; + const auto from = [&]() -> SponsoredFrom { if (data.vfrom_id()) { - return peerFromMTP(*data.vfrom_id()); + return makeFrom( + _session->data().peer(peerFromMTP(*data.vfrom_id()))); } Assert(data.vchat_invite()); return data.vchat_invite()->match([](const MTPDchatInvite &data) { - return Data::FakePeerIdForJustName(qs(data.vtitle())); + return SponsoredFrom{ + .title = qs(data.vtitle()), + .isBroadcast = data.is_broadcast(), + .isMegagroup = data.is_megagroup(), + .isChannel = data.is_channel(), + .isPublic = data.is_public(), + }; }, [&](const MTPDchatInviteAlready &data) { const auto chat = _session->data().processChat(data.vchat()); - if (!chat) { - return PeerId(0); - } if (const auto channel = chat->asChannel()) { channel->clearInvitePeek(); } - return chat->id; + return makeFrom(chat); }, [&](const MTPDchatInvitePeek &data) { const auto chat = _session->data().processChat(data.vchat()); - if (!chat) { - return PeerId(0); - } if (const auto channel = chat->asChannel()) { channel->setInvitePeek(hash, data.vexpires().v); } - return chat->id; + return makeFrom(chat); }); }(); auto sharedMessage = SponsoredMessage{ .randomId = randomId, - .fromId = fromId, + .from = from, .textWithEntities = { .text = qs(data.vmessage()), .entities = Api::EntitiesFromMTP( @@ -263,17 +264,17 @@ void SponsoredMessages::view(const FullMsgId &fullId) { }).send(); } -SponsoredMessages::ChannelPost SponsoredMessages::channelPost( +SponsoredMessages::Details SponsoredMessages::lookupDetails( const FullMsgId &fullId) const { const auto entryPtr = find(fullId); if (!entryPtr) { - return { .msgId = ShowAtUnreadMsgId, .hash = std::nullopt }; + return {}; } - const auto msgId = entryPtr->sponsored.msgId; - const auto hash = entryPtr->sponsored.chatInviteHash; + const auto &hash = entryPtr->sponsored.chatInviteHash; return { - .msgId = msgId ? msgId : ShowAtUnreadMsgId, .hash = hash.isEmpty() ? std::nullopt : std::make_optional(hash), + .peer = entryPtr->sponsored.from.peer, + .msgId = entryPtr->sponsored.msgId, }; } diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.h b/Telegram/SourceFiles/data/data_sponsored_messages.h index 90c2a4ef0..5e3109feb 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.h +++ b/Telegram/SourceFiles/data/data_sponsored_messages.h @@ -20,9 +20,19 @@ namespace Data { class Session; -struct SponsoredMessage final { +struct SponsoredFrom { + PeerData *peer = nullptr; + QString title; + bool isBroadcast = false; + bool isMegagroup = false; + bool isChannel = false; + bool isPublic = false; + bool isBot = false; +}; + +struct SponsoredMessage { QByteArray randomId; - PeerId fromId; + SponsoredFrom from; TextWithEntities textWithEntities; History *history = nullptr; MsgId msgId; @@ -31,9 +41,10 @@ struct SponsoredMessage final { class SponsoredMessages final { public: - struct ChannelPost { - MsgId msgId; + struct Details { std::optional hash; + PeerData *peer = nullptr; + MsgId msgId; }; using RandomId = QByteArray; explicit SponsoredMessages(not_null owner); @@ -45,7 +56,7 @@ public: void request(not_null history); [[nodiscard]] bool append(not_null history); void clearItems(not_null history); - [[nodiscard]] ChannelPost channelPost(const FullMsgId &fullId) const; + [[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const; void view(const FullMsgId &fullId); diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 4c3c5629d..77e42ae9a 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -280,9 +280,6 @@ enum class MessageFlag : uint32 { // Contact sign-up message, notification should be skipped for Silent. IsContactSignUp = (1U << 30), - - // In channels. - IsSponsored = (1U << 31), }; inline constexpr bool is_flag_type(MessageFlag) { return true; } using MessageFlags = base::flags; diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index b951587ee..614ebac0c 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_changes.h" #include "data/data_chat_filters.h" #include "data/data_scheduled_messages.h" +#include "data/data_sponsored_messages.h" #include "data/data_send_action.h" #include "data/data_folder.h" #include "data/data_photo.h" @@ -673,6 +674,18 @@ not_null History::addNewLocalMessage( true); } +not_null History::addNewLocalMessage( + MsgId id, + Data::SponsoredFrom from, + const TextWithEntities &textWithEntities) { + return addNewItem( + makeMessage( + id, + from, + textWithEntities), + true); +} + void History::setUnreadMentionsCount(int count) { const auto had = _unreadMentionsCount && (*_unreadMentionsCount > 0); if (_unreadMentions.size() > count) { diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index a3f4178c7..f70d0ba79 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -35,6 +35,7 @@ struct Draft; class Session; class Folder; class ChatFilter; +struct SponsoredFrom; enum class ForwardOptions { PreserveInfo, @@ -190,6 +191,10 @@ public: const QString &postAuthor, not_null game, HistoryMessageMarkupData &&markup); + not_null addNewLocalMessage( + MsgId id, + Data::SponsoredFrom from, + const TextWithEntities &textWithEntities); // sponsored // Used only internally and for channel admin log. not_null createItem( diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 37a6aef07..adc27e192 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -896,7 +896,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) { userpicTop, width(), st::msgPhotoSize); - } else if (const auto info = view->data()->hiddenForwardedInfo()) { + } else if (const auto info = view->data()->hiddenSenderInfo()) { info->userpic.paint( p, st::historyPhotoLeft, diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index d85a8641f..31e866ffa 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -45,6 +45,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_chat.h" #include "data/data_user.h" +#include "data/data_sponsored_messages.h" #include "styles/style_dialogs.h" #include "styles/style_chat.h" @@ -294,6 +295,10 @@ HistoryItem *HistoryItem::lookupDiscussionPostOriginal() const { PeerData *HistoryItem::displayFrom() const { if (const auto sender = discussionPostOriginalSender()) { return sender; + } else if (const auto sponsored = Get()) { + if (sponsored->sender) { + return nullptr; + } } else if (const auto forwarded = Get()) { if (history()->peer->isSelf() || history()->peer->isRepliesChat() || forwarded->imported) { return forwarded->originalSender; @@ -484,7 +489,7 @@ bool HistoryItem::isScheduled() const { } bool HistoryItem::isSponsored() const { - return (_flags & MessageFlag::IsSponsored); + return Has(); } bool HistoryItem::skipNotification() const { @@ -900,8 +905,10 @@ PeerData *HistoryItem::senderOriginal() const { return (peer->isChannel() && !peer->isMegagroup()) ? peer : from(); } -const HiddenSenderInfo *HistoryItem::hiddenForwardedInfo() const { - if (const auto forwarded = Get()) { +const HiddenSenderInfo *HistoryItem::hiddenSenderInfo() const { + if (const auto sponsored = Get()) { + return sponsored->sender.get(); + } else if (const auto forwarded = Get()) { return forwarded->hiddenSenderInfo.get(); } return nullptr; @@ -1118,6 +1125,8 @@ ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const { const auto sender = [&]() -> std::optional { if (options.hideSender || isPost() || isEmpty()) { return {}; + } else if (const auto sponsored = Get()) { + return sponsored->sender->name; } else if (!_history->peer->isUser()) { if (const auto from = displayFrom()) { return fromSender(from); diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index a2f447be1..dae4f898d 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -387,7 +387,7 @@ public: [[nodiscard]] TimeId dateOriginal() const; [[nodiscard]] PeerData *senderOriginal() const; - [[nodiscard]] const HiddenSenderInfo *hiddenForwardedInfo() const; + [[nodiscard]] const HiddenSenderInfo *hiddenSenderInfo() const; [[nodiscard]] not_null fromOriginal() const; [[nodiscard]] QString authorOriginal() const; [[nodiscard]] MsgId idOriginal() const; diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index bf0ed95f6..87021780b 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -102,6 +102,17 @@ struct HistoryMessageForwarded : public RuntimeComponent { + enum class Type : uchar { + User, + Group, + Broadcast, + Bot, + }; + std::unique_ptr sender; + Type type = Type::User; +}; + struct HistoryMessageReply : public RuntimeComponent { HistoryMessageReply() = default; HistoryMessageReply(const HistoryMessageReply &other) = delete; diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 9063207bc..0634657eb 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_histories.h" #include "data/data_web_page.h" +#include "data/data_sponsored_messages.h" #include "styles/style_dialogs.h" #include "styles/style_widgets.h" #include "styles/style_chat.h" @@ -582,7 +583,7 @@ HistoryMessage::HistoryMessage( && (!originalMedia || !originalMedia->forceForwardedInfo())); if (!dropForwardInfo) { config.originalDate = original->dateOriginal(); - if (const auto info = original->hiddenForwardedInfo()) { + if (const auto info = original->hiddenSenderInfo()) { config.senderNameOriginal = info->name; } else if (const auto senderOriginal = original->senderOriginal()) { config.senderOriginal = senderOriginal->id; @@ -768,6 +769,29 @@ HistoryMessage::HistoryMessage( setEmptyText(); } +HistoryMessage::HistoryMessage( + not_null history, + MsgId id, + Data::SponsoredFrom from, + const TextWithEntities &textWithEntities) +: HistoryItem( + history, + id, + ((history->peer->isChannel() ? MessageFlag::Post : MessageFlag(0)) + //| (from.peer ? MessageFlag::HasFromId : MessageFlag(0)) + | MessageFlag::Local), + HistoryItem::NewMessageDate(0), + /*from.peer ? from.peer->id : */PeerId(0)) { + createComponentsHelper( + _flags, + MsgId(0), // replyTo + UserId(0), // viaBotId + QString(), // postAuthor + HistoryMessageMarkupData()); + setText(textWithEntities); + setSponsoredFrom(from); +} + void HistoryMessage::createComponentsHelper( MessageFlags flags, MsgId replyTo, @@ -1915,6 +1939,23 @@ void HistoryMessage::setUnreadRepliesCount( Data::MessageUpdate::Flag::RepliesUnreadCount); } +void HistoryMessage::setSponsoredFrom(const Data::SponsoredFrom &from) { + AddComponents(HistoryMessageSponsored::Bit()); + const auto sponsored = Get(); + sponsored->sender = std::make_unique( + from.title, + false); + + using Type = HistoryMessageSponsored::Type; + sponsored->type = from.isBot + ? Type::Bot + : from.isBroadcast + ? Type::Broadcast + : (from.peer && from.peer->isUser()) + ? Type::User + : Type::Group; +} + void HistoryMessage::setReplyToTop(MsgId replyToTop) { const auto reply = Get(); if (!reply diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index 3cf8c8ec4..eb02f0906 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -14,6 +14,10 @@ struct SendAction; struct SendOptions; } // namespace Api +namespace Data { +struct SponsoredFrom; +} // namespace Data + namespace HistoryView { class Message; } // namespace HistoryView @@ -115,6 +119,11 @@ public: const QString &postAuthor, not_null game, HistoryMessageMarkupData &&markup); // local game + HistoryMessage( + not_null history, + MsgId id, + Data::SponsoredFrom from, + const TextWithEntities &textWithEntities); // sponsored void refreshMedia(const MTPMessageMedia *media); void refreshSentMedia(const MTPMessageMedia *media); @@ -251,6 +260,7 @@ private: void setUnreadRepliesCount( not_null views, int count); + void setSponsoredFrom(const Data::SponsoredFrom &from); static void FillForwardedInfo( CreateConfig &config, diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 8a6dcd112..f3d85ffff 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -7006,7 +7006,7 @@ void HistoryWidget::updateForwardingTexts() { fullname = from->name; } version += from->nameVersion; - } else if (const auto info = item->hiddenForwardedInfo()) { + } else if (const auto info = item->hiddenSenderInfo()) { if (!insertedNames.contains(info->name)) { insertedNames.emplace(info->name); names.push_back(info->firstName); @@ -7058,7 +7058,7 @@ void HistoryWidget::checkForwardingInfo() { for (const auto item : _toForward.items) { if (const auto from = item->senderOriginal()) { version += from->nameVersion; - } else if (const auto info = item->hiddenForwardedInfo()) { + } else if (const auto info = item->hiddenSenderInfo()) { ++version; } else { Unexpected("Corrupt forwarded information in message."); diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index a188b342c..97058d6c4 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -45,7 +45,7 @@ namespace { // A new message from the same sender is attached to previous within 15 minutes. constexpr int kAttachMessageToPreviousSecondsDelta = 900; -bool IsAttachedToPreviousInSavedMessages( +[[nodiscard]] bool IsAttachedToPreviousInSavedMessages( not_null previous, HistoryMessageForwarded *prevForwarded, not_null item, @@ -65,6 +65,22 @@ bool IsAttachedToPreviousInSavedMessages( return (*previousInfo == *itemInfo); } +[[nodiscard]] Window::SessionController *ContextOrSessionWindow( + const ClickHandlerContext &context, + not_null session) { + if (const auto controller = context.sessionWindow.get()) { + return controller; + } + const auto &windows = session->windows(); + if (windows.empty()) { + session->domain().activate(&session->account()); + if (windows.empty()) { + return nullptr; + } + } + return windows.front(); +} + } // namespace std::unique_ptr MakePathShiftGradient( @@ -599,7 +615,26 @@ ClickHandlerPtr Element::fromLink() const { return _fromLink; } const auto item = data(); - if (const auto from = item->displayFrom()) { + if (item->isSponsored()) { + const auto session = &item->history()->session(); + _fromLink = std::make_shared([=]( + ClickContext context) { + if (context.button != Qt::LeftButton) { + return; + } + const auto my = context.other.value(); + if (const auto window = ContextOrSessionWindow(my, session)) { + auto &sponsored = session->data().sponsoredMessages(); + const auto details = sponsored.lookupDetails(my.itemId); + if (const auto &hash = details.hash) { + Api::CheckChatInvite(window, *hash); + } else if (const auto peer = details.peer) { + window->showPeerInfo(peer); + } + } + }); + return _fromLink; + } else if (const auto from = item->displayFrom()) { _fromLink = std::make_shared([=]( ClickContext context) { if (context.button != Qt::LeftButton) { @@ -607,29 +642,8 @@ ClickHandlerPtr Element::fromLink() const { } const auto my = context.other.value(); const auto session = &from->session(); - const auto window = [&]() -> Window::SessionController* { - if (const auto controller = my.sessionWindow.get()) { - return controller; - } - const auto &windows = session->windows(); - if (windows.empty()) { - session->domain().activate(&session->account()); - if (windows.empty()) { - return nullptr; - } - } - return windows.front(); - }(); - if (window) { - const auto inviteHash = item->isSponsored() - ? session->data().sponsoredMessages().channelPost( - my.itemId).hash - : std::nullopt; - if (inviteHash) { - Api::CheckChatInvite(window, *inviteHash); - } else { - window->showPeerInfo(from); - } + if (const auto window = ContextOrSessionWindow(my, session)) { + window->showPeerInfo(from); } }); _fromLink->setProperty(kPeerLinkPeerIdProperty, from->id.value); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 29e2bdbe9..3cfb449ee 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1753,7 +1753,7 @@ void ListWidget::paintEvent(QPaintEvent *e) { userpicTop, view->width(), st::msgPhotoSize); - } else if (const auto info = view->data()->hiddenForwardedInfo()) { + } else if (const auto info = view->data()->hiddenSenderInfo()) { info->userpic.paint( p, st::historyPhotoLeft, diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index d00c33b29..151a2ab96 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_channel.h" #include "data/data_message_reactions.h" +#include "data/data_sponsored_messages.h" #include "lang/lang_keys.h" #include "mainwidget.h" #include "main/main_session.h" @@ -415,7 +416,7 @@ QSize Message::performCountOptimalSize() { const auto from = item->displayFrom(); const auto &name = from ? from->nameText() - : item->hiddenForwardedInfo()->nameText; + : item->hiddenSenderInfo()->nameText; auto namew = st::msgPadding.left() + name.maxWidth() + st::msgPadding.right(); @@ -935,17 +936,19 @@ void Message::paintFromName( const auto nameText = [&]() -> const Ui::Text::String * { const auto from = item->displayFrom(); - if (context.outbg || item->isPost()) { - p.setPen(stm->msgServiceFg); + const auto service = (context.outbg || item->isPost()); + if (from) { + p.setPen(service + ? stm->msgServiceFg + : FromNameFg(context, from->id)); return &from->nameText(); - } else if (from) { - p.setPen(FromNameFg(context, from->id)); - return &from->nameText(); - } else if (const auto info = item->hiddenForwardedInfo()) { - p.setPen(FromNameFg(context, info->colorPeerId)); + } else if (const auto info = item->hiddenSenderInfo()) { + p.setPen(service + ? stm->msgServiceFg + : FromNameFg(context, info->colorPeerId)); return &info->nameText; } else { - Unexpected("Corrupt forwarded information in message."); + Unexpected("Corrupt sender information in message."); } }(); nameText->drawElided(p, availableLeft, trect.top(), availableWidth); @@ -1524,7 +1527,7 @@ bool Message::getStateFromName( const auto nameText = [&]() -> const Ui::Text::String * { if (from) { return &from->nameText(); - } else if (const auto info = item->hiddenForwardedInfo()) { + } else if (const auto info = item->hiddenSenderInfo()) { return &info->nameText; } else { Unexpected("Corrupt forwarded information in message."); @@ -2076,14 +2079,11 @@ int Message::viewButtonHeight() const { } void Message::updateViewButtonExistence() { - const auto has = [&] { - const auto item = data(); - if (item->isSponsored()) { - return true; - } - const auto media = item->media(); - return media && ViewButton::MediaHasViewButton(media); - }(); + const auto item = data(); + const auto sponsored = item->Get(); + const auto media = sponsored ? nullptr : item->media(); + const auto has = sponsored + || (media && ViewButton::MediaHasViewButton(media)); if (!has) { _viewButton = nullptr; return; @@ -2091,13 +2091,9 @@ void Message::updateViewButtonExistence() { return; } auto callback = [=] { history()->owner().requestViewRepaint(this); }; - _viewButton = data()->isSponsored() - ? std::make_unique( - data()->displayFrom(), - std::move(callback)) - : std::make_unique( - data()->media(), - std::move(callback)); + _viewButton = sponsored + ? std::make_unique(sponsored, std::move(callback)) + : std::make_unique(media, std::move(callback)); } void Message::initLogEntryOriginal() { @@ -2572,7 +2568,7 @@ void Message::fromNameUpdated(int width) const { const auto nameText = [&]() -> const Ui::Text::String * { if (from) { return &from->nameText(); - } else if (const auto info = item->hiddenForwardedInfo()) { + } else if (const auto info = item->hiddenSenderInfo()) { return &info->nameText; } else { Unexpected("Corrupted forwarded information in message."); diff --git a/Telegram/SourceFiles/history/view/history_view_view_button.cpp b/Telegram/SourceFiles/history/view/history_view_view_button.cpp index 3fd4f8a42..783b0878c 100644 --- a/Telegram/SourceFiles/history/view/history_view_view_button.cpp +++ b/Telegram/SourceFiles/history/view/history_view_view_button.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_sponsored_messages.h" #include "data/data_user.h" #include "data/data_web_page.h" +#include "history/history_item_components.h" #include "history/view/history_view_cursor_state.h" #include "lang/lang_keys.h" #include "main/main_session.h" @@ -30,20 +31,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace HistoryView { namespace { -inline auto PeerToPhrase(not_null peer) { +using SponsoredType = HistoryMessageSponsored::Type; + +inline auto SponsoredPhrase(SponsoredType type) { const auto phrase = [&] { - if (const auto user = peer->asUser()) { - return user->isBot() - ? tr::lng_view_button_bot - : tr::lng_view_button_user; - } else if (peer->isChat()) { - return tr::lng_view_button_group; - } else if (peer->isChannel()) { - return tr::lng_view_button_channel; + switch (type) { + case SponsoredType::Bot: return tr::lng_view_button_bot; + case SponsoredType::Group: return tr::lng_view_button_group; + case SponsoredType::Broadcast: return tr::lng_view_button_channel; + case SponsoredType::User: return tr::lng_view_button_user; } - Unexpected("Invalid peer in ViewButton."); - }()(tr::now); - return Ui::Text::Upper(phrase); + Unexpected("SponsoredType in SponsoredPhrase."); + }(); + return Ui::Text::Upper(phrase(tr::now)); } inline auto WebPageToPhrase(not_null webpage) { @@ -75,8 +75,11 @@ inline auto WebPageToPhrase(not_null webpage) { } // namespace struct ViewButton::Inner { - Inner(not_null peer, Fn updateCallback); + Inner( + not_null sponsored, + Fn updateCallback); Inner(not_null media, Fn updateCallback); + void updateMask(int height); void toggleRipple(bool pressed); @@ -114,22 +117,28 @@ bool ViewButton::MediaHasViewButton( && webpage->document->isWallPaper()); } -ViewButton::Inner::Inner(not_null peer, Fn updateCallback) +ViewButton::Inner::Inner( + not_null sponsored, + Fn updateCallback) : margins(st::historyViewButtonMargins) , link(std::make_shared([=](ClickContext context) { const auto my = context.other.value(); if (const auto controller = my.sessionWindow.get()) { const auto &data = controller->session().data(); - const auto link = data.sponsoredMessages().channelPost(my.itemId); - if (link.hash) { - Api::CheckChatInvite(controller, *link.hash); - } else { - controller->showPeer(peer, link.msgId); + const auto itemId = my.itemId; + const auto details = data.sponsoredMessages().lookupDetails(itemId); + if (details.hash) { + Api::CheckChatInvite(controller, *details.hash); + } else if (details.peer) { + controller->showPeerHistory( + details.peer, + Window::SectionShow::Way::Forward, + details.msgId); } } })) , updateCallback(std::move(updateCallback)) -, text(st::historyViewButtonTextStyle, PeerToPhrase(peer)) { +, text(st::historyViewButtonTextStyle, SponsoredPhrase(sponsored->type)) { } ViewButton::Inner::Inner( @@ -170,8 +179,10 @@ void ViewButton::Inner::toggleRipple(bool pressed) { } } -ViewButton::ViewButton(not_null peer, Fn updateCallback) -: _inner(std::make_unique(peer, std::move(updateCallback))) { +ViewButton::ViewButton( + not_null sponsored, + Fn updateCallback) +: _inner(std::make_unique(sponsored, std::move(updateCallback))) { } ViewButton::ViewButton( diff --git a/Telegram/SourceFiles/history/view/history_view_view_button.h b/Telegram/SourceFiles/history/view/history_view_view_button.h index f49ae2ab2..d9b45b7f8 100644 --- a/Telegram/SourceFiles/history/view/history_view_view_button.h +++ b/Telegram/SourceFiles/history/view/history_view_view_button.h @@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/chat_style.h" +struct HistoryMessageSponsored; + namespace Data { class Media; } // namespace Data @@ -21,7 +23,9 @@ struct TextState; class ViewButton { public: - ViewButton(not_null peer, Fn updateCallback); + ViewButton( + not_null sponsored, + Fn updateCallback); ViewButton(not_null media, Fn updateCallback); ~ViewButton(); diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index a63f49839..8e343df24 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -2130,7 +2130,7 @@ void OverlayWidget::refreshMediaViewer() { void OverlayWidget::refreshFromLabel() { if (_message) { _from = _message->senderOriginal(); - if (const auto info = _message->hiddenForwardedInfo()) { + if (const auto info = _message->hiddenSenderInfo()) { _fromName = info->name; } else { Assert(_from != nullptr);