From d633860e1d74d52052d820b80d3357855433d9d1 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 8 Feb 2022 22:20:37 +0300 Subject: [PATCH] Added simple animation of static stickers sending. --- .../chat_helpers/stickers_list_widget.cpp | 41 +++++++++++++--- .../chat_helpers/stickers_list_widget.h | 5 ++ .../chat_helpers/tabbed_selector.h | 2 + .../history/history_inner_widget.cpp | 6 ++- .../SourceFiles/history/history_widget.cpp | 47 +++++++++++++++++-- Telegram/SourceFiles/history/history_widget.h | 5 +- .../message_sending_animation_controller.cpp | 2 +- 7 files changed, 96 insertions(+), 12 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 51c8c25c7..82cd8ce72 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -2468,15 +2468,21 @@ void StickersListWidget::fillContextMenu( return; } if (auto sticker = std::get_if<OverSticker>(&selected)) { - Assert(sticker->section >= 0 && sticker->section < sets.size()); - auto &set = sets[sticker->section]; - Assert(sticker->index >= 0 && sticker->index < set.stickers.size()); + const auto section = sticker->section; + const auto index = sticker->index; + Assert(section >= 0 && section < sets.size()); + auto &set = sets[section]; + Assert(index >= 0 && index < set.stickers.size()); const auto document = set.stickers[sticker->index].document; const auto send = [=](Api::SendOptions options) { - _chosen.fire_copy({ + _chosen.fire({ .document = document, - .options = options }); + .options = options, + .messageSendingFrom = options.scheduled + ? Ui::MessageSendingAnimationFrom() + : messageSentAnimationInfo(section, index, document), + }); }; SendMenu::FillSendMenu( menu, @@ -2512,6 +2518,23 @@ void StickersListWidget::fillContextMenu( } } +Ui::MessageSendingAnimationFrom StickersListWidget::messageSentAnimationInfo( + int section, + int index, + not_null<DocumentData*> document) { + const auto rect = stickerRect(section, index); + const auto size = ComputeStickerSize(document, boundingBoxSize()); + const auto innerPos = QPoint( + (rect.width() - size.width()) / 2, + (rect.height() - size.height()) / 2); + + return { + .localId = session().data().nextLocalMessageId(), + .globalStartGeometry = mapToGlobal( + QRect(rect.topLeft() + innerPos, size)), + }; +} + void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { _previewTimer.cancel(); @@ -2550,7 +2573,13 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { if (e->modifiers() & Qt::ControlModifier) { showStickerSetBox(document); } else { - _chosen.fire_copy({ .document = document }); + _chosen.fire({ + .document = document, + .messageSendingFrom = messageSentAnimationInfo( + sticker->section, + sticker->index, + document), + }); } } else if (auto set = std::get_if<OverSet>(&pressed)) { Assert(set->section >= 0 && set->section < sets.size()); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index c583f6d81..8c744f650 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -330,6 +330,11 @@ private: void showPreview(); + Ui::MessageSendingAnimationFrom messageSentAnimationInfo( + int section, + int index, + not_null<DocumentData*> document); + MTP::Sender _api; ChannelData *_megagroupSet = nullptr; uint64 _megagroupSetIdRequested = 0; diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index 256031dd5..280b74976 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_common.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" +#include "ui/effects/message_sending_animation_common.h" #include "ui/effects/panel_animation.h" #include "mtproto/sender.h" #include "base/object_ptr.h" @@ -56,6 +57,7 @@ public: struct FileChosen { not_null<DocumentData*> document; Api::SendOptions options; + Ui::MessageSendingAnimationFrom messageSendingFrom; }; struct PhotoChosen { not_null<PhotoData*> photo; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 63909882c..5c837c3b1 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "ui/toasts/common_toasts.h" #include "ui/effects/path_shift_gradient.h" +#include "ui/effects/message_sending_animation_controller.h" #include "ui/text/text_options.h" #include "ui/boxes/report_box.h" #include "ui/layers/generic_box.h" @@ -1017,9 +1018,12 @@ void HistoryInner::paintEvent(QPaintEvent *e) { QRect(0, hdrawtop, width(), clip.top() + clip.height())); context.translate(0, -top); p.translate(0, top); + const auto &sendingAnimation = _controller->sendingAnimation(); while (top < drawToY) { const auto height = view->height(); - if (context.clip.y() < height && hdrawtop < top + height) { + if ((context.clip.y() < height) + && (hdrawtop < top + height) + && !sendingAnimation.hasAnimatedMessage(view->data())) { context.reactionInfo = _reactionsManager->currentReactionPaintInfo(); context.outbg = view->hasOutLayout(); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 3f0601710..c48d91d68 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/shadow.h" #include "ui/effects/ripple_animation.h" +#include "ui/effects/message_sending_animation_controller.h" #include "ui/text/text_utilities.h" // Ui::Text::ToUpper #include "ui/text/format_values.h" #include "ui/chat/forward_options_box.h" @@ -996,7 +997,12 @@ void HistoryWidget::initTabbedSelector() { selector->fileChosen( ) | filter | rpl::start_with_next([=](Selector::FileChosen data) { - sendExistingDocument(data.document, data.options); + controller()->sendingAnimation().appendSending( + data.messageSendingFrom); + sendExistingDocument( + data.document, + data.options, + data.messageSendingFrom.localId); }, lifetime()); selector->photoChosen( @@ -5354,6 +5360,7 @@ void HistoryWidget::startItemRevealAnimations() { if (const auto view = item->mainView()) { if (const auto top = _list->itemTop(view); top >= 0) { if (const auto height = view->height()) { + startMessageSendingAnimation(item); if (!_itemRevealAnimations.contains(item)) { auto &animation = _itemRevealAnimations[item]; animation.startHeight = height; @@ -5374,6 +5381,38 @@ void HistoryWidget::startItemRevealAnimations() { } } +void HistoryWidget::startMessageSendingAnimation( + not_null<HistoryItem*> item) { + auto &sendingAnimation = controller()->sendingAnimation(); + if (!sendingAnimation.hasLocalMessage(item->fullId().msg)) { + return; + } + Assert(item->mainView() != nullptr); + Assert(item->mainView()->media() != nullptr); + + auto globalEndGeometry = rpl::merge( + _scroll->innerResizes() | rpl::to_empty, + session().data().newItemAdded() | rpl::to_empty, + geometryValue() | rpl::to_empty, + _scroll->geometryValue() | rpl::to_empty, + _list->geometryValue() | rpl::to_empty + ) | rpl::map([=] { + const auto view = item->mainView(); + const auto additional = (_list->height() == _scroll->height()) + ? view->height() + : 0; + return _list->mapToGlobal(view->innerGeometry().translated( + 0, + _list->itemTop(view) - additional)); + }); + + sendingAnimation.startAnimation({ + .globalEndGeometry = std::move(globalEndGeometry), + .item = item, + .theme = _list->theme(), + }); +} + void HistoryWidget::updateListSize() { Expects(_list != nullptr); @@ -6376,7 +6415,8 @@ void HistoryWidget::requestMessageData(MsgId msgId) { bool HistoryWidget::sendExistingDocument( not_null<DocumentData*> document, - Api::SendOptions options) { + Api::SendOptions options, + std::optional<MsgId> localId) { const auto error = _peer ? Data::RestrictionError(_peer, ChatRestriction::SendStickers) : std::nullopt; @@ -6393,7 +6433,8 @@ bool HistoryWidget::sendExistingDocument( Api::SendExistingDocument( Api::MessageToSend(prepareSendAction(options)), - document); + document, + localId); if (_fieldAutocomplete->stickersShown()) { clearFieldText(); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index e8cd71b5c..9c87e5660 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -264,7 +264,8 @@ public: [[nodiscard]] SendMenu::Type sendMenuType() const; bool sendExistingDocument( not_null<DocumentData*> document, - Api::SendOptions options); + Api::SendOptions options, + std::optional<MsgId> localId = std::nullopt); bool sendExistingPhoto( not_null<PhotoData*> photo, Api::SendOptions options); @@ -553,6 +554,8 @@ private: void startItemRevealAnimations(); void revealItemsCallback(); + void startMessageSendingAnimation(not_null<HistoryItem*> item); + // Does any of the shown histories has this flag set. bool hasPendingResizedItems() const; diff --git a/Telegram/SourceFiles/ui/effects/message_sending_animation_controller.cpp b/Telegram/SourceFiles/ui/effects/message_sending_animation_controller.cpp index 13091ad50..19b6a78aa 100644 --- a/Telegram/SourceFiles/ui/effects/message_sending_animation_controller.cpp +++ b/Telegram/SourceFiles/ui/effects/message_sending_animation_controller.cpp @@ -152,7 +152,7 @@ void Content::updateCache() { }); using Context = Ui::ChatPaintContext; context.skipDrawingParts = Context::SkipDrawingParts::Surrounding; - context.outbg = true; + context.outbg = _item->mainView()->hasOutLayout(); p.translate(-innerContentRect.left(), -innerContentRect.top()); _media->draw(p, context); }