From a1be63f8901c115e1d6c1326dfee6465bddf2c6d Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 22 Feb 2018 02:59:56 +0300 Subject: [PATCH] Jump to date by date click in feed. --- Telegram/SourceFiles/apiwrap.cpp | 1 + .../history/feed/history_feed_section.cpp | 9 ++ .../history/feed/history_feed_section.h | 7 +- .../history/view/history_view_list_widget.cpp | 116 ++++++++++++++---- .../history/view/history_view_list_widget.h | 3 + .../SourceFiles/window/window_controller.cpp | 2 +- 6 files changed, 115 insertions(+), 23 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 4de24bd0d..9ff67b82e 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2756,6 +2756,7 @@ void ApiWrap::requestMessageAfterDate( void ApiWrap::jumpToFeedDate(not_null feed, const QDate &date) { requestMessageAfterDate(feed, date, [=](Data::MessagePosition result) { + Ui::hideLayer(); App::wnd()->controller()->showSection( HistoryFeed::Memento(feed, result)); }); diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.cpp b/Telegram/SourceFiles/history/feed/history_feed_section.cpp index 19616d83b..98fa109c5 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.cpp +++ b/Telegram/SourceFiles/history/feed/history_feed_section.cpp @@ -437,6 +437,15 @@ void Widget::listContentRefreshed() { } } +ClickHandlerPtr Widget::listDateLink(not_null view) { + if (!_dateLink) { + _dateLink = std::make_shared(_feed, view->dateTime().date()); + } else { + _dateLink->setDate(view->dateTime().date()); + } + return _dateLink; +} + std::unique_ptr Widget::createMemento() { auto result = std::make_unique(_feed); saveState(result.get()); diff --git a/Telegram/SourceFiles/history/feed/history_feed_section.h b/Telegram/SourceFiles/history/feed/history_feed_section.h index 2122d7eb8..75726b7e5 100644 --- a/Telegram/SourceFiles/history/feed/history_feed_section.h +++ b/Telegram/SourceFiles/history/feed/history_feed_section.h @@ -27,6 +27,10 @@ class TopBarWidget; class Element; } // namespace HistoryView +namespace Window { +class DateClickHandler; +} // namespace Window + namespace HistoryFeed { class Memento; @@ -85,6 +89,7 @@ public: base::optional listUnreadBarView( const std::vector> &elements) override; void listContentRefreshed() override; + ClickHandlerPtr listDateLink(not_null view) override; protected: void resizeEvent(QResizeEvent *e) override; @@ -136,7 +141,7 @@ private: Animation _scrollDownShown; bool _scrollDownIsShown = false; object_ptr _scrollDown; - + std::shared_ptr _dateLink; }; diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 7cda2aa20..72ad0e8e0 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -621,7 +621,9 @@ void ListWidget::scrollDateCheck() { void ListWidget::scrollDateHideByTimer() { _scrollDateHideTimer.cancel(); - scrollDateHide(); + if (!_scrollDateLink || ClickHandler::getPressed() != _scrollDateLink) { + scrollDateHide(); + } } void ListWidget::scrollDateHide() { @@ -630,6 +632,15 @@ void ListWidget::scrollDateHide() { } } +void ListWidget::keepScrollDateForNow() { + if (!_scrollDateShown + && _scrollDateLastItem + && _scrollDateOpacity.animating()) { + toggleScrollDateShown(); + } + _scrollDateHideTimer.callOnce(kScrollDateHideTimeout); +} + void ListWidget::toggleScrollDateShown() { _scrollDateShown = !_scrollDateShown; auto from = _scrollDateShown ? 0. : 1.; @@ -1602,10 +1613,20 @@ void ListWidget::mousePressEvent(QMouseEvent *e) { } void ListWidget::mouseMoveEvent(QMouseEvent *e) { + static auto lastGlobalPosition = e->globalPos(); + auto reallyMoved = (lastGlobalPosition != e->globalPos()); auto buttonsPressed = (e->buttons() & (Qt::LeftButton | Qt::MiddleButton)); if (!buttonsPressed && _mouseAction != MouseAction::None) { mouseReleaseEvent(e); } + if (reallyMoved) { + lastGlobalPosition = e->globalPos(); + if (!buttonsPressed + || (_scrollDateLink + && ClickHandler::getPressed() == _scrollDateLink)) { + keepScrollDateForNow(); + } + } mouseActionUpdate(e->globalPos()); } @@ -2047,34 +2068,87 @@ void ListWidget::mouseActionUpdate() { } else { inTextSelection = false; } - // #TODO enumerate dates like HistoryInner - dragState = view->textState(itemPoint, request); - _overItemExact = App::histItemById(dragState.itemId); - lnkhost = view; - if (!dragState.link - && itemPoint.x() >= st::historyPhotoLeft - && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) { - if (view->hasFromPhoto()) { - enumerateUserpics([&](not_null view, int userpicTop) { - // stop enumeration if the userpic is below our point - if (userpicTop > point.y()) { - return false; + + const auto dateHeight = st::msgServicePadding.bottom() + + st::msgServiceFont->height + + st::msgServicePadding.top(); + const auto scrollDateOpacity = _scrollDateOpacity.current(_scrollDateShown ? 1. : 0.); + enumerateDates([&](not_null view, int itemtop, int dateTop) { + // stop enumeration if the date is above our point + if (dateTop + dateHeight <= point.y()) { + return false; + } + + const auto displayDate = view->displayDate(); + auto dateInPlace = displayDate; + if (dateInPlace) { + const auto correctDateTop = itemtop + st::msgServiceMargin.top(); + dateInPlace = (dateTop < correctDateTop + dateHeight); + } + + // stop enumeration if we've found a date under the cursor + if (dateTop <= point.y()) { + auto opacity = (dateInPlace/* || noFloatingDate*/) ? 1. : scrollDateOpacity; + if (opacity > 0.) { + const auto item = view->data(); + auto dateWidth = 0; + if (const auto date = view->Get()) { + dateWidth = date->width; + } else { + dateWidth = st::msgServiceFont->width(langDayOfMonthFull(view->dateTime().date())); } + dateWidth += st::msgServicePadding.left() + st::msgServicePadding.right(); + auto dateLeft = st::msgServiceMargin.left(); + auto maxwidth = view->width(); + if (Adaptive::ChatWide()) { + maxwidth = qMin(maxwidth, int32(st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left())); + } + auto widthForDate = maxwidth - st::msgServiceMargin.left() - st::msgServiceMargin.left(); - // stop enumeration if we've found a userpic under the cursor - if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) { - const auto message = view->data()->toHistoryMessage(); - Assert(message != nullptr); + dateLeft += (widthForDate - dateWidth) / 2; + if (point.x() >= dateLeft && point.x() < dateLeft + dateWidth) { + _scrollDateLink = _delegate->listDateLink(view); dragState = TextState( nullptr, - message->displayFrom()->openLink()); + _scrollDateLink); _overItemExact = App::histItemById(dragState.itemId); lnkhost = view; - return false; } - return true; - }); + } + return false; + } + return true; + }); + if (!dragState.link) { + dragState = view->textState(itemPoint, request); + _overItemExact = App::histItemById(dragState.itemId); + lnkhost = view; + if (!dragState.link + && itemPoint.x() >= st::historyPhotoLeft + && itemPoint.x() < st::historyPhotoLeft + st::msgPhotoSize) { + if (view->hasFromPhoto()) { + enumerateUserpics([&](not_null view, int userpicTop) { + // stop enumeration if the userpic is below our point + if (userpicTop > point.y()) { + return false; + } + + // stop enumeration if we've found a userpic under the cursor + if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) { + const auto message = view->data()->toHistoryMessage(); + Assert(message != nullptr); + + dragState = TextState( + nullptr, + message->displayFrom()->openLink()); + _overItemExact = App::histItemById(dragState.itemId); + lnkhost = view; + return false; + } + return true; + }); + } } } } diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 5dcd551d8..418f6fd3b 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -65,6 +65,7 @@ public: virtual base::optional listUnreadBarView( const std::vector> &elements) = 0; virtual void listContentRefreshed() = 0; + virtual ClickHandlerPtr listDateLink(not_null view) = 0; }; @@ -302,6 +303,7 @@ private: void scrollDateHide(); void scrollDateCheck(); void scrollDateHideByTimer(); + void keepScrollDateForNow(); void trySwitchToWordSelection(); void switchToWordSelection(); @@ -440,6 +442,7 @@ private: base::Timer _scrollDateHideTimer; Element *_scrollDateLastItem = nullptr; int _scrollDateLastItemTop = 0; + ClickHandlerPtr _scrollDateLink; SingleQueuedInvokation _applyUpdatedScrollState; Element *_unreadBarElement = nullptr; diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 5b7daa885..f307b628b 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -337,7 +337,7 @@ void Controller::showJumpToDate(Dialogs::Key chat, QDate requestedDate) { return history->chatsListDate().date(); } } else if (const auto feed = chat.feed()) { - /*if (chatScrollPosition(feed)) { + /*if (chatScrollPosition(feed)) { // #TODO feeds save position } else */if (!feed->chatsListDate().isNull()) { return feed->chatsListDate().date();