Correctly load tab slices.

This commit is contained in:
John Preston 2025-05-23 17:33:47 +04:00
parent fdbdeeb956
commit 72b57924b7
5 changed files with 164 additions and 28 deletions

View file

@ -7657,10 +7657,6 @@ void HistoryWidget::setupTranslateBar() {
}, _translateBar->lifetime());
orderWidgets();
if (_showAnimation) {
_translateBar->hide();
}
}
void HistoryWidget::setupPinnedTracker() {
@ -7803,10 +7799,6 @@ void HistoryWidget::checkPinnedBarState() {
}, _pinnedBar->lifetime());
orderWidgets();
if (_showAnimation) {
_pinnedBar->hide();
}
}
void HistoryWidget::clearHidingPinnedBar() {
@ -7966,10 +7958,6 @@ void HistoryWidget::setupGroupCallBar() {
}, _groupCallBar->lifetime());
orderWidgets();
if (_showAnimation) {
_groupCallBar->hide();
}
}
void HistoryWidget::setupRequestsBar() {
@ -8013,10 +8001,6 @@ void HistoryWidget::setupRequestsBar() {
}, _requestsBar->lifetime());
orderWidgets();
if (_showAnimation) {
_requestsBar->hide();
}
}
void HistoryWidget::requestMessageData(MsgId msgId) {

View file

@ -30,7 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace HistoryView {
namespace {
constexpr auto kDefaultLimit = 10;
constexpr auto kDefaultLimit = 5;AssertIsDebug()// 10;
} // namespace
@ -91,6 +91,54 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
}
}, tabs->lifetime());
scroll->setCustomWheelProcess([=](not_null<QWheelEvent*> e) {
const auto pixelDelta = e->pixelDelta();
const auto angleDelta = e->angleDelta();
if (std::abs(pixelDelta.x()) + std::abs(angleDelta.x())) {
return false;
}
const auto y = pixelDelta.y() ? pixelDelta.y() : angleDelta.y();
scroll->scrollToX(scroll->scrollLeft() - y);
return true;
});
rpl::merge(
scroll->scrolls(),
_scrollCheckRequests.events(),
scroll->widthValue() | rpl::skip(1) | rpl::map_to(rpl::empty)
) | rpl::start_with_next([=] {
const auto width = scroll->width();
const auto left = scroll->scrollLeft();
const auto max = scroll->scrollLeftMax();
const auto availableLeft = left;
const auto availableRight = (max - left);
if (max <= 2 * width && _afterAvailable > 0) {
_beforeLimit *= 2;
_afterLimit *= 2;
}
if (availableLeft < width
&& _beforeSkipped.value_or(0) > 0
&& !_slice.empty()) {
_around = _slice.front();
refreshSlice();
} else if (availableRight < width) {
if (_afterAvailable > 0) {
_around = _slice.back();
refreshSlice();
} else if (!_afterSkipped.has_value()) {
_loading = true;
loadMore();
}
}
}, _horizontal->lifetime());
dataChanged() | rpl::start_with_next([=] {
if (_loading) {
_loading = false;
refreshSlice();
}
}, _horizontal->lifetime());
_horizontal->sizeValue(
) | rpl::start_with_next([=](QSize size) {
const auto togglew = toggle->width();
@ -127,14 +175,62 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
Ui::Text::WithEntities));
}
}
const auto paused = [=] {
return _controller->isGifPausedAtLeastFor(
Window::GifPauseReason::Any);
};
auto scrollSavingThread = (Data::Thread*)nullptr;
auto scrollSavingShift = 0;
auto scrollSavingIndex = -1;
if (const auto count = tabs->sectionsCount()) {
const auto scrollLeft = scroll->scrollLeft();
auto indexLeft = tabs->lookupSectionLeft(0);
for (auto index = 0; index != count; ++index) {
const auto nextLeft = (index + 1 != count)
? tabs->lookupSectionLeft(index + 1)
: (indexLeft + scrollLeft + 1);
if (indexLeft <= scrollLeft && nextLeft > scrollLeft) {
scrollSavingThread = _sectionsSlice[index];
scrollSavingShift = scrollLeft - indexLeft;
break;
}
indexLeft = nextLeft;
}
scrollSavingIndex = scrollSavingThread
? int(ranges::find(_slice, not_null(scrollSavingThread))
- begin(_slice))
: -1;
if (scrollSavingIndex == _slice.size()) {
scrollSavingIndex = -1;
for (auto index = 0; index != count; ++index) {
const auto thread = _sectionsSlice[index];
if (ranges::contains(_slice, thread)) {
scrollSavingThread = thread;
scrollSavingShift = scrollLeft
- tabs->lookupSectionLeft(index);
scrollSavingIndex = index;
break;
}
}
}
}
tabs->setSections(sections, Core::TextContext({
.session = &_history->session(),
}));
}), paused);
tabs->fitWidthToSections();
tabs->setActiveSectionFast(activeIndex);
_sectionsSlice = _slice;
_horizontal->resize(
tabs->width(),
_horizontal->width(),
std::max(toggle->height(), tabs->height()));
if (scrollSavingIndex >= 0) {
scroll->scrollToX(tabs->lookupSectionLeft(scrollSavingIndex)
+ scrollSavingShift);
}
_scrollCheckRequests.fire({});
}, _horizontal->lifetime());
}
@ -179,6 +275,26 @@ void SubsectionTabs::setupVertical(not_null<QWidget*> parent) {
}, _vertical->lifetime());
}
void SubsectionTabs::loadMore() {
if (const auto forum = _history->peer->forum()) {
forum->requestTopics();
} else if (const auto monoforum = _history->peer->monoforum()) {
monoforum->loadMore();
} else {
Unexpected("Peer in SubsectionTabs::loadMore.");
}
}
rpl::producer<> SubsectionTabs::dataChanged() const {
if (const auto forum = _history->peer->forum()) {
return forum->chatsListChanges();
} else if (const auto monoforum = _history->peer->monoforum()) {
return monoforum->chatsListChanges();
} else {
Unexpected("Peer in SubsectionTabs::dataChanged.");
}
}
void SubsectionTabs::toggleModes() {
Expects((_horizontal || _vertical) && _shadow);
@ -323,6 +439,8 @@ void SubsectionTabs::refreshSlice() {
});
if (!list) {
slice.push_back(_history);
_beforeSkipped = _afterSkipped = 0;
_afterAvailable = 0;
return;
}
const auto &chats = list->indexed()->all();
@ -339,9 +457,8 @@ void SubsectionTabs::refreshSlice() {
const auto from = i - takeBefore;
const auto till = i + takeAfter;
_beforeSkipped = std::max(0, int(from - chats.begin()));
_afterSkipped = list->loaded()
? std::max(0, int(chats.end() - till))
: std::optional<int>();
_afterAvailable = std::max(0, int(chats.end() - till));
_afterSkipped = list->loaded() ? _afterAvailable : std::optional<int>();
if (from == chats.begin()) {
slice.push_back(_history);
}
@ -358,6 +475,7 @@ bool SubsectionTabs::switchTo(
if (thread->owningHistory() != _history) {
return false;
}
_active = thread;
if (_vertical) {
_vertical->setParent(parent);
_vertical->show();

View file

@ -57,6 +57,8 @@ private:
void toggleModes();
void setVisible(bool shown);
void refreshSlice();
void loadMore();
[[nodiscard]] rpl::producer<> dataChanged() const;
const not_null<Window::SessionController*> _controller;
const not_null<History*> _history;
@ -66,16 +68,20 @@ private:
Ui::RpWidget *_shadow = nullptr;
std::vector<not_null<Data::Thread*>> _slice;
std::vector<not_null<Data::Thread*>> _sectionsSlice;
not_null<Data::Thread*> _active;
not_null<Data::Thread*> _around;
int _beforeLimit = 0;
int _afterLimit = 0;
int _afterAvailable = 0;
bool _loading = false;
std::optional<int> _beforeSkipped;
std::optional<int> _afterSkipped;
rpl::event_stream<> _layoutRequests;
rpl::event_stream<> _refreshed;
rpl::event_stream<> _scrollCheckRequests;
rpl::lifetime _lifetime;

View file

@ -50,6 +50,7 @@ void DiscreteSlider::setActiveSectionFast(int index) {
void DiscreteSlider::finishAnimating() {
_a_left.stop();
_a_width.stop();
update();
_callbackAfterMs = 0;
if (_timerId >= 0) {
@ -64,10 +65,24 @@ void DiscreteSlider::setAdditionalContentWidthToSection(int index, int w) {
}
}
int DiscreteSlider::sectionsCount() const {
return int(_sections.size());
}
int DiscreteSlider::lookupSectionLeft(int index) const {
Expects(index >= 0 && index < _sections.size());
return _sections[index].left;
}
void DiscreteSlider::setSelectOnPress(bool selectOnPress) {
_selectOnPress = selectOnPress;
}
bool DiscreteSlider::paused() const {
return _paused && _paused();
}
std::vector<DiscreteSlider::Section> &DiscreteSlider::sectionsRef() {
return _sections;
}
@ -97,7 +112,8 @@ void DiscreteSlider::setSections(const std::vector<QString> &labels) {
void DiscreteSlider::setSections(
const std::vector<TextWithEntities> &labels,
Text::MarkedContext context) {
Text::MarkedContext context,
Fn<bool()> paused) {
Assert(!labels.empty());
context.repaint = [this] { update(); };
@ -106,6 +122,7 @@ void DiscreteSlider::setSections(
for (const auto &label : labels) {
_sections.push_back(Section(label, getLabelStyle(), context));
}
_paused = std::move(paused);
refresh();
}
@ -122,7 +139,9 @@ void DiscreteSlider::refresh() {
}
DiscreteSlider::Range DiscreteSlider::getFinalActiveRange() const {
const auto raw = _sections.empty() ? nullptr : &_sections[_selected];
const auto raw = (_sections.empty() || _selected < 0)
? nullptr
: &_sections[_selected];
if (!raw) {
return { 0, 0 };
}
@ -193,7 +212,7 @@ void DiscreteSlider::mouseReleaseEvent(QMouseEvent *e) {
}
void DiscreteSlider::setSelectedSection(int index) {
if (index < 0 || index >= _sections.size()) {
if (index >= int(_sections.size())) {
return;
}
@ -414,9 +433,10 @@ void SettingsSlider::paintEvent(QPaintEvent *e) {
: section.width;
const auto activeLeft = section.left
+ (section.width - activeWidth) / 2;
const auto divider = std::max(std::min(activeWidth, range.width), 1);
const auto active = 1.
- std::clamp(
std::abs(range.left - activeLeft) / float64(range.width),
std::abs(range.left - activeLeft) / float64(divider),
0.,
1.);
if (section.ripple) {
@ -467,6 +487,7 @@ void SettingsSlider::paintEvent(QPaintEvent *e) {
.position = QPoint(labelLeft, _st.labelTop),
.outerWidth = width(),
.availableWidth = section.label.maxWidth(),
.paused = paused(),
});
}
return true;

View file

@ -37,7 +37,8 @@ public:
void setSections(const std::vector<QString> &labels);
void setSections(
const std::vector<TextWithEntities> &labels,
Text::MarkedContext context = {});
Text::MarkedContext context = {},
Fn<bool()> paused = nullptr);
int activeSection() const {
return _activeIndex;
}
@ -51,6 +52,9 @@ public:
return _sectionActivated.events();
}
[[nodiscard]] int sectionsCount() const;
[[nodiscard]] int lookupSectionLeft(int index) const;
protected:
void timerEvent(QTimerEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
@ -98,7 +102,9 @@ protected:
void setSelectOnPress(bool selectOnPress);
std::vector<Section> &sectionsRef();
[[nodiscard]] std::vector<Section> &sectionsRef();
[[nodiscard]] bool paused() const;
private:
void activateCallback();
@ -109,6 +115,7 @@ private:
void setSelectedSection(int index);
std::vector<Section> _sections;
Fn<bool()> _paused;
int _activeIndex = 0;
bool _selectOnPress = true;
bool _snapToLabel = false;