diff --git a/Telegram/SourceFiles/boxes/premium_preview_box.cpp b/Telegram/SourceFiles/boxes/premium_preview_box.cpp index dc12d2697..02c344d22 100644 --- a/Telegram/SourceFiles/boxes/premium_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/premium_preview_box.cpp @@ -996,7 +996,7 @@ void ReactionPreview::paintEffect(QPainter &p) { Data::Reactions::Type::Active); const auto count = ranges::count(list, true, &Data::Reaction::premium); const auto rows = (count + kReactionsPerRow - 1) / kReactionsPerRow; - const auto inrowmax = (count + rows - 1) / rows; + const auto inrowmax = rows ? ((count + rows - 1) / rows) : 1; const auto inrowless = (inrowmax * rows - count); const auto inrowmore = rows - inrowless; const auto inmaxrows = inrowmore * inrowmax; diff --git a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp index 3dbddc6f6..8617597fa 100644 --- a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp @@ -455,9 +455,7 @@ void ReactionsSettingsBox( button->setClickedCallback([=, id = r.id] { if (premium && !controller->session().premium()) { - ShowPremiumPreviewBox( - controller, - PremiumPreview::Reactions); + ShowPremiumPreviewBox(controller, PremiumPreview::Reactions); return; } checkButton(button); diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index e8cd03700..d6738880b 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -826,8 +826,11 @@ void EmojiListWidget::paint( const auto buttonSelected = selectedButton ? (selectedButton->section == info.section) : false; + const auto titleLeft = (info.premiumRequired + ? st().headerLockedLeft + : st().headerLeft) - st().margin.left(); const auto widthForTitle = emojiRight() - - (st().headerLeft - st().margin.left()) + - titleLeft - paintButtonGetWidth(p, info, buttonSelected, clip); if (info.section > 0 && clip.top() < info.rowsTop) { p.setFont(st::emojiPanHeaderFont); @@ -840,9 +843,6 @@ void EmojiListWidget::paint( titleText = st::emojiPanHeaderFont->elided(titleText, widthForTitle); titleWidth = st::emojiPanHeaderFont->width(titleText); } - const auto left = (info.premiumRequired - ? st().headerLockedLeft - : st().headerLeft) - st().margin.left(); const auto top = info.top + st().headerTop; if (info.premiumRequired) { st::emojiPremiumRequired.paint( @@ -851,10 +851,10 @@ void EmojiListWidget::paint( top, width()); } - const auto textTop = top + st::emojiPanHeaderFont->ascent; + const auto textBaseline = top + st::emojiPanHeaderFont->ascent; p.setFont(st::emojiPanHeaderFont); p.setPen(st::emojiPanHeaderFg); - p.drawText(left, textTop, titleText); + p.drawText(titleLeft, textBaseline, titleText); } if (clip.top() + clip.height() > info.rowsTop) { ensureLoaded(info.section); @@ -1139,7 +1139,18 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) { _localSetsManager->install(id); } else if (_controller) { _jumpedToPremium.fire({}); - Settings::ShowPremium(_controller, u"animated_emoji"_q); + switch (_mode) { + case Mode::Full: + Settings::ShowPremium(_controller, u"animated_emoji"_q); + break; + case Mode::FullReactions: + case Mode::RecentReactions: + Settings::ShowPremium(_controller, u"unique_reactions"_q); + break; + case Mode::EmojiStatus: + Settings::ShowPremium(_controller, u"emoji_status"_q); + break; + } } } } @@ -1679,7 +1690,7 @@ int EmojiListWidget::paintButtonGetWidth( remove.topLeft() + st::stickerPanRemoveSet.iconPosition, width()); } - return remove.width(); + return emojiRight() - remove.x(); } const auto canAdd = hasAddButton(info.section); const auto &button = rightButton(info.section); @@ -1704,7 +1715,7 @@ int EmojiListWidget::paintButtonGetWidth( + st::emojiPanButton.textTop + st::emojiPanButton.font->ascent), button.text); - return rect.width(); + return emojiRight() - rect.x(); } bool EmojiListWidget::eventHook(QEvent *e) { diff --git a/Telegram/SourceFiles/data/data_message_reactions.cpp b/Telegram/SourceFiles/data/data_message_reactions.cpp index 8045d68b1..97632582d 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.cpp +++ b/Telegram/SourceFiles/data/data_message_reactions.cpp @@ -184,18 +184,21 @@ Reactions::Reactions(not_null owner) _repaintItems.remove(item); }, _lifetime); - rpl::single(rpl::empty) | rpl::then( - _owner->session().mtp().config().updates() - ) | rpl::map([=] { - const auto &config = _owner->session().mtp().configValues(); - return config.reactionDefaultCustom - ? ReactionId{ DocumentId(config.reactionDefaultCustom) } - : ReactionId{ config.reactionDefaultEmoji }; - }) | rpl::filter([=](const ReactionId &id) { - return !_saveFaveRequestId; - }) | rpl::start_with_next([=](ReactionId &&id) { - applyFavorite(id); - }, _lifetime); + crl::on_main(&owner->session(), [=] { + // applyFavorite accesses not yet constructed parts of session. + rpl::single(rpl::empty) | rpl::then( + _owner->session().mtp().config().updates() + ) | rpl::map([=] { + const auto &config = _owner->session().mtp().configValues(); + return config.reactionDefaultCustom + ? ReactionId{ DocumentId(config.reactionDefaultCustom) } + : ReactionId{ config.reactionDefaultEmoji }; + }) | rpl::filter([=](const ReactionId &id) { + return !_saveFaveRequestId; + }) | rpl::start_with_next([=](ReactionId &&id) { + applyFavorite(id); + }, _lifetime); + }); } Reactions::~Reactions() = default; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index fdf90c110..84d4984ff 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -464,11 +464,15 @@ HistoryInner::HistoryInner( void HistoryInner::reactionChosen(const ChosenReaction &reaction) { const auto item = session().data().message(reaction.context); - if (!item - || Window::ShowReactPremiumError( + if (!item) { + return; + } else if (Window::ShowReactPremiumError( _controller, item, reaction.id)) { + if (_menu) { + _menu->hideMenu(); + } return; } item->toggleReaction(reaction.id, HistoryItem::ReactionSource::Selector); @@ -1943,9 +1947,9 @@ void HistoryInner::toggleFavoriteReaction(not_null view) const { const auto item = view->data(); const auto favorite = session().data().reactions().favoriteId(); if (!ranges::contains( - Data::LookupPossibleReactions(item).recent, - favorite, - &Data::Reaction::id) + Data::LookupPossibleReactions(item).recent, + favorite, + &Data::Reaction::id) || Window::ShowReactPremiumError(_controller, item, favorite)) { return; } else if (!ranges::contains(item->chosenReactions(), favorite)) { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 38cd8e508..d079cf8ab 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -357,11 +357,15 @@ ListWidget::ListWidget( _reactionsManager->updateButton({}); const auto item = session().data().message(reaction.context); - if (!item - || Window::ShowReactPremiumError( - _controller, - item, - reaction.id)) { + if (!item) { + return; + } else if (Window::ShowReactPremiumError( + _controller, + item, + reaction.id)) { + if (_menu) { + _menu->hideMenu(); + } return; } item->toggleReaction( diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp index 131755295..eff1c7ccf 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_selector.cpp @@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/emoji_list_widget.h" #include "chat_helpers/stickers_list_footer.h" #include "window/window_session_controller.h" -#include "settings/settings_premium.h" +#include "boxes/premium_preview_box.h" #include "mainwidget.h" #include "apiwrap.h" #include "base/call_delayed.h" @@ -515,7 +515,14 @@ void Selector::expand() { } _expandScheduled = true; const auto parent = parentWidget()->geometry(); - const auto additionalBottom = parent.height() - y() - height(); + const auto extents = extentsForShadow(); + const auto heightLimit = _reactions.customAllowed + ? st::emojiPanMaxHeight + : minimalHeight(); + const auto willBeHeight = std::min( + parent.height() - y(), + extents.top() + heightLimit + extents.bottom()); + const auto additionalBottom = willBeHeight - height(); const auto additional = _specialExpandTopSkip + additionalBottom; const auto strong = _parentController.get(); if (additionalBottom < 0 || additional <= 0 || !strong) { @@ -627,9 +634,14 @@ void Selector::createList(not_null controller) { }) ).data(); - _list->customChosen( - ) | rpl::start_with_next([=](const TabbedSelector::FileChosen &chosen) { - const auto id = DocumentId{ chosen.document->id }; + rpl::merge( + _list->customChosen( + ) | rpl::map([=](const TabbedSelector::FileChosen &chosen) { + return chosen.document; + }), + _list->premiumChosen() + ) | rpl::start_with_next([=](not_null document) { + const auto id = DocumentId{ document->id }; const auto i = defaultReactionIds.find(id); if (i != end(defaultReactionIds)) { _chosen.fire({ .id = { i->second } }); @@ -638,12 +650,6 @@ void Selector::createList(not_null controller) { } }, _list->lifetime()); - _list->premiumChosen( - ) | rpl::start_with_next([=] { - _jumpedToPremium(); - Settings::ShowPremium(controller, u"animated_emoji"_q); - }, _list->lifetime()); - _list->jumpedToPremium( ) | rpl::start_with_next(_jumpedToPremium, _list->lifetime()); diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index f6840ae9e..9797b2cfb 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -375,7 +375,9 @@ bool ShowReactPremiumError( Data::Reactions::Type::Active); const auto i = ranges::find(list, id, &Data::Reaction::id); if (i == end(list) || !i->premium) { - return false; + if (!id.custom()) { + return false; + } } ShowPremiumPreviewBox( controller,