From 7e2a49c1f9e9dcba1e6d92484db19d3779e7468b Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 9 Nov 2022 10:18:55 +0400 Subject: [PATCH] Fix possible crash in pinned bar destruction. --- .../SourceFiles/history/history_widget.cpp | 33 +++++++++++-------- Telegram/SourceFiles/history/history_widget.h | 2 ++ .../view/history_view_replies_section.cpp | 32 +++++++++++------- .../view/history_view_replies_section.h | 2 ++ 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index dc4b17bb50..dbf7ea21ed 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6193,20 +6193,15 @@ void HistoryWidget::checkPinnedBarState() { : currentPinnedId.msg; if (universalPinnedId == hiddenId) { if (_pinnedBar) { + _pinnedBar->setContent(rpl::single(Ui::MessageBarContent())); _pinnedTracker->reset(); - auto qobject = base::unique_qptr{ - Ui::WrapAsQObject(this, std::move(_pinnedBar)).get() - }; - auto destroyer = [this, object = std::move(qobject)]() mutable { - object = nullptr; - _pinnedBarHeight = 0; - updateHistoryGeometry(); - updateControlsGeometry(); - }; - base::call_delayed( - st::defaultMessageBar.duration, - this, - std::move(destroyer)); + _hidingPinnedBar = base::take(_pinnedBar); + const auto raw = _hidingPinnedBar.get(); + base::call_delayed(st::defaultMessageBar.duration, this, [=] { + if (_hidingPinnedBar.get() == raw) { + clearHidingPinnedBar(); + } + }); } return; } @@ -6214,6 +6209,7 @@ void HistoryWidget::checkPinnedBarState() { return; } + clearHidingPinnedBar(); _pinnedBar = std::make_unique(this, [=] { return controller()->isGifPausedAtLeastFor( Window::GifPauseReason::Any); @@ -6300,6 +6296,17 @@ void HistoryWidget::checkPinnedBarState() { } } +void HistoryWidget::clearHidingPinnedBar() { + if (!_hidingPinnedBar) { + return; + } + if (const auto delta = -_pinnedBarHeight) { + _pinnedBarHeight = 0; + setGeometryWithTopMoved(geometry(), delta); + } + _hidingPinnedBar = nullptr; +} + void HistoryWidget::checkMessagesTTL() { if (!_peer || !_peer->messagesTTL()) { if (_ttlInfo) { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 7939f91432..d8b236c813 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -487,6 +487,7 @@ private: void updatePinnedViewer(); void setupPinnedTracker(); void checkPinnedBarState(); + void clearHidingPinnedBar(); void refreshPinnedBarButton(bool many, HistoryItem *item); void checkLastPinnedClickedIdReset( int wasScrollTop, @@ -628,6 +629,7 @@ private: std::unique_ptr _pinnedTracker; std::unique_ptr _pinnedBar; + std::unique_ptr _hidingPinnedBar; int _pinnedBarHeight = 0; FullMsgId _pinnedClickedId; std::optional _minPinnedId; diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 59d60193e4..4b84057467 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -1569,19 +1569,15 @@ void RepliesWidget::checkPinnedBarState() { : currentPinnedId.msg; if (universalPinnedId == hiddenId) { if (_pinnedBar) { + _pinnedBar->setContent(rpl::single(Ui::MessageBarContent())); _pinnedTracker->reset(); - auto qobject = base::unique_qptr{ - Ui::WrapAsQObject(this, std::move(_pinnedBar)).get() - }; - auto destroyer = [this, object = std::move(qobject)]() mutable { - object = nullptr; - _pinnedBarHeight = 0; - updateControlsGeometry(); - }; - base::call_delayed( - st::defaultMessageBar.duration, - this, - std::move(destroyer)); + _hidingPinnedBar = base::take(_pinnedBar); + const auto raw = _hidingPinnedBar.get(); + base::call_delayed(st::defaultMessageBar.duration, this, [=] { + if (_hidingPinnedBar.get() == raw) { + clearHidingPinnedBar(); + } + }); } return; } @@ -1589,6 +1585,7 @@ void RepliesWidget::checkPinnedBarState() { return; } + clearHidingPinnedBar(); _pinnedBar = std::make_unique(this, [=] { return controller()->isGifPausedAtLeastFor( Window::GifPauseReason::Any); @@ -1671,6 +1668,17 @@ void RepliesWidget::checkPinnedBarState() { } } +void RepliesWidget::clearHidingPinnedBar() { + if (!_hidingPinnedBar) { + return; + } + if (const auto delta = -_pinnedBarHeight) { + _pinnedBarHeight = 0; + setGeometryWithTopMoved(geometry(), delta); + } + _hidingPinnedBar = nullptr; +} + void RepliesWidget::refreshPinnedBarButton(bool many, HistoryItem *item) { if (!_pinnedBar) { return; // It can be in process of hiding. diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index 3b5060e2a0..de4074ce2e 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -256,6 +256,7 @@ private: void updatePinnedViewer(); void setupPinnedTracker(); void checkPinnedBarState(); + void clearHidingPinnedBar(); void refreshPinnedBarButton(bool many, HistoryItem *item); void checkLastPinnedClickedIdReset( int wasScrollTop, @@ -332,6 +333,7 @@ private: std::unique_ptr _pinnedTracker; std::unique_ptr _pinnedBar; + std::unique_ptr _hidingPinnedBar; int _pinnedBarHeight = 0; FullMsgId _pinnedClickedId; std::optional _minPinnedId;