Improve the tabbed emoji panel design.

This commit is contained in:
John Preston 2023-01-23 22:56:25 +04:00
parent e73dbf5f65
commit 88e7f4b662
12 changed files with 222 additions and 99 deletions

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
using "ui/basic.style"; using "ui/basic.style";
using "boxes/boxes.style"; using "boxes/boxes.style";
using "ui/layers/layers.style";
using "ui/widgets/widgets.style"; using "ui/widgets/widgets.style";
TabbedSearch { TabbedSearch {
@ -42,6 +43,7 @@ EmojiPan {
iconArea: pixels; iconArea: pixels;
bg: color; bg: color;
overBg: color; overBg: color;
categoriesBg: color;
fadeLeft: icon; fadeLeft: icon;
fadeRight: icon; fadeRight: icon;
search: TabbedSearch; search: TabbedSearch;
@ -162,11 +164,10 @@ filtersRemove: IconButton(stickersRemove) {
emojiPanMargins: margins(10px, 10px, 10px, 10px); emojiPanMargins: margins(10px, 10px, 10px, 10px);
emojiTabs: SettingsSlider(defaultTabsSlider) { emojiTabs: SettingsSlider(defaultTabsSlider) {
height: 45px; height: 43px;
barTop: 42px; barTop: 40px;
labelTop: 13px; labelTop: 12px;
} }
emojiScroll: defaultSolidScroll;
emojiRecent: icon {{ "emoji/emoji_recent", emojiIconFg }}; emojiRecent: icon {{ "emoji/emoji_recent", emojiIconFg }};
emojiRecentActive: icon {{ "emoji/emoji_recent", emojiSubIconFgActive }}; emojiRecentActive: icon {{ "emoji/emoji_recent", emojiSubIconFgActive }};
emojiPeople: icon {{ "emoji/emoji_smile", emojiIconFg }}; emojiPeople: icon {{ "emoji/emoji_smile", emojiIconFg }};
@ -187,6 +188,7 @@ emojiSymbolsActive: icon {{ "emoji/emoji_love", emojiSubIconFgActive }};
emojiCategoryIconTop: 6px; emojiCategoryIconTop: 6px;
emojiPanAnimation: PanelAnimation(defaultPanelAnimation) { emojiPanAnimation: PanelAnimation(defaultPanelAnimation) {
fadeBg: emojiPanBg; fadeBg: emojiPanBg;
shadow: boxRoundShadow;
} }
emojiPanPadding: 12px; emojiPanPadding: 12px;
emojiPanWidth: 345px; emojiPanWidth: 345px;
@ -217,7 +219,7 @@ defaultTabbedSearch: TabbedSearch {
height: 33px; height: 33px;
icon: icon{{ "emoji/emoji_search_input", emojiIconFg }}; icon: icon{{ "emoji/emoji_search_input", emojiIconFg }};
iconOver: icon{{ "emoji/emoji_search_input", emojiIconFg }}; iconOver: icon{{ "emoji/emoji_search_input", emojiIconFg }};
iconPosition: point(12px, -1px); iconPosition: point(7px, -1px);
ripple: emptyRippleAnimation; ripple: emptyRippleAnimation;
} }
back: IconButton(defaultIconButton) { back: IconButton(defaultIconButton) {
@ -225,34 +227,35 @@ defaultTabbedSearch: TabbedSearch {
height: 33px; height: 33px;
icon: icon{{ "emoji/emoji_back", menuIconFg }}; icon: icon{{ "emoji/emoji_back", menuIconFg }};
iconOver: icon{{ "emoji/emoji_back", menuIconFg }}; iconOver: icon{{ "emoji/emoji_back", menuIconFg }};
iconPosition: point(12px, -1px); iconPosition: point(7px, -1px);
ripple: emptyRippleAnimation; ripple: emptyRippleAnimation;
} }
cancel: defaultMultiSelectSearchCancel; cancel: defaultMultiSelectSearchCancel;
defaultFieldWidth: 95px; defaultFieldWidth: 101px;
groupWidth: 30px; groupWidth: 30px;
height: 33px; height: 33px;
} }
defaultEmojiPan: EmojiPan { defaultEmojiPan: EmojiPan {
margin: margins(roundRadiusSmall, 0px, 14px, 0px); margin: margins(7px, 0px, 7px, 0px);
padding: margins(13px, 12px, 17px, 12px); padding: margins(7px, 0px, 4px, 7px);
desiredSize: 39px; desiredSize: 37px;
verticalSizeSub: 2px; verticalSizeSub: 1px;
header: 40px; header: 25px;
headerLeft: 23px; headerLeft: 14px;
headerLockLeft: 17px; headerLockLeft: 7px;
headerLockedLeft: 36px; headerLockedLeft: 26px;
headerTop: 12px; headerTop: 2px;
footer: 46px; footer: 36px;
iconSkip: 4px; iconSkip: 3px;
iconWidth: 35px; iconWidth: 30px;
iconArea: 32px; iconArea: 28px;
bg: emojiPanBg; bg: emojiPanBg;
overBg: emojiPanHover; overBg: emojiPanHover;
categoriesBg: emojiPanCategories;
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }}; fadeLeft: icon {{ "fade_horizontal-flip_horizontal", emojiPanCategories }};
fadeRight: icon {{ "fade_horizontal", emojiPanCategories }}; fadeRight: icon {{ "fade_horizontal", emojiPanCategories }};
search: defaultTabbedSearch; search: defaultTabbedSearch;
searchMargin: margins(6px, 10px, 6px, 10px); searchMargin: margins(1px, 11px, 2px, 5px);
} }
inlineResultsMinHeight: 278px; inlineResultsMinHeight: 278px;
@ -385,14 +388,8 @@ reactPanelEmojiPan: EmojiPan(defaultEmojiPan) {
padding: margins(reactStripSkip, 0px, reactStripSkip, reactStripSkip); padding: margins(reactStripSkip, 0px, reactStripSkip, reactStripSkip);
desiredSize: reactStripSize; desiredSize: reactStripSize;
verticalSizeSub: 0px; verticalSizeSub: 0px;
headerLeft: 13px;
headerLockLeft: 7px;
headerLockedLeft: 26px;
footer: 42px;
iconSkip: 6px;
iconWidth: 33px;
iconArea: 30px;
overBg: transparent; overBg: transparent;
categoriesBg: windowBg;
fadeLeft: icon {{ "fade_horizontal-flip_horizontal", windowBg }}; fadeLeft: icon {{ "fade_horizontal-flip_horizontal", windowBg }};
fadeRight: icon {{ "fade_horizontal", windowBg }}; fadeRight: icon {{ "fade_horizontal", windowBg }};
} }
@ -404,6 +401,7 @@ reactPanelScroll: ScrollArea(defaultSolidScroll) {
deltax: 2px; deltax: 2px;
hiding: 0; hiding: 0;
} }
emojiScroll: reactPanelScroll;
emojiSuggestionsFadeLeft: icon {{ "fade_horizontal-flip_horizontal", boxBg }}; emojiSuggestionsFadeLeft: icon {{ "fade_horizontal-flip_horizontal", boxBg }};
emojiSuggestionsFadeRight: icon {{ "fade_horizontal", boxBg }}; emojiSuggestionsFadeRight: icon {{ "fade_horizontal", boxBg }};

View file

@ -177,7 +177,7 @@ void EmojiColorPicker::paintEvent(QPaintEvent *e) {
p.drawPixmap(0, 0, _cache); p.drawPixmap(0, 0, _cache);
return; return;
} }
Ui::Shadow::paint(p, inner, width(), st::defaultRoundShadow); Ui::Shadow::paint(p, inner, width(), st::emojiPanAnimation.shadow);
Ui::FillRoundRect(p, inner, st::boxBg, Ui::BoxCorners); Ui::FillRoundRect(p, inner, st::boxBg, Ui::BoxCorners);
auto x = st::emojiPanMargins.left() + 2 * st::emojiColorsPadding + _singleSize.width(); auto x = st::emojiPanMargins.left() + 2 * st::emojiColorsPadding + _singleSize.width();
@ -414,6 +414,9 @@ EmojiListWidget::EmojiListWidget(
_customSingleSize = Data::FrameSizeFromTag( _customSingleSize = Data::FrameSizeFromTag(
Data::CustomEmojiManager::SizeTag::Large Data::CustomEmojiManager::SizeTag::Large
) / style::DevicePixelRatio(); ) / style::DevicePixelRatio();
_customSetIconSize = Data::FrameSizeFromTag(
Data::CustomEmojiManager::SizeTag::SetIcon
) / style::DevicePixelRatio();
_picker->hide(); _picker->hide();
@ -755,7 +758,7 @@ bool EmojiListWidget::enumerateSections(Callback callback) const {
+ (i == 0 ? _rowsTop : st().header); + (i == 0 ? _rowsTop : st().header);
info.rowsBottom = info.rowsTop info.rowsBottom = info.rowsTop
+ (info.rowsCount * _singleSize.height()) + (info.rowsCount * _singleSize.height())
+ st::roundRadiusSmall; + st::emojiPanRadius;
if (!callback(info)) { if (!callback(info)) {
return false; return false;
} }
@ -1485,9 +1488,9 @@ void EmojiListWidget::showPicker() {
_picker->showEmoji(emoji); _picker->showEmoji(emoji);
auto y = emojiRect(over->section, over->index).y(); auto y = emojiRect(over->section, over->index).y();
y -= _picker->height() - st::roundRadiusSmall + getVisibleTop(); y -= _picker->height() - st::emojiPanRadius + getVisibleTop();
if (y < st().header) { if (y < st().header) {
y += _picker->height() - st::roundRadiusSmall + _singleSize.height() - st::roundRadiusSmall; y += _picker->height() - st::emojiPanRadius + _singleSize.height() - st::emojiPanRadius;
} }
auto xmax = width() - _picker->width(); auto xmax = width() - _picker->width();
auto coef = float64(over->index % _columnCount) / float64(_columnCount - 1); auto coef = float64(over->index % _columnCount) / float64(_columnCount - 1);
@ -1935,7 +1938,7 @@ std::vector<StickerIcon> EmojiListWidget::fillIcons() {
} else { } else {
result.emplace_back(AllEmojiSectionSetId()); result.emplace_back(AllEmojiSectionSetId());
} }
const auto esize = _customSingleSize; const auto esize = _customSetIconSize;
for (const auto &custom : _custom) { for (const auto &custom : _custom) {
const auto set = custom.set; const auto set = custom.set;
result.emplace_back(set, custom.thumbnailDocument, esize, esize); result.emplace_back(set, custom.thumbnailDocument, esize, esize);

View file

@ -359,6 +359,7 @@ private:
DocumentId, DocumentId,
std::unique_ptr<Ui::Text::CustomEmoji>> _customRecent; std::unique_ptr<Ui::Text::CustomEmoji>> _customRecent;
int _customSingleSize = 0; int _customSingleSize = 0;
int _customSetIconSize = 0;
bool _allowWithoutPremium = false; bool _allowWithoutPremium = false;
Ui::RoundRect _overBg; Ui::RoundRect _overBg;

View file

@ -19,6 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "ui/dpr/dpr_icon.h"
#include "ui/dpr/dpr_image.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/painter.h" #include "ui/painter.h"
@ -197,7 +199,7 @@ StickersListFooter::StickersListFooter(Descriptor &&descriptor)
, _settingsButtonVisible(descriptor.settingsButtonVisible) , _settingsButtonVisible(descriptor.settingsButtonVisible)
, _iconState([=] { update(); }) , _iconState([=] { update(); })
, _subiconState([=] { update(); }) , _subiconState([=] { update(); })
, _selectionBg(st::roundRadiusLarge, st::windowBgRipple) , _selectionBg(st::emojiPanRadius, st::windowBgRipple)
, _subselectionBg(st().iconArea / 2, st::windowBgRipple) , _subselectionBg(st().iconArea / 2, st::windowBgRipple)
, _barSelection(descriptor.barSelection) { , _barSelection(descriptor.barSelection) {
setMouseTracking(true); setMouseTracking(true);
@ -603,6 +605,13 @@ void StickersListFooter::paint(
paintSelectionBg(p, context); paintSelectionBg(p, context);
} }
const auto iconCacheSize = QSize(_singleWidth, st().footer);
const auto full = iconCacheSize * style::DevicePixelRatio();
if (_setIconCache.size() != full) {
_setIconCache = QImage(full, QImage::Format_ARGB32_Premultiplied);
_setIconCache.setDevicePixelRatio(style::DevicePixelRatio());
}
const auto now = crl::now(); const auto now = crl::now();
const auto paused = _paused(); const auto paused = _paused();
p.setPen(st::windowFg); p.setPen(st::windowFg);
@ -683,11 +692,20 @@ void StickersListFooter::paintLeftRightFading(
? (1. - context.progress * (1. - o_left_normal)) ? (1. - context.progress * (1. - o_left_normal))
: o_left_normal; : o_left_normal;
const auto radiusSkip = context.expanding const auto radiusSkip = context.expanding
? std::max(context.radius - st::roundRadiusSmall, 0) ? std::max(context.radius - st::emojiPanRadius, 0)
: 0; : 0;
if (o_left > 0) { if (o_left > 0) {
p.setOpacity(o_left); p.setOpacity(o_left);
st().fadeLeft.fill(p, style::rtlrect(std::max(_iconsLeft, radiusSkip), _iconsTop, st().fadeLeft.width(), st().footer, width())); const auto left = std::max(_iconsLeft, radiusSkip);
const auto top = _iconsTop;
if (left >= st::emojiPanRadius) {
st().fadeLeft.fill(
p,
QRect(left, top, st().fadeLeft.width(), st().footer));
} else {
validateFadeLeft(left + st().fadeLeft.width());
p.drawImage(0, _iconsTop, _fadeLeftCache);
}
p.setOpacity(1.); p.setOpacity(1.);
} }
const auto o_right_normal = std::clamp( const auto o_right_normal = std::clamp(
@ -699,17 +717,78 @@ void StickersListFooter::paintLeftRightFading(
: o_right_normal; : o_right_normal;
if (o_right > 0) { if (o_right > 0) {
p.setOpacity(o_right); p.setOpacity(o_right);
st().fadeRight.fill( const auto right = std::max(_iconsRight, radiusSkip);
p, const auto rightWidth = right + st().fadeRight.width();
style::rtlrect( if (right >= st::emojiPanRadius) {
width() - std::max(_iconsRight, radiusSkip) - st().fadeRight.width(), st().fadeRight.fill(
_iconsTop, p,
st().fadeRight.width(), QRect(
st().footer, width())); width() - rightWidth,
_iconsTop,
st().fadeRight.width(),
st().footer));
} else {
validateFadeRight(rightWidth);
p.drawImage(width() - rightWidth, _iconsTop, _fadeRightCache);
}
p.setOpacity(1.); p.setOpacity(1.);
} }
} }
void StickersListFooter::validateFadeLeft(int leftWidth) const {
validateFadeMask();
const auto ratio = devicePixelRatioF();
const auto &color = st().categoriesBg->c;
dpr::Validate(_fadeLeftCache, ratio, { leftWidth, st().footer }, [&](
QPainter &p,
QSize size) {
_fadeLeftColor = color;
const auto frame = dpr::IconFrame(st().fadeLeft, color, ratio);
p.drawImage(
QRect(
size.width() - frame.width(),
0,
frame.width(),
size.height()),
frame);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.drawImage(0, 0, _fadeMask);
}, (_fadeLeftColor != color), Qt::transparent);
}
void StickersListFooter::validateFadeRight(int rightWidth) const {
validateFadeMask();
const auto ratio = devicePixelRatioF();
const auto &color = st().categoriesBg->c;
dpr::Validate(_fadeRightCache, ratio, { rightWidth, st().footer }, [&](
QPainter &p,
QSize size) {
_fadeRightColor = color;
const auto frame = dpr::IconFrame(st().fadeRight, color, ratio);
p.drawImage(QRect(0, 0, frame.width(), size.height()), frame);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.drawImage(size.width() - _fadeMask.width(), 0, _fadeMask);
}, (_fadeRightColor != color), Qt::transparent);
}
void StickersListFooter::validateFadeMask() const {
const auto ratio = devicePixelRatioF();
const auto width = st().fadeLeft.width()
+ st().fadeRight.width()
+ 2 * st::emojiPanRadius;
dpr::Validate(_fadeMask, ratio, { width, st().footer }, [&](
QPainter &p,
QSize size) {
const auto radius = st::emojiPanRadius * ratio;
p.setBrush(Qt::white);
p.setPen(Qt::NoPen);
auto hq = PainterHighQualityEnabler(p);
p.drawRoundedRect(QRect(QPoint(), size), radius, radius);
}, false, Qt::transparent, false);
}
void StickersListFooter::resizeEvent(QResizeEvent *e) { void StickersListFooter::resizeEvent(QResizeEvent *e) {
if (_searchField) { if (_searchField) {
resizeSearchControls(); resizeSearchControls();
@ -1073,7 +1152,7 @@ void StickersListFooter::refreshSubiconsGeometry() {
const auto half = _singleWidth / 2; const auto half = _singleWidth / 2;
const auto count = int(Section::Symbols) - int(Section::Recent); const auto count = int(Section::Symbols) - int(Section::Recent);
const auto widthMax = count * _singleWidth; const auto widthMax = count * _singleWidth;
const auto widthMin = 4 * _singleWidth + half; const auto widthMin = 5 * _singleWidth + half;
const auto collapsedWidth = int(_icons.size()) * _singleWidth; const auto collapsedWidth = int(_icons.size()) * _singleWidth;
_subiconsWidth = std::clamp( _subiconsWidth = std::clamp(
width() + _singleWidth - collapsedWidth, width() + _singleWidth - collapsedWidth,
@ -1169,7 +1248,7 @@ void StickersListFooter::validateIconAnimation(
const auto emoji = icon.sticker; const auto emoji = icon.sticker;
if (emoji && emoji->sticker()->setType == Data::StickersType::Emoji) { if (emoji && emoji->sticker()->setType == Data::StickersType::Emoji) {
if (!icon.custom) { if (!icon.custom) {
const auto tag = Data::CustomEmojiManager::SizeTag::Large; const auto tag = Data::CustomEmojiManager::SizeTag::SetIcon;
auto &manager = emoji->owner().customEmojiManager(); auto &manager = emoji->owner().customEmojiManager();
icon.custom = manager.create( icon.custom = manager.create(
emoji->id, emoji->id,
@ -1224,6 +1303,47 @@ void StickersListFooter::paintSetIcon(
p.translate(-center); p.translate(-center);
} }
} }
prepareSetIcon(context, info, now, paused);
p.drawImage(info.adjustedLeft, _iconsTop, _setIconCache);
if (context.expanding) {
if (icon.custom) {
p.translate(-expandingShift);
} else {
p.restore();
}
}
}
void StickersListFooter::prepareSetIcon(
const ExpandingContext &context,
const IconInfo &info,
crl::time now,
bool paused) const {
_setIconCache.fill(Qt::transparent);
auto p = Painter(&_setIconCache);
paintSetIconToCache(p, context, info, now, paused);
if (!_icons[info.index].sticker) {
return;
}
// Rounding the corners.
auto hq = PainterHighQualityEnabler(p);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.setBrush(Qt::NoBrush);
auto pen = QPen(Qt::transparent);
pen.setWidth(style::ConvertScaleExact(4.));
p.setPen(pen);
const auto area = st().iconArea;
auto rect = QRect(_areaPosition, QSize(area, area));
p.drawRoundedRect(rect, st::emojiPanRadius, st::emojiPanRadius);
}
void StickersListFooter::paintSetIconToCache(
Painter &p,
const ExpandingContext &context,
const IconInfo &info,
crl::time now,
bool paused) const {
const auto &icon = _icons[info.index];
if (icon.sticker) { if (icon.sticker) {
const auto origin = icon.sticker->stickerSetOrigin(); const auto origin = icon.sticker->stickerSetOrigin();
const auto thumb = icon.thumbnailMedia const auto thumb = icon.thumbnailMedia
@ -1231,8 +1351,8 @@ void StickersListFooter::paintSetIcon(
: icon.stickerMedia : icon.stickerMedia
? icon.stickerMedia->thumbnail() ? icon.stickerMedia->thumbnail()
: nullptr; : nullptr;
const auto x = info.adjustedLeft + (_singleWidth - icon.pixw) / 2; const auto x = (_singleWidth - icon.pixw) / 2;
const auto y = _iconsTop + (st().footer - icon.pixh) / 2; const auto y = (st().footer - icon.pixh) / 2;
if (icon.custom) { if (icon.custom) {
icon.custom->paint(p, Ui::Text::CustomEmoji::Context{ icon.custom->paint(p, Ui::Text::CustomEmoji::Context{
.textColor = st::windowFg->c, .textColor = st::windowFg->c,
@ -1252,8 +1372,8 @@ void StickersListFooter::paintSetIcon(
} }
p.drawImage( p.drawImage(
QRect( QRect(
(info.adjustedLeft + (_singleWidth - size.width()) / 2), (_singleWidth - size.width()) / 2,
_iconsTop + (st().footer - size.height()) / 2, (st().footer - size.height()) / 2,
size.width(), size.width(),
size.height()), size.height()),
frame); frame);
@ -1287,15 +1407,15 @@ void StickersListFooter::paintSetIcon(
icon.megagroup->paintUserpicLeft( icon.megagroup->paintUserpicLeft(
p, p,
icon.megagroupUserpic, icon.megagroupUserpic,
info.adjustedLeft + (_singleWidth - size) / 2, (_singleWidth - size) / 2,
_iconsTop + (st().footer - size) / 2, (st().footer - size) / 2,
width(), width(),
st::stickerGroupCategorySize); st::stickerGroupCategorySize);
} else if (icon.setId == Data::Stickers::PremiumSetId) { } else if (icon.setId == Data::Stickers::PremiumSetId) {
const auto size = st::emojiStatusDefault.size(); const auto size = st::emojiStatusDefault.size();
p.drawImage( p.drawImage(
info.adjustedLeft + (_singleWidth - size.width()) / 2, (_singleWidth - size.width()) / 2,
_iconsTop + (st().footer - size.height()) / 2, (st().footer - size.height()) / 2,
_premiumIcon.image()); _premiumIcon.image());
} else { } else {
using Section = Ui::Emoji::Section; using Section = Ui::Emoji::Section;
@ -1323,12 +1443,11 @@ void StickersListFooter::paintSetIcon(
Assert(index >= 0 && index < icons.size()); Assert(index >= 0 && index < icons.size());
return icons[index]; return icons[index];
}; };
const auto left = info.adjustedLeft;
const auto paintOne = [&](int left, const style::icon *icon) { const auto paintOne = [&](int left, const style::icon *icon) {
icon->paint( icon->paint(
p, p,
left + (_singleWidth - icon->width()) / 2, left + (_singleWidth - icon->width()) / 2,
_iconsTop + (st().footer - icon->height()) / 2, (st().footer - icon->height()) / 2,
width()); width());
}; };
if (_icons[info.index].setId == AllEmojiSectionSetId() if (_icons[info.index].setId == AllEmojiSectionSetId()
@ -1336,7 +1455,7 @@ void StickersListFooter::paintSetIcon(
const auto skip = st::emojiIconSelectSkip; const auto skip = st::emojiIconSelectSkip;
p.save(); p.save();
p.setClipRect( p.setClipRect(
left + skip, skip,
_iconsTop, _iconsTop,
info.width - 2 * skip, info.width - 2 * skip,
st().footer, st().footer,
@ -1344,7 +1463,7 @@ void StickersListFooter::paintSetIcon(
enumerateSubicons([&](const IconInfo &info) { enumerateSubicons([&](const IconInfo &info) {
if (info.visible) { if (info.visible) {
paintOne( paintOne(
left + info.adjustedLeft, info.adjustedLeft,
sectionIcon( sectionIcon(
Section(int(Section::People) + info.index), Section(int(Section::People) + info.index),
(_subiconState.selected == info.index))); (_subiconState.selected == info.index)));
@ -1353,7 +1472,7 @@ void StickersListFooter::paintSetIcon(
}); });
p.restore(); p.restore();
} else { } else {
paintOne(left, [&] { paintOne(0, [&] {
if (icon.setId == Data::Stickers::FeaturedSetId) { if (icon.setId == Data::Stickers::FeaturedSetId) {
const auto &stickers = _session->data().stickers(); const auto &stickers = _session->data().stickers();
return stickers.featuredSetsUnreadCount() return stickers.featuredSetsUnreadCount()
@ -1370,13 +1489,6 @@ void StickersListFooter::paintSetIcon(
}()); }());
} }
} }
if (context.expanding) {
if (icon.custom) {
p.translate(-expandingShift);
} else {
p.restore();
}
}
} }
LocalStickersManager::LocalStickersManager(not_null<Main::Session*> session) LocalStickersManager::LocalStickersManager(not_null<Main::Session*> session)

View file

@ -10,6 +10,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 "mtproto/sender.h" #include "mtproto/sender.h"
#include "ui/dpr/dpr_image.h"
#include "ui/round_rect.h" #include "ui/round_rect.h"
#include "ui/userpic_view.h" #include "ui/userpic_view.h"
@ -232,6 +233,17 @@ private:
const IconInfo &info, const IconInfo &info,
crl::time now, crl::time now,
bool paused) const; bool paused) const;
void prepareSetIcon(
const ExpandingContext &context,
const IconInfo &info,
crl::time now,
bool paused) const;
void paintSetIconToCache(
Painter &p,
const ExpandingContext &context,
const IconInfo &info,
crl::time now,
bool paused) const;
void paintSelectionBg( void paintSelectionBg(
QPainter &p, QPainter &p,
const ExpandingContext &context) const; const ExpandingContext &context) const;
@ -248,6 +260,10 @@ private:
void resizeSearchControls(); void resizeSearchControls();
void scrollByWheelEvent(not_null<QWheelEvent*> e); void scrollByWheelEvent(not_null<QWheelEvent*> e);
void validateFadeLeft(int leftWidth) const;
void validateFadeRight(int rightWidth) const;
void validateFadeMask() const;
void clipCallback(Media::Clip::Notification notification, uint64 setId); void clipCallback(Media::Clip::Notification notification, uint64 setId);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
@ -271,6 +287,13 @@ private:
int _singleWidth = 0; int _singleWidth = 0;
QPoint _areaPosition; QPoint _areaPosition;
mutable QImage _fadeLeftCache;
mutable QColor _fadeLeftColor;
mutable QImage _fadeRightCache;
mutable QColor _fadeRightColor;
mutable QImage _fadeMask;
mutable QImage _setIconCache;
ScrollState _iconState; ScrollState _iconState;
ScrollState _subiconState; ScrollState _subiconState;

View file

@ -62,7 +62,7 @@ TabbedPanel::TabbedPanel(
Expects(_selector != nullptr); Expects(_selector != nullptr);
_selector->setParent(this); _selector->setParent(this);
_selector->setRoundRadius(st::roundRadiusSmall); _selector->setRoundRadius(st::emojiPanRadius);
_selector->setAfterShownCallback([=](SelectorTab tab) { _selector->setAfterShownCallback([=](SelectorTab tab) {
_controller->enableGifPauseReason(_selector->level()); _controller->enableGifPauseReason(_selector->level());
}); });
@ -347,7 +347,7 @@ void TabbedPanel::startShowAnimation() {
_showAnimation = std::make_unique<Ui::PanelAnimation>(st::emojiPanAnimation, _dropDown ? Ui::PanelAnimation::Origin::TopRight : Ui::PanelAnimation::Origin::BottomRight); _showAnimation = std::make_unique<Ui::PanelAnimation>(st::emojiPanAnimation, _dropDown ? Ui::PanelAnimation::Origin::TopRight : Ui::PanelAnimation::Origin::BottomRight);
auto inner = rect().marginsRemoved(st::emojiPanMargins); auto inner = rect().marginsRemoved(st::emojiPanMargins);
_showAnimation->setFinalImage(std::move(image), QRect(inner.topLeft() * cIntRetinaFactor(), inner.size() * cIntRetinaFactor())); _showAnimation->setFinalImage(std::move(image), QRect(inner.topLeft() * cIntRetinaFactor(), inner.size() * cIntRetinaFactor()));
_showAnimation->setCornerMasks(Images::CornersMask(ImageRoundRadius::Small)); _showAnimation->setCornerMasks(Images::CornersMask(st::emojiPanRadius));
_showAnimation->start(); _showAnimation->start();
} }
hideChildren(); hideChildren();
@ -471,8 +471,9 @@ bool TabbedPanel::overlaps(const QRect &globalRect) const {
auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()); auto testRect = QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size());
auto inner = rect().marginsRemoved(st::emojiPanMargins); auto inner = rect().marginsRemoved(st::emojiPanMargins);
return inner.marginsRemoved(QMargins(st::roundRadiusSmall, 0, st::roundRadiusSmall, 0)).contains(testRect) const auto radius = st::emojiPanRadius;
|| inner.marginsRemoved(QMargins(0, st::roundRadiusSmall, 0, st::roundRadiusSmall)).contains(testRect); return inner.marginsRemoved(QMargins(radius, 0, radius, 0)).contains(testRect)
|| inner.marginsRemoved(QMargins(0, radius, 0, radius)).contains(testRect);
} }
TabbedPanel::~TabbedPanel() { TabbedPanel::~TabbedPanel() {

View file

@ -298,12 +298,9 @@ TabbedSelector::TabbedSelector(
, _controller(controller) , _controller(controller)
, _level(level) , _level(level)
, _mode(mode) , _mode(mode)
, _panelRounding(Ui::PrepareCornerPixmaps( , _panelRounding(Ui::PrepareCornerPixmaps(st::emojiPanRadius, _st.bg))
ImageRoundRadius::Small, , _categoriesRounding(
st::emojiPanBg)) Ui::PrepareCornerPixmaps(st::emojiPanRadius, _st.categoriesBg))
, _categoriesRounding(Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small,
st::emojiPanCategories))
, _topShadow(full() ? object_ptr<Ui::PlainShadow>(this) : nullptr) , _topShadow(full() ? object_ptr<Ui::PlainShadow>(this) : nullptr)
, _bottomShadow(this) , _bottomShadow(this)
, _scroll(this, st::emojiScroll) , _scroll(this, st::emojiScroll)
@ -421,10 +418,10 @@ TabbedSelector::TabbedSelector(
style::PaletteChanged( style::PaletteChanged(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
_panelRounding = Ui::PrepareCornerPixmaps( _panelRounding = Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small, st::emojiPanRadius,
st::emojiPanBg); st::emojiPanBg);
_categoriesRounding = Ui::PrepareCornerPixmaps( _categoriesRounding = Ui::PrepareCornerPixmaps(
ImageRoundRadius::Small, st::emojiPanRadius,
st::emojiPanCategories); st::emojiPanCategories);
}, lifetime()); }, lifetime());
@ -586,13 +583,13 @@ void TabbedSelector::resizeEvent(QResizeEvent *e) {
} }
void TabbedSelector::updateScrollGeometry(QSize oldSize) { void TabbedSelector::updateScrollGeometry(QSize oldSize) {
auto scrollWidth = width() - st::roundRadiusSmall; auto scrollWidth = width() - st::emojiPanRadius;
auto scrollHeight = height() - scrollTop() - scrollBottom(); auto scrollHeight = height() - scrollTop() - scrollBottom();
auto inner = currentTab()->widget(); auto inner = currentTab()->widget();
auto innerWidth = scrollWidth - st::emojiScroll.width; auto innerWidth = scrollWidth - st::emojiScroll.width;
auto setScrollGeometry = [&] { auto setScrollGeometry = [&] {
_scroll->setGeometryToLeft( _scroll->setGeometryToLeft(
st::roundRadiusSmall, st::emojiPanRadius,
scrollTop(), scrollTop(),
scrollWidth, scrollWidth,
scrollHeight); scrollHeight);
@ -722,7 +719,7 @@ void TabbedSelector::paintContent(QPainter &p) {
sidesHeight), sidesHeight),
st::emojiPanBg); st::emojiPanBg);
p.fillRect( p.fillRect(
myrtlrect(0, sidesTop, st::roundRadiusSmall, sidesHeight), myrtlrect(0, sidesTop, st::emojiPanRadius, sidesHeight),
st::emojiPanBg); st::emojiPanBg);
} }
} }
@ -1083,7 +1080,7 @@ void TabbedSelector::switchTab() {
slidingRect, slidingRect,
wasSectionIcons); wasSectionIcons);
_slideAnimation->setCornerMasks( _slideAnimation->setCornerMasks(
Images::CornersMask(ImageRoundRadius::Small)); Images::CornersMask(st::emojiPanRadius));
_slideAnimation->start(); _slideAnimation->start();
hideForSliding(); hideForSliding();

View file

@ -63,6 +63,7 @@ private:
case SizeTag::Normal: return LottieSize::EmojiInteraction; case SizeTag::Normal: return LottieSize::EmojiInteraction;
case SizeTag::Large: return LottieSize::EmojiInteractionReserved1; case SizeTag::Large: return LottieSize::EmojiInteractionReserved1;
case SizeTag::Isolated: return LottieSize::EmojiInteractionReserved2; case SizeTag::Isolated: return LottieSize::EmojiInteractionReserved2;
case SizeTag::SetIcon: return LottieSize::EmojiInteractionReserved3;
} }
Unexpected("SizeTag value in CustomEmojiManager-LottieSizeFromTag."); Unexpected("SizeTag value in CustomEmojiManager-LottieSizeFromTag.");
} }
@ -74,6 +75,9 @@ private:
case SizeTag::Isolated: case SizeTag::Isolated:
return (st::largeEmojiSize + 2 * st::largeEmojiOutline) return (st::largeEmojiSize + 2 * st::largeEmojiOutline)
* style::DevicePixelRatio(); * style::DevicePixelRatio();
case SizeTag::SetIcon:
return int(style::ConvertScale(18 * 7 / 6., style::Scale()))
* style::DevicePixelRatio();
} }
Unexpected("SizeTag value in CustomEmojiManager-SizeFromTag."); Unexpected("SizeTag value in CustomEmojiManager-SizeFromTag.");
} }

View file

@ -25,6 +25,7 @@ enum class CustomEmojiSizeTag : uchar {
Normal, Normal,
Large, Large,
Isolated, Isolated,
SetIcon,
kCount, kCount,
}; };

View file

@ -493,21 +493,6 @@ bool MainWindow::initGeometryFromSystem() {
return true; return true;
} }
QRect MainWindow::computeDesktopRect() const {
const auto flags = MONITOR_DEFAULTTONEAREST;
if (const auto monitor = MonitorFromWindow(psHwnd(), flags)) {
MONITORINFOEX info;
info.cbSize = sizeof(info);
GetMonitorInfo(monitor, &info);
return QRect(
info.rcWork.left,
info.rcWork.top,
info.rcWork.right - info.rcWork.left,
info.rcWork.bottom - info.rcWork.top);
}
return Window::MainWindow::computeDesktopRect();
}
void MainWindow::updateWindowIcon() { void MainWindow::updateWindowIcon() {
updateTaskbarAndIconCounters(); updateTaskbarAndIconCounters();
} }

View file

@ -48,8 +48,6 @@ protected:
bool initGeometryFromSystem() override; bool initGeometryFromSystem() override;
QRect computeDesktopRect() const override;
private: private:
struct Private; struct Private;

@ -1 +1 @@
Subproject commit 77cd7f642c13ce215ff7bc4764670e9149202b06 Subproject commit 9cb928b7c41f0f1eb36a4d26ce31d053ea12466d