Implement jump-to-date in topics.
This commit is contained in:
		
							parent
							
								
									ee8f997c14
								
							
						
					
					
						commit
						5d76415a5d
					
				
					 7 changed files with 182 additions and 59 deletions
				
			
		| 
						 | 
					@ -2834,13 +2834,16 @@ void ApiWrap::resolveJumpToDate(
 | 
				
			||||||
		const QDate &date,
 | 
							const QDate &date,
 | 
				
			||||||
		Fn<void(not_null<PeerData*>, MsgId)> callback) {
 | 
							Fn<void(not_null<PeerData*>, MsgId)> callback) {
 | 
				
			||||||
	if (const auto peer = chat.peer()) {
 | 
						if (const auto peer = chat.peer()) {
 | 
				
			||||||
		resolveJumpToHistoryDate(peer, date, std::move(callback));
 | 
							const auto topic = chat.topic();
 | 
				
			||||||
 | 
							const auto rootId = topic ? topic->rootId() : 0;
 | 
				
			||||||
 | 
							resolveJumpToHistoryDate(peer, rootId, date, std::move(callback));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename Callback>
 | 
					template <typename Callback>
 | 
				
			||||||
void ApiWrap::requestMessageAfterDate(
 | 
					void ApiWrap::requestMessageAfterDate(
 | 
				
			||||||
		not_null<PeerData*> peer,
 | 
							not_null<PeerData*> peer,
 | 
				
			||||||
 | 
							MsgId topicRootId,
 | 
				
			||||||
		const QDate &date,
 | 
							const QDate &date,
 | 
				
			||||||
		Callback &&callback) {
 | 
							Callback &&callback) {
 | 
				
			||||||
	// API returns a message with date <= offset_date.
 | 
						// API returns a message with date <= offset_date.
 | 
				
			||||||
| 
						 | 
					@ -2853,48 +2856,40 @@ void ApiWrap::requestMessageAfterDate(
 | 
				
			||||||
	const auto maxId = 0;
 | 
						const auto maxId = 0;
 | 
				
			||||||
	const auto minId = 0;
 | 
						const auto minId = 0;
 | 
				
			||||||
	const auto historyHash = uint64(0);
 | 
						const auto historyHash = uint64(0);
 | 
				
			||||||
	request(MTPmessages_GetHistory(
 | 
					
 | 
				
			||||||
		peer->input,
 | 
						auto send = [&](auto &&serialized) {
 | 
				
			||||||
		MTP_int(offsetId),
 | 
							request(std::move(serialized)).done([
 | 
				
			||||||
		MTP_int(offsetDate),
 | 
					 | 
				
			||||||
		MTP_int(addOffset),
 | 
					 | 
				
			||||||
		MTP_int(limit),
 | 
					 | 
				
			||||||
		MTP_int(maxId),
 | 
					 | 
				
			||||||
		MTP_int(minId),
 | 
					 | 
				
			||||||
		MTP_long(historyHash)
 | 
					 | 
				
			||||||
	)).done([
 | 
					 | 
				
			||||||
			=,
 | 
								=,
 | 
				
			||||||
			callback = std::forward<Callback>(callback)
 | 
								callback = std::forward<Callback>(callback)
 | 
				
			||||||
		](const MTPmessages_Messages &result) {
 | 
							](const MTPmessages_Messages &result) {
 | 
				
			||||||
		auto getMessagesList = [&]() -> const QVector<MTPMessage>* {
 | 
								const auto handleMessages = [&](auto &messages) {
 | 
				
			||||||
			auto handleMessages = [&](auto &messages) {
 | 
					 | 
				
			||||||
				_session->data().processUsers(messages.vusers());
 | 
									_session->data().processUsers(messages.vusers());
 | 
				
			||||||
				_session->data().processChats(messages.vchats());
 | 
									_session->data().processChats(messages.vchats());
 | 
				
			||||||
				return &messages.vmessages().v;
 | 
									return &messages.vmessages().v;
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			switch (result.type()) {
 | 
								const auto list = result.match([&](
 | 
				
			||||||
			case mtpc_messages_messages:
 | 
										const MTPDmessages_messages &data) {
 | 
				
			||||||
				return handleMessages(result.c_messages_messages());
 | 
									return handleMessages(result.c_messages_messages());
 | 
				
			||||||
			case mtpc_messages_messagesSlice:
 | 
								}, [&](const MTPDmessages_messagesSlice &data) {
 | 
				
			||||||
				return handleMessages(result.c_messages_messagesSlice());
 | 
									return handleMessages(result.c_messages_messagesSlice());
 | 
				
			||||||
			case mtpc_messages_channelMessages: {
 | 
								}, [&](const MTPDmessages_channelMessages &data) {
 | 
				
			||||||
				auto &messages = result.c_messages_channelMessages();
 | 
									const auto &messages = result.c_messages_channelMessages();
 | 
				
			||||||
				if (peer && peer->isChannel()) {
 | 
									if (peer && peer->isChannel()) {
 | 
				
			||||||
					peer->asChannel()->ptsReceived(messages.vpts().v);
 | 
										peer->asChannel()->ptsReceived(messages.vpts().v);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					LOG(("API Error: received messages.channelMessages when no channel was passed! (ApiWrap::jumpToDate)"));
 | 
										LOG(("API Error: received messages.channelMessages when "
 | 
				
			||||||
 | 
											"no channel was passed! (ApiWrap::jumpToDate)"));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				return handleMessages(messages);
 | 
									return handleMessages(messages);
 | 
				
			||||||
			} break;
 | 
								}, [&](const MTPDmessages_messagesNotModified &) {
 | 
				
			||||||
			case mtpc_messages_messagesNotModified: {
 | 
									LOG(("API Error: received messages.messagesNotModified! "
 | 
				
			||||||
				LOG(("API Error: received messages.messagesNotModified! (ApiWrap::jumpToDate)"));
 | 
										"(ApiWrap::jumpToDate)"));
 | 
				
			||||||
			} break;
 | 
									return (const QVector<MTPMessage>*)nullptr;
 | 
				
			||||||
			}
 | 
								});
 | 
				
			||||||
			return nullptr;
 | 
								if (list) {
 | 
				
			||||||
		};
 | 
									_session->data().processMessages(
 | 
				
			||||||
 | 
										*list,
 | 
				
			||||||
		if (const auto list = getMessagesList()) {
 | 
										NewMessageType::Existing);
 | 
				
			||||||
			_session->data().processMessages(*list, NewMessageType::Existing);
 | 
					 | 
				
			||||||
				for (const auto &message : *list) {
 | 
									for (const auto &message : *list) {
 | 
				
			||||||
					if (DateFromMessage(message) >= offsetDate) {
 | 
										if (DateFromMessage(message) >= offsetDate) {
 | 
				
			||||||
						callback(IdFromMessage(message));
 | 
											callback(IdFromMessage(message));
 | 
				
			||||||
| 
						 | 
					@ -2904,24 +2899,52 @@ void ApiWrap::requestMessageAfterDate(
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			callback(ShowAtUnreadMsgId);
 | 
								callback(ShowAtUnreadMsgId);
 | 
				
			||||||
		}).send();
 | 
							}).send();
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						if (topicRootId) {
 | 
				
			||||||
 | 
							send(MTPmessages_GetReplies(
 | 
				
			||||||
 | 
								peer->input,
 | 
				
			||||||
 | 
								MTP_int(topicRootId),
 | 
				
			||||||
 | 
								MTP_int(offsetId),
 | 
				
			||||||
 | 
								MTP_int(offsetDate),
 | 
				
			||||||
 | 
								MTP_int(addOffset),
 | 
				
			||||||
 | 
								MTP_int(limit),
 | 
				
			||||||
 | 
								MTP_int(maxId),
 | 
				
			||||||
 | 
								MTP_int(minId),
 | 
				
			||||||
 | 
								MTP_long(historyHash)));
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							send(MTPmessages_GetHistory(
 | 
				
			||||||
 | 
								peer->input,
 | 
				
			||||||
 | 
								MTP_int(offsetId),
 | 
				
			||||||
 | 
								MTP_int(offsetDate),
 | 
				
			||||||
 | 
								MTP_int(addOffset),
 | 
				
			||||||
 | 
								MTP_int(limit),
 | 
				
			||||||
 | 
								MTP_int(maxId),
 | 
				
			||||||
 | 
								MTP_int(minId),
 | 
				
			||||||
 | 
								MTP_long(historyHash)));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ApiWrap::resolveJumpToHistoryDate(
 | 
					void ApiWrap::resolveJumpToHistoryDate(
 | 
				
			||||||
		not_null<PeerData*> peer,
 | 
							not_null<PeerData*> peer,
 | 
				
			||||||
 | 
							MsgId topicRootId,
 | 
				
			||||||
		const QDate &date,
 | 
							const QDate &date,
 | 
				
			||||||
		Fn<void(not_null<PeerData*>, MsgId)> callback) {
 | 
							Fn<void(not_null<PeerData*>, MsgId)> callback) {
 | 
				
			||||||
	if (const auto channel = peer->migrateTo()) {
 | 
						if (const auto channel = peer->migrateTo()) {
 | 
				
			||||||
		return resolveJumpToHistoryDate(channel, date, std::move(callback));
 | 
							return resolveJumpToHistoryDate(
 | 
				
			||||||
 | 
								channel,
 | 
				
			||||||
 | 
								topicRootId,
 | 
				
			||||||
 | 
								date,
 | 
				
			||||||
 | 
								std::move(callback));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const auto jumpToDateInPeer = [=] {
 | 
						const auto jumpToDateInPeer = [=] {
 | 
				
			||||||
		requestMessageAfterDate(peer, date, [=](MsgId resultId) {
 | 
							requestMessageAfterDate(peer, topicRootId, date, [=](MsgId itemId) {
 | 
				
			||||||
			callback(peer, resultId);
 | 
								callback(peer, itemId);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	if (const auto chat = peer->migrateFrom()) {
 | 
						if (const auto chat = topicRootId ? nullptr : peer->migrateFrom()) {
 | 
				
			||||||
		requestMessageAfterDate(chat, date, [=](MsgId resultId) {
 | 
							requestMessageAfterDate(chat, 0, date, [=](MsgId itemId) {
 | 
				
			||||||
			if (resultId) {
 | 
								if (itemId) {
 | 
				
			||||||
				callback(chat, resultId);
 | 
									callback(chat, itemId);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				jumpToDateInPeer();
 | 
									jumpToDateInPeer();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -454,11 +454,13 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void resolveJumpToHistoryDate(
 | 
						void resolveJumpToHistoryDate(
 | 
				
			||||||
		not_null<PeerData*> peer,
 | 
							not_null<PeerData*> peer,
 | 
				
			||||||
 | 
							MsgId topicRootId,
 | 
				
			||||||
		const QDate &date,
 | 
							const QDate &date,
 | 
				
			||||||
		Fn<void(not_null<PeerData*>, MsgId)> callback);
 | 
							Fn<void(not_null<PeerData*>, MsgId)> callback);
 | 
				
			||||||
	template <typename Callback>
 | 
						template <typename Callback>
 | 
				
			||||||
	void requestMessageAfterDate(
 | 
						void requestMessageAfterDate(
 | 
				
			||||||
		not_null<PeerData*> peer,
 | 
							not_null<PeerData*> peer,
 | 
				
			||||||
 | 
							MsgId topicRootId,
 | 
				
			||||||
		const QDate &date,
 | 
							const QDate &date,
 | 
				
			||||||
		Callback &&callback);
 | 
							Callback &&callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,7 +223,9 @@ void Forum::applyReceivedTopics(
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Forum::requestSomeStale() {
 | 
					void Forum::requestSomeStale() {
 | 
				
			||||||
	if (_staleRequestId || (!_offset.id && _requestId)) {
 | 
						if (_staleRequestId
 | 
				
			||||||
 | 
							|| (!_offset.id && _requestId)
 | 
				
			||||||
 | 
							|| _staleRootIds.empty()) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const auto type = Histories::RequestType::History;
 | 
						const auto type = Histories::RequestType::History;
 | 
				
			||||||
| 
						 | 
					@ -241,6 +243,9 @@ void Forum::requestSomeStale() {
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (rootIds.empty()) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	const auto call = [=] {
 | 
						const auto call = [=] {
 | 
				
			||||||
		for (const auto &id : rootIds) {
 | 
							for (const auto &id : rootIds) {
 | 
				
			||||||
			finishTopicRequest(id.v);
 | 
								finishTopicRequest(id.v);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -779,7 +779,11 @@ void Widget::refreshTopBars() {
 | 
				
			||||||
			_subsectionTopBar->searchQuery(
 | 
								_subsectionTopBar->searchQuery(
 | 
				
			||||||
			) | rpl::start_with_next([=](QString query) {
 | 
								) | rpl::start_with_next([=](QString query) {
 | 
				
			||||||
				applyFilterUpdate();
 | 
									applyFilterUpdate();
 | 
				
			||||||
			}, lifetime());
 | 
								}, _subsectionTopBar->lifetime());
 | 
				
			||||||
 | 
								_subsectionTopBar->jumpToDateRequest(
 | 
				
			||||||
 | 
								) | rpl::start_with_next([=] {
 | 
				
			||||||
 | 
									showCalendar();
 | 
				
			||||||
 | 
								}, _subsectionTopBar->lifetime());
 | 
				
			||||||
			updateControlsGeometry();
 | 
								updateControlsGeometry();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		const auto history = _openedForum
 | 
							const auto history = _openedForum
 | 
				
			||||||
| 
						 | 
					@ -1386,14 +1390,16 @@ void Widget::searchTopics() {
 | 
				
			||||||
		MTP_int(kSearchPerPage)
 | 
							MTP_int(kSearchPerPage)
 | 
				
			||||||
	)).done([=](const MTPmessages_ForumTopics &result) {
 | 
						)).done([=](const MTPmessages_ForumTopics &result) {
 | 
				
			||||||
		_topicSearchRequest = 0;
 | 
							_topicSearchRequest = 0;
 | 
				
			||||||
		const auto savedTopicId = _topicSearchOffsetId;
 | 
							const auto savedTopicId = _topicSearchOffsetTopicId;
 | 
				
			||||||
		const auto byCreation = result.data().is_order_by_create_date();
 | 
							const auto byCreation = result.data().is_order_by_create_date();
 | 
				
			||||||
		_openedForum->forum()->applyReceivedTopics(result, [&](
 | 
							_openedForum->forum()->applyReceivedTopics(result, [&](
 | 
				
			||||||
				not_null<Data::ForumTopic*> topic) {
 | 
									not_null<Data::ForumTopic*> topic) {
 | 
				
			||||||
			_topicSearchOffsetTopicId = topic->rootId();
 | 
								_topicSearchOffsetTopicId = topic->rootId();
 | 
				
			||||||
			if (byCreation) {
 | 
								if (byCreation) {
 | 
				
			||||||
				_topicSearchOffsetId = _topicSearchOffsetTopicId;
 | 
					 | 
				
			||||||
				_topicSearchOffsetDate = topic->creationDate();
 | 
									_topicSearchOffsetDate = topic->creationDate();
 | 
				
			||||||
 | 
									if (const auto last = topic->lastServerMessage()) {
 | 
				
			||||||
 | 
										_topicSearchOffsetId = last->id;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			} else if (const auto last = topic->lastServerMessage()) {
 | 
								} else if (const auto last = topic->lastServerMessage()) {
 | 
				
			||||||
				_topicSearchOffsetId = last->id;
 | 
									_topicSearchOffsetId = last->id;
 | 
				
			||||||
				_topicSearchOffsetDate = last->date();
 | 
									_topicSearchOffsetDate = last->date();
 | 
				
			||||||
| 
						 | 
					@ -1899,6 +1905,10 @@ void Widget::setSearchInChat(Key chat, PeerData *from) {
 | 
				
			||||||
		clearSearchCache();
 | 
							clearSearchCache();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_inner->searchInChat(_searchInChat, _searchFromAuthor);
 | 
						_inner->searchInChat(_searchInChat, _searchFromAuthor);
 | 
				
			||||||
 | 
						if (_subsectionTopBar) {
 | 
				
			||||||
 | 
							_subsectionTopBar->searchEnableJumpToDate(
 | 
				
			||||||
 | 
								_openedForum && _searchInChat);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (_searchFromAuthor && _lastFilterText == SwitchToChooseFromQuery()) {
 | 
						if (_searchFromAuthor && _lastFilterText == SwitchToChooseFromQuery()) {
 | 
				
			||||||
		cancelSearch();
 | 
							cancelSearch();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
				
			||||||
#include "core/shortcuts.h"
 | 
					#include "core/shortcuts.h"
 | 
				
			||||||
#include "core/application.h"
 | 
					#include "core/application.h"
 | 
				
			||||||
#include "core/core_settings.h"
 | 
					#include "core/core_settings.h"
 | 
				
			||||||
 | 
					#include "ui/wrap/fade_wrap.h"
 | 
				
			||||||
#include "ui/widgets/buttons.h"
 | 
					#include "ui/widgets/buttons.h"
 | 
				
			||||||
#include "ui/widgets/input_fields.h"
 | 
					#include "ui/widgets/input_fields.h"
 | 
				
			||||||
#include "ui/widgets/popup_menu.h"
 | 
					#include "ui/widgets/popup_menu.h"
 | 
				
			||||||
| 
						 | 
					@ -880,8 +881,10 @@ int TopBarWidget::countSelectedButtonsTop(float64 selectedShown) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TopBarWidget::updateSearchVisibility() {
 | 
					void TopBarWidget::updateSearchVisibility() {
 | 
				
			||||||
	const auto historyMode = (_activeChat.section == Section::History);
 | 
						const auto searchAllowedMode = (_activeChat.section == Section::History)
 | 
				
			||||||
	_search->setVisible(historyMode && !_chooseForReportReason);
 | 
							|| (_activeChat.section == Section::Replies
 | 
				
			||||||
 | 
								&& _activeChat.key.topic());
 | 
				
			||||||
 | 
						_search->setVisible(searchAllowedMode && !_chooseForReportReason);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TopBarWidget::updateControlsGeometry() {
 | 
					void TopBarWidget::updateControlsGeometry() {
 | 
				
			||||||
| 
						 | 
					@ -894,6 +897,7 @@ void TopBarWidget::updateControlsGeometry() {
 | 
				
			||||||
	if (!_searchMode && !_searchShown.animating() && _searchField) {
 | 
						if (!_searchMode && !_searchShown.animating() && _searchField) {
 | 
				
			||||||
		_searchField.destroy();
 | 
							_searchField.destroy();
 | 
				
			||||||
		_searchCancel.destroy();
 | 
							_searchCancel.destroy();
 | 
				
			||||||
 | 
							_jumpToDate.destroy();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	auto searchFieldTop = _searchField
 | 
						auto searchFieldTop = _searchField
 | 
				
			||||||
		? countSelectedButtonsTop(_searchShown.value(_searchMode ? 1. : 0.))
 | 
							? countSelectedButtonsTop(_searchShown.value(_searchMode ? 1. : 0.))
 | 
				
			||||||
| 
						 | 
					@ -966,6 +970,11 @@ void TopBarWidget::updateControlsGeometry() {
 | 
				
			||||||
		_searchCancel->moveToLeft(
 | 
							_searchCancel->moveToLeft(
 | 
				
			||||||
			right - _searchCancel->width(),
 | 
								right - _searchCancel->width(),
 | 
				
			||||||
			_searchField->y());
 | 
								_searchField->y());
 | 
				
			||||||
 | 
							if (_jumpToDate) {
 | 
				
			||||||
 | 
								_jumpToDate->moveToLeft(
 | 
				
			||||||
 | 
									right - _jumpToDate->width(),
 | 
				
			||||||
 | 
									_searchField->y());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		right -= _searchCancel->width();
 | 
							right -= _searchCancel->width();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1054,6 +1063,19 @@ void TopBarWidget::updateControlsVisibility() {
 | 
				
			||||||
			? (_activeChat.key.topic() != nullptr)
 | 
								? (_activeChat.key.topic() != nullptr)
 | 
				
			||||||
			: false);
 | 
								: false);
 | 
				
			||||||
	updateSearchVisibility();
 | 
						updateSearchVisibility();
 | 
				
			||||||
 | 
						if (_searchMode) {
 | 
				
			||||||
 | 
							const auto hasSearchQuery = _searchField
 | 
				
			||||||
 | 
								&& !_searchField->getLastText().isEmpty();
 | 
				
			||||||
 | 
							if (!_jumpToDate || hasSearchQuery) {
 | 
				
			||||||
 | 
								_searchCancel->show(anim::type::normal);
 | 
				
			||||||
 | 
								if (_jumpToDate) {
 | 
				
			||||||
 | 
									_jumpToDate->hide(anim::type::normal);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								_searchCancel->hide(anim::type::normal);
 | 
				
			||||||
 | 
								_jumpToDate->show(anim::type::normal);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	_menuToggle->setVisible(hasMenu
 | 
						_menuToggle->setVisible(hasMenu
 | 
				
			||||||
		&& !_chooseForReportReason
 | 
							&& !_chooseForReportReason
 | 
				
			||||||
		&& !_narrowMode);
 | 
							&& !_narrowMode);
 | 
				
			||||||
| 
						 | 
					@ -1201,7 +1223,13 @@ bool TopBarWidget::toggleSearch(bool shown, anim::type animated) {
 | 
				
			||||||
			_searchSubmitted.fire({});
 | 
								_searchSubmitted.fire({});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		QObject::connect(_searchField, &Ui::InputField::changed, [=] {
 | 
							QObject::connect(_searchField, &Ui::InputField::changed, [=] {
 | 
				
			||||||
			_searchQuery = _searchField->getLastText();
 | 
								const auto wasEmpty = _searchQuery.current().isEmpty();
 | 
				
			||||||
 | 
								const auto query = _searchField->getLastText();
 | 
				
			||||||
 | 
								const auto nowEmpty = query.isEmpty();
 | 
				
			||||||
 | 
								if (_jumpToDate && nowEmpty != wasEmpty) {
 | 
				
			||||||
 | 
									updateControlsVisibility();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								_searchQuery = query;
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		Assert(_searchField != nullptr);
 | 
							Assert(_searchField != nullptr);
 | 
				
			||||||
| 
						 | 
					@ -1224,6 +1252,27 @@ bool TopBarWidget::toggleSearch(bool shown, anim::type animated) {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TopBarWidget::searchEnableJumpToDate(bool enable) {
 | 
				
			||||||
 | 
						if (!_searchMode && !enable) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						} else if (enable) {
 | 
				
			||||||
 | 
							_jumpToDate.create(
 | 
				
			||||||
 | 
								this,
 | 
				
			||||||
 | 
								object_ptr<Ui::IconButton>(this, st::dialogsCalendar));
 | 
				
			||||||
 | 
							_jumpToDate->toggle(
 | 
				
			||||||
 | 
								_searchField->getLastText().isEmpty(),
 | 
				
			||||||
 | 
								anim::type::instant);
 | 
				
			||||||
 | 
							_jumpToDate->entity()->clicks(
 | 
				
			||||||
 | 
							) | rpl::to_empty | rpl::start_to_stream(
 | 
				
			||||||
 | 
								_jumpToDateRequests,
 | 
				
			||||||
 | 
								_jumpToDate->lifetime());
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							_jumpToDate.destroy();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						updateControlsVisibility();
 | 
				
			||||||
 | 
						updateControlsGeometry();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool TopBarWidget::searchSetFocus() {
 | 
					bool TopBarWidget::searchSetFocus() {
 | 
				
			||||||
	if (!_searchMode) {
 | 
						if (!_searchMode) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,7 @@ public:
 | 
				
			||||||
	void clearChooseMessagesForReport();
 | 
						void clearChooseMessagesForReport();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool toggleSearch(bool shown, anim::type animated);
 | 
						bool toggleSearch(bool shown, anim::type animated);
 | 
				
			||||||
 | 
						void searchEnableJumpToDate(bool enable);
 | 
				
			||||||
	bool searchSetFocus();
 | 
						bool searchSetFocus();
 | 
				
			||||||
	[[nodiscard]] bool searchHasFocus() const;
 | 
						[[nodiscard]] bool searchHasFocus() const;
 | 
				
			||||||
	[[nodiscard]] rpl::producer<> searchCancelled() const;
 | 
						[[nodiscard]] rpl::producer<> searchCancelled() const;
 | 
				
			||||||
| 
						 | 
					@ -100,6 +101,9 @@ public:
 | 
				
			||||||
	[[nodiscard]] rpl::producer<> cancelChooseForReportRequest() const {
 | 
						[[nodiscard]] rpl::producer<> cancelChooseForReportRequest() const {
 | 
				
			||||||
		return _cancelChooseForReport.events();
 | 
							return _cancelChooseForReport.events();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						[[nodiscard]] rpl::producer<> jumpToDateRequest() const {
 | 
				
			||||||
 | 
							return _jumpToDateRequests.events();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	[[nodiscard]] rpl::producer<> searchRequest() const;
 | 
						[[nodiscard]] rpl::producer<> searchRequest() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
| 
						 | 
					@ -198,6 +202,7 @@ private:
 | 
				
			||||||
	rpl::variable<QString> _searchQuery;
 | 
						rpl::variable<QString> _searchQuery;
 | 
				
			||||||
	rpl::event_stream<> _searchCancelled;
 | 
						rpl::event_stream<> _searchCancelled;
 | 
				
			||||||
	rpl::event_stream<> _searchSubmitted;
 | 
						rpl::event_stream<> _searchSubmitted;
 | 
				
			||||||
 | 
						rpl::event_stream<> _jumpToDateRequests;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	object_ptr<Ui::IconButton> _back;
 | 
						object_ptr<Ui::IconButton> _back;
 | 
				
			||||||
	object_ptr<Ui::IconButton> _cancelChoose;
 | 
						object_ptr<Ui::IconButton> _cancelChoose;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1396,12 +1396,18 @@ void SessionController::startOrJoinGroupCall(
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SessionController::showCalendar(Dialogs::Key chat, QDate requestedDate) {
 | 
					void SessionController::showCalendar(Dialogs::Key chat, QDate requestedDate) {
 | 
				
			||||||
	const auto history = chat.history();
 | 
						const auto topic = chat.topic();
 | 
				
			||||||
 | 
						const auto history = chat.owningHistory();
 | 
				
			||||||
	if (!history) {
 | 
						if (!history) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const auto currentPeerDate = [&] {
 | 
						const auto currentPeerDate = [&] {
 | 
				
			||||||
		if (history->scrollTopItem) {
 | 
							if (topic) {
 | 
				
			||||||
 | 
								if (const auto item = topic->lastMessage()) {
 | 
				
			||||||
 | 
									return base::unixtime::parse(item->date()).date();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return QDate();
 | 
				
			||||||
 | 
							} else if (history->scrollTopItem) {
 | 
				
			||||||
			return history->scrollTopItem->dateTime().date();
 | 
								return history->scrollTopItem->dateTime().date();
 | 
				
			||||||
		} else if (history->loadedAtTop()
 | 
							} else if (history->loadedAtTop()
 | 
				
			||||||
			&& !history->isEmpty()
 | 
								&& !history->isEmpty()
 | 
				
			||||||
| 
						 | 
					@ -1419,6 +1425,12 @@ void SessionController::showCalendar(Dialogs::Key chat, QDate requestedDate) {
 | 
				
			||||||
		return QDate();
 | 
							return QDate();
 | 
				
			||||||
	}();
 | 
						}();
 | 
				
			||||||
	const auto maxPeerDate = [&] {
 | 
						const auto maxPeerDate = [&] {
 | 
				
			||||||
 | 
							if (topic) {
 | 
				
			||||||
 | 
								if (const auto item = topic->lastMessage()) {
 | 
				
			||||||
 | 
									return base::unixtime::parse(item->date()).date();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return QDate();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		const auto check = history->peer->migrateTo()
 | 
							const auto check = history->peer->migrateTo()
 | 
				
			||||||
			? history->owner().historyLoaded(history->peer->migrateTo())
 | 
								? history->owner().historyLoaded(history->peer->migrateTo())
 | 
				
			||||||
			: history;
 | 
								: history;
 | 
				
			||||||
| 
						 | 
					@ -1428,11 +1440,13 @@ void SessionController::showCalendar(Dialogs::Key chat, QDate requestedDate) {
 | 
				
			||||||
		return QDate();
 | 
							return QDate();
 | 
				
			||||||
	}();
 | 
						}();
 | 
				
			||||||
	const auto minPeerDate = [&] {
 | 
						const auto minPeerDate = [&] {
 | 
				
			||||||
		const auto startDate = [] {
 | 
							const auto startDate = [&] {
 | 
				
			||||||
			// Telegram was launched in August 2013 :)
 | 
								// Telegram was launched in August 2013 :)
 | 
				
			||||||
			return QDate(2013, 8, 1);
 | 
								return QDate(2013, 8, 1);
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		if (const auto chat = history->peer->migrateFrom()) {
 | 
							if (topic) {
 | 
				
			||||||
 | 
								return base::unixtime::parse(topic->creationDate()).date();
 | 
				
			||||||
 | 
							} else if (const auto chat = history->peer->migrateFrom()) {
 | 
				
			||||||
			if (const auto history = chat->owner().historyLoaded(chat)) {
 | 
								if (const auto history = chat->owner().historyLoaded(chat)) {
 | 
				
			||||||
				if (history->loadedAtTop()) {
 | 
									if (history->loadedAtTop()) {
 | 
				
			||||||
					if (!history->isEmpty()) {
 | 
										if (!history->isEmpty()) {
 | 
				
			||||||
| 
						 | 
					@ -1515,13 +1529,28 @@ void SessionController::showCalendar(Dialogs::Key chat, QDate requestedDate) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	const auto weak = base::make_weak(this);
 | 
						const auto weak = base::make_weak(this);
 | 
				
			||||||
 | 
						const auto weakTopic = base::make_weak(topic);
 | 
				
			||||||
	const auto jump = [=](const QDate &date) {
 | 
						const auto jump = [=](const QDate &date) {
 | 
				
			||||||
		const auto open = [=](not_null<PeerData*> peer, MsgId id) {
 | 
							const auto open = [=](not_null<PeerData*> peer, MsgId id) {
 | 
				
			||||||
			if (const auto strong = weak.get()) {
 | 
								if (const auto strong = weak.get()) {
 | 
				
			||||||
				strong->showPeerHistory(peer, SectionShow::Way::Forward, id);
 | 
									if (!topic) {
 | 
				
			||||||
 | 
										strong->showPeerHistory(
 | 
				
			||||||
 | 
											peer,
 | 
				
			||||||
 | 
											SectionShow::Way::Forward,
 | 
				
			||||||
 | 
											id);
 | 
				
			||||||
 | 
									} else if (const auto strongTopic = weakTopic.get()) {
 | 
				
			||||||
 | 
										strong->showRepliesForMessage(
 | 
				
			||||||
 | 
											strongTopic->history(),
 | 
				
			||||||
 | 
											strongTopic->rootId(),
 | 
				
			||||||
 | 
											id,
 | 
				
			||||||
 | 
											SectionShow::Way::Forward);
 | 
				
			||||||
 | 
										strong->hideLayer(anim::type::normal);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
							if (!topic || weakTopic) {
 | 
				
			||||||
			session().api().resolveJumpToDate(chat, date, open);
 | 
								session().api().resolveJumpToDate(chat, date, open);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	show(Box<Ui::CalendarBox>(Ui::CalendarBoxArgs{
 | 
						show(Box<Ui::CalendarBox>(Ui::CalendarBoxArgs{
 | 
				
			||||||
		.month = highlighted,
 | 
							.month = highlighted,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue