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,
EmojiInteractionReserved7,
ChatIntroHelloSticker,
StickerEmojiSize,
};
[[nodiscard]] uint8 LottieCacheKeyShift(
uint8 replacementsTag,

View File

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

View File

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

View File

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

View File

@ -139,7 +139,11 @@ bool Sticker::emojiSticker() const {
void Sticker::initSize(int customSize) {
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) {
_size = EmojiSize();
if (_diceIndex > 0) {

View File

@ -9,12 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_premium.h"
#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_selector.h"
#include "core/application.h"
#include "data/business/data_business_info.h"
#include "data/data_document.h"
#include "data/data_document_media.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_context_menu.h"
#include "history/view/history_view_element.h"
@ -97,7 +101,6 @@ public:
struct Descriptor {
not_null<Window::SessionController*> controller;
not_null<QWidget*> button;
DocumentId ensureAddedId = 0;
};
void show(Descriptor &&descriptor);
void repaint();
@ -164,10 +167,49 @@ private:
current),
st::settingsChatIntroFieldMargins);
field->setMaxLength(limit);
HistoryView::AddLengthLimitLabel(field, limit);
AddLengthLimitLabel(field, limit);
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(
not_null<Ui::RpWidget*> parent,
std::shared_ptr<ChatHelpers::Show> show,
@ -188,7 +230,9 @@ private:
struct State {
StickerPanel panel;
DocumentId stickerId = 0;
DocumentData *sticker = nullptr;
std::shared_ptr<StickerPlayer> player;
rpl::lifetime playerLifetime;
};
const auto state = right->lifetime().make_state<State>();
state->panel.someCustomChosen(
@ -200,11 +244,23 @@ private:
std::move(
stickerValue
) | rpl::start_with_next([=](DocumentData *sticker) {
state->stickerId = sticker ? sticker->id : 0;
right->resize(
(sticker ? button.emojiWidth : button.noneWidth) + button.added,
right->height());
right->update();
state->sticker = sticker;
if (sticker) {
right->resize(button.emojiWidth + button.added, right->height());
IconPlayerValue(
sticker,
[=] { right->update(); }
) | rpl::start_with_next([=](
std::shared_ptr<StickerPlayer> player) {
state->player = std::move(player);
right->update();
}, state->playerLifetime);
} else {
state->playerLifetime.destroy();
state->player = nullptr;
right->resize(button.noneWidth + button.added, right->height());
right->update();
}
}, right->lifetime());
rpl::combine(
@ -220,8 +276,26 @@ private:
) | rpl::start_with_next([=] {
auto p = QPainter(right);
const auto height = right->height();
if (false) {
// #TODO paint small sticker
if (state->player) {
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 {
const auto &font = st::normalFont;
p.setFont(font);
@ -241,7 +315,6 @@ private:
state->panel.show({
.controller = controller,
.button = right,
.ensureAddedId = state->stickerId,
});
}
});
@ -384,14 +457,6 @@ void StickerPanel::show(Descriptor &&descriptor) {
}
}
_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 global = button->mapToGlobal(QPoint());
const auto local = parent->mapFromGlobal(global);

View File

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