mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Expand emoji categories in the footer.
This commit is contained in:
parent
d3f62d971d
commit
0bd9d5f7ae
5 changed files with 229 additions and 84 deletions
|
@ -179,6 +179,8 @@ emojiSwitchColor: windowActiveTextFg;
|
||||||
emojiSwitchStickers: icon {{ "emoji/emoji_switch", emojiSwitchColor }};
|
emojiSwitchStickers: icon {{ "emoji/emoji_switch", emojiSwitchColor }};
|
||||||
emojiSwitchEmoji: icon {{ "emoji/emoji_switch-flip_horizontal", emojiSwitchColor }};
|
emojiSwitchEmoji: icon {{ "emoji/emoji_switch-flip_horizontal", emojiSwitchColor }};
|
||||||
|
|
||||||
|
emojiIconSelectSkip: 2px;
|
||||||
|
|
||||||
hashtagClose: IconButton {
|
hashtagClose: IconButton {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|
|
@ -1211,11 +1211,10 @@ void EmojiListWidget::refreshCustom() {
|
||||||
|
|
||||||
std::vector<StickerIcon> EmojiListWidget::fillIcons() {
|
std::vector<StickerIcon> EmojiListWidget::fillIcons() {
|
||||||
auto result = std::vector<StickerIcon>();
|
auto result = std::vector<StickerIcon>();
|
||||||
result.reserve(kEmojiSectionCount + _custom.size());
|
result.reserve(2 + _custom.size());
|
||||||
|
|
||||||
for (auto i = 0; i != kEmojiSectionCount; ++i) {
|
result.emplace_back(EmojiSectionSetId(Ui::Emoji::Section::Recent));
|
||||||
result.emplace_back(EmojiSectionSetId(static_cast<Section>(i)));
|
result.emplace_back(EmojiSectionSetId(Ui::Emoji::Section::People));
|
||||||
}
|
|
||||||
for (const auto &custom : _custom) {
|
for (const auto &custom : _custom) {
|
||||||
const auto set = custom.set;
|
const auto set = custom.set;
|
||||||
const auto s = custom.list[0].document;
|
const auto s = custom.list[0].document;
|
||||||
|
|
|
@ -41,6 +41,14 @@ uint64 EmojiSectionSetId(EmojiSection section) {
|
||||||
return kEmojiSectionSetIdBase + static_cast<uint64>(section);
|
return kEmojiSectionSetIdBase + static_cast<uint64>(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64 RecentEmojiSectionSetId() {
|
||||||
|
return EmojiSectionSetId(EmojiSection::Recent);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 FirstEmojiSectionSetId() {
|
||||||
|
return EmojiSectionSetId(EmojiSection::People);
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<EmojiSection> SetIdEmojiSection(uint64 id) {
|
std::optional<EmojiSection> SetIdEmojiSection(uint64 id) {
|
||||||
const auto base = EmojiSectionSetId(EmojiSection::Recent);
|
const auto base = EmojiSectionSetId(EmojiSection::Recent);
|
||||||
if (id < base) {
|
if (id < base) {
|
||||||
|
@ -94,7 +102,10 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
|
||||||
, _settingsButtonVisible(descriptor.settingsButtonVisible)
|
, _settingsButtonVisible(descriptor.settingsButtonVisible)
|
||||||
, _iconsAnimation([=](crl::time now) {
|
, _iconsAnimation([=](crl::time now) {
|
||||||
return iconsAnimationCallback(now);
|
return iconsAnimationCallback(now);
|
||||||
}) {
|
})
|
||||||
|
, _selectionBg(st::roundRadiusSmall, st::windowBgRipple)
|
||||||
|
, _emojiIconWidth(st::stickerIconWidth)
|
||||||
|
, _barSelection(descriptor.barSelection) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
_iconsLeft = st::emojiCategorySkip + (_searchButtonVisible
|
_iconsLeft = st::emojiCategorySkip + (_searchButtonVisible
|
||||||
|
@ -152,6 +163,7 @@ void StickersListFooter::clearHeavyData() {
|
||||||
if (!info.visible) {
|
if (!info.visible) {
|
||||||
icon.savedFrame = QPixmap();
|
icon.savedFrame = QPixmap();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,39 +236,54 @@ void StickersListFooter::returnFocus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListFooter::enumerateVisibleIcons(
|
void StickersListFooter::enumerateVisibleIcons(
|
||||||
Fn<void(const IconInfo &)> callback) {
|
Fn<void(const IconInfo &)> callback) const {
|
||||||
auto iconsX = qRound(_iconsX.current());
|
enumerateIcons([&](const IconInfo &info) {
|
||||||
auto x = _iconsLeft - (iconsX % st::stickerIconWidth);
|
if (info.visible) {
|
||||||
auto first = floorclamp(iconsX, st::stickerIconWidth, 0, _icons.size());
|
callback(info);
|
||||||
auto last = ceilclamp(
|
} else if (info.left > 0) {
|
||||||
iconsX + width(),
|
return false;
|
||||||
st::stickerIconWidth,
|
}
|
||||||
0,
|
return true;
|
||||||
_icons.size());
|
});
|
||||||
for (auto index = first; index != last; ++index) {
|
|
||||||
callback({ .index = index, .left = x, .visible = true });
|
|
||||||
x += st::stickerIconWidth;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListFooter::enumerateIcons(
|
void StickersListFooter::enumerateIcons(
|
||||||
Fn<void(const IconInfo &)> callback) {
|
Fn<bool(const IconInfo &)> callback) const {
|
||||||
auto iconsX = qRound(_iconsX.current());
|
auto iconsX = int(base::SafeRound(_iconsX.current()));
|
||||||
auto x = _iconsLeft - (iconsX % st::stickerIconWidth);
|
auto left = _iconsLeft - iconsX;
|
||||||
auto first = floorclamp(iconsX, st::stickerIconWidth, 0, _icons.size());
|
const auto emojiId = FirstEmojiSectionSetId();
|
||||||
auto last = ceilclamp(
|
const auto right = width();
|
||||||
iconsX + width(),
|
|
||||||
st::stickerIconWidth,
|
|
||||||
0,
|
|
||||||
_icons.size());
|
|
||||||
x -= first * st::stickerIconWidth;
|
|
||||||
for (auto i = 0, count = int(_icons.size()); i != count; ++i) {
|
for (auto i = 0, count = int(_icons.size()); i != count; ++i) {
|
||||||
const auto visible = (i >= first && i < last);
|
auto &icon = _icons[i];
|
||||||
callback({ .index = i, .left = x, .visible = visible });
|
const auto width = (icon.setId == emojiId)
|
||||||
x += st::stickerIconWidth;
|
? _emojiIconWidthAnimation.value(_emojiIconWidth)
|
||||||
|
: st::stickerIconWidth;
|
||||||
|
const auto visible = (left + width > 0 && left < right);
|
||||||
|
const auto result = callback({
|
||||||
|
.index = i,
|
||||||
|
.left = left,
|
||||||
|
.width = int(base::SafeRound(width)),
|
||||||
|
.visible = visible,
|
||||||
|
});
|
||||||
|
if (!result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
left += width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto StickersListFooter::iconInfo(int index) const -> IconInfo {
|
||||||
|
auto result = IconInfo();
|
||||||
|
enumerateIcons([&](const IconInfo &info) {
|
||||||
|
if (info.index == index) {
|
||||||
|
result = info;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void StickersListFooter::preloadImages() {
|
void StickersListFooter::preloadImages() {
|
||||||
enumerateVisibleIcons([&](const IconInfo &info) {
|
enumerateVisibleIcons([&](const IconInfo &info) {
|
||||||
const auto &icon = _icons[info.index];
|
const auto &icon = _icons[info.index];
|
||||||
|
@ -276,8 +303,13 @@ void StickersListFooter::validateSelectedIcon(
|
||||||
ValidateIconAnimations animations) {
|
ValidateIconAnimations animations) {
|
||||||
_activeByScrollId = setId;
|
_activeByScrollId = setId;
|
||||||
|
|
||||||
|
using EmojiSection = Ui::Emoji::Section;
|
||||||
auto favedIconIndex = -1;
|
auto favedIconIndex = -1;
|
||||||
auto newSelected = -1;
|
auto newSelected = -1;
|
||||||
|
const auto emojiSection = SetIdEmojiSection(setId);
|
||||||
|
const auto isEmojiSection = emojiSection.has_value()
|
||||||
|
&& (emojiSection != EmojiSection::Recent);
|
||||||
|
const auto firstEmojiSetId = FirstEmojiSectionSetId();
|
||||||
for (auto i = 0, l = int(_icons.size()); i != l; ++i) {
|
for (auto i = 0, l = int(_icons.size()); i != l; ++i) {
|
||||||
if (_icons[i].setId == setId
|
if (_icons[i].setId == setId
|
||||||
|| (_icons[i].setId == Data::Stickers::FavedSetId
|
|| (_icons[i].setId == Data::Stickers::FavedSetId
|
||||||
|
@ -286,6 +318,8 @@ void StickersListFooter::validateSelectedIcon(
|
||||||
break;
|
break;
|
||||||
} else if (_icons[i].setId == Data::Stickers::FavedSetId) {
|
} else if (_icons[i].setId == Data::Stickers::FavedSetId) {
|
||||||
favedIconIndex = i;
|
favedIconIndex = i;
|
||||||
|
} else if (isEmojiSection && _icons[i].setId == firstEmojiSetId) {
|
||||||
|
newSelected = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setSelectedIcon(
|
setSelectedIcon(
|
||||||
|
@ -295,6 +329,39 @@ void StickersListFooter::validateSelectedIcon(
|
||||||
animations);
|
animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickersListFooter::updateEmojiSectionWidth() {
|
||||||
|
_emojiIconExpanded = (_iconSel >= 0)
|
||||||
|
&& (_iconSel < _icons.size())
|
||||||
|
&& (_icons[_iconSel].setId == FirstEmojiSectionSetId());
|
||||||
|
const auto desired = _emojiIconExpanded
|
||||||
|
? (9 * st::stickerIconWidth / 2)
|
||||||
|
: st::stickerIconWidth;
|
||||||
|
if (_emojiIconWidth == desired) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_emojiIconWidthAnimation.start(
|
||||||
|
[=] { updateEmojiWidthCallback(); },
|
||||||
|
_emojiIconWidth,
|
||||||
|
desired,
|
||||||
|
st::stickerIconMove);
|
||||||
|
_emojiIconWidth = desired;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersListFooter::updateEmojiWidthCallback() {
|
||||||
|
update();
|
||||||
|
const auto info = iconInfo(_iconSel);
|
||||||
|
if (_iconSelX.from() != _iconSelX.to()) {
|
||||||
|
_iconSelX = anim::value(_iconSelX.from(), info.left);
|
||||||
|
} else {
|
||||||
|
_iconSelX = anim::value(info.left, info.left);
|
||||||
|
}
|
||||||
|
if (_iconSelWidth.from() != _iconSelWidth.to()) {
|
||||||
|
_iconSelWidth = anim::value(_iconSelWidth.from(), info.width);
|
||||||
|
} else {
|
||||||
|
_iconSelWidth = anim::value(info.width, info.width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StickersListFooter::setSelectedIcon(
|
void StickersListFooter::setSelectedIcon(
|
||||||
int newSelected,
|
int newSelected,
|
||||||
ValidateIconAnimations animations) {
|
ValidateIconAnimations animations) {
|
||||||
|
@ -302,16 +369,18 @@ void StickersListFooter::setSelectedIcon(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_iconSel = newSelected;
|
_iconSel = newSelected;
|
||||||
auto iconSelXFinal = _iconSel * st::stickerIconWidth;
|
const auto info = iconInfo(_iconSel);
|
||||||
|
updateEmojiSectionWidth();
|
||||||
if (animations == ValidateIconAnimations::Full) {
|
if (animations == ValidateIconAnimations::Full) {
|
||||||
_iconSelX.start(iconSelXFinal);
|
_iconSelX.start(info.left);
|
||||||
|
_iconSelWidth.start(info.width);
|
||||||
} else {
|
} else {
|
||||||
_iconSelX = anim::value(iconSelXFinal, iconSelXFinal);
|
_iconSelX = anim::value(info.left, info.left);
|
||||||
|
_iconSelWidth = anim::value(info.width, info.width);
|
||||||
}
|
}
|
||||||
auto iconsCountForCentering = (2 * _iconSel + 1);
|
const auto relativeLeft = info.left - _iconsLeft;
|
||||||
auto iconsWidthForCentering = iconsCountForCentering
|
const auto iconsWidthForCentering = 2 * relativeLeft + info.width;
|
||||||
* st::stickerIconWidth;
|
const auto iconsXFinal = std::clamp(
|
||||||
auto iconsXFinal = std::clamp(
|
|
||||||
(_iconsLeft + iconsWidthForCentering + _iconsRight - width()) / 2,
|
(_iconsLeft + iconsWidthForCentering + _iconsRight - width()) / 2,
|
||||||
0,
|
0,
|
||||||
_iconsMax);
|
_iconsMax);
|
||||||
|
@ -333,6 +402,7 @@ void StickersListFooter::processHideFinished() {
|
||||||
_iconsAnimation.stop();
|
_iconsAnimation.stop();
|
||||||
_iconsX.finish();
|
_iconsX.finish();
|
||||||
_iconSelX.finish();
|
_iconSelX.finish();
|
||||||
|
_iconSelWidth.finish();
|
||||||
_horizontal = false;
|
_horizontal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +441,10 @@ void StickersListFooter::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
p.setClipRect(clip);
|
p.setClipRect(clip);
|
||||||
|
|
||||||
|
if (!_barSelection) {
|
||||||
|
paintSelectionBg(p);
|
||||||
|
}
|
||||||
|
|
||||||
const auto now = crl::now();
|
const auto now = crl::now();
|
||||||
const auto paused = _controller->isGifPausedAtLeastFor(
|
const auto paused = _controller->isGifPausedAtLeastFor(
|
||||||
Window::GifPauseReason::SavedGifs);
|
Window::GifPauseReason::SavedGifs);
|
||||||
|
@ -378,20 +452,39 @@ void StickersListFooter::paintEvent(QPaintEvent *e) {
|
||||||
paintSetIcon(p, info, now, paused);
|
paintSetIcon(p, info, now, paused);
|
||||||
});
|
});
|
||||||
|
|
||||||
paintSelectionBar(p);
|
if (_barSelection) {
|
||||||
|
paintSelectionBar(p);
|
||||||
|
}
|
||||||
paintLeftRightFading(p);
|
paintLeftRightFading(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersListFooter::paintSelectionBar(Painter &p) const {
|
void StickersListFooter::paintSelectionBg(Painter &p) const {
|
||||||
auto selxrel = _iconsLeft + qRound(_iconSelX.current());
|
auto selxrel = qRound(_iconSelX.current());
|
||||||
auto selx = selxrel - qRound(_iconsX.current());
|
auto selx = selxrel - qRound(_iconsX.current());
|
||||||
|
const auto selw = qRound(_iconSelWidth.current());
|
||||||
if (rtl()) {
|
if (rtl()) {
|
||||||
selx = width() - selx - st::stickerIconWidth;
|
selx = width() - selx - selw;
|
||||||
|
}
|
||||||
|
const auto skip = st::emojiIconSelectSkip;
|
||||||
|
const auto sely = _iconsTop
|
||||||
|
+ (st::emojiFooterHeight - st::stickerIconWidth) / 2;
|
||||||
|
const auto selh = st::stickerIconWidth;
|
||||||
|
const auto rect = QRect(selx, sely, selw, selh);
|
||||||
|
const auto fill = rect.marginsRemoved({ skip, skip, skip, skip });
|
||||||
|
_selectionBg.paint(p, fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersListFooter::paintSelectionBar(Painter &p) const {
|
||||||
|
auto selxrel = qRound(_iconSelX.current());
|
||||||
|
auto selx = selxrel - qRound(_iconsX.current());
|
||||||
|
const auto selw = qRound(_iconSelWidth.current());
|
||||||
|
if (rtl()) {
|
||||||
|
selx = width() - selx - selw;
|
||||||
}
|
}
|
||||||
p.fillRect(
|
p.fillRect(
|
||||||
selx,
|
selx,
|
||||||
_iconsTop + st::emojiFooterHeight - st::stickerIconPadding,
|
_iconsTop + st::emojiFooterHeight - st::stickerIconPadding,
|
||||||
st::stickerIconWidth,
|
selw,
|
||||||
st::stickerIconSel,
|
st::stickerIconSel,
|
||||||
st::stickerIconSelColor);
|
st::stickerIconSelColor);
|
||||||
}
|
}
|
||||||
|
@ -509,9 +602,9 @@ void StickersListFooter::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
updateSelected();
|
updateSelected();
|
||||||
if (wasDown == _iconOver) {
|
if (wasDown == _iconOver) {
|
||||||
if (const auto index = std::get_if<int>(&_iconOver)) {
|
if (const auto index = std::get_if<int>(&_iconOver)) {
|
||||||
_iconSelX = anim::value(
|
const auto info = iconInfo(*index);
|
||||||
*index * st::stickerIconWidth,
|
_iconSelX = anim::value(info.left, info.left);
|
||||||
*index * st::stickerIconWidth);
|
_iconSelWidth = anim::value(info.width, info.width);
|
||||||
_setChosen.fire_copy(_icons[*index].setId);
|
_setChosen.fire_copy(_icons[*index].setId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -585,7 +678,7 @@ void StickersListFooter::clipCallback(
|
||||||
enumerateIcons([&](const IconInfo &info) {
|
enumerateIcons([&](const IconInfo &info) {
|
||||||
auto &icon = _icons[info.index];
|
auto &icon = _icons[info.index];
|
||||||
if (icon.setId != setId || !icon.webm) {
|
if (icon.setId != setId || !icon.webm) {
|
||||||
return;
|
return true;
|
||||||
} else if (icon.webm->state() == State::Error) {
|
} else if (icon.webm->state() == State::Error) {
|
||||||
icon.webm.setBad();
|
icon.webm.setBad();
|
||||||
} else if (!info.visible) {
|
} else if (!info.visible) {
|
||||||
|
@ -597,6 +690,7 @@ void StickersListFooter::clipCallback(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateSetIconAt(info.left);
|
updateSetIconAt(info.left);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
@ -636,10 +730,14 @@ void StickersListFooter::updateSelected() {
|
||||||
&& y < _iconsTop + st::emojiFooterHeight
|
&& y < _iconsTop + st::emojiFooterHeight
|
||||||
&& x >= _iconsLeft
|
&& x >= _iconsLeft
|
||||||
&& x < width() - _iconsRight) {
|
&& x < width() - _iconsRight) {
|
||||||
x += qRound(_iconsX.current()) - _iconsLeft;
|
x += qRound(_iconsX.current());
|
||||||
if (x < _icons.size() * st::stickerIconWidth) {
|
enumerateIcons([&](const IconInfo &info) {
|
||||||
newOver = qFloor(x / st::stickerIconWidth);
|
if (x >= info.left && x < info.left + info.width) {
|
||||||
}
|
newOver = info.index;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newOver != _iconOver) {
|
if (newOver != _iconOver) {
|
||||||
|
@ -698,10 +796,12 @@ void StickersListFooter::refreshIconsGeometry(
|
||||||
_iconOver = _iconDown = SpecialOver::None;
|
_iconOver = _iconDown = SpecialOver::None;
|
||||||
_iconsX.finish();
|
_iconsX.finish();
|
||||||
_iconSelX.finish();
|
_iconSelX.finish();
|
||||||
|
_iconSelWidth.finish();
|
||||||
_iconsStartAnim = 0;
|
_iconsStartAnim = 0;
|
||||||
_iconsAnimation.stop();
|
_iconsAnimation.stop();
|
||||||
|
const auto &last = iconInfo(_icons.size() - 1);
|
||||||
_iconsMax = std::max(
|
_iconsMax = std::max(
|
||||||
_iconsLeft + int(_icons.size()) * st::stickerIconWidth + _iconsRight - width(),
|
last.left + last.width + _iconsRight - width(),
|
||||||
0);
|
0);
|
||||||
if (_iconsX.current() > _iconsMax) {
|
if (_iconsX.current() > _iconsMax) {
|
||||||
_iconsX = anim::value(_iconsMax, _iconsMax);
|
_iconsX = anim::value(_iconsMax, _iconsMax);
|
||||||
|
@ -880,35 +980,58 @@ void StickersListFooter::paintSetIcon(
|
||||||
_iconsTop + (st::emojiFooterHeight - size.height()) / 2,
|
_iconsTop + (st::emojiFooterHeight - size.height()) / 2,
|
||||||
_premiumIcon);
|
_premiumIcon);
|
||||||
} else {
|
} else {
|
||||||
const auto paintedIcon = [&] {
|
using Section = Ui::Emoji::Section;
|
||||||
if (icon.setId == Data::Stickers::FeaturedSetId) {
|
const auto sectionIcon = [&](Section section) {
|
||||||
const auto session = &_controller->session();
|
switch (section) {
|
||||||
return session->data().stickers().featuredSetsUnreadCount()
|
case Section::Recent: return &st::emojiRecent;
|
||||||
? &st::stickersTrendingUnread
|
case Section::People: return &st::emojiPeople;
|
||||||
: &st::stickersTrending;
|
case Section::Nature: return &st::emojiNature;
|
||||||
//} else if (setId == Stickers::FavedSetId) {
|
case Section::Food: return &st::emojiFood;
|
||||||
// return &st::stickersFaved;
|
case Section::Activity: return &st::emojiActivity;
|
||||||
} else if (const auto section = SetIdEmojiSection(icon.setId)) {
|
case Section::Travel: return &st::emojiTravel;
|
||||||
using Section = Ui::Emoji::Section;
|
case Section::Objects: return &st::emojiObjects;
|
||||||
switch (*section) {
|
case Section::Symbols: return &st::emojiSymbols;
|
||||||
case Section::Recent: return &st::emojiRecent;
|
|
||||||
case Section::People: return &st::emojiPeople;
|
|
||||||
case Section::Nature: return &st::emojiNature;
|
|
||||||
case Section::Food: return &st::emojiFood;
|
|
||||||
case Section::Activity: return &st::emojiActivity;
|
|
||||||
case Section::Travel: return &st::emojiTravel;
|
|
||||||
case Section::Objects: return &st::emojiObjects;
|
|
||||||
case Section::Symbols: return &st::emojiSymbols;
|
|
||||||
}
|
|
||||||
Unexpected("Section in SetIdEmojiSection result.");
|
|
||||||
}
|
}
|
||||||
return &st::emojiRecent;
|
Unexpected("Section in SetIdEmojiSection result.");
|
||||||
}();
|
};
|
||||||
paintedIcon->paint(
|
auto left = info.left;
|
||||||
p,
|
const auto paintOne = [&](const style::icon *icon) {
|
||||||
info.left + (st::stickerIconWidth - paintedIcon->width()) / 2,
|
icon->paint(
|
||||||
_iconsTop + (st::emojiFooterHeight - paintedIcon->height()) / 2,
|
p,
|
||||||
width());
|
left + (st::stickerIconWidth - icon->width()) / 2,
|
||||||
|
_iconsTop + (st::emojiFooterHeight - icon->height()) / 2,
|
||||||
|
width());
|
||||||
|
};
|
||||||
|
if (_icons[info.index].setId == FirstEmojiSectionSetId()
|
||||||
|
&& info.width > st::stickerIconWidth) {
|
||||||
|
const auto skip = st::emojiIconSelectSkip;
|
||||||
|
p.save();
|
||||||
|
p.setClipRect(
|
||||||
|
left + skip,
|
||||||
|
_iconsTop,
|
||||||
|
info.width - 2 * skip,
|
||||||
|
st::emojiFooterHeight,
|
||||||
|
Qt::IntersectClip);
|
||||||
|
for (auto i = int(Section::People); i <= int(Section::Symbols); ++i) {
|
||||||
|
paintOne(sectionIcon(Section(i)));
|
||||||
|
left += st::stickerIconWidth;
|
||||||
|
}
|
||||||
|
p.restore();
|
||||||
|
} else {
|
||||||
|
paintOne([&] {
|
||||||
|
if (icon.setId == Data::Stickers::FeaturedSetId) {
|
||||||
|
const auto session = &_controller->session();
|
||||||
|
return session->data().stickers().featuredSetsUnreadCount()
|
||||||
|
? &st::stickersTrendingUnread
|
||||||
|
: &st::stickersTrending;
|
||||||
|
//} else if (setId == Stickers::FavedSetId) {
|
||||||
|
// return &st::stickersFaved;
|
||||||
|
} else if (const auto section = SetIdEmojiSection(icon.setId)) {
|
||||||
|
return sectionIcon(*section);
|
||||||
|
}
|
||||||
|
return &st::emojiRecent;
|
||||||
|
}());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,14 +1040,17 @@ bool StickersListFooter::iconsAnimationCallback(crl::time now) {
|
||||||
now += st::stickerIconMove;
|
now += st::stickerIconMove;
|
||||||
}
|
}
|
||||||
if (_iconsStartAnim) {
|
if (_iconsStartAnim) {
|
||||||
const auto dt = (now - _iconsStartAnim) / float64(st::stickerIconMove);
|
const auto dt = (now - _iconsStartAnim)
|
||||||
|
/ float64(st::stickerIconMove);
|
||||||
if (dt >= 1.) {
|
if (dt >= 1.) {
|
||||||
_iconsStartAnim = 0;
|
_iconsStartAnim = 0;
|
||||||
_iconsX.finish();
|
_iconsX.finish();
|
||||||
_iconSelX.finish();
|
_iconSelX.finish();
|
||||||
|
_iconSelWidth.finish();
|
||||||
} else {
|
} else {
|
||||||
_iconsX.update(dt, anim::linear);
|
_iconsX.update(dt, anim::linear);
|
||||||
_iconSelX.update(dt, anim::linear);
|
_iconSelX.update(dt, anim::linear);
|
||||||
|
_iconSelWidth.update(dt, anim::linear);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "media/clip/media_clip_reader.h"
|
#include "media/clip/media_clip_reader.h"
|
||||||
#include "chat_helpers/tabbed_selector.h"
|
#include "chat_helpers/tabbed_selector.h"
|
||||||
|
#include "ui/round_rect.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class InputField;
|
class InputField;
|
||||||
|
@ -40,6 +41,8 @@ enum class ValidateIconAnimations {
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] uint64 EmojiSectionSetId(Ui::Emoji::Section section);
|
[[nodiscard]] uint64 EmojiSectionSetId(Ui::Emoji::Section section);
|
||||||
|
[[nodiscard]] uint64 RecentEmojiSectionSetId();
|
||||||
|
[[nodiscard]] uint64 FirstEmojiSectionSetId();
|
||||||
[[nodiscard]] std::optional<Ui::Emoji::Section> SetIdEmojiSection(uint64 id);
|
[[nodiscard]] std::optional<Ui::Emoji::Section> SetIdEmojiSection(uint64 id);
|
||||||
|
|
||||||
struct StickerIcon {
|
struct StickerIcon {
|
||||||
|
@ -77,6 +80,7 @@ public:
|
||||||
not_null<RpWidget*> parent;
|
not_null<RpWidget*> parent;
|
||||||
bool searchButtonVisible = false;
|
bool searchButtonVisible = false;
|
||||||
bool settingsButtonVisible = false;
|
bool settingsButtonVisible = false;
|
||||||
|
bool barSelection = false;
|
||||||
};
|
};
|
||||||
explicit StickersListFooter(Descriptor &&descriptor);
|
explicit StickersListFooter(Descriptor &&descriptor);
|
||||||
|
|
||||||
|
@ -127,11 +131,13 @@ private:
|
||||||
struct IconInfo {
|
struct IconInfo {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int left = 0;
|
int left = 0;
|
||||||
|
int width = 0;
|
||||||
bool visible = false;
|
bool visible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void enumerateVisibleIcons(Fn<void(const IconInfo &)> callback);
|
void enumerateVisibleIcons(Fn<void(const IconInfo &)> callback) const;
|
||||||
void enumerateIcons(Fn<void(const IconInfo &)> callback);
|
void enumerateIcons(Fn<bool(const IconInfo &)> callback) const;
|
||||||
|
[[nodiscard]] IconInfo iconInfo(int index) const;
|
||||||
|
|
||||||
[[nodiscard]] std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
|
[[nodiscard]] std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
|
||||||
bool iconsAnimationCallback(crl::time now);
|
bool iconsAnimationCallback(crl::time now);
|
||||||
|
@ -154,10 +160,14 @@ private:
|
||||||
const IconInfo &info,
|
const IconInfo &info,
|
||||||
crl::time now,
|
crl::time now,
|
||||||
bool paused) const;
|
bool paused) const;
|
||||||
|
void paintSelectionBg(Painter &p) const;
|
||||||
void paintSelectionBar(Painter &p) const;
|
void paintSelectionBar(Painter &p) const;
|
||||||
void paintLeftRightFading(Painter &p) const;
|
void paintLeftRightFading(Painter &p) const;
|
||||||
void validatePremiumIcon() const;
|
void validatePremiumIcon() const;
|
||||||
|
|
||||||
|
void updateEmojiSectionWidth();
|
||||||
|
void updateEmojiWidthCallback();
|
||||||
|
|
||||||
void initSearch();
|
void initSearch();
|
||||||
void toggleSearch(bool visible);
|
void toggleSearch(bool visible);
|
||||||
void resizeSearchControls();
|
void resizeSearchControls();
|
||||||
|
@ -189,8 +199,15 @@ private:
|
||||||
int _iconsMax = 0;
|
int _iconsMax = 0;
|
||||||
anim::value _iconsX;
|
anim::value _iconsX;
|
||||||
anim::value _iconSelX;
|
anim::value _iconSelX;
|
||||||
|
anim::value _iconSelWidth;
|
||||||
crl::time _iconsStartAnim = 0;
|
crl::time _iconsStartAnim = 0;
|
||||||
|
|
||||||
|
Ui::RoundRect _selectionBg;
|
||||||
|
Ui::Animations::Simple _emojiIconWidthAnimation;
|
||||||
|
int _emojiIconWidth = 0;
|
||||||
|
bool _emojiIconExpanded = false;
|
||||||
|
bool _barSelection = false;
|
||||||
|
|
||||||
bool _horizontal = false;
|
bool _horizontal = false;
|
||||||
|
|
||||||
bool _searchShown = false;
|
bool _searchShown = false;
|
||||||
|
|
|
@ -252,6 +252,7 @@ object_ptr<TabbedSelector::InnerFooter> StickersListWidget::createFooter() {
|
||||||
.parent = this,
|
.parent = this,
|
||||||
.searchButtonVisible = !_isMasks,
|
.searchButtonVisible = !_isMasks,
|
||||||
.settingsButtonVisible = true,
|
.settingsButtonVisible = true,
|
||||||
|
.barSelection = true,
|
||||||
});
|
});
|
||||||
_footer = result;
|
_footer = result;
|
||||||
|
|
||||||
|
@ -303,7 +304,7 @@ void StickersListWidget::visibleTopBottomUpdated(
|
||||||
}
|
}
|
||||||
if (_footer) {
|
if (_footer) {
|
||||||
_footer->validateSelectedIcon(
|
_footer->validateSelectedIcon(
|
||||||
currentSet(top),
|
currentSet(visibleTop),
|
||||||
ValidateIconAnimations::Full);
|
ValidateIconAnimations::Full);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue