From ccea6ce4924228f86e6c60ccb641fba215bd6f6b Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 30 Aug 2021 16:11:50 +0300 Subject: [PATCH] Added animated indicator of choosing sticker action to chats list. --- Telegram/Resources/langs/lang.strings | 2 + Telegram/SourceFiles/api/api_send_progress.h | 1 + .../history/view/history_view_send_action.cpp | 6 +- .../ui/effects/send_action_animations.cpp | 134 ++++++++++++++++++ Telegram/lib_ui | 2 +- 5 files changed, 143 insertions(+), 2 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 387db2670..666223191 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1615,6 +1615,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_user_action_upload_photo" = "{user} is sending a photo"; "lng_send_action_upload_file" = "sending a file"; "lng_user_action_upload_file" = "{user} is sending a file"; +"lng_send_action_choose_sticker" = "choosing a sticker"; +"lng_user_action_choose_sticker" = "{user} is choosing a sticker"; "lng_unread_bar#one" = "{count} unread message"; "lng_unread_bar#other" = "{count} unread messages"; "lng_unread_bar_some" = "Unread messages"; diff --git a/Telegram/SourceFiles/api/api_send_progress.h b/Telegram/SourceFiles/api/api_send_progress.h index 511e25cc1..037edf6de 100644 --- a/Telegram/SourceFiles/api/api_send_progress.h +++ b/Telegram/SourceFiles/api/api_send_progress.h @@ -30,6 +30,7 @@ enum class SendProgressType { UploadFile, ChooseLocation, ChooseContact, + ChooseSticker, PlayGame, Speaking, }; diff --git a/Telegram/SourceFiles/history/view/history_view_send_action.cpp b/Telegram/SourceFiles/history/view/history_view_send_action.cpp index e4508cef1..0e72edd53 100644 --- a/Telegram/SourceFiles/history/view/history_view_send_action.cpp +++ b/Telegram/SourceFiles/history/view/history_view_send_action.cpp @@ -30,6 +30,7 @@ constexpr auto kStatusShowClientsideUploadPhoto = 6 * crl::time(1000); constexpr auto kStatusShowClientsideUploadFile = 6 * crl::time(1000); constexpr auto kStatusShowClientsideChooseLocation = 6 * crl::time(1000); constexpr auto kStatusShowClientsideChooseContact = 6 * crl::time(1000); +constexpr auto kStatusShowClientsideChooseSticker = 6 * crl::time(1000); constexpr auto kStatusShowClientsidePlayGame = 10 * crl::time(1000); constexpr auto kStatusShowClientsideSpeaking = 6 * crl::time(1000); @@ -107,7 +108,9 @@ bool SendActionPainter::updateNeedsAnimating( now + kStatusShowClientsideSpeaking); }, [&](const MTPDsendMessageHistoryImportAction &) { }, [&](const MTPDsendMessageChooseStickerAction &) { - // #TODO send_action + emplaceAction( + Type::ChooseSticker, + kStatusShowClientsideChooseSticker); }, [&](const MTPDsendMessageCancelAction &) { Unexpected("CancelAction here."); }); @@ -230,6 +233,7 @@ bool SendActionPainter::updateNeedsAnimating(crl::time now, bool force) { case Type::UploadFile: return name.isEmpty() ? tr::lng_send_action_upload_file(tr::now) : tr::lng_user_action_upload_file(tr::now, lt_user, name); case Type::ChooseLocation: case Type::ChooseContact: return name.isEmpty() ? tr::lng_typing(tr::now) : tr::lng_user_typing(tr::now, lt_user, name); + case Type::ChooseSticker: return name.isEmpty() ? tr::lng_send_action_choose_sticker(tr::now) : tr::lng_user_action_choose_sticker(tr::now, lt_user, name); default: break; }; return QString(); diff --git a/Telegram/SourceFiles/ui/effects/send_action_animations.cpp b/Telegram/SourceFiles/ui/effects/send_action_animations.cpp index 378b5a4b4..7caf43593 100644 --- a/Telegram/SourceFiles/ui/effects/send_action_animations.cpp +++ b/Telegram/SourceFiles/ui/effects/send_action_animations.cpp @@ -55,6 +55,9 @@ public: virtual ~Impl() = default; protected: + [[nodiscard]] int period() const { + return _period; + } [[nodiscard]] crl::time started() const { return _started; } @@ -401,6 +404,134 @@ void SpeakingAnimation::PaintFrame( drawRoundedRect(left, sideSize); } +class ChooseStickerAnimation : public SendActionAnimation::Impl { +public: + ChooseStickerAnimation() + : Impl(st::historySendActionChooseStickerDuration) + , _eye({ + .outWidth = float64(st::historySendActionChooseStickerEyeWidth), + .outHeight = float64(st::historySendActionChooseStickerEyeHeight), + .step = float64(st::historySendActionChooseStickerEyeStep), + .inLeftOffset = style::ConvertScale(1.5), + .inRightOffset = -style::ConvertScale(2.5) + + st::historySendActionChooseStickerEyeWidth, + .outXOffset = style::ConvertScale(1.5), + .outStrokeWidth = style::ConvertScale(0.8 * 1.3), + .inStrokeWidth = style::ConvertScale(1.2 * 1.3), + .inSize = style::ConvertScale(2.), + .minProgress = 0.3, + .outHeightOffset = 1.5, + }) { + } + + static const MetaData kMeta; + static std::unique_ptr create() { + return std::make_unique(); + } + const MetaData *metaData() const override { + return &kMeta; + } + + int width() const override { + return st::historySendActionChooseStickerPosition.x() + + 2 * (_eye.outWidth + _eye.step) + + _eye.step; + } + + void paint( + Painter &p, + style::color color, + int x, + int y, + int outerWidth, + crl::time now) override; +private: + const struct { + const float64 outWidth; + const float64 outHeight; + const float64 step; + const float64 inLeftOffset; + const float64 inRightOffset; + const float64 outXOffset; + const float64 outStrokeWidth; + const float64 inStrokeWidth; + const float64 inSize; + const float64 minProgress; + const float64 outHeightOffset; + } _eye; + +}; + +const ChooseStickerAnimation::MetaData ChooseStickerAnimation::kMeta = { + 0, + &ChooseStickerAnimation::create, +}; + +void ChooseStickerAnimation::paint( + Painter &p, + style::color color, + int x, + int y, + int outerWidth, + crl::time now) { + PainterHighQualityEnabler hq(p); + const auto frameMs = frameTime(now); + auto pen = color->p; + pen.setJoinStyle(Qt::RoundJoin); + pen.setCapStyle(Qt::RoundCap); + + const auto half = float64(period() / 2); + const auto increment = (frameMs < half) ? true : false; + // A double-progress within a period half. + const auto progress = (frameMs / (half / 2)) - (increment ? 0 : 2); + + const auto animationProgress = std::min(progress, 1.); + + const auto k = _eye.minProgress; + const auto pIn = anim::easeInCirc(1, std::min(animationProgress / k, 1.)); + const auto pInRev = 1. - pIn; + const auto pOut = anim::easeOutCirc(1., (animationProgress < k) + ? 0. + : (animationProgress - k) / (1. - k)); + + const auto inX = _eye.inLeftOffset * (increment ? pIn : pInRev) + + _eye.inRightOffset * (increment ? pInRev : pIn); + const auto inY = (_eye.outHeight - _eye.inSize) / 2.; + + const auto outLeft = _eye.outXOffset + * (increment + ? (1. - anim::easeOutCirc(1., progress / 2.)) + : anim::easeOutQuint(1., progress / 2.)); + + const auto outScaleOffset = (pIn - pOut) * _eye.outHeightOffset; + const auto top = st::historySendActionChooseStickerPosition.y() + y; + const auto left = st::historySendActionChooseStickerPosition.x() + + x + + outLeft; + + for (auto i = 0; i < 2; i++) { + const auto currentLeft = left + (_eye.outWidth + _eye.step) * i; + + pen.setWidthF(_eye.outStrokeWidth); + p.setPen(pen); + p.setBrush(Qt::NoBrush); + p.drawEllipse(QRectF( + currentLeft, + top + outScaleOffset, + _eye.outWidth, + _eye.outHeight - outScaleOffset)); + + pen.setWidthF(_eye.inStrokeWidth); + p.setPen(pen); + p.setBrush(color->b); + p.drawEllipse(QRectF( + currentLeft + inX, + top + inY, + _eye.inSize, + _eye.inSize)); + } +} + void CreateImplementationsMap() { if (Implementations) { return; @@ -426,6 +557,9 @@ void CreateImplementationsMap() { Implementations->insert(type, &UploadAnimation::kMeta); } Implementations->insert(Type::Speaking, &SpeakingAnimation::kMeta); + Implementations->insert( + Type::ChooseSticker, + &ChooseStickerAnimation::kMeta); } } // namespace diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 3c95a9187..2e3eef52f 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 3c95a9187194c07fda409f1ad1e142232bb82cbc +Subproject commit 2e3eef52f7eac3b804164bf91990baa75fffb818