mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Optimize small emoji image caching and painting.
This commit is contained in:
parent
4050866b3b
commit
6f8c9f65cf
7 changed files with 172 additions and 263 deletions
|
@ -13,8 +13,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "base/timer_rpl.h"
|
||||
#include "apiwrap.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
||||
namespace Data {
|
||||
namespace {
|
||||
|
@ -55,6 +58,105 @@ rpl::producer<> Reactions::updates() const {
|
|||
return _updated.events();
|
||||
}
|
||||
|
||||
void Reactions::preloadImageFor(const QString &emoji) {
|
||||
if (_images.contains(emoji)) {
|
||||
return;
|
||||
}
|
||||
auto &set = _images.emplace(emoji).first->second;
|
||||
const auto i = ranges::find(_available, emoji, &Reaction::emoji);
|
||||
const auto document = (i != end(_available))
|
||||
? i->staticIcon.get()
|
||||
: nullptr;
|
||||
if (document) {
|
||||
loadImage(set, document);
|
||||
} else if (!_waitingForList) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
QImage Reactions::resolveImageFor(
|
||||
const QString &emoji,
|
||||
ImageSize size) {
|
||||
const auto i = _images.find(emoji);
|
||||
if (i == end(_images)) {
|
||||
preloadImageFor(emoji);
|
||||
}
|
||||
auto &set = (i != end(_images)) ? i->second : _images[emoji];
|
||||
switch (size) {
|
||||
case ImageSize::BottomInfo: return set.bottomInfo;
|
||||
case ImageSize::InlineList: return set.inlineList;
|
||||
}
|
||||
Unexpected("ImageSize in Reactions::resolveImageFor.");
|
||||
}
|
||||
|
||||
void Reactions::resolveImages() {
|
||||
for (auto &[emoji, set] : _images) {
|
||||
if (!set.bottomInfo.isNull() || set.media) {
|
||||
continue;
|
||||
}
|
||||
const auto i = ranges::find(_available, emoji, &Reaction::emoji);
|
||||
const auto document = (i != end(list()))
|
||||
? i->staticIcon.get()
|
||||
: nullptr;
|
||||
if (document) {
|
||||
loadImage(set, document);
|
||||
} else {
|
||||
LOG(("API Error: Reaction for emoji '%1' not found!"
|
||||
).arg(emoji));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Reactions::loadImage(
|
||||
ImageSet &set,
|
||||
not_null<DocumentData*> document) {
|
||||
if (!set.bottomInfo.isNull()) {
|
||||
return;
|
||||
} else if (!set.media) {
|
||||
set.media = document->createMediaView();
|
||||
}
|
||||
if (const auto image = set.media->getStickerLarge()) {
|
||||
setImage(set, image->original());
|
||||
} else if (!_imagesLoadLifetime) {
|
||||
document->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
downloadTaskFinished();
|
||||
}, _imagesLoadLifetime);
|
||||
}
|
||||
}
|
||||
|
||||
void Reactions::setImage(ImageSet &set, QImage large) {
|
||||
set.media = nullptr;
|
||||
const auto scale = [&](int size) {
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
return Images::prepare(
|
||||
large,
|
||||
size * factor,
|
||||
size * factor,
|
||||
Images::Option::Smooth,
|
||||
size,
|
||||
size);
|
||||
};
|
||||
set.bottomInfo = scale(st::reactionInfoSize);
|
||||
set.inlineList = scale(st::reactionBottomSize);
|
||||
}
|
||||
|
||||
void Reactions::downloadTaskFinished() {
|
||||
auto hasOne = false;
|
||||
for (auto &[emoji, set] : _images) {
|
||||
if (!set.media) {
|
||||
continue;
|
||||
} else if (const auto image = set.media->getStickerLarge()) {
|
||||
setImage(set, image->original());
|
||||
} else {
|
||||
hasOne = true;
|
||||
}
|
||||
}
|
||||
if (!hasOne) {
|
||||
_imagesLoadLifetime.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Reaction> Reactions::Filtered(
|
||||
const std::vector<Reaction> &reactions,
|
||||
const std::vector<QString> &emoji) {
|
||||
|
@ -101,6 +203,10 @@ void Reactions::request() {
|
|||
_available.push_back(*parsed);
|
||||
}
|
||||
}
|
||||
if (_waitingForList) {
|
||||
_waitingForList = false;
|
||||
resolveImages();
|
||||
}
|
||||
_updated.fire({});
|
||||
}, [&](const MTPDmessages_availableReactionsNotModified &) {
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Data {
|
||||
|
||||
class DocumentMedia;
|
||||
class Session;
|
||||
|
||||
struct Reaction {
|
||||
|
@ -40,12 +41,32 @@ public:
|
|||
|
||||
[[nodiscard]] rpl::producer<> updates() const;
|
||||
|
||||
enum class ImageSize {
|
||||
BottomInfo,
|
||||
InlineList,
|
||||
};
|
||||
void preloadImageFor(const QString &emoji);
|
||||
[[nodiscard]] QImage resolveImageFor(
|
||||
const QString &emoji,
|
||||
ImageSize size);
|
||||
|
||||
private:
|
||||
struct ImageSet {
|
||||
QImage bottomInfo;
|
||||
QImage inlineList;
|
||||
std::shared_ptr<DocumentMedia> media;
|
||||
};
|
||||
|
||||
void request();
|
||||
|
||||
[[nodiscard]] std::optional<Reaction> parse(
|
||||
const MTPAvailableReaction &entry);
|
||||
|
||||
void loadImage(ImageSet &set, not_null<DocumentData*> document);
|
||||
void setImage(ImageSet &set, QImage large);
|
||||
void resolveImages();
|
||||
void downloadTaskFinished();
|
||||
|
||||
const not_null<Session*> _owner;
|
||||
|
||||
std::vector<Reaction> _available;
|
||||
|
@ -54,6 +75,10 @@ private:
|
|||
mtpRequestId _requestId = 0;
|
||||
int32 _hash = 0;
|
||||
|
||||
base::flat_map<QString, ImageSet> _images;
|
||||
rpl::lifetime _imagesLoadLifetime;
|
||||
bool _waitingForList = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,17 +18,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/view/history_view_message.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "main/main_session.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
namespace HistoryView {
|
||||
|
||||
BottomInfo::BottomInfo(Data &&data)
|
||||
: _data(std::move(data)) {
|
||||
BottomInfo::BottomInfo(
|
||||
not_null<::Data::Reactions*> reactionsOwner,
|
||||
Data &&data)
|
||||
: _reactionsOwner(reactionsOwner)
|
||||
, _data(std::move(data)) {
|
||||
layout();
|
||||
}
|
||||
|
||||
|
@ -227,6 +226,11 @@ void BottomInfo::paintReactions(
|
|||
y += st::msgDateFont->height;
|
||||
widthLeft = availableWidth;
|
||||
}
|
||||
if (reaction.image.isNull()) {
|
||||
reaction.image = _reactionsOwner->resolveImageFor(
|
||||
reaction.emoji,
|
||||
::Data::Reactions::ImageSize::BottomInfo);
|
||||
}
|
||||
if (!reaction.image.isNull()) {
|
||||
p.drawImage(
|
||||
x,
|
||||
|
@ -362,56 +366,10 @@ QSize BottomInfo::countOptimalSize() {
|
|||
BottomInfo::Reaction BottomInfo::prepareReactionWithEmoji(
|
||||
const QString &emoji) {
|
||||
auto result = Reaction{ .emoji = emoji };
|
||||
auto &reactions = _data.owner->reactions();
|
||||
const auto &list = reactions.list();
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
emoji,
|
||||
&::Data::Reaction::emoji);
|
||||
const auto document = (i != end(list))
|
||||
? i->staticIcon.get()
|
||||
: nullptr;
|
||||
if (document) {
|
||||
loadReactionImage(result, document);
|
||||
} else if (!_waitingForReactionsList) {
|
||||
reactions.refresh();
|
||||
reactions.updates(
|
||||
) | rpl::filter([=] {
|
||||
return _waitingForReactionsList;
|
||||
}) | rpl::start_with_next([=] {
|
||||
reactionsListLoaded();
|
||||
}, _assetsLoadLifetime);
|
||||
}
|
||||
_reactionsOwner->preloadImageFor(emoji);
|
||||
return result;
|
||||
}
|
||||
|
||||
void BottomInfo::reactionsListLoaded() {
|
||||
_waitingForReactionsList = false;
|
||||
if (assetsLoaded()) {
|
||||
_assetsLoadLifetime.destroy();
|
||||
}
|
||||
|
||||
const auto &list = _data.owner->reactions().list();
|
||||
for (auto &reaction : _reactions) {
|
||||
if (!reaction.image.isNull() || reaction.media) {
|
||||
continue;
|
||||
}
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
reaction.emoji,
|
||||
&::Data::Reaction::emoji);
|
||||
const auto document = (i != end(list))
|
||||
? i->staticIcon.get()
|
||||
: nullptr;
|
||||
if (document) {
|
||||
loadReactionImage(reaction, document);
|
||||
} else {
|
||||
LOG(("API Error: Reaction for emoji '%1' not found!"
|
||||
).arg(reaction.emoji));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BottomInfo::setReactionCount(Reaction &reaction, int count) {
|
||||
if (reaction.count == count) {
|
||||
return;
|
||||
|
@ -425,72 +383,14 @@ void BottomInfo::setReactionCount(Reaction &reaction, int count) {
|
|||
: 0;
|
||||
}
|
||||
|
||||
void BottomInfo::loadReactionImage(
|
||||
Reaction &reaction,
|
||||
not_null<DocumentData*> document) {
|
||||
if (!reaction.image.isNull()) {
|
||||
return;
|
||||
} else if (!reaction.media) {
|
||||
reaction.media = document->createMediaView();
|
||||
}
|
||||
if (const auto image = reaction.media->getStickerLarge()) {
|
||||
setReactionImage(reaction, image->original());
|
||||
} else if (!_waitingForDownloadTask) {
|
||||
_waitingForDownloadTask = true;
|
||||
document->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
downloadTaskFinished();
|
||||
}, _assetsLoadLifetime);
|
||||
}
|
||||
}
|
||||
|
||||
void BottomInfo::setReactionImage(Reaction &reaction, QImage large) {
|
||||
reaction.media = nullptr;
|
||||
const auto size = st::reactionInfoSize;
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
reaction.image = Images::prepare(
|
||||
std::move(large),
|
||||
size * factor,
|
||||
size * factor,
|
||||
Images::Option::Smooth,
|
||||
size,
|
||||
size);
|
||||
}
|
||||
|
||||
void BottomInfo::downloadTaskFinished() {
|
||||
auto hasOne = false;
|
||||
for (auto &reaction : _reactions) {
|
||||
if (!reaction.media) {
|
||||
continue;
|
||||
} else if (const auto image = reaction.media->getStickerLarge()) {
|
||||
setReactionImage(reaction, image->original());
|
||||
} else {
|
||||
hasOne = true;
|
||||
}
|
||||
}
|
||||
if (!hasOne) {
|
||||
_waitingForDownloadTask = false;
|
||||
if (assetsLoaded()) {
|
||||
_assetsLoadLifetime.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BottomInfo::assetsLoaded() const {
|
||||
return !_waitingForReactionsList && !_waitingForDownloadTask;
|
||||
}
|
||||
|
||||
BottomInfo::Data BottomInfoDataFromMessage(not_null<Message*> message) {
|
||||
using Flag = BottomInfo::Data::Flag;
|
||||
|
||||
const auto owner = &message->data()->history()->owner();
|
||||
auto result = BottomInfo::Data{ .owner = owner };
|
||||
|
||||
const auto item = message->message();
|
||||
|
||||
auto result = BottomInfo::Data();
|
||||
result.date = message->dateTime();
|
||||
if (message->embedReactionsInBottomInfo()) {
|
||||
result.reactions = item->reactions();
|
||||
result.chosenReaction = item->chosenReaction();
|
||||
}
|
||||
if (message->hasOutLayout()) {
|
||||
result.flags |= Flag::OutLayout;
|
||||
|
|
|
@ -16,8 +16,7 @@ struct ChatPaintContext;
|
|||
} // namespace Ui
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
class DocumentMedia;
|
||||
class Reactions;
|
||||
} // namespace Data
|
||||
|
||||
namespace HistoryView {
|
||||
|
@ -41,16 +40,14 @@ public:
|
|||
friend inline constexpr bool is_flag_type(Flag) { return true; };
|
||||
using Flags = base::flags<Flag>;
|
||||
|
||||
not_null<::Data::Session*> owner;
|
||||
QDateTime date;
|
||||
QString author;
|
||||
base::flat_map<QString, int> reactions;
|
||||
QString chosenReaction;
|
||||
std::optional<int> views;
|
||||
std::optional<int> replies;
|
||||
Flags flags;
|
||||
};
|
||||
explicit BottomInfo(Data &&data);
|
||||
BottomInfo(not_null<::Data::Reactions*> reactionsOwner, Data &&data);
|
||||
|
||||
void update(Data &&data, int availableWidth);
|
||||
|
||||
|
@ -70,9 +67,8 @@ public:
|
|||
|
||||
private:
|
||||
struct Reaction {
|
||||
QImage image;
|
||||
mutable QImage image;
|
||||
QString emoji;
|
||||
std::shared_ptr<::Data::DocumentMedia> media;
|
||||
QString countText;
|
||||
int count = 0;
|
||||
int countTextWidth = 0;
|
||||
|
@ -96,14 +92,9 @@ private:
|
|||
QSize countCurrentSize(int newWidth) override;
|
||||
|
||||
void setReactionCount(Reaction &reaction, int count);
|
||||
void loadReactionImage(Reaction &reaction, not_null<DocumentData*> document);
|
||||
void setReactionImage(Reaction &reaction, QImage large);
|
||||
[[nodiscard]] Reaction prepareReactionWithEmoji(const QString &emoji);
|
||||
|
||||
void reactionsListLoaded();
|
||||
void downloadTaskFinished();
|
||||
[[nodiscard]] bool assetsLoaded() const;
|
||||
|
||||
const not_null<::Data::Reactions*> _reactionsOwner;
|
||||
Data _data;
|
||||
Ui::Text::String _authorEditedDate;
|
||||
Ui::Text::String _views;
|
||||
|
@ -111,11 +102,6 @@ private:
|
|||
std::vector<Reaction> _reactions;
|
||||
int _reactionsMaxWidth = 0;
|
||||
int _dateWidth = 0;
|
||||
|
||||
rpl::lifetime _assetsLoadLifetime;
|
||||
bool _waitingForReactionsList = false;
|
||||
bool _waitingForDownloadTask = false;
|
||||
|
||||
bool _authorElided = false;
|
||||
|
||||
};
|
||||
|
|
|
@ -245,7 +245,9 @@ Message::Message(
|
|||
not_null<HistoryMessage*> data,
|
||||
Element *replacing)
|
||||
: Element(delegate, data, replacing)
|
||||
, _bottomInfo(BottomInfoDataFromMessage(this)) {
|
||||
, _bottomInfo(
|
||||
&data->history()->owner().reactions(),
|
||||
BottomInfoDataFromMessage(this)) {
|
||||
initLogEntryOriginal();
|
||||
initPsa();
|
||||
refreshReactions();
|
||||
|
@ -1924,7 +1926,9 @@ void Message::refreshReactions() {
|
|||
using namespace Reactions;
|
||||
auto data = InlineListDataFromMessage(this);
|
||||
if (!_reactions) {
|
||||
_reactions = std::make_unique<InlineList>(std::move(data));
|
||||
_reactions = std::make_unique<InlineList>(
|
||||
&item->history()->owner().reactions(),
|
||||
std::move(data));
|
||||
} else {
|
||||
_reactions->update(std::move(data), width());
|
||||
}
|
||||
|
|
|
@ -10,11 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_message.h"
|
||||
#include "history/history.h"
|
||||
#include "history/view/history_view_message.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "data/data_session.h"
|
||||
#include "main/main_session.h"
|
||||
#include "lang/lang_tag.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "styles/style_chat.h"
|
||||
|
@ -27,8 +23,9 @@ constexpr auto kOutNonChosenOpacity = 0.18;
|
|||
|
||||
} // namespace
|
||||
|
||||
InlineList::InlineList(Data &&data)
|
||||
: _data(std::move(data)) {
|
||||
InlineList::InlineList(not_null<::Data::Reactions*> owner, Data &&data)
|
||||
: _owner(owner)
|
||||
, _data(std::move(data)) {
|
||||
layout();
|
||||
}
|
||||
|
||||
|
@ -79,56 +76,10 @@ void InlineList::layoutButtons() {
|
|||
|
||||
InlineList::Button InlineList::prepareButtonWithEmoji(const QString &emoji) {
|
||||
auto result = Button{ .emoji = emoji };
|
||||
auto &reactions = _data.owner->reactions();
|
||||
const auto &list = reactions.list();
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
emoji,
|
||||
&::Data::Reaction::emoji);
|
||||
const auto document = (i != end(list))
|
||||
? i->staticIcon.get()
|
||||
: nullptr;
|
||||
if (document) {
|
||||
loadButtonImage(result, document);
|
||||
} else if (!_waitingForReactionsList) {
|
||||
reactions.refresh();
|
||||
reactions.updates(
|
||||
) | rpl::filter([=] {
|
||||
return _waitingForReactionsList;
|
||||
}) | rpl::start_with_next([=] {
|
||||
reactionsListLoaded();
|
||||
}, _assetsLoadLifetime);
|
||||
}
|
||||
_owner->preloadImageFor(emoji);
|
||||
return result;
|
||||
}
|
||||
|
||||
void InlineList::reactionsListLoaded() {
|
||||
_waitingForReactionsList = false;
|
||||
if (assetsLoaded()) {
|
||||
_assetsLoadLifetime.destroy();
|
||||
}
|
||||
|
||||
const auto &list = _data.owner->reactions().list();
|
||||
for (auto &button : _buttons) {
|
||||
if (!button.image.isNull() || button.media) {
|
||||
continue;
|
||||
}
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
button.emoji,
|
||||
&::Data::Reaction::emoji);
|
||||
const auto document = (i != end(list))
|
||||
? i->staticIcon.get()
|
||||
: nullptr;
|
||||
if (document) {
|
||||
loadButtonImage(button, document);
|
||||
} else {
|
||||
LOG(("API Error: Reaction for emoji '%1' not found!"
|
||||
).arg(button.emoji));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InlineList::setButtonCount(Button &button, int count) {
|
||||
if (button.count == count) {
|
||||
return;
|
||||
|
@ -138,61 +89,6 @@ void InlineList::setButtonCount(Button &button, int count) {
|
|||
button.countTextWidth = st::semiboldFont->width(button.countText);
|
||||
}
|
||||
|
||||
void InlineList::loadButtonImage(
|
||||
Button &button,
|
||||
not_null<DocumentData*> document) {
|
||||
if (!button.image.isNull()) {
|
||||
return;
|
||||
} else if (!button.media) {
|
||||
button.media = document->createMediaView();
|
||||
}
|
||||
if (const auto image = button.media->getStickerLarge()) {
|
||||
setButtonImage(button, image->original());
|
||||
} else if (!_waitingForDownloadTask) {
|
||||
_waitingForDownloadTask = true;
|
||||
document->session().downloaderTaskFinished(
|
||||
) | rpl::start_with_next([=] {
|
||||
downloadTaskFinished();
|
||||
}, _assetsLoadLifetime);
|
||||
}
|
||||
}
|
||||
|
||||
void InlineList::setButtonImage(Button &button, QImage large) {
|
||||
button.media = nullptr;
|
||||
const auto size = st::reactionBottomSize;
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
button.image = Images::prepare(
|
||||
std::move(large),
|
||||
size * factor,
|
||||
size * factor,
|
||||
Images::Option::Smooth,
|
||||
size,
|
||||
size);
|
||||
}
|
||||
|
||||
void InlineList::downloadTaskFinished() {
|
||||
auto hasOne = false;
|
||||
for (auto &button : _buttons) {
|
||||
if (!button.media) {
|
||||
continue;
|
||||
} else if (const auto image = button.media->getStickerLarge()) {
|
||||
setButtonImage(button, image->original());
|
||||
} else {
|
||||
hasOne = true;
|
||||
}
|
||||
}
|
||||
if (!hasOne) {
|
||||
_waitingForDownloadTask = false;
|
||||
if (assetsLoaded()) {
|
||||
_assetsLoadLifetime.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InlineList::assetsLoaded() const {
|
||||
return !_waitingForReactionsList && !_waitingForDownloadTask;
|
||||
}
|
||||
|
||||
QSize InlineList::countOptimalSize() {
|
||||
if (_buttons.empty()) {
|
||||
return _skipBlock;
|
||||
|
@ -282,7 +178,14 @@ void InlineList::paint(
|
|||
p.setOpacity(1.);
|
||||
}
|
||||
}
|
||||
p.drawImage(inner.topLeft(), button.image);
|
||||
if (button.image.isNull()) {
|
||||
button.image = _owner->resolveImageFor(
|
||||
button.emoji,
|
||||
::Data::Reactions::ImageSize::InlineList);
|
||||
}
|
||||
if (!button.image.isNull()) {
|
||||
p.drawImage(inner.topLeft(), button.image);
|
||||
}
|
||||
p.setPen(!inbubble
|
||||
? st->msgServiceFg()
|
||||
: !chosen
|
||||
|
@ -304,11 +207,10 @@ void InlineList::paint(
|
|||
}
|
||||
|
||||
InlineListData InlineListDataFromMessage(not_null<Message*> message) {
|
||||
const auto owner = &message->data()->history()->owner();
|
||||
auto result = InlineListData{ .owner = owner };
|
||||
|
||||
using Flag = InlineListData::Flag;
|
||||
const auto item = message->message();
|
||||
|
||||
auto result = InlineListData();
|
||||
result.reactions = item->reactions();
|
||||
result.chosenReaction = item->chosenReaction();
|
||||
result.flags = (message->hasOutLayout() ? Flag::OutLayout : Flag())
|
||||
|
|
|
@ -9,11 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "history/view/history_view_object.h"
|
||||
|
||||
class DocumentData;
|
||||
|
||||
namespace Data {
|
||||
class Session;
|
||||
class DocumentMedia;
|
||||
class Reactions;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
|
@ -35,7 +32,6 @@ struct InlineListData {
|
|||
friend inline constexpr bool is_flag_type(Flag) { return true; };
|
||||
using Flags = base::flags<Flag>;
|
||||
|
||||
not_null<Data::Session*> owner;
|
||||
base::flat_map<QString, int> reactions;
|
||||
QString chosenReaction;
|
||||
Flags flags = {};
|
||||
|
@ -44,7 +40,7 @@ struct InlineListData {
|
|||
class InlineList final : public Object {
|
||||
public:
|
||||
using Data = InlineListData;
|
||||
explicit InlineList(Data &&data);
|
||||
InlineList(not_null<::Data::Reactions*> owner, Data &&data);
|
||||
|
||||
void update(Data &&data, int availableWidth);
|
||||
QSize countCurrentSize(int newWidth) override;
|
||||
|
@ -61,9 +57,8 @@ public:
|
|||
private:
|
||||
struct Button {
|
||||
QRect geometry;
|
||||
QImage image;
|
||||
mutable QImage image;
|
||||
QString emoji;
|
||||
std::shared_ptr<::Data::DocumentMedia> media;
|
||||
ClickHandlerPtr link;
|
||||
QString countText;
|
||||
int count = 0;
|
||||
|
@ -74,24 +69,15 @@ private:
|
|||
void layoutButtons();
|
||||
|
||||
void setButtonCount(Button &button, int count);
|
||||
void loadButtonImage(Button &button, not_null<DocumentData*> document);
|
||||
void setButtonImage(Button &button, QImage large);
|
||||
[[nodiscard]] Button prepareButtonWithEmoji(const QString &emoji);
|
||||
|
||||
void reactionsListLoaded();
|
||||
void downloadTaskFinished();
|
||||
[[nodiscard]] bool assetsLoaded() const;
|
||||
|
||||
QSize countOptimalSize() override;
|
||||
|
||||
const not_null<::Data::Reactions*> _owner;
|
||||
Data _data;
|
||||
std::vector<Button> _buttons;
|
||||
QSize _skipBlock;
|
||||
|
||||
rpl::lifetime _assetsLoadLifetime;
|
||||
bool _waitingForReactionsList = false;
|
||||
bool _waitingForDownloadTask = false;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] InlineListData InlineListDataFromMessage(
|
||||
|
|
Loading…
Add table
Reference in a new issue