Support external links sponsored messages.

This commit is contained in:
John Preston 2023-06-23 19:36:40 +04:00
parent 859636ff9c
commit 7ad5520b82
6 changed files with 62 additions and 18 deletions

View file

@ -3707,6 +3707,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_view_button_voice_chat" = "Voice chat"; "lng_view_button_voice_chat" = "Voice chat";
"lng_view_button_voice_chat_channel" = "Live stream"; "lng_view_button_voice_chat_channel" = "Live stream";
"lng_view_button_request_join" = "Request to Join"; "lng_view_button_request_join" = "Request to Join";
"lng_view_button_external_link" = "Open link";
"lng_sponsored_hide_ads" = "Hide"; "lng_sponsored_hide_ads" = "Hide";
"lng_sponsored_title" = "What are sponsored messages?"; "lng_sponsored_title" = "What are sponsored messages?";

View file

@ -270,28 +270,45 @@ void SponsoredMessages::append(
.isForceUserpicDisplay = data.is_show_peer_photo(), .isForceUserpicDisplay = data.is_show_peer_photo(),
}; };
}; };
const auto externalLink = data.vwebpage()
? qs(data.vwebpage()->data().vurl())
: QString();
const auto userpicFromPhoto = [&](const MTPphoto &photo) {
return photo.match([&](const MTPDphoto &data) {
for (const auto &size : data.vsizes().v) {
const auto result = Images::FromPhotoSize(
_session,
data,
size);
if (result.location.valid()) {
return result;
}
}
return ImageWithLocation{};
}, [](const MTPDphotoEmpty &) {
return ImageWithLocation{};
});
};
const auto from = [&]() -> SponsoredFrom { const auto from = [&]() -> SponsoredFrom {
if (data.vfrom_id()) { if (const auto webpage = data.vwebpage()) {
const auto &data = webpage->data();
auto userpic = data.vphoto()
? userpicFromPhoto(*data.vphoto())
: ImageWithLocation{};
return SponsoredFrom{
.title = qs(data.vsite_name()),
.isExternalLink = true,
.userpic = std::move(userpic),
.isForceUserpicDisplay = message.data().is_show_peer_photo(),
};
} else if (const auto fromId = data.vfrom_id()) {
return makeFrom( return makeFrom(
_session->data().peer(peerFromMTP(*data.vfrom_id())), _session->data().peer(peerFromMTP(*fromId)),
(data.vchannel_post() != nullptr)); (data.vchannel_post() != nullptr));
} }
Assert(data.vchat_invite()); Assert(data.vchat_invite());
return data.vchat_invite()->match([&](const MTPDchatInvite &data) { return data.vchat_invite()->match([&](const MTPDchatInvite &data) {
auto userpic = data.vphoto().match([&](const MTPDphoto &data) { auto userpic = userpicFromPhoto(data.vphoto());
for (const auto &size : data.vsizes().v) {
const auto result = Images::FromPhotoSize(
_session,
data,
size);
if (result.location.valid()) {
return result;
}
}
return ImageWithLocation{};
}, [](const MTPDphotoEmpty &) {
return ImageWithLocation{};
});
return SponsoredFrom{ return SponsoredFrom{
.title = qs(data.vtitle()), .title = qs(data.vtitle()),
.isBroadcast = data.is_broadcast(), .isBroadcast = data.is_broadcast(),
@ -336,6 +353,7 @@ void SponsoredMessages::append(
.history = history, .history = history,
.msgId = data.vchannel_post().value_or_empty(), .msgId = data.vchannel_post().value_or_empty(),
.chatInviteHash = hash, .chatInviteHash = hash,
.externalLink = externalLink,
.sponsorInfo = std::move(sponsorInfo), .sponsorInfo = std::move(sponsorInfo),
.additionalInfo = std::move(additionalInfo), .additionalInfo = std::move(additionalInfo),
}; };
@ -423,6 +441,7 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails(
.peer = data.from.peer, .peer = data.from.peer,
.msgId = data.msgId, .msgId = data.msgId,
.info = std::move(info), .info = std::move(info),
.externalLink = data.externalLink,
}; };
} }

View file

@ -31,6 +31,7 @@ struct SponsoredFrom {
bool isBot = false; bool isBot = false;
bool isExactPost = false; bool isExactPost = false;
bool isRecommended = false; bool isRecommended = false;
bool isExternalLink = false;
ImageWithLocation userpic; ImageWithLocation userpic;
bool isForceUserpicDisplay = false; bool isForceUserpicDisplay = false;
}; };
@ -42,6 +43,7 @@ struct SponsoredMessage {
History *history = nullptr; History *history = nullptr;
MsgId msgId; MsgId msgId;
QString chatInviteHash; QString chatInviteHash;
QString externalLink;
TextWithEntities sponsorInfo; TextWithEntities sponsorInfo;
TextWithEntities additionalInfo; TextWithEntities additionalInfo;
}; };
@ -58,6 +60,7 @@ public:
PeerData *peer = nullptr; PeerData *peer = nullptr;
MsgId msgId; MsgId msgId;
std::vector<TextWithEntities> info; std::vector<TextWithEntities> info;
QString externalLink;
}; };
using RandomId = QByteArray; using RandomId = QByteArray;
explicit SponsoredMessages(not_null<Session*> owner); explicit SponsoredMessages(not_null<Session*> owner);

View file

@ -3201,7 +3201,9 @@ void HistoryItem::setSponsoredFrom(const Data::SponsoredFrom &from) {
} }
using Type = HistoryMessageSponsored::Type; using Type = HistoryMessageSponsored::Type;
sponsored->type = from.isExactPost sponsored->type = from.isExternalLink
? Type::ExternalLink
: from.isExactPost
? Type::Post ? Type::Post
: from.isBot : from.isBot
? Type::Bot ? Type::Bot

View file

@ -139,6 +139,7 @@ struct HistoryMessageSponsored : public RuntimeComponent<HistoryMessageSponsored
Broadcast, Broadcast,
Post, Post,
Bot, Bot,
ExternalLink,
}; };
std::unique_ptr<HiddenSenderInfo> sender; std::unique_ptr<HiddenSenderInfo> sender;
Type type = Type::User; Type type = Type::User;

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_chat_invite.h" #include "api/api_chat_invite.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "core/file_utilities.h"
#include "data/data_cloud_themes.h" #include "data/data_cloud_themes.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_sponsored_messages.h" #include "data/data_sponsored_messages.h"
@ -42,6 +43,8 @@ inline auto SponsoredPhrase(SponsoredType type) {
case SponsoredType::Broadcast: return tr::lng_view_button_channel; case SponsoredType::Broadcast: return tr::lng_view_button_channel;
case SponsoredType::Post: return tr::lng_view_button_message; case SponsoredType::Post: return tr::lng_view_button_message;
case SponsoredType::Bot: return tr::lng_view_button_bot; case SponsoredType::Bot: return tr::lng_view_button_bot;
case SponsoredType::ExternalLink:
return tr::lng_view_button_external_link;
} }
Unexpected("SponsoredType in SponsoredPhrase."); Unexpected("SponsoredType in SponsoredPhrase.");
}(); }();
@ -115,6 +118,7 @@ struct ViewButton::Inner {
const ClickHandlerPtr link; const ClickHandlerPtr link;
const Fn<void()> updateCallback; const Fn<void()> updateCallback;
bool belowInfo = true; bool belowInfo = true;
bool externalLink = false;
int lastWidth = 0; int lastWidth = 0;
QPoint lastPoint; QPoint lastPoint;
std::unique_ptr<Ui::RippleAnimation> ripple; std::unique_ptr<Ui::RippleAnimation> ripple;
@ -158,7 +162,9 @@ ViewButton::Inner::Inner(
const auto &data = controller->session().data(); const auto &data = controller->session().data();
const auto itemId = my.itemId; const auto itemId = my.itemId;
const auto details = data.sponsoredMessages().lookupDetails(itemId); const auto details = data.sponsoredMessages().lookupDetails(itemId);
if (details.hash) { if (!details.externalLink.isEmpty()) {
File::OpenUrl(details.externalLink);
} else if (details.hash) {
Api::CheckChatInvite(controller, *details.hash); Api::CheckChatInvite(controller, *details.hash);
} else if (details.peer) { } else if (details.peer) {
controller->showPeerHistory( controller->showPeerHistory(
@ -169,6 +175,7 @@ ViewButton::Inner::Inner(
} }
})) }))
, updateCallback(std::move(updateCallback)) , updateCallback(std::move(updateCallback))
, externalLink(sponsored->type == SponsoredType::ExternalLink)
, text(st::historyViewButtonTextStyle, SponsoredPhrase(sponsored->type)) { , text(st::historyViewButtonTextStyle, SponsoredPhrase(sponsored->type)) {
} }
@ -260,6 +267,17 @@ void ViewButton::draw(
r.width(), r.width(),
1, 1,
style::al_center); style::al_center);
if (_inner->externalLink) {
const auto &icon = st::msgBotKbUrlIcon;
const auto padding = st::msgBotKbIconPadding;
icon.paint(
p,
r.left() + r.width() - icon.width() - padding,
r.top() + padding,
r.width(),
stm->fwdTextPalette.linkFg->c);
}
} }
p.restore(); p.restore();
if (_inner->lastWidth != r.width()) { if (_inner->lastWidth != r.width()) {