From be16a7725c658e3e9f731655eacf53f7a8596ada Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 26 May 2022 12:30:50 +0400 Subject: [PATCH] Show premium stickers toast on double click. --- Telegram/CMakeLists.txt | 2 + Telegram/Resources/langs/lang.strings | 7 +- .../history/history_inner_widget.cpp | 7 +- .../SourceFiles/history/history_widget.cpp | 16 +++ Telegram/SourceFiles/history/history_widget.h | 4 + .../view/history_view_emoji_interactions.cpp | 7 +- .../view/history_view_emoji_interactions.h | 2 +- .../view/history_view_sticker_toast.cpp | 125 ++++++++++++++++++ .../history/view/history_view_sticker_toast.h | 46 +++++++ Telegram/SourceFiles/ui/chat/chat.style | 16 +++ Telegram/lib_ui | 2 +- 11 files changed, 224 insertions(+), 10 deletions(-) create mode 100644 Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp create mode 100644 Telegram/SourceFiles/history/view/history_view_sticker_toast.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 862a44dbe8..5df046df7d 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -692,6 +692,8 @@ PRIVATE history/view/history_view_service_message.h history/view/history_view_spoiler_click_handler.cpp history/view/history_view_spoiler_click_handler.h + history/view/history_view_sticker_toast.cpp + history/view/history_view_sticker_toast.h history/view/history_view_transcribe_button.cpp history/view/history_view_transcribe_button.h history/view/history_view_top_bar_widget.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 5f4149fd0f..138c2850c2 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -232,14 +232,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_sticker_premium_about" = "Unlock this sticker and more by subscribing to\nTelegram Premium."; "lng_sticker_premium_button" = "Unlock Premium Stickers"; +"lng_sticker_premium_title" = "With Effects"; +"lng_sticker_premium_text" = "This pack contains premium stickers like this one."; +"lng_sticker_premium_view" = "View"; "lng_flood_error" = "Too many tries. Please try again later."; "lng_gif_error" = "An error has occurred while reading GIF animation :("; "lng_edit_error" = "You cannot edit this message"; "lng_error_phone_flood" = "Sorry, you have deleted and re-created your account too many times recently. Please wait for a few days before signing up again."; "lng_error_start_minimized_passcoded" = "You have set a local passcode, so Telegram Desktop can't be launched minimised; it will ask you to enter your passcode before it can start working."; -"lng_error_pinned_max#one" = "Sorry, you can pin no more than {count} chat to the top."; -"lng_error_pinned_max#other" = "Sorry, you can pin no more than {count} chats to the top."; "lng_error_public_groups_denied" = "Unfortunately, you were banned from participating in public groups.\n{more_info}"; "lng_error_cant_add_member" = "Sorry, you can't add the bot to this group. Ask a group admin to do it."; "lng_error_cant_add_bot" = "Sorry, this bot can't be added to groups."; @@ -1661,8 +1662,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_stickers_description" = "You can choose a sticker set which will be available for every member while in the group chat."; "lng_group_stickers_add" = "Choose sticker set"; "lng_premium_stickers" = "Premium stickers"; -"lng_premium_unlock_button" = "Unlock Premium Stickers"; -"lng_premium_unlock_about" = "Unlock this sticker and more by subscribing to Telegram Premium."; "lng_premium" = "Premium"; "lng_premium_free" = "Free"; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 401e3d05ca..dad1a37fb7 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -3232,8 +3232,13 @@ void HistoryInner::elementStartInteraction(not_null view) { void HistoryInner::elementStartPremium( not_null view, Element *replacing) { - _emojiInteractions->playPremiumEffect(view, replacing); + const auto already = !_emojiInteractions->playPremiumEffect( + view, + replacing); _animatedStickersPlayed.emplace(view->data()); + if (already) { + _widget->showPremiumStickerTooltip(view); + } } void HistoryInner::elementCancelPremium(not_null view) { diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index c8b23f8417..cf4889be8a 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -98,6 +98,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_group_call_bar.h" #include "history/view/history_view_item_preview.h" #include "history/view/history_view_requests_bar.h" +#include "history/view/history_view_sticker_toast.h" #include "history/view/media/history_view_media.h" #include "profile/profile_block_group_members.h" #include "info/info_memento.h" @@ -6771,6 +6772,21 @@ void HistoryWidget::hideInfoTooltip(anim::type animated) { } } +void HistoryWidget::showPremiumStickerTooltip( + not_null view) { + if (const auto media = view->data()->media()) { + if (const auto document = media->document()) { + if (!_stickerToast) { + _stickerToast = std::make_unique( + controller(), + _scroll.data(), + [=] { _stickerToast = nullptr; }); + } + _stickerToast->showFor(document); + } + } +} + void HistoryWidget::setFieldText( const TextWithTags &textWithTags, TextUpdateEvents events, diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 67d5a86147..86c4689afb 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -102,6 +102,7 @@ enum class MimeDataState; } // namespace Storage namespace HistoryView { +class StickerToast; class TopBarWidget; class ContactStatus; class Element; @@ -277,6 +278,8 @@ public: const TextWithEntities &text, Fn hiddenCallback); void hideInfoTooltip(anim::type animated); + void showPremiumStickerTooltip( + not_null view); // Tabbed selector management. bool pushTabbedSelectorToThirdSection( @@ -798,6 +801,7 @@ private: base::Timer _saveCloudDraftTimer; base::weak_ptr _topToast; + std::unique_ptr _stickerToast; std::unique_ptr _chooseForReport; base::flat_set> _itemRevealPending; diff --git a/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp b/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp index 5e4774a5a3..b982c9d761 100644 --- a/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp +++ b/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp @@ -91,7 +91,7 @@ void EmojiInteractions::play( } } -void EmojiInteractions::playPremiumEffect( +bool EmojiInteractions::playPremiumEffect( not_null view, Element *replacing) { const auto already = ranges::contains(_plays, view, &Play::view); @@ -109,10 +109,10 @@ void EmojiInteractions::playPremiumEffect( //if (i->premium) { // view->externalLottieProgressing(true); //} - return; + return true; } } else if (already) { - return; + return false; } if (const auto media = view->media()) { if (const auto document = media->getDocument()) { @@ -128,6 +128,7 @@ void EmojiInteractions::playPremiumEffect( } } } + return true; } void EmojiInteractions::cancelPremiumEffect(not_null view) { diff --git a/Telegram/SourceFiles/history/view/history_view_emoji_interactions.h b/Telegram/SourceFiles/history/view/history_view_emoji_interactions.h index 4214af4bec..4d38f38ebf 100644 --- a/Telegram/SourceFiles/history/view/history_view_emoji_interactions.h +++ b/Telegram/SourceFiles/history/view/history_view_emoji_interactions.h @@ -37,7 +37,7 @@ public: void play( ChatHelpers::EmojiInteractionPlayRequest request, not_null view); - void playPremiumEffect( + bool playPremiumEffect( not_null view, Element *replacing); void cancelPremiumEffect(not_null view); diff --git a/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp b/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp new file mode 100644 index 0000000000..9605d25ac0 --- /dev/null +++ b/Telegram/SourceFiles/history/view/history_view_sticker_toast.cpp @@ -0,0 +1,125 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "history/view/history_view_sticker_toast.h" + +#include "ui/toast/toast.h" +#include "ui/toast/toast_widget.h" +#include "ui/widgets/buttons.h" +#include "data/data_document.h" +#include "data/data_document_media.h" +#include "lang/lang_keys.h" +#include "ui/text/text_utilities.h" +#include "boxes/sticker_set_box.h" +#include "lottie/lottie_single_player.h" +#include "window/window_session_controller.h" +#include "styles/style_chat.h" + +namespace HistoryView { +namespace { + +constexpr auto kPremiumToastDuration = 5 * crl::time(1000); + +} // namespace + +StickerToast::StickerToast( + not_null controller, + not_null parent, + Fn destroy) +: _controller(controller) +, _parent(parent) +, _destroy(std::move(destroy)) { +} + +StickerToast::~StickerToast() = default; + +void StickerToast::showFor(not_null document) { + const auto sticker = document->sticker(); + if (!sticker || sticker->type != StickerType::Tgs) { + return; + } else if (const auto strong = _weak.get()) { + if (_for == document) { + return; + } + strong->hideAnimated(); + } + _for = document; + + const auto text = Ui::Text::Bold( + tr::lng_sticker_premium_title(tr::now) + ).append('\n').append( + tr::lng_sticker_premium_text(tr::now) + ); + _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); + _st.padding.setLeft(skip + size + skip); + _st.padding.setRight(st::historyPremiumViewSet.font->width(view) + - st::historyPremiumViewSet.width); + _weak = Ui::Toast::Show(_parent, Ui::Toast::Config{ + .text = text, + .st = &_st, + .durationMs = kPremiumToastDuration, + .multiline = true, + .dark = true, + .slideSide = RectPart::Bottom, + }); + const auto strong = _weak.get(); + if (!strong) { + return; + } + strong->setInputUsed(true); + const auto widget = strong->widget(); + const auto button = Ui::CreateChild( + widget.get(), + rpl::single(view), + st::historyPremiumViewSet); + button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); + button->show(); + widget->widthValue( + ) | rpl::start_with_next([=](int width) { + button->moveToRight(0, 0, width); + }, widget->lifetime()); + const auto preview = Ui::CreateChild(widget.get()); + preview->moveToLeft(skip, skip); + preview->resize(size, size); + preview->show(); + + const auto bytes = document->createMediaView()->bytes(); + const auto filepath = document->filepath(); + const auto player = preview->lifetime().make_state( + Lottie::ReadContent(bytes, filepath), + Lottie::FrameRequest{ QSize(size, size) }, + Lottie::Quality::Default); + preview->paintRequest( + ) | rpl::start_with_next([=] { + if (!player->ready()) { + return; + } + const auto image = player->frame(); + QPainter(preview).drawImage( + QRect(QPoint(), image.size() / image.devicePixelRatio()), + image); + player->markFrameShown(); + }, preview->lifetime()); + player->updates( + ) | rpl::start_with_next([=] { + preview->update(); + }, preview->lifetime()); + + button->setClickedCallback([=, weak = _weak] { + _controller->show( + Box(_controller, document->sticker()->set), + Ui::LayerOption::KeepOther); + if (const auto strong = weak.get()) { + strong->hideAnimated(); + } + }); +} + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_sticker_toast.h b/Telegram/SourceFiles/history/view/history_view_sticker_toast.h new file mode 100644 index 0000000000..ef2a583522 --- /dev/null +++ b/Telegram/SourceFiles/history/view/history_view_sticker_toast.h @@ -0,0 +1,46 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "styles/style_widgets.h" + +namespace Ui { +class Show; +} // namespace Ui + +namespace Ui::Toast { +class Instance; +} // namespace Ui::Toast + +namespace Window { +class SessionController; +} // namespace Window + +namespace HistoryView { + +class StickerToast final { +public: + StickerToast( + not_null controller, + not_null parent, + Fn destroy); + ~StickerToast(); + + void showFor(not_null document); + +private: + const not_null _controller; + const not_null _parent; + style::Toast _st; + base::weak_ptr _weak; + DocumentData *_for = nullptr; + Fn _destroy; + +}; + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 5e766f47b5..bc656db83d 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -75,6 +75,22 @@ historyResizeWidth: 6px; historyPaddingBottom: 8px; +historyPremiumToast: Toast(defaultToast) { + minWidth: msgMinWidth; + maxWidth: 380px; + padding: margins(19px, 13px, 19px, 12px); +} +historyPremiumViewSet: RoundButton(defaultActiveButton) { + width: -24px; + height: 44px; + textTop: 13px; + textFg: mediaviewTextLinkFg; + textFgOver: mediaviewTextLinkFg; + textBg: transparent; + textBgOver: transparent; + ripple: emptyRippleAnimation; +} + historyToDownPosition: point(12px, 10px); historyToDownAbove: icon {{ "history_down_arrow", historyToDownFg }}; historyToDownAboveOver: icon {{ "history_down_arrow", historyToDownFgOver }}; diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 79af7c5523..a78089716b 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 79af7c5523ae59d4dd13cc2bde86bb8611bde11c +Subproject commit a78089716bf153b4283ec79757268d1047913f12