mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show featured custom sets in the panel.
This commit is contained in:
parent
ff55918da0
commit
b0fab8c987
11 changed files with 478 additions and 193 deletions
|
@ -1061,11 +1061,11 @@ bool StickersBox::Inner::Row::isRecentSet() const {
|
|||
}
|
||||
|
||||
bool StickersBox::Inner::Row::isMasksSet() const {
|
||||
return (set->flags & SetFlag::Masks);
|
||||
return (set->type() == Data::StickersType::Masks);
|
||||
}
|
||||
|
||||
bool StickersBox::Inner::Row::isEmojiSet() const {
|
||||
return (set->flags & SetFlag::Emoji);
|
||||
return (set->type() == Data::StickersType::Emoji);
|
||||
}
|
||||
|
||||
bool StickersBox::Inner::Row::isWebm() const {
|
||||
|
|
|
@ -31,6 +31,14 @@ stickersTrendingSubheaderFont: normalFont;
|
|||
stickersTrendingSubheaderFg: windowSubTextFg;
|
||||
stickersTrendingSubheaderTop: 31px;
|
||||
|
||||
emojiPanButtonRight: 7px;
|
||||
emojiPanButtonTop: 10px;
|
||||
emojiPanButton: RoundButton(defaultActiveButton) {
|
||||
width: -24px;
|
||||
height: 23px;
|
||||
textTop: 2px;
|
||||
}
|
||||
|
||||
stickersTrendingAddTop: 14px;
|
||||
stickersTrendingAdd: RoundButton(defaultActiveButton) {
|
||||
width: -16px;
|
||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/shadow.h"
|
||||
#include "ui/text/custom_emoji_instance.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/emoji_config.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
|
@ -31,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "core/application.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "facades.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
@ -363,6 +365,8 @@ EmojiListWidget::EmojiListWidget(
|
|||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Inner(parent, controller)
|
||||
, _localSetsManager(
|
||||
std::make_unique<LocalStickersManager>(&controller->session()))
|
||||
, _picker(this)
|
||||
, _showPickerTimer([=] { showPicker(); })
|
||||
, _repaintTimer([=] { invokeRepaints(); }) {
|
||||
|
@ -399,6 +403,16 @@ EmojiListWidget::EmojiListWidget(
|
|||
refreshCustom();
|
||||
resizeToWidth(width());
|
||||
}, lifetime());
|
||||
|
||||
rpl::single(
|
||||
rpl::empty
|
||||
) | rpl::then(
|
||||
style::PaletteChanged()
|
||||
) | rpl::start_with_next([=] {
|
||||
initButton(_add, tr::lng_stickers_featured_add(tr::now), false);
|
||||
initButton(_unlock, tr::lng_emoji_featured_unlock(tr::now), true);
|
||||
initButton(_restore, tr::lng_emoji_premium_restore(tr::now), true);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
EmojiListWidget::~EmojiListWidget() {
|
||||
|
@ -581,8 +595,6 @@ bool EmojiListWidget::enumerateSections(Callback callback) const {
|
|||
auto i = 0;
|
||||
auto info = SectionInfo();
|
||||
const auto session = &controller()->session();
|
||||
const auto premiumMayBeBought = !session->premium()
|
||||
&& session->premiumPossible();
|
||||
const auto next = [&] {
|
||||
info.rowsCount = (info.count + _columnCount - 1) / _columnCount;
|
||||
info.rowsTop = info.top
|
||||
|
@ -605,7 +617,7 @@ bool EmojiListWidget::enumerateSections(Callback callback) const {
|
|||
}
|
||||
for (auto §ion : _custom) {
|
||||
info.section = i++;
|
||||
info.premiumRequired = section.premium && premiumMayBeBought;
|
||||
info.premiumRequired = section.premiumRequired;
|
||||
info.count = int(section.list.size());
|
||||
if (!next()) {
|
||||
return false;
|
||||
|
@ -763,23 +775,13 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) {
|
|||
} else if (r.top() + r.height() <= info.top) {
|
||||
return false;
|
||||
}
|
||||
auto widthForTitle = emojiRight() - (st::emojiPanHeaderLeft - st::roundRadiusSmall);
|
||||
const auto buttonSelected = selectedButton
|
||||
? (selectedButton->section == info.section)
|
||||
: false;
|
||||
const auto widthForTitle = emojiRight()
|
||||
- (st::emojiPanHeaderLeft - st::roundRadiusSmall)
|
||||
- paintButtonGetWidth(p, info, buttonSelected, r);
|
||||
const auto skip = st::roundRadiusSmall;
|
||||
if (hasRemoveButton(info.section)) {
|
||||
auto &custom = _custom[info.section - kEmojiSectionCount];
|
||||
auto remove = removeButtonRect(info.section);
|
||||
if (remove.intersects(r)) {
|
||||
auto selected = selectedButton ? (selectedButton->section == info.section) : false;
|
||||
if (custom.ripple) {
|
||||
custom.ripple->paint(p, remove.x() + st::stickerPanRemoveSet.rippleAreaPosition.x(), remove.y() + st::stickerPanRemoveSet.rippleAreaPosition.y(), width());
|
||||
if (custom.ripple->empty()) {
|
||||
custom.ripple.reset();
|
||||
}
|
||||
}
|
||||
(selected ? st::stickerPanRemoveSet.iconOver : st::stickerPanRemoveSet.icon).paint(p, remove.topLeft() + st::stickerPanRemoveSet.iconPosition, width());
|
||||
}
|
||||
widthForTitle -= remove.width();
|
||||
}
|
||||
if (info.section > 0 && r.top() < info.rowsTop) {
|
||||
p.setFont(st::emojiPanHeaderFont);
|
||||
p.setPen(st::emojiPanHeaderFg);
|
||||
|
@ -1010,7 +1012,14 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
|||
} else if (auto button = std::get_if<OverButton>(&pressed)) {
|
||||
Assert(button->section >= kEmojiSectionCount
|
||||
&& button->section < kEmojiSectionCount + _custom.size());
|
||||
removeSet(_custom[button->section - kEmojiSectionCount].id);
|
||||
const auto id = _custom[button->section - kEmojiSectionCount].id;
|
||||
if (hasRemoveButton(button->section)) {
|
||||
removeSet(id);
|
||||
} else if (hasAddButton(button->section)) {
|
||||
_localSetsManager->install(id);
|
||||
} else {
|
||||
Settings::ShowPremium(controller(), u"animated_emoji"_q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1089,18 +1098,88 @@ bool EmojiListWidget::hasRemoveButton(int index) const {
|
|||
|| index >= kEmojiSectionCount + _custom.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
const auto &set = _custom[index - kEmojiSectionCount];
|
||||
return set.canRemove && !set.premiumRequired;
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::removeButtonRect(int index) const {
|
||||
auto buttonw = st::stickerPanRemoveSet.rippleAreaPosition.x()
|
||||
return removeButtonRect(sectionInfo(index));
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::removeButtonRect(const SectionInfo &info) const {
|
||||
const auto buttonw = st::stickerPanRemoveSet.rippleAreaPosition.x()
|
||||
+ st::stickerPanRemoveSet.rippleAreaSize;
|
||||
auto buttonh = st::stickerPanRemoveSet.height;
|
||||
auto buttonx = emojiRight() - st::emojiPanRemoveSkip - buttonw;
|
||||
auto buttony = sectionInfo(index).top + (st::emojiPanHeader - buttonh) / 2;
|
||||
const auto buttonh = st::stickerPanRemoveSet.height;
|
||||
const auto buttonx = emojiRight() - st::emojiPanRemoveSkip - buttonw;
|
||||
const auto buttony = info.top + (st::emojiPanHeader - buttonh) / 2;
|
||||
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||
}
|
||||
|
||||
bool EmojiListWidget::hasAddButton(int index) const {
|
||||
if (index < kEmojiSectionCount
|
||||
|| index >= kEmojiSectionCount + _custom.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto &set = _custom[index - kEmojiSectionCount];
|
||||
return !set.canRemove && !set.premiumRequired;
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::addButtonRect(int index) const {
|
||||
return buttonRect(sectionInfo(index), _add);
|
||||
}
|
||||
|
||||
bool EmojiListWidget::hasUnlockButton(int index) const {
|
||||
if (index < kEmojiSectionCount
|
||||
|| index >= kEmojiSectionCount + _custom.size()) {
|
||||
return false;
|
||||
}
|
||||
const auto &set = _custom[index - kEmojiSectionCount];
|
||||
return set.premiumRequired;
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::unlockButtonRect(int index) const {
|
||||
Expects(index >= kEmojiSectionCount
|
||||
&& index < kEmojiSectionCount + _custom.size());
|
||||
|
||||
return buttonRect(sectionInfo(index), rightButton(index));
|
||||
}
|
||||
|
||||
bool EmojiListWidget::hasButton(int index) const {
|
||||
if (index < kEmojiSectionCount
|
||||
|| index >= kEmojiSectionCount + _custom.size()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::buttonRect(int index) const {
|
||||
return hasRemoveButton(index)
|
||||
? removeButtonRect(index)
|
||||
: hasAddButton(index)
|
||||
? addButtonRect(index)
|
||||
: unlockButtonRect(index);
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::buttonRect(
|
||||
const SectionInfo &info,
|
||||
const RightButton &button) const {
|
||||
const auto buttonw = button.textWidth - st::emojiPanButton.width;
|
||||
const auto buttonh = st::emojiPanButton.height;
|
||||
const auto buttonx = emojiRight() - buttonw - st::emojiPanButtonRight;
|
||||
const auto buttony = info.top + st::emojiPanButtonTop;
|
||||
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||
}
|
||||
|
||||
auto EmojiListWidget::rightButton(int index) const -> const RightButton & {
|
||||
Expects(index >= kEmojiSectionCount
|
||||
&& index < kEmojiSectionCount + _custom.size());
|
||||
return hasAddButton(index)
|
||||
? _add
|
||||
: _custom[index - kEmojiSectionCount].canRemove
|
||||
? _restore
|
||||
: _unlock;
|
||||
}
|
||||
|
||||
int EmojiListWidget::emojiRight() const {
|
||||
return emojiLeft() + (_columnCount * _singleSize.width());
|
||||
}
|
||||
|
@ -1221,15 +1300,22 @@ void EmojiListWidget::refreshRecent() {
|
|||
|
||||
void EmojiListWidget::refreshCustom() {
|
||||
auto old = base::take(_custom);
|
||||
const auto owner = &controller()->session().data();
|
||||
const auto &order = owner->stickers().emojiSetsOrder();
|
||||
const auto &featured = owner->stickers().featuredEmojiSetsOrder();
|
||||
const auto session = &controller()->session();
|
||||
const auto premiumPossible = session->premiumPossible();
|
||||
const auto premiumMayBeBought = premiumPossible && !session->premium();
|
||||
const auto owner = &session->data();
|
||||
const auto &sets = owner->stickers().sets();
|
||||
for (const auto setId : ranges::views::concat(order, featured)) {
|
||||
const auto push = [&](uint64 setId, bool installed) {
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend() || it->second->stickers.isEmpty()) {
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
const auto canRemove = !!(it->second->flags
|
||||
& Data::StickersSetFlag::Installed);
|
||||
if (canRemove != installed) {
|
||||
return;
|
||||
}
|
||||
auto premium = false;
|
||||
const auto &list = it->second->stickers;
|
||||
const auto i = ranges::find(old, setId, &CustomSet::id);
|
||||
if (i != end(old)) {
|
||||
|
@ -1239,19 +1325,26 @@ void EmojiListWidget::refreshCustom() {
|
|||
return false;
|
||||
}
|
||||
for (auto k = 0; k != count; ++k) {
|
||||
if (!premium && list[k]->isPremiumEmoji()) {
|
||||
premium = true;
|
||||
}
|
||||
if (i->list[k].document != list[k]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
if (valid) {
|
||||
if (premium && !premiumPossible) {
|
||||
return;
|
||||
} else if (valid) {
|
||||
i->thumbnailDocument = it->second->lookupThumbnailDocument();
|
||||
i->canRemove = canRemove;
|
||||
i->premiumRequired = premium && premiumMayBeBought;
|
||||
i->ripple.reset();
|
||||
_custom.push_back(std::move(*i));
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto premium = false;
|
||||
auto set = std::vector<CustomOne>();
|
||||
set.reserve(list.size());
|
||||
for (const auto document : list) {
|
||||
|
@ -1260,13 +1353,13 @@ void EmojiListWidget::refreshCustom() {
|
|||
.instance = resolveCustomInstance(document, setId),
|
||||
.document = document,
|
||||
});
|
||||
if (document->isPremiumEmoji()) {
|
||||
if (!premium && document->isPremiumEmoji()) {
|
||||
premium = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (premium && !controller()->session().premiumPossible()) {
|
||||
continue;
|
||||
if (premium && !premiumPossible) {
|
||||
return;
|
||||
}
|
||||
_custom.push_back({
|
||||
.id = setId,
|
||||
|
@ -1274,13 +1367,22 @@ void EmojiListWidget::refreshCustom() {
|
|||
.thumbnailDocument = it->second->lookupThumbnailDocument(),
|
||||
.title = it->second->title,
|
||||
.list = std::move(set),
|
||||
.premium = premium,
|
||||
.canRemove = canRemove,
|
||||
.premiumRequired = premium && premiumMayBeBought,
|
||||
});
|
||||
};
|
||||
for (const auto setId : owner->stickers().emojiSetsOrder()) {
|
||||
push(setId, true);
|
||||
}
|
||||
for (const auto setId : owner->stickers().featuredEmojiSetsOrder()) {
|
||||
push(setId, false);
|
||||
}
|
||||
|
||||
_footer->refreshIcons(
|
||||
fillIcons(),
|
||||
nullptr,
|
||||
ValidateIconAnimations::None);
|
||||
update();
|
||||
}
|
||||
|
||||
auto EmojiListWidget::customInstanceWithLoader(
|
||||
|
@ -1419,6 +1521,64 @@ std::vector<StickerIcon> EmojiListWidget::fillIcons() {
|
|||
return result;
|
||||
}
|
||||
|
||||
int EmojiListWidget::paintButtonGetWidth(
|
||||
QPainter &p,
|
||||
const SectionInfo &info,
|
||||
bool selected,
|
||||
QRect clip) const {
|
||||
if (info.section < kEmojiSectionCount
|
||||
|| info.section >= kEmojiSectionCount + _custom.size()) {
|
||||
return 0;
|
||||
}
|
||||
auto &custom = _custom[info.section - kEmojiSectionCount];
|
||||
if (hasRemoveButton(info.section)) {
|
||||
const auto remove = removeButtonRect(info);
|
||||
if (remove.intersects(clip)) {
|
||||
if (custom.ripple) {
|
||||
custom.ripple->paint(
|
||||
p,
|
||||
remove.x() + st::stickerPanRemoveSet.rippleAreaPosition.x(),
|
||||
remove.y() + st::stickerPanRemoveSet.rippleAreaPosition.y(),
|
||||
width());
|
||||
if (custom.ripple->empty()) {
|
||||
custom.ripple.reset();
|
||||
}
|
||||
}
|
||||
(selected
|
||||
? st::stickerPanRemoveSet.iconOver
|
||||
: st::stickerPanRemoveSet.icon).paint(
|
||||
p,
|
||||
remove.topLeft() + st::stickerPanRemoveSet.iconPosition,
|
||||
width());
|
||||
}
|
||||
return remove.width();
|
||||
}
|
||||
const auto canAdd = hasAddButton(info.section);
|
||||
const auto &button = rightButton(info.section);
|
||||
const auto rect = buttonRect(info, button);
|
||||
p.drawImage(rect.topLeft(), selected ? button.backOver : button.back);
|
||||
if (custom.ripple) {
|
||||
const auto ripple = QColor(0, 0, 0, 36);
|
||||
custom.ripple->paint(p, rect.x(), rect.y(), width(), &ripple);
|
||||
if (custom.ripple->empty()) {
|
||||
custom.ripple.reset();
|
||||
}
|
||||
}
|
||||
p.setPen(!canAdd
|
||||
? st::premiumButtonFg
|
||||
: selected
|
||||
? st::emojiPanButton.textFgOver
|
||||
: st::emojiPanButton.textFg);
|
||||
p.setFont(st::emojiPanButton.font);
|
||||
p.drawText(
|
||||
rect.x() - (st::emojiPanButton.width / 2),
|
||||
(rect.y()
|
||||
+ st::emojiPanButton.textTop
|
||||
+ st::emojiPanButton.font->ascent),
|
||||
button.text);
|
||||
return rect.width();
|
||||
}
|
||||
|
||||
bool EmojiListWidget::eventHook(QEvent *e) {
|
||||
if (e->type() == QEvent::ParentChange) {
|
||||
if (_picker->parentWidget() != parentWidget()) {
|
||||
|
@ -1439,9 +1599,8 @@ void EmojiListWidget::updateSelected() {
|
|||
auto info = sectionInfoByOffset(p.y());
|
||||
auto section = info.section;
|
||||
if (p.y() >= info.top && p.y() < info.rowsTop) {
|
||||
if (hasRemoveButton(section)
|
||||
&& myrtlrect(
|
||||
removeButtonRect(section)).contains(p.x(), p.y())) {
|
||||
if (hasButton(section)
|
||||
&& myrtlrect(buttonRect(section)).contains(p.x(), p.y())) {
|
||||
newSelected = OverButton{ section };
|
||||
} else if (section >= kEmojiSectionCount) {
|
||||
newSelected = OverSet{ section };
|
||||
|
@ -1470,7 +1629,7 @@ void EmojiListWidget::setSelected(OverState newSelected) {
|
|||
if (const auto sticker = std::get_if<OverEmoji>(&_selected)) {
|
||||
rtlupdate(emojiRect(sticker->section, sticker->index));
|
||||
} else if (const auto button = std::get_if<OverButton>(&_selected)) {
|
||||
rtlupdate(removeButtonRect(button->section));
|
||||
rtlupdate(buttonRect(button->section));
|
||||
}
|
||||
};
|
||||
updateSelected();
|
||||
|
@ -1513,27 +1672,72 @@ void EmojiListWidget::setPressed(OverState newPressed) {
|
|||
}
|
||||
}
|
||||
|
||||
void EmojiListWidget::initButton(
|
||||
RightButton &button,
|
||||
const QString &text,
|
||||
bool gradient) {
|
||||
button.text = text;
|
||||
button.textWidth = st::emojiPanButton.font->width(text);
|
||||
const auto width = button.textWidth - st::emojiPanButton.width;
|
||||
const auto height = st::emojiPanButton.height;
|
||||
const auto factor = style::DevicePixelRatio();
|
||||
auto prepare = [&](QColor bg, QBrush fg) {
|
||||
auto image = QImage(
|
||||
QSize(width, height) * factor,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
image.setDevicePixelRatio(factor);
|
||||
image.fill(Qt::transparent);
|
||||
auto p = QPainter(&image);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(fg);
|
||||
const auto radius = height / 2.;
|
||||
p.drawRoundedRect(QRect(0, 0, width, height), radius, radius);
|
||||
p.end();
|
||||
return image;
|
||||
};
|
||||
button.back = prepare(Qt::transparent, [&]() -> QBrush {
|
||||
if (gradient) {
|
||||
auto result = QLinearGradient(QPointF(0, 0), QPointF(width, 0));
|
||||
result.setStops(Ui::Premium::ButtonGradientStops());
|
||||
return result;
|
||||
}
|
||||
return st::emojiPanButton.textBg;
|
||||
}());
|
||||
button.backOver = gradient
|
||||
? button.back
|
||||
: prepare(Qt::transparent, st::emojiPanButton.textBgOver);
|
||||
button.rippleMask = prepare(Qt::black, Qt::white);
|
||||
}
|
||||
|
||||
std::unique_ptr<Ui::RippleAnimation> EmojiListWidget::createButtonRipple(
|
||||
int section) {
|
||||
Expects(section >= kEmojiSectionCount
|
||||
&& section < kEmojiSectionCount + _custom.size());
|
||||
|
||||
auto maskSize = QSize(
|
||||
st::stickerPanRemoveSet.rippleAreaSize,
|
||||
st::stickerPanRemoveSet.rippleAreaSize);
|
||||
auto mask = Ui::RippleAnimation::ellipseMask(maskSize);
|
||||
const auto remove = hasRemoveButton(section);
|
||||
const auto &st = remove
|
||||
? st::stickerPanRemoveSet.ripple
|
||||
: st::emojiPanButton.ripple;
|
||||
auto mask = remove
|
||||
? Ui::RippleAnimation::ellipseMask(QSize(
|
||||
st::stickerPanRemoveSet.rippleAreaSize,
|
||||
st::stickerPanRemoveSet.rippleAreaSize))
|
||||
: rightButton(section).rippleMask;
|
||||
return std::make_unique<Ui::RippleAnimation>(
|
||||
st::stickerPanRemoveSet.ripple,
|
||||
st,
|
||||
std::move(mask),
|
||||
[this, section] { rtlupdate(removeButtonRect(section)); });
|
||||
[this, section] { rtlupdate(buttonRect(section)); });
|
||||
}
|
||||
|
||||
QPoint EmojiListWidget::buttonRippleTopLeft(int section) const {
|
||||
Expects(section >= kEmojiSectionCount
|
||||
&& section < kEmojiSectionCount + _custom.size());
|
||||
|
||||
return myrtlrect(removeButtonRect(section)).topLeft()
|
||||
+ st::stickerPanRemoveSet.rippleAreaPosition;
|
||||
return myrtlrect(buttonRect(section)).topLeft()
|
||||
+ (hasRemoveButton(section)
|
||||
? st::stickerPanRemoveSet.rippleAreaPosition
|
||||
: QPoint());
|
||||
}
|
||||
|
||||
void EmojiListWidget::showEmojiSection(Section section) {
|
||||
|
|
|
@ -49,6 +49,7 @@ inline constexpr auto kEmojiSectionCount = 8;
|
|||
struct StickerIcon;
|
||||
class EmojiColorPicker;
|
||||
class StickersListFooter;
|
||||
class LocalStickersManager;
|
||||
|
||||
class EmojiListWidget
|
||||
: public TabbedSelector::Inner
|
||||
|
@ -120,9 +121,17 @@ private:
|
|||
DocumentData *thumbnailDocument = nullptr;
|
||||
QString title;
|
||||
std::vector<CustomOne> list;
|
||||
std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
mutable std::unique_ptr<Ui::RippleAnimation> ripple;
|
||||
bool painted = false;
|
||||
bool premium = false;
|
||||
bool canRemove = false;
|
||||
bool premiumRequired = false;
|
||||
};
|
||||
struct RightButton {
|
||||
QImage back;
|
||||
QImage backOver;
|
||||
QImage rippleMask;
|
||||
QString text;
|
||||
int textWidth = 0;
|
||||
};
|
||||
struct RecentOne;
|
||||
struct RepaintSet {
|
||||
|
@ -210,15 +219,32 @@ private:
|
|||
int index);
|
||||
[[nodiscard]] bool hasRemoveButton(int index) const;
|
||||
[[nodiscard]] QRect removeButtonRect(int index) const;
|
||||
[[nodiscard]] QRect removeButtonRect(const SectionInfo &info) const;
|
||||
[[nodiscard]] bool hasAddButton(int index) const;
|
||||
[[nodiscard]] QRect addButtonRect(int index) const;
|
||||
[[nodiscard]] bool hasUnlockButton(int index) const;
|
||||
[[nodiscard]] QRect unlockButtonRect(int index) const;
|
||||
[[nodiscard]] bool hasButton(int index) const;
|
||||
[[nodiscard]] QRect buttonRect(int index) const;
|
||||
[[nodiscard]] QRect buttonRect(
|
||||
const SectionInfo &info,
|
||||
const RightButton &button) const;
|
||||
[[nodiscard]] const RightButton &rightButton(int index) const;
|
||||
[[nodiscard]] QRect emojiRect(int section, int index) const;
|
||||
[[nodiscard]] int emojiRight() const;
|
||||
[[nodiscard]] int emojiLeft() const;
|
||||
[[nodiscard]] uint64 sectionSetId(int section) const;
|
||||
[[nodiscard]] std::vector<StickerIcon> fillIcons();
|
||||
int paintButtonGetWidth(
|
||||
QPainter &p,
|
||||
const SectionInfo &info,
|
||||
bool selected,
|
||||
QRect clip) const;
|
||||
|
||||
void displaySet(uint64 setId);
|
||||
void removeSet(uint64 setId);
|
||||
|
||||
void initButton(RightButton &button, const QString &text, bool gradient);
|
||||
[[nodiscard]] std::unique_ptr<Ui::RippleAnimation> createButtonRipple(
|
||||
int section);
|
||||
[[nodiscard]] QPoint buttonRippleTopLeft(int section) const;
|
||||
|
@ -246,6 +272,7 @@ private:
|
|||
uint64 setId);
|
||||
|
||||
StickersListFooter *_footer = nullptr;
|
||||
std::unique_ptr<LocalStickersManager> _localSetsManager;
|
||||
|
||||
int _counts[kEmojiSectionCount];
|
||||
std::vector<RecentOne> _recent;
|
||||
|
@ -261,6 +288,10 @@ private:
|
|||
QPoint _areaPosition;
|
||||
QPoint _innerPosition;
|
||||
|
||||
RightButton _add;
|
||||
RightButton _unlock;
|
||||
RightButton _restore;
|
||||
|
||||
OverState _selected;
|
||||
OverState _pressed;
|
||||
OverState _pickerSelected;
|
||||
|
|
|
@ -1275,4 +1275,79 @@ void StickersListFooter::paintSetIcon(
|
|||
}
|
||||
}
|
||||
|
||||
LocalStickersManager::LocalStickersManager(not_null<Main::Session*> session)
|
||||
: _session(session)
|
||||
, _api(&session->mtp()) {
|
||||
}
|
||||
|
||||
void LocalStickersManager::install(uint64 setId) {
|
||||
const auto &sets = _session->data().stickers().sets();
|
||||
const auto it = sets.find(setId);
|
||||
if (it == sets.cend()) {
|
||||
return;
|
||||
}
|
||||
const auto set = it->second.get();
|
||||
const auto input = set->mtpInput();
|
||||
if (!(set->flags & Data::StickersSetFlag::NotLoaded)
|
||||
&& !set->stickers.empty()) {
|
||||
sendInstallRequest(setId, input);
|
||||
return;
|
||||
}
|
||||
_api.request(MTPmessages_GetStickerSet(
|
||||
input,
|
||||
MTP_int(0) // hash
|
||||
)).done([=](const MTPmessages_StickerSet &result) {
|
||||
result.match([&](const MTPDmessages_stickerSet &data) {
|
||||
_session->data().stickers().feedSetFull(data);
|
||||
}, [](const MTPDmessages_stickerSetNotModified &) {
|
||||
LOG(("API Error: Unexpected messages.stickerSetNotModified."));
|
||||
});
|
||||
sendInstallRequest(setId, input);
|
||||
}).send();
|
||||
}
|
||||
|
||||
bool LocalStickersManager::isInstalledLocally(uint64 setId) const {
|
||||
return _installedLocallySets.contains(setId);
|
||||
}
|
||||
|
||||
void LocalStickersManager::sendInstallRequest(
|
||||
uint64 setId,
|
||||
const MTPInputStickerSet &input) {
|
||||
_api.request(MTPmessages_InstallStickerSet(
|
||||
input,
|
||||
MTP_bool(false)
|
||||
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
|
||||
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
|
||||
_session->data().stickers().applyArchivedResult(
|
||||
result.c_messages_stickerSetInstallResultArchive());
|
||||
}
|
||||
}).fail([=] {
|
||||
notInstalledLocally(setId);
|
||||
_session->data().stickers().undoInstallLocally(setId);
|
||||
}).send();
|
||||
|
||||
installedLocally(setId);
|
||||
_session->data().stickers().installLocally(setId);
|
||||
}
|
||||
|
||||
void LocalStickersManager::installedLocally(uint64 setId) {
|
||||
_installedLocallySets.insert(setId);
|
||||
}
|
||||
|
||||
void LocalStickersManager::notInstalledLocally(uint64 setId) {
|
||||
_installedLocallySets.remove(setId);
|
||||
}
|
||||
|
||||
void LocalStickersManager::removeInstalledLocally(uint64 setId) {
|
||||
_installedLocallySets.remove(setId);
|
||||
}
|
||||
|
||||
bool LocalStickersManager::clearInstalledLocally() {
|
||||
if (_installedLocallySets.empty()) {
|
||||
return false;
|
||||
}
|
||||
_installedLocallySets.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "media/clip/media_clip_reader.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "mtproto/sender.h"
|
||||
#include "ui/round_rect.h"
|
||||
|
||||
namespace Ui {
|
||||
|
@ -251,4 +252,27 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class LocalStickersManager final {
|
||||
public:
|
||||
explicit LocalStickersManager(not_null<Main::Session*> session);
|
||||
|
||||
void install(uint64 setId);
|
||||
[[nodiscard]] bool isInstalledLocally(uint64 setId) const;
|
||||
void removeInstalledLocally(uint64 setId);
|
||||
bool clearInstalledLocally();
|
||||
|
||||
private:
|
||||
void sendInstallRequest(
|
||||
uint64 setId,
|
||||
const MTPInputStickerSet &input);
|
||||
void installedLocally(uint64 setId);
|
||||
void notInstalledLocally(uint64 setId);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
||||
base::flat_set<uint64> _installedLocallySets;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|
|
@ -165,6 +165,8 @@ StickersListWidget::StickersListWidget(
|
|||
bool masks)
|
||||
: Inner(parent, controller)
|
||||
, _api(&controller->session().mtp())
|
||||
, _localSetsManager(
|
||||
std::make_unique<LocalStickersManager>(&controller->session()))
|
||||
, _section(Section::Stickers)
|
||||
, _isMasks(masks)
|
||||
, _updateItemsTimer([=] { updateItems(); })
|
||||
|
@ -495,21 +497,6 @@ int StickersListWidget::countDesiredHeight(int newWidth) {
|
|||
+ st::stickerPanPadding;
|
||||
}
|
||||
|
||||
void StickersListWidget::installedLocally(uint64 setId) {
|
||||
_installedLocallySets.insert(setId);
|
||||
}
|
||||
|
||||
void StickersListWidget::notInstalledLocally(uint64 setId) {
|
||||
_installedLocallySets.remove(setId);
|
||||
}
|
||||
|
||||
void StickersListWidget::clearInstalledLocally() {
|
||||
if (!_installedLocallySets.empty()) {
|
||||
_installedLocallySets.clear();
|
||||
refreshStickers();
|
||||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::sendSearchRequest() {
|
||||
if (_searchRequestId || _searchNextQuery.isEmpty()) {
|
||||
return;
|
||||
|
@ -851,7 +838,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
|
||||
auto widthForTitle = stickersRight() - (st::emojiPanHeaderLeft - st::roundRadiusSmall);
|
||||
if (featuredHasAddButton(info.section)) {
|
||||
auto add = featuredAddRect(info.section);
|
||||
auto add = featuredAddRect(info);
|
||||
auto selected = selectedButton ? (selectedButton->section == info.section) : false;
|
||||
auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg;
|
||||
|
||||
|
@ -868,7 +855,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
|
||||
widthForTitle -= add.width() - (st::stickersTrendingAdd.width / 2);
|
||||
} else {
|
||||
auto add = featuredAddRect(info.section);
|
||||
auto add = featuredAddRect(info);
|
||||
int checkx = add.left() + (add.width() - st::stickersFeaturedInstalled.width()) / 2;
|
||||
int checky = add.top() + (add.height() - st::stickersFeaturedInstalled.height()) / 2;
|
||||
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
|
||||
|
@ -924,7 +911,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
|
|||
auto titleWidth = st::stickersTrendingHeaderFont->width(titleText);
|
||||
auto widthForTitle = stickersRight() - (st::emojiPanHeaderLeft - st::roundRadiusSmall);
|
||||
if (hasRemoveButton(info.section)) {
|
||||
auto remove = removeButtonRect(info.section);
|
||||
auto remove = removeButtonRect(info);
|
||||
auto selected = selectedButton ? (selectedButton->section == info.section) : false;
|
||||
if (set.ripple) {
|
||||
set.ripple->paint(p, remove.x() + st::stickerPanRemoveSet.rippleAreaPosition.x(), remove.y() + st::stickerPanRemoveSet.rippleAreaPosition.y(), width());
|
||||
|
@ -1430,10 +1417,14 @@ bool StickersListWidget::featuredHasAddButton(int index) const {
|
|||
}
|
||||
|
||||
QRect StickersListWidget::featuredAddRect(int index) const {
|
||||
return featuredAddRect(sectionInfo(index));
|
||||
}
|
||||
|
||||
QRect StickersListWidget::featuredAddRect(const SectionInfo &info) const {
|
||||
auto addw = _addWidth - st::stickersTrendingAdd.width;
|
||||
auto addh = st::stickersTrendingAdd.height;
|
||||
auto addx = stickersRight() - addw;
|
||||
auto addy = sectionInfo(index).top + st::stickersTrendingAddTop;
|
||||
auto addy = info.top + st::stickersTrendingAddTop;
|
||||
return QRect(addx, addy, addw, addh);
|
||||
}
|
||||
|
||||
|
@ -1460,10 +1451,14 @@ bool StickersListWidget::hasRemoveButton(int index) const {
|
|||
}
|
||||
|
||||
QRect StickersListWidget::removeButtonRect(int index) const {
|
||||
return removeButtonRect(sectionInfo(index));
|
||||
}
|
||||
|
||||
QRect StickersListWidget::removeButtonRect(const SectionInfo &info) const {
|
||||
auto buttonw = st::stickerPanRemoveSet.width;
|
||||
auto buttonh = st::stickerPanRemoveSet.height;
|
||||
auto buttonx = stickersRight() - buttonw;
|
||||
auto buttony = sectionInfo(index).top + (st::emojiPanHeader - buttonh) / 2;
|
||||
auto buttony = info.top + (st::emojiPanHeader - buttonh) / 2;
|
||||
return QRect(buttonx, buttony, buttonw, buttonh);
|
||||
}
|
||||
|
||||
|
@ -1692,7 +1687,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
|
|||
} else if (auto button = std::get_if<OverButton>(&pressed)) {
|
||||
Assert(button->section >= 0 && button->section < sets.size());
|
||||
if (sets[button->section].externalLayout) {
|
||||
installSet(sets[button->section].id);
|
||||
_localSetsManager->install(sets[button->section].id);
|
||||
} else if (sets[button->section].id == Data::Stickers::MegagroupSetId) {
|
||||
auto removeLocally = sets[button->section].stickers.empty()
|
||||
|| !_megagroupSet->canEditStickers();
|
||||
|
@ -1823,7 +1818,9 @@ void StickersListWidget::processHideFinished() {
|
|||
}
|
||||
|
||||
void StickersListWidget::processPanelHideFinished() {
|
||||
clearInstalledLocally();
|
||||
if (_localSetsManager->clearInstalledLocally()) {
|
||||
refreshStickers();
|
||||
}
|
||||
clearHeavyData();
|
||||
if (_footer) {
|
||||
_footer->clearHeavyData();
|
||||
|
@ -1925,7 +1922,7 @@ void StickersListWidget::refreshFeaturedSets() {
|
|||
if (it == sets.cend()
|
||||
|| ((it->second->flags & SetFlag::Installed)
|
||||
&& !(it->second->flags & SetFlag::Archived)
|
||||
&& !_installedLocallySets.contains(set.id))) {
|
||||
&& !_localSetsManager->isInstalledLocally(set.id))) {
|
||||
continue;
|
||||
}
|
||||
set.flags = it->second->flags;
|
||||
|
@ -1949,7 +1946,7 @@ void StickersListWidget::refreshSearchSets() {
|
|||
entry.stickers = std::move(elements);
|
||||
}
|
||||
if (!SetInMyList(entry.flags)) {
|
||||
_installedLocallySets.remove(entry.id);
|
||||
_localSetsManager->removeInstalledLocally(entry.id);
|
||||
entry.externalLayout = true;
|
||||
}
|
||||
}
|
||||
|
@ -2017,7 +2014,7 @@ bool StickersListWidget::appendSet(
|
|||
if ((skip == AppendSkip::Installed)
|
||||
&& (set->flags & SetFlag::Installed)
|
||||
&& !(set->flags & SetFlag::Archived)) {
|
||||
if (!_installedLocallySets.contains(setId)) {
|
||||
if (!_localSetsManager->isInstalledLocally(setId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2379,22 +2376,22 @@ void StickersListWidget::updateSelected() {
|
|||
auto info = sectionInfoByOffset(p.y());
|
||||
auto section = info.section;
|
||||
if (p.y() >= info.top && p.y() < info.rowsTop) {
|
||||
if (hasRemoveButton(section) && myrtlrect(removeButtonRect(section)).contains(p.x(), p.y())) {
|
||||
newSelected = OverButton { section };
|
||||
} else if (featuredHasAddButton(section) && myrtlrect(featuredAddRect(section)).contains(p.x(), p.y())) {
|
||||
if (hasRemoveButton(section) && myrtlrect(removeButtonRect(info)).contains(p.x(), p.y())) {
|
||||
newSelected = OverButton{ section };
|
||||
} else if (featuredHasAddButton(section) && myrtlrect(featuredAddRect(info)).contains(p.x(), p.y())) {
|
||||
newSelected = OverButton{ section };
|
||||
} else if (!(sets[section].flags & SetFlag::Special)) {
|
||||
newSelected = OverSet { section };
|
||||
newSelected = OverSet{ section };
|
||||
} else if (sets[section].id == Data::Stickers::MegagroupSetId
|
||||
&& (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) {
|
||||
newSelected = OverSet { section };
|
||||
newSelected = OverSet{ section };
|
||||
}
|
||||
} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) {
|
||||
auto yOffset = p.y() - info.rowsTop;
|
||||
auto &set = sets[section];
|
||||
if (set.id == Data::Stickers::MegagroupSetId && set.stickers.empty()) {
|
||||
if (_megagroupSetButtonRect.contains(stickersLeft() + sx, yOffset)) {
|
||||
newSelected = OverGroupAdd {};
|
||||
newSelected = OverGroupAdd{};
|
||||
}
|
||||
} else {
|
||||
auto rowIndex = qFloor(yOffset / _singleSize.height());
|
||||
|
@ -2616,50 +2613,6 @@ void StickersListWidget::displaySet(uint64 setId) {
|
|||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::installSet(uint64 setId) {
|
||||
const auto &sets = session().data().stickers().sets();
|
||||
const auto it = sets.find(setId);
|
||||
if (it != sets.cend()) {
|
||||
const auto set = it->second.get();
|
||||
const auto input = set->mtpInput();
|
||||
if ((set->flags & SetFlag::NotLoaded) || set->stickers.empty()) {
|
||||
_api.request(MTPmessages_GetStickerSet(
|
||||
input,
|
||||
MTP_int(0) // hash
|
||||
)).done([=](const MTPmessages_StickerSet &result) {
|
||||
result.match([&](const MTPDmessages_stickerSet &data) {
|
||||
session().data().stickers().feedSetFull(data);
|
||||
}, [](const MTPDmessages_stickerSetNotModified &) {
|
||||
LOG(("API Error: Unexpected messages.stickerSetNotModified."));
|
||||
});
|
||||
sendInstallRequest(setId, input);
|
||||
}).send();
|
||||
} else {
|
||||
sendInstallRequest(setId, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StickersListWidget::sendInstallRequest(
|
||||
uint64 setId,
|
||||
const MTPInputStickerSet &input) {
|
||||
_api.request(MTPmessages_InstallStickerSet(
|
||||
input,
|
||||
MTP_bool(false)
|
||||
)).done([=](const MTPmessages_StickerSetInstallResult &result) {
|
||||
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
|
||||
session().data().stickers().applyArchivedResult(
|
||||
result.c_messages_stickerSetInstallResultArchive());
|
||||
}
|
||||
}).fail([=] {
|
||||
notInstalledLocally(setId);
|
||||
session().data().stickers().undoInstallLocally(setId);
|
||||
}).send();
|
||||
|
||||
installedLocally(setId);
|
||||
session().data().stickers().installLocally(setId);
|
||||
}
|
||||
|
||||
void StickersListWidget::removeMegagroupSet(bool locally) {
|
||||
if (locally) {
|
||||
session().settings().setGroupStickersSectionHidden(_megagroupSet->id);
|
||||
|
@ -2693,15 +2646,15 @@ void StickersListWidget::removeSet(uint64 setId) {
|
|||
}
|
||||
|
||||
const Data::StickersSetsOrder &StickersListWidget::defaultSetsOrder() const {
|
||||
return !_isMasks
|
||||
? session().data().stickers().setsOrder()
|
||||
: session().data().stickers().maskSetsOrder();
|
||||
return _isMasks
|
||||
? session().data().stickers().maskSetsOrder()
|
||||
: session().data().stickers().setsOrder();
|
||||
}
|
||||
|
||||
Data::StickersSetsOrder &StickersListWidget::defaultSetsOrderRef() {
|
||||
return !_isMasks
|
||||
? session().data().stickers().setsOrderRef()
|
||||
: session().data().stickers().maskSetsOrderRef();
|
||||
return _isMasks
|
||||
? session().data().stickers().maskSetsOrderRef()
|
||||
: session().data().stickers().setsOrderRef();
|
||||
}
|
||||
|
||||
bool StickersListWidget::mySetsEmpty() const {
|
||||
|
@ -2762,9 +2715,9 @@ object_ptr<Ui::BoxContent> MakeConfirmRemoveSetBox(
|
|||
// && !(set->flags & SetFlag::Special)) {
|
||||
// sets.erase(it);
|
||||
//}
|
||||
auto &orderRef = (set->flags & SetFlag::Emoji)
|
||||
auto &orderRef = (set->type() == Data::StickersType::Emoji)
|
||||
? session->data().stickers().emojiSetsOrderRef()
|
||||
: (set->flags & SetFlag::Masks)
|
||||
: (set->type() == Data::StickersType::Masks)
|
||||
? session->data().stickers().maskSetsOrderRef()
|
||||
: session->data().stickers().setsOrderRef();
|
||||
const auto removeIndex = orderRef.indexOf(setId);
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace ChatHelpers {
|
|||
struct StickerIcon;
|
||||
enum class ValidateIconAnimations;
|
||||
class StickersListFooter;
|
||||
class LocalStickersManager;
|
||||
|
||||
class StickersListWidget final : public TabbedSelector::Inner {
|
||||
public:
|
||||
|
@ -78,10 +79,6 @@ public:
|
|||
|
||||
uint64 currentSet(int yOffset) const;
|
||||
|
||||
void installedLocally(uint64 setId);
|
||||
void notInstalledLocally(uint64 setId);
|
||||
void clearInstalledLocally();
|
||||
|
||||
void sendSearchRequest();
|
||||
void searchForSets(const QString &query);
|
||||
|
||||
|
@ -202,12 +199,8 @@ private:
|
|||
|
||||
void setSection(Section section);
|
||||
void displaySet(uint64 setId);
|
||||
void installSet(uint64 setId);
|
||||
void removeMegagroupSet(bool locally);
|
||||
void removeSet(uint64 setId);
|
||||
void sendInstallRequest(
|
||||
uint64 setId,
|
||||
const MTPInputStickerSet &input);
|
||||
void refreshMySets();
|
||||
void refreshFeaturedSets();
|
||||
void refreshSearchSets();
|
||||
|
@ -277,14 +270,16 @@ private:
|
|||
const SectionInfo &info,
|
||||
crl::time now);
|
||||
|
||||
int stickersRight() const;
|
||||
bool featuredHasAddButton(int index) const;
|
||||
QRect featuredAddRect(int index) const;
|
||||
bool hasRemoveButton(int index) const;
|
||||
QRect removeButtonRect(int index) const;
|
||||
int megagroupSetInfoLeft() const;
|
||||
[[nodiscard]] int stickersRight() const;
|
||||
[[nodiscard]] bool featuredHasAddButton(int index) const;
|
||||
[[nodiscard]] QRect featuredAddRect(int index) const;
|
||||
[[nodiscard]] QRect featuredAddRect(const SectionInfo &info) const;
|
||||
[[nodiscard]] bool hasRemoveButton(int index) const;
|
||||
[[nodiscard]] QRect removeButtonRect(int index) const;
|
||||
[[nodiscard]] QRect removeButtonRect(const SectionInfo &info) const;
|
||||
[[nodiscard]] int megagroupSetInfoLeft() const;
|
||||
void refreshMegagroupSetGeometry();
|
||||
QRect megagroupSetButtonRectFinal() const;
|
||||
[[nodiscard]] QRect megagroupSetButtonRectFinal() const;
|
||||
|
||||
[[nodiscard]] const Data::StickersSetsOrder &defaultSetsOrder() const;
|
||||
[[nodiscard]] Data::StickersSetsOrder &defaultSetsOrderRef();
|
||||
|
@ -332,6 +327,7 @@ private:
|
|||
not_null<DocumentData*> document);
|
||||
|
||||
MTP::Sender _api;
|
||||
std::unique_ptr<LocalStickersManager> _localSetsManager;
|
||||
ChannelData *_megagroupSet = nullptr;
|
||||
uint64 _megagroupSetIdRequested = 0;
|
||||
std::vector<Set> _mySets;
|
||||
|
@ -339,7 +335,6 @@ private:
|
|||
std::vector<Set> _searchSets;
|
||||
int _premiumsIndex = -1;
|
||||
int _featuredSetsCount = 0;
|
||||
base::flat_set<uint64> _installedLocallySets;
|
||||
std::vector<bool> _custom;
|
||||
base::flat_set<not_null<DocumentData*>> _favedStickersMap;
|
||||
std::weak_ptr<Lottie::FrameRenderer> _lottieRenderer;
|
||||
|
|
|
@ -356,9 +356,12 @@ void Stickers::applyArchivedResult(
|
|||
if (set->flags & SetFlag::NotLoaded) {
|
||||
setsToRequest.insert(set->id, set->accessHash);
|
||||
}
|
||||
const auto masks = !!(set->flags & SetFlag::Masks);
|
||||
(masks ? masksCount : stickersCount)++;
|
||||
auto &order = masks ? maskSetsOrderRef() : setsOrderRef();
|
||||
if (set->type() == StickersType::Emoji) {
|
||||
continue;
|
||||
}
|
||||
const auto isMasks = (set->type() == StickersType::Masks);
|
||||
(isMasks ? masksCount : stickersCount)++;
|
||||
auto &order = isMasks ? maskSetsOrderRef() : setsOrderRef();
|
||||
const auto index = order.indexOf(set->id);
|
||||
if (index >= 0) {
|
||||
order.removeAt(index);
|
||||
|
@ -692,12 +695,7 @@ void Stickers::somethingReceived(
|
|||
QMap<uint64, uint64> setsToRequest;
|
||||
for (auto &[id, set] : sets) {
|
||||
const auto archived = !!(set->flags & SetFlag::Archived);
|
||||
const auto setType = !!(set->flags & SetFlag::Emoji)
|
||||
? StickersType::Emoji
|
||||
: !!(set->flags & SetFlag::Masks)
|
||||
? StickersType::Masks
|
||||
: StickersType::Stickers;
|
||||
if (!archived && (type == setType)) {
|
||||
if (!archived && (type == set->type())) {
|
||||
// Mark for removing.
|
||||
set->flags &= ~SetFlag::Installed;
|
||||
set->installDate = 0;
|
||||
|
@ -964,10 +962,10 @@ void Stickers::featuredReceived(
|
|||
};
|
||||
|
||||
const auto isEmoji = (type == StickersType::Emoji);
|
||||
auto &setsOrder = isEmoji
|
||||
auto &featuredOrder = isEmoji
|
||||
? featuredEmojiSetsOrderRef()
|
||||
: featuredSetsOrderRef();
|
||||
setsOrder.clear();
|
||||
featuredOrder.clear();
|
||||
|
||||
auto &sets = setsRef();
|
||||
auto setsToRequest = base::flat_map<uint64, uint64>();
|
||||
|
@ -1000,15 +998,14 @@ void Stickers::featuredReceived(
|
|||
}
|
||||
return ImageWithLocation();
|
||||
}();
|
||||
const auto setId = data->vid().v;
|
||||
const auto flags = SetFlag::Featured
|
||||
| (unreadMap.contains(data->vid().v)
|
||||
? SetFlag::Unread
|
||||
: SetFlag())
|
||||
| (unreadMap.contains(setId) ? SetFlag::Unread : SetFlag())
|
||||
| ParseStickersSetFlags(*data);
|
||||
if (it == sets.cend()) {
|
||||
it = sets.emplace(data->vid().v, std::make_unique<StickersSet>(
|
||||
&owner(),
|
||||
data->vid().v,
|
||||
setId,
|
||||
data->vaccess_hash().v,
|
||||
data->vhash().v,
|
||||
title,
|
||||
|
@ -1032,7 +1029,7 @@ void Stickers::featuredReceived(
|
|||
}
|
||||
it->second->setThumbnail(thumbnail);
|
||||
it->second->thumbnailDocumentId = data->vthumb_document_id().value_or_empty();
|
||||
setsOrder.push_back(data->vid().v);
|
||||
featuredOrder.push_back(data->vid().v);
|
||||
if (it->second->stickers.isEmpty()
|
||||
|| (it->second->flags & SetFlag::NotLoaded)) {
|
||||
setsToRequest.emplace(data->vid().v, data->vaccess_hash().v);
|
||||
|
@ -1361,8 +1358,8 @@ not_null<StickersSet*> Stickers::feedSet(const MTPStickerSet &info) {
|
|||
set->thumbnailDocumentId = data.vthumb_document_id().value_or_empty();
|
||||
auto changedFlags = (oldFlags ^ set->flags);
|
||||
if (changedFlags & SetFlag::Archived) {
|
||||
const auto masks = !!(set->flags & SetFlag::Masks);
|
||||
auto &archivedOrder = masks
|
||||
const auto isMasks = (set->type() == StickersType::Masks);
|
||||
auto &archivedOrder = isMasks
|
||||
? archivedMaskSetsOrderRef()
|
||||
: archivedSetsOrderRef();
|
||||
const auto index = archivedOrder.indexOf(set->id);
|
||||
|
|
|
@ -403,7 +403,7 @@ void Form::processDetails(const MTPDpayments_paymentForm &data) {
|
|||
_invoice.cover.title = qs(data.vtitle());
|
||||
_invoice.cover.description = TextUtilities::ParseEntities(
|
||||
qs(data.vdescription()),
|
||||
TextParseLinks | TextParseMultiline)
|
||||
TextParseLinks | TextParseMultiline);
|
||||
if (_invoice.cover.thumbnail.isNull() && !_thumbnailLoadProcess) {
|
||||
if (const auto photo = data.vphoto()) {
|
||||
loadThumbnail(
|
||||
|
@ -435,7 +435,7 @@ void Form::processDetails(const MTPDpayments_paymentReceipt &data) {
|
|||
.providerId = data.vprovider_id().v,
|
||||
};
|
||||
if (_invoice.cover.title.isEmpty()
|
||||
&& _invoice.cover.description.isEmpty()
|
||||
&& _invoice.cover.description.empty()
|
||||
&& _invoice.cover.thumbnail.isNull()
|
||||
&& !_thumbnailLoadProcess) {
|
||||
_invoice.cover = Ui::Cover{
|
||||
|
|
|
@ -2019,9 +2019,8 @@ void Account::writeInstalledStickers() {
|
|||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
} else if (!(set.flags & SetFlag::Installed)
|
||||
|| (set.flags & SetFlag::Archived)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & (SetFlag::Masks | SetFlag::Emoji)) {
|
||||
|| (set.flags & SetFlag::Archived)
|
||||
|| (set.type() != Data::StickersType::Stickers)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & SetFlag::NotLoaded) {
|
||||
// waiting to receive
|
||||
|
@ -2042,9 +2041,9 @@ void Account::writeFeaturedStickers() {
|
|||
|| set.id == Data::Stickers::CloudRecentAttachedSetId) {
|
||||
// separate files for them
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & (SetFlag::Special | SetFlag::Emoji)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (!(set.flags & SetFlag::Featured)) {
|
||||
} else if ((set.flags & SetFlag::Special)
|
||||
|| !(set.flags & SetFlag::Featured)
|
||||
|| (set.type() != Data::StickersType::Stickers)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & SetFlag::NotLoaded) { // waiting to receive
|
||||
return StickerSetCheckResult::Abort;
|
||||
|
@ -2059,9 +2058,8 @@ void Account::writeFeaturedCustomEmoji() {
|
|||
using SetFlag = Data::StickersSetFlag;
|
||||
|
||||
writeStickerSets(_featuredCustomEmojiKey, [](const Data::StickersSet &set) {
|
||||
if (!(set.flags & SetFlag::Emoji)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (!(set.flags & SetFlag::Featured)) {
|
||||
if (!(set.flags & SetFlag::Featured)
|
||||
|| (set.type() != Data::StickersType::Emoji)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & SetFlag::NotLoaded) { // waiting to receive
|
||||
return StickerSetCheckResult::Abort;
|
||||
|
@ -2095,10 +2093,8 @@ void Account::writeArchivedStickers() {
|
|||
using SetFlag = Data::StickersSetFlag;
|
||||
|
||||
writeStickerSets(_archivedStickersKey, [](const Data::StickersSet &set) {
|
||||
if (set.flags & (SetFlag::Masks | SetFlag::Emoji)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
if (!(set.flags & SetFlag::Archived)
|
||||
|| (set.type() != Data::StickersType::Stickers)
|
||||
|| set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
|
@ -2110,10 +2106,9 @@ void Account::writeArchivedMasks() {
|
|||
using SetFlag = Data::StickersSetFlag;
|
||||
|
||||
writeStickerSets(_archivedStickersKey, [](const Data::StickersSet &set) {
|
||||
if (!(set.flags & SetFlag::Masks)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
if (!(set.flags & SetFlag::Archived) || set.stickers.isEmpty()) {
|
||||
if (!(set.flags & SetFlag::Archived)
|
||||
|| (set.type() != Data::StickersType::Masks)
|
||||
|| set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
|
@ -2124,7 +2119,10 @@ void Account::writeInstalledMasks() {
|
|||
using SetFlag = Data::StickersSetFlag;
|
||||
|
||||
writeStickerSets(_installedMasksKey, [](const Data::StickersSet &set) {
|
||||
if (!(set.flags & SetFlag::Masks) || set.stickers.isEmpty()) {
|
||||
if (!(set.flags & SetFlag::Installed)
|
||||
|| (set.flags & SetFlag::Archived)
|
||||
|| (set.type() != Data::StickersType::Masks)
|
||||
|| set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
|
@ -2145,14 +2143,14 @@ void Account::writeInstalledCustomEmoji() {
|
|||
using SetFlag = Data::StickersSetFlag;
|
||||
|
||||
writeStickerSets(_installedCustomEmojiKey, [](const Data::StickersSet &set) {
|
||||
if (!(set.flags & SetFlag::Emoji)) {
|
||||
if (!(set.flags & SetFlag::Installed)
|
||||
|| (set.flags & SetFlag::Archived)
|
||||
|| (set.type() != Data::StickersType::Emoji)) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & SetFlag::NotLoaded) {
|
||||
// waiting to receive
|
||||
return StickerSetCheckResult::Abort;
|
||||
} else if (!(set.flags & SetFlag::Installed)
|
||||
|| (set.flags & SetFlag::Archived)
|
||||
|| set.stickers.isEmpty()) {
|
||||
} else if (set.stickers.isEmpty()) {
|
||||
return StickerSetCheckResult::Skip;
|
||||
}
|
||||
return StickerSetCheckResult::Write;
|
||||
|
|
Loading…
Add table
Reference in a new issue