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