mirror of https://github.com/procxx/kepka.git
Show animated stickers in StickerSetBox.
This commit is contained in:
parent
10910588a0
commit
8f3f898c47
|
@ -2844,7 +2844,7 @@ void ApiWrap::requestAttachedStickerSets(not_null<PhotoData*> photo) {
|
||||||
? MTP_inputStickerSetID(setData->vid, setData->vaccess_hash)
|
? MTP_inputStickerSetID(setData->vid, setData->vaccess_hash)
|
||||||
: MTP_inputStickerSetShortName(setData->vshort_name);
|
: MTP_inputStickerSetShortName(setData->vshort_name);
|
||||||
Ui::show(
|
Ui::show(
|
||||||
Box<StickerSetBox>(setId),
|
Box<StickerSetBox>(App::wnd()->sessionController(), setId),
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
|
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "chat_helpers/stickers.h"
|
#include "chat_helpers/stickers.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "dialogs/dialogs_layout.h"
|
#include "dialogs/dialogs_layout.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
|
@ -20,6 +21,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/emoji_config.h"
|
#include "ui/emoji_config.h"
|
||||||
|
#include "lottie/lottie_animation.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
@ -33,9 +36,12 @@ constexpr auto kStickersPanelPerRow = 5;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class StickerSetBox::Inner : public TWidget, public RPCSender, private base::Subscriber {
|
class StickerSetBox::Inner : public Ui::RpWidget, private base::Subscriber {
|
||||||
public:
|
public:
|
||||||
Inner(QWidget *parent, const MTPInputStickerSet &set);
|
Inner(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
const MTPInputStickerSet &set);
|
||||||
|
|
||||||
bool loaded() const;
|
bool loaded() const;
|
||||||
bool notInstalled() const;
|
bool notInstalled() const;
|
||||||
|
@ -57,16 +63,22 @@ protected:
|
||||||
void leaveEventHook(QEvent *e) override;
|
void leaveEventHook(QEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Element {
|
||||||
|
not_null<DocumentData*> document;
|
||||||
|
std::unique_ptr<Lottie::Animation> animated;
|
||||||
|
Ui::Animations::Simple overAnimation;
|
||||||
|
};
|
||||||
|
|
||||||
|
void paintSticker(Painter &p, int index, QPoint position) const;
|
||||||
|
void setupLottie(int index);
|
||||||
|
|
||||||
void updateSelected();
|
void updateSelected();
|
||||||
void setSelected(int selected);
|
void setSelected(int selected);
|
||||||
void startOverAnimation(int index, float64 from, float64 to);
|
void startOverAnimation(int index, float64 from, float64 to);
|
||||||
int stickerFromGlobalPos(const QPoint &p) const;
|
int stickerFromGlobalPos(const QPoint &p) const;
|
||||||
|
|
||||||
void gotSet(const MTPmessages_StickerSet &set);
|
void gotSet(const MTPmessages_StickerSet &set);
|
||||||
bool failedSet(const RPCError &error);
|
|
||||||
|
|
||||||
void installDone(const MTPmessages_StickerSetInstallResult &result);
|
void installDone(const MTPmessages_StickerSetInstallResult &result);
|
||||||
bool installFail(const RPCError &error);
|
|
||||||
|
|
||||||
bool isMasksSet() const {
|
bool isMasksSet() const {
|
||||||
return (_setFlags & MTPDstickerSet::Flag::f_masks);
|
return (_setFlags & MTPDstickerSet::Flag::f_masks);
|
||||||
|
@ -74,7 +86,9 @@ private:
|
||||||
|
|
||||||
void showPreview();
|
void showPreview();
|
||||||
|
|
||||||
std::vector<Ui::Animations::Simple> _packOvers;
|
not_null<Window::SessionController*> _controller;
|
||||||
|
MTP::Sender _mtp;
|
||||||
|
std::vector<Element> _elements;
|
||||||
Stickers::Pack _pack;
|
Stickers::Pack _pack;
|
||||||
Stickers::ByEmojiMap _emoji;
|
Stickers::ByEmojiMap _emoji;
|
||||||
bool _loaded = false;
|
bool _loaded = false;
|
||||||
|
@ -101,14 +115,22 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StickerSetBox::StickerSetBox(QWidget*, const MTPInputStickerSet &set)
|
StickerSetBox::StickerSetBox(
|
||||||
: _set(set) {
|
QWidget*,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
const MTPInputStickerSet &set)
|
||||||
|
: _controller(controller)
|
||||||
|
, _set(set) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::Show(DocumentData *document) {
|
void StickerSetBox::Show(
|
||||||
if (const auto sticker = document ? document->sticker() : nullptr) {
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<DocumentData*> document) {
|
||||||
|
if (const auto sticker = document->sticker()) {
|
||||||
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
if (sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
Ui::show(Box<StickerSetBox>(sticker->set));
|
Ui::show(
|
||||||
|
Box<StickerSetBox>(controller, sticker->set),
|
||||||
|
LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +138,9 @@ void StickerSetBox::Show(DocumentData *document) {
|
||||||
void StickerSetBox::prepare() {
|
void StickerSetBox::prepare() {
|
||||||
setTitle(tr::lng_contacts_loading());
|
setTitle(tr::lng_contacts_loading());
|
||||||
|
|
||||||
_inner = setInnerWidget(object_ptr<Inner>(this, _set), st::stickersScroll);
|
_inner = setInnerWidget(
|
||||||
|
object_ptr<Inner>(this, _controller, _set),
|
||||||
|
st::stickersScroll);
|
||||||
Auth().data().stickersUpdated(
|
Auth().data().stickersUpdated(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
updateButtons();
|
updateButtons();
|
||||||
|
@ -176,14 +200,31 @@ void StickerSetBox::resizeEvent(QResizeEvent *e) {
|
||||||
_inner->resize(width(), _inner->height());
|
_inner->resize(width(), _inner->height());
|
||||||
}
|
}
|
||||||
|
|
||||||
StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TWidget(parent)
|
StickerSetBox::Inner::Inner(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
const MTPInputStickerSet &set)
|
||||||
|
: RpWidget(parent)
|
||||||
|
, _controller(controller)
|
||||||
, _input(set)
|
, _input(set)
|
||||||
, _previewTimer([=] { showPreview(); }) {
|
, _previewTimer([=] { showPreview(); }) {
|
||||||
switch (set.type()) {
|
set.match([&](const MTPDinputStickerSetID &data) {
|
||||||
case mtpc_inputStickerSetID: _setId = set.c_inputStickerSetID().vid.v; _setAccess = set.c_inputStickerSetID().vaccess_hash.v; break;
|
_setId = data.vid.v;
|
||||||
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
|
_setAccess = data.vaccess_hash.v;
|
||||||
}
|
}, [&](const MTPDinputStickerSetShortName &data) {
|
||||||
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&Inner::gotSet), rpcFail(&Inner::failedSet));
|
_setShortName = qs(data.vshort_name);
|
||||||
|
}, [&](const MTPDinputStickerSetEmpty &) {
|
||||||
|
});
|
||||||
|
|
||||||
|
_mtp.request(MTPmessages_GetStickerSet(
|
||||||
|
_input
|
||||||
|
)).done([=](const MTPmessages_StickerSet &result) {
|
||||||
|
gotSet(result);
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_loaded = true;
|
||||||
|
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
|
||||||
|
}).send();
|
||||||
|
|
||||||
Auth().api().updateStickers();
|
Auth().api().updateStickers();
|
||||||
|
|
||||||
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
subscribe(Auth().downloaderTaskFinished(), [this] { update(); });
|
||||||
|
@ -194,19 +235,21 @@ StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TW
|
||||||
void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
|
||||||
_pack.clear();
|
_pack.clear();
|
||||||
_emoji.clear();
|
_emoji.clear();
|
||||||
_packOvers.clear();
|
_elements.clear();
|
||||||
_selected = -1;
|
_selected = -1;
|
||||||
setCursor(style::cur_default);
|
setCursor(style::cur_default);
|
||||||
set.match([&](const MTPDmessages_stickerSet &data) {
|
set.match([&](const MTPDmessages_stickerSet &data) {
|
||||||
const auto &v = data.vdocuments.v;
|
const auto &v = data.vdocuments.v;
|
||||||
_pack.reserve(v.size());
|
_pack.reserve(v.size());
|
||||||
_packOvers.reserve(v.size());
|
_elements.reserve(v.size());
|
||||||
for (const auto &item : v) {
|
for (const auto &item : v) {
|
||||||
const auto document = Auth().data().processDocument(item);
|
const auto document = Auth().data().processDocument(item);
|
||||||
if (!document->sticker()) continue;
|
const auto sticker = document->sticker();
|
||||||
|
if (!sticker) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_pack.push_back(document);
|
_pack.push_back(document);
|
||||||
_packOvers.emplace_back();
|
_elements.push_back({ document });
|
||||||
}
|
}
|
||||||
for (const auto &pack : data.vpacks.v) {
|
for (const auto &pack : data.vpacks.v) {
|
||||||
pack.match([&](const MTPDstickerPack &pack) {
|
pack.match([&](const MTPDstickerPack &pack) {
|
||||||
|
@ -280,17 +323,8 @@ rpl::producer<> StickerSetBox::Inner::updateControls() const {
|
||||||
return _updateControls.events();
|
return _updateControls.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StickerSetBox::Inner::failedSet(const RPCError &error) {
|
void StickerSetBox::Inner::installDone(
|
||||||
if (MTP::isDefaultHandledError(error)) return false;
|
const MTPmessages_StickerSetInstallResult &result) {
|
||||||
|
|
||||||
_loaded = true;
|
|
||||||
|
|
||||||
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult &result) {
|
|
||||||
auto &sets = Auth().data().stickerSetsRef();
|
auto &sets = Auth().data().stickerSetsRef();
|
||||||
|
|
||||||
bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived);
|
bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived);
|
||||||
|
@ -356,14 +390,6 @@ void StickerSetBox::Inner::installDone(const MTPmessages_StickerSetInstallResult
|
||||||
_setInstalled.fire_copy(_setId);
|
_setInstalled.fire_copy(_setId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StickerSetBox::Inner::installFail(const RPCError &error) {
|
|
||||||
if (MTP::isDefaultHandledError(error)) return false;
|
|
||||||
|
|
||||||
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StickerSetBox::Inner::mousePressEvent(QMouseEvent *e) {
|
void StickerSetBox::Inner::mousePressEvent(QMouseEvent *e) {
|
||||||
int index = stickerFromGlobalPos(e->globalPos());
|
int index = stickerFromGlobalPos(e->globalPos());
|
||||||
if (index >= 0 && index < _pack.size()) {
|
if (index >= 0 && index < _pack.size()) {
|
||||||
|
@ -422,15 +448,16 @@ void StickerSetBox::Inner::setSelected(int selected) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::Inner::startOverAnimation(int index, float64 from, float64 to) {
|
void StickerSetBox::Inner::startOverAnimation(int index, float64 from, float64 to) {
|
||||||
if (index >= 0 && index < _packOvers.size()) {
|
if (index < 0 || index >= _elements.size()) {
|
||||||
_packOvers[index].start([this, index] {
|
return;
|
||||||
int row = index / kStickersPanelPerRow;
|
|
||||||
int column = index % kStickersPanelPerRow;
|
|
||||||
int left = st::stickersPadding.left() + column * st::stickersSize.width();
|
|
||||||
int top = st::stickersPadding.top() + row * st::stickersSize.height();
|
|
||||||
rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height());
|
|
||||||
}, from, to, st::emojiPanDuration);
|
|
||||||
}
|
}
|
||||||
|
_elements[index].overAnimation.start([=] {
|
||||||
|
const auto row = index / kStickersPanelPerRow;
|
||||||
|
const auto column = index % kStickersPanelPerRow;
|
||||||
|
const auto left = st::stickersPadding.left() + column * st::stickersSize.width();
|
||||||
|
const auto top = st::stickersPadding.top() + row * st::stickersSize.height();
|
||||||
|
rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height());
|
||||||
|
}, from, to, st::emojiPanDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickerSetBox::Inner::showPreview() {
|
void StickerSetBox::Inner::showPreview() {
|
||||||
|
@ -459,46 +486,89 @@ void StickerSetBox::Inner::paintEvent(QPaintEvent *e) {
|
||||||
QRect r(e->rect());
|
QRect r(e->rect());
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
if (_pack.isEmpty()) return;
|
if (_elements.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int32 rows = _pack.size() / kStickersPanelPerRow + ((_pack.size() % kStickersPanelPerRow) ? 1 : 0);
|
int32 rows = _elements.size() / kStickersPanelPerRow + ((_elements.size() % kStickersPanelPerRow) ? 1 : 0);
|
||||||
int32 from = qFloor(e->rect().top() / st::stickersSize.height()), to = qFloor(e->rect().bottom() / st::stickersSize.height()) + 1;
|
int32 from = qFloor(e->rect().top() / st::stickersSize.height()), to = qFloor(e->rect().bottom() / st::stickersSize.height()) + 1;
|
||||||
|
|
||||||
for (int32 i = from; i < to; ++i) {
|
for (int32 i = from; i < to; ++i) {
|
||||||
for (int32 j = 0; j < kStickersPanelPerRow; ++j) {
|
for (int32 j = 0; j < kStickersPanelPerRow; ++j) {
|
||||||
int32 index = i * kStickersPanelPerRow + j;
|
int32 index = i * kStickersPanelPerRow + j;
|
||||||
if (index >= _pack.size()) break;
|
if (index >= _elements.size()) {
|
||||||
Assert(index < _packOvers.size());
|
break;
|
||||||
|
|
||||||
DocumentData *doc = _pack.at(index);
|
|
||||||
QPoint pos(st::stickersPadding.left() + j * st::stickersSize.width(), st::stickersPadding.top() + i * st::stickersSize.height());
|
|
||||||
|
|
||||||
if (auto over = _packOvers[index].value((index == _selected) ? 1. : 0.)) {
|
|
||||||
p.setOpacity(over);
|
|
||||||
QPoint tl(pos);
|
|
||||||
if (rtl()) tl.setX(width() - tl.x() - st::stickersSize.width());
|
|
||||||
App::roundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, StickerHoverCorners);
|
|
||||||
p.setOpacity(1);
|
|
||||||
|
|
||||||
}
|
|
||||||
doc->checkStickerSmall();
|
|
||||||
|
|
||||||
float64 coef = qMin((st::stickersSize.width() - st::buttonRadius * 2) / float64(doc->dimensions.width()), (st::stickersSize.height() - st::buttonRadius * 2) / float64(doc->dimensions.height()));
|
|
||||||
if (coef > 1) coef = 1;
|
|
||||||
int32 w = qRound(coef * doc->dimensions.width()), h = qRound(coef * doc->dimensions.height());
|
|
||||||
if (w < 1) w = 1;
|
|
||||||
if (h < 1) h = 1;
|
|
||||||
QPoint ppos = pos + QPoint((st::stickersSize.width() - w) / 2, (st::stickersSize.height() - h) / 2);
|
|
||||||
if (const auto image = doc->getStickerSmall()) {
|
|
||||||
p.drawPixmapLeft(
|
|
||||||
ppos,
|
|
||||||
width(),
|
|
||||||
image->pix(doc->stickerSetOrigin(), w, h));
|
|
||||||
}
|
}
|
||||||
|
const auto pos = QPoint(st::stickersPadding.left() + j * st::stickersSize.width(), st::stickersPadding.top() + i * st::stickersSize.height());
|
||||||
|
paintSticker(p, index, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickerSetBox::Inner::setupLottie(int index) {
|
||||||
|
auto &element = _elements[index];
|
||||||
|
const auto document = element.document;
|
||||||
|
|
||||||
|
element.animated = document->data().isEmpty()
|
||||||
|
? Lottie::FromFile(document->filepath())
|
||||||
|
: Lottie::FromData(document->data());
|
||||||
|
const auto animation = element.animated.get();
|
||||||
|
|
||||||
|
animation->updates(
|
||||||
|
) | rpl::start_with_next_error([=](Lottie::Update update) {
|
||||||
|
this->update();
|
||||||
|
}, [=](Lottie::Error error) {
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickerSetBox::Inner::paintSticker(
|
||||||
|
Painter &p,
|
||||||
|
int index,
|
||||||
|
QPoint position) const {
|
||||||
|
if (const auto over = _elements[index].overAnimation.value((index == _selected) ? 1. : 0.)) {
|
||||||
|
p.setOpacity(over);
|
||||||
|
auto tl = position;
|
||||||
|
if (rtl()) tl.setX(width() - tl.x() - st::stickersSize.width());
|
||||||
|
App::roundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, StickerHoverCorners);
|
||||||
|
p.setOpacity(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &element = _elements[index];
|
||||||
|
const auto document = element.document;
|
||||||
|
document->checkStickerSmall();
|
||||||
|
|
||||||
|
if (document->sticker()->animated
|
||||||
|
&& !element.animated
|
||||||
|
&& document->loaded()) {
|
||||||
|
const_cast<Inner*>(this)->setupLottie(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 coef = qMin((st::stickersSize.width() - st::buttonRadius * 2) / float64(document->dimensions.width()), (st::stickersSize.height() - st::buttonRadius * 2) / float64(document->dimensions.height()));
|
||||||
|
if (coef > 1) coef = 1;
|
||||||
|
int32 w = qRound(coef * document->dimensions.width()), h = qRound(coef * document->dimensions.height());
|
||||||
|
if (w < 1) w = 1;
|
||||||
|
if (h < 1) h = 1;
|
||||||
|
QPoint ppos = position + QPoint((st::stickersSize.width() - w) / 2, (st::stickersSize.height() - h) / 2);
|
||||||
|
if (element.animated && element.animated->ready()) {
|
||||||
|
const auto size = QSize(w, h);
|
||||||
|
auto request = Lottie::FrameRequest();
|
||||||
|
request.resize = size * cIntRetinaFactor();
|
||||||
|
const auto paused = _controller->isGifPausedAtLeastFor(
|
||||||
|
Window::GifPauseReason::Layer);
|
||||||
|
if (!paused) {
|
||||||
|
element.animated->markFrameShown();
|
||||||
|
}
|
||||||
|
p.drawImage(
|
||||||
|
QRect(ppos, size),
|
||||||
|
element.animated->frame(request));
|
||||||
|
} else if (const auto image = document->getStickerSmall()) {
|
||||||
|
p.drawPixmapLeft(
|
||||||
|
ppos,
|
||||||
|
width(),
|
||||||
|
image->pix(document->stickerSetOrigin(), w, h));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool StickerSetBox::Inner::loaded() const {
|
bool StickerSetBox::Inner::loaded() const {
|
||||||
return _loaded && !_pack.isEmpty();
|
return _loaded && !_pack.isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -541,10 +611,17 @@ void StickerSetBox::Inner::install() {
|
||||||
Box<InformBox>(tr::lng_stickers_masks_pack(tr::now)),
|
Box<InformBox>(tr::lng_stickers_masks_pack(tr::now)),
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
return;
|
return;
|
||||||
|
} else if (_installRequest) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (_installRequest) return;
|
_installRequest = _mtp.request(MTPmessages_InstallStickerSet(
|
||||||
_installRequest = MTP::send(MTPmessages_InstallStickerSet(_input, MTP_bool(false)), rpcDone(&Inner::installDone), rpcFail(&Inner::installFail));
|
_input,
|
||||||
|
MTP_bool(false)
|
||||||
|
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
|
||||||
|
installDone(result);
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
Ui::show(Box<InformBox>(tr::lng_stickers_not_found(tr::now)));
|
||||||
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
StickerSetBox::Inner::~Inner() {
|
StickerSetBox::Inner::~Inner() = default;
|
||||||
}
|
|
||||||
|
|
|
@ -13,15 +13,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
class SessionController;
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class PlainShadow;
|
class PlainShadow;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class StickerSetBox : public BoxContent, public RPCSender {
|
class StickerSetBox : public BoxContent, public RPCSender {
|
||||||
public:
|
public:
|
||||||
StickerSetBox(QWidget*, const MTPInputStickerSet &set);
|
StickerSetBox(
|
||||||
|
QWidget*,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
const MTPInputStickerSet &set);
|
||||||
|
|
||||||
static void Show(DocumentData *document);
|
static void Show(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<DocumentData*> document);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
@ -34,6 +43,7 @@ private:
|
||||||
void addStickers();
|
void addStickers();
|
||||||
void shareStickers();
|
void shareStickers();
|
||||||
|
|
||||||
|
not_null<Window::SessionController*> _controller;
|
||||||
MTPInputStickerSet _set;
|
MTPInputStickerSet _set;
|
||||||
|
|
||||||
class Inner;
|
class Inner;
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
#include "chat_helpers/stickers.h"
|
#include "chat_helpers/stickers.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "boxes/sticker_set_box.h"
|
#include "boxes/sticker_set_box.h"
|
||||||
|
@ -1212,7 +1213,9 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
if (auto set = getSetByRow(row)) {
|
if (auto set = getSetByRow(row)) {
|
||||||
setSelected(SelectedRow());
|
setSelected(SelectedRow());
|
||||||
Ui::show(
|
Ui::show(
|
||||||
Box<StickerSetBox>(Stickers::inputSetId(*set)),
|
Box<StickerSetBox>(
|
||||||
|
App::wnd()->sessionController(),
|
||||||
|
Stickers::inputSetId(*set)),
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2360,7 +2360,7 @@ void StickersListWidget::displaySet(uint64 setId) {
|
||||||
if (it != sets.cend()) {
|
if (it != sets.cend()) {
|
||||||
_displayingSetId = setId;
|
_displayingSetId = setId;
|
||||||
auto box = Ui::show(
|
auto box = Ui::show(
|
||||||
Box<StickerSetBox>(Stickers::inputSetId(*it)),
|
Box<StickerSetBox>(controller(), Stickers::inputSetId(*it)),
|
||||||
LayerOption::KeepOther);
|
LayerOption::KeepOther);
|
||||||
connect(box, &QObject::destroyed, this, [this] {
|
connect(box, &QObject::destroyed, this, [this] {
|
||||||
_displayingSetId = 0;
|
_displayingSetId = 0;
|
||||||
|
|
|
@ -67,6 +67,7 @@ bool ShowStickerSet(const Match &match, const QVariant &context) {
|
||||||
}
|
}
|
||||||
Core::App().hideMediaView();
|
Core::App().hideMediaView();
|
||||||
Ui::show(Box<StickerSetBox>(
|
Ui::show(Box<StickerSetBox>(
|
||||||
|
App::wnd()->sessionController(),
|
||||||
MTP_inputStickerSetShortName(MTP_string(match->captured(1)))));
|
MTP_inputStickerSetShortName(MTP_string(match->captured(1)))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,17 +461,20 @@ void DocumentData::setattributes(
|
||||||
const QVector<MTPDocumentAttribute> &attributes) {
|
const QVector<MTPDocumentAttribute> &attributes) {
|
||||||
_flags &= ~(Flag::ImageType | kStreamingSupportedMask);
|
_flags &= ~(Flag::ImageType | kStreamingSupportedMask);
|
||||||
_flags |= kStreamingSupportedUnknown;
|
_flags |= kStreamingSupportedUnknown;
|
||||||
|
|
||||||
|
validateLottieSticker();
|
||||||
|
|
||||||
for (const auto &attribute : attributes) {
|
for (const auto &attribute : attributes) {
|
||||||
attribute.match([&](const MTPDdocumentAttributeImageSize & data) {
|
attribute.match([&](const MTPDdocumentAttributeImageSize &data) {
|
||||||
dimensions = QSize(data.vw.v, data.vh.v);
|
dimensions = QSize(data.vw.v, data.vh.v);
|
||||||
}, [&](const MTPDdocumentAttributeAnimated & data) {
|
}, [&](const MTPDdocumentAttributeAnimated &data) {
|
||||||
if (type == FileDocument
|
if (type == FileDocument
|
||||||
|| type == StickerDocument
|
|| type == StickerDocument
|
||||||
|| type == VideoDocument) {
|
|| type == VideoDocument) {
|
||||||
type = AnimatedDocument;
|
type = AnimatedDocument;
|
||||||
_additional = nullptr;
|
_additional = nullptr;
|
||||||
}
|
}
|
||||||
}, [&](const MTPDdocumentAttributeSticker & data) {
|
}, [&](const MTPDdocumentAttributeSticker &data) {
|
||||||
if (type == FileDocument) {
|
if (type == FileDocument) {
|
||||||
type = StickerDocument;
|
type = StickerDocument;
|
||||||
_additional = std::make_unique<StickerData>();
|
_additional = std::make_unique<StickerData>();
|
||||||
|
@ -483,7 +486,7 @@ void DocumentData::setattributes(
|
||||||
sticker()->set = data.vstickerset;
|
sticker()->set = data.vstickerset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [&](const MTPDdocumentAttributeVideo & data) {
|
}, [&](const MTPDdocumentAttributeVideo &data) {
|
||||||
if (type == FileDocument) {
|
if (type == FileDocument) {
|
||||||
type = data.is_round_message()
|
type = data.is_round_message()
|
||||||
? RoundVideoDocument
|
? RoundVideoDocument
|
||||||
|
@ -492,7 +495,7 @@ void DocumentData::setattributes(
|
||||||
_duration = data.vduration.v;
|
_duration = data.vduration.v;
|
||||||
setMaybeSupportsStreaming(data.is_supports_streaming());
|
setMaybeSupportsStreaming(data.is_supports_streaming());
|
||||||
dimensions = QSize(data.vw.v, data.vh.v);
|
dimensions = QSize(data.vw.v, data.vh.v);
|
||||||
}, [&](const MTPDdocumentAttributeAudio & data) {
|
}, [&](const MTPDdocumentAttributeAudio &data) {
|
||||||
if (type == FileDocument) {
|
if (type == FileDocument) {
|
||||||
if (data.is_voice()) {
|
if (data.is_voice()) {
|
||||||
type = VoiceDocument;
|
type = VoiceDocument;
|
||||||
|
@ -514,7 +517,7 @@ void DocumentData::setattributes(
|
||||||
songData->title = qs(data.vtitle);
|
songData->title = qs(data.vtitle);
|
||||||
songData->performer = qs(data.vperformer);
|
songData->performer = qs(data.vperformer);
|
||||||
}
|
}
|
||||||
}, [&](const MTPDdocumentAttributeFilename & data) {
|
}, [&](const MTPDdocumentAttributeFilename &data) {
|
||||||
_filename = qs(data.vfile_name);
|
_filename = qs(data.vfile_name);
|
||||||
|
|
||||||
// We don't want LTR/RTL mark/embedding/override/isolate chars
|
// We don't want LTR/RTL mark/embedding/override/isolate chars
|
||||||
|
@ -536,7 +539,6 @@ void DocumentData::setattributes(
|
||||||
}, [&](const MTPDdocumentAttributeHasStickers &data) {
|
}, [&](const MTPDdocumentAttributeHasStickers &data) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
validateLottieSticker();
|
|
||||||
if (type == StickerDocument) {
|
if (type == StickerDocument) {
|
||||||
if (dimensions.width() <= 0
|
if (dimensions.width() <= 0
|
||||||
|| dimensions.height() <= 0
|
|| dimensions.height() <= 0
|
||||||
|
@ -557,7 +559,6 @@ void DocumentData::setattributes(
|
||||||
|
|
||||||
void DocumentData::validateLottieSticker() {
|
void DocumentData::validateLottieSticker() {
|
||||||
if (type == FileDocument
|
if (type == FileDocument
|
||||||
&& _filename.endsWith(qstr(".tgs"))
|
|
||||||
&& _mimeString == qstr("application/x-tgsticker")
|
&& _mimeString == qstr("application/x-tgsticker")
|
||||||
&& _thumbnail) {
|
&& _thumbnail) {
|
||||||
type = StickerDocument;
|
type = StickerDocument;
|
||||||
|
@ -1179,8 +1180,12 @@ void DocumentData::checkStickerLarge() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentData::checkStickerSmall() {
|
void DocumentData::checkStickerSmall() {
|
||||||
if (thumbnailEnoughForSticker()) {
|
const auto data = sticker();
|
||||||
|
if ((data && data->animated) || thumbnailEnoughForSticker()) {
|
||||||
_thumbnail->load(stickerSetOrigin());
|
_thumbnail->load(stickerSetOrigin());
|
||||||
|
if (data && data->animated) {
|
||||||
|
automaticLoad(stickerSetOrigin(), nullptr);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
checkStickerLarge();
|
checkStickerLarge();
|
||||||
}
|
}
|
||||||
|
@ -1195,9 +1200,10 @@ Image *DocumentData::getStickerLarge() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Image *DocumentData::getStickerSmall() {
|
Image *DocumentData::getStickerSmall() {
|
||||||
if (thumbnailEnoughForSticker()) {
|
const auto data = sticker();
|
||||||
|
if ((data && data->animated) || thumbnailEnoughForSticker()) {
|
||||||
return _thumbnail->isNull() ? nullptr : _thumbnail.get();
|
return _thumbnail->isNull() ? nullptr : _thumbnail.get();
|
||||||
} else if (const auto data = sticker()) {
|
} else if (data) {
|
||||||
return data->image.get();
|
return data->image.get();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -1128,7 +1128,7 @@ void InnerWidget::copySelectedText() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::showStickerPackInfo(not_null<DocumentData*> document) {
|
void InnerWidget::showStickerPackInfo(not_null<DocumentData*> document) {
|
||||||
StickerSetBox::Show(document);
|
StickerSetBox::Show(_controller, document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerWidget::cancelContextDownload(not_null<DocumentData*> document) {
|
void InnerWidget::cancelContextDownload(not_null<DocumentData*> document) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "boxes/sticker_set_box.h"
|
#include "boxes/sticker_set_box.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#include "mainwindow.h" // App::wnd()->sessionController
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
|
||||||
namespace AdminLog {
|
namespace AdminLog {
|
||||||
|
@ -602,7 +603,9 @@ void GenerateItems(
|
||||||
lt_sticker_set,
|
lt_sticker_set,
|
||||||
textcmdLink(2, tr::lng_admin_log_changed_stickers_set(tr::now)));
|
textcmdLink(2, tr::lng_admin_log_changed_stickers_set(tr::now)));
|
||||||
auto setLink = std::make_shared<LambdaClickHandler>([set] {
|
auto setLink = std::make_shared<LambdaClickHandler>([set] {
|
||||||
Ui::show(Box<StickerSetBox>(set));
|
Ui::show(Box<StickerSetBox>(
|
||||||
|
App::wnd()->sessionController(),
|
||||||
|
set));
|
||||||
});
|
});
|
||||||
auto message = HistoryService::PreparedText { text };
|
auto message = HistoryService::PreparedText { text };
|
||||||
message.links.push_back(fromLink);
|
message.links.push_back(fromLink);
|
||||||
|
|
|
@ -1825,7 +1825,7 @@ void HistoryInner::copyContextImage(not_null<PhotoData*> photo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::showStickerPackInfo(not_null<DocumentData*> document) {
|
void HistoryInner::showStickerPackInfo(not_null<DocumentData*> document) {
|
||||||
StickerSetBox::Show(document);
|
StickerSetBox::Show(_controller, document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryInner::cancelContextDownload(not_null<DocumentData*> document) {
|
void HistoryInner::cancelContextDownload(not_null<DocumentData*> document) {
|
||||||
|
|
|
@ -50,7 +50,7 @@ QSize HistorySticker::countOptimalSize() {
|
||||||
|
|
||||||
if (!_packLink && sticker && sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
if (!_packLink && sticker && sticker->set.type() != mtpc_inputStickerSetEmpty) {
|
||||||
_packLink = std::make_shared<LambdaClickHandler>([document = _data] {
|
_packLink = std::make_shared<LambdaClickHandler>([document = _data] {
|
||||||
StickerSetBox::Show(document);
|
StickerSetBox::Show(App::wnd()->sessionController(), document);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_pixw = _data->dimensions.width();
|
_pixw = _data->dimensions.width();
|
||||||
|
@ -97,9 +97,6 @@ QSize HistorySticker::countCurrentSize(int newWidth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistorySticker::setupLottie() {
|
void HistorySticker::setupLottie() {
|
||||||
if (_lottie) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_lottie = _data->data().isEmpty()
|
_lottie = _data->data().isEmpty()
|
||||||
? Lottie::FromFile(_data->filepath())
|
? Lottie::FromFile(_data->filepath())
|
||||||
: Lottie::FromData(_data->data());
|
: Lottie::FromData(_data->data());
|
||||||
|
@ -128,7 +125,7 @@ void HistorySticker::draw(Painter &p, const QRect &r, TextSelection selection, c
|
||||||
auto sticker = _data->sticker();
|
auto sticker = _data->sticker();
|
||||||
if (!sticker) return;
|
if (!sticker) return;
|
||||||
|
|
||||||
if (sticker->animated && !_lottie && _data->loaded()) {
|
if (sticker->animated && _data->loaded() && !_lottie) {
|
||||||
const_cast<HistorySticker*>(this)->setupLottie();
|
const_cast<HistorySticker*>(this)->setupLottie();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
#include "mainwindow.h" // App::wnd()->sessionController
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ void CopyImage(not_null<PhotoData*> photo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowStickerPackInfo(not_null<DocumentData*> document) {
|
void ShowStickerPackInfo(not_null<DocumentData*> document) {
|
||||||
StickerSetBox::Show(document);
|
StickerSetBox::Show(App::wnd()->sessionController(), document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToggleFavedSticker(
|
void ToggleFavedSticker(
|
||||||
|
|
Loading…
Reference in New Issue