diff --git a/Telegram/Resources/icons/emoji/emoji_travel.png b/Telegram/Resources/icons/emoji/emoji_travel.png index 0a7bec1a4..315acc6f1 100644 Binary files a/Telegram/Resources/icons/emoji/emoji_travel.png and b/Telegram/Resources/icons/emoji/emoji_travel.png differ diff --git a/Telegram/Resources/icons/emoji/emoji_travel@2x.png b/Telegram/Resources/icons/emoji/emoji_travel@2x.png index 3aa82ef42..e644cbf97 100644 Binary files a/Telegram/Resources/icons/emoji/emoji_travel@2x.png and b/Telegram/Resources/icons/emoji/emoji_travel@2x.png differ diff --git a/Telegram/Resources/icons/emoji/emoji_travel@3x.png b/Telegram/Resources/icons/emoji/emoji_travel@3x.png index 708d71324..0d6e1babb 100644 Binary files a/Telegram/Resources/icons/emoji/emoji_travel@3x.png and b/Telegram/Resources/icons/emoji/emoji_travel@3x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 380316b62..f486b1adf 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1791,6 +1791,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_switch_gifs" = "GIFs"; "lng_switch_masks" = "Masks"; "lng_stickers_featured_add" = "Add"; +"lng_emoji_featured_unlock" = "Unlock"; +"lng_emoji_premium_restore" = "Restore"; "lng_gifs_search" = "Search GIFs"; "lng_gifs_no_saved" = "You have no saved GIFs yet."; @@ -1825,6 +1827,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_custom_emoji_count#other" = "{count} emoji"; "lng_stickers_attached_sets" = "Sets of attached stickers"; "lng_custom_emoji_used_sets" = "Sets of used emoji"; +"lng_custom_emoji_remove_pack_button" = "Remove Emoji"; "lng_stickers_group_set" = "Group sticker set"; "lng_stickers_remove_group_set" = "Remove group sticker set?"; "lng_stickers_group_from_your" = "Choose from your stickers"; @@ -1833,8 +1836,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_stickers_nothing_found" = "No stickers found"; "lng_stickers_remove_pack_confirm" = "Remove"; "lng_stickers_archive_pack" = "Archive Stickers"; +"lng_stickers_remove_pack_button" = "Remove Stickers"; "lng_stickers_has_been_archived" = "Sticker pack has been archived."; "lng_masks_archive_pack" = "Archive Masks"; +"lng_masks_remove_pack_button" = "Remove Masks"; "lng_masks_has_been_archived" = "Mask pack has been archived."; "lng_masks_installed" = "Mask pack has been installed."; diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style index 7f63b31b2..fd9317e39 100644 --- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style +++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style @@ -159,15 +159,22 @@ emojiPanShowDuration: 200; emojiPanDuration: 200; emojiPanHover: windowBgOver; emojiPanSlideDuration: 200; -emojiPanDesiredSize: 45px; +emojiPanDesiredSize: 39px; +emojiPanArea: size(34px, 32px); +emojiPanLeft: 13px; +emojiPanRight: 17px; +emojiPanRadius: 8px; inlineResultsMinHeight: 278px; inlineResultsMaxHeight: 640px; -emojiPanHeader: 42px; +emojiPanHeader: 40px; emojiPanHeaderFont: semiboldFont; -emojiPanHeaderLeft: 22px; +emojiPanHeaderLeft: 23px; +emojiPanHeaderLockLeft: 17px; +emojiPanHeaderLockedLeft: 36px; emojiPanHeaderTop: 12px; +emojiPanRemoveSkip: 10px; emojiColorsPadding: 5px; emojiColorsSep: 1px; diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index b77605192..e99e0b0e6 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -84,6 +84,8 @@ private: int _pressedSel = -1; QPoint _lastMousePos; QSize _singleSize; + QPoint _areaPosition; + QPoint _innerPosition; bool _hiding = false; QPixmap _cache; @@ -224,7 +226,15 @@ void EmojiColorPicker::handleMouseRelease(QPoint globalPos) { } void EmojiColorPicker::setSingleSize(QSize size) { + const auto area = st::emojiPanArea; _singleSize = size; + _areaPosition = QPoint( + (_singleSize.width() - area.width()) / 2, + (_singleSize.height() - area.height()) / 2); + const auto esize = Ui::Emoji::GetSizeLarge() / style::DevicePixelRatio(); + _innerPosition = QPoint( + (area.width() - esize) / 2, + (area.height() - esize) / 2); updateSize(); } @@ -342,19 +352,33 @@ void EmojiColorPicker::setSelected(int newSelected) { } void EmojiColorPicker::drawVariant(Painter &p, int variant) { - QPoint w(st::emojiPanMargins.left() + st::emojiColorsPadding + variant * _singleSize.width() + (variant ? 2 * st::emojiColorsPadding + st::emojiColorsSep : 0), st::emojiPanMargins.top() + st::emojiColorsPadding); + const auto w = QPoint( + st::emojiPanMargins.left(), + st::emojiPanMargins.top() + ) + QPoint( + (st::emojiColorsPadding + + variant * _singleSize.width() + + (variant + ? (2 * st::emojiColorsPadding + st::emojiColorsSep) + : 0)), + st::emojiColorsPadding + ) + _areaPosition; if (variant == _selected) { QPoint tl(w); - if (rtl()) tl.setX(width() - tl.x() - _singleSize.width()); - Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners); + if (rtl()) tl.setX(width() - tl.x() - st::emojiPanArea.width()); + + Ui::FillRoundRect( + p, + QRect(tl, st::emojiPanArea), + st::emojiPanHover, + Ui::EmojiHoverCorners); } - const auto esize = Ui::Emoji::GetSizeLarge(); Ui::Emoji::Draw( p, _variants[variant], - esize, - w.x() + (_singleSize.width() - (esize / cIntRetinaFactor())) / 2, - w.y() + (_singleSize.height() - (esize / cIntRetinaFactor())) / 2); + Ui::Emoji::GetSizeLarge(), + w.x() + _innerPosition.x(), + w.y() + _innerPosition.y()); } EmojiListWidget::EmojiListWidget( @@ -369,8 +393,6 @@ EmojiListWidget::EmojiListWidget( _picker->hide(); - _esize = Ui::Emoji::GetSizeLarge(); - for (auto i = 1; i != kEmojiSectionCount; ++i) { const auto section = static_cast
(i); _counts[i] = Ui::Emoji::GetSectionCount(section); @@ -563,13 +585,10 @@ bool EmojiListWidget::enumerateSections(Callback callback) const { const auto premiumMayBeBought = !session->premium() && session->premiumPossible(); const auto next = [&] { - const auto shift = (info.premiumRequired ? st::emojiPanPadding : 0); info.rowsCount = (info.count + _columnCount - 1) / _columnCount; info.rowsTop = info.top - + (i == 0 ? st::emojiPanPadding : st::emojiPanHeader) - - shift; + + (i == 0 ? st::emojiPanPadding : st::emojiPanHeader); info.rowsBottom = info.rowsTop - + shift + (info.rowsCount * _singleSize.height()) + st::roundRadiusSmall; if (!callback(info)) { @@ -628,21 +647,32 @@ int EmojiListWidget::sectionsCount() const { return kEmojiSectionCount + int(_custom.size()); } +void EmojiListWidget::setSingleSize(QSize size) { + const auto area = st::emojiPanArea; + _singleSize = size; + _areaPosition = QPoint( + (_singleSize.width() - area.width()) / 2, + (_singleSize.height() - area.height()) / 2); + const auto esize = Ui::Emoji::GetSizeLarge() / style::DevicePixelRatio(); + _innerPosition = QPoint( + (area.width() - esize) / 2, + (area.height() - esize) / 2); + _picker->setSingleSize(_singleSize); +} + int EmojiListWidget::countDesiredHeight(int newWidth) { + const auto left = st::emojiPanLeft; + const auto right = st::emojiPanRight; const auto fullWidth = st::roundRadiusSmall + newWidth + st::emojiScroll.width; - _columnCount = std::max( - (fullWidth - st::emojiPadding * 2) / st::emojiPanDesiredSize, - 1); - - _rowsLeft = fullWidth / (_columnCount * 4 + 2); - auto rowsRight = std::max(_rowsLeft, st::emojiScroll.width); - auto singleWidth = (fullWidth - _rowsLeft - rowsRight) - / _columnCount; - _rowsLeft -= st::roundRadiusSmall; - _singleSize = QSize(singleWidth, singleWidth - 4 * st::lineWidth); - _picker->setSingleSize(_singleSize); + const auto innerWidth = fullWidth - left - right; + _columnCount = std::max(innerWidth / st::emojiPanDesiredSize, 1); + const auto singleWidth = innerWidth / _columnCount; + _rowsLeft = left + + (innerWidth - _columnCount * singleWidth) / 2 + - st::roundRadiusSmall; + setSingleSize({ singleWidth, singleWidth - 4 * st::lineWidth }); auto visibleHeight = minimalHeight(); auto minimalHeight = (visibleHeight - st::stickerPanPadding); @@ -734,17 +764,12 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) { } else if (r.top() + r.height() <= info.top) { return false; } - if (info.premiumRequired) { - drawPremiumRect(p, info); - } auto widthForTitle = emojiRight() - (st::emojiPanHeaderLeft - st::roundRadiusSmall); const auto skip = st::roundRadiusSmall; if (hasRemoveButton(info.section)) { auto &custom = _custom[info.section - kEmojiSectionCount]; auto remove = removeButtonRect(info.section); - auto expanded = remove.marginsAdded({ skip, 0, skip, 0 }); - if (expanded.intersects(r)) { - p.fillRect(expanded, st::emojiPanBg); + if (remove.intersects(r)) { auto selected = selectedButton ? (selectedButton->section == info.section) : false; if (custom.ripple) { custom.ripple->paint(p, remove.x() + st::stickerPanRemoveSet.rippleAreaPosition.x(), remove.y() + st::stickerPanRemoveSet.rippleAreaPosition.y(), width()); @@ -767,17 +792,16 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) { titleText = st::emojiPanHeaderFont->elided(titleText, widthForTitle); titleWidth = st::emojiPanHeaderFont->width(titleText); } - auto left = st::emojiPanHeaderLeft - st::roundRadiusSmall; + const auto left = (info.premiumRequired + ? st::emojiPanHeaderLockedLeft + : st::emojiPanHeaderLeft) - st::roundRadiusSmall; const auto top = info.top + st::emojiPanHeaderTop; if (info.premiumRequired) { - p.fillRect( - left - skip, - top - skip, - titleWidth + st::emojiPremiumRequired.width() + skip, - st::emojiPanHeaderFont->height + 2 * skip, - st::emojiPanBg); - st::emojiPremiumRequired.paint(p, left - skip, top, width()); - left += st::emojiPremiumRequired.width() - skip; + st::emojiPremiumRequired.paint( + p, + st::emojiPanHeaderLockLeft - st::roundRadiusSmall, + top, + width()); } p.setFont(st::emojiPanHeaderFont); p.setPen(st::emojiPanHeaderFg); @@ -800,11 +824,18 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) { || (!_picker->isHidden() && state == _pickerSelected); - auto w = QPoint(_rowsLeft + j * _singleSize.width(), info.rowsTop + i * _singleSize.height()); + auto w = QPoint( + _rowsLeft + j * _singleSize.width(), + info.rowsTop + i * _singleSize.height() + ) + _areaPosition; if (selected && !info.premiumRequired) { auto tl = w; - if (rtl()) tl.setX(width() - tl.x() - _singleSize.width()); - Ui::FillRoundRect(p, QRect(tl, _singleSize), st::emojiPanHover, Ui::StickerHoverCorners); + if (rtl()) tl.setX(width() - tl.x() - st::emojiPanArea.width()); + Ui::FillRoundRect( + p, + QRect(tl, st::emojiPanArea), + st::emojiPanHover, + Ui::EmojiHoverCorners); } if (info.section == int(Section::Recent)) { drawRecent(p, w, now, paused, index); @@ -821,41 +852,22 @@ void EmojiListWidget::paintEvent(QPaintEvent *e) { }); } -void EmojiListWidget::drawPremiumRect(QPainter &p, const SectionInfo &info) { - auto pen = st::windowSubTextFg->p; - pen.setWidthF(style::ConvertScale(2.)); - pen.setDashPattern({ 3, 5 }); - pen.setDashOffset(2); - pen.setCapStyle(Qt::RoundCap); - p.setPen(pen); - p.setBrush(Qt::NoBrush); - - const auto radius = st::roundRadiusLarge; - const auto titleTop = info.top + st::emojiPanHeaderTop; - const auto left = _rowsLeft; - const auto top = titleTop + st::emojiPanHeaderFont->height / 2; - const auto width = _columnCount * _singleSize.width(); - const auto height = info.rowsBottom - top - st::roundRadiusSmall; - p.drawRoundedRect(left, top, width, height, radius, radius); -} - void EmojiListWidget::drawRecent( QPainter &p, QPoint position, crl::time now, bool paused, int index) { - const auto size = (_esize / cIntRetinaFactor()); _recentPainted = true; if (const auto emoji = std::get_if(&_recent[index].id.data)) { drawEmoji(p, position, *emoji); } else { Assert(_recent[index].instance != nullptr); - + position += _innerPosition; _recent[index].instance->object.paint( p, - position.x() + (_singleSize.width() - size) / 2, - position.y() + (_singleSize.height() - size) / 2, + position.x(), + position.y(), now, st::windowBgRipple->c, paused); @@ -866,13 +878,13 @@ void EmojiListWidget::drawEmoji( QPainter &p, QPoint position, EmojiPtr emoji) { - const auto size = (_esize / cIntRetinaFactor()); + position += _innerPosition; Ui::Emoji::Draw( p, emoji, - _esize, - position.x() + (_singleSize.width() - size) / 2, - position.y() + (_singleSize.height() - size) / 2); + Ui::Emoji::GetSizeLarge(), + position.x(), + position.y()); } void EmojiListWidget::drawCustom( @@ -882,12 +894,12 @@ void EmojiListWidget::drawCustom( bool paused, int set, int index) { - const auto size = (_esize / cIntRetinaFactor()); + position += _innerPosition; _custom[set].painted = true; _custom[set].list[index].instance->object.paint( p, - position.x() + (_singleSize.width() - size) / 2, - position.y() + (_singleSize.height() - size) / 2, + position.x(), + position.y(), now, st::windowBgRipple->c, paused); @@ -1085,7 +1097,7 @@ QRect EmojiListWidget::removeButtonRect(int index) const { auto buttonw = st::stickerPanRemoveSet.rippleAreaPosition.x() + st::stickerPanRemoveSet.rippleAreaSize; auto buttonh = st::stickerPanRemoveSet.height; - auto buttonx = emojiRight() - buttonw; + auto buttonx = emojiRight() - st::emojiPanRemoveSkip - buttonw; auto buttony = sectionInfo(index).top + (st::emojiPanHeader - buttonh) / 2; return QRect(buttonx, buttony, buttonw, buttonh); } diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h index 0c7c03403..7d5edb74e 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h @@ -171,6 +171,7 @@ private: [[nodiscard]] SectionInfo sectionInfo(int section) const; [[nodiscard]] SectionInfo sectionInfoByOffset(int yOffset) const; [[nodiscard]] int sectionsCount() const; + void setSingleSize(QSize size); void showPicker(); void pickerHidden(); @@ -204,7 +205,6 @@ private: bool paused, int set, int index); - void drawPremiumRect(QPainter &p, const SectionInfo &info); [[nodiscard]] bool hasRemoveButton(int index) const; [[nodiscard]] QRect removeButtonRect(int index) const; [[nodiscard]] QRect emojiRect(int section, int index) const; @@ -255,7 +255,8 @@ private: int _rowsLeft = 0; int _columnCount = 1; QSize _singleSize; - int _esize = 0; + QPoint _areaPosition; + QPoint _innerPosition; OverState _selected; OverState _pressed; diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 0c7f36f01..1f1284755 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -1009,8 +1009,6 @@ void Settings::resetOnLastLogout() { _recentEmoji.clear(); _emojiVariants.clear(); - _workMode = WorkMode::WindowAndTray; - _accountsOrder.clear(); } diff --git a/Telegram/SourceFiles/ui/cached_round_corners.cpp b/Telegram/SourceFiles/ui/cached_round_corners.cpp index bcd9a9478..056484388 100644 --- a/Telegram/SourceFiles/ui/cached_round_corners.cpp +++ b/Telegram/SourceFiles/ui/cached_round_corners.cpp @@ -80,7 +80,7 @@ void CreatePaletteCorners() { PrepareCorners(OverviewVideoSelectedCorners, st::overviewVideoStatusRadius, st::msgDateImgBgSelected); PrepareCorners(ForwardCorners, st::historyMessageRadius, st::historyForwardChooseBg); PrepareCorners(MediaviewSaveCorners, st::mediaviewControllerRadius, st::mediaviewSaveMsgBg); - PrepareCorners(EmojiHoverCorners, st::roundRadiusSmall, st::emojiPanHover); + PrepareCorners(EmojiHoverCorners, st::emojiPanRadius, st::emojiPanHover); PrepareCorners(StickerHoverCorners, st::roundRadiusSmall, st::emojiPanHover); PrepareCorners(BotKeyboardCorners, st::roundRadiusSmall, st::botKbBg);