Show background preview in service messages.

This commit is contained in:
John Preston 2023-04-14 13:52:49 +04:00
parent d0e8802b9d
commit 5cbf9a2dc4
11 changed files with 271 additions and 46 deletions

View File

@ -749,6 +749,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_background_link_copied" = "Link copied to clipboard";
"lng_background_blur" = "Blurred";
"lng_background_sure_delete" = "Are you sure you want to delete this background?";
"lng_background_other_info" = "{user} will be able to apply this wallpaper";
"lng_background_apply1" = "Apply the wallpaper in this chat.";
"lng_background_apply2" = "Enjoy the view.";
"lng_background_apply_button" = "Apply For This Chat";
"lng_download_path_ask" = "Ask download path for each file";
"lng_download_path" = "Download path";
@ -1539,10 +1543,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_suggested_video" = "{user} suggests you to use this profile video.";
"lng_action_suggested_video_button" = "View Video";
"lng_action_attach_menu_bot_allowed" = "You allowed this bot to message you when you added it in the attachment menu.";
"lng_action_set_wallpaper_me" = "You set a new background for this chat.";
"lng_action_set_wallpaper" = "{user} set a new background for this chat.";
"lng_action_set_same_wallpaper_me" = "You set the same background for this chat.";
"lng_action_set_same_wallpaper" = "{user} set the same background for this chat.";
"lng_action_set_wallpaper_me" = "You set a new wallpaper for this chat";
"lng_action_set_wallpaper" = "{user} set a new wallpaper for this chat";
"lng_action_set_wallpaper_button" = "View Wallpaper";
"lng_action_set_same_wallpaper_me" = "You set the same wallpaper for this chat";
"lng_action_set_same_wallpaper" = "{user} set the same wallpaper for this chat";
"lng_action_topic_created_inside" = "Topic created";
"lng_action_topic_closed_inside" = "Topic closed";
"lng_action_topic_reopened_inside" = "Topic reopened";

View File

@ -392,7 +392,7 @@ const Invoice *Media::invoice() const {
return nullptr;
}
Data::CloudImage *Media::location() const {
CloudImage *Media::location() const {
return nullptr;
}
@ -400,6 +400,10 @@ PollData *Media::poll() const {
return nullptr;
}
const WallPaper *Media::paper() const {
return nullptr;
}
bool Media::uploading() const {
return false;
}
@ -1238,7 +1242,7 @@ std::unique_ptr<Media> MediaLocation::clone(not_null<HistoryItem*> parent) {
_description);
}
Data::CloudImage *MediaLocation::location() const {
CloudImage *MediaLocation::location() const {
return _location;
}
@ -1827,7 +1831,7 @@ ClickHandlerPtr MediaDice::MakeHandler(
.durationMs = Ui::Toast::kDefaultDuration * 2,
.multiline = true,
};
if (Data::CanSend(history->peer, ChatRestriction::SendOther)) {
if (CanSend(history->peer, ChatRestriction::SendOther)) {
auto link = Ui::Text::Link(
tr::lng_about_random_send(tr::now).toUpper());
link.entities.push_back(
@ -1883,10 +1887,6 @@ int MediaGiftBox::months() const {
return _months;
}
bool MediaGiftBox::allowsRevoke(TimeId now) const {
return false;
}
TextWithEntities MediaGiftBox::notificationText() const {
return {};
}
@ -1899,10 +1899,6 @@ TextForMimeData MediaGiftBox::clipboardText() const {
return {};
}
bool MediaGiftBox::forceForwardedInfo() const {
return false;
}
bool MediaGiftBox::updateInlineResultMedia(const MTPMessageMedia &media) {
return false;
}
@ -1928,4 +1924,50 @@ void MediaGiftBox::setActivated(bool activated) {
_activated = activated;
}
MediaWallPaper::MediaWallPaper(
not_null<HistoryItem*> parent,
const WallPaper &paper)
: Media(parent)
, _paper(paper) {
}
MediaWallPaper::~MediaWallPaper() = default;
std::unique_ptr<Media> MediaWallPaper::clone(not_null<HistoryItem*> parent) {
return std::make_unique<MediaWallPaper>(parent, _paper);
}
const WallPaper *MediaWallPaper::paper() const {
return &_paper;
}
TextWithEntities MediaWallPaper::notificationText() const {
return {};
}
QString MediaWallPaper::pinnedTextSubstring() const {
return {};
}
TextForMimeData MediaWallPaper::clipboardText() const {
return {};
}
bool MediaWallPaper::updateInlineResultMedia(const MTPMessageMedia &media) {
return false;
}
bool MediaWallPaper::updateSentMedia(const MTPMessageMedia &media) {
return false;
}
std::unique_ptr<HistoryView::Media> MediaWallPaper::createView(
not_null<HistoryView::Element*> message,
not_null<HistoryItem*> realParent,
HistoryView::Element *replacing) {
return std::make_unique<HistoryView::ServiceBox>(
message,
std::make_unique<HistoryView::ThemeDocumentBox>(message, _paper));
}
} // namespace Data

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "data/data_location.h"
#include "data/data_wall_paper.h"
class Image;
class History;
@ -35,6 +36,7 @@ struct ToPreviewOptions;
namespace Data {
class CloudImage;
class WallPaper;
enum class CallFinishReason : char {
Missed,
@ -105,8 +107,9 @@ public:
virtual const Call *call() const;
virtual GameData *game() const;
virtual const Invoice *invoice() const;
virtual Data::CloudImage *location() const;
virtual CloudImage *location() const;
virtual PollData *poll() const;
virtual const WallPaper *paper() const;
virtual bool uploading() const;
virtual Storage::SharedMediaTypesMask sharedMediaTypes() const;
@ -291,7 +294,7 @@ public:
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
Data::CloudImage *location() const override;
CloudImage *location() const override;
ItemPreview toPreview(ToPreviewOptions options) const override;
TextWithEntities notificationText() const override;
QString pinnedTextSubstring() const override;
@ -306,7 +309,7 @@ public:
private:
LocationPoint _point;
not_null<Data::CloudImage*> _location;
not_null<CloudImage*> _location;
QString _title;
QString _description;
@ -517,11 +520,9 @@ public:
[[nodiscard]] bool activated() const;
void setActivated(bool activated);
bool allowsRevoke(TimeId now) const override;
TextWithEntities notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;
bool forceForwardedInfo() const override;
bool updateInlineResultMedia(const MTPMessageMedia &media) override;
bool updateSentMedia(const MTPMessageMedia &media) override;
@ -537,6 +538,31 @@ private:
};
class MediaWallPaper final : public Media {
public:
MediaWallPaper(not_null<HistoryItem*> parent, const WallPaper &paper);
~MediaWallPaper();
std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
const WallPaper *paper() const override;
TextWithEntities notificationText() const override;
QString pinnedTextSubstring() const override;
TextForMimeData clipboardText() const override;
bool updateInlineResultMedia(const MTPMessageMedia &media) override;
bool updateSentMedia(const MTPMessageMedia &media) override;
std::unique_ptr<HistoryView::Media> createView(
not_null<HistoryView::Element*> message,
not_null<HistoryItem*> realParent,
HistoryView::Element *replacing = nullptr) override;
private:
const WallPaper _paper;
};
[[nodiscard]] TextForMimeData WithCaptionClipboardText(
const QString &attachType,
TextForMimeData &&caption);

View File

@ -66,6 +66,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_group_call.h" // Data::GroupCall::id().
#include "data/data_poll.h" // PollData::publicVotes.
#include "data/data_sponsored_messages.h"
#include "data/data_wall_paper.h"
#include "data/data_web_page.h"
#include "chat_helpers/stickers_gift_box_pack.h"
#include "payments/payments_checkout_process.h" // CheckoutProcess::Start.
@ -4172,12 +4173,14 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
auto result = PreparedServiceText{};
result.links.push_back(peer->createOpenLink());
result.text = isSelf
? tr::lng_action_set_wallpaper(
? tr::lng_action_set_wallpaper_me(
tr::now,
Ui::Text::WithEntities)
: tr::lng_action_set_wallpaper(
tr::now,
lt_user,
Ui::Text::Link(name, 1), // Link 1.
Ui::Text::WithEntities)
: tr::lng_action_set_wallpaper_me(tr::now, Ui::Text::WithEntities);
Ui::Text::WithEntities);
return result;
};
@ -4194,13 +4197,13 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
result.links.push_back(peer->createOpenLink());
}
result.text = isSelf
? tr::lng_action_set_same_wallpaper(
? tr::lng_action_set_same_wallpaper_me(
tr::now,
Ui::Text::WithEntities)
: tr::lng_action_set_same_wallpaper(
tr::now,
lt_user,
Ui::Text::Link(name, 1), // Link 1.
Ui::Text::WithEntities)
: tr::lng_action_set_same_wallpaper_me(
tr::now,
Ui::Text::WithEntities);
return result;
};
@ -4349,7 +4352,11 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
}, [](const MTPDphotoEmpty &) {
});
}, [&](const MTPDmessageActionSetChatWallPaper &data) {
//_media = std::make_unique.. #TODO wallpapers
const auto session = &history()->session();
const auto &attached = data.vwallpaper();
if (const auto paper = Data::WallPaper::Create(session, attached)) {
_media = std::make_unique<Data::MediaWallPaper>(this, *paper);
}
}, [](const auto &) {
});
}

View File

@ -429,7 +429,7 @@ QSize Service::performCountCurrentSize(int newWidth) {
return { newWidth, newHeight };
}
const auto media = this->media();
if (media && data()->isUserpicSuggestion()) {
if (media && media->hideServiceText()) {
newHeight += st::msgServiceMargin.top()
+ media->resizeGetHeight(newWidth)
+ st::msgServiceMargin.bottom();
@ -461,7 +461,7 @@ QSize Service::performCountOptimalSize() {
if (const auto media = this->media()) {
media->initDimensions();
if (data()->isUserpicSuggestion()) {
if (media->hideServiceText()) {
return { media->maxWidth(), media->minHeight() };
}
}
@ -527,7 +527,7 @@ void Service::draw(Painter &p, const PaintContext &context) const {
p.setTextPalette(st->serviceTextPalette());
const auto media = this->media();
const auto onlyMedia = (media && data()->isUserpicSuggestion());
const auto onlyMedia = (media && media->hideServiceText());
if (!onlyMedia) {
if (media) {
@ -602,7 +602,7 @@ PointState Service::pointState(QPoint point) const {
TextState Service::textState(QPoint point, StateRequest request) const {
const auto item = data();
const auto media = this->media();
const auto onlyMedia = (media && data()->isUserpicSuggestion());
const auto onlyMedia = (media && media->hideServiceText());
auto result = TextState(item);

View File

@ -98,6 +98,9 @@ public:
[[nodiscard]] virtual bool hideMessageText() const {
return true;
}
[[nodiscard]] virtual bool hideServiceText() const {
return false;
}
[[nodiscard]] virtual bool allowsFastShare() const {
return false;
}

View File

@ -34,6 +34,10 @@ public:
const QRect &geometry) override;
ClickHandlerPtr createViewLink() override;
bool hideServiceText() override {
return false;
}
void stickerClearLoopPlayed() override;
std::unique_ptr<StickerPlayer> stickerTakePlayer(
not_null<DocumentData*> data,

View File

@ -30,6 +30,8 @@ public:
const QRect &geometry) = 0;
[[nodiscard]] virtual ClickHandlerPtr createViewLink() = 0;
[[nodiscard]] virtual bool hideServiceText() = 0;
virtual void stickerClearLoopPlayed() = 0;
[[nodiscard]] virtual std::unique_ptr<StickerPlayer> stickerTakePlayer(
not_null<DocumentData*> data,
@ -69,6 +71,10 @@ public:
[[nodiscard]] bool needsBubble() const override;
[[nodiscard]] bool customInfoLayout() const override;
[[nodiscard]] bool hideServiceText() const override {
return _content->hideServiceText();
}
bool hasHeavyPart() const override;
void unloadHeavyPart() override;

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h"
#include "history/view/history_view_element.h"
#include "history/view/history_view_cursor_state.h"
#include "history/view/media/history_view_sticker_player_abstract.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_document_media.h"
@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_wall_paper.h"
#include "base/qthelp_url.h"
#include "core/local_url_handlers.h"
#include "lang/lang_keys.h"
#include "ui/text/format_values.h"
#include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h"
@ -32,15 +34,17 @@ namespace HistoryView {
ThemeDocument::ThemeDocument(
not_null<Element*> parent,
DocumentData *document)
: ThemeDocument(parent, document, std::nullopt) {
: ThemeDocument(parent, document, std::nullopt, 0) {
}
ThemeDocument::ThemeDocument(
not_null<Element*> parent,
DocumentData *document,
const std::optional<Data::WallPaper> &params)
const std::optional<Data::WallPaper> &params,
int serviceWidth)
: File(parent, parent->data())
, _data(document) {
, _data(document)
, _serviceWidth(serviceWidth) {
Expects(params.has_value() || _data->hasThumbnail() || _data->isTheme());
if (params) {
@ -100,6 +104,10 @@ std::optional<Data::WallPaper> ThemeDocument::ParamsFromUrl(
}
QSize ThemeDocument::countOptimalSize() {
if (_serviceWidth > 0) {
return { _serviceWidth, _serviceWidth };
}
if (!_data) {
return { st::maxWallPaperWidth, st::maxWallPaperHeight };
} else if (_data->isTheme()) {
@ -123,6 +131,10 @@ QSize ThemeDocument::countOptimalSize() {
}
QSize ThemeDocument::countCurrentSize(int newWidth) {
if (_serviceWidth) {
_pixw = _pixh = _serviceWidth;
return { _serviceWidth, _serviceWidth };
}
if (!_data) {
_pixw = st::maxWallPaperWidth;
_pixh = st::maxWallPaperHeight;
@ -187,14 +199,16 @@ void ThemeDocument::draw(Painter &p, const PaintContext &context) const {
}
if (_data) {
auto statusX = paintx + st::msgDateImgDelta + st::msgDateImgPadding.x();
auto statusY = painty + st::msgDateImgDelta + st::msgDateImgPadding.y();
auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), sti->msgDateImgBg, sti->msgDateImgBgCorners);
p.setFont(st::normalFont);
p.setPen(st->msgDateImgFg());
p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x());
if (!_serviceWidth) {
auto statusX = paintx + st::msgDateImgDelta + st::msgDateImgPadding.x();
auto statusY = painty + st::msgDateImgDelta + st::msgDateImgPadding.y();
auto statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
auto statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
Ui::FillRoundRect(p, style::rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, width()), sti->msgDateImgBg, sti->msgDateImgBgCorners);
p.setFont(st::normalFont);
p.setPen(st->msgDateImgFg());
p.drawTextLeft(statusX, statusY, width(), _statusText, statusW - 2 * st::msgDateImgPadding.x());
}
if (radial || (!loaded && !_data->loading())) {
const auto radialOpacity = (radial && loaded && !_data->uploading())
? _animation->radial.opacity() :
@ -278,11 +292,15 @@ void ThemeDocument::validateThumbnail() const {
}
void ThemeDocument::generateThumbnail() const {
_thumbnail = Ui::PixmapFromImage(Ui::GenerateBackgroundImage(
auto image = Ui::GenerateBackgroundImage(
QSize(_pixw, _pixh) * cIntRetinaFactor(),
_background,
_gradientRotation,
_patternOpacity));
_patternOpacity);
if (_serviceWidth) {
image = Images::Circle(std::move(image));
}
_thumbnail = Ui::PixmapFromImage(std::move(image));
_thumbnail.setDevicePixelRatio(cRetinaFactor());
_thumbnailGood = 1;
}
@ -296,6 +314,7 @@ void ThemeDocument::prepareThumbnailFrom(
const auto isTheme = _data->isTheme();
const auto isPattern = _data->isPatternWallPaper();
auto options = (good >= 0 ? Images::Option(0) : Images::Option::Blur)
| (_serviceWidth ? Images::Option::RoundCircle : Images::Option(0))
| (isPattern
? Images::Option::TransparentBackground
: Images::Option(0));
@ -382,4 +401,74 @@ void ThemeDocument::unloadHeavyPart() {
_dataMedia = nullptr;
}
ThemeDocumentBox::ThemeDocumentBox(
not_null<Element*> parent,
const Data::WallPaper &paper)
: _parent(parent)
, _preview(
parent,
paper.document(),
paper,
st::msgServicePhotoWidth) {
_preview.initDimensions();
_preview.resizeGetHeight(_preview.maxWidth());
}
ThemeDocumentBox::~ThemeDocumentBox() = default;
int ThemeDocumentBox::top() {
return st::msgServiceGiftBoxButtonMargins.top();
}
QSize ThemeDocumentBox::size() {
return { _preview.maxWidth(), _preview.minHeight() };
}
QString ThemeDocumentBox::title() {
return QString();
}
QString ThemeDocumentBox::subtitle() {
return _parent->data()->notificationText().text;
}
QString ThemeDocumentBox::button() {
return tr::lng_sticker_premium_view(tr::now);
}
ClickHandlerPtr ThemeDocumentBox::createViewLink() {
const auto to = _parent->history()->peer;
return std::make_shared<LambdaClickHandler>([=](ClickContext context) {
//const auto my = context.other.value<ClickHandlerContext>();
//if (const auto controller = my.sessionWindow.get()) {
//}
});
}
void ThemeDocumentBox::draw(
Painter &p,
const PaintContext &context,
const QRect &geometry) {
p.translate(geometry.topLeft());
_preview.draw(p, context);
p.translate(-geometry.topLeft());
}
void ThemeDocumentBox::stickerClearLoopPlayed() {
}
std::unique_ptr<StickerPlayer> ThemeDocumentBox::stickerTakePlayer(
not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) {
return nullptr;
}
bool ThemeDocumentBox::hasHeavyPart() {
return _preview.hasHeavyPart();
}
void ThemeDocumentBox::unloadHeavyPart() {
_preview.unloadHeavyPart();
}
} // namespace HistoryView

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "history/view/media/history_view_file.h"
#include "history/view/media/history_view_service_box.h"
class Image;
@ -24,7 +25,8 @@ public:
ThemeDocument(
not_null<Element*> parent,
DocumentData *document,
const std::optional<Data::WallPaper> &params);
const std::optional<Data::WallPaper> &params,
int serviceWidth = 0);
~ThemeDocument();
void draw(Painter &p, const PaintContext &context) const override;
@ -71,6 +73,7 @@ private:
DocumentData *_data = nullptr;
int _pixw = 1;
int _pixh = 1;
const int _serviceWidth = 0;
mutable QPixmap _thumbnail;
mutable int _thumbnailGood = -1; // -1 inline, 0 thumbnail, 1 good
mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
@ -82,4 +85,40 @@ private:
};
class ThemeDocumentBox final : public ServiceBoxContent {
public:
ThemeDocumentBox(
not_null<Element*> parent,
const Data::WallPaper &paper);
~ThemeDocumentBox();
int top() override;
QSize size() override;
QString title() override;
QString subtitle() override;
QString button() override;
void draw(
Painter &p,
const PaintContext &context,
const QRect &geometry) override;
ClickHandlerPtr createViewLink() override;
bool hideServiceText() override {
return true;
}
void stickerClearLoopPlayed() override;
std::unique_ptr<StickerPlayer> stickerTakePlayer(
not_null<DocumentData*> data,
const Lottie::ColorReplacements *replacements) override;
bool hasHeavyPart() override;
void unloadHeavyPart() override;
private:
const not_null<Element*> _parent;
ThemeDocument _preview;
};
} // namespace HistoryView

View File

@ -38,6 +38,10 @@ public:
const QRect &geometry) override;
ClickHandlerPtr createViewLink() override;
bool hideServiceText() override {
return true;
}
void stickerClearLoopPlayed() override;
std::unique_ptr<StickerPlayer> stickerTakePlayer(
not_null<DocumentData*> data,