mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added userpics support to sponsored messages.
This commit is contained in:
parent
2e40798e8e
commit
4dee21c0e6
14 changed files with 117 additions and 21 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue