diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index defc4bd64..8e94beeb9 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -470,8 +470,8 @@ void EditCaptionBox::rebuildPreview() { void EditCaptionBox::setupField() { const auto peer = _historyItem->history()->peer; - const auto allow = [=](const auto&) { - return Data::AllowEmojiWithoutPremium(peer); + const auto allow = [=](not_null emoji) { + return Data::AllowEmojiWithoutPremium(peer, emoji); }; InitMessageFieldHandlers( _controller, diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp index 0ab69bf3b..15700114b 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp @@ -479,6 +479,7 @@ void Set( MTP_flags(Flag::f_color | Flag::f_background_emoji_id), MTP_int(values.colorIndex), MTP_long(values.backgroundEmojiId))); + } else if (peer->isMegagroup()) { } else if (const auto channel = peer->asChannel()) { using Flag = MTPchannels_UpdateColor::Flag; send(MTPchannels_UpdateColor( diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 7cd37dbe8..8b871cb63 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -335,16 +335,16 @@ SendFilesBox::SendFilesBox( not_null controller, Ui::PreparedList &&list, const TextWithTags &caption, - SendFilesLimits limits, - SendFilesCheck check, + not_null toPeer, Api::SendType sendType, SendMenu::Type sendMenuType) : SendFilesBox(nullptr, { .show = controller->uiShow(), .list = std::move(list), .caption = caption, - .limits = limits, - .check = check, + .captionToPeer = toPeer, + .limits = DefaultLimitsForPeer(toPeer), + .check = DefaultCheckForPeer(controller, toPeer), .sendType = sendType, .sendMenuType = sendMenuType, }) { @@ -360,6 +360,7 @@ SendFilesBox::SendFilesBox(QWidget*, SendFilesBoxDescriptor &&descriptor) , _list(std::move(descriptor.list)) , _limits(descriptor.limits) , _sendMenuType(descriptor.sendMenuType) +, _captionToPeer(descriptor.captionToPeer) , _check(std::move(descriptor.check)) , _confirmedCallback(std::move(descriptor.confirmed)) , _cancelledCallback(std::move(descriptor.cancelled)) @@ -1000,8 +1001,10 @@ void SendFilesBox::updateSendWayControls() { } void SendFilesBox::setupCaption() { - const auto allow = [=](const auto &) { - return (_limits & SendFilesAllow::EmojiWithoutPremium); + const auto allow = [=](not_null emoji) { + return _captionToPeer + ? Data::AllowEmojiWithoutPremium(_captionToPeer, emoji) + : (_limits & SendFilesAllow::EmojiWithoutPremium); }; const auto show = _show; InitMessageFieldHandlers( @@ -1113,7 +1116,6 @@ void SendFilesBox::setupEmojiPanel() { .level = Window::GifPauseReason::Layer, .mode = ChatHelpers::TabbedSelector::Mode::EmojiOnly, .features = { - .megagroupSet = false, .stickersSettings = false, .openStickerSets = false, }, @@ -1124,6 +1126,7 @@ void SendFilesBox::setupEmojiPanel() { st::emojiPanMinHeight / 2, st::emojiPanMinHeight); _emojiPanel->hide(); + _emojiPanel->selector()->setCurrentPeer(_captionToPeer); _emojiPanel->selector()->setAllowEmojiWithoutPremium( _limits & SendFilesAllow::EmojiWithoutPremium); _emojiPanel->selector()->emojiChosen( @@ -1136,7 +1139,11 @@ void SendFilesBox::setupEmojiPanel() { if (info && info->setType == Data::StickersType::Emoji && !_show->session().premium() - && !(_limits & SendFilesAllow::EmojiWithoutPremium)) { + && !(_captionToPeer + ? Data::AllowEmojiWithoutPremium( + _captionToPeer, + data.document) + : (_limits & SendFilesAllow::EmojiWithoutPremium))) { ShowPremiumPreviewBox(_show, PremiumPreview::AnimatedEmoji); } else { Data::InsertCustomEmoji(_caption.data(), data.document); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 0acbb8f49..af712eda1 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -92,6 +92,7 @@ struct SendFilesBoxDescriptor { std::shared_ptr show; Ui::PreparedList list; TextWithTags caption; + PeerData *captionToPeer = nullptr; SendFilesLimits limits = {}; SendFilesCheck check; Api::SendType sendType = {}; @@ -112,8 +113,7 @@ public: not_null controller, Ui::PreparedList &&list, const TextWithTags &caption, - SendFilesLimits limits, - SendFilesCheck check, + not_null toPeer, Api::SendType sendType, SendMenu::Type sendMenuType); SendFilesBox(QWidget*, SendFilesBoxDescriptor &&descriptor); @@ -239,7 +239,7 @@ private: SendFilesLimits _limits = {}; SendMenu::Type _sendMenuType = {}; - + PeerData *_captionToPeer = nullptr; SendFilesCheck _check; SendFilesConfirmed _confirmedCallback; Fn _cancelledCallback; diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp index 2d27f1db4..224dafa08 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.cpp @@ -31,6 +31,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "layout/layout_position.h" #include "data/data_session.h" +#include "data/data_changes.h" +#include "data/data_channel.h" #include "data/data_document.h" #include "data/data_peer_values.h" #include "data/stickers/data_stickers.h" @@ -41,6 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "emoji_suggestions_data.h" #include "emoji_suggestions_helper.h" #include "main/main_session.h" +#include "main/main_session_settings.h" #include "core/core_settings.h" #include "core/application.h" #include "settings/settings_premium.h" @@ -462,6 +465,7 @@ EmojiListWidget::EmojiListWidget( , _show(std::move(descriptor.show)) , _features(descriptor.features) , _mode(descriptor.mode) +, _api(&session().mtp()) , _staticCount(_mode == Mode::Full ? kEmojiSectionCount : 1) , _premiumIcon(_mode == Mode::EmojiStatus ? std::make_unique() @@ -517,6 +521,15 @@ EmojiListWidget::EmojiListWidget( pickerHidden(); }, lifetime()); + session().changes().peerUpdates( + Data::PeerUpdate::Flag::EmojiSet + ) | rpl::filter([=](const Data::PeerUpdate &update) { + return (update.peer.get() == _megagroupSet); + }) | rpl::start_with_next([=] { + refreshCustom(); + resizeToWidth(width()); + }, lifetime()); + session().data().stickers().updated( Data::StickersType::Emoji ) | rpl::start_with_next([=] { @@ -1678,6 +1691,13 @@ void EmojiListWidget::mouseReleaseEvent(QMouseEvent *e) { } void EmojiListWidget::displaySet(uint64 setId) { + if (setId == Data::Stickers::MegagroupSetId) { + if (_megagroupSet->mgInfo->emojiSet.id) { + setId = _megagroupSet->mgInfo->emojiSet.id; + } else { + return; + } + } const auto &sets = session().data().stickers().sets(); auto it = sets.find(setId); if (it != sets.cend()) { @@ -1685,9 +1705,37 @@ void EmojiListWidget::displaySet(uint64 setId) { } } +void EmojiListWidget::removeMegagroupSet(bool locally) { + if (locally) { + session().settings().setGroupEmojiSectionHidden(_megagroupSet->id); + session().saveSettings(); + refreshCustom(); + return; + } + checkHideWithBox(Ui::MakeConfirmBox({ + .text = tr::lng_emoji_remove_group_set(), + .confirmed = crl::guard(this, [this, group = _megagroupSet]( + Fn &&close) { + Expects(group->mgInfo != nullptr); + + if (group->mgInfo->emojiSet) { + session().api().setGroupEmojiSet(group, {}); + } + close(); + }), + .cancelled = [](Fn &&close) { close(); }, + .labelStyle = &st().boxLabel, + })); +} + void EmojiListWidget::removeSet(uint64 setId) { const auto &labelSt = st().boxLabel; - if (auto box = MakeConfirmRemoveSetBox(&session(), labelSt, setId)) { + if (setId == Data::Stickers::MegagroupSetId) { + const auto i = ranges::find(_custom, setId, &CustomSet::id); + Assert(i != end(_custom)); + const auto removeLocally = !_megagroupSet->canEditEmoji(); + removeMegagroupSet(removeLocally); + } else if (auto box = MakeConfirmRemoveSetBox(&session(), labelSt, setId)) { checkHideWithBox(std::move(box)); } } @@ -1784,6 +1832,13 @@ bool EmojiListWidget::hasRemoveButton(int index) const { return false; } const auto &set = _custom[index - _staticCount]; + if (set.id == Data::Stickers::MegagroupSetId) { + Assert(_megagroupSet != nullptr); + if (index + 1 != _staticCount + _custom.size()) { + return true; + } + return !set.list.empty() && _megagroupSet->canEditEmoji(); + } return set.canRemove && !set.premiumRequired; } @@ -1810,7 +1865,9 @@ bool EmojiListWidget::hasAddButton(int index) const { return false; } const auto &set = _custom[index - _staticCount]; - return !set.canRemove && !set.premiumRequired; + return !set.canRemove + && !set.premiumRequired + && set.id != Data::Stickers::MegagroupSetId; } QRect EmojiListWidget::addButtonRect(int index) const { @@ -1834,10 +1891,13 @@ QRect EmojiListWidget::unlockButtonRect(int index) const { } bool EmojiListWidget::hasButton(int index) const { - if (hasColorButton(index) - || (index >= _staticCount - && index < _staticCount + _custom.size())) { + if (hasColorButton(index)) { return true; + } else if (index >= _staticCount + && index < _staticCount + _custom.size()) { + const auto &custom = _custom[index - _staticCount]; + return (custom.id != Data::Stickers::MegagroupSetId) + || custom.canRemove; } return false; } @@ -1967,6 +2027,16 @@ void EmojiListWidget::setAllowWithoutPremium(bool allow) { resizeToWidth(width()); } +void EmojiListWidget::showMegagroupSet(ChannelData *megagroup) { + Expects(!megagroup || megagroup->isMegagroup()); + + if (_megagroupSet != megagroup) { + _megagroupSet = megagroup; + refreshCustom(); + resizeToWidth(width()); + } +} + QString EmojiListWidget::tooltipText() const { if (_mode != Mode::Full) { return {}; @@ -2037,7 +2107,15 @@ void EmojiListWidget::refreshCustom() { const auto owner = &session->data(); const auto &sets = owner->stickers().sets(); const auto push = [&](uint64 setId, bool installed) { - auto it = sets.find(setId); + const auto megagroup = _megagroupSet + && (setId == Data::Stickers::MegagroupSetId); + const auto lookupId = megagroup + ? _megagroupSet->mgInfo->emojiSet.id + : setId; + if (!lookupId) { + return; + } + auto it = sets.find(lookupId); if (it == sets.cend() || it->second->stickers.isEmpty() || (_mode == Mode::BackgroundEmoji && !it->second->textColor()) @@ -2045,12 +2123,13 @@ void EmojiListWidget::refreshCustom() { && !it->second->channelStatus())) { return; } - const auto canRemove = !!(it->second->flags - & Data::StickersSetFlag::Installed); + const auto canRemove = megagroup + ? (_megagroupSet->canEditEmoji() || installed) + : !!(it->second->flags & Data::StickersSetFlag::Installed); const auto sortAsInstalled = canRemove && (!(it->second->flags & Data::StickersSetFlag::Featured) - || !_localSetsManager->isInstalledLocally(setId)); - if (sortAsInstalled != installed) { + || !_localSetsManager->isInstalledLocally(lookupId)); + if (!megagroup && sortAsInstalled != installed) { return; } auto premium = false; @@ -2063,7 +2142,7 @@ void EmojiListWidget::refreshCustom() { return false; } for (auto k = 0; k != count; ++k) { - if (!premium && list[k]->isPremiumEmoji()) { + if (!premium && !megagroup && list[k]->isPremiumEmoji()) { premium = true; } if (i->list[k].document != list[k]) { @@ -2097,11 +2176,11 @@ void EmojiListWidget::refreshCustom() { continue; } else if (const auto sticker = document->sticker()) { set.push_back({ - .custom = resolveCustomEmoji(document, setId), + .custom = resolveCustomEmoji(document, lookupId), .document = document, .emoji = Ui::Emoji::Find(sticker->alt), }); - if (!premium && document->isPremiumEmoji()) { + if (!premium && !megagroup && document->isPremiumEmoji()) { premium = true; } } @@ -2119,12 +2198,14 @@ void EmojiListWidget::refreshCustom() { .premiumRequired = premium && premiumMayBeBought, }); }; + refreshMegagroupStickers(push, GroupStickersPlace::Visible); for (const auto setId : owner->stickers().emojiSetsOrder()) { push(setId, true); } for (const auto setId : owner->stickers().featuredEmojiSetsOrder()) { push(setId, false); } + refreshMegagroupStickers(push, GroupStickersPlace::Hidden); _footer->refreshIcons( fillIcons(), @@ -2217,6 +2298,60 @@ not_null EmojiListWidget::resolveCustomRecent( ).first->second.emoji.get(); } +void EmojiListWidget::refreshMegagroupStickers( + Fn push, + GroupStickersPlace place) { + if (!_features.megagroupSet + || !_megagroupSet + || !_megagroupSet->mgInfo->emojiSet) { + return; + } + auto canEdit = _megagroupSet->canEditEmoji(); + auto isShownHere = [place](bool hidden) { + return (hidden == (place == GroupStickersPlace::Hidden)); + }; + auto hidden = session().settings().isGroupEmojiSectionHidden(_megagroupSet->id); + auto removeHiddenForGroup = [this, &hidden] { + if (hidden) { + session().settings().removeGroupEmojiSectionHidden(_megagroupSet->id); + session().saveSettings(); + hidden = false; + } + }; + if (canEdit && hidden) { + removeHiddenForGroup(); + } + const auto &set = _megagroupSet->mgInfo->emojiSet; + if (!set.id || !isShownHere(hidden)) { + return; + } + push(Data::Stickers::MegagroupSetId, !hidden); + if (!_custom.empty() + && _custom.back().id == Data::Stickers::MegagroupSetId) { + return; + } else if (_megagroupSetIdRequested == set.id) { + return; + } + _megagroupSetIdRequested = set.id; + _api.request(MTPmessages_GetStickerSet( + Data::InputStickerSet(set), + MTP_int(0) // hash + )).done([=](const MTPmessages_StickerSet &result) { + result.match([&](const MTPDmessages_stickerSet &data) { + if (const auto set = session().data().stickers().feedSetFull(data)) { + refreshCustom(); + if (set->id == _megagroupSetIdRequested) { + _megagroupSetIdRequested = 0; + } else { + LOG(("API Error: Got different set.")); + } + } + }, [](const MTPDmessages_stickerSetNotModified &) { + LOG(("API Error: Unexpected messages.stickerSetNotModified.")); + }); + }).send(); +} + std::vector EmojiListWidget::fillIcons() { auto result = std::vector(); result.reserve(2 + _custom.size()); @@ -2233,6 +2368,11 @@ std::vector EmojiListWidget::fillIcons() { } const auto esize = StickersListFooter::IconFrameSize(); for (const auto &custom : _custom) { + if (custom.id == Data::Stickers::MegagroupSetId) { + result.emplace_back(Data::Stickers::MegagroupSetId); + result.back().megagroup = _megagroupSet; + continue; + } const auto set = custom.set; result.emplace_back(set, custom.thumbnailDocument, esize, esize); } diff --git a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h index c2a8ef3ed..0f1c897a6 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/emoji_list_widget.h @@ -117,6 +117,7 @@ public: void showSet(uint64 setId); [[nodiscard]] uint64 currentSet(int yOffset) const; void setAllowWithoutPremium(bool allow); + void showMegagroupSet(ChannelData *megagroup); // Ui::AbstractTooltipShower interface. QString tooltipText() const override; @@ -257,6 +258,13 @@ private: void colorChosen(EmojiChosen data); bool checkPickerHide(); void refreshCustom(); + enum class GroupStickersPlace { + Visible, + Hidden, + }; + void refreshMegagroupStickers( + Fn push, + GroupStickersPlace place); void unloadNotSeenCustom(int visibleTop, int visibleBottom); void unloadAllCustom(); void unloadCustomIn(const SectionInfo &info); @@ -340,6 +348,7 @@ private: void displaySet(uint64 setId); void removeSet(uint64 setId); + void removeMegagroupSet(bool locally); void initButton(RightButton &button, const QString &text, bool gradient); [[nodiscard]] std::unique_ptr createButtonRipple( @@ -368,10 +377,13 @@ private: const ComposeFeatures _features; Mode _mode = Mode::Full; std::unique_ptr _search; + MTP::Sender _api; const int _staticCount = 0; StickersListFooter *_footer = nullptr; std::unique_ptr _premiumIcon; std::unique_ptr _localSetsManager; + ChannelData *_megagroupSet = nullptr; + uint64 _megagroupSetIdRequested = 0; Fn( DocumentId, Fn)> _customRecentFactory; diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp index 77ca3bdd3..85c8f9dda 100644 --- a/Telegram/SourceFiles/chat_helpers/message_field.cpp +++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp @@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_widget.h" #include "history/history.h" // History::session #include "history/history_item.h" // HistoryItem::originalText -#include "history/history_item_helpers.h" // DropCustomEmoji +#include "history/history_item_helpers.h" // DropDisallowedCustomEmoji #include "base/qthelp_regex.h" #include "base/qthelp_url.h" #include "base/event_filter.h" @@ -278,11 +278,9 @@ TextWithTags PrepareEditText(not_null item) { auto original = item->history()->session().supportMode() ? StripSupportHashtag(item->originalText()) : item->originalText(); - const auto dropCustomEmoji = !item->history()->session().premium() - && !item->history()->peer->isSelf(); - if (dropCustomEmoji) { - original = DropCustomEmoji(std::move(original)); - } + original = DropDisallowedCustomEmoji( + item->history()->peer, + std::move(original)); return TextWithTags{ original.text, TextUtilities::ConvertEntitiesToTextTags(original.entities) diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 6fc2c555a..5841f2c9e 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -966,6 +966,9 @@ void TabbedSelector::setCurrentPeer(PeerData *peer) { } _currentPeer = peer; checkRestrictedPeer(); + if (hasEmojiTab()) { + emoji()->showMegagroupSet(peer ? peer->asMegagroup() : nullptr); + } if (hasStickersTab()) { stickers()->showMegagroupSet(peer ? peer->asMegagroup() : nullptr); } diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 831709a18..0c73b00b6 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -648,6 +648,10 @@ bool ChannelData::canEditStickers() const { return (flags() & Flag::CanSetStickers); } +bool ChannelData::canEditEmoji() const { + return amCreator(); AssertIsDebug(); +} + bool ChannelData::canDelete() const { constexpr auto kDeleteChannelMembersLimit = 1000; return amCreator() diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 9cdebf5c4..afeb20cbd 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -361,6 +361,7 @@ public: [[nodiscard]] bool canViewBanned() const; [[nodiscard]] bool canEditSignatures() const; [[nodiscard]] bool canEditStickers() const; + [[nodiscard]] bool canEditEmoji() const; [[nodiscard]] bool canDelete() const; [[nodiscard]] bool canEditAdmin(not_null user) const; [[nodiscard]] bool canRestrictParticipant( diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index 5b271b5b6..0e40b7792 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_account.h" #include "main/main_app_config.h" #include "main/main_session.h" +#include "data/data_channel.h" #include "data/data_session.h" #include "data/data_document.h" #include "data/data_document_media.h" @@ -980,8 +981,21 @@ TextWithEntities SingleCustomEmoji(not_null document) { return SingleCustomEmoji(document->id); } -bool AllowEmojiWithoutPremium(not_null peer) { - return peer->isSelf(); +bool AllowEmojiWithoutPremium( + not_null peer, + DocumentData *exactEmoji) { + if (peer->isSelf()) { + return true; + } else if (!exactEmoji) { + return false; + } else if (const auto sticker = exactEmoji->sticker()) { + if (const auto channel = peer->asMegagroup()) { + if (channel->mgInfo->emojiSet.id == sticker->set.id) { + return (sticker->set.id != 0); + } + } + } + return false; } void InsertCustomEmoji( diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h index 947f8bfda..49799e639 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h @@ -201,7 +201,9 @@ private: [[nodiscard]] TextWithEntities SingleCustomEmoji( not_null document); -[[nodiscard]] bool AllowEmojiWithoutPremium(not_null peer); +[[nodiscard]] bool AllowEmojiWithoutPremium( + not_null peer, + DocumentData *exactEmoji = nullptr); void InsertCustomEmoji( not_null field, diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 79fef7373..aa815ccc9 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -564,11 +564,8 @@ HistoryItem::HistoryItem( } } - const auto dropCustomEmoji = dropForwardInfo - && !history->session().premium() - && !history->peer->isSelf(); - setText(dropCustomEmoji - ? DropCustomEmoji(original->originalText()) + setText(dropForwardInfo + ? DropDisallowedCustomEmoji(history->peer, original->originalText()) : original->originalText()); } diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index f3aba166e..911ec9068 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_text_entities.h" #include "boxes/premium_preview_box.h" #include "calls/calls_instance.h" +#include "data/stickers/data_custom_emoji.h" #include "data/notify/data_notify_settings.h" #include "data/data_channel.h" #include "data/data_chat.h" @@ -217,13 +218,40 @@ bool LookupReplyIsTopicPost(HistoryItem *replyTo) { && (replyTo->topicRootId() != Data::ForumTopic::kGeneralId); } -TextWithEntities DropCustomEmoji(TextWithEntities text) { - text.entities.erase( - ranges::remove( - text.entities, - EntityType::CustomEmoji, - &EntityInText::type), - text.entities.end()); +TextWithEntities DropDisallowedCustomEmoji( + not_null to, + TextWithEntities text) { + if (to->session().premium() || to->isSelf()) { + return text; + } + const auto channel = to->asMegagroup(); + const auto allowSetId = channel ? channel->mgInfo->emojiSet.id : 0; + if (!allowSetId) { + text.entities.erase( + ranges::remove( + text.entities, + EntityType::CustomEmoji, + &EntityInText::type), + text.entities.end()); + } else { + const auto predicate = [&](const EntityInText &entity) { + if (entity.type() != EntityType::CustomEmoji) { + return false; + } + if (const auto id = Data::ParseCustomEmojiData(entity.data())) { + const auto document = to->owner().document(id); + if (const auto sticker = document->sticker()) { + if (sticker->set.id == allowSetId) { + return false; + } + } + } + return true; + }; + text.entities.erase( + ranges::remove_if(text.entities, predicate), + text.entities.end()); + } return text; } diff --git a/Telegram/SourceFiles/history/history_item_helpers.h b/Telegram/SourceFiles/history/history_item_helpers.h index 5ebb3f0de..e468f1497 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.h +++ b/Telegram/SourceFiles/history/history_item_helpers.h @@ -111,7 +111,9 @@ struct SendingErrorRequest { not_null thread, SendingErrorRequest request); -[[nodiscard]] TextWithEntities DropCustomEmoji(TextWithEntities text); +[[nodiscard]] TextWithEntities DropDisallowedCustomEmoji( + not_null to, + TextWithEntities text); [[nodiscard]] Main::Session *SessionByUniqueId(uint64 sessionUniqueId); [[nodiscard]] HistoryItem *MessageByGlobalId(GlobalMsgId globalId); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index e003b6020..ba20e32ca 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -395,7 +395,7 @@ HistoryWidget::HistoryWidget( InitMessageField(controller, _field, [=]( not_null document) { - if (_peer && Data::AllowEmojiWithoutPremium(_peer)) { + if (_peer && Data::AllowEmojiWithoutPremium(_peer, document)) { return true; } showPremiumToast(document); @@ -1091,7 +1091,10 @@ void HistoryWidget::initTabbedSelector() { ; info && info->setType == Data::StickersType::Emoji) { if (data.document->isPremiumEmoji() && !session().premium() - && (!_peer || !Data::AllowEmojiWithoutPremium(_peer))) { + && (!_peer + || !Data::AllowEmojiWithoutPremium( + _peer, + data.document))) { showPremiumToast(data.document); } else if (!_field->isHidden()) { Data::InsertCustomEmoji(_field.data(), data.document); @@ -5474,8 +5477,7 @@ bool HistoryWidget::confirmSendingFiles( controller(), std::move(list), text, - DefaultLimitsForPeer(_peer), - DefaultCheckForPeer(controller(), _peer), + _peer, Api::SendType::Normal, sendMenuType()); _field->setTextWithTags({}); diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 19ec21b33..cc960fe9b 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -1572,7 +1572,8 @@ void ComposeControls::initField() { }, _field->lifetime()); #endif // Q_OS_MAC InitMessageField(_show, _field, [=](not_null emoji) { - if (_history && Data::AllowEmojiWithoutPremium(_history->peer)) { + if (_history + && Data::AllowEmojiWithoutPremium(_history->peer, emoji)) { return true; } if (_unavailableEmojiPasted) { @@ -1584,8 +1585,9 @@ void ComposeControls::initField() { _field->setEditLinkCallback( DefaultEditLinkCallback(_show, _field, &_st.boxField)); initAutocomplete(); - const auto allow = [=](const auto &) { - return _history && Data::AllowEmojiWithoutPremium(_history->peer); + const auto allow = [=](not_null emoji) { + return _history + && Data::AllowEmojiWithoutPremium(_history->peer, emoji); }; const auto suggestions = Ui::Emoji::SuggestionsController::Init( _parent, @@ -2087,7 +2089,9 @@ void ComposeControls::initTabbedSelector() { if (data.document->isPremiumEmoji() && !session().premium() && (!_history - || !Data::AllowEmojiWithoutPremium(_history->peer))) { + || !Data::AllowEmojiWithoutPremium( + _history->peer, + data.document))) { if (_unavailableEmojiPasted) { _unavailableEmojiPasted(data.document); } diff --git a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp index 13c6dace6..ca783f07a 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_forward_panel.cpp @@ -194,12 +194,8 @@ void ForwardPanel::updateTexts() { .generateImages = false, .ignoreGroup = true, }).text; - const auto history = item->history(); - const auto dropCustomEmoji = !history->session().premium() - && !_to->peer()->isSelf() - && (item->computeDropForwardedInfo() || !keepNames); - if (dropCustomEmoji) { - text = DropCustomEmoji(std::move(text)); + if (item->computeDropForwardedInfo() || !keepNames) { + text = DropDisallowedCustomEmoji(_to->peer(), std::move(text)); } } else { text = Ui::Text::Colorized( diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index ef330f374..1043cd596 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -964,8 +964,7 @@ bool RepliesWidget::confirmSendingFiles( controller(), std::move(list), _composeControls->getTextWithAppliedMarkdown(), - DefaultLimitsForPeer(_history->peer), - DefaultCheckForPeer(controller(), _history->peer), + _history->peer, Api::SendType::Normal, SendMenu::Type::SilentOnly); // #TODO replies schedule diff --git a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp index 581de48a5..dae80a18d 100644 --- a/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_scheduled_section.cpp @@ -416,8 +416,7 @@ bool ScheduledWidget::confirmSendingFiles( controller(), std::move(list), _composeControls->getTextWithAppliedMarkdown(), - DefaultLimitsForPeer(_history->peer), - DefaultCheckForPeer(controller(), _history->peer), + _history->peer, (CanScheduleUntilOnline(_history->peer) ? Api::SendType::ScheduledToUser : Api::SendType::Scheduled), diff --git a/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp b/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp index 076b34532..eb0805c49 100644 --- a/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp +++ b/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp @@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/slide_wrap.h" #include "styles/style_giveaway.h" #include "styles/style_info.h" +#include "styles/style_premium.h" #include "styles/style_statistics.h" #include @@ -301,6 +302,9 @@ void InnerWidget::fill() { { auto dividerContent = object_ptr(inner); + dividerContent->add(object_ptr( + dividerContent, + st::boostSkipTop)); Ui::FillBoostLimit( fakeShowed->events(), dividerContent.data(), diff --git a/Telegram/SourceFiles/main/main_session_settings.cpp b/Telegram/SourceFiles/main/main_session_settings.cpp index 769cd6998..cf451a20b 100644 --- a/Telegram/SourceFiles/main/main_session_settings.cpp +++ b/Telegram/SourceFiles/main/main_session_settings.cpp @@ -44,7 +44,9 @@ QByteArray SessionSettings::serialize() const { + sizeof(qint32) + (_mutePeriods.size() * sizeof(quint64)) + sizeof(qint32) * 2 - + _hiddenPinnedMessages.size() * (sizeof(quint64) * 3); + + _hiddenPinnedMessages.size() * (sizeof(quint64) * 3) + + sizeof(qint32) + + _groupEmojiSectionHidden.size() * sizeof(quint64); auto result = QByteArray(); result.reserve(size); @@ -91,6 +93,11 @@ QByteArray SessionSettings::serialize() const { << qint64(key.topicRootId.bare) << qint64(value.bare); } + stream + << qint32(_groupEmojiSectionHidden.size()); + for (const auto &peerId : _groupEmojiSectionHidden) { + stream << SerializePeerId(peerId); + } } return result; } @@ -114,6 +121,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) { qint32 appFloatPlayerCorner = static_cast(RectPart::TopRight); base::flat_map appSoundOverrides; base::flat_set groupStickersSectionHidden; + base::flat_set groupEmojiSectionHidden; qint32 appThirdSectionInfoEnabled = 0; qint32 legacySmallDialogsList = 0; float64 appDialogsWidthRatio = app.dialogsWidthRatio(); @@ -410,6 +418,22 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) { } } } + if (!stream.atEnd()) { + auto count = qint32(0); + stream >> count; + if (stream.status() == QDataStream::Ok) { + for (auto i = 0; i != count; ++i) { + quint64 peerId; + stream >> peerId; + if (stream.status() != QDataStream::Ok) { + LOG(("App Error: " + "Bad data for SessionSettings::addFromSerialized()")); + return; + } + groupEmojiSectionHidden.emplace(DeserializePeerId(peerId)); + } + } + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for SessionSettings::addFromSerialized()")); @@ -433,6 +457,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) { case ChatHelpers::SelectorTab::Gifs: _selectorTab = uncheckedTab; break; } _groupStickersSectionHidden = std::move(groupStickersSectionHidden); + _groupEmojiSectionHidden = std::move(groupEmojiSectionHidden); auto uncheckedSupportSwitch = static_cast( supportSwitch); switch (uncheckedSupportSwitch) { diff --git a/Telegram/SourceFiles/main/main_session_settings.h b/Telegram/SourceFiles/main/main_session_settings.h index 44d9e9a4a..222a94ead 100644 --- a/Telegram/SourceFiles/main/main_session_settings.h +++ b/Telegram/SourceFiles/main/main_session_settings.h @@ -75,6 +75,16 @@ public: _groupStickersSectionHidden.remove(peerId); } + void setGroupEmojiSectionHidden(PeerId peerId) { + _groupEmojiSectionHidden.insert(peerId); + } + [[nodiscard]] bool isGroupEmojiSectionHidden(PeerId peerId) const { + return _groupEmojiSectionHidden.contains(peerId); + } + void removeGroupEmojiSectionHidden(PeerId peerId) { + _groupEmojiSectionHidden.remove(peerId); + } + void setMediaLastPlaybackPosition(DocumentId id, crl::time time); [[nodiscard]] crl::time mediaLastPlaybackPosition(DocumentId id) const; @@ -137,6 +147,7 @@ private: ChatHelpers::SelectorTab _selectorTab; // per-window base::flat_set _groupStickersSectionHidden; + base::flat_set _groupEmojiSectionHidden; bool _hadLegacyCallsPeerToPeerNobody = false; Data::AutoDownload::Full _autoDownload; rpl::variable _archiveCollapsed = false; diff --git a/Telegram/SourceFiles/media/stories/media_stories_reply.cpp b/Telegram/SourceFiles/media/stories/media_stories_reply.cpp index d06f32dbb..dba4cb02b 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_reply.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_reply.cpp @@ -505,6 +505,7 @@ bool ReplyArea::confirmSendingFiles( .show = show, .list = std::move(list), .caption = _controls->getTextWithAppliedMarkdown(), + .captionToPeer = _data.peer, .limits = DefaultLimitsForPeer(_data.peer), .check = DefaultCheckForPeer(show, _data.peer), .sendType = Api::SendType::Normal, diff --git a/Telegram/SourceFiles/ui/boxes/boost_box.cpp b/Telegram/SourceFiles/ui/boxes/boost_box.cpp index 25cfd75e5..f4676dcc5 100644 --- a/Telegram/SourceFiles/ui/boxes/boost_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/boost_box.cpp @@ -777,8 +777,6 @@ void FillBoostLimit( container->add(object_ptr(container, skip)); }; - //addSkip(st::boostSkipTop); - const auto ratio = [=](BoostCounters counters) { const auto min = counters.thisLevelBoosts; const auto max = counters.nextLevelBoosts;