From 6bd530182879337ab1ba50769e465392f23391ae Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 9 Mar 2018 14:44:42 +0300 Subject: [PATCH] Fix crash when accessing a deleted item view. --- .../SourceFiles/data/data_peer_values.cpp | 4 ++-- Telegram/SourceFiles/data/data_session.cpp | 8 +++++++ Telegram/SourceFiles/data/data_session.h | 3 +++ .../history/history_inner_widget.cpp | 22 ++++++++++++++++--- .../history/history_inner_widget.h | 1 + Telegram/SourceFiles/history/history_item.cpp | 1 + 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp index 8d55136e4..2f3e849a8 100644 --- a/Telegram/SourceFiles/data/data_peer_values.cpp +++ b/Telegram/SourceFiles/data/data_peer_values.cpp @@ -21,7 +21,7 @@ int OnlinePhraseChangeInSeconds(TimeId online, TimeId now) { if (-online > now) { return (-online - now); } - return std::numeric_limits::max(); + return std::numeric_limits::max(); } if (online > now) { return online - now; @@ -36,7 +36,7 @@ int OnlinePhraseChangeInSeconds(TimeId online, TimeId now) { } const auto nowFull = ParseDateTime(now); const auto tomorrow = QDateTime(nowFull.date().addDays(1)); - return static_cast(nowFull.secsTo(tomorrow)); + return std::max(static_cast(nowFull.secsTo(tomorrow)), 0); } base::optional OnlineTextSpecial(not_null user) { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 5f670542a..2a42fadd2 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -273,6 +273,14 @@ rpl::producer> Session::itemRemoved() const { return _itemRemoved.events(); } +void Session::notifyViewRemoved(not_null view) { + _viewRemoved.fire_copy(view); +} + +rpl::producer> Session::viewRemoved() const { + return _viewRemoved.events(); +} + void Session::notifyHistoryUnloaded(not_null history) { _historyUnloaded.fire_copy(history); } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 58e88a4ca..11ce8b635 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -87,6 +87,8 @@ public: void notifyItemRemoved(not_null item); [[nodiscard]] rpl::producer> itemRemoved() const; + void notifyViewRemoved(not_null view); + [[nodiscard]] rpl::producer> viewRemoved() const; void notifyHistoryCleared(not_null history); [[nodiscard]] rpl::producer> historyCleared() const; void notifyHistoryChangeDelayed(not_null history); @@ -468,6 +470,7 @@ private: rpl::event_stream> _itemViewRefreshRequest; rpl::event_stream> _animationPlayInlineRequest; rpl::event_stream> _itemRemoved; + rpl::event_stream> _viewRemoved; rpl::event_stream> _historyUnloaded; rpl::event_stream> _historyCleared; base::flat_set> _historiesChanged; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 0d7b8d1c1..3c0068a8f 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -139,10 +139,14 @@ HistoryInner::HistoryInner( ) | rpl::start_with_next( [this](auto item) { itemRemoved(item); }, lifetime()); + Auth().data().viewRemoved( + ) | rpl::start_with_next( + [this](auto view) { viewRemoved(view); }, + lifetime()); Auth().data().itemViewRefreshRequest( - ) | rpl::start_with_next([this](auto item) { - refreshView(item); - }, lifetime()); + ) | rpl::start_with_next( + [this](auto item) { refreshView(item); }, + lifetime()); rpl::merge( Auth().data().historyUnloaded(), Auth().data().historyCleared() @@ -1222,6 +1226,18 @@ void HistoryInner::itemRemoved(not_null item) { mouseActionUpdate(); } +void HistoryInner::viewRemoved(not_null view) { + if (_dragSelFrom == view) { + _dragSelFrom = nullptr; + } + if (_dragSelTo == view) { + _dragSelTo = nullptr; + } + if (_scrollDateLastItem == view) { + _scrollDateLastItem = nullptr; + } +} + void HistoryInner::refreshView(not_null item) { const auto dragSelFrom = (_dragSelFrom && _dragSelFrom->data() == item); const auto dragSelTo = (_dragSelTo && _dragSelTo->data() == item); diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index d430769d4..e8eec987d 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -214,6 +214,7 @@ private: void toggleFavedSticker(not_null document); void itemRemoved(not_null item); + void viewRemoved(not_null view); void refreshView(not_null item); void touchResetSpeed(); diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 71014e4e6..39f6d5da7 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -268,6 +268,7 @@ void HistoryItem::refreshMainView() { void HistoryItem::removeMainView() { if (const auto view = mainView()) { Auth().data().notifyHistoryChangeDelayed(_history); + Auth().data().notifyViewRemoved(view); view->removeFromBlock(); } }