mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Show premium emoji toast / send to Saved Messages.
This commit is contained in:
parent
59903b0b1c
commit
f4b80d8714
16 changed files with 133 additions and 23 deletions
|
@ -233,6 +233,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_sticker_premium_text" = "This pack contains premium stickers like this one.";
|
||||
"lng_sticker_premium_view" = "View";
|
||||
"lng_animated_emoji_text" = "Subscribe to **Telegram Premium** to unlock this emoji.";
|
||||
"lng_animated_emoji_saved" = "Try sending these emoji in **Saved Messages** for free to test.";
|
||||
"lng_animated_emoji_saved_open" = "Open";
|
||||
"lng_reaction_premium_info" = "Click on the reaction to preview the animation.";
|
||||
"lng_reaction_premium_no_group" = "Some reactions are restricted in this group.";
|
||||
"lng_reaction_premium_no_channel" = "Some reactions are restricted in this channel.";
|
||||
|
@ -499,6 +501,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_settings_section_chat_settings" = "Chat Settings";
|
||||
"lng_settings_replace_emojis" = "Replace emoji";
|
||||
"lng_settings_suggest_emoji" = "Suggest emoji replacements";
|
||||
"lng_settings_suggest_animated_emoji" = "Suggest animated emoji";
|
||||
"lng_settings_suggest_by_emoji" = "Suggest popular stickers by emoji";
|
||||
"lng_settings_loop_stickers" = "Loop animated stickers";
|
||||
"lng_settings_large_emoji" = "Large emoji";
|
||||
|
|
|
@ -504,6 +504,7 @@ void EditCaptionBox::setupEmojiPanel() {
|
|||
) | rpl::start_with_next([=](Selector::FileChosen data) {
|
||||
Data::InsertCustomEmoji(_field.get(), data.document);
|
||||
}, lifetime());
|
||||
_emojiPanel->selector()->showPromoForPremiumEmoji();
|
||||
|
||||
const auto filterCallback = [=](not_null<QEvent*> event) {
|
||||
emojiFilterForGeometry(event);
|
||||
|
|
|
@ -746,6 +746,7 @@ void SendFilesBox::setupEmojiPanel() {
|
|||
) | rpl::start_with_next([=](Selector::FileChosen data) {
|
||||
Data::InsertCustomEmoji(_caption.data(), data.document);
|
||||
}, lifetime());
|
||||
_emojiPanel->selector()->showPromoForPremiumEmoji();
|
||||
|
||||
const auto filterCallback = [=](not_null<QEvent*> event) {
|
||||
emojiFilterForGeometry(event);
|
||||
|
|
|
@ -17,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/ui_utility.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout/layout_position.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -453,6 +452,11 @@ auto EmojiListWidget::customChosen() const
|
|||
return _customChosen.events();
|
||||
}
|
||||
|
||||
auto EmojiListWidget::premiumChosen() const
|
||||
-> rpl::producer<not_null<DocumentData*>> {
|
||||
return _premiumChosen.events();
|
||||
}
|
||||
|
||||
void EmojiListWidget::visibleTopBottomUpdated(
|
||||
int visibleTop,
|
||||
int visibleBottom) {
|
||||
|
@ -1026,13 +1030,7 @@ void EmojiListWidget::selectCustom(not_null<DocumentData*> document) {
|
|||
if (document->isPremiumEmoji()
|
||||
&& !document->session().premium()
|
||||
&& !_allowWithoutPremium) {
|
||||
ShowPremiumPreviewBox(
|
||||
controller(),
|
||||
PremiumPreview::AnimatedEmoji,
|
||||
{},
|
||||
crl::guard(this, [=](not_null<Ui::BoxContent*> box) {
|
||||
checkHideWithBox(box.get());
|
||||
}));
|
||||
_premiumChosen.fire_copy(document);
|
||||
return;
|
||||
}
|
||||
Core::App().settings().incrementRecentEmoji({ RecentEmojiDocument{
|
||||
|
|
|
@ -82,6 +82,8 @@ public:
|
|||
[[nodiscard]] rpl::producer<EmojiPtr> chosen() const;
|
||||
[[nodiscard]] auto customChosen() const
|
||||
-> rpl::producer<TabbedSelector::FileChosen>;
|
||||
[[nodiscard]] auto premiumChosen() const
|
||||
-> rpl::producer<not_null<DocumentData*>>;
|
||||
|
||||
protected:
|
||||
void visibleTopBottomUpdated(
|
||||
|
@ -298,6 +300,7 @@ private:
|
|||
|
||||
rpl::event_stream<EmojiPtr> _chosen;
|
||||
rpl::event_stream<TabbedSelector::FileChosen> _customChosen;
|
||||
rpl::event_stream<not_null<DocumentData*>> _premiumChosen;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -111,7 +111,9 @@ auto SuggestionsWidget::appendCustom(std::vector<Row> rows)
|
|||
|
||||
auto SuggestionsWidget::lookupCustom(const std::vector<Row> &rows) const
|
||||
-> base::flat_multi_map<int, Custom> {
|
||||
if (rows.empty() || !_suggestCustomEmoji) {
|
||||
if (rows.empty()
|
||||
|| !_suggestCustomEmoji
|
||||
|| !Core::App().settings().suggestAnimatedEmoji()) {
|
||||
return {};
|
||||
}
|
||||
auto custom = base::flat_multi_map<int, Custom>();
|
||||
|
|
|
@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_changes.h"
|
||||
#include "data/stickers/data_stickers.h"
|
||||
#include "data/stickers/data_custom_emoji.h" // AllowEmojiWithoutPremium.
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "mainwindow.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -491,6 +492,11 @@ auto TabbedSelector::customEmojiChosen() const -> rpl::producer<FileChosen> {
|
|||
return emoji()->customChosen();
|
||||
}
|
||||
|
||||
auto TabbedSelector::premiumEmojiChosen() const
|
||||
-> rpl::producer<not_null<DocumentData*>> {
|
||||
return emoji()->premiumChosen();
|
||||
}
|
||||
|
||||
auto TabbedSelector::fileChosen() const -> rpl::producer<FileChosen> {
|
||||
auto never = rpl::never<TabbedSelector::FileChosen>(
|
||||
) | rpl::type_erased();
|
||||
|
@ -844,6 +850,16 @@ void TabbedSelector::setCurrentPeer(PeerData *peer) {
|
|||
peer && Data::AllowEmojiWithoutPremium(peer));
|
||||
}
|
||||
|
||||
void TabbedSelector::showPromoForPremiumEmoji() {
|
||||
premiumEmojiChosen(
|
||||
) | rpl::start_with_next([=] {
|
||||
ShowPremiumPreviewBox(
|
||||
_controller,
|
||||
PremiumPreview::AnimatedEmoji,
|
||||
{});
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void TabbedSelector::checkRestrictedPeer() {
|
||||
if (_currentPeer) {
|
||||
const auto error = (_currentTabType == SelectorTab::Stickers)
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
|
||||
rpl::producer<EmojiPtr> emojiChosen() const;
|
||||
rpl::producer<FileChosen> customEmojiChosen() const;
|
||||
rpl::producer<not_null<DocumentData*>> premiumEmojiChosen() const;
|
||||
rpl::producer<FileChosen> fileChosen() const;
|
||||
rpl::producer<PhotoChosen> photoChosen() const;
|
||||
rpl::producer<InlineChosen> inlineResultChosen() const;
|
||||
|
@ -102,6 +103,7 @@ public:
|
|||
void setRoundRadius(int radius);
|
||||
void refreshStickers();
|
||||
void setCurrentPeer(PeerData *peer);
|
||||
void showPromoForPremiumEmoji();
|
||||
|
||||
void hideFinished();
|
||||
void showStarted();
|
||||
|
|
|
@ -137,8 +137,7 @@ QByteArray Settings::serialize() const {
|
|||
+ sizeof(qint64)
|
||||
+ sizeof(qint32) * 2
|
||||
+ Serialize::bytearraySize(windowPosition)
|
||||
+ sizeof(qint32) * 2
|
||||
+ (_accountsOrder.size() * sizeof(quint64));
|
||||
+ sizeof(qint32);
|
||||
for (const auto &[id, rating] : recentEmojiPreloadData) {
|
||||
size += Serialize::stringSize(id) + sizeof(quint16);
|
||||
}
|
||||
|
@ -152,6 +151,8 @@ QByteArray Settings::serialize() const {
|
|||
+ Serialize::bytearraySize(_photoEditorBrush)
|
||||
+ sizeof(qint32) * 3
|
||||
+ Serialize::stringSize(_customDeviceModel.current())
|
||||
+ sizeof(qint32) * 4
|
||||
+ (_accountsOrder.size() * sizeof(quint64))
|
||||
+ sizeof(qint32) * 4;
|
||||
|
||||
auto result = QByteArray();
|
||||
|
@ -264,7 +265,8 @@ QByteArray Settings::serialize() const {
|
|||
stream
|
||||
<< qint32(0) // old hardwareAcceleratedVideo
|
||||
<< qint32(_chatQuickAction)
|
||||
<< qint32(_hardwareAcceleratedVideo ? 1 : 0);
|
||||
<< qint32(_hardwareAcceleratedVideo ? 1 : 0)
|
||||
<< qint32(_suggestAnimatedEmoji ? 1 : 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -356,6 +358,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
std::vector<uint64> accountsOrder;
|
||||
qint32 hardwareAcceleratedVideo = _hardwareAcceleratedVideo ? 1 : 0;
|
||||
qint32 chatQuickAction = static_cast<qint32>(_chatQuickAction);
|
||||
qint32 suggestAnimatedEmoji = _suggestAnimatedEmoji ? 1 : 0;
|
||||
|
||||
stream >> themesAccentColors;
|
||||
if (!stream.atEnd()) {
|
||||
|
@ -547,6 +550,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
if (!stream.atEnd()) {
|
||||
stream >> hardwareAcceleratedVideo;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
stream >> suggestAnimatedEmoji;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||
|
@ -714,6 +720,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
case Quick::React: _chatQuickAction = uncheckedChatQuickAction; break;
|
||||
}
|
||||
}
|
||||
_suggestAnimatedEmoji = (suggestAnimatedEmoji == 1);
|
||||
}
|
||||
|
||||
QString Settings::getSoundPath(const QString &key) const {
|
||||
|
@ -986,6 +993,7 @@ void Settings::resetOnLastLogout() {
|
|||
_replaceEmoji = true;
|
||||
_suggestEmoji = true;
|
||||
_suggestStickersByEmoji = true;
|
||||
_suggestAnimatedEmoji = true;
|
||||
_spellcheckerEnabled = true;
|
||||
_videoPlaybackSpeed = 1.;
|
||||
_voicePlaybackSpeed = 1.;
|
||||
|
|
|
@ -404,6 +404,12 @@ public:
|
|||
void setSuggestStickersByEmoji(bool value) {
|
||||
_suggestStickersByEmoji = value;
|
||||
}
|
||||
[[nodiscard]] bool suggestAnimatedEmoji() const {
|
||||
return _suggestAnimatedEmoji;
|
||||
}
|
||||
void setSuggestAnimatedEmoji(bool value) {
|
||||
_suggestAnimatedEmoji = value;
|
||||
}
|
||||
|
||||
void setSpellcheckerEnabled(bool value) {
|
||||
_spellcheckerEnabled = value;
|
||||
|
@ -775,6 +781,7 @@ private:
|
|||
rpl::variable<bool> _replaceEmoji = true;
|
||||
bool _suggestEmoji = true;
|
||||
bool _suggestStickersByEmoji = true;
|
||||
bool _suggestAnimatedEmoji = true;
|
||||
rpl::variable<bool> _spellcheckerEnabled = true;
|
||||
rpl::variable<float64> _videoPlaybackSpeed = 1.;
|
||||
float64 _voicePlaybackSpeed = 2.;
|
||||
|
|
|
@ -1078,6 +1078,13 @@ void HistoryWidget::initTabbedSelector() {
|
|||
Data::InsertCustomEmoji(_field.data(), data.document);
|
||||
}, lifetime());
|
||||
|
||||
selector->premiumEmojiChosen(
|
||||
) | rpl::filter([=] {
|
||||
return !isHidden() && !_field->isHidden();
|
||||
}) | rpl::start_with_next([=](not_null<DocumentData*> document) {
|
||||
showPremiumToast(document);
|
||||
}, lifetime());
|
||||
|
||||
selector->fileChosen(
|
||||
) | filter | rpl::start_with_next([=](Selector::FileChosen data) {
|
||||
controller()->sendingAnimation().appendSending(
|
||||
|
@ -5004,7 +5011,6 @@ bool HistoryWidget::confirmSendingFiles(
|
|||
const auto position = cursor.position();
|
||||
const auto anchor = cursor.anchor();
|
||||
const auto text = _field->getTextWithTags();
|
||||
using SendLimit = SendFilesBox::SendLimit;
|
||||
auto box = Box<SendFilesBox>(
|
||||
controller(),
|
||||
std::move(list),
|
||||
|
@ -6763,7 +6769,7 @@ void HistoryWidget::showPremiumToast(not_null<DocumentData*> document) {
|
|||
if (!_stickerToast) {
|
||||
_stickerToast = std::make_unique<HistoryView::StickerToast>(
|
||||
controller(),
|
||||
_scroll.data(),
|
||||
this,
|
||||
[=] { _stickerToast = nullptr; });
|
||||
}
|
||||
_stickerToast->showFor(document);
|
||||
|
|
|
@ -1850,6 +1850,13 @@ void ComposeControls::initTabbedSelector() {
|
|||
Data::InsertCustomEmoji(_field, data.document);
|
||||
}, wrap->lifetime());
|
||||
|
||||
selector->premiumEmojiChosen(
|
||||
) | rpl::start_with_next([=](not_null<DocumentData*> document) {
|
||||
if (_unavailableEmojiPasted) {
|
||||
_unavailableEmojiPasted(document);
|
||||
}
|
||||
}, wrap->lifetime());
|
||||
|
||||
selector->fileChosen(
|
||||
) | rpl::start_to_stream(_fileChosen, wrap->lifetime());
|
||||
|
||||
|
|
|
@ -742,7 +742,6 @@ bool RepliesWidget::confirmSendingFiles(
|
|||
return false;
|
||||
}
|
||||
|
||||
using SendLimit = SendFilesBox::SendLimit;
|
||||
auto box = Box<SendFilesBox>(
|
||||
controller(),
|
||||
std::move(list),
|
||||
|
@ -2049,7 +2048,7 @@ void RepliesWidget::listShowPremiumToast(not_null<DocumentData*> document) {
|
|||
if (!_stickerToast) {
|
||||
_stickerToast = std::make_unique<HistoryView::StickerToast>(
|
||||
controller(),
|
||||
_scroll.get(),
|
||||
this,
|
||||
[=] { _stickerToast = nullptr; });
|
||||
}
|
||||
_stickerToast->showFor(document);
|
||||
|
|
|
@ -400,7 +400,6 @@ bool ScheduledWidget::confirmSendingFiles(
|
|||
return false;
|
||||
}
|
||||
|
||||
using SendLimit = SendFilesBox::SendLimit;
|
||||
auto box = Box<SendFilesBox>(
|
||||
controller(),
|
||||
std::move(list),
|
||||
|
@ -1367,7 +1366,7 @@ void ScheduledWidget::listShowPremiumToast(
|
|||
if (!_stickerToast) {
|
||||
_stickerToast = std::make_unique<HistoryView::StickerToast>(
|
||||
controller(),
|
||||
_scroll.data(),
|
||||
this,
|
||||
[=] { _stickerToast = nullptr; });
|
||||
}
|
||||
_stickerToast->showFor(document);
|
||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "lang/lang_keys.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "boxes/sticker_set_box.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "lottie/lottie_single_player.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -120,19 +121,25 @@ void StickerToast::cancelRequest() {
|
|||
void StickerToast::showWithTitle(const QString &title) {
|
||||
Expects(_for != nullptr);
|
||||
|
||||
static auto counter = 0;
|
||||
const auto setType = _for->sticker()->setType;
|
||||
const auto isEmoji = (setType == Data::StickersType::Emoji);
|
||||
const auto toSaved = isEmoji && !(++counter % 2);
|
||||
const auto text = Ui::Text::Bold(
|
||||
title
|
||||
).append('\n').append(
|
||||
(isEmoji
|
||||
(toSaved
|
||||
? tr::lng_animated_emoji_saved(tr::now, Ui::Text::RichLangValue)
|
||||
: isEmoji
|
||||
? tr::lng_animated_emoji_text(tr::now, Ui::Text::RichLangValue)
|
||||
: tr::lng_sticker_premium_text(tr::now, Ui::Text::RichLangValue))
|
||||
);
|
||||
_st = st::historyPremiumToast;
|
||||
const auto skip = _st.padding.top();
|
||||
const auto size = _st.style.font->height * 2;
|
||||
const auto view = tr::lng_sticker_premium_view(tr::now);
|
||||
const auto view = toSaved
|
||||
? tr::lng_animated_emoji_saved_open(tr::now)
|
||||
: tr::lng_sticker_premium_view(tr::now);
|
||||
_st.padding.setLeft(skip + size + skip);
|
||||
_st.padding.setRight(st::historyPremiumViewSet.font->width(view)
|
||||
- st::historyPremiumViewSet.width);
|
||||
|
@ -194,9 +201,27 @@ void StickerToast::showWithTitle(const QString &title) {
|
|||
setupLottiePreview(preview, size);
|
||||
}
|
||||
button->setClickedCallback([=] {
|
||||
_controller->show(
|
||||
Box<StickerSetBox>(_controller, _for->sticker()->set, setType),
|
||||
Ui::LayerOption::KeepOther);
|
||||
if (toSaved) {
|
||||
_controller->showPeerHistory(
|
||||
_controller->session().userPeerId(),
|
||||
Window::SectionShow::Way::Forward);
|
||||
hideToast();
|
||||
return;
|
||||
}
|
||||
const auto id = _for->sticker()->set.id;
|
||||
const auto &sets = _for->owner().stickers().sets();
|
||||
const auto i = sets.find(id);
|
||||
if (i != end(sets)
|
||||
&& (i->second->flags & Data::StickersSetFlag::Installed)) {
|
||||
ShowPremiumPreviewBox(
|
||||
_controller,
|
||||
PremiumPreview::AnimatedEmoji);
|
||||
} else {
|
||||
_controller->show(Box<StickerSetBox>(
|
||||
_controller,
|
||||
_for->sticker()->set,
|
||||
setType));
|
||||
}
|
||||
hideToast();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_cloud_themes.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_message_reactions.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "chat_helpers/emoji_sets_manager.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "platform/platform_specific.h"
|
||||
|
@ -710,6 +711,21 @@ void SetupStickersEmoji(
|
|||
std::move(handle),
|
||||
inner->lifetime());
|
||||
};
|
||||
const auto addSliding = [&](
|
||||
const QString &label,
|
||||
bool checked,
|
||||
auto &&handle,
|
||||
rpl::producer<bool> shown) {
|
||||
inner->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
|
||||
inner,
|
||||
checkbox(label, checked),
|
||||
st::settingsCheckboxPadding)
|
||||
)->setDuration(0)->toggleOn(std::move(shown))->entity()->checkedChanges(
|
||||
) | rpl::start_with_next(
|
||||
std::move(handle),
|
||||
inner->lifetime());
|
||||
};
|
||||
|
||||
add(
|
||||
tr::lng_settings_large_emoji(tr::now),
|
||||
|
@ -727,14 +743,31 @@ void SetupStickersEmoji(
|
|||
Core::App().saveSettingsDelayed();
|
||||
});
|
||||
|
||||
const auto suggestEmoji = inner->lifetime().make_state<
|
||||
rpl::variable<bool>
|
||||
>(Core::App().settings().suggestEmoji());
|
||||
add(
|
||||
tr::lng_settings_suggest_emoji(tr::now),
|
||||
Core::App().settings().suggestEmoji(),
|
||||
[=](bool checked) {
|
||||
*suggestEmoji = checked;
|
||||
Core::App().settings().setSuggestEmoji(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
});
|
||||
|
||||
using namespace rpl::mappers;
|
||||
addSliding(
|
||||
tr::lng_settings_suggest_animated_emoji(tr::now),
|
||||
Core::App().settings().suggestAnimatedEmoji(),
|
||||
[=](bool checked) {
|
||||
Core::App().settings().setSuggestAnimatedEmoji(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
},
|
||||
rpl::combine(
|
||||
Data::AmPremiumValue(session),
|
||||
suggestEmoji->value(),
|
||||
_1 && _2));
|
||||
|
||||
add(
|
||||
tr::lng_settings_suggest_by_emoji(tr::now),
|
||||
Core::App().settings().suggestStickersByEmoji(),
|
||||
|
|
Loading…
Add table
Reference in a new issue