Handle clicks on expandable emoji category icons.

This commit is contained in:
John Preston 2022-07-13 14:58:36 +03:00
parent 38a69242ca
commit 57d5ec4513
6 changed files with 189 additions and 95 deletions

View file

@ -114,21 +114,21 @@ emojiTabs: SettingsSlider(defaultTabsSlider) {
} }
emojiScroll: defaultSolidScroll; emojiScroll: defaultSolidScroll;
emojiRecent: icon {{ "emoji/emoji_recent", emojiIconFg }}; emojiRecent: icon {{ "emoji/emoji_recent", emojiIconFg }};
emojiRecentActive: icon {{ "emoji/emoji_recent", emojiIconFgActive }}; emojiRecentActive: icon {{ "emoji/emoji_recent", windowBoldFg }};
emojiPeople: icon {{ "emoji/emoji_people", emojiIconFg }}; emojiPeople: icon {{ "emoji/emoji_people", emojiIconFg }};
emojiPeopleActive: icon {{ "emoji/emoji_people", emojiIconFgActive }}; emojiPeopleActive: icon {{ "emoji/emoji_people", windowBoldFg }};
emojiNature: icon {{ "emoji/emoji_nature", emojiIconFg }}; emojiNature: icon {{ "emoji/emoji_nature", emojiIconFg }};
emojiNatureActive: icon {{ "emoji/emoji_nature", emojiIconFgActive }}; emojiNatureActive: icon {{ "emoji/emoji_nature", windowBoldFg }};
emojiFood: icon {{ "emoji/emoji_food", emojiIconFg }}; emojiFood: icon {{ "emoji/emoji_food", emojiIconFg }};
emojiFoodActive: icon {{ "emoji/emoji_food", emojiIconFgActive }}; emojiFoodActive: icon {{ "emoji/emoji_food", windowBoldFg }};
emojiActivity: icon {{ "emoji/emoji_activity", emojiIconFg }}; emojiActivity: icon {{ "emoji/emoji_activity", emojiIconFg }};
emojiActivityActive: icon {{ "emoji/emoji_activity", emojiIconFgActive }}; emojiActivityActive: icon {{ "emoji/emoji_activity", windowBoldFg }};
emojiTravel: icon {{ "emoji/emoji_travel", emojiIconFg }}; emojiTravel: icon {{ "emoji/emoji_travel", emojiIconFg }};
emojiTravelActive: icon {{ "emoji/emoji_travel", emojiIconFgActive }}; emojiTravelActive: icon {{ "emoji/emoji_travel", windowBoldFg }};
emojiObjects: icon {{ "emoji/emoji_objects", emojiIconFg }}; emojiObjects: icon {{ "emoji/emoji_objects", emojiIconFg }};
emojiObjectsActive: icon {{ "emoji/emoji_objects", emojiIconFgActive }}; emojiObjectsActive: icon {{ "emoji/emoji_objects", windowBoldFg }};
emojiSymbols: icon {{ "emoji/emoji_symbols", emojiIconFg }}; emojiSymbols: icon {{ "emoji/emoji_symbols", emojiIconFg }};
emojiSymbolsActive: icon {{ "emoji/emoji_symbols", emojiIconFgActive }}; emojiSymbolsActive: icon {{ "emoji/emoji_symbols", windowBoldFg }};
emojiFooterHeight: 46px; emojiFooterHeight: 46px;
emojiCategorySkip: 4px; emojiCategorySkip: 4px;

View file

@ -1129,7 +1129,6 @@ void EmojiListWidget::refreshRecent() {
clearSelection(); clearSelection();
_emoji[0] = Core::App().settings().recentEmojiSection(); _emoji[0] = Core::App().settings().recentEmojiSection();
_counts[0] = _emoji[0].size(); _counts[0] = _emoji[0].size();
refreshCustom();
resizeToWidth(width()); resizeToWidth(width());
} }
@ -1371,10 +1370,15 @@ void EmojiListWidget::showEmojiSection(Section section) {
showSet(EmojiSectionSetId(section)); showSet(EmojiSectionSetId(section));
} }
void EmojiListWidget::refreshEmoji() {
refreshRecent();
refreshCustom();
}
void EmojiListWidget::showSet(uint64 setId) { void EmojiListWidget::showSet(uint64 setId) {
clearSelection(); clearSelection();
refreshRecent(); refreshEmoji();
auto y = 0; auto y = 0;
enumerateSections([&](const SectionInfo &info) { enumerateSections([&](const SectionInfo &info) {

View file

@ -69,6 +69,8 @@ public:
QPoint tooltipPos() const override; QPoint tooltipPos() const override;
bool tooltipWindowActive() const override; bool tooltipWindowActive() const override;
void refreshEmoji();
[[nodiscard]] rpl::producer<EmojiPtr> chosen() const; [[nodiscard]] rpl::producer<EmojiPtr> chosen() const;
[[nodiscard]] auto customChosen() const [[nodiscard]] auto customChosen() const
-> rpl::producer<TabbedSelector::FileChosen>; -> rpl::producer<TabbedSelector::FileChosen>;

View file

@ -33,6 +33,9 @@ constexpr auto kEmojiSectionSetIdBase = uint64(0x77FF'FFFF'FFFF'FFF0ULL);
using EmojiSection = Ui::Emoji::Section; using EmojiSection = Ui::Emoji::Section;
void UpdateAnimated(anim::value &value, int to) { void UpdateAnimated(anim::value &value, int to) {
if (int(base::SafeRound(value.to())) == to) {
return;
}
value = anim::value( value = anim::value(
(value.from() != value.to()) ? value.from() : to, (value.from() != value.to()) ? value.from() : to,
to); to);
@ -118,13 +121,12 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
, _searchButtonVisible(descriptor.searchButtonVisible) , _searchButtonVisible(descriptor.searchButtonVisible)
, _settingsButtonVisible(descriptor.settingsButtonVisible) , _settingsButtonVisible(descriptor.settingsButtonVisible)
, _iconsAnimation([=](crl::time now) { , _iconsAnimation([=](crl::time now) {
return iconsAnimationCallback(now); return iconsAnimationCallback(_iconState, now);
}) })
, _subiconsAnimation([=](crl::time now) { , _subiconsAnimation([=](crl::time now) {
return iconsAnimationCallback(now); return iconsAnimationCallback(_subiconState, now);
}) })
, _selectionBg(st::roundRadiusSmall, st::windowBgRipple) , _selectionBg(st::roundRadiusSmall, st::windowBgRipple)
, _emojiIconWidth(st::stickerIconWidth)
, _barSelection(descriptor.barSelection) { , _barSelection(descriptor.barSelection) {
setMouseTracking(true); setMouseTracking(true);
@ -273,11 +275,14 @@ void StickersListFooter::enumerateIcons(
auto left = _iconsLeft - iconsX; auto left = _iconsLeft - iconsX;
const auto emojiId = AllEmojiSectionSetId(); const auto emojiId = AllEmojiSectionSetId();
const auto right = width(); const auto right = width();
const auto single = st::stickerIconWidth;
for (auto i = 0, count = int(_icons.size()); i != count; ++i) { for (auto i = 0, count = int(_icons.size()); i != count; ++i) {
auto &icon = _icons[i]; auto &icon = _icons[i];
const auto width = (icon.setId == emojiId) const auto width = (icon.setId == emojiId)
? _emojiIconWidthAnimation.value(_emojiIconWidth) ? _subiconsWidthAnimation.value(_subiconsExpanded
: st::stickerIconWidth; ? _subiconsWidth
: single)
: single;
const auto visible = (left + width > 0 && left < right); const auto visible = (left + width > 0 && left < right);
const auto result = callback({ const auto result = callback({
.index = i, .index = i,
@ -296,13 +301,13 @@ void StickersListFooter::enumerateSubicons(
Fn<bool(const IconInfo &)> callback) const { Fn<bool(const IconInfo &)> callback) const {
auto iconsX = int(base::SafeRound(_subiconState.x.current())); auto iconsX = int(base::SafeRound(_subiconState.x.current()));
auto left = -iconsX; auto left = -iconsX;
const auto right = _emojiIconWidth; const auto right = _subiconsWidth;
using Section = Ui::Emoji::Section; using Section = Ui::Emoji::Section;
for (auto i = int(Section::People); i <= int(Section::Symbols); ++i) { for (auto i = int(Section::People); i <= int(Section::Symbols); ++i) {
const auto width = st::stickerIconWidth; const auto width = st::stickerIconWidth;
const auto visible = (left + width > 0 && left < right); const auto visible = (left + width > 0 && left < right);
const auto result = callback({ const auto result = callback({
.index = i, .index = i - int(Section::People),
.left = left, .left = left,
.width = int(base::SafeRound(width)), .width = int(base::SafeRound(width)),
.visible = visible, .visible = visible,
@ -353,8 +358,8 @@ void StickersListFooter::preloadImages() {
} }
void StickersListFooter::validateSelectedIcon( void StickersListFooter::validateSelectedIcon(
uint64 setId, uint64 setId,
ValidateIconAnimations animations) { ValidateIconAnimations animations) {
_activeByScrollId = setId; _activeByScrollId = setId;
using EmojiSection = Ui::Emoji::Section; using EmojiSection = Ui::Emoji::Section;
@ -389,21 +394,18 @@ void StickersListFooter::validateSelectedIcon(
} }
void StickersListFooter::updateEmojiSectionWidth() { void StickersListFooter::updateEmojiSectionWidth() {
_emojiIconExpanded = (_iconState.selected >= 0) const auto expanded = (_iconState.selected >= 0)
&& (_iconState.selected < _icons.size()) && (_iconState.selected < _icons.size())
&& (_icons[_iconState.selected].setId == AllEmojiSectionSetId()); && (_icons[_iconState.selected].setId == AllEmojiSectionSetId());
const auto desired = _emojiIconExpanded if (_subiconsExpanded == expanded) {
? (9 * st::stickerIconWidth / 2)
: st::stickerIconWidth;
if (_emojiIconWidth == desired) {
return; return;
} }
_emojiIconWidthAnimation.start( _subiconsExpanded = expanded;
_subiconsWidthAnimation.start(
[=] { updateEmojiWidthCallback(); }, [=] { updateEmojiWidthCallback(); },
_emojiIconWidth, expanded ? st::stickerIconWidth : _subiconsWidth,
desired, expanded ? _subiconsWidth : st::stickerIconWidth,
st::stickerIconMove); st::slideDuration);
_emojiIconWidth = desired;
} }
void StickersListFooter::updateEmojiWidthCallback() { void StickersListFooter::updateEmojiWidthCallback() {
@ -411,6 +413,9 @@ void StickersListFooter::updateEmojiWidthCallback() {
const auto info = iconInfo(_iconState.selected); const auto info = iconInfo(_iconState.selected);
UpdateAnimated(_iconState.selectionX, info.left); UpdateAnimated(_iconState.selectionX, info.left);
UpdateAnimated(_iconState.selectionWidth, info.width); UpdateAnimated(_iconState.selectionWidth, info.width);
if (_iconsAnimation.animating()) {
iconsAnimationCallback(_iconState, crl::now());
}
} }
void StickersListFooter::setSelectedIcon( void StickersListFooter::setSelectedIcon(
@ -421,10 +426,11 @@ void StickersListFooter::setSelectedIcon(
} }
_iconState.selected = newSelected; _iconState.selected = newSelected;
updateEmojiSectionWidth(); updateEmojiSectionWidth();
const auto shift = int(base::SafeRound(_iconState.x.current()));
const auto info = iconInfo(_iconState.selected); const auto info = iconInfo(_iconState.selected);
UpdateAnimated(_iconState.selectionX, info.left, animations); UpdateAnimated(_iconState.selectionX, shift + info.left, animations);
UpdateAnimated(_iconState.selectionWidth, info.width, animations); UpdateAnimated(_iconState.selectionWidth, info.width, animations);
const auto relativeLeft = info.left - _iconsLeft; const auto relativeLeft = shift + info.left - _iconsLeft;
const auto iconsWidthForCentering = 2 * relativeLeft + info.width; const auto iconsWidthForCentering = 2 * relativeLeft + info.width;
const auto iconsXFinal = std::clamp( const auto iconsXFinal = std::clamp(
(_iconsLeft + iconsWidthForCentering + _iconsRight - width()) / 2, (_iconsLeft + iconsWidthForCentering + _iconsRight - width()) / 2,
@ -449,23 +455,21 @@ void StickersListFooter::setSelectedSubicon(
return; return;
} }
_subiconState.selected = newSelected; _subiconState.selected = newSelected;
const auto shift = int(base::SafeRound(_subiconState.x.current()));
const auto info = subiconInfo(_subiconState.selected); const auto info = subiconInfo(_subiconState.selected);
updateEmojiSectionWidth(); UpdateAnimated(_subiconState.selectionX, shift + info.left, animations);
UpdateAnimated(_subiconState.selectionX, info.left, animations);
UpdateAnimated(_subiconState.selectionWidth, info.width, animations); UpdateAnimated(_subiconState.selectionWidth, info.width, animations);
const auto relativeLeft = info.left; const auto relativeLeft = shift + info.left;
const auto subiconsWidthForCentering = 2 * relativeLeft + info.width; const auto subiconsWidthForCentering = 2 * relativeLeft + info.width;
const auto subiconsXFinal = std::clamp( const auto subiconsXFinal = std::clamp(
(subiconsWidthForCentering - width()) / 2, (subiconsWidthForCentering - _subiconsWidth) / 2,
0, 0,
_subiconState.max); _subiconState.max);
if (animations == ValidateIconAnimations::None) { if (animations == ValidateIconAnimations::None) {
_subiconState.selectionX = anim::value( _subiconState.x = anim::value(subiconsXFinal, subiconsXFinal);
subiconsXFinal,
subiconsXFinal);
_subiconsAnimation.stop(); _subiconsAnimation.stop();
} else { } else {
_subiconState.selectionX.start(subiconsXFinal); _subiconState.x.start(subiconsXFinal);
_subiconState.animationStart = crl::now(); _subiconState.animationStart = crl::now();
_subiconsAnimation.start(); _subiconsAnimation.start();
} }
@ -474,7 +478,7 @@ void StickersListFooter::setSelectedSubicon(
} }
void StickersListFooter::processHideFinished() { void StickersListFooter::processHideFinished() {
_iconOver = _iconDown = SpecialOver::None; _selected = _pressed = SpecialOver::None;
_iconsAnimation.stop(); _iconsAnimation.stop();
_iconState.animationStart = 0; _iconState.animationStart = 0;
_iconState.x.finish(); _iconState.x.finish();
@ -603,6 +607,7 @@ void StickersListFooter::resizeEvent(QResizeEvent *e) {
resizeSearchControls(); resizeSearchControls();
} }
refreshIconsGeometry(ValidateIconAnimations::None); refreshIconsGeometry(ValidateIconAnimations::None);
refreshSubiconsGeometry();
} }
void StickersListFooter::resizeSearchControls() { void StickersListFooter::resizeSearchControls() {
@ -637,12 +642,12 @@ void StickersListFooter::mousePressEvent(QMouseEvent *e) {
_iconsMousePos = e ? e->globalPos() : QCursor::pos(); _iconsMousePos = e ? e->globalPos() : QCursor::pos();
updateSelected(); updateSelected();
if (_iconOver == SpecialOver::Settings) { if (_selected == SpecialOver::Settings) {
_openSettingsRequests.fire({}); _openSettingsRequests.fire({});
} else if (_iconOver == SpecialOver::Search) { } else if (_selected == SpecialOver::Search) {
toggleSearch(true); toggleSearch(true);
} else { } else {
_iconDown = _iconOver; _pressed = _selected;
_iconsMouseDown = _iconsMousePos; _iconsMouseDown = _iconsMousePos;
_iconsStartX = qRound(_iconState.x.current()); _iconsStartX = qRound(_iconState.x.current());
} }
@ -654,7 +659,7 @@ void StickersListFooter::mouseMoveEvent(QMouseEvent *e) {
if (!_iconsDragging if (!_iconsDragging
&& !_icons.empty() && !_icons.empty()
&& v::is<int>(_iconDown)) { && v::is<IconId>(_pressed)) {
if ((_iconsMousePos - _iconsMouseDown).manhattanLength() >= QApplication::startDragDistance()) { if ((_iconsMousePos - _iconsMouseDown).manhattanLength() >= QApplication::startDragDistance()) {
_iconsDragging = true; _iconsDragging = true;
} }
@ -679,7 +684,7 @@ void StickersListFooter::mouseReleaseEvent(QMouseEvent *e) {
return; return;
} }
const auto wasDown = std::exchange(_iconDown, SpecialOver::None); const auto wasDown = std::exchange(_pressed, SpecialOver::None);
_iconsMousePos = e ? e->globalPos() : QCursor::pos(); _iconsMousePos = e ? e->globalPos() : QCursor::pos();
if (_iconsDragging) { if (_iconsDragging) {
@ -688,12 +693,23 @@ void StickersListFooter::mouseReleaseEvent(QMouseEvent *e) {
} }
updateSelected(); updateSelected();
if (wasDown == _iconOver) { if (wasDown == _selected) {
if (const auto index = std::get_if<int>(&_iconOver)) { if (const auto icon = std::get_if<IconId>(&_selected)) {
const auto info = iconInfo(*index); const auto info = iconInfo(icon->index);
_iconState.selectionX = anim::value(info.left, info.left); _iconState.selectionX = anim::value(info.left, info.left);
_iconState.selectionWidth = anim::value(info.width, info.width); _iconState.selectionWidth = anim::value(info.width, info.width);
_setChosen.fire_copy(_icons[*index].setId); const auto subinfo = subiconInfo(icon->subindex);
_subiconState.selectionX = anim::value(
subinfo.left,
subinfo.left);
_subiconState.selectionWidth = anim::value(
subinfo.width,
subinfo.width);
const auto setId = _icons[icon->index].setId;
_setChosen.fire_copy((setId == AllEmojiSectionSetId())
? EmojiSectionSetId(
EmojiSection(int(EmojiSection::People) + icon->subindex))
: setId);
} }
} }
} }
@ -717,8 +733,8 @@ bool StickersListFooter::eventHook(QEvent *e) {
if (e->type() == QEvent::TouchBegin) { if (e->type() == QEvent::TouchBegin) {
} else if (e->type() == QEvent::Wheel) { } else if (e->type() == QEvent::Wheel) {
if (!_icons.empty() if (!_icons.empty()
&& v::is<int>(_iconOver) && v::is<IconId>(_selected)
&& (_iconDown == SpecialOver::None)) { && (_pressed == SpecialOver::None)) {
scrollByWheelEvent(static_cast<QWheelEvent*>(e)); scrollByWheelEvent(static_cast<QWheelEvent*>(e));
} }
} }
@ -789,7 +805,7 @@ void StickersListFooter::clipCallback(
} }
void StickersListFooter::updateSelected() { void StickersListFooter::updateSelected() {
if (_iconDown != SpecialOver::None) { if (_pressed != SpecialOver::None) {
return; return;
} }
@ -821,20 +837,30 @@ void StickersListFooter::updateSelected() {
x += qRound(_iconState.x.current()); x += qRound(_iconState.x.current());
enumerateIcons([&](const IconInfo &info) { enumerateIcons([&](const IconInfo &info) {
if (x >= info.left && x < info.left + info.width) { if (x >= info.left && x < info.left + info.width) {
newOver = info.index; newOver = IconId{ .index = info.index };
if (_icons[info.index].setId == AllEmojiSectionSetId()) {
const auto subx = (x - info.left);
enumerateSubicons([&](const IconInfo &info) {
if (subx >= info.left && subx < info.left + info.width) {
v::get<IconId>(newOver).subindex = info.index;
return false;
}
return true;
});
}
return false; return false;
} }
return true; return true;
}); });
} }
} }
if (newOver != _iconOver) { if (newOver != _selected) {
if (newOver == SpecialOver::None) { if (newOver == SpecialOver::None) {
setCursor(style::cur_default); setCursor(style::cur_default);
} else if (_iconOver == SpecialOver::None) { } else if (_selected == SpecialOver::None) {
setCursor(style::cur_pointer); setCursor(style::cur_pointer);
} }
_iconOver = newOver; _selected = newOver;
} }
} }
@ -881,7 +907,7 @@ void StickersListFooter::refreshIcons(
void StickersListFooter::refreshIconsGeometry( void StickersListFooter::refreshIconsGeometry(
ValidateIconAnimations animations) { ValidateIconAnimations animations) {
_iconOver = _iconDown = SpecialOver::None; _selected = _pressed = SpecialOver::None;
_iconState.x.finish(); _iconState.x.finish();
_iconState.selectionX.finish(); _iconState.selectionX.finish();
_iconState.selectionWidth.finish(); _iconState.selectionWidth.finish();
@ -896,9 +922,39 @@ void StickersListFooter::refreshIconsGeometry(
} }
updateSelected(); updateSelected();
validateSelectedIcon(_activeByScrollId, animations); validateSelectedIcon(_activeByScrollId, animations);
refreshSubiconsGeometry();
update(); update();
} }
void StickersListFooter::refreshSubiconsGeometry() {
using Section = Ui::Emoji::Section;
_subiconState.x.finish();
_subiconState.selectionX.finish();
_subiconState.selectionWidth.finish();
_subiconState.animationStart = 0;
_subiconsAnimation.stop();
const auto single = st::stickerIconWidth;
const auto half = single / 2;
const auto count = int(Section::Symbols) - int(Section::Recent);
const auto widthMax = count * single;
const auto widthMin = 4 * single + half;
const auto collapsedWidth = int(_icons.size()) * single;
_subiconsWidth = std::clamp(
width() + single - collapsedWidth,
widthMin,
widthMax);
if (_subiconsWidth < widthMax) {
_subiconsWidth = ((_subiconsWidth - half) / single) * single + half;
}
const auto &last = subiconInfo(int(Section::Symbols));
_subiconState.max = std::max(
widthMax - _subiconsWidth,
0);
if (_subiconState.x.current() > _subiconState.max) {
_subiconState.x = anim::value(_subiconState.max, _subiconState.max);
}
}
bool StickersListFooter::hasOnlyFeaturedSets() const { bool StickersListFooter::hasOnlyFeaturedSets() const {
return (_icons.size() == 1) return (_icons.size() == 1)
&& (_icons[0].setId == Data::Stickers::FeaturedSetId); && (_icons[0].setId == Data::Stickers::FeaturedSetId);
@ -1069,21 +1125,32 @@ void StickersListFooter::paintSetIcon(
_premiumIcon); _premiumIcon);
} else { } else {
using Section = Ui::Emoji::Section; using Section = Ui::Emoji::Section;
const auto sectionIcon = [&](Section section) { const auto sectionIcon = [&](Section section, bool active) {
switch (section) { const auto icons = std::array{
case Section::Recent: return &st::emojiRecent; &st::emojiRecent,
case Section::People: return &st::emojiPeople; &st::emojiRecentActive,
case Section::Nature: return &st::emojiNature; &st::emojiPeople,
case Section::Food: return &st::emojiFood; &st::emojiPeopleActive,
case Section::Activity: return &st::emojiActivity; &st::emojiNature,
case Section::Travel: return &st::emojiTravel; &st::emojiNatureActive,
case Section::Objects: return &st::emojiObjects; &st::emojiFood,
case Section::Symbols: return &st::emojiSymbols; &st::emojiFoodActive,
} &st::emojiActivity,
Unexpected("Section in SetIdEmojiSection result."); &st::emojiActivityActive,
&st::emojiTravel,
&st::emojiTravelActive,
&st::emojiObjects,
&st::emojiObjectsActive,
&st::emojiSymbols,
&st::emojiSymbolsActive,
};
const auto index = int(section) * 2 + (active ? 1 : 0);
Assert(index >= 0 && index < icons.size());
return icons[index];
}; };
auto left = info.left; const auto left = info.left;
const auto paintOne = [&](const style::icon *icon) { const auto paintOne = [&](int left, const style::icon *icon) {
icon->paint( icon->paint(
p, p,
left + (st::stickerIconWidth - icon->width()) / 2, left + (st::stickerIconWidth - icon->width()) / 2,
@ -1100,13 +1167,19 @@ void StickersListFooter::paintSetIcon(
info.width - 2 * skip, info.width - 2 * skip,
st::emojiFooterHeight, st::emojiFooterHeight,
Qt::IntersectClip); Qt::IntersectClip);
for (auto i = int(Section::People); i <= int(Section::Symbols); ++i) { enumerateSubicons([&](const IconInfo &info) {
paintOne(sectionIcon(Section(i))); if (info.visible) {
left += st::stickerIconWidth; paintOne(
} info.left + left,
sectionIcon(
Section(int(Section::People) + info.index),
(_subiconState.selected == info.index)));
}
return true;
});
p.restore(); p.restore();
} else { } else {
paintOne([&] { paintOne(left, [&] {
if (icon.setId == Data::Stickers::FeaturedSetId) { if (icon.setId == Data::Stickers::FeaturedSetId) {
const auto session = &_controller->session(); const auto session = &_controller->session();
return session->data().stickers().featuredSetsUnreadCount() return session->data().stickers().featuredSetsUnreadCount()
@ -1114,8 +1187,10 @@ void StickersListFooter::paintSetIcon(
: &st::stickersTrending; : &st::stickersTrending;
//} else if (setId == Stickers::FavedSetId) { //} else if (setId == Stickers::FavedSetId) {
// return &st::stickersFaved; // return &st::stickersFaved;
} else if (icon.setId == AllEmojiSectionSetId()) {
return &st::emojiPeople;
} else if (const auto section = SetIdEmojiSection(icon.setId)) { } else if (const auto section = SetIdEmojiSection(icon.setId)) {
return sectionIcon(*section); return sectionIcon(*section, false);
} }
return &st::emojiRecent; return &st::emojiRecent;
}()); }());
@ -1123,28 +1198,30 @@ void StickersListFooter::paintSetIcon(
} }
} }
bool StickersListFooter::iconsAnimationCallback(crl::time now) { bool StickersListFooter::iconsAnimationCallback(
ScrollState &state,
crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
now += st::stickerIconMove; now += st::stickerIconMove;
} }
if (_iconState.animationStart) { if (state.animationStart) {
const auto dt = (now - _iconState.animationStart) const auto dt = (now - state.animationStart)
/ float64(st::stickerIconMove); / float64(st::stickerIconMove);
if (dt >= 1.) { if (dt >= 1.) {
_iconState.animationStart = 0; state.animationStart = 0;
_iconState.x.finish(); state.x.finish();
_iconState.selectionX.finish(); state.selectionX.finish();
_iconState.selectionWidth.finish(); state.selectionWidth.finish();
} else { } else {
_iconState.x.update(dt, anim::linear); state.x.update(dt, anim::linear);
_iconState.selectionX.update(dt, anim::linear); state.selectionX.update(dt, anim::linear);
_iconState.selectionWidth.update(dt, anim::linear); state.selectionWidth.update(dt, anim::linear);
} }
} }
update(); update();
return (_iconState.animationStart != 0); return (state.animationStart != 0);
} }
} // namespace ChatHelpers } // namespace ChatHelpers

View file

@ -127,7 +127,15 @@ private:
Search, Search,
Settings, Settings,
}; };
using OverState = std::variant<SpecialOver, int>; struct IconId {
int index = 0;
int subindex = 0;
friend inline bool operator==(IconId a, IconId b) {
return (a.index == b.index) && (a.subindex == b.subindex);
}
};
using OverState = std::variant<SpecialOver, IconId>;
struct IconInfo { struct IconInfo {
int index = 0; int index = 0;
int left = 0; int left = 0;
@ -150,7 +158,7 @@ private:
[[nodiscard]] IconInfo subiconInfo(int index) const; [[nodiscard]] IconInfo subiconInfo(int index) const;
[[nodiscard]] std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer(); [[nodiscard]] std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
bool iconsAnimationCallback(crl::time now); bool iconsAnimationCallback(ScrollState &state, crl::time now);
void setSelectedIcon( void setSelectedIcon(
int newSelected, int newSelected,
ValidateIconAnimations animations); ValidateIconAnimations animations);
@ -162,6 +170,7 @@ private:
void validateIconAnimation(const StickerIcon &icon); void validateIconAnimation(const StickerIcon &icon);
void refreshIconsGeometry(ValidateIconAnimations animations); void refreshIconsGeometry(ValidateIconAnimations animations);
void refreshSubiconsGeometry();
void updateSelected(); void updateSelected();
void updateSetIcon(uint64 setId); void updateSetIcon(uint64 setId);
void updateSetIconAt(int left); void updateSetIconAt(int left);
@ -198,8 +207,8 @@ private:
std::vector<StickerIcon> _icons; std::vector<StickerIcon> _icons;
Fn<std::shared_ptr<Lottie::FrameRenderer>()> _renderer; Fn<std::shared_ptr<Lottie::FrameRenderer>()> _renderer;
uint64 _activeByScrollId = 0; uint64 _activeByScrollId = 0;
OverState _iconOver = SpecialOver::None; OverState _selected = SpecialOver::None;
OverState _iconDown = SpecialOver::None; OverState _pressed = SpecialOver::None;
QPoint _iconsMousePos, _iconsMouseDown; QPoint _iconsMousePos, _iconsMouseDown;
mutable QImage _premiumIcon; mutable QImage _premiumIcon;
@ -217,9 +226,9 @@ private:
Ui::Animations::Basic _subiconsAnimation; Ui::Animations::Basic _subiconsAnimation;
Ui::RoundRect _selectionBg; Ui::RoundRect _selectionBg;
Ui::Animations::Simple _emojiIconWidthAnimation; Ui::Animations::Simple _subiconsWidthAnimation;
int _emojiIconWidth = 0; int _subiconsWidth = 0;
bool _emojiIconExpanded = false; bool _subiconsExpanded = false;
bool _barSelection = false; bool _barSelection = false;
bool _horizontal = false; bool _horizontal = false;

View file

@ -410,6 +410,8 @@ TabbedSelector::TabbedSelector(
emoji()->showSet(setId); emoji()->showSet(setId);
_showRequests.fire({}); _showRequests.fire({});
}, lifetime()); }, lifetime());
emoji()->refreshEmoji();
} }
//setAttribute(Qt::WA_AcceptTouchEvents); //setAttribute(Qt::WA_AcceptTouchEvents);
setAttribute(Qt::WA_OpaquePaintEvent, false); setAttribute(Qt::WA_OpaquePaintEvent, false);