mirror of
https://github.com/vale981/tdesktop
synced 2025-03-05 09:41:41 -05:00
Improve sticker by emoji ordering.
First display recent by send/install date, then trending, then other.
This commit is contained in:
parent
ccef155f7a
commit
90179188b9
7 changed files with 178 additions and 54 deletions
|
@ -2200,6 +2200,10 @@ void ApiWrap::updateStickers() {
|
|||
requestSavedGifs(now);
|
||||
}
|
||||
|
||||
void ApiWrap::requestRecentStickersForce() {
|
||||
requestRecentStickersWithHash(0);
|
||||
}
|
||||
|
||||
void ApiWrap::setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInputStickerSet &set) {
|
||||
Expects(megagroup->mgInfo != nullptr);
|
||||
|
||||
|
@ -2283,13 +2287,19 @@ void ApiWrap::requestStickers(TimeId now) {
|
|||
}
|
||||
|
||||
void ApiWrap::requestRecentStickers(TimeId now) {
|
||||
if (!_session->data().recentStickersUpdateNeeded(now)
|
||||
|| _recentStickersUpdateRequest) {
|
||||
if (!_session->data().recentStickersUpdateNeeded(now)) {
|
||||
return;
|
||||
}
|
||||
requestRecentStickersWithHash(Local::countRecentStickersHash());
|
||||
}
|
||||
|
||||
void ApiWrap::requestRecentStickersWithHash(int32 hash) {
|
||||
if (_recentStickersUpdateRequest) {
|
||||
return;
|
||||
}
|
||||
_recentStickersUpdateRequest = request(MTPmessages_GetRecentStickers(
|
||||
MTP_flags(0),
|
||||
MTP_int(Local::countRecentStickersHash())
|
||||
MTP_int(hash)
|
||||
)).done([=](const MTPmessages_RecentStickers &result) {
|
||||
_session->data().setLastRecentStickersUpdate(getms(true));
|
||||
_recentStickersUpdateRequest = 0;
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
const Stickers::Order &localOrder,
|
||||
const Stickers::Order &localRemoved);
|
||||
void updateStickers();
|
||||
void requestRecentStickersForce();
|
||||
void setGroupStickerSet(
|
||||
not_null<ChannelData*> megagroup,
|
||||
const MTPInputStickerSet &set);
|
||||
|
@ -345,6 +346,7 @@ private:
|
|||
|
||||
void requestStickers(TimeId now);
|
||||
void requestRecentStickers(TimeId now);
|
||||
void requestRecentStickersWithHash(int32 hash);
|
||||
void requestFavedStickers(TimeId now);
|
||||
void requestFeaturedStickers(TimeId now);
|
||||
void requestSavedGifs(TimeId now);
|
||||
|
|
|
@ -101,7 +101,7 @@ void FieldAutocomplete::showStickers(EmojiPtr emoji) {
|
|||
_emoji = emoji;
|
||||
_type = Type::Stickers;
|
||||
if (!emoji) {
|
||||
rowsUpdated(_mrows, _hrows, _brows, Stickers::Pack(), false);
|
||||
rowsUpdated(_mrows, _hrows, _brows, internal::StickerRows(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -135,9 +135,9 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
internal::MentionRows mrows;
|
||||
internal::HashtagRows hrows;
|
||||
internal::BotCommandRows brows;
|
||||
Stickers::Pack srows;
|
||||
internal::StickerRows srows;
|
||||
if (_emoji) {
|
||||
srows = Stickers::GetListByEmoji(_emoji);
|
||||
srows = Stickers::GetListByEmoji(_emoji, _stickersSeed);
|
||||
} else if (_type == Type::Mentions) {
|
||||
int maxListSize = _addInlineBots ? cRecentInlineBots().size() : 0;
|
||||
if (_chat) {
|
||||
|
@ -319,8 +319,8 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
|
|||
_inner->setRecentInlineBotsInRows(recentInlineBots);
|
||||
}
|
||||
|
||||
void FieldAutocomplete::rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const Stickers::Pack &srows, bool resetScroll) {
|
||||
if (mrows.isEmpty() && hrows.isEmpty() && brows.isEmpty() && srows.isEmpty()) {
|
||||
void FieldAutocomplete::rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const internal::StickerRows &srows, bool resetScroll) {
|
||||
if (mrows.isEmpty() && hrows.isEmpty() && brows.isEmpty() && srows.empty()) {
|
||||
if (!isHidden()) {
|
||||
hideAnimated();
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ void FieldAutocomplete::setBoundings(QRect boundings) {
|
|||
|
||||
void FieldAutocomplete::recount(bool resetScroll) {
|
||||
int32 h = 0, oldst = _scroll->scrollTop(), st = oldst, maxh = 4.5 * st::mentionHeight;
|
||||
if (!_srows.isEmpty()) {
|
||||
if (!_srows.empty()) {
|
||||
int32 stickersPerRow = qMax(1, int32(_boundings.width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()));
|
||||
int32 rows = rowscount(_srows.size(), stickersPerRow);
|
||||
h = st::stickerPanPadding + rows * st::stickerPanSize.height();
|
||||
|
@ -416,6 +416,7 @@ void FieldAutocomplete::showAnimated() {
|
|||
return;
|
||||
}
|
||||
if (_cache.isNull()) {
|
||||
_stickersSeed = rand_value<uint64>();
|
||||
_scroll->show();
|
||||
_cache = Ui::GrabWidget(this);
|
||||
}
|
||||
|
@ -477,7 +478,7 @@ bool FieldAutocomplete::eventFilter(QObject *obj, QEvent *e) {
|
|||
QKeyEvent *ev = static_cast<QKeyEvent*>(e);
|
||||
if (!(ev->modifiers() & (Qt::AltModifier | Qt::ControlModifier | Qt::ShiftModifier | Qt::MetaModifier))) {
|
||||
if (!hidden) {
|
||||
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down || (!_srows.isEmpty() && (ev->key() == Qt::Key_Left || ev->key() == Qt::Key_Right))) {
|
||||
if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down || (!_srows.empty() && (ev->key() == Qt::Key_Left || ev->key() == Qt::Key_Right))) {
|
||||
return _inner->moveSel(ev->key());
|
||||
} else if (ev->key() == Qt::Key_Enter || ev->key() == Qt::Key_Return) {
|
||||
return _inner->chooseSelected(ChooseMethod::ByEnter);
|
||||
|
@ -498,7 +499,7 @@ FieldAutocomplete::~FieldAutocomplete() {
|
|||
|
||||
namespace internal {
|
||||
|
||||
FieldAutocompleteInner::FieldAutocompleteInner(FieldAutocomplete *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, Stickers::Pack *srows)
|
||||
FieldAutocompleteInner::FieldAutocompleteInner(FieldAutocomplete *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, StickerRows *srows)
|
||||
: _parent(parent)
|
||||
, _mrows(mrows)
|
||||
, _hrows(hrows)
|
||||
|
@ -527,7 +528,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
|
|||
int32 mentionwidth = width() - mentionleft - 2 * st::mentionPadding.right();
|
||||
int32 htagleft = st::historyAttach.width + st::historyComposeField.textMrg.left() - st::lineWidth, htagwidth = width() - st::mentionPadding.right() - htagleft - st::mentionScroll.width;
|
||||
|
||||
if (!_srows->isEmpty()) {
|
||||
if (!_srows->empty()) {
|
||||
int32 rows = rowscount(_srows->size(), _stickersPerRow);
|
||||
int32 fromrow = floorclamp(r.y() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
|
||||
int32 torow = ceilclamp(r.y() + r.height() - st::stickerPanPadding, st::stickerPanSize.height(), 0, rows);
|
||||
|
@ -697,7 +698,7 @@ bool FieldAutocompleteInner::moveSel(int key) {
|
|||
_mouseSel = false;
|
||||
int32 maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? (_brows->isEmpty() ? _srows->size() : _brows->size()) : _hrows->size()) : _mrows->size());
|
||||
int32 direction = (key == Qt::Key_Up) ? -1 : (key == Qt::Key_Down ? 1 : 0);
|
||||
if (!_srows->isEmpty()) {
|
||||
if (!_srows->empty()) {
|
||||
if (key == Qt::Key_Left) {
|
||||
direction = -1;
|
||||
} else if (key == Qt::Key_Right) {
|
||||
|
@ -721,7 +722,7 @@ bool FieldAutocompleteInner::moveSel(int key) {
|
|||
}
|
||||
|
||||
bool FieldAutocompleteInner::chooseSelected(FieldAutocomplete::ChooseMethod method) const {
|
||||
if (!_srows->isEmpty()) {
|
||||
if (!_srows->empty()) {
|
||||
if (_sel >= 0 && _sel < _srows->size()) {
|
||||
emit stickerChosen(_srows->at(_sel), method);
|
||||
return true;
|
||||
|
@ -791,7 +792,7 @@ void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
|
|||
|
||||
_mouseSel = true;
|
||||
onUpdateSelected(true);
|
||||
} else if (_srows->isEmpty()) {
|
||||
} else if (_srows->empty()) {
|
||||
chooseSelected(FieldAutocomplete::ChooseMethod::ByClick);
|
||||
} else {
|
||||
_down = _sel;
|
||||
|
@ -815,7 +816,7 @@ void FieldAutocompleteInner::mouseReleaseEvent(QMouseEvent *e) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (_sel < 0 || _sel != pressed || _srows->isEmpty()) return;
|
||||
if (_sel < 0 || _sel != pressed || _srows->empty()) return;
|
||||
|
||||
chooseSelected(FieldAutocomplete::ChooseMethod::ByClick);
|
||||
}
|
||||
|
@ -835,7 +836,7 @@ void FieldAutocompleteInner::leaveEventHook(QEvent *e) {
|
|||
|
||||
void FieldAutocompleteInner::updateSelectedRow() {
|
||||
if (_sel >= 0) {
|
||||
if (_srows->isEmpty()) {
|
||||
if (_srows->empty()) {
|
||||
update(0, _sel * st::mentionHeight, width(), st::mentionHeight);
|
||||
} else {
|
||||
int32 row = _sel / _stickersPerRow, col = _sel % _stickersPerRow;
|
||||
|
@ -850,7 +851,7 @@ void FieldAutocompleteInner::setSel(int sel, bool scroll) {
|
|||
updateSelectedRow();
|
||||
|
||||
if (scroll && _sel >= 0) {
|
||||
if (_srows->isEmpty()) {
|
||||
if (_srows->empty()) {
|
||||
emit mustScrollTo(_sel * st::mentionHeight, (_sel + 1) * st::mentionHeight);
|
||||
} else {
|
||||
int32 row = _sel / _stickersPerRow;
|
||||
|
@ -866,7 +867,7 @@ void FieldAutocompleteInner::onUpdateSelected(bool force) {
|
|||
if (_down >= 0 && !_previewShown) return;
|
||||
|
||||
int32 sel = -1, maxSel = 0;
|
||||
if (!_srows->isEmpty()) {
|
||||
if (!_srows->empty()) {
|
||||
int32 rows = rowscount(_srows->size(), _stickersPerRow);
|
||||
int32 row = (mouse.y() >= st::stickerPanPadding) ? ((mouse.y() - st::stickerPanPadding) / st::stickerPanSize.height()) : -1;
|
||||
int32 col = (mouse.x() >= st::stickerPanPadding) ? ((mouse.x() - st::stickerPanPadding) / st::stickerPanSize.width()) : -1;
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace internal {
|
|||
using MentionRows = QList<UserData*>;
|
||||
using HashtagRows = QList<QString>;
|
||||
using BotCommandRows = QList<QPair<UserData*, const BotCommand*>>;
|
||||
using StickerRows = std::vector<not_null<DocumentData*>>;
|
||||
|
||||
class FieldAutocompleteInner;
|
||||
|
||||
|
@ -53,7 +54,7 @@ public:
|
|||
bool chooseSelected(ChooseMethod method) const;
|
||||
|
||||
bool stickersShown() const {
|
||||
return !_srows.isEmpty();
|
||||
return !_srows.empty();
|
||||
}
|
||||
|
||||
bool overlaps(const QRect &globalRect) {
|
||||
|
@ -92,9 +93,9 @@ private:
|
|||
internal::MentionRows _mrows;
|
||||
internal::HashtagRows _hrows;
|
||||
internal::BotCommandRows _brows;
|
||||
Stickers::Pack _srows;
|
||||
internal::StickerRows _srows;
|
||||
|
||||
void rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const Stickers::Pack &srows, bool resetScroll);
|
||||
void rowsUpdated(const internal::MentionRows &mrows, const internal::HashtagRows &hrows, const internal::BotCommandRows &brows, const internal::StickerRows &srows, bool resetScroll);
|
||||
|
||||
object_ptr<Ui::ScrollArea> _scroll;
|
||||
QPointer<internal::FieldAutocompleteInner> _inner;
|
||||
|
@ -103,6 +104,7 @@ private:
|
|||
UserData *_user = nullptr;
|
||||
ChannelData *_channel = nullptr;
|
||||
EmojiPtr _emoji;
|
||||
uint64 _stickersSeed = 0;
|
||||
enum class Type {
|
||||
Mentions,
|
||||
Hashtags,
|
||||
|
@ -129,7 +131,7 @@ class FieldAutocompleteInner final : public TWidget, private base::Subscriber {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FieldAutocompleteInner(FieldAutocomplete *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, Stickers::Pack *srows);
|
||||
FieldAutocompleteInner(FieldAutocomplete *parent, MentionRows *mrows, HashtagRows *hrows, BotCommandRows *brows, StickerRows *srows);
|
||||
|
||||
void clearSel(bool hidden = false);
|
||||
bool moveSel(int key);
|
||||
|
@ -167,7 +169,7 @@ private:
|
|||
MentionRows *_mrows;
|
||||
HashtagRows *_hrows;
|
||||
BotCommandRows *_brows;
|
||||
Stickers::Pack *_srows;
|
||||
StickerRows *_srows;
|
||||
int32 _stickersPerRow, _recentInlineBotsInRows;
|
||||
int32 _sel, _down;
|
||||
bool _mouseSel;
|
||||
|
|
|
@ -668,19 +668,84 @@ void GifsReceived(const QVector<MTPDocument> &items, int32 hash) {
|
|||
Auth().data().notifySavedGifsUpdated();
|
||||
}
|
||||
|
||||
Pack GetListByEmoji(not_null<EmojiPtr> emoji) {
|
||||
auto original = emoji->original();
|
||||
auto result = Pack();
|
||||
auto setsToRequest = QMap<uint64, uint64>();
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
std::vector<not_null<DocumentData*>> GetListByEmoji(
|
||||
not_null<EmojiPtr> emoji,
|
||||
uint64 seed) {
|
||||
const auto original = emoji->original();
|
||||
|
||||
auto faved = Pack();
|
||||
auto favedIt = sets.find(Stickers::FavedSetId);
|
||||
if (favedIt != sets.cend()) {
|
||||
auto i = favedIt->emoji.constFind(original);
|
||||
if (i != favedIt->emoji.cend()) {
|
||||
faved = *i;
|
||||
result = faved;
|
||||
struct StickerWithDate {
|
||||
not_null<DocumentData*> document;
|
||||
TimeId date = 0;
|
||||
};
|
||||
auto result = std::vector<StickerWithDate>();
|
||||
auto &sets = Auth().data().stickerSetsRef();
|
||||
auto setsToRequest = base::flat_map<uint64, uint64>();
|
||||
|
||||
const auto add = [&](not_null<DocumentData*> document, TimeId date) {
|
||||
if (ranges::find(result, document, [](const StickerWithDate &data) {
|
||||
return data.document;
|
||||
}) == result.end()) {
|
||||
result.push_back({ document, date });
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto kSlice = 65536;
|
||||
const auto CreateSortKey = [&](
|
||||
not_null<DocumentData*> document,
|
||||
int base) {
|
||||
return TimeId(base + int((document->id ^ seed) % kSlice));
|
||||
};
|
||||
const auto CreateRecentSortKey = [&](not_null<DocumentData*> document) {
|
||||
return CreateSortKey(document, kSlice * 4);
|
||||
};
|
||||
auto myCounter = 0;
|
||||
const auto CreateMySortKey = [&] {
|
||||
return (kSlice * 4 - (++myCounter));
|
||||
};
|
||||
const auto CreateFeaturedSortKey = [&](not_null<DocumentData*> document) {
|
||||
return CreateSortKey(document, kSlice * 2);
|
||||
};
|
||||
const auto CreateOtherSortKey = [&](not_null<DocumentData*> document) {
|
||||
return CreateSortKey(document, kSlice);
|
||||
};
|
||||
const auto InstallDate = [&](not_null<DocumentData*> document) {
|
||||
Expects(document->sticker() != nullptr);
|
||||
|
||||
const auto sticker = document->sticker();
|
||||
if (sticker->set.type() == mtpc_inputStickerSetID) {
|
||||
const auto setId = sticker->set.c_inputStickerSetID().vid.v;
|
||||
const auto setIt = sets.find(setId);
|
||||
if (setIt != sets.end()) {
|
||||
return setIt->installDate;
|
||||
}
|
||||
}
|
||||
return TimeId(0);
|
||||
};
|
||||
|
||||
auto recentIt = sets.find(Stickers::CloudRecentSetId);
|
||||
if (recentIt != sets.cend()) {
|
||||
auto i = recentIt->emoji.constFind(original);
|
||||
if (i != recentIt->emoji.cend()) {
|
||||
result.reserve(i->size());
|
||||
for (const auto document : *i) {
|
||||
const auto usageDate = [&] {
|
||||
if (recentIt->dates.empty()) {
|
||||
return TimeId(0);
|
||||
}
|
||||
const auto index = recentIt->stickers.indexOf(document);
|
||||
if (index < 0) {
|
||||
return TimeId(0);
|
||||
}
|
||||
Assert(index < recentIt->dates.size());
|
||||
return recentIt->dates[index];
|
||||
}();
|
||||
const auto date = usageDate
|
||||
? usageDate
|
||||
: InstallDate(document);
|
||||
result.push_back({
|
||||
document,
|
||||
date ? date : CreateRecentSortKey(document) });
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto addList = [&](const Order &order, MTPDstickerSet::Flag skip) {
|
||||
|
@ -690,7 +755,7 @@ Pack GetListByEmoji(not_null<EmojiPtr> emoji) {
|
|||
continue;
|
||||
}
|
||||
if (it->emoji.isEmpty()) {
|
||||
setsToRequest.insert(it->id, it->access);
|
||||
setsToRequest.emplace(it->id, it->access);
|
||||
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded;
|
||||
continue;
|
||||
}
|
||||
|
@ -698,11 +763,16 @@ Pack GetListByEmoji(not_null<EmojiPtr> emoji) {
|
|||
if (i == it->emoji.cend()) {
|
||||
continue;
|
||||
}
|
||||
const auto my = (it->flags & MTPDstickerSet::Flag::f_installed_date);
|
||||
result.reserve(result.size() + i->size());
|
||||
for_const (const auto document, *i) {
|
||||
if (!faved.contains(document)) {
|
||||
result.push_back(document);
|
||||
}
|
||||
for (const auto document : *i) {
|
||||
const auto installDate = my ? it->installDate : TimeId(0);
|
||||
const auto date = (installDate > 1)
|
||||
? installDate
|
||||
: my
|
||||
? CreateMySortKey()
|
||||
: CreateFeaturedSortKey(document);
|
||||
add(document, date);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -714,21 +784,32 @@ Pack GetListByEmoji(not_null<EmojiPtr> emoji) {
|
|||
Auth().data().featuredStickerSetsOrder(),
|
||||
MTPDstickerSet::Flag::f_installed_date);
|
||||
|
||||
if (!setsToRequest.isEmpty()) {
|
||||
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
|
||||
Auth().api().scheduleStickerSetRequest(i.key(), i.value());
|
||||
if (!setsToRequest.empty()) {
|
||||
for (const auto [setId, accessHash] : setsToRequest) {
|
||||
Auth().api().scheduleStickerSetRequest(setId, accessHash);
|
||||
}
|
||||
Auth().api().requestStickerSets();
|
||||
}
|
||||
if (const auto pack = Auth().api().stickersByEmoji(original)) {
|
||||
for (const auto document : *pack) {
|
||||
if (!base::contains(result, document)) {
|
||||
result.push_back(document);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
const auto others = Auth().api().stickersByEmoji(original);
|
||||
if (!others) {
|
||||
return {};
|
||||
}
|
||||
return Pack();
|
||||
result.reserve(result.size() + others->size());
|
||||
for (const auto document : *others) {
|
||||
add(document, CreateOtherSortKey(document));
|
||||
}
|
||||
|
||||
ranges::action::sort(
|
||||
result,
|
||||
std::greater<>(),
|
||||
[](const StickerWithDate &data) { return data.date; });
|
||||
|
||||
return ranges::view::all(
|
||||
result
|
||||
) | ranges::view::transform([](const StickerWithDate &data) {
|
||||
return data.document;
|
||||
}) | ranges::to_vector;
|
||||
}
|
||||
|
||||
base::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
|
||||
|
|
|
@ -86,7 +86,9 @@ void FeaturedSetsReceived(
|
|||
int32 hash);
|
||||
void GifsReceived(const QVector<MTPDocument> &items, int32 hash);
|
||||
|
||||
Pack GetListByEmoji(not_null<EmojiPtr> emoji);
|
||||
std::vector<not_null<DocumentData*>> GetListByEmoji(
|
||||
not_null<EmojiPtr> emoji,
|
||||
uint64 seed);
|
||||
base::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
|
||||
not_null<DocumentData*> document);
|
||||
|
||||
|
|
|
@ -4058,19 +4058,45 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
|
|||
it->title = lang(lng_recent_stickers);
|
||||
}
|
||||
}
|
||||
auto removedFromEmoji = std::vector<not_null<EmojiPtr>>();
|
||||
auto index = it->stickers.indexOf(sticker);
|
||||
if (index > 0) {
|
||||
if (!it->dates.empty()) {
|
||||
if (it->dates.empty()) {
|
||||
Auth().api().requestRecentStickersForce();
|
||||
} else {
|
||||
Assert(it->dates.size() == it->stickers.size());
|
||||
it->dates.erase(it->dates.begin() + index);
|
||||
}
|
||||
it->stickers.removeAt(index);
|
||||
for (auto i = it->emoji.begin(); i != it->emoji.end();) {
|
||||
if (const auto index = i->indexOf(sticker); index >= 0) {
|
||||
removedFromEmoji.push_back(i.key());
|
||||
i->removeAt(index);
|
||||
if (i->isEmpty()) {
|
||||
i = it->emoji.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
if (index) {
|
||||
if (it->dates.size() == it->stickers.size()) {
|
||||
it->dates.insert(it->dates.begin(), unixtime());
|
||||
}
|
||||
it->stickers.push_front(sticker);
|
||||
if (const auto emojiList = Stickers::GetEmojiListFromSet(sticker)) {
|
||||
for (const auto emoji : *emojiList) {
|
||||
it->emoji[emoji].push_front(sticker);
|
||||
}
|
||||
} else if (!removedFromEmoji.empty()) {
|
||||
for (const auto emoji : removedFromEmoji) {
|
||||
it->emoji[emoji].push_front(sticker);
|
||||
}
|
||||
} else {
|
||||
Auth().api().requestRecentStickersForce();
|
||||
}
|
||||
|
||||
writeRecentStickers = true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue