Fix chat intro sticker aspect ratio.

This commit is contained in:
John Preston 2024-03-20 18:09:37 +04:00
parent 9f67b9ba2f
commit 7f4d13c54a
7 changed files with 120 additions and 33 deletions

View file

@ -67,6 +67,7 @@ enum class StickerLottieSize : uint8 {
EmojiInteractionReserved6, EmojiInteractionReserved6,
EmojiInteractionReserved7, EmojiInteractionReserved7,
ChatIntroHelloSticker, ChatIntroHelloSticker,
StickerEmojiSize,
}; };
[[nodiscard]] uint8 LottieCacheKeyShift( [[nodiscard]] uint8 LottieCacheKeyShift(
uint8 replacementsTag, uint8 replacementsTag,

View file

@ -146,7 +146,8 @@ auto GenerateChatIntro(
push(std::make_unique<StickerInBubblePart>( push(std::make_unique<StickerInBubblePart>(
parent, parent,
replacing, replacing,
sticker)); sticker,
st::chatIntroStickerPadding));
}; };
} }

View file

@ -342,9 +342,11 @@ QSize TextDelimeterPart::countCurrentSize(int newWidth) {
StickerInBubblePart::StickerInBubblePart( StickerInBubblePart::StickerInBubblePart(
not_null<Element*> parent, not_null<Element*> parent,
Element *replacing, Element *replacing,
Fn<Data()> lookup) Fn<Data()> lookup,
QMargins padding)
: _parent(parent) : _parent(parent)
, _lookup(std::move(lookup)) { , _lookup(std::move(lookup))
, _padding(padding) {
ensureCreated(replacing); ensureCreated(replacing);
} }
@ -353,14 +355,14 @@ void StickerInBubblePart::draw(
not_null<const MediaInBubble*> owner, not_null<const MediaInBubble*> owner,
const PaintContext &context, const PaintContext &context,
int outerWidth) const { int outerWidth) const {
const auto stickerSize = st::msgServiceGiftBoxStickerSize;
const auto sticker = QRect(
(outerWidth - stickerSize) / 2,
st::chatGiveawayStickerTop + _skipTop,
stickerSize,
stickerSize);
ensureCreated(); ensureCreated();
if (_sticker) { if (_sticker) {
const auto stickerSize = _sticker->countOptimalSize();
const auto sticker = QRect(
(outerWidth - stickerSize.width()) / 2,
_padding.top() + _skipTop,
stickerSize.width(),
stickerSize.height());
_sticker->draw(p, context, sticker); _sticker->draw(p, context, sticker);
} }
} }
@ -384,8 +386,15 @@ std::unique_ptr<StickerPlayer> StickerInBubblePart::stickerTakePlayer(
} }
QSize StickerInBubblePart::countOptimalSize() { QSize StickerInBubblePart::countOptimalSize() {
const auto size = st::msgServiceGiftBoxStickerSize; ensureCreated();
return { size, st::chatGiveawayStickerTop + size }; const auto size = _sticker ? _sticker->countOptimalSize() : [&] {
const auto fallback = _lookup().size;
return QSize{ fallback, fallback };
}();
return {
_padding.left() + size.width() + _padding.right(),
_padding.top() + size.height() + _padding.bottom(),
};
} }
QSize StickerInBubblePart::countCurrentSize(int newWidth) { QSize StickerInBubblePart::countCurrentSize(int newWidth) {
@ -414,8 +423,9 @@ StickerWithBadgePart::StickerWithBadgePart(
not_null<Element*> parent, not_null<Element*> parent,
Element *replacing, Element *replacing,
Fn<Data()> lookup, Fn<Data()> lookup,
QMargins padding,
QString badge) QString badge)
: _sticker(parent, replacing, std::move(lookup)) : _sticker(parent, replacing, std::move(lookup), padding)
, _badgeText(badge) { , _badgeText(badge) {
} }
@ -751,6 +761,7 @@ auto GenerateGiveawayStart(
parent, parent,
nullptr, nullptr,
sticker, sticker,
QMargins(0, st::chatGiveawayStickerTop, 0, 0),
tr::lng_prizes_badge( tr::lng_prizes_badge(
tr::now, tr::now,
lt_amount, lt_amount,
@ -887,6 +898,7 @@ auto GenerateGiveawayResults(
parent, parent,
nullptr, nullptr,
sticker, sticker,
QMargins(0, st::chatGiveawayStickerTop, 0, 0),
tr::lng_prizes_badge( tr::lng_prizes_badge(
tr::now, tr::now,
lt_amount, lt_amount,

View file

@ -177,7 +177,8 @@ public:
StickerInBubblePart( StickerInBubblePart(
not_null<Element*> parent, not_null<Element*> parent,
Element *replacing, Element *replacing,
Fn<Data()> lookup); Fn<Data()> lookup,
QMargins padding);
[[nodiscard]] not_null<Element*> parent() const { [[nodiscard]] not_null<Element*> parent() const {
return _parent; return _parent;
@ -207,6 +208,7 @@ private:
const not_null<Element*> _parent; const not_null<Element*> _parent;
Fn<Data()> _lookup; Fn<Data()> _lookup;
mutable int _skipTop = 0; mutable int _skipTop = 0;
mutable QMargins _padding;
mutable std::optional<Sticker> _sticker; mutable std::optional<Sticker> _sticker;
}; };
@ -218,6 +220,7 @@ public:
not_null<Element*> parent, not_null<Element*> parent,
Element *replacing, Element *replacing,
Fn<Data()> lookup, Fn<Data()> lookup,
QMargins padding,
QString badge); QString badge);
void draw( void draw(

View file

@ -139,7 +139,11 @@ bool Sticker::emojiSticker() const {
void Sticker::initSize(int customSize) { void Sticker::initSize(int customSize) {
if (customSize > 0) { if (customSize > 0) {
_size = { customSize, customSize }; const auto original = Size(_data);
const auto proposed = QSize{ customSize, customSize };
_size = original.isEmpty()
? proposed
: DownscaledSize(original, proposed);
} else if (emojiSticker() || _diceIndex >= 0) { } else if (emojiSticker() || _diceIndex >= 0) {
_size = EmojiSize(); _size = EmojiSize();
if (_diceIndex > 0) { if (_diceIndex > 0) {

View file

@ -9,12 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_premium.h" #include "api/api_premium.h"
#include "boxes/peers/edit_peer_color_box.h" // ButtonStyleWithRightEmoji #include "boxes/peers/edit_peer_color_box.h" // ButtonStyleWithRightEmoji
#include "chat_helpers/stickers_lottie.h"
#include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_panel.h"
#include "chat_helpers/tabbed_selector.h" #include "chat_helpers/tabbed_selector.h"
#include "core/application.h" #include "core/application.h"
#include "data/business/data_business_info.h" #include "data/business/data_business_info.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/view/media/history_view_media_common.h"
#include "history/view/media/history_view_sticker_player.h"
#include "history/view/history_view_about_view.h" #include "history/view/history_view_about_view.h"
#include "history/view/history_view_context_menu.h" #include "history/view/history_view_context_menu.h"
#include "history/view/history_view_element.h" #include "history/view/history_view_element.h"
@ -97,7 +101,6 @@ public:
struct Descriptor { struct Descriptor {
not_null<Window::SessionController*> controller; not_null<Window::SessionController*> controller;
not_null<QWidget*> button; not_null<QWidget*> button;
DocumentId ensureAddedId = 0;
}; };
void show(Descriptor &&descriptor); void show(Descriptor &&descriptor);
void repaint(); void repaint();
@ -164,10 +167,49 @@ private:
current), current),
st::settingsChatIntroFieldMargins); st::settingsChatIntroFieldMargins);
field->setMaxLength(limit); field->setMaxLength(limit);
HistoryView::AddLengthLimitLabel(field, limit); AddLengthLimitLabel(field, limit);
return field; return field;
} }
rpl::producer<std::shared_ptr<StickerPlayer>> IconPlayerValue(
not_null<DocumentData*> sticker,
Fn<void()> update) {
const auto media = sticker->createMediaView();
media->checkStickerLarge();
media->goodThumbnailWanted();
return rpl::single() | rpl::then(
sticker->owner().session().downloaderTaskFinished()
) | rpl::filter([=] {
return media->loaded();
}) | rpl::take(1) | rpl::map([=] {
auto result = std::shared_ptr<StickerPlayer>();
const auto info = sticker->sticker();
const auto box = QSize(st::emojiSize, st::emojiSize);
if (info->isLottie()) {
result = std::make_shared<LottiePlayer>(
ChatHelpers::LottiePlayerFromDocument(
media.get(),
ChatHelpers::StickerLottieSize::StickerEmojiSize,
box,
Lottie::Quality::High));
} else if (info->isWebm()) {
result = std::make_shared<WebmPlayer>(
media->owner()->location(),
media->bytes(),
box);
} else {
result = std::make_shared<StaticStickerPlayer>(
media->owner()->location(),
media->bytes(),
box);
}
result->setRepaintCallback(update);
return result;
});
}
[[nodiscard]] object_ptr<Ui::SettingsButton> CreateIntroStickerButton( [[nodiscard]] object_ptr<Ui::SettingsButton> CreateIntroStickerButton(
not_null<Ui::RpWidget*> parent, not_null<Ui::RpWidget*> parent,
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
@ -188,7 +230,9 @@ private:
struct State { struct State {
StickerPanel panel; StickerPanel panel;
DocumentId stickerId = 0; DocumentData *sticker = nullptr;
std::shared_ptr<StickerPlayer> player;
rpl::lifetime playerLifetime;
}; };
const auto state = right->lifetime().make_state<State>(); const auto state = right->lifetime().make_state<State>();
state->panel.someCustomChosen( state->panel.someCustomChosen(
@ -200,11 +244,23 @@ private:
std::move( std::move(
stickerValue stickerValue
) | rpl::start_with_next([=](DocumentData *sticker) { ) | rpl::start_with_next([=](DocumentData *sticker) {
state->stickerId = sticker ? sticker->id : 0; state->sticker = sticker;
right->resize( if (sticker) {
(sticker ? button.emojiWidth : button.noneWidth) + button.added, right->resize(button.emojiWidth + button.added, right->height());
right->height()); IconPlayerValue(
sticker,
[=] { right->update(); }
) | rpl::start_with_next([=](
std::shared_ptr<StickerPlayer> player) {
state->player = std::move(player);
right->update(); right->update();
}, state->playerLifetime);
} else {
state->playerLifetime.destroy();
state->player = nullptr;
right->resize(button.noneWidth + button.added, right->height());
right->update();
}
}, right->lifetime()); }, right->lifetime());
rpl::combine( rpl::combine(
@ -220,8 +276,26 @@ private:
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
auto p = QPainter(right); auto p = QPainter(right);
const auto height = right->height(); const auto height = right->height();
if (false) { if (state->player) {
// #TODO paint small sticker if (state->player->ready()) {
const auto frame = state->player->frame(
QSize(st::emojiSize, st::emojiSize),
QColor(0, 0, 0, 0),
false,
crl::now(),
!right->window()->isActiveWindow()).image;
const auto target = DownscaledSize(
frame.size(),
QSize(st::emojiSize, st::emojiSize));
p.drawImage(
QRect(
button.added + (st::emojiSize - target.width()) / 2,
(height - target.height()) / 2,
target.width(),
target.height()),
frame);
state->player->markFrameShown();
}
} else { } else {
const auto &font = st::normalFont; const auto &font = st::normalFont;
p.setFont(font); p.setFont(font);
@ -241,7 +315,6 @@ private:
state->panel.show({ state->panel.show({
.controller = controller, .controller = controller,
.button = right, .button = right,
.ensureAddedId = state->stickerId,
}); });
} }
}); });
@ -384,14 +457,6 @@ void StickerPanel::show(Descriptor &&descriptor) {
} }
} }
_panelButton = button; _panelButton = button;
const auto feed = [=, now = descriptor.ensureAddedId](
std::vector<DocumentId> list) {
list.insert(begin(list), 0);
if (now && !ranges::contains(list, now)) {
list.push_back(now);
}
_panel->selector()->provideRecentEmoji(list);
};
const auto parent = _panel->parentWidget(); const auto parent = _panel->parentWidget();
const auto global = button->mapToGlobal(QPoint()); const auto global = button->mapToGlobal(QPoint());
const auto local = parent->mapFromGlobal(global); const auto local = parent->mapFromGlobal(global);

View file

@ -1066,3 +1066,4 @@ chatIntroStickerSize: 96px;
chatIntroWidth: 224px; chatIntroWidth: 224px;
chatIntroTitleMargin: margins(11px, 16px, 11px, 4px); chatIntroTitleMargin: margins(11px, 16px, 11px, 4px);
chatIntroMargin: margins(11px, 0px, 11px, 0px); chatIntroMargin: margins(11px, 0px, 11px, 0px);
chatIntroStickerPadding: margins(10px, 8px, 10px, 16px);