diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 8c49d16934..4de24bd0d4 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -12,6 +12,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_web_page.h" #include "data/data_feed.h" #include "data/data_media_types.h" +#include "data/data_sparse_ids.h" +#include "data/data_search_controller.h" +#include "data/data_channel_admins.h" +#include "data/data_session.h" +#include "dialogs/dialogs_key.h" #include "core/tl_help.h" #include "base/overload.h" #include "observer_peer.h" @@ -25,10 +30,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_message.h" #include "history/history_media_types.h" #include "history/history_item_components.h" +#include "history/feed/history_feed_section.h" #include "storage/localstorage.h" #include "auth_session.h" #include "boxes/confirm_box.h" #include "window/notifications_manager.h" +#include "window/window_controller.h" #include "chat_helpers/message_field.h" #include "chat_helpers/stickers.h" #include "storage/localimageloader.h" @@ -37,10 +44,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/storage_user_photos.h" #include "storage/storage_media_prepare.h" #include "storage/storage_feed_messages.h" -#include "data/data_sparse_ids.h" -#include "data/data_search_controller.h" -#include "data/data_channel_admins.h" -#include "data/data_session.h" namespace { @@ -2601,6 +2604,14 @@ void ApiWrap::applyUpdateNoPtsCheck(const MTPUpdate &update) { } } +void ApiWrap::jumpToDate(Dialogs::Key chat, const QDate &date) { + if (const auto peer = chat.peer()) { + jumpToHistoryDate(peer, date); + } else if (const auto feed = chat.feed()) { + jumpToFeedDate(feed, date); + } +} + template void ApiWrap::requestMessageAfterDate( not_null peer, @@ -2670,17 +2681,17 @@ void ApiWrap::requestMessageAfterDate( }).send(); } -void ApiWrap::jumpToDate(not_null peer, const QDate &date) { - if (auto channel = peer->migrateTo()) { - jumpToDate(channel, date); +void ApiWrap::jumpToHistoryDate(not_null peer, const QDate &date) { + if (const auto channel = peer->migrateTo()) { + jumpToHistoryDate(channel, date); return; } - auto jumpToDateInPeer = [peer, date, this] { - requestMessageAfterDate(peer, date, [peer](MsgId resultId) { + const auto jumpToDateInPeer = [=] { + requestMessageAfterDate(peer, date, [=](MsgId resultId) { Ui::showPeerHistory(peer, resultId); }); }; - if (auto chat = peer->migrateFrom()) { + if (const auto chat = peer->migrateFrom()) { requestMessageAfterDate(chat, date, [=](MsgId resultId) { if (resultId) { Ui::showPeerHistory(chat, resultId); @@ -2693,6 +2704,63 @@ void ApiWrap::jumpToDate(not_null peer, const QDate &date) { } } +template +void ApiWrap::requestMessageAfterDate( + not_null feed, + const QDate &date, + Callback &&callback) { + const auto offsetId = 0; + const auto offsetDate = static_cast(QDateTime(date).toTime_t()); + const auto addOffset = -2; + const auto limit = 1; + const auto hash = 0; + request(MTPchannels_GetFeed( + MTP_flags(MTPchannels_GetFeed::Flag::f_offset_position), + MTP_int(feed->id()), + MTP_feedPosition( + MTP_int(offsetDate), + MTP_peerUser(MTP_int(_session->userId())), + MTP_int(0)), + MTP_int(addOffset), + MTP_int(limit), + MTPfeedPosition(), // max_id + MTPfeedPosition(), // min_id + MTP_int(hash) + )).done([ + =, + callback = std::forward(callback) + ](const MTPmessages_FeedMessages &result) { + if (result.type() == mtpc_messages_feedMessagesNotModified) { + LOG(("API Error: " + "Unexpected messages.feedMessagesNotModified.")); + callback(Data::UnreadMessagePosition); + return; + } + Assert(result.type() == mtpc_messages_feedMessages); + const auto &data = result.c_messages_feedMessages(); + const auto &messages = data.vmessages.v; + const auto type = NewMessageExisting; + App::feedUsers(data.vusers); + App::feedChats(data.vchats); + for (const auto &msg : messages) { + if (const auto item = App::histories().addNewMessage(msg, type)) { + if (item->date() >= offsetDate || true) { + callback(item->position()); + return; + } + } + } + callback(Data::UnreadMessagePosition); + }).send(); +} + +void ApiWrap::jumpToFeedDate(not_null feed, const QDate &date) { + requestMessageAfterDate(feed, date, [=](Data::MessagePosition result) { + App::wnd()->controller()->showSection( + HistoryFeed::Memento(feed, result)); + }); +} + void ApiWrap::preloadEnoughUnreadMentions(not_null history) { auto fullCount = history->getUnreadMentionsCount(); auto loadedCount = history->getUnreadMentionsLoadedCount(); diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 8f2669c779..77bd1f9913 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -27,6 +27,10 @@ enum class SharedMediaType : char; struct PreparedList; } // namespace Storage +namespace Dialogs { +class Key; +} // namespace Dialogs + namespace Api { inline const MTPVector *getChatsFromMessagesChats(const MTPmessages_Chats &chats) { @@ -152,7 +156,7 @@ public: void applyUpdatesNoPtsCheck(const MTPUpdates &updates); void applyUpdateNoPtsCheck(const MTPUpdate &update); - void jumpToDate(not_null peer, const QDate &date); + void jumpToDate(Dialogs::Key chat, const QDate &date); void preloadEnoughUnreadMentions(not_null history); void checkForUnreadMentions(const base::flat_set &possiblyReadMentions, ChannelData *channel = nullptr); @@ -345,11 +349,19 @@ private: not_null channel, const QVector &participants); + + void jumpToHistoryDate(not_null peer, const QDate &date); + void jumpToFeedDate(not_null feed, const QDate &date); template void requestMessageAfterDate( not_null peer, const QDate &date, Callback &&callback); + template + void requestMessageAfterDate( + not_null feed, + const QDate &date, + Callback &&callback); void sharedMediaDone( not_null peer, diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 66388d35b4..77b355607e 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -128,11 +128,7 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont subscribe(Adaptive::Changed(), [this] { updateForwardBar(); }); _cancelSearch->setClickedCallback([this] { onCancelSearch(); }); - _jumpToDate->entity()->setClickedCallback([this] { - if (const auto peer = _searchInChat.peer()) { - this->controller()->showJumpToDate(peer, QDate()); - } - }); + _jumpToDate->entity()->setClickedCallback([this] { showJumpToDate(); }); _chooseFromUser->entity()->setClickedCallback([this] { showSearchFrom(); }); _lockUnlock->setVisible(Global::LocalPasscode()); subscribe(Global::RefLocalPasscodeChanged(), [this] { updateLockUnlockVisibility(); }); @@ -1036,6 +1032,12 @@ void DialogsWidget::clearSearchCache() { MTP::cancel(base::take(_searchRequest)); } +void DialogsWidget::showJumpToDate() { + if (_searchInChat) { + this->controller()->showJumpToDate(_searchInChat, QDate()); + } +} + void DialogsWidget::showSearchFrom() { if (const auto peer = _searchInChat.peer()) { const auto chat = _searchInChat; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index fbcce90115..0822e18dba 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -156,6 +156,7 @@ private: const QVector &messages); void setSearchInChat(Dialogs::Key chat, UserData *from = nullptr); + void showJumpToDate(); void showSearchFrom(); void showMainMenu(); void clearSearchCache(); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 9147caa1d4..b628363a10 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -41,25 +41,6 @@ namespace { constexpr auto kScrollDateHideTimeout = 1000; -class DateClickHandler : public ClickHandler { -public: - DateClickHandler(PeerData *peer, QDate date) : _peer(peer), _date(date) { - } - - void setDate(QDate date) { - _date = date; - } - - void onClick(Qt::MouseButton) const override { - App::wnd()->controller()->showJumpToDate(_peer, _date); - } - -private: - PeerData *_peer = nullptr; - QDate _date; - -}; - // Helper binary search for an item in a list that is not completely // above the given top of the visible area or below the given bottom of the visible area // is applied once for blocks list in a history and once for items list in the found block. @@ -2401,9 +2382,9 @@ void HistoryInner::mouseActionUpdate() { if (point.x() >= dateLeft && point.x() < dateLeft + dateWidth) { if (!_scrollDateLink) { - _scrollDateLink = std::make_shared(item->history()->peer, view->dateTime().date()); + _scrollDateLink = std::make_shared(item->history(), view->dateTime().date()); } else { - static_cast(_scrollDateLink.get())->setDate(view->dateTime().date()); + static_cast(_scrollDateLink.get())->setDate(view->dateTime().date()); } dragState = TextState( nullptr, diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 96661dae9a..7d5df7e359 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -242,7 +242,6 @@ public: void hideSingleUseKeyboard(PeerData *peer, MsgId replyTo); bool insertBotCommand(const QString &cmd); - void jumpToDate(not_null peer, const QDate &date); void searchMessages(const QString &query, Dialogs::Key inChat); void itemEdited(not_null item); diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 065e8887b3..5b7daa885c 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_element.h" #include "media/player/media_player_round_controller.h" #include "data/data_session.h" +#include "data/data_feed.h" #include "boxes/calendar_box.h" #include "mainwidget.h" #include "mainwindow.h" @@ -24,6 +25,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Window { +DateClickHandler::DateClickHandler(Dialogs::Key chat, QDate date) +: _chat(chat) +, _date(date) { +} + +void DateClickHandler::setDate(QDate date) { + _date = date; +} + +void DateClickHandler::onClick(Qt::MouseButton) const { + App::wnd()->controller()->showJumpToDate(_chat, _date); +} + Controller::Controller(not_null window) : _window(window) { Auth().data().animationPlayInlineRequest( @@ -304,14 +318,15 @@ void Controller::closeThirdSection() { } } -void Controller::showJumpToDate(not_null peer, QDate requestedDate) { - Expects(peer != nullptr); - auto currentPeerDate = [peer] { - if (auto history = App::historyLoaded(peer)) { +void Controller::showJumpToDate(Dialogs::Key chat, QDate requestedDate) { + const auto currentPeerDate = [&] { + if (const auto history = chat.history()) { if (history->scrollTopItem) { return history->scrollTopItem->dateTime().date(); - } else if (history->loadedAtTop() && !history->isEmpty() && history->peer->migrateFrom()) { - if (auto migrated = App::historyLoaded(history->peer->migrateFrom())) { + } else if (history->loadedAtTop() + && !history->isEmpty() + && history->peer->migrateFrom()) { + if (const auto migrated = App::historyLoaded(history->peer->migrateFrom())) { if (migrated->scrollTopItem) { // We're up in the migrated history. // So current date is the date of first message here. @@ -321,59 +336,71 @@ void Controller::showJumpToDate(not_null peer, QDate requestedDate) { } else if (!history->chatsListDate().isNull()) { return history->chatsListDate().date(); } - } - return QDate::currentDate(); - }; - auto maxPeerDate = [](not_null peer) { - if (auto channel = peer->migrateTo()) { - peer = channel; - } - if (auto history = App::historyLoaded(peer)) { - if (!history->chatsListDate().isNull()) { - return history->chatsListDate().date(); + } else if (const auto feed = chat.feed()) { + /*if (chatScrollPosition(feed)) { + + } else */if (!feed->chatsListDate().isNull()) { + return feed->chatsListDate().date(); } } return QDate::currentDate(); }; - auto minPeerDate = [](not_null peer) { + const auto maxPeerDate = [](Dialogs::Key chat) { + if (auto history = chat.history()) { + if (const auto channel = history->peer->migrateTo()) { + history = App::historyLoaded(channel); + } + if (history && !history->chatsListDate().isNull()) { + return history->chatsListDate().date(); + } + } else if (const auto feed = chat.feed()) { + if (!feed->chatsListDate().isNull()) { + return feed->chatsListDate().date(); + } + } + return QDate::currentDate(); + }; + const auto minPeerDate = [](Dialogs::Key chat) { const auto startDate = [] { // Telegram was launched in August 2013 :) return QDate(2013, 8, 1); }; - if (auto chat = peer->migrateFrom()) { - if (auto history = App::historyLoaded(chat)) { - if (history->loadedAtTop()) { - if (!history->isEmpty()) { - return history->blocks.front()->messages.front()->dateTime().date(); + if (const auto history = chat.history()) { + if (const auto chat = history->peer->migrateFrom()) { + if (const auto history = App::historyLoaded(chat)) { + if (history->loadedAtTop()) { + if (!history->isEmpty()) { + return history->blocks.front()->messages.front()->dateTime().date(); + } + } else { + return startDate(); } - } else { - return startDate(); } } - } - if (auto history = App::historyLoaded(peer)) { if (history->loadedAtTop()) { if (!history->isEmpty()) { return history->blocks.front()->messages.front()->dateTime().date(); } return QDate::currentDate(); } + } else if (const auto feed = chat.feed()) { + return startDate(); } return startDate(); }; - auto highlighted = requestedDate.isNull() + const auto highlighted = requestedDate.isNull() ? currentPeerDate() : requestedDate; - auto month = highlighted; - auto callback = [this, peer](const QDate &date) { - Auth().api().jumpToDate(peer, date); + const auto month = highlighted; + auto callback = [=](const QDate &date) { + Auth().api().jumpToDate(chat, date); }; auto box = Box( month, highlighted, std::move(callback)); - box->setMinDate(minPeerDate(peer)); - box->setMaxDate(maxPeerDate(peer)); + box->setMinDate(minPeerDate(chat)); + box->setMaxDate(maxPeerDate(chat)); Ui::show(std::move(box)); } diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index 0fedc2245f..0033611973 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -38,6 +38,19 @@ enum class GifPauseReason { using GifPauseReasons = base::flags; inline constexpr bool is_flag_type(GifPauseReason) { return true; }; +class DateClickHandler : public ClickHandler { +public: + DateClickHandler(Dialogs::Key chat, QDate date); + + void setDate(QDate date); + void onClick(Qt::MouseButton) const override; + +private: + Dialogs::Key _chat; + QDate _date; + +}; + struct SectionShow { enum class Way { Forward, @@ -184,7 +197,7 @@ public: } void showJumpToDate( - not_null peer, + Dialogs::Key chat, QDate requestedDate); base::Variable &dialogsListFocused() {