mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Display selected emoji set in footer by background.
This commit is contained in:
parent
0bd9d5f7ae
commit
3dfe48a407
3 changed files with 217 additions and 108 deletions
|
@ -1213,8 +1213,15 @@ std::vector<StickerIcon> EmojiListWidget::fillIcons() {
|
|||
auto result = std::vector<StickerIcon>();
|
||||
result.reserve(2 + _custom.size());
|
||||
|
||||
result.emplace_back(EmojiSectionSetId(Ui::Emoji::Section::Recent));
|
||||
result.emplace_back(EmojiSectionSetId(Ui::Emoji::Section::People));
|
||||
result.emplace_back(RecentEmojiSectionSetId());
|
||||
if (_custom.empty()) {
|
||||
using Section = Ui::Emoji::Section;
|
||||
for (auto i = int(Section::People); i <= int(Section::Symbols); ++i) {
|
||||
result.emplace_back(EmojiSectionSetId(Section(i)));
|
||||
}
|
||||
} else {
|
||||
result.emplace_back(AllEmojiSectionSetId());
|
||||
}
|
||||
for (const auto &custom : _custom) {
|
||||
const auto set = custom.set;
|
||||
const auto s = custom.list[0].document;
|
||||
|
|
|
@ -32,25 +32,42 @@ constexpr auto kEmojiSectionSetIdBase = uint64(0x77FF'FFFF'FFFF'FFF0ULL);
|
|||
|
||||
using EmojiSection = Ui::Emoji::Section;
|
||||
|
||||
void UpdateAnimated(anim::value &value, int to) {
|
||||
value = anim::value(
|
||||
(value.from() != value.to()) ? value.from() : to,
|
||||
to);
|
||||
}
|
||||
|
||||
void UpdateAnimated(
|
||||
anim::value &value,
|
||||
int to,
|
||||
ValidateIconAnimations animations) {
|
||||
if (animations == ValidateIconAnimations::Full) {
|
||||
value.start(to);
|
||||
} else {
|
||||
value = anim::value(to, to);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
uint64 EmojiSectionSetId(EmojiSection section) {
|
||||
Expects(section >= EmojiSection::Recent
|
||||
&& section <= EmojiSection::Symbols);
|
||||
|
||||
return kEmojiSectionSetIdBase + static_cast<uint64>(section);
|
||||
return kEmojiSectionSetIdBase + static_cast<uint64>(section) + 1;
|
||||
}
|
||||
|
||||
uint64 RecentEmojiSectionSetId() {
|
||||
return EmojiSectionSetId(EmojiSection::Recent);
|
||||
}
|
||||
|
||||
uint64 FirstEmojiSectionSetId() {
|
||||
return EmojiSectionSetId(EmojiSection::People);
|
||||
uint64 AllEmojiSectionSetId() {
|
||||
return kEmojiSectionSetIdBase;
|
||||
}
|
||||
|
||||
std::optional<EmojiSection> SetIdEmojiSection(uint64 id) {
|
||||
const auto base = EmojiSectionSetId(EmojiSection::Recent);
|
||||
const auto base = RecentEmojiSectionSetId();
|
||||
if (id < base) {
|
||||
return {};
|
||||
}
|
||||
|
@ -68,11 +85,11 @@ StickerIcon::StickerIcon(
|
|||
DocumentData *sticker,
|
||||
int pixw,
|
||||
int pixh)
|
||||
: setId(set->id)
|
||||
, set(set)
|
||||
, sticker(sticker)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh) {
|
||||
: setId(set->id)
|
||||
, set(set)
|
||||
, sticker(sticker)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh) {
|
||||
}
|
||||
|
||||
StickerIcon::StickerIcon(StickerIcon&&) = default;
|
||||
|
@ -103,6 +120,9 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
|
|||
, _iconsAnimation([=](crl::time now) {
|
||||
return iconsAnimationCallback(now);
|
||||
})
|
||||
, _subiconsAnimation([=](crl::time now) {
|
||||
return iconsAnimationCallback(now);
|
||||
})
|
||||
, _selectionBg(st::roundRadiusSmall, st::windowBgRipple)
|
||||
, _emojiIconWidth(st::stickerIconWidth)
|
||||
, _barSelection(descriptor.barSelection) {
|
||||
|
@ -145,7 +165,7 @@ void StickersListFooter::validatePremiumIcon() const {
|
|||
gradient.setStops({
|
||||
{ 0., st::stickerPanPremium1->c },
|
||||
{ 1., st::stickerPanPremium2->c },
|
||||
});
|
||||
});
|
||||
p.fillRect(QRect(QPoint(), size), gradient);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.drawImage(QRect(QPoint(), size), mask);
|
||||
|
@ -153,7 +173,7 @@ void StickersListFooter::validatePremiumIcon() const {
|
|||
|
||||
void StickersListFooter::clearHeavyData() {
|
||||
const auto count = int(_icons.size());
|
||||
const auto iconsX = qRound(_iconsX.current());
|
||||
const auto iconsX = qRound(_iconState.x.current());
|
||||
enumerateIcons([&](const IconInfo &info) {
|
||||
auto &icon = _icons[info.index];
|
||||
icon.webm = nullptr;
|
||||
|
@ -187,13 +207,13 @@ void StickersListFooter::initSearch() {
|
|||
_searchRequests.fire({
|
||||
.text = _searchField->getLastText(),
|
||||
.forced = true,
|
||||
});
|
||||
});
|
||||
});
|
||||
connect(_searchField, &Ui::InputField::cancelled, cancelSearch);
|
||||
connect(_searchField, &Ui::InputField::changed, [=] {
|
||||
_searchRequests.fire({
|
||||
.text = _searchField->getLastText(),
|
||||
});
|
||||
});
|
||||
});
|
||||
_searchCancel->setClickedCallback(cancelSearch);
|
||||
|
||||
|
@ -236,7 +256,7 @@ void StickersListFooter::returnFocus() {
|
|||
}
|
||||
|
||||
void StickersListFooter::enumerateVisibleIcons(
|
||||
Fn<void(const IconInfo &)> callback) const {
|
||||
Fn<void(const IconInfo &)> callback) const {
|
||||
enumerateIcons([&](const IconInfo &info) {
|
||||
if (info.visible) {
|
||||
callback(info);
|
||||
|
@ -249,9 +269,9 @@ void StickersListFooter::enumerateVisibleIcons(
|
|||
|
||||
void StickersListFooter::enumerateIcons(
|
||||
Fn<bool(const IconInfo &)> callback) const {
|
||||
auto iconsX = int(base::SafeRound(_iconsX.current()));
|
||||
auto iconsX = int(base::SafeRound(_iconState.x.current()));
|
||||
auto left = _iconsLeft - iconsX;
|
||||
const auto emojiId = FirstEmojiSectionSetId();
|
||||
const auto emojiId = AllEmojiSectionSetId();
|
||||
const auto right = width();
|
||||
for (auto i = 0, count = int(_icons.size()); i != count; ++i) {
|
||||
auto &icon = _icons[i];
|
||||
|
@ -272,6 +292,28 @@ void StickersListFooter::enumerateIcons(
|
|||
}
|
||||
}
|
||||
|
||||
void StickersListFooter::enumerateSubicons(
|
||||
Fn<bool(const IconInfo &)> callback) const {
|
||||
auto iconsX = int(base::SafeRound(_subiconState.x.current()));
|
||||
auto left = -iconsX;
|
||||
const auto right = _emojiIconWidth;
|
||||
using Section = Ui::Emoji::Section;
|
||||
for (auto i = int(Section::People); i <= int(Section::Symbols); ++i) {
|
||||
const auto width = 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) {
|
||||
|
@ -284,6 +326,18 @@ auto StickersListFooter::iconInfo(int index) const -> IconInfo {
|
|||
return result;
|
||||
}
|
||||
|
||||
auto StickersListFooter::subiconInfo(int index) const -> IconInfo {
|
||||
auto result = IconInfo();
|
||||
enumerateSubicons([&](const IconInfo &info) {
|
||||
if (info.index == index) {
|
||||
result = info;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void StickersListFooter::preloadImages() {
|
||||
enumerateVisibleIcons([&](const IconInfo &info) {
|
||||
const auto &icon = _icons[info.index];
|
||||
|
@ -299,17 +353,18 @@ void StickersListFooter::preloadImages() {
|
|||
}
|
||||
|
||||
void StickersListFooter::validateSelectedIcon(
|
||||
uint64 setId,
|
||||
ValidateIconAnimations animations) {
|
||||
uint64 setId,
|
||||
ValidateIconAnimations animations) {
|
||||
_activeByScrollId = setId;
|
||||
|
||||
using EmojiSection = Ui::Emoji::Section;
|
||||
auto favedIconIndex = -1;
|
||||
auto newSelected = -1;
|
||||
auto newSubSelected = -1;
|
||||
const auto emojiSection = SetIdEmojiSection(setId);
|
||||
const auto isEmojiSection = emojiSection.has_value()
|
||||
&& (emojiSection != EmojiSection::Recent);
|
||||
const auto firstEmojiSetId = FirstEmojiSectionSetId();
|
||||
const auto allEmojiSetId = AllEmojiSectionSetId();
|
||||
for (auto i = 0, l = int(_icons.size()); i != l; ++i) {
|
||||
if (_icons[i].setId == setId
|
||||
|| (_icons[i].setId == Data::Stickers::FavedSetId
|
||||
|
@ -318,8 +373,9 @@ void StickersListFooter::validateSelectedIcon(
|
|||
break;
|
||||
} else if (_icons[i].setId == Data::Stickers::FavedSetId) {
|
||||
favedIconIndex = i;
|
||||
} else if (isEmojiSection && _icons[i].setId == firstEmojiSetId) {
|
||||
} else if (isEmojiSection && _icons[i].setId == allEmojiSetId) {
|
||||
newSelected = i;
|
||||
newSubSelected = setId - EmojiSectionSetId(EmojiSection::People);
|
||||
}
|
||||
}
|
||||
setSelectedIcon(
|
||||
|
@ -327,12 +383,15 @@ void StickersListFooter::validateSelectedIcon(
|
|||
? newSelected
|
||||
: (favedIconIndex >= 0) ? favedIconIndex : 0),
|
||||
animations);
|
||||
setSelectedSubicon(
|
||||
(newSubSelected >= 0 ? newSubSelected : 0),
|
||||
animations);
|
||||
}
|
||||
|
||||
void StickersListFooter::updateEmojiSectionWidth() {
|
||||
_emojiIconExpanded = (_iconSel >= 0)
|
||||
&& (_iconSel < _icons.size())
|
||||
&& (_icons[_iconSel].setId == FirstEmojiSectionSetId());
|
||||
_emojiIconExpanded = (_iconState.selected >= 0)
|
||||
&& (_iconState.selected < _icons.size())
|
||||
&& (_icons[_iconState.selected].setId == AllEmojiSectionSetId());
|
||||
const auto desired = _emojiIconExpanded
|
||||
? (9 * st::stickerIconWidth / 2)
|
||||
: st::stickerIconWidth;
|
||||
|
@ -349,60 +408,83 @@ void StickersListFooter::updateEmojiSectionWidth() {
|
|||
|
||||
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);
|
||||
}
|
||||
const auto info = iconInfo(_iconState.selected);
|
||||
UpdateAnimated(_iconState.selectionX, info.left);
|
||||
UpdateAnimated(_iconState.selectionWidth, info.width);
|
||||
}
|
||||
|
||||
void StickersListFooter::setSelectedIcon(
|
||||
int newSelected,
|
||||
ValidateIconAnimations animations) {
|
||||
if (_iconSel == newSelected) {
|
||||
if (_iconState.selected == newSelected) {
|
||||
return;
|
||||
}
|
||||
_iconSel = newSelected;
|
||||
const auto info = iconInfo(_iconSel);
|
||||
_iconState.selected = newSelected;
|
||||
updateEmojiSectionWidth();
|
||||
if (animations == ValidateIconAnimations::Full) {
|
||||
_iconSelX.start(info.left);
|
||||
_iconSelWidth.start(info.width);
|
||||
} else {
|
||||
_iconSelX = anim::value(info.left, info.left);
|
||||
_iconSelWidth = anim::value(info.width, info.width);
|
||||
}
|
||||
const auto info = iconInfo(_iconState.selected);
|
||||
UpdateAnimated(_iconState.selectionX, info.left, animations);
|
||||
UpdateAnimated(_iconState.selectionWidth, info.width, animations);
|
||||
const auto relativeLeft = info.left - _iconsLeft;
|
||||
const auto iconsWidthForCentering = 2 * relativeLeft + info.width;
|
||||
const auto iconsXFinal = std::clamp(
|
||||
(_iconsLeft + iconsWidthForCentering + _iconsRight - width()) / 2,
|
||||
0,
|
||||
_iconsMax);
|
||||
_iconState.max);
|
||||
if (animations == ValidateIconAnimations::None) {
|
||||
_iconsX = anim::value(iconsXFinal, iconsXFinal);
|
||||
_iconState.x = anim::value(iconsXFinal, iconsXFinal);
|
||||
_iconsAnimation.stop();
|
||||
} else {
|
||||
_iconsX.start(iconsXFinal);
|
||||
_iconsStartAnim = crl::now();
|
||||
_iconState.x.start(iconsXFinal);
|
||||
_iconState.animationStart = crl::now();
|
||||
_iconsAnimation.start();
|
||||
}
|
||||
updateSelected();
|
||||
update();
|
||||
}
|
||||
|
||||
void StickersListFooter::setSelectedSubicon(
|
||||
int newSelected,
|
||||
ValidateIconAnimations animations) {
|
||||
if (_subiconState.selected == newSelected) {
|
||||
return;
|
||||
}
|
||||
_subiconState.selected = newSelected;
|
||||
const auto info = subiconInfo(_subiconState.selected);
|
||||
updateEmojiSectionWidth();
|
||||
UpdateAnimated(_subiconState.selectionX, info.left, animations);
|
||||
UpdateAnimated(_subiconState.selectionWidth, info.width, animations);
|
||||
const auto relativeLeft = info.left;
|
||||
const auto subiconsWidthForCentering = 2 * relativeLeft + info.width;
|
||||
const auto subiconsXFinal = std::clamp(
|
||||
(subiconsWidthForCentering - width()) / 2,
|
||||
0,
|
||||
_subiconState.max);
|
||||
if (animations == ValidateIconAnimations::None) {
|
||||
_subiconState.selectionX = anim::value(
|
||||
subiconsXFinal,
|
||||
subiconsXFinal);
|
||||
_subiconsAnimation.stop();
|
||||
} else {
|
||||
_subiconState.selectionX.start(subiconsXFinal);
|
||||
_subiconState.animationStart = crl::now();
|
||||
_subiconsAnimation.start();
|
||||
}
|
||||
updateSelected();
|
||||
update();
|
||||
}
|
||||
|
||||
void StickersListFooter::processHideFinished() {
|
||||
_iconOver = _iconDown = SpecialOver::None;
|
||||
_iconsStartAnim = 0;
|
||||
_iconsAnimation.stop();
|
||||
_iconsX.finish();
|
||||
_iconSelX.finish();
|
||||
_iconSelWidth.finish();
|
||||
_iconState.animationStart = 0;
|
||||
_iconState.x.finish();
|
||||
_iconState.selectionX.finish();
|
||||
_iconState.selectionWidth.finish();
|
||||
_subiconsAnimation.stop();
|
||||
_subiconState.animationStart = 0;
|
||||
_subiconState.x.finish();
|
||||
_subiconState.selectionX.finish();
|
||||
_subiconState.selectionWidth.finish();
|
||||
_horizontal = false;
|
||||
}
|
||||
|
||||
|
@ -459,9 +541,9 @@ void StickersListFooter::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
|
||||
void StickersListFooter::paintSelectionBg(Painter &p) const {
|
||||
auto selxrel = qRound(_iconSelX.current());
|
||||
auto selx = selxrel - qRound(_iconsX.current());
|
||||
const auto selw = qRound(_iconSelWidth.current());
|
||||
auto selxrel = qRound(_iconState.selectionX.current());
|
||||
auto selx = selxrel - qRound(_iconState.x.current());
|
||||
const auto selw = qRound(_iconState.selectionWidth.current());
|
||||
if (rtl()) {
|
||||
selx = width() - selx - selw;
|
||||
}
|
||||
|
@ -475,9 +557,9 @@ void StickersListFooter::paintSelectionBg(Painter &p) const {
|
|||
}
|
||||
|
||||
void StickersListFooter::paintSelectionBar(Painter &p) const {
|
||||
auto selxrel = qRound(_iconSelX.current());
|
||||
auto selx = selxrel - qRound(_iconsX.current());
|
||||
const auto selw = qRound(_iconSelWidth.current());
|
||||
auto selxrel = qRound(_iconState.selectionX.current());
|
||||
auto selx = selxrel - qRound(_iconState.x.current());
|
||||
const auto selw = qRound(_iconState.selectionWidth.current());
|
||||
if (rtl()) {
|
||||
selx = width() - selx - selw;
|
||||
}
|
||||
|
@ -491,7 +573,7 @@ void StickersListFooter::paintSelectionBar(Painter &p) const {
|
|||
|
||||
void StickersListFooter::paintLeftRightFading(Painter &p) const {
|
||||
auto o_left = std::clamp(
|
||||
_iconsX.current() / st::stickerIconLeft.width(),
|
||||
_iconState.x.current() / st::stickerIconLeft.width(),
|
||||
0.,
|
||||
1.);
|
||||
if (o_left > 0) {
|
||||
|
@ -500,12 +582,18 @@ void StickersListFooter::paintLeftRightFading(Painter &p) const {
|
|||
p.setOpacity(1.);
|
||||
}
|
||||
auto o_right = std::clamp(
|
||||
(_iconsMax - _iconsX.current()) / st::stickerIconRight.width(),
|
||||
(_iconState.max - _iconState.x.current()) / st::stickerIconRight.width(),
|
||||
0.,
|
||||
1.);
|
||||
if (o_right > 0) {
|
||||
p.setOpacity(o_right);
|
||||
st::stickerIconRight.fill(p, style::rtlrect(width() - _iconsRight - st::stickerIconRight.width(), _iconsTop, st::stickerIconRight.width(), st::emojiFooterHeight, width()));
|
||||
st::stickerIconRight.fill(
|
||||
p,
|
||||
style::rtlrect(
|
||||
width() - _iconsRight - st::stickerIconRight.width(),
|
||||
_iconsTop,
|
||||
st::stickerIconRight.width(),
|
||||
st::emojiFooterHeight, width()));
|
||||
p.setOpacity(1.);
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +644,7 @@ void StickersListFooter::mousePressEvent(QMouseEvent *e) {
|
|||
} else {
|
||||
_iconDown = _iconOver;
|
||||
_iconsMouseDown = _iconsMousePos;
|
||||
_iconsStartX = qRound(_iconsX.current());
|
||||
_iconsStartX = qRound(_iconState.x.current());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,10 +664,10 @@ void StickersListFooter::mouseMoveEvent(QMouseEvent *e) {
|
|||
(rtl() ? -1 : 1) * (_iconsMouseDown.x() - _iconsMousePos.x())
|
||||
+ _iconsStartX,
|
||||
0,
|
||||
_iconsMax);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_iconState.max);
|
||||
if (newX != qRound(_iconState.x.current())) {
|
||||
_iconState.x = anim::value(newX, newX);
|
||||
_iconState.animationStart = 0;
|
||||
_iconsAnimation.stop();
|
||||
update();
|
||||
}
|
||||
|
@ -603,8 +691,8 @@ void StickersListFooter::mouseReleaseEvent(QMouseEvent *e) {
|
|||
if (wasDown == _iconOver) {
|
||||
if (const auto index = std::get_if<int>(&_iconOver)) {
|
||||
const auto info = iconInfo(*index);
|
||||
_iconSelX = anim::value(info.left, info.left);
|
||||
_iconSelWidth = anim::value(info.width, info.width);
|
||||
_iconState.selectionX = anim::value(info.left, info.left);
|
||||
_iconState.selectionWidth = anim::value(info.width, info.width);
|
||||
_setChosen.fire_copy(_icons[*index].setId);
|
||||
}
|
||||
}
|
||||
|
@ -614,10 +702,10 @@ void StickersListFooter::finishDragging() {
|
|||
auto newX = std::clamp(
|
||||
_iconsStartX + _iconsMouseDown.x() - _iconsMousePos.x(),
|
||||
0,
|
||||
_iconsMax);
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
_iconState.max);
|
||||
if (newX != qRound(_iconState.x.current())) {
|
||||
_iconState.x = anim::value(newX, newX);
|
||||
_iconState.animationStart = 0;
|
||||
_iconsAnimation.stop();
|
||||
update();
|
||||
}
|
||||
|
@ -644,25 +732,25 @@ void StickersListFooter::scrollByWheelEvent(
|
|||
if (horizontal) {
|
||||
_horizontal = true;
|
||||
}
|
||||
auto newX = qRound(_iconsX.current());
|
||||
auto newX = qRound(_iconState.x.current());
|
||||
if (/*_horizontal && */horizontal) {
|
||||
newX = std::clamp(
|
||||
newX - (rtl() ? -1 : 1) * (e->pixelDelta().x()
|
||||
? e->pixelDelta().x()
|
||||
: e->angleDelta().x()),
|
||||
0,
|
||||
_iconsMax);
|
||||
_iconState.max);
|
||||
} else if (/*!_horizontal && */vertical) {
|
||||
newX = std::clamp(
|
||||
newX - (e->pixelDelta().y()
|
||||
? e->pixelDelta().y()
|
||||
: e->angleDelta().y()),
|
||||
0,
|
||||
_iconsMax);
|
||||
_iconState.max);
|
||||
}
|
||||
if (newX != qRound(_iconsX.current())) {
|
||||
_iconsX = anim::value(newX, newX);
|
||||
_iconsStartAnim = 0;
|
||||
if (newX != qRound(_iconState.x.current())) {
|
||||
_iconState.x = anim::value(newX, newX);
|
||||
_iconState.animationStart = 0;
|
||||
_iconsAnimation.stop();
|
||||
updateSelected();
|
||||
update();
|
||||
|
@ -730,7 +818,7 @@ void StickersListFooter::updateSelected() {
|
|||
&& y < _iconsTop + st::emojiFooterHeight
|
||||
&& x >= _iconsLeft
|
||||
&& x < width() - _iconsRight) {
|
||||
x += qRound(_iconsX.current());
|
||||
x += qRound(_iconState.x.current());
|
||||
enumerateIcons([&](const IconInfo &info) {
|
||||
if (x >= info.left && x < info.left + info.width) {
|
||||
newOver = info.index;
|
||||
|
@ -794,17 +882,17 @@ void StickersListFooter::refreshIcons(
|
|||
void StickersListFooter::refreshIconsGeometry(
|
||||
ValidateIconAnimations animations) {
|
||||
_iconOver = _iconDown = SpecialOver::None;
|
||||
_iconsX.finish();
|
||||
_iconSelX.finish();
|
||||
_iconSelWidth.finish();
|
||||
_iconsStartAnim = 0;
|
||||
_iconState.x.finish();
|
||||
_iconState.selectionX.finish();
|
||||
_iconState.selectionWidth.finish();
|
||||
_iconState.animationStart = 0;
|
||||
_iconsAnimation.stop();
|
||||
const auto &last = iconInfo(_icons.size() - 1);
|
||||
_iconsMax = std::max(
|
||||
_iconState.max = std::max(
|
||||
last.left + last.width + _iconsRight - width(),
|
||||
0);
|
||||
if (_iconsX.current() > _iconsMax) {
|
||||
_iconsX = anim::value(_iconsMax, _iconsMax);
|
||||
if (_iconState.x.current() > _iconState.max) {
|
||||
_iconState.x = anim::value(_iconState.max, _iconState.max);
|
||||
}
|
||||
updateSelected();
|
||||
validateSelectedIcon(_activeByScrollId, animations);
|
||||
|
@ -1002,7 +1090,7 @@ void StickersListFooter::paintSetIcon(
|
|||
_iconsTop + (st::emojiFooterHeight - icon->height()) / 2,
|
||||
width());
|
||||
};
|
||||
if (_icons[info.index].setId == FirstEmojiSectionSetId()
|
||||
if (_icons[info.index].setId == AllEmojiSectionSetId()
|
||||
&& info.width > st::stickerIconWidth) {
|
||||
const auto skip = st::emojiIconSelectSkip;
|
||||
p.save();
|
||||
|
@ -1039,24 +1127,24 @@ bool StickersListFooter::iconsAnimationCallback(crl::time now) {
|
|||
if (anim::Disabled()) {
|
||||
now += st::stickerIconMove;
|
||||
}
|
||||
if (_iconsStartAnim) {
|
||||
const auto dt = (now - _iconsStartAnim)
|
||||
if (_iconState.animationStart) {
|
||||
const auto dt = (now - _iconState.animationStart)
|
||||
/ float64(st::stickerIconMove);
|
||||
if (dt >= 1.) {
|
||||
_iconsStartAnim = 0;
|
||||
_iconsX.finish();
|
||||
_iconSelX.finish();
|
||||
_iconSelWidth.finish();
|
||||
_iconState.animationStart = 0;
|
||||
_iconState.x.finish();
|
||||
_iconState.selectionX.finish();
|
||||
_iconState.selectionWidth.finish();
|
||||
} else {
|
||||
_iconsX.update(dt, anim::linear);
|
||||
_iconSelX.update(dt, anim::linear);
|
||||
_iconSelWidth.update(dt, anim::linear);
|
||||
_iconState.x.update(dt, anim::linear);
|
||||
_iconState.selectionX.update(dt, anim::linear);
|
||||
_iconState.selectionWidth.update(dt, anim::linear);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
return (_iconsStartAnim != 0);
|
||||
return (_iconState.animationStart != 0);
|
||||
}
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|
|
@ -42,7 +42,7 @@ enum class ValidateIconAnimations {
|
|||
|
||||
[[nodiscard]] uint64 EmojiSectionSetId(Ui::Emoji::Section section);
|
||||
[[nodiscard]] uint64 RecentEmojiSectionSetId();
|
||||
[[nodiscard]] uint64 FirstEmojiSectionSetId();
|
||||
[[nodiscard]] uint64 AllEmojiSectionSetId();
|
||||
[[nodiscard]] std::optional<Ui::Emoji::Section> SetIdEmojiSection(uint64 id);
|
||||
|
||||
struct StickerIcon {
|
||||
|
@ -134,16 +134,29 @@ private:
|
|||
int width = 0;
|
||||
bool visible = false;
|
||||
};
|
||||
struct ScrollState {
|
||||
int selected = 0;
|
||||
int max = 0;
|
||||
anim::value x;
|
||||
anim::value selectionX;
|
||||
anim::value selectionWidth;
|
||||
crl::time animationStart = 0;
|
||||
};
|
||||
|
||||
void enumerateVisibleIcons(Fn<void(const IconInfo &)> callback) const;
|
||||
void enumerateIcons(Fn<bool(const IconInfo &)> callback) const;
|
||||
void enumerateSubicons(Fn<bool(const IconInfo &)> callback) const;
|
||||
[[nodiscard]] IconInfo iconInfo(int index) const;
|
||||
[[nodiscard]] IconInfo subiconInfo(int index) const;
|
||||
|
||||
[[nodiscard]] std::shared_ptr<Lottie::FrameRenderer> getLottieRenderer();
|
||||
bool iconsAnimationCallback(crl::time now);
|
||||
void setSelectedIcon(
|
||||
int newSelected,
|
||||
ValidateIconAnimations animations);
|
||||
void setSelectedSubicon(
|
||||
int newSelected,
|
||||
ValidateIconAnimations animations);
|
||||
void validateIconLottieAnimation(const StickerIcon &icon);
|
||||
void validateIconWebmAnimation(const StickerIcon &icon);
|
||||
void validateIconAnimation(const StickerIcon &icon);
|
||||
|
@ -186,21 +199,22 @@ private:
|
|||
Fn<std::shared_ptr<Lottie::FrameRenderer>()> _renderer;
|
||||
uint64 _activeByScrollId = 0;
|
||||
OverState _iconOver = SpecialOver::None;
|
||||
int _iconSel = 0;
|
||||
OverState _iconDown = SpecialOver::None;
|
||||
bool _iconsDragging = false;
|
||||
Ui::Animations::Basic _iconsAnimation;
|
||||
|
||||
QPoint _iconsMousePos, _iconsMouseDown;
|
||||
mutable QImage _premiumIcon;
|
||||
int _iconsLeft = 0;
|
||||
int _iconsRight = 0;
|
||||
int _iconsTop = 0;
|
||||
|
||||
int _iconsStartX = 0;
|
||||
int _iconsMax = 0;
|
||||
anim::value _iconsX;
|
||||
anim::value _iconSelX;
|
||||
anim::value _iconSelWidth;
|
||||
crl::time _iconsStartAnim = 0;
|
||||
bool _iconsDragging = false;
|
||||
|
||||
ScrollState _iconState;
|
||||
Ui::Animations::Basic _iconsAnimation;
|
||||
|
||||
ScrollState _subiconState;
|
||||
Ui::Animations::Basic _subiconsAnimation;
|
||||
|
||||
Ui::RoundRect _selectionBg;
|
||||
Ui::Animations::Simple _emojiIconWidthAnimation;
|
||||
|
|
Loading…
Add table
Reference in a new issue