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;
}
std::shared_ptr<CloudImageView> CloudImage::activeView() {
std::shared_ptr<CloudImageView> CloudImage::activeView() const {
return _view.lock();
}

View file

@ -80,7 +80,7 @@ public:
[[nodiscard]] int byteSize() const;
[[nodiscard]] std::shared_ptr<CloudImageView> createView();
[[nodiscard]] std::shared_ptr<CloudImageView> activeView();
[[nodiscard]] std::shared_ptr<CloudImageView> activeView() const;
[[nodiscard]] bool isCurrentView(
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 "history/history.h"
#include "main/main_session.h"
#include "ui/image/image_location_factory.h"
namespace Data {
namespace {
@ -164,6 +165,7 @@ void SponsoredMessages::append(
.isPublic = (channel && channel->isPublic()),
.isBot = (peer->isUser() && peer->asUser()->isBot()),
.isExactPost = exactPost,
.userpic = { .location = peer->userpicLocation() },
};
};
const auto from = [&]() -> SponsoredFrom {
@ -173,13 +175,28 @@ void SponsoredMessages::append(
(data.vchannel_post() != nullptr));
}
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{
.title = qs(data.vtitle()),
.isBroadcast = data.is_broadcast(),
.isMegagroup = data.is_megagroup(),
.isChannel = data.is_channel(),
.isPublic = data.is_public(),
.userpic = std::move(userpic),
};
}, [&](const MTPDchatInviteAlready &data) {
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 "base/timer.h"
#include "ui/image/image_location.h"
class History;
@ -29,6 +30,7 @@ struct SponsoredFrom {
bool isPublic = false;
bool isBot = false;
bool isExactPost = false;
ImageWithLocation userpic;
};
struct SponsoredMessage {

View file

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

View file

@ -1075,12 +1075,29 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
width(),
st::msgPhotoSize);
} else if (const auto info = view->data()->hiddenSenderInfo()) {
info->userpic.paint(
p,
st::historyPhotoLeft,
userpicTop,
width(),
st::msgPhotoSize);
if (info->customUserpic.empty()) {
info->emptyUserpic.paint(
p,
st::historyPhotoLeft,
userpicTop,
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 {
Unexpected("Corrupt forwarded information in message.");
}

View file

@ -428,6 +428,9 @@ private:
base::flat_map<
not_null<PeerData*>,
std::shared_ptr<Data::CloudImageView>> _userpics, _userpicsCache;
base::flat_map<
MsgId,
std::shared_ptr<Data::CloudImageView>> _sponsoredUserpics;
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)
: name(name)
, colorPeerId(Data::FakePeerIdForJustName(name))
, userpic(
, emptyUserpic(
Data::PeerUserpicColor(colorPeerId),
(external
? 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 {
auto phrase = TextWithEntities();
const auto fromChannel = originalSender

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "data/data_cloud_file.h"
#include "history/history_item.h"
#include "ui/empty_userpic.h"
#include "ui/effects/animations.h"
@ -75,8 +76,16 @@ struct HiddenSenderInfo {
QString firstName;
QString lastName;
PeerId colorPeerId = 0;
Ui::EmptyUserpic userpic;
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 {
return name == other.name;

View file

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

View file

@ -636,7 +636,8 @@ ClickHandlerPtr Element::fromLink() const {
const auto my = context.other.value<ClickHandlerContext>();
if (const auto window = ContextOrSessionWindow(my, session)) {
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) {
Api::CheckChatInvite(window, *hash);
} else if (const auto peer = details.peer) {

View file

@ -1812,12 +1812,29 @@ void ListWidget::paintEvent(QPaintEvent *e) {
view->width(),
st::msgPhotoSize);
} else if (const auto info = view->data()->hiddenSenderInfo()) {
info->userpic.paint(
p,
st::historyPhotoLeft,
userpicTop,
view->width(),
st::msgPhotoSize);
if (info->customUserpic.empty()) {
info->emptyUserpic.paint(
p,
st::historyPhotoLeft,
userpicTop,
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 {
Unexpected("Corrupt forwarded information in message.");
}

View file

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

View file

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