Added userpics support to sponsored messages.

This commit is contained in:
23rd 2022-02-15 05:20:55 +03:00 committed by John Preston
parent 2e40798e8e
commit 4dee21c0e6
14 changed files with 117 additions and 21 deletions

View file

@ -146,7 +146,7 @@ std::shared_ptr<CloudImageView> CloudImage::createView() {
return view; return view;
} }
std::shared_ptr<CloudImageView> CloudImage::activeView() { std::shared_ptr<CloudImageView> CloudImage::activeView() const {
return _view.lock(); return _view.lock();
} }

View file

@ -80,7 +80,7 @@ public:
[[nodiscard]] int byteSize() const; [[nodiscard]] int byteSize() const;
[[nodiscard]] std::shared_ptr<CloudImageView> createView(); [[nodiscard]] std::shared_ptr<CloudImageView> createView();
[[nodiscard]] std::shared_ptr<CloudImageView> activeView(); [[nodiscard]] std::shared_ptr<CloudImageView> activeView() const;
[[nodiscard]] bool isCurrentView( [[nodiscard]] bool isCurrentView(
const std::shared_ptr<CloudImageView> &view) const; const std::shared_ptr<CloudImageView> &view) const;

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "history/history.h" #include "history/history.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "ui/image/image_location_factory.h"
namespace Data { namespace Data {
namespace { namespace {
@ -164,6 +165,7 @@ void SponsoredMessages::append(
.isPublic = (channel && channel->isPublic()), .isPublic = (channel && channel->isPublic()),
.isBot = (peer->isUser() && peer->asUser()->isBot()), .isBot = (peer->isUser() && peer->asUser()->isBot()),
.isExactPost = exactPost, .isExactPost = exactPost,
.userpic = { .location = peer->userpicLocation() },
}; };
}; };
const auto from = [&]() -> SponsoredFrom { const auto from = [&]() -> SponsoredFrom {
@ -173,13 +175,28 @@ void SponsoredMessages::append(
(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) {
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(),
.isMegagroup = data.is_megagroup(), .isMegagroup = data.is_megagroup(),
.isChannel = data.is_channel(), .isChannel = data.is_channel(),
.isPublic = data.is_public(), .isPublic = data.is_public(),
.userpic = std::move(userpic),
}; };
}, [&](const MTPDchatInviteAlready &data) { }, [&](const MTPDchatInviteAlready &data) {
const auto chat = _session->data().processChat(data.vchat()); const auto chat = _session->data().processChat(data.vchat());

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h" #include "history/history_item.h"
#include "base/timer.h" #include "base/timer.h"
#include "ui/image/image_location.h"
class History; class History;
@ -29,6 +30,7 @@ struct SponsoredFrom {
bool isPublic = false; bool isPublic = false;
bool isBot = false; bool isBot = false;
bool isExactPost = false; bool isExactPost = false;
ImageWithLocation userpic;
}; };
struct SponsoredMessage { struct SponsoredMessage {

View file

@ -365,7 +365,7 @@ void paintRow(
active, active,
fullWidth); fullWidth);
} else if (hiddenSenderInfo) { } else if (hiddenSenderInfo) {
hiddenSenderInfo->userpic.paint( hiddenSenderInfo->emptyUserpic.paint(
p, p,
st::dialogsPadding.x(), st::dialogsPadding.x(),
st::dialogsPadding.y(), st::dialogsPadding.y(),

View file

@ -1075,12 +1075,29 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
width(), width(),
st::msgPhotoSize); st::msgPhotoSize);
} else if (const auto info = view->data()->hiddenSenderInfo()) { } else if (const auto info = view->data()->hiddenSenderInfo()) {
info->userpic.paint( if (info->customUserpic.empty()) {
p, info->emptyUserpic.paint(
st::historyPhotoLeft, p,
userpicTop, st::historyPhotoLeft,
width(), userpicTop,
st::msgPhotoSize); width(),
st::msgPhotoSize);
} else {
const auto painted = info->paintCustomUserpic(
p,
st::historyPhotoLeft,
userpicTop,
width(),
st::msgPhotoSize);
if (!painted) {
const auto itemId = view->data()->fullId();
auto &v = _sponsoredUserpics[itemId.msg];
if (!info->customUserpic.isCurrentView(v)) {
v = info->customUserpic.createView();
info->customUserpic.load(&session(), itemId);
}
}
}
} else { } else {
Unexpected("Corrupt forwarded information in message."); Unexpected("Corrupt forwarded information in message.");
} }

View file

@ -428,6 +428,9 @@ private:
base::flat_map< base::flat_map<
not_null<PeerData*>, not_null<PeerData*>,
std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache; std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache;
base::flat_map<
MsgId,
std::shared_ptr<Data::CloudImageView>> _sponsoredUserpics;
std::unique_ptr<HistoryView::Reactions::Manager> _reactionsManager; std::unique_ptr<HistoryView::Reactions::Manager> _reactionsManager;

View file

@ -89,7 +89,7 @@ void HistoryMessageVia::resize(int32 availw) const {
HiddenSenderInfo::HiddenSenderInfo(const QString &name, bool external) HiddenSenderInfo::HiddenSenderInfo(const QString &name, bool external)
: name(name) : name(name)
, colorPeerId(Data::FakePeerIdForJustName(name)) , colorPeerId(Data::FakePeerIdForJustName(name))
, userpic( , emptyUserpic(
Data::PeerUserpicColor(colorPeerId), Data::PeerUserpicColor(colorPeerId),
(external (external
? Ui::EmptyUserpic::ExternalName() ? Ui::EmptyUserpic::ExternalName()
@ -107,6 +107,26 @@ HiddenSenderInfo::HiddenSenderInfo(const QString &name, bool external)
} }
} }
bool HiddenSenderInfo::paintCustomUserpic(
Painter &p,
int x,
int y,
int outerWidth,
int size) const {
const auto view = customUserpic.activeView();
if (const auto image = view ? view->image() : nullptr) {
const auto circled = Images::Option::RoundCircle;
p.drawPixmap(
x,
y,
image->pix(size, size, { .options = circled }));
return true;
} else {
emptyUserpic.paint(p, x, y, outerWidth, size);
return false;
}
}
void HistoryMessageForwarded::create(const HistoryMessageVia *via) const { void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
auto phrase = TextWithEntities(); auto phrase = TextWithEntities();
const auto fromChannel = originalSender const auto fromChannel = originalSender

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "data/data_cloud_file.h"
#include "history/history_item.h" #include "history/history_item.h"
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
@ -75,8 +76,16 @@ struct HiddenSenderInfo {
QString firstName; QString firstName;
QString lastName; QString lastName;
PeerId colorPeerId = 0; PeerId colorPeerId = 0;
Ui::EmptyUserpic userpic;
Ui::Text::String nameText; Ui::Text::String nameText;
Ui::EmptyUserpic emptyUserpic;
mutable Data::CloudImage customUserpic;
[[nodiscard]] bool paintCustomUserpic(
Painter &p,
int x,
int y,
int outerWidth,
int size) const;
inline bool operator==(const HiddenSenderInfo &other) const { inline bool operator==(const HiddenSenderInfo &other) const {
return name == other.name; return name == other.name;

View file

@ -1988,6 +1988,11 @@ void HistoryMessage::setSponsoredFrom(const Data::SponsoredFrom &from) {
sponsored->sender = std::make_unique<HiddenSenderInfo>( sponsored->sender = std::make_unique<HiddenSenderInfo>(
from.title, from.title,
false); false);
if (from.userpic.location.valid()) {
sponsored->sender->customUserpic.set(
&history()->session(),
from.userpic);
}
using Type = HistoryMessageSponsored::Type; using Type = HistoryMessageSponsored::Type;
sponsored->type = from.isExactPost sponsored->type = from.isExactPost

View file

@ -636,7 +636,8 @@ ClickHandlerPtr Element::fromLink() const {
const auto my = context.other.value<ClickHandlerContext>(); const auto my = context.other.value<ClickHandlerContext>();
if (const auto window = ContextOrSessionWindow(my, session)) { if (const auto window = ContextOrSessionWindow(my, session)) {
auto &sponsored = session->data().sponsoredMessages(); auto &sponsored = session->data().sponsoredMessages();
const auto details = sponsored.lookupDetails(my.itemId); const auto itemId = my.itemId ? my.itemId : item->fullId();
const auto details = sponsored.lookupDetails(itemId);
if (const auto &hash = details.hash) { if (const auto &hash = details.hash) {
Api::CheckChatInvite(window, *hash); Api::CheckChatInvite(window, *hash);
} else if (const auto peer = details.peer) { } else if (const auto peer = details.peer) {

View file

@ -1812,12 +1812,29 @@ void ListWidget::paintEvent(QPaintEvent *e) {
view->width(), view->width(),
st::msgPhotoSize); st::msgPhotoSize);
} else if (const auto info = view->data()->hiddenSenderInfo()) { } else if (const auto info = view->data()->hiddenSenderInfo()) {
info->userpic.paint( if (info->customUserpic.empty()) {
p, info->emptyUserpic.paint(
st::historyPhotoLeft, p,
userpicTop, st::historyPhotoLeft,
view->width(), userpicTop,
st::msgPhotoSize); view->width(),
st::msgPhotoSize);
} else {
const auto painted = info->paintCustomUserpic(
p,
st::historyPhotoLeft,
userpicTop,
view->width(),
st::msgPhotoSize);
if (!painted) {
const auto itemId = view->data()->fullId();
auto &v = _sponsoredUserpics[itemId.msg];
if (!info->customUserpic.isCurrentView(v)) {
v = info->customUserpic.createView();
info->customUserpic.load(&session(), itemId);
}
}
}
} else { } else {
Unexpected("Corrupt forwarded information in message."); Unexpected("Corrupt forwarded information in message.");
} }

View file

@ -564,6 +564,9 @@ private:
base::flat_map< base::flat_map<
not_null<PeerData*>, not_null<PeerData*>,
std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache; std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache;
base::flat_map<
MsgId,
std::shared_ptr<Data::CloudImageView>> _sponsoredUserpics;
const std::unique_ptr<Ui::PathShiftGradient> _pathGradient; const std::unique_ptr<Ui::PathShiftGradient> _pathGradient;

View file

@ -1390,8 +1390,10 @@ bool Message::hasFromPhoto() const {
case Context::Pinned: case Context::Pinned:
case Context::Replies: { case Context::Replies: {
const auto item = message(); const auto item = message();
if (item->isPost() if (item->isPost()) {
|| item->isEmpty() return item->isSponsored();
}
if (item->isEmpty()
|| (context() == Context::Replies && item->isDiscussionPost())) { || (context() == Context::Replies && item->isDiscussionPost())) {
return false; return false;
} else if (delegate()->elementIsChatWide()) { } else if (delegate()->elementIsChatWide()) {