mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Optimize stories list generation.
This commit is contained in:
parent
645ad5e1bd
commit
4fb03e532c
5 changed files with 57 additions and 69 deletions
|
@ -78,45 +78,19 @@ using UpdateFlag = StoryUpdate::Flag;
|
|||
|
||||
} // namespace
|
||||
|
||||
int IndexRespectingPinned(const StoriesIds &ids, StoryId id) {
|
||||
const auto i = ids.list.find(id);
|
||||
if (ids.pinnedToTop.empty() || i == end(ids.list)) {
|
||||
return int(i - begin(ids.list));
|
||||
}
|
||||
const auto j = ranges::find(ids.pinnedToTop, id);
|
||||
if (j != end(ids.pinnedToTop)) {
|
||||
return int(j - begin(ids.pinnedToTop));
|
||||
}
|
||||
auto result = int(i - begin(ids.list));
|
||||
for (const auto &pinnedId : ids.pinnedToTop) {
|
||||
if (pinnedId < id) {
|
||||
++result;
|
||||
}
|
||||
}
|
||||
|
||||
Ensures(result < int(ids.list.size()));
|
||||
return result;
|
||||
}
|
||||
|
||||
StoryId IdRespectingPinned(const StoriesIds &ids, int index) {
|
||||
Expects(index >= 0 && index < int(ids.list.size()));
|
||||
|
||||
std::vector<StoryId> RespectingPinned(const StoriesIds &ids) {
|
||||
if (ids.pinnedToTop.empty()) {
|
||||
return *(begin(ids.list) + index);
|
||||
} else if (index < int(ids.pinnedToTop.size())) {
|
||||
return ids.pinnedToTop[index];
|
||||
return ids.list | ranges::to_vector;
|
||||
}
|
||||
auto i = begin(ids.list) + index - int(ids.pinnedToTop.size());
|
||||
auto sorted = ids.pinnedToTop;
|
||||
ranges::sort(sorted, ranges::greater());
|
||||
for (const auto &pinnedId : sorted) {
|
||||
if (pinnedId >= *i) {
|
||||
++i;
|
||||
auto result = std::vector<StoryId>();
|
||||
result.reserve(ids.list.size());
|
||||
result.insert(end(result), begin(ids.pinnedToTop), end(ids.pinnedToTop));
|
||||
for (const auto &id : ids.list) {
|
||||
if (!ranges::contains(ids.pinnedToTop, id)) {
|
||||
result.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
Ensures(i != end(ids.list));
|
||||
return *i;
|
||||
return result;
|
||||
}
|
||||
|
||||
StoriesSourceInfo StoriesSource::info() const {
|
||||
|
|
|
@ -40,9 +40,7 @@ struct StoriesIds {
|
|||
const StoriesIds&) = default;
|
||||
};
|
||||
|
||||
// ids.list.size() if not found.
|
||||
[[nodiscard]] int IndexRespectingPinned(const StoriesIds &ids, StoryId id);
|
||||
[[nodiscard]] StoryId IdRespectingPinned(const StoriesIds &ids, int index);
|
||||
[[nodiscard]] std::vector<StoryId> RespectingPinned(const StoriesIds &ids);
|
||||
|
||||
struct StoriesSourceInfo {
|
||||
PeerId id = 0;
|
||||
|
|
|
@ -39,14 +39,15 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
|||
}
|
||||
|
||||
const auto &saved = stories->saved(peerId);
|
||||
const auto sorted = RespectingPinned(saved);
|
||||
const auto count = stories->savedCount(peerId);
|
||||
auto aroundIndex = IndexRespectingPinned(saved, aroundId);
|
||||
if (aroundIndex == int(saved.list.size())) {
|
||||
const auto around = saved.list.lower_bound(aroundId);
|
||||
aroundIndex = int(around - begin(saved.list));
|
||||
auto i = ranges::find(sorted, aroundId);
|
||||
if (i == end(sorted)) {
|
||||
const auto j = saved.list.lower_bound(aroundId);
|
||||
i = begin(sorted) + int(j - begin(saved.list));
|
||||
}
|
||||
const auto hasBefore = aroundIndex;
|
||||
const auto hasAfter = int(saved.list.size()) - aroundIndex;
|
||||
const auto hasBefore = int(i - begin(sorted));
|
||||
const auto hasAfter = int(end(sorted) - i);
|
||||
if (hasAfter < limit) {
|
||||
stories->savedLoadMore(peerId);
|
||||
}
|
||||
|
@ -54,8 +55,8 @@ rpl::producer<StoriesIdsSlice> SavedStoriesIds(
|
|||
const auto takeAfter = std::min(hasAfter, limit);
|
||||
auto ids = std::vector<StoryId>();
|
||||
ids.reserve(takeBefore + takeAfter);
|
||||
for (auto i = aroundIndex - takeBefore; i != aroundIndex + takeAfter; ++i) {
|
||||
ids.push_back(IdRespectingPinned(saved, i));
|
||||
for (auto j = i - takeBefore; j != i + takeAfter; ++j) {
|
||||
ids.push_back(*j);
|
||||
}
|
||||
const auto added = int(ids.size());
|
||||
state->slice = StoriesIdsSlice(
|
||||
|
@ -118,14 +119,15 @@ rpl::producer<StoriesIdsSlice> ArchiveStoriesIds(
|
|||
}
|
||||
|
||||
const auto &archive = stories->archive(peerId);
|
||||
const auto count = stories->archiveCount(peerId);
|
||||
auto aroundIndex = IndexRespectingPinned(archive, aroundId);
|
||||
if (aroundIndex == int(archive.list.size())) {
|
||||
const auto around = archive.list.lower_bound(aroundId);
|
||||
aroundIndex = int(around - begin(archive.list));
|
||||
const auto sorted = RespectingPinned(archive);
|
||||
const auto count = stories->savedCount(peerId);
|
||||
auto i = ranges::find(sorted, aroundId);
|
||||
if (i == end(sorted)) {
|
||||
const auto j = archive.list.lower_bound(aroundId);
|
||||
i = begin(sorted) + int(j - begin(archive.list));
|
||||
}
|
||||
const auto hasBefore = aroundIndex;
|
||||
const auto hasAfter = int(archive.list.size()) - aroundIndex;
|
||||
const auto hasBefore = int(i - begin(sorted));
|
||||
const auto hasAfter = int(end(sorted) - i);
|
||||
if (hasAfter < limit) {
|
||||
stories->archiveLoadMore(peerId);
|
||||
}
|
||||
|
@ -133,8 +135,8 @@ rpl::producer<StoriesIdsSlice> ArchiveStoriesIds(
|
|||
const auto takeAfter = std::min(hasAfter, limit);
|
||||
auto ids = std::vector<StoryId>();
|
||||
ids.reserve(takeBefore + takeAfter);
|
||||
for (auto i = aroundIndex - takeBefore; i != aroundIndex + takeAfter; ++i) {
|
||||
ids.push_back(IdRespectingPinned(archive, i));
|
||||
for (auto j = i - takeBefore; j != i + takeAfter; ++j) {
|
||||
ids.push_back(*j);
|
||||
}
|
||||
const auto added = int(ids.size());
|
||||
state->slice = StoriesIdsSlice(
|
||||
|
|
|
@ -77,8 +77,10 @@ struct SameDayRange {
|
|||
[[nodiscard]] SameDayRange ComputeSameDayRange(
|
||||
not_null<Data::Story*> story,
|
||||
const Data::StoriesIds &ids,
|
||||
const std::vector<StoryId> &sorted,
|
||||
int index) {
|
||||
Expects(index >= 0 && index < ids.list.size());
|
||||
Expects(index >= 0 && index < sorted.size());
|
||||
|
||||
const auto pinned = int(ids.pinnedToTop.size());
|
||||
if (index < pinned) {
|
||||
|
@ -90,7 +92,7 @@ struct SameDayRange {
|
|||
const auto stories = &story->owner().stories();
|
||||
const auto now = base::unixtime::parse(story->date());
|
||||
for (auto i = index; i != 0;) {
|
||||
const auto storyId = IdRespectingPinned(ids, --i);
|
||||
const auto storyId = sorted[--i];
|
||||
if (const auto maybeStory = stories->lookup({ peerId, storyId })) {
|
||||
const auto day = base::unixtime::parse((*maybeStory)->date());
|
||||
if (day.date() != now.date()) {
|
||||
|
@ -99,8 +101,8 @@ struct SameDayRange {
|
|||
}
|
||||
--result.from;
|
||||
}
|
||||
for (auto i = index + 1, c = int(ids.list.size()); i != c; ++i) {
|
||||
const auto storyId = IdRespectingPinned(ids, i);
|
||||
for (auto i = index + 1, c = int(sorted.size()); i != c; ++i) {
|
||||
const auto storyId = sorted[i];
|
||||
if (const auto maybeStory = stories->lookup({ peerId, storyId })) {
|
||||
const auto day = base::unixtime::parse((*maybeStory)->date());
|
||||
if (day.date() != now.date()) {
|
||||
|
@ -700,16 +702,19 @@ void Controller::rebuildFromContext(
|
|||
}, [&](StoriesContextSaved) {
|
||||
if (stories.savedCountKnown(peerId)) {
|
||||
const auto &saved = stories.saved(peerId);
|
||||
const auto i = IndexRespectingPinned(saved, id);
|
||||
if (i < saved.list.size()) {
|
||||
auto sorted = RespectingPinned(saved);
|
||||
const auto i = ranges::find(sorted, id);
|
||||
const auto tillEnd = int(end(sorted) - i);
|
||||
if (tillEnd > 0) {
|
||||
_index = int(i - begin(sorted));
|
||||
list = StoriesList{
|
||||
.peer = peer,
|
||||
.ids = saved,
|
||||
.sorted = std::move(sorted),
|
||||
.total = stories.savedCount(peerId),
|
||||
};
|
||||
_index = i;
|
||||
if (saved.list.size() < list->total
|
||||
&& (saved.list.size() - i) < kPreloadStoriesCount) {
|
||||
&& tillEnd < kPreloadStoriesCount) {
|
||||
stories.savedLoadMore(peerId);
|
||||
}
|
||||
}
|
||||
|
@ -718,16 +723,19 @@ void Controller::rebuildFromContext(
|
|||
}, [&](StoriesContextArchive) {
|
||||
if (stories.archiveCountKnown(peerId)) {
|
||||
const auto &archive = stories.archive(peerId);
|
||||
const auto i = IndexRespectingPinned(archive, id);
|
||||
if (i < archive.list.size()) {
|
||||
auto sorted = RespectingPinned(archive);
|
||||
const auto i = ranges::find(sorted, id);
|
||||
const auto tillEnd = int(end(sorted) - i);
|
||||
if (tillEnd > 0) {
|
||||
_index = int(i - begin(sorted));
|
||||
list = StoriesList{
|
||||
.peer = peer,
|
||||
.ids = archive,
|
||||
.sorted = std::move(sorted),
|
||||
.total = stories.archiveCount(peerId),
|
||||
};
|
||||
_index = i;
|
||||
if (archive.list.size() < list->total
|
||||
&& (archive.list.size() - i) < kPreloadStoriesCount) {
|
||||
&& tillEnd < kPreloadStoriesCount) {
|
||||
stories.archiveLoadMore(peerId);
|
||||
}
|
||||
}
|
||||
|
@ -761,7 +769,11 @@ void Controller::rebuildFromContext(
|
|||
}
|
||||
if (const auto maybe = peer->owner().stories().lookup(storyId)) {
|
||||
const auto now = *maybe;
|
||||
const auto range = ComputeSameDayRange(now, _list->ids, _index);
|
||||
const auto range = ComputeSameDayRange(
|
||||
now,
|
||||
_list->ids,
|
||||
_list->sorted,
|
||||
_index);
|
||||
_sliderCount = range.till - range.from + 1;
|
||||
_sliderIndex = _index - range.from;
|
||||
}
|
||||
|
@ -779,6 +791,7 @@ void Controller::rebuildFromContext(
|
|||
_list = StoriesList{
|
||||
.peer = peer,
|
||||
.ids = { { id } },
|
||||
.sorted = { id },
|
||||
.total = 1,
|
||||
};
|
||||
_index = 0;
|
||||
|
@ -1523,8 +1536,8 @@ StoryId Controller::shownId(int index) const {
|
|||
|
||||
return _source
|
||||
? (_source->ids.begin() + index)->id
|
||||
: (index < int(_list->ids.list.size()))
|
||||
? IdRespectingPinned(_list->ids, index)
|
||||
: (index < int(_list->sorted.size()))
|
||||
? _list->sorted[index]
|
||||
: StoryId();
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ private:
|
|||
struct StoriesList {
|
||||
not_null<PeerData*> peer;
|
||||
Data::StoriesIds ids;
|
||||
std::vector<StoryId> sorted;
|
||||
int total = 0;
|
||||
|
||||
friend inline bool operator==(
|
||||
|
|
Loading…
Add table
Reference in a new issue