Implement free megagroup emoji set.

This commit is contained in:
John Preston 2024-02-09 14:32:29 +04:00
parent 08efa73b2b
commit 571f1a5179
25 changed files with 317 additions and 69 deletions

View file

@ -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<DocumentData*> emoji) {
return Data::AllowEmojiWithoutPremium(peer, emoji);
};
InitMessageFieldHandlers(
_controller,

View file

@ -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(

View file

@ -335,16 +335,16 @@ SendFilesBox::SendFilesBox(
not_null<Window::SessionController*> controller,
Ui::PreparedList &&list,
const TextWithTags &caption,
SendFilesLimits limits,
SendFilesCheck check,
not_null<PeerData*> 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<DocumentData*> 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);

View file

@ -92,6 +92,7 @@ struct SendFilesBoxDescriptor {
std::shared_ptr<ChatHelpers::Show> show;
Ui::PreparedList list;
TextWithTags caption;
PeerData *captionToPeer = nullptr;
SendFilesLimits limits = {};
SendFilesCheck check;
Api::SendType sendType = {};
@ -112,8 +113,7 @@ public:
not_null<Window::SessionController*> controller,
Ui::PreparedList &&list,
const TextWithTags &caption,
SendFilesLimits limits,
SendFilesCheck check,
not_null<PeerData*> 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<void()> _cancelledCallback;

View file

@ -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<GradientPremiumStar>()
@ -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<void()> &&close) {
Expects(group->mgInfo != nullptr);
if (group->mgInfo->emojiSet) {
session().api().setGroupEmojiSet(group, {});
}
close();
}),
.cancelled = [](Fn<void()> &&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<Ui::Text::CustomEmoji*> EmojiListWidget::resolveCustomRecent(
).first->second.emoji.get();
}
void EmojiListWidget::refreshMegagroupStickers(
Fn<void(uint64 setId, bool installed)> 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<StickerIcon> EmojiListWidget::fillIcons() {
auto result = std::vector<StickerIcon>();
result.reserve(2 + _custom.size());
@ -2233,6 +2368,11 @@ std::vector<StickerIcon> 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);
}

View file

@ -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<void(uint64 setId, bool installed)> 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<Ui::RippleAnimation> createButtonRipple(
@ -368,10 +377,13 @@ private:
const ComposeFeatures _features;
Mode _mode = Mode::Full;
std::unique_ptr<Ui::TabbedSearch> _search;
MTP::Sender _api;
const int _staticCount = 0;
StickersListFooter *_footer = nullptr;
std::unique_ptr<GradientPremiumStar> _premiumIcon;
std::unique_ptr<LocalStickersManager> _localSetsManager;
ChannelData *_megagroupSet = nullptr;
uint64 _megagroupSetIdRequested = 0;
Fn<std::unique_ptr<Ui::Text::CustomEmoji>(
DocumentId,
Fn<void()>)> _customRecentFactory;

View file

@ -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<HistoryItem*> 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)

View file

@ -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);
}

View file

@ -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()

View file

@ -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<UserData*> user) const;
[[nodiscard]] bool canRestrictParticipant(

View file

@ -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<DocumentData*> document) {
return SingleCustomEmoji(document->id);
}
bool AllowEmojiWithoutPremium(not_null<PeerData*> peer) {
return peer->isSelf();
bool AllowEmojiWithoutPremium(
not_null<PeerData*> 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(

View file

@ -201,7 +201,9 @@ private:
[[nodiscard]] TextWithEntities SingleCustomEmoji(
not_null<DocumentData*> document);
[[nodiscard]] bool AllowEmojiWithoutPremium(not_null<PeerData*> peer);
[[nodiscard]] bool AllowEmojiWithoutPremium(
not_null<PeerData*> peer,
DocumentData *exactEmoji = nullptr);
void InsertCustomEmoji(
not_null<Ui::InputField*> field,

View file

@ -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());
}

View file

@ -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<PeerData*> 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;
}

View file

@ -111,7 +111,9 @@ struct SendingErrorRequest {
not_null<Data::Thread*> thread,
SendingErrorRequest request);
[[nodiscard]] TextWithEntities DropCustomEmoji(TextWithEntities text);
[[nodiscard]] TextWithEntities DropDisallowedCustomEmoji(
not_null<PeerData*> to,
TextWithEntities text);
[[nodiscard]] Main::Session *SessionByUniqueId(uint64 sessionUniqueId);
[[nodiscard]] HistoryItem *MessageByGlobalId(GlobalMsgId globalId);

View file

@ -395,7 +395,7 @@ HistoryWidget::HistoryWidget(
InitMessageField(controller, _field, [=](
not_null<DocumentData*> 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({});

View file

@ -1572,7 +1572,8 @@ void ComposeControls::initField() {
}, _field->lifetime());
#endif // Q_OS_MAC
InitMessageField(_show, _field, [=](not_null<DocumentData*> 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<DocumentData*> 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);
}

View file

@ -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(

View file

@ -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

View file

@ -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),

View file

@ -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 <QtGui/QGuiApplication>
@ -301,6 +302,9 @@ void InnerWidget::fill() {
{
auto dividerContent = object_ptr<Ui::VerticalLayout>(inner);
dividerContent->add(object_ptr<Ui::FixedHeightWidget>(
dividerContent,
st::boostSkipTop));
Ui::FillBoostLimit(
fakeShowed->events(),
dividerContent.data(),

View file

@ -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<qint32>(RectPart::TopRight);
base::flat_map<QString, QString> appSoundOverrides;
base::flat_set<PeerId> groupStickersSectionHidden;
base::flat_set<PeerId> 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<Support::SwitchSettings>(
supportSwitch);
switch (uncheckedSupportSwitch) {

View file

@ -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<PeerId> _groupStickersSectionHidden;
base::flat_set<PeerId> _groupEmojiSectionHidden;
bool _hadLegacyCallsPeerToPeerNobody = false;
Data::AutoDownload::Full _autoDownload;
rpl::variable<bool> _archiveCollapsed = false;

View file

@ -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,

View file

@ -777,8 +777,6 @@ void FillBoostLimit(
container->add(object_ptr<Ui::FixedHeightWidget>(container, skip));
};
//addSkip(st::boostSkipTop);
const auto ratio = [=](BoostCounters counters) {
const auto min = counters.thisLevelBoosts;
const auto max = counters.nextLevelBoosts;