Fix sticker set icons display.

This commit is contained in:
John Preston 2020-05-28 15:58:50 +04:00
parent 803593cd8d
commit ae9ed820ee
16 changed files with 393 additions and 445 deletions

View File

@ -1865,7 +1865,7 @@ void ApiWrap::saveStickerSets(
auto &sets = _session->data().stickerSetsRef();
_stickersOrder = localOrder;
for_const (auto removedSetId, localRemoved) {
for (const auto removedSetId : localRemoved) {
if (removedSetId == Stickers::CloudRecentSetId) {
if (sets.remove(Stickers::CloudRecentSetId) != 0) {
writeCloudRecent = true;
@ -3348,8 +3348,8 @@ void ApiWrap::readFeaturedSets() {
auto count = _session->data().featuredStickerSetsUnreadCount();
QVector<MTPlong> wrappedIds;
wrappedIds.reserve(_featuredSetsRead.size());
for (auto setId : _featuredSetsRead) {
auto it = sets.find(setId);
for (const auto setId : _featuredSetsRead) {
const auto it = sets.find(setId);
if (it != sets.cend()) {
it->second->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
wrappedIds.append(MTP_long(setId));

View File

@ -166,7 +166,7 @@ void StickersBox::showAttachedStickers() {
});
if (const auto set = Stickers::FeedSet(*setData)) {
if (_attached.widget()->appendSet(*set)) {
if (_attached.widget()->appendSet(set)) {
addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
_session->api().scheduleStickerSetRequest(set->id, set->access);
@ -221,8 +221,8 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
}
if (!setData) continue;
if (auto set = Stickers::FeedSet(*setData)) {
auto index = archived.indexOf(set->id);
if (const auto set = Stickers::FeedSet(*setData)) {
const auto index = archived.indexOf(set->id);
if (archived.isEmpty() || index != archived.size() - 1) {
changedSets = true;
if (index < archived.size() - 1) {
@ -230,7 +230,7 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
}
archived.push_back(set->id);
}
if (_archived.widget()->appendSet(*set)) {
if (_archived.widget()->appendSet(set)) {
addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
_session->api().scheduleStickerSetRequest(set->id, set->access);
@ -635,9 +635,7 @@ void StickersBox::setInnerFocus() {
StickersBox::~StickersBox() = default;
StickersBox::Inner::Row::Row(
uint64 id,
uint64 accessHash,
ImagePtr thumbnail,
not_null<Stickers::Set*> set,
DocumentData *sticker,
int32 count,
const QString &title,
@ -649,11 +647,8 @@ StickersBox::Inner::Row::Row(
bool removed,
int32 pixw,
int32 pixh)
: id(id)
, accessHash(accessHash)
, thumbnail(thumbnail)
: set(set)
, sticker(sticker)
, stickerMedia(sticker ? sticker->createMediaView() : nullptr)
, count(count)
, title(title)
, titleWidth(titleWidth)
@ -669,7 +664,7 @@ StickersBox::Inner::Row::Row(
StickersBox::Inner::Row::~Row() = default;
bool StickersBox::Inner::Row::isRecentSet() const {
return (id == Stickers::CloudRecentSetId);
return (set->id == Stickers::CloudRecentSetId);
}
StickersBox::Inner::Inner(
@ -820,8 +815,8 @@ QRect StickersBox::Inner::relativeButtonRect(bool removeButton) const {
return QRect(buttonx, buttony, buttonw, buttonh);
}
void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> set, int index) {
auto xadd = 0, yadd = qRound(set->yadd.current());
void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> row, int index) {
auto xadd = 0, yadd = qRound(row->yadd.current());
if (xadd || yadd) p.translate(xadd, yadd);
if (_megagroupSet) {
@ -833,8 +828,8 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> set, int index) {
}();
if (index >= 0 && index == selectedIndex) {
p.fillRect(0, 0, width(), _rowHeight, st::contactsBgOver);
if (set->ripple) {
set->ripple->paint(p, 0, 0, width());
if (row->ripple) {
row->ripple->paint(p, 0, 0, width());
}
}
}
@ -849,24 +844,24 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> set, int index) {
current = reachedOpacity;
}
}
auto row = myrtlrect(st::contactsPadding.left() / 2, st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - st::contactsPadding.left() / 2, _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2));
auto rect = myrtlrect(st::contactsPadding.left() / 2, st::contactsPadding.top() / 2, width() - (st::contactsPadding.left() / 2) - _scrollbar - st::contactsPadding.left() / 2, _rowHeight - ((st::contactsPadding.top() + st::contactsPadding.bottom()) / 2));
p.setOpacity(current);
Ui::Shadow::paint(p, row, width(), st::boxRoundShadow);
Ui::Shadow::paint(p, rect, width(), st::boxRoundShadow);
p.setOpacity(1);
App::roundRect(p, row, st::boxBg, BoxCorners);
App::roundRect(p, rect, st::boxBg, BoxCorners);
p.setOpacity(1. - current);
paintFakeButton(p, set, index);
paintFakeButton(p, row, index);
p.setOpacity(1.);
} else if (!_megagroupSet) {
paintFakeButton(p, set, index);
paintFakeButton(p, row, index);
}
} else if (!_megagroupSet) {
paintFakeButton(p, set, index);
paintFakeButton(p, row, index);
}
if (set->removed && _section == Section::Installed) {
if (row->removed && _section == Section::Installed) {
p.setOpacity(st::stickersRowDisabledOpacity);
}
@ -874,13 +869,13 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> set, int index) {
if (!_megagroupSet && _section == Section::Installed) {
stickerx += st::stickersReorderIcon.width() + st::stickersReorderSkip;
if (!set->isRecentSet()) {
if (!row->isRecentSet()) {
st::stickersReorderIcon.paint(p, st::contactsPadding.left(), (_rowHeight - st::stickersReorderIcon.height()) / 2, width());
}
}
if (set->sticker) {
paintRowThumbnail(p, set, stickerx);
if (row->sticker) {
paintRowThumbnail(p, row, stickerx);
}
int namex = stickerx + st::contactsPhotoSize + st::contactsPadding.left();
@ -891,19 +886,19 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> set, int index) {
p.setFont(st::contactsNameStyle.font);
p.setPen(st::contactsNameFg);
p.drawTextLeft(namex, namey, width(), set->title, set->titleWidth);
p.drawTextLeft(namex, namey, width(), row->title, row->titleWidth);
if (set->unread) {
if (row->unread) {
p.setPen(Qt::NoPen);
p.setBrush(st::stickersFeaturedUnreadBg);
{
PainterHighQualityEnabler hq(p);
p.drawEllipse(style::rtlrect(namex + set->titleWidth + st::stickersFeaturedUnreadSkip, namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize, st::stickersFeaturedUnreadSize, width()));
p.drawEllipse(style::rtlrect(namex + row->titleWidth + st::stickersFeaturedUnreadSkip, namey + st::stickersFeaturedUnreadTop, st::stickersFeaturedUnreadSize, st::stickersFeaturedUnreadSize, width()));
}
}
auto statusText = (set->count > 0) ? tr::lng_stickers_count(tr::now, lt_count, set->count) : tr::lng_contacts_loading(tr::now);
auto statusText = (row->count > 0) ? tr::lng_stickers_count(tr::now, lt_count, row->count) : tr::lng_contacts_loading(tr::now);
p.setFont(st::contactsStatusFont);
p.setPen(st::contactsStatusFg);
@ -915,30 +910,39 @@ void StickersBox::Inner::paintRow(Painter &p, not_null<Row*> set, int index) {
void StickersBox::Inner::paintRowThumbnail(
Painter &p,
not_null<Row*> set,
not_null<Row*> row,
int left) {
const auto origin = Data::FileOriginStickerSet(
set->id,
set->accessHash);
const auto thumb = set->thumbnail
? set->thumbnail.get()
: set->stickerMedia->thumbnail();
if (!thumb) {
return;
row->set->id,
row->set->access);
if (row->set->hasThumbnail()) {
if (!row->thumbnailMedia) {
row->thumbnailMedia = row->set->createThumbnailView();
row->set->loadThumbnail();
}
} else if (row->sticker) {
if (!row->stickerMedia) {
row->stickerMedia = row->sticker->createMediaView();
row->stickerMedia->thumbnailWanted(origin);
}
}
thumb->load(origin);
validateLottieAnimation(set);
if (!set->lottie) {
if (!thumb->loaded()) {
validateLottieAnimation(row);
if (!row->lottie) {
const auto thumb = row->thumbnailMedia
? row->thumbnailMedia->image()
: row->stickerMedia
? row->stickerMedia->thumbnail()
: nullptr;
if (!thumb) {
return;
}
p.drawPixmapLeft(
left + (st::contactsPhotoSize - set->pixw) / 2,
st::contactsPadding.top() + (st::contactsPhotoSize - set->pixh) / 2,
left + (st::contactsPhotoSize - row->pixw) / 2,
st::contactsPadding.top() + (st::contactsPhotoSize - row->pixh) / 2,
width(),
thumb->pix(origin, set->pixw, set->pixh));
} else if (set->lottie->ready()) {
const auto frame = set->lottie->frame();
thumb->pix(origin, row->pixw, row->pixh));
} else if (row->lottie->ready()) {
const auto frame = row->lottie->frame();
const auto size = frame.size() / cIntRetinaFactor();
p.drawImage(
QRect(
@ -951,21 +955,21 @@ void StickersBox::Inner::paintRowThumbnail(
const auto paused = controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Layer);
if (!paused) {
set->lottie->markFrameShown();
row->lottie->markFrameShown();
}
}
}
void StickersBox::Inner::validateLottieAnimation(not_null<Row*> set) {
if (set->lottie
void StickersBox::Inner::validateLottieAnimation(not_null<Row*> row) {
if (row->lottie
|| !Stickers::HasLottieThumbnail(
set->thumbnail,
set->stickerMedia.get())) {
row->thumbnailMedia.get(),
row->stickerMedia.get())) {
return;
}
auto player = Stickers::LottieThumbnail(
set->thumbnail,
set->stickerMedia.get(),
row->thumbnailMedia.get(),
row->stickerMedia.get(),
Stickers::LottieSize::SetsListThumbnail,
QSize(
st::contactsPhotoSize,
@ -973,21 +977,21 @@ void StickersBox::Inner::validateLottieAnimation(not_null<Row*> set) {
if (!player) {
return;
}
set->lottie = std::move(player);
set->lottie->updates(
row->lottie = std::move(player);
row->lottie->updates(
) | rpl::start_with_next([=] {
updateRowThumbnail(set);
updateRowThumbnail(row);
}, lifetime());
}
void StickersBox::Inner::updateRowThumbnail(not_null<Row*> set) {
void StickersBox::Inner::updateRowThumbnail(not_null<Row*> row) {
const auto rowTop = [&] {
if (set == _megagroupSelectedSet.get()) {
if (row == _megagroupSelectedSet.get()) {
return _megagroupDivider->y() - _rowHeight;
}
auto top = _itemsTop;
for (const auto &row : _rows) {
if (row.get() == set) {
for (const auto &entry : _rows) {
if (entry.get() == row) {
return top + qRound(row->yadd.current());
}
top += _rowHeight;
@ -1005,10 +1009,10 @@ void StickersBox::Inner::updateRowThumbnail(not_null<Row*> set) {
st::contactsPhotoSize);
}
void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> set, int index) {
auto removeButton = (_section == Section::Installed && !set->removed);
void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int index) {
auto removeButton = (_section == Section::Installed && !row->removed);
auto rect = relativeButtonRect(removeButton);
if (_section != Section::Installed && set->installed && !set->archived && !set->removed) {
if (_section != Section::Installed && row->installed && !row->archived && !row->removed) {
// Checkbox after installed from Trending or Archived.
int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() + (rect.width() + st::stickersFeaturedInstalled.width()) / 2);
int checky = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersFeaturedInstalled.height()) / 2;
@ -1017,10 +1021,10 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> set, int ind
auto selected = (index == _actionSel && _actionDown < 0) || (index == _actionDown);
if (removeButton) {
// Trash icon button when not disabled in Installed.
if (set->ripple) {
set->ripple->paint(p, rect.x(), rect.y(), width());
if (set->ripple->empty()) {
set->ripple.reset();
if (row->ripple) {
row->ripple->paint(p, rect.x(), rect.y(), width());
if (row->ripple->empty()) {
row->ripple.reset();
}
}
auto &icon = selected ? st::stickersRemove.iconOver : st::stickersRemove.icon;
@ -1036,10 +1040,10 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> set, int ind
auto &text = (_section == Section::Installed) ? _undoText : _addText;
auto &textBg = selected ? st.textBgOver : st.textBg;
App::roundRect(p, myrtlrect(rect), textBg, ImageRoundRadius::Small);
if (set->ripple) {
set->ripple->paint(p, rect.x(), rect.y(), width());
if (set->ripple->empty()) {
set->ripple.reset();
if (row->ripple) {
row->ripple->paint(p, rect.x(), rect.y(), width());
if (row->ripple->empty()) {
row->ripple.reset();
}
}
p.setFont(st.font);
@ -1072,19 +1076,19 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
}
if (_actionDown >= 0 && _actionDown < _rows.size()) {
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
auto &set = _rows[_actionDown];
if (set->ripple) {
set->ripple->lastStop();
const auto row = _rows[_actionDown].get();
if (row->ripple) {
row->ripple->lastStop();
}
}
_actionDown = newActionDown;
if (_actionDown >= 0 && _actionDown < _rows.size()) {
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
auto &set = _rows[_actionDown];
auto removeButton = (_section == Section::Installed && !set->removed);
if (!set->ripple) {
const auto row = _rows[_actionDown].get();
auto removeButton = (_section == Section::Installed && !row->removed);
if (!row->ripple) {
if (_section == Section::Installed) {
if (set->removed) {
if (row->removed) {
auto rippleSize = QSize(_undoWidth - st::stickersUndoRemove.width, st::stickersUndoRemove.height);
auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::buttonRadius);
ensureRipple(st::stickersUndoRemove.ripple, std::move(rippleMask), removeButton);
@ -1093,15 +1097,15 @@ void StickersBox::Inner::setActionDown(int newActionDown) {
auto rippleMask = Ui::RippleAnimation::ellipseMask(QSize(rippleSize, rippleSize));
ensureRipple(st::stickersRemove.ripple, std::move(rippleMask), removeButton);
}
} else if (!set->installed || set->archived || set->removed) {
} else if (!row->installed || row->archived || row->removed) {
auto rippleSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height);
auto rippleMask = Ui::RippleAnimation::roundRectMask(rippleSize, st::buttonRadius);
ensureRipple(st::stickersTrendingAdd.ripple, std::move(rippleMask), removeButton);
}
}
if (set->ripple) {
if (row->ripple) {
auto rect = relativeButtonRect(removeButton);
set->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(myrtlrect(rect).x(), _itemsTop + _actionDown * _rowHeight + rect.y()));
row->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(myrtlrect(rect).x(), _itemsTop + _actionDown * _rowHeight + rect.y()));
}
}
}
@ -1110,14 +1114,6 @@ void StickersBox::Inner::setSelected(SelectedRow selected) {
if (_selected == selected) {
return;
}
if ((_megagroupSet || _section != Section::Installed)
&& ((_selected.has_value() || _pressed.has_value()) != (selected.has_value() || _pressed.has_value()))) {
if (!_inDragArea) {
setCursor((selected.has_value() || _pressed.has_value())
? style::cur_pointer
: style::cur_default);
}
}
auto countSelectedIndex = [&] {
if (auto index = base::get_if<int>(&_selected)) {
return *index;
@ -1129,6 +1125,7 @@ void StickersBox::Inner::setSelected(SelectedRow selected) {
update(0, _itemsTop + selectedIndex * _rowHeight, width(), _rowHeight);
}
_selected = selected;
updateCursor();
selectedIndex = countSelectedIndex();
if (_megagroupSet && selectedIndex >= 0 && selectedIndex < _rows.size()) {
update(0, _itemsTop + selectedIndex * _rowHeight, width(), _rowHeight);
@ -1148,9 +1145,9 @@ void StickersBox::Inner::setPressed(SelectedRow pressed) {
auto pressedIndex = countPressedIndex();
if (_megagroupSet && pressedIndex >= 0 && pressedIndex < _rows.size()) {
update(0, _itemsTop + pressedIndex * _rowHeight, width(), _rowHeight);
auto &set = _rows[pressedIndex];
if (set->ripple) {
set->ripple->lastStop();
const auto row = _rows[pressedIndex].get();
if (row->ripple) {
row->ripple->lastStop();
}
}
_pressed = pressed;
@ -1234,15 +1231,15 @@ void StickersBox::Inner::onUpdateSelected() {
auto selectedIndex = floorclamp(local.y() - _itemsTop, _rowHeight, 0, _rows.size() - 1);
selected = selectedIndex;
local.setY(local.y() - _itemsTop - selectedIndex * _rowHeight);
auto &set = _rows[selectedIndex];
if (!_megagroupSet && (_section == Section::Installed || !set->installed || set->archived || set->removed)) {
auto removeButton = (_section == Section::Installed && !set->removed);
const auto row = _rows[selectedIndex].get();
if (!_megagroupSet && (_section == Section::Installed || !row->installed || row->archived || row->removed)) {
auto removeButton = (_section == Section::Installed && !row->removed);
auto rect = myrtlrect(relativeButtonRect(removeButton));
actionSel = rect.contains(local) ? selectedIndex : -1;
} else {
actionSel = -1;
}
if (!_megagroupSet && _section == Section::Installed && !set->isRecentSet()) {
if (!_megagroupSet && _section == Section::Installed && !row->isRecentSet()) {
auto dragAreaWidth = st::contactsPadding.left() + st::stickersReorderIcon.width() + st::stickersReorderSkip;
auto dragArea = myrtlrect(0, 0, dragAreaWidth, _rowHeight);
inDragArea = dragArea.contains(local);
@ -1256,17 +1253,25 @@ void StickersBox::Inner::onUpdateSelected() {
setSelected(selected);
if (_inDragArea != inDragArea) {
_inDragArea = inDragArea;
setCursor(_inDragArea
? style::cur_sizeall
: ((_selected.has_value() || _pressed.has_value())
? style::cur_pointer
: style::cur_default));
updateCursor();
}
setActionSel(actionSel);
emit draggingScrollDelta(0);
}
}
void StickersBox::Inner::updateCursor() {
setCursor(_inDragArea
? style::cur_sizeall
: (!_megagroupSet && _section == Section::Installed)
? ((_actionSel >= 0 && (_actionDown < 0 || _actionDown == _actionSel))
? style::cur_pointer
: style::cur_default)
: (_selected.has_value() || _pressed.has_value())
? style::cur_pointer
: style::cur_default);
}
float64 StickersBox::Inner::aboveShadowOpacity() const {
if (_above < 0) return 0;
@ -1278,9 +1283,7 @@ float64 StickersBox::Inner::aboveShadowOpacity() const {
void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
auto pressed = std::exchange(_pressed, SelectedRow());
if (_section != Section::Installed && !_selected.has_value() && pressed.has_value()) {
setCursor(style::cur_default);
}
updateCursor();
_mouse = e->globalPos();
onUpdateSelected();
@ -1288,7 +1291,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
if (_section == Section::Installed) {
setRowRemoved(_actionDown, !_rows[_actionDown]->removed);
} else if (_installSetCallback) {
_installSetCallback(_rows[_actionDown]->id);
_installSetCallback(_rows[_actionDown]->set->id);
}
} else if (_dragging >= 0) {
QPoint local(mapFromGlobal(_mouse));
@ -1301,42 +1304,28 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
_dragging = _started = -1;
} else if (pressed == _selected && _actionSel < 0 && _actionDown < 0) {
auto selectedIndex = [&] {
const auto selectedIndex = [&] {
if (auto index = base::get_if<int>(&_selected)) {
return *index;
}
return -1;
}();
auto getSetByRow = [&](const Row &row) -> const Stickers::Set* {
auto &sets = _session->data().stickerSetsRef();
if (!row.isRecentSet()) {
auto it = sets.find(row.id);
if (it != sets.cend()) {
return it->second.get();
}
}
return nullptr;
};
auto showSetByRow = [&](const Row &row) {
if (auto set = getSetByRow(row)) {
setSelected(SelectedRow());
Ui::show(
Box<StickerSetBox>(
App::wnd()->sessionController(),
set->mtpInput()),
Ui::LayerOption::KeepOther);
}
const auto showSetByRow = [&](const Row &row) {
setSelected(SelectedRow());
Ui::show(
Box<StickerSetBox>(
App::wnd()->sessionController(),
row.set->mtpInput()),
Ui::LayerOption::KeepOther);
};
if (selectedIndex >= 0 && !_inDragArea) {
auto &row = *_rows[selectedIndex];
if (_megagroupSet) {
if (auto set = getSetByRow(row)) {
setMegagroupSelectedSet(MTP_inputStickerSetID(
MTP_long(set->id),
MTP_long(set->access)));
const auto row = _rows[selectedIndex].get();
if (!row->isRecentSet()) {
if (_megagroupSet) {
setMegagroupSelectedSet(row->set->mtpInput());
} else {
showSetByRow(*row);
}
} else {
showSetByRow(row);
}
} else if (_megagroupSelectedSet && _selected.is<MegagroupSet>()) {
showSetByRow(*_megagroupSelectedSet);
@ -1447,9 +1436,7 @@ void StickersBox::Inner::setActionSel(int32 actionSel) {
if (_actionSel >= 0) update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
_actionSel = actionSel;
if (_actionSel >= 0) update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
if (_section == Section::Installed) {
setCursor((_actionSel >= 0 && (_actionDown < 0 || _actionDown == _actionSel)) ? style::cur_pointer : style::cur_default);
}
updateCursor();
}
}
@ -1485,7 +1472,7 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
if (text.isEmpty()) {
if (_megagroupSelectedSet) {
const auto &sets = _session->data().stickerSets();
const auto it = sets.find(_megagroupSelectedSet->id);
const auto it = sets.find(_megagroupSelectedSet->set->id);
if (it != sets.cend() && !it->second->shortName.isEmpty()) {
setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
}
@ -1522,7 +1509,7 @@ void StickersBox::Inner::rebuildMegagroupSet() {
}
auto &inputId = _megagroupSetInput.c_inputStickerSetID();
auto setId = inputId.vid().v;
auto &sets = _session->data().stickerSets();
const auto &sets = _session->data().stickerSets();
auto it = sets.find(setId);
if (it == sets.cend()
|| (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
@ -1535,21 +1522,18 @@ void StickersBox::Inner::rebuildMegagroupSet() {
const auto set = it->second.get();
auto maxNameWidth = countMaxNameWidth();
auto titleWidth = 0;
auto title = fillSetTitle(*set, maxNameWidth, &titleWidth);
auto count = fillSetCount(*set);
auto thumbnail = ImagePtr();
auto title = fillSetTitle(set, maxNameWidth, &titleWidth);
auto count = fillSetCount(set);
auto sticker = (DocumentData*)nullptr;
auto pixw = 0, pixh = 0;
fillSetCover(*set, &thumbnail, &sticker, &pixw, &pixh);
fillSetCover(set, &sticker, &pixw, &pixh);
auto installed = true, official = false, unread = false, archived = false, removed = false;
if (!_megagroupSelectedSet || _megagroupSelectedSet->id != set->id) {
if (!_megagroupSelectedSet || _megagroupSelectedSet->set->id != set->id) {
_megagroupSetField->setText(set->shortName);
_megagroupSetField->finishAnimating();
}
_megagroupSelectedSet = std::make_unique<Row>(
set->id,
set->access,
thumbnail,
set,
sticker,
count,
title,
@ -1601,7 +1585,7 @@ void StickersBox::Inner::rebuild() {
_rows.reserve(order.size() + 1);
_shiftingStartTimes.reserve(order.size() + 1);
auto &sets = _session->data().stickerSets();
const auto &sets = _session->data().stickerSets();
if (_megagroupSet) {
auto usingFeatured = _session->data().stickerSetsOrder().empty();
_megagroupSubTitle->setText(usingFeatured
@ -1611,7 +1595,7 @@ void StickersBox::Inner::rebuild() {
} else if (_section == Section::Installed) {
auto cloudIt = sets.find(Stickers::CloudRecentSetId);
if (cloudIt != sets.cend() && !cloudIt->second->stickers.isEmpty()) {
rebuildAppendSet(*cloudIt->second, maxNameWidth);
rebuildAppendSet(cloudIt->second.get(), maxNameWidth);
}
}
for (const auto setId : order) {
@ -1621,7 +1605,7 @@ void StickersBox::Inner::rebuild() {
}
const auto set = it->second.get();
rebuildAppendSet(*set, maxNameWidth);
rebuildAppendSet(set, maxNameWidth);
if (set->stickers.isEmpty()
|| (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
@ -1653,28 +1637,23 @@ void StickersBox::Inner::updateSize(int newWidth) {
void StickersBox::Inner::updateRows() {
int maxNameWidth = countMaxNameWidth();
auto &sets = _session->data().stickerSets();
const auto &sets = _session->data().stickerSets();
for (const auto &row : _rows) {
const auto it = sets.find(row->id);
const auto it = sets.find(row->set->id);
if (it == sets.cend()) {
continue;
}
const auto set = it->second.get();
if (!row->sticker) {
auto thumbnail = ImagePtr();
auto sticker = (DocumentData*)nullptr;
auto pixw = 0, pixh = 0;
fillSetCover(*set, &thumbnail, &sticker, &pixw, &pixh);
fillSetCover(set, &sticker, &pixw, &pixh);
if (sticker) {
if ((row->thumbnail.get() != thumbnail.get())
|| (!thumbnail && row->sticker != sticker)) {
if (row->sticker != sticker && !row->thumbnailMedia) {
row->lottie = nullptr;
row->stickerMedia = nullptr;
}
row->thumbnail = thumbnail;
row->sticker = sticker;
row->stickerMedia = sticker->createMediaView();
row->stickerMedia->thumbnailWanted(
Data::FileOriginStickerSet(row->id, row->accessHash));
row->pixw = pixw;
row->pixh = pixh;
}
@ -1682,7 +1661,7 @@ void StickersBox::Inner::updateRows() {
if (!row->isRecentSet()) {
auto wasInstalled = row->installed;
auto wasArchived = row->archived;
fillSetFlags(*set, &row->installed, &row->official, &row->unread, &row->archived);
fillSetFlags(set, &row->installed, &row->official, &row->unread, &row->archived);
if (_section == Section::Installed) {
row->archived = false;
}
@ -1690,15 +1669,15 @@ void StickersBox::Inner::updateRows() {
row->ripple.reset();
}
}
row->title = fillSetTitle(*set, maxNameWidth, &row->titleWidth);
row->count = fillSetCount(*set);
row->title = fillSetTitle(set, maxNameWidth, &row->titleWidth);
row->count = fillSetCount(set);
}
update();
}
bool StickersBox::Inner::appendSet(const Stickers::Set &set) {
for_const (auto &row, _rows) {
if (row->id == set.id) {
bool StickersBox::Inner::appendSet(not_null<Stickers::Set*> set) {
for (const auto &row : _rows) {
if (row->set == set) {
return false;
}
}
@ -1725,28 +1704,27 @@ int StickersBox::Inner::countMaxNameWidth() const {
return namew;
}
void StickersBox::Inner::rebuildAppendSet(const Stickers::Set &set, int maxNameWidth) {
void StickersBox::Inner::rebuildAppendSet(
not_null<Stickers::Set*> set,
int maxNameWidth) {
bool installed = true, official = true, unread = false, archived = false, removed = false;
if (set.id != Stickers::CloudRecentSetId) {
if (set->id != Stickers::CloudRecentSetId) {
fillSetFlags(set, &installed, &official, &unread, &archived);
}
if (_section == Section::Installed && archived) {
return;
}
ImagePtr thumbnail;
DocumentData *sticker = nullptr;
int pixw = 0, pixh = 0;
fillSetCover(set, &thumbnail, &sticker, &pixw, &pixh);
fillSetCover(set, &sticker, &pixw, &pixh);
int titleWidth = 0;
QString title = fillSetTitle(set, maxNameWidth, &titleWidth);
int count = fillSetCount(set);
_rows.push_back(std::make_unique<Row>(
set.id,
set.access,
thumbnail,
set,
sticker,
count,
title,
@ -1761,19 +1739,22 @@ void StickersBox::Inner::rebuildAppendSet(const Stickers::Set &set, int maxNameW
_shiftingStartTimes.push_back(0);
}
void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbnail, DocumentData **outSticker, int *outWidth, int *outHeight) const {
//*thumbnail = set.thumbnail; // #TODO optimize stickers
if (set.stickers.isEmpty()) {
void StickersBox::Inner::fillSetCover(
not_null<Stickers::Set*> set,
DocumentData **outSticker,
int *outWidth,
int *outHeight) const {
if (set->stickers.isEmpty()) {
*outSticker = nullptr;
*outWidth = *outHeight = 0;
return;
}
auto sticker = *outSticker = set.stickers.front();
auto sticker = *outSticker = set->stickers.front();
const auto size = set.hasThumbnail()
const auto size = set->hasThumbnail()
? QSize(
set.thumbnailLocation().width(),
set.thumbnailLocation().height())
set->thumbnailLocation().width(),
set->thumbnailLocation().height())
: sticker->hasThumbnail()
? QSize(
sticker->thumbnailLocation().width(),
@ -1797,9 +1778,12 @@ void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbn
*outHeight = pixh;
}
int StickersBox::Inner::fillSetCount(const Stickers::Set &set) const {
int result = set.stickers.isEmpty() ? set.count : set.stickers.size(), added = 0;
if (set.id == Stickers::CloudRecentSetId) {
int StickersBox::Inner::fillSetCount(not_null<Stickers::Set*> set) const {
int result = set->stickers.isEmpty()
? set->count
: set->stickers.size();
auto added = 0;
if (set->id == Stickers::CloudRecentSetId) {
const auto &sets = _session->data().stickerSets();
auto customIt = sets.find(Stickers::CustomSetId);
if (customIt != sets.cend()) {
@ -1817,8 +1801,11 @@ int StickersBox::Inner::fillSetCount(const Stickers::Set &set) const {
return result + added;
}
QString StickersBox::Inner::fillSetTitle(const Stickers::Set &set, int maxNameWidth, int *outTitleWidth) const {
auto result = set.title;
QString StickersBox::Inner::fillSetTitle(
not_null<Stickers::Set*> set,
int maxNameWidth,
int *outTitleWidth) const {
auto result = set->title;
int titleWidth = st::contactsNameStyle.font->width(result);
if (titleWidth > maxNameWidth) {
result = st::contactsNameStyle.font->elided(result, maxNameWidth);
@ -1831,16 +1818,16 @@ QString StickersBox::Inner::fillSetTitle(const Stickers::Set &set, int maxNameWi
}
void StickersBox::Inner::fillSetFlags(
const Stickers::Set &set,
not_null<Stickers::Set*> set,
bool *outInstalled,
bool *outOfficial,
bool *outUnread,
bool *outArchived) {
*outInstalled = (set.flags & MTPDstickerSet::Flag::f_installed_date);
*outOfficial = (set.flags & MTPDstickerSet::Flag::f_official);
*outArchived = (set.flags & MTPDstickerSet::Flag::f_archived);
*outInstalled = (set->flags & MTPDstickerSet::Flag::f_installed_date);
*outOfficial = (set->flags & MTPDstickerSet::Flag::f_official);
*outArchived = (set->flags & MTPDstickerSet::Flag::f_archived);
if (_section == Section::Featured) {
*outUnread = (set.flags & MTPDstickerSet_ClientFlag::f_unread);
*outUnread = (set->flags & MTPDstickerSet_ClientFlag::f_unread);
} else {
*outUnread = false;
}
@ -1852,7 +1839,7 @@ Stickers::Order StickersBox::Inner::collectSets(Check check) const {
result.reserve(_rows.size());
for_const (auto &row, _rows) {
if (check(row.get())) {
result.push_back(row->id);
result.push_back(row->set->id);
}
}
return result;
@ -1879,7 +1866,7 @@ Stickers::Order StickersBox::Inner::getRemovedSets() const {
int StickersBox::Inner::getRowIndex(uint64 setId) const {
for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
auto &row = _rows[i];
if (row->id == setId) {
if (row->set->id == setId) {
return i;
}
}
@ -1902,7 +1889,7 @@ void StickersBox::Inner::setFullOrder(const Stickers::Order &order) {
void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) {
for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
setRowRemoved(i, removed.contains(_rows[i]->id));
setRowRemoved(i, removed.contains(_rows[i]->set->id));
}
}
@ -1940,22 +1927,14 @@ void StickersBox::Inner::readVisibleSets() {
if (i * _rowHeight < itemsVisibleTop || (i + 1) * _rowHeight > itemsVisibleBottom) {
continue;
}
const auto thumbnail = !_rows[i]->sticker
? nullptr
: _rows[i]->thumbnail
? _rows[i]->thumbnail.get()
: _rows[i]->stickerMedia
? _rows[i]->stickerMedia->thumbnail()
: nullptr;
const auto thumbnailLoading = !_rows[i]->sticker
? false
: _rows[i]->thumbnail
? !thumbnail->loaded()
: _rows[i]->stickerMedia
? _rows[i]->sticker->thumbnailLoading()
const auto thumbnailLoading = _rows[i]->set->hasThumbnail()
? _rows[i]->set->thumbnailLoading()
: _rows[i]->sticker
? ((_rows[i]->stickerMedia && _rows[i]->stickerMedia->loaded())
|| _rows[i]->sticker->thumbnailLoading())
: false;
if (!thumbnailLoading || _rows[i]->stickerMedia->loaded()) {
_session->api().readFeaturedSetDelayed(_rows[i]->id);
_session->api().readFeaturedSetDelayed(_rows[i]->set->id);
}
}
}

View File

@ -41,6 +41,10 @@ namespace Lottie {
class SinglePlayer;
} // namespace Lottie
namespace Stickers {
class Set;
} // namespace Stickers
class StickersBox final
: public Ui::BoxContent
, public RPCSender
@ -181,7 +185,7 @@ public:
void rebuild();
void updateSize(int newWidth = 0);
void updateRows(); // refresh only pack cover stickers
bool appendSet(const Stickers::Set &set);
bool appendSet(not_null<Stickers::Set*> set);
Stickers::Order getOrder() const;
Stickers::Order getFullOrder() const;
@ -227,9 +231,7 @@ public slots:
private:
struct Row {
Row(
uint64 id,
uint64 accessHash,
ImagePtr thumbnail,
not_null<Stickers::Set*> set,
DocumentData *sticker,
int32 count,
const QString &title,
@ -245,11 +247,10 @@ private:
bool isRecentSet() const;
uint64 id = 0;
uint64 accessHash = 0;
ImagePtr thumbnail;
const not_null<Stickers::Set*> set;
DocumentData *sticker = nullptr;
std::shared_ptr<Data::DocumentMedia> stickerMedia;
std::shared_ptr<Stickers::SetThumbnailView> thumbnailMedia;
int32 count = 0;
QString title;
int titleWidth = 0;
@ -302,23 +303,24 @@ private:
void ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton);
bool shiftingAnimationCallback(crl::time now);
void paintRow(Painter &p, not_null<Row*> set, int index);
void paintRowThumbnail(Painter &p, not_null<Row*> set, int left);
void paintFakeButton(Painter &p, not_null<Row*> set, int index);
void paintRow(Painter &p, not_null<Row*> row, int index);
void paintRowThumbnail(Painter &p, not_null<Row*> row, int left);
void paintFakeButton(Painter &p, not_null<Row*> row, int index);
void clear();
void updateCursor();
void setActionSel(int32 actionSel);
float64 aboveShadowOpacity() const;
void validateLottieAnimation(not_null<Row*> set);
void updateRowThumbnail(not_null<Row*> set);
void validateLottieAnimation(not_null<Row*> row);
void updateRowThumbnail(not_null<Row*> row);
void readVisibleSets();
void updateControlsGeometry();
void rebuildAppendSet(const Stickers::Set &set, int maxNameWidth);
void fillSetCover(const Stickers::Set &set, ImagePtr *thumbnail, DocumentData **outSticker, int *outWidth, int *outHeight) const;
int fillSetCount(const Stickers::Set &set) const;
QString fillSetTitle(const Stickers::Set &set, int maxNameWidth, int *outTitleWidth) const;
void fillSetFlags(const Stickers::Set &set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived);
void rebuildAppendSet(not_null<Stickers::Set*> set, int maxNameWidth);
void fillSetCover(not_null<Stickers::Set*> set, DocumentData **outSticker, int *outWidth, int *outHeight) const;
int fillSetCount(not_null<Stickers::Set*> set) const;
QString fillSetTitle(not_null<Stickers::Set*> set, int maxNameWidth, int *outTitleWidth) const;
void fillSetFlags(not_null<Stickers::Set*> set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived);
void rebuildMegagroupSet();
void fixupMegagroupSetAddress();
void handleMegagroupSetAddressChange();

View File

@ -93,7 +93,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
// For testing: Just apply random subset or your sticker sets as archived.
bool ApplyArchivedResultFake() {
auto sets = QVector<MTPStickerSetCovered>();
for (const auto &[id, set] : Auth().data().stickerSetsRef()) {
for (const auto &[id, set] : Auth().data().stickerSets()) {
const auto raw = set.get();
if ((raw->flags & MTPDstickerSet::Flag::f_installed_date)
&& !(raw->flags & MTPDstickerSet_ClientFlag::f_special)) {
@ -884,7 +884,7 @@ std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
if (inputSet.type() != mtpc_inputStickerSetID) {
return std::nullopt;
}
auto &sets = Auth().data().stickerSets();
const auto &sets = Auth().data().stickerSets();
auto it = sets.find(inputSet.c_inputStickerSetID().vid().v);
if (it == sets.cend()) {
return std::nullopt;
@ -1231,19 +1231,15 @@ not_null<Lottie::Animation*> LottieAnimationFromDocument(
}
bool HasLottieThumbnail(
ImagePtr thumbnail,
not_null<Data::DocumentMedia*> media) {
SetThumbnailView *thumb,
Data::DocumentMedia *media) {
if (thumb) {
return !thumb->content().isEmpty();
} else if (!media) {
return false;
}
const auto document = media->owner();
if (thumbnail) {
if (!thumbnail->loaded()) {
return false;
}
const auto &location = thumbnail->location();
const auto &bytes = thumbnail->bytesForCache();
return location.valid()
&& location.type() == StorageFileLocation::Type::StickerSetThumb
&& !bytes.isEmpty();
} else if (const auto info = document->sticker()) {
if (const auto info = document->sticker()) {
if (!info->animated) {
return false;
}
@ -1257,21 +1253,22 @@ bool HasLottieThumbnail(
}
std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
ImagePtr thumbnail,
not_null<Data::DocumentMedia*> media,
SetThumbnailView *thumb,
Data::DocumentMedia *media,
LottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> renderer) {
const auto document = media->owner();
const auto baseKey = thumbnail
? thumbnail->location().file().bigFileBaseCacheKey()
: document->bigFileBaseCacheKey();
const auto baseKey = thumb
? thumb->owner()->thumbnailLocation().file().bigFileBaseCacheKey()
: media
? media->owner()->bigFileBaseCacheKey()
: Storage::Cache::Key();
if (!baseKey) {
return nullptr;
}
const auto content = (thumbnail
? thumbnail->bytesForCache()
: Lottie::ReadContent(media->bytes(), document->filepath()));
const auto content = thumb
? thumb->content()
: Lottie::ReadContent(media->bytes(), media->owner()->filepath());
if (content.isEmpty()) {
return nullptr;
}
@ -1279,11 +1276,16 @@ std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
return std::make_unique<Lottie::SinglePlayer>(
std::forward<decltype(args)>(args)...);
};
const auto session = thumb
? &thumb->owner()->session()
: media
? &media->owner()->session()
: nullptr;
return LottieCachedFromContent(
method,
baseKey,
uint8(sizeTag),
&document->session(),
session,
content,
box);
}

View File

@ -46,6 +46,7 @@ constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL; // for cloud-stored faved sti
constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL; // for setting up megagroup sticker set
class Set;
class SetThumbnailView;
void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d);
bool ApplyArchivedResultFake(); // For testing.
@ -112,11 +113,11 @@ enum class LottieSize : uchar {
QSize box);
[[nodiscard]] bool HasLottieThumbnail(
ImagePtr thumbnail,
not_null<Data::DocumentMedia*> media);
SetThumbnailView *thumb,
Data::DocumentMedia *media);
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
ImagePtr thumbnail,
not_null<Data::DocumentMedia*> media,
SetThumbnailView *thumb,
Data::DocumentMedia *media,
LottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);

View File

@ -59,31 +59,37 @@ struct StickerIcon {
StickerIcon(uint64 setId) : setId(setId) {
}
StickerIcon(
uint64 setId,
ImagePtr thumbnail,
not_null<Stickers::Set*> set,
DocumentData *sticker,
int pixw,
int pixh)
: setId(setId)
, thumbnail(thumbnail)
: setId(set->id)
, set(set)
, sticker(sticker)
, pixw(pixw)
, pixh(pixh) {
}
void ensureMediaCreated() const {
if (stickerMedia || !sticker) {
if (!sticker) {
return;
} else if (set->hasThumbnail()) {
if (!thumbnailMedia) {
thumbnailMedia = set->createThumbnailView();
set->loadThumbnail();
}
} else if (!stickerMedia) {
stickerMedia = sticker->createMediaView();
stickerMedia->thumbnailWanted(sticker->stickerSetOrigin());
}
stickerMedia = sticker->createMediaView();
stickerMedia->thumbnailWanted(sticker->stickerSetOrigin());
}
uint64 setId = 0;
ImagePtr thumbnail;
Stickers::Set *set = nullptr;
mutable std::unique_ptr<Lottie::SinglePlayer> lottie;
mutable QPixmap savedFrame;
DocumentData *sticker = nullptr;
mutable std::shared_ptr<Stickers::SetThumbnailView> thumbnailMedia;
mutable std::shared_ptr<Data::DocumentMedia> stickerMedia;
ChannelData *megagroup = nullptr;
int pixw = 0;
@ -196,18 +202,18 @@ auto StickersListWidget::PrepareStickers(
StickersListWidget::Set::Set(
uint64 id,
Stickers::Set *set,
MTPDstickerSet::Flags flags,
const QString &title,
const QString &shortName,
ImagePtr thumbnail,
int count,
bool externalLayout,
std::vector<Sticker> &&stickers)
: id(id)
, set(set)
, flags(flags)
, title(title)
, shortName(shortName)
, thumbnail(thumbnail)
, stickers(std::move(stickers))
, count(count)
, externalLayout(externalLayout) {
@ -343,11 +349,11 @@ void StickersListWidget::Footer::enumerateVisibleIcons(Callback callback) {
void StickersListWidget::Footer::preloadImages() {
enumerateVisibleIcons([](const StickerIcon &icon, int x) {
if (const auto sticker = icon.sticker) {
const auto origin = sticker->stickerSetOrigin();
if (icon.thumbnail) {
icon.thumbnail->load(origin);
Assert(icon.set != nullptr);
if (icon.set->hasThumbnail()) {
icon.set->loadThumbnail();
} else {
sticker->loadThumbnail(origin);
sticker->loadThumbnail(sticker->stickerSetOrigin());
}
}
});
@ -679,8 +685,7 @@ void StickersListWidget::Footer::refreshIcons(
for (auto &now : icons) {
if (const auto i = indices.find(now.setId); i != end(indices)) {
auto &was = _icons[i->second];
if (now.sticker == was.sticker
&& now.thumbnail.get() == was.thumbnail.get()) {
if (now.sticker == was.sticker) {
now.lottie = std::move(was.lottie);
now.lifetime = std::move(was.lifetime);
now.savedFrame = std::move(was.savedFrame);
@ -728,13 +733,14 @@ void StickersListWidget::Footer::validateIconLottieAnimation(
const StickerIcon &icon) {
icon.ensureMediaCreated();
if (icon.lottie
|| !icon.sticker
|| !Stickers::HasLottieThumbnail(
icon.thumbnail,
icon.thumbnailMedia.get(),
icon.stickerMedia.get())) {
return;
}
auto player = Stickers::LottieThumbnail(
icon.thumbnail,
icon.thumbnailMedia.get(),
icon.stickerMedia.get(),
Stickers::LottieSize::StickersFooter,
QSize(
@ -769,14 +775,13 @@ void StickersListWidget::Footer::paintSetIcon(
int x) const {
if (icon.sticker) {
icon.ensureMediaCreated();
const auto origin = icon.sticker->stickerSetOrigin();
const auto thumb = icon.thumbnail
? icon.thumbnail.get()
: icon.stickerMedia->thumbnail();
if (thumb) {
thumb->load(origin);
}
const_cast<Footer*>(this)->validateIconLottieAnimation(icon);
const auto origin = icon.sticker->stickerSetOrigin();
const auto thumb = icon.thumbnailMedia
? icon.thumbnailMedia->image()
: icon.stickerMedia
? icon.stickerMedia->thumbnail()
: nullptr;
if (!icon.lottie
|| (!icon.lottie->ready() && !icon.savedFrame.isNull())) {
const auto pixmap = !icon.savedFrame.isNull()
@ -1305,13 +1310,13 @@ void StickersListWidget::fillCloudSearchRows(
}
}
void StickersListWidget::addSearchRow(not_null<const Stickers::Set*> set) {
void StickersListWidget::addSearchRow(not_null<Stickers::Set*> set) {
_searchSets.emplace_back(
set->id,
set,
set->flags,
set->title,
set->shortName,
ImagePtr(),// set->thumbnail, #TODO optimize stickers
set->count,
!SetInMyList(set->flags),
PrepareStickers(set->stickers.empty()
@ -2292,7 +2297,7 @@ void StickersListWidget::refreshFeaturedSets() {
}
_featuredSetsCount = _officialSets.size();
if (wereOfficial.size() > wasFeaturedSetsCount) {
auto &sets = session().data().stickerSets();
const auto &sets = session().data().stickerSets();
const auto from = begin(wereOfficial) + wasFeaturedSetsCount;
const auto till = end(wereOfficial);
for (auto i = from; i != till; ++i) {
@ -2375,7 +2380,7 @@ bool StickersListWidget::appendSet(
uint64 setId,
bool externalLayout,
AppendSkip skip) {
auto &sets = session().data().stickerSets();
const auto &sets = session().data().stickerSets();
auto it = sets.find(setId);
if (it == sets.cend()
|| (!externalLayout && it->second->stickers.isEmpty())) {
@ -2395,10 +2400,10 @@ bool StickersListWidget::appendSet(
}
to.emplace_back(
set->id,
set,
set->flags,
set->title,
set->shortName,
ImagePtr(), // set->thumbnail, #TODO optimize stickers
set->count,
externalLayout,
PrepareStickers((set->stickers.empty() && externalLayout)
@ -2477,15 +2482,14 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
});
if (!recentPack.empty()) {
const auto shortName = QString();
const auto thumbnail = ImagePtr();
const auto externalLayout = false;
auto set = Set(
Stickers::RecentSetId,
nullptr,
(MTPDstickerSet::Flag::f_official
| MTPDstickerSet_ClientFlag::f_special),
tr::lng_recent_stickers(tr::now),
shortName,
thumbnail,
recentPack.size(),
externalLayout,
std::move(recentPack));
@ -2515,14 +2519,13 @@ void StickersListWidget::refreshFavedStickers() {
const auto set = it->second.get();
const auto externalLayout = false;
const auto shortName = QString();
const auto thumbnail = ImagePtr();
_mySets.emplace_back(
Stickers::FavedSetId,
nullptr,
(MTPDstickerSet::Flag::f_official
| MTPDstickerSet_ClientFlag::f_special),
Lang::Hard::FavedSetTitle(),
shortName,
thumbnail,
set->count,
externalLayout,
PrepareStickers(set->stickers));
@ -2542,18 +2545,18 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
};
if (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetEmpty) {
if (canEdit) {
auto hidden = session().settings().isGroupStickersSectionHidden(_megagroupSet->id);
auto hidden = session().settings().isGroupStickersSectionHidden(
_megagroupSet->id);
if (isShownHere(hidden)) {
const auto shortName = QString();
const auto thumbnail = ImagePtr();
const auto externalLayout = false;
const auto count = 0;
_mySets.emplace_back(
Stickers::MegagroupSetId,
nullptr,
MTPDstickerSet_ClientFlag::f_special | 0,
tr::lng_group_stickers(tr::now),
shortName,
thumbnail,
count,
externalLayout);
}
@ -2585,14 +2588,13 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
removeHiddenForGroup();
} else if (isShownHere(hidden)) {
const auto shortName = QString();
const auto thumbnail = ImagePtr();
const auto externalLayout = false;
_mySets.emplace_back(
Stickers::MegagroupSetId,
set,
MTPDstickerSet_ClientFlag::f_special | 0,
tr::lng_group_stickers(tr::now),
shortName,
thumbnail,
set->count,
externalLayout,
PrepareStickers(set->stickers));
@ -2635,18 +2637,22 @@ std::vector<StickerIcon> StickersListWidget::fillIcons() {
result.emplace_back(Stickers::RecentSetId);
}
}
const auto &sets = session().data().stickerSets();
for (auto l = _mySets.size(); i != l; ++i) {
if (_mySets[i].id == Stickers::MegagroupSetId) {
result.emplace_back(Stickers::MegagroupSetId);
result.back().megagroup = _megagroupSet;
continue;
}
const auto thumbnail = _mySets[i].thumbnail;
const auto set = _mySets[i].set;
Assert(set != nullptr);
const auto s = _mySets[i].stickers[0].document;
const auto availw = st::stickerIconWidth - 2 * st::stickerIconPadding;
const auto availh = st::emojiFooterHeight - 2 * st::stickerIconPadding;
const auto size = thumbnail
? thumbnail->size()
const auto size = set->hasThumbnail()
? QSize(
set->thumbnailLocation().width(),
set->thumbnailLocation().height())
: s->hasThumbnail()
? QSize(
s->thumbnailLocation().width(),
@ -2662,12 +2668,7 @@ std::vector<StickerIcon> StickersListWidget::fillIcons() {
}
if (pixw < 1) pixw = 1;
if (pixh < 1) pixh = 1;
result.emplace_back(
_mySets[i].id,
thumbnail,
s,
pixw,
pixh);
result.emplace_back(set, s, pixw, pixh);
}
return result;
}
@ -2915,7 +2916,7 @@ void StickersListWidget::displaySet(uint64 setId) {
return;
}
}
auto &sets = session().data().stickerSets();
const auto &sets = session().data().stickerSets();
auto it = sets.find(setId);
if (it != sets.cend()) {
_displayingSet = true;
@ -3006,7 +3007,7 @@ void StickersListWidget::removeSet(uint64 setId) {
auto text = tr::lng_stickers_remove_pack(tr::now, lt_sticker_pack, set->title);
Ui::show(Box<ConfirmBox>(text, tr::lng_stickers_remove_pack_confirm(tr::now), crl::guard(this, [=] {
Ui::hideLayer();
const auto &sets = session().data().stickerSetsRef();
const auto &sets = session().data().stickerSets();
const auto it = sets.find(_removingSetId);
if (it != sets.cend()) {
const auto set = it->second.get();

View File

@ -36,6 +36,10 @@ namespace Data {
class DocumentMedia;
} // namespace Data
namespace Stickers {
class Set;
} // namespace Stickers
namespace ChatHelpers {
struct StickerIcon;
@ -165,10 +169,10 @@ private:
struct Set {
Set(
uint64 id,
Stickers::Set *set,
MTPDstickerSet::Flags flags,
const QString &title,
const QString &shortName,
ImagePtr thumbnail,
int count,
bool externalLayout,
std::vector<Sticker> &&stickers = {});
@ -177,10 +181,10 @@ private:
~Set();
uint64 id = 0;
Stickers::Set *set = nullptr;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
QString title;
QString shortName;
ImagePtr thumbnail;
std::vector<Sticker> stickers;
std::unique_ptr<Ui::RippleAnimation> ripple;
@ -304,7 +308,7 @@ private:
void refreshSearchRows(const std::vector<uint64> *cloudSets);
void fillLocalSearchRows(const QString &query);
void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
void addSearchRow(not_null<const Stickers::Set*> set);
void addSearchRow(not_null<Stickers::Set*> set);
void showPreview();

View File

@ -16,6 +16,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Stickers {
SetThumbnailView::SetThumbnailView(not_null<Set*> owner) : _owner(owner) {
}
not_null<Set*> SetThumbnailView::owner() const {
return _owner;
}
void SetThumbnailView::set(
not_null<Main::Session*> session,
QByteArray content) {
@ -58,6 +65,14 @@ Set::Set(
, _owner(owner) {
}
Data::Session &Set::owner() const {
return *_owner;
}
Main::Session &Set::session() const {
return _owner->session();
}
MTPInputStickerSet Set::mtpInput() const {
return (id && access)
? MTP_inputStickerSetID(MTP_long(id), MTP_long(access))
@ -70,7 +85,7 @@ void Set::setThumbnail(const ImageWithLocation &data) {
data,
_owner->cache(),
Data::kImageCacheTag,
[=](Data::FileOrigin origin) { loadThumbnail(origin); });
[=](Data::FileOrigin origin) { loadThumbnail(); });
if (!data.bytes.isEmpty()) {
if (_thumbnail.loader) {
_thumbnail.loader->cancel();
@ -93,8 +108,9 @@ bool Set::thumbnailFailed() const {
return (_thumbnail.flags & Data::CloudFile::Flag::Failed);
}
void Set::loadThumbnail(Data::FileOrigin origin) {
void Set::loadThumbnail() {
auto &file = _thumbnail;
const auto origin = Data::FileOriginStickerSet(id, access);
const auto fromCloud = LoadFromCloudOrLocal;
const auto cacheTag = Data::kImageCacheTag;
const auto autoLoading = false;
@ -122,7 +138,7 @@ std::shared_ptr<SetThumbnailView> Set::createThumbnailView() {
if (auto active = activeThumbnailView()) {
return active;
}
auto view = std::make_shared<SetThumbnailView>();
auto view = std::make_shared<SetThumbnailView>(this);
_thumbnailView = view;
return view;
}

View File

@ -31,12 +31,17 @@ using Sets = base::flat_map<uint64, std::unique_ptr<Set>>;
class SetThumbnailView final {
public:
explicit SetThumbnailView(not_null<Set*> owner);
[[nodiscard]] not_null<Set*> owner() const;
void set(not_null<Main::Session*> session, QByteArray content);
[[nodiscard]] Image *image() const;
[[nodiscard]] QByteArray content() const;
private:
const not_null<Set*> _owner;
std::unique_ptr<Image> _image;
QByteArray _content;
@ -55,6 +60,9 @@ public:
MTPDstickerSet::Flags flags,
TimeId installDate);
[[nodiscard]] Data::Session &owner() const;
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] MTPInputStickerSet mtpInput() const;
void setThumbnail(const ImageWithLocation &data);
@ -62,7 +70,7 @@ public:
[[nodiscard]] bool hasThumbnail() const;
[[nodiscard]] bool thumbnailLoading() const;
[[nodiscard]] bool thumbnailFailed() const;
void loadThumbnail(Data::FileOrigin origin);
void loadThumbnail();
[[nodiscard]] const ImageLocation &thumbnailLocation() const;
[[nodiscard]] int thumbnailByteSize() const;

View File

@ -3360,16 +3360,18 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
auto it = sets.find(Stickers::CloudRecentSetId);
if (it == sets.cend()) {
if (it == sets.cend()) {
it = sets.emplace(Stickers::CloudRecentSetId, std::make_unique<Stickers::Set>(
&session().data(),
it = sets.emplace(
Stickers::CloudRecentSetId,
uint64(0),
tr::lng_recent_stickers(tr::now),
QString(),
0, // count
0, // hash
MTPDstickerSet_ClientFlag::f_special | 0,
TimeId(0))).first;
std::make_unique<Stickers::Set>(
&session().data(),
Stickers::CloudRecentSetId,
uint64(0),
tr::lng_recent_stickers(tr::now),
QString(),
0, // count
0, // hash
MTPDstickerSet_ClientFlag::f_special | 0,
TimeId(0))).first;
} else {
it->second->title = tr::lng_recent_stickers(tr::now);
}
@ -4518,8 +4520,8 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateStickerSetsOrder: {
auto &d = update.c_updateStickerSetsOrder();
if (!d.is_masks()) {
auto &order = d.vorder().v;
auto &sets = session().data().stickerSets();
const auto &order = d.vorder().v;
const auto &sets = session().data().stickerSets();
Stickers::Order result;
for (const auto &item : order) {
if (sets.find(item.v) == sets.cend()) {

View File

@ -220,9 +220,9 @@ inline std::optional<QString> RestrictionToSendStickers() {
QString TitleRecentlyUsed() {
const auto &sets = Auth().data().stickerSets();
const auto it = sets.constFind(Stickers::CloudRecentSetId);
const auto it = sets.find(Stickers::CloudRecentSetId);
if (it != sets.cend()) {
return it->title;
return it->second->title;
}
return tr::lng_recent_stickers(tr::now);
}
@ -328,37 +328,37 @@ void SendKeyEvent(int command) {
}
void AppendStickerSet(std::vector<PickerScrubberItem> &to, uint64 setId) {
auto &sets = Auth().data().stickerSets();
auto it = sets.constFind(setId);
if (it == sets.cend() || it->stickers.isEmpty()) {
const auto &sets = Auth().data().stickerSets();
const auto it = sets.find(setId);
if (it == sets.cend() || it->second->stickers.isEmpty()) {
return;
}
if (it->flags & MTPDstickerSet::Flag::f_archived) {
const auto set = it->second.get();
if (set->flags & MTPDstickerSet::Flag::f_archived) {
return;
}
if (!(it->flags & MTPDstickerSet::Flag::f_installed_date)) {
if (!(set->flags & MTPDstickerSet::Flag::f_installed_date)) {
return;
}
to.emplace_back(PickerScrubberItem(it->title.isEmpty()
? it->shortName
: it->title));
for (const auto sticker : it->stickers) {
to.emplace_back(PickerScrubberItem(set->title.isEmpty()
? set->shortName
: set->title));
for (const auto sticker : set->stickers) {
to.emplace_back(PickerScrubberItem(sticker));
}
}
void AppendRecentStickers(std::vector<PickerScrubberItem> &to) {
const auto &sets = Auth().data().stickerSets();
const auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
const auto favedIt = sets.constFind(Stickers::FavedSetId);
const auto cloudIt = sets.find(Stickers::CloudRecentSetId);
const auto cloudCount = (cloudIt != sets.cend())
? cloudIt->stickers.size()
? cloudIt->second->stickers.size()
: 0;
if (cloudCount > 0) {
to.emplace_back(PickerScrubberItem(cloudIt->title));
to.emplace_back(PickerScrubberItem(cloudIt->second->title));
auto count = 0;
for (const auto document : cloudIt->stickers) {
for (const auto document : cloudIt->second->stickers) {
if (Stickers::IsFaved(document)) {
continue;
}
@ -372,16 +372,16 @@ void AppendRecentStickers(std::vector<PickerScrubberItem> &to) {
void AppendFavedStickers(std::vector<PickerScrubberItem> &to) {
const auto &sets = Auth().data().stickerSets();
const auto it = sets.constFind(Stickers::FavedSetId);
const auto it = sets.find(Stickers::FavedSetId);
const auto count = (it != sets.cend())
? it->stickers.size()
? it->second->stickers.size()
: 0;
if (!count) {
return;
}
to.emplace_back(PickerScrubberItem(
tr::lng_mac_touchbar_favorite_stickers(tr::now)));
for (const auto document : it->stickers) {
for (const auto document : it->second->stickers) {
to.emplace_back(PickerScrubberItem(document));
}
}
@ -1060,7 +1060,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
) | rpl::start_with_next([=] {
if (const auto window = App::wnd()) {
if (const auto controller = window->sessionController()) {
if (!Auth().data().stickerSets().size()) {
if (Auth().data().stickerSets().empty()) {
Auth().api().updateStickers();
}
_lifetimeSessionControllerChecker.destroy();

View File

@ -3887,29 +3887,33 @@ void importOldRecentStickers() {
auto &recent = cRefRecentStickers();
recent.clear();
const auto def = sets.emplace(Stickers::DefaultSetId, std::make_unique<Stickers::Set>(
&Auth().data(),
const auto def = sets.emplace(
Stickers::DefaultSetId,
uint64(0),
tr::lng_stickers_default_set(tr::now),
QString(),
0, // count
0, // hash
(MTPDstickerSet::Flag::f_official
| MTPDstickerSet::Flag::f_installed_date
| MTPDstickerSet_ClientFlag::f_special),
kDefaultStickerInstallDate)).first->second.get();
const auto custom = sets.emplace(Stickers::CustomSetId, std::make_unique<Stickers::Set>(
&Auth().data(),
std::make_unique<Stickers::Set>(
&Auth().data(),
Stickers::DefaultSetId,
uint64(0),
tr::lng_stickers_default_set(tr::now),
QString(),
0, // count
0, // hash
(MTPDstickerSet::Flag::f_official
| MTPDstickerSet::Flag::f_installed_date
| MTPDstickerSet_ClientFlag::f_special),
kDefaultStickerInstallDate)).first->second.get();
const auto custom = sets.emplace(
Stickers::CustomSetId,
uint64(0),
qsl("Custom stickers"),
QString(),
0, // count
0, // hash
(MTPDstickerSet::Flag::f_installed_date
| MTPDstickerSet_ClientFlag::f_special),
kDefaultStickerInstallDate)).first->second.get();
std::make_unique<Stickers::Set>(
&Auth().data(),
Stickers::CustomSetId,
uint64(0),
qsl("Custom stickers"),
QString(),
0, // count
0, // hash
(MTPDstickerSet::Flag::f_installed_date
| MTPDstickerSet_ClientFlag::f_special),
kDefaultStickerInstallDate)).first->second.get();
QMap<uint64, bool> read;
while (!stickers.stream.atEnd()) {
@ -4035,8 +4039,8 @@ int32 countDocumentVectorHash(const QVector<DocumentData*> vector) {
}
int32 countSpecialStickerSetHash(uint64 setId) {
auto &sets = Auth().data().stickerSets();
auto it = sets.find(setId);
const auto &sets = Auth().data().stickerSets();
const auto it = sets.find(setId);
if (it != sets.cend()) {
return countDocumentVectorHash(it->second->stickers);
}

View File

@ -24,9 +24,7 @@ namespace {
// After 128 MB of unpacked images we try to clear some memory.
constexpr auto kMemoryForCache = 128 * 1024 * 1024;
std::map<QString, std::unique_ptr<Image>> WebUrlImages;
std::unordered_map<InMemoryKey, std::unique_ptr<Image>> StorageImages;
std::unordered_map<InMemoryKey, std::unique_ptr<Image>> WebCachedImages;
std::unordered_map<InMemoryKey, std::unique_ptr<Image>> GeoPointImages;
int64 ComputeUsage(QSize size) {
@ -115,8 +113,6 @@ QImage FromInlineBytes(const QByteArray &bytes) {
void ClearRemote() {
base::take(StorageImages);
base::take(WebUrlImages);
base::take(WebCachedImages);
base::take(GeoPointImages);
}
@ -125,18 +121,6 @@ void ClearAll() {
ClearRemote();
}
ImagePtr Create(const QString &url, QSize box) {
const auto key = qsl("//:%1//:%2//:").arg(box.width()).arg(box.height()) + url;
const auto i = WebUrlImages.find(key);
const auto image = (i != end(WebUrlImages))
? i->second.get()
: WebUrlImages.emplace(
key,
std::make_unique<Image>(std::make_unique<WebUrlSource>(url, box))
).first->second.get();
return ImagePtr(image);
}
ImagePtr Create(QImage &&image, QByteArray format) {
return ImagePtr(new Image(std::make_unique<ImageSource>(
std::move(image),
@ -185,60 +169,6 @@ QSize GetSizeForDocument(const QVector<MTPDocumentAttribute> &attributes) {
return QSize();
}
ImagePtr Create(const MTPDwebDocument &document, QSize box) {
//const auto size = GetSizeForDocument(document.vattributes().v);
//if (size.isEmpty()) {
// return ImagePtr();
//}
// We don't use size from WebDocument, because it is not reliable.
// It can be > 0 and different from the real size that we get in upload.WebFile result.
auto filesize = 0; // document.vsize().v;
return Create(
WebFileLocation(
document.vurl().v,
document.vaccess_hash().v),
box,
filesize);
}
ImagePtr Create(const MTPDwebDocumentNoProxy &document, QSize box) {
//const auto size = GetSizeForDocument(document.vattributes().v);
//if (size.isEmpty()) {
// return ImagePtr();
//}
return Create(qs(document.vurl()), box);
}
ImagePtr Create(const MTPWebDocument &document, QSize box) {
switch (document.type()) {
case mtpc_webDocument:
return Create(document.c_webDocument(), box);
case mtpc_webDocumentNoProxy:
return Create(document.c_webDocumentNoProxy(), box);
}
Unexpected("Type in getImage(MTPWebDocument).");
}
ImagePtr Create(
const WebFileLocation &location,
QSize box,
int size) {
const auto key = inMemoryKey(location);
const auto i = WebCachedImages.find(key);
const auto image = (i != end(WebCachedImages))
? i->second.get()
: WebCachedImages.emplace(
key,
std::make_unique<Image>(std::make_unique<WebCachedSource>(
location,
box,
size))
).first->second.get();
return ImagePtr(image);
}
ImagePtr Create(const GeoPointLocation &location) {
const auto key = inMemoryKey(location);
const auto i = GeoPointImages.find(key);

View File

@ -22,16 +22,8 @@ void ClearAll();
[[nodiscard]] QSize GetSizeForDocument(
const QVector<MTPDocumentAttribute> &attributes);
ImagePtr Create(const QString &url, QSize box);
ImagePtr Create(QImage &&data, QByteArray format);
ImagePtr Create(const StorageImageLocation &location, int size = 0);
ImagePtr CreateStickerSetThumbnail(const StorageImageLocation &location);
ImagePtr Create(const MTPDstickerSet &set, const MTPPhotoSize &size);
ImagePtr Create(const MTPWebDocument &location, QSize box);
ImagePtr Create(
const WebFileLocation &location,
QSize box,
int size = 0);
ImagePtr Create(const GeoPointLocation &location);
class Source {

View File

@ -776,7 +776,7 @@ DownloadLocation DownloadLocation::convertToModern(
if (!data.is<StorageFileLocation>()) {
return *this;
}
auto &file = this->data.get_unchecked<StorageFileLocation>();
auto &file = data.get_unchecked<StorageFileLocation>();
return DownloadLocation{ file.convertToModern(type, id, accessHash) };
}
@ -800,6 +800,12 @@ Storage::Cache::Key DownloadLocation::cacheKey() const {
});
}
Storage::Cache::Key DownloadLocation::bigFileBaseCacheKey() const {
return data.is<StorageFileLocation>()
? data.get_unchecked<StorageFileLocation>().bigFileBaseCacheKey()
: Storage::Cache::Key();
}
bool DownloadLocation::valid() const {
return data.match([](const GeoPointLocation &data) {
return true;

View File

@ -416,6 +416,7 @@ public:
uint64 accessHash) const;
[[nodiscard]] Storage::Cache::Key cacheKey() const;
[[nodiscard]] Storage::Cache::Key bigFileBaseCacheKey() const;
[[nodiscard]] bool valid() const;
[[nodiscard]] bool isLegacy() const;
[[nodiscard]] QByteArray fileReference() const;