mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Implement free megagroup emoji set.
This commit is contained in:
parent
08efa73b2b
commit
571f1a5179
25 changed files with 317 additions and 69 deletions
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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({});
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue