mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-27 07:52:57 +02:00
Correctly load tab slices.
This commit is contained in:
parent
fdbdeeb956
commit
72b57924b7
5 changed files with 164 additions and 28 deletions
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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> §ionsRef();
|
||||
[[nodiscard]] std::vector<Section> §ionsRef();
|
||||
|
||||
[[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;
|
||||
|
|
Loading…
Add table
Reference in a new issue