Improve adaptive loading in subsection tabs.

This commit is contained in:
John Preston 2025-06-05 10:45:06 +04:00
parent d25356917d
commit e92adf94a7
2 changed files with 44 additions and 27 deletions

View file

@ -241,45 +241,24 @@ void SubsectionTabs::setupSlider(
: scroll->scrollLeftMax();
const auto availableFrom = scrollValue;
const auto availableTill = (scrollMax - scrollValue);
if (scrollMax <= 3 * full && _afterAvailable > 0) {
const auto needMore = (scrollMax <= 3 * full && _afterAvailable > 0);
if (needMore) {
_beforeLimit *= 2;
_afterLimit *= 2;
}
const auto findMiddle = [&] {
Expects(!_slice.empty());
auto best = -1;
auto bestDistance = -1;
const auto ideal = scrollValue + (full / 2);
for (auto i = 0, count = int(_slice.size()); i != count; ++i) {
const auto a = slider->lookupSectionPosition(i);
const auto b = (i + 1 == count)
? (full + scrollMax)
: slider->lookupSectionPosition(i + 1);
const auto middle = (a + b) / 2;
const auto distance = std::abs(middle - ideal);
if (best < 0 || distance < bestDistance) {
best = i;
bestDistance = distance;
}
}
Ensures(best >= 0);
return best;
};
if (availableFrom < full
&& _beforeSkipped.value_or(0) > 0
&& !_slice.empty()) {
_around = _slice[findMiddle()].thread;
refreshSlice();
refreshAroundMiddle(scroll, slider);
} else if (availableTill < full) {
if (_afterAvailable > 0) {
_around = _slice[findMiddle()].thread;
refreshSlice();
refreshAroundMiddle(scroll, slider);
} else if (!_afterSkipped.has_value()) {
_loading = true;
loadMore();
}
} else if (needMore) {
refreshAroundMiddle(scroll, slider);
}
}, scroll->lifetime());
@ -641,6 +620,41 @@ void SubsectionTabs::track() {
}
}
void SubsectionTabs::refreshAroundMiddle(
not_null<Ui::ScrollArea*> scroll,
not_null<Ui::SubsectionSlider*> slider) {
Expects(!_slice.empty());
const auto full = _vertical ? scroll->height() : scroll->width();
const auto scrollValue = _vertical
? scroll->scrollTop()
: scroll->scrollLeft();
const auto scrollMax = _vertical
? scroll->scrollTopMax()
: scroll->scrollLeftMax();
auto best = -1;
auto bestDistance = -1;
const auto ideal = scrollValue + (full / 2);
for (auto i = 0, count = int(_slice.size()); i != count; ++i) {
const auto a = slider->lookupSectionPosition(i);
const auto b = (i + 1 == count)
? (full + scrollMax)
: slider->lookupSectionPosition(i + 1);
const auto middle = (a + b) / 2;
const auto distance = std::abs(middle - ideal);
if (best < 0 || distance < bestDistance) {
best = i;
bestDistance = distance;
}
}
Assert(best >= 0 && best < _slice.size());
_around = _slice[best].thread;
refreshSlice();
}
void SubsectionTabs::refreshSlice() {
_refreshScheduled = false;

View file

@ -83,6 +83,9 @@ private:
void toggleModes();
void setVisible(bool shown);
void refreshSlice();
void refreshAroundMiddle(
not_null<Ui::ScrollArea*> scroll,
not_null<Ui::SubsectionSlider*> slider);
void scheduleRefresh();
void loadMore();
void setup(not_null<Ui::RpWidget*> parent);