Added initial ability to info list widget to jump to date.

This commit is contained in:
23rd
2026-01-08 08:15:09 +03:00
parent d80cd8d7aa
commit 9e434a9136
9 changed files with 158 additions and 0 deletions
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/data_search_controller.h"
#include "base/unixtime.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_messages.h"
@@ -334,6 +335,79 @@ HistoryResult ParseHistoryResult(
data);
}
std::optional<SearchRequest> PrepareSearchRequestByDate(
not_null<PeerData*> peer,
MsgId topicRootId,
PeerId monoforumPeerId,
Storage::SharedMediaType type,
const QDate &date,
Data::LoadDirection direction) {
const auto filter = PrepareSearchFilter(type);
const auto minDate = base::unixtime::serialize(
QDateTime(date, QTime(0, 0)));
const auto maxDate = base::unixtime::serialize(
QDateTime(date.addDays(1), QTime(0, 0))) - 1;
const auto limit = kSharedMediaLimit;
const auto offsetId = 0;
const auto addOffset = 0;
const auto hash = uint64(0);
using Flag = MTPmessages_Search::Flag;
return MTPmessages_Search(
MTP_flags((topicRootId ? Flag::f_top_msg_id : Flag(0))
| (monoforumPeerId ? Flag::f_saved_peer_id : Flag(0))),
peer->input(),
MTP_string(""),
MTP_inputPeerEmpty(),
(monoforumPeerId
? peer->owner().peer(monoforumPeerId)->input()
: MTPInputPeer()),
MTPVector<MTPReaction>(),
MTP_int(topicRootId),
filter,
MTP_int(minDate),
MTP_int(maxDate),
MTP_int(offsetId),
MTP_int(addOffset),
MTP_int(limit),
MTP_int(0),
MTP_int(0),
MTP_long(hash));
}
SearchResultByDate ParseSearchResultByDate(
not_null<PeerData*> peer,
const QDate &date,
const SearchResult &parsed) {
const auto targetDate = base::unixtime::serialize(
QDateTime(date, QTime(0, 0)));
auto result = SearchResultByDate();
if (parsed.messageIds.empty()) {
return result;
}
const auto firstMsgId = parsed.messageIds.front();
result.first = Data::MessagePosition{
.fullId = FullMsgId(peer->id, firstMsgId),
.date = TimeId(0),
};
auto closestMsgId = firstMsgId;
auto minDiff = std::numeric_limits<TimeId>::max();
for (const auto msgId : parsed.messageIds) {
if (const auto item = peer->owner().message(peer->id, msgId)) {
const auto diff = std::abs(item->date() - targetDate);
if (diff < minDiff) {
minDiff = diff;
closestMsgId = msgId;
}
}
}
result.closestToDate = Data::MessagePosition{
.fullId = FullMsgId(peer->id, closestMsgId),
.date = TimeId(0),
};
return result;
}
SearchController::CacheEntry::CacheEntry(
not_null<Main::Session*> session,
const Query &query)
@@ -44,6 +44,11 @@ struct GlobalMediaResult {
int fullCount = 0;
};
struct SearchResultByDate {
Data::MessagePosition first;
Data::MessagePosition closestToDate;
};
[[nodiscard]] MTPMessagesFilter PrepareSearchFilter(
Storage::SharedMediaType type);
@@ -74,6 +79,19 @@ struct GlobalMediaResult {
Data::LoadDirection direction,
const SearchRequestResult &data);
[[nodiscard]] std::optional<SearchRequest> PrepareSearchRequestByDate(
not_null<PeerData*> peer,
MsgId topicRootId,
PeerId monoforumPeerId,
Storage::SharedMediaType type,
const QDate &date,
Data::LoadDirection direction);
[[nodiscard]] SearchResultByDate ParseSearchResultByDate(
not_null<PeerData*> peer,
const QDate &date,
const SearchResult &parsed);
[[nodiscard]] HistoryRequest PrepareHistoryRequest(
not_null<PeerData*> peer,
MsgId messageId,
@@ -245,5 +245,9 @@ rpl::producer<Ui::ScrollToRequest> InnerWidget::scrollToRequests() const {
return _scrollToRequests.events();
}
void InnerWidget::jumpToDate(const QDate &date, Fn<void(FullMsgId)> c) {
_list->jumpToDate(date, std::move(c));
}
} // namespace Media
} // namespace Info
@@ -49,6 +49,8 @@ public:
rpl::producer<SelectedItems> selectedListValue() const;
void selectionAction(SelectionAction action);
void jumpToDate(const QDate &date, Fn<void(FullMsgId)> callback);
~InnerWidget();
protected:
@@ -2713,5 +2713,19 @@ ListWidget::~ListWidget() {
}
}
void ListWidget::jumpToDate(const QDate &date, Fn<void(FullMsgId)> c) {
_provider->jumpToDate(date, [=](FullMsgId fullId) {
const auto item = session().data().message(fullId);
if (!item) {
return;
}
_scrollTopState.position = _provider->scrollTopStatePosition(item);
_scrollTopState.item = item;
if (c) {
c(fullId);
}
});
}
} // namespace Media
} // namespace Info
@@ -87,6 +87,8 @@ public:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);
void jumpToDate(const QDate &date, Fn<void(FullMsgId)> callback);
// Overview::Layout::Delegate
void registerHeavyItem(not_null<const BaseLayout*> item) override;
void unregisterHeavyItem(not_null<const BaseLayout*> item) override;
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "info/media/info_media_provider.h"
#include "apiwrap.h"
#include "info/media/info_media_widget.h"
#include "info/media/info_media_list_section.h"
#include "info/info_controller.h"
@@ -343,6 +344,43 @@ void Provider::setSearchQuery(QString query) {
}
void Provider::jumpToDate(const QDate &date, Fn<void(FullMsgId)> callback) {
_viewerLifetime.destroy();
const auto peer = _controller->session().data().peer(_peer->id);
const auto request = Api::PrepareSearchRequestByDate(
peer,
_topicRootId,
_monoforumPeerId,
_type,
date,
Data::LoadDirection::Around);
if (!request) {
return;
}
_controller->session().api().request(
std::move(*request)
).done([=](const Api::SearchRequestResult &result) {
const auto byDate = Api::ParseSearchResultByDate(
peer,
date,
Api::ParseSearchResult(
peer,
_type,
0,
Data::LoadDirection::Around,
result));
if (byDate.first) {
_universalAroundId = GetUniversalId(byDate.first.fullId);
if (callback) {
callback(byDate.closestToDate.fullId);
}
_idsLimit = kMinimalIdsLimit * 2;
refreshViewer();
}
}).send();
}
SparseIdsMergedSlice::Key Provider::sliceKey(
@@ -198,4 +198,8 @@ void Widget::restoreState(not_null<Memento*> memento) {
_inner->restoreState(memento);
}
void Widget::jumpToDate(const QDate &date, Fn<void(FullMsgId)> c) {
_inner->jumpToDate(date, std::move(c));
}
} // namespace Info::Media
@@ -127,6 +127,8 @@ public:
rpl::producer<QString> title() override;
void jumpToDate(const QDate &date, Fn<void(FullMsgId)> callback);
private:
void saveState(not_null<Memento*> memento);
void restoreState(not_null<Memento*> memento);