From e5de8e22b773538fd0252d14904cda876d3638b4 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 10 Jun 2025 18:25:35 +0400 Subject: [PATCH] Add fireworks on ending a task list. --- .../view/media/history_view_todo_list.cpp | 25 +++++++++++++++++++ .../view/media/history_view_todo_list.h | 8 ++++++ 2 files changed, 33 insertions(+) diff --git a/Telegram/SourceFiles/history/view/media/history_view_todo_list.cpp b/Telegram/SourceFiles/history/view/media/history_view_todo_list.cpp index ae40429964..e061a65bb4 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_todo_list.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_todo_list.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animations.h" #include "ui/effects/radial_animation.h" #include "ui/effects/ripple_animation.h" +#include "ui/effects/fireworks_animation.h" #include "ui/toast/toast.h" #include "ui/painter.h" #include "data/data_media_types.h" @@ -276,14 +277,19 @@ void TodoList::updateTasks(bool skipAnimations) { &Task::id, &TodoListItem::id); if (!changed) { + auto animated = false; auto &&tasks = ranges::views::zip(_tasks, _todolist->items); for (auto &&[task, original] : tasks) { const auto wasDate = task.completionDate; task.fillData(_todolist, original, context); if (!skipAnimations && (!wasDate != !task.completionDate)) { startToggleAnimation(task); + animated = true; } } + if (animated) { + maybeStartFireworks(); + } return; } _tasks = ranges::views::all( @@ -337,6 +343,15 @@ void TodoList::toggleCompletion(int id) { _parent->data()->fullId(), id, !selected); + + maybeStartFireworks(); +} + +void TodoList::maybeStartFireworks() { + if (!ranges::contains(_tasks, TimeId(), &Task::completionDate)) { + _fireworksAnimation = std::make_unique( + [=] { repaint(); }); + } } void TodoList::updateCompletionStatus() { @@ -625,6 +640,16 @@ TextState TodoList::textState(QPoint point, StateRequest request) const { return result; } +void TodoList::paintBubbleFireworks( + Painter &p, + const QRect &bubble, + crl::time ms) const { + if (!_fireworksAnimation || _fireworksAnimation->paint(p, bubble)) { + return; + } + _fireworksAnimation = nullptr; +} + void TodoList::clickHandlerPressedChanged( const ClickHandlerPtr &handler, bool pressed) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_todo_list.h b/Telegram/SourceFiles/history/view/media/history_view_todo_list.h index d0f25638b0..bc6e5ee08a 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_todo_list.h +++ b/Telegram/SourceFiles/history/view/media/history_view_todo_list.h @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Ui { class RippleAnimation; +class FireworksAnimation; } // namespace Ui namespace HistoryView { @@ -51,6 +52,11 @@ public: uint16 fullSelectionLength() const override; TextForMimeData selectedText(TextSelection selection) const override; + void paintBubbleFireworks( + Painter &p, + const QRect &bubble, + crl::time ms) const override; + void clickHandlerPressedChanged( const ClickHandlerPtr &handler, bool pressed) override; @@ -80,6 +86,7 @@ private: void updateTasks(bool skipAnimations); void startToggleAnimation(Task &task); void updateCompletionStatus(); + void maybeStartFireworks(); void setupPreviousState(const std::vector &info); int paintTask( @@ -122,6 +129,7 @@ private: std::vector _tasks; Ui::Text::String _completionStatusLabel; + mutable std::unique_ptr _fireworksAnimation; mutable QPoint _lastLinkPoint; mutable QImage _userpicCircleCache; mutable QImage _fillingIconCache;