Reuse filters slider scroll for search.

This commit is contained in:
John Preston 2024-12-13 13:32:51 +04:00
parent 5072e95f16
commit 04e9eed88d
8 changed files with 104 additions and 60 deletions

View file

@ -689,7 +689,11 @@ recentPeersSpecialName: PeerListItem(recentPeersItem) {
namePosition: point(64px, 19px);
}
dialogsTabsScroll: ScrollArea(defaultScrollArea) {
barHidden: true;
}
dialogsSearchTabs: SettingsSlider(defaultSettingsSlider) {
padding: 8px;
height: 33px;
barTop: 30px;
barSkip: 0px;
@ -707,7 +711,6 @@ dialogsSearchTabs: SettingsSlider(defaultSettingsSlider) {
rippleBgActive: lightButtonBgOver;
ripple: defaultRippleAnimation;
}
dialogsSearchTabsPadding: 8px;
chatsFiltersTabs: SettingsSlider(dialogsSearchTabs) {
rippleBottomSkip: 0px;

View file

@ -1292,7 +1292,11 @@ Suggestions::Suggestions(
RecentPeersList recentPeers)
: RpWidget(parent)
, _controller(controller)
, _tabs(std::make_unique<Ui::SettingsSlider>(this, st::dialogsSearchTabs))
, _tabsScroll(
std::make_unique<Ui::ScrollArea>(this, st::dialogsTabsScroll, true))
, _tabs(
_tabsScroll->setOwnedWidget(
object_ptr<Ui::SettingsSlider>(this, st::dialogsSearchTabs)))
, _chatsScroll(std::make_unique<Ui::ElasticScroll>(this))
, _chatsContent(
_chatsScroll->setOwnedWidget(object_ptr<Ui::VerticalLayout>(this)))
@ -1314,7 +1318,6 @@ Suggestions::Suggestions(
_appsScroll->setOwnedWidget(object_ptr<Ui::VerticalLayout>(this)))
, _recentApps(setupRecentApps())
, _popularApps(setupPopularApps()) {
setupTabs();
setupChats();
setupChannels();
@ -1324,10 +1327,46 @@ Suggestions::Suggestions(
Suggestions::~Suggestions() = default;
void Suggestions::setupTabs() {
_tabsScroll->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();
_tabsScroll->scrollToX(_tabsScroll->scrollLeft() - y);
return true;
});
const auto scrollToIndex = [=](int index, anim::type type) {
const auto to = index
? (_tabs->centerOfSection(index) - _tabsScroll->width() / 2)
: 0;
_tabsScrollAnimation.stop();
if (type == anim::type::instant) {
_tabsScroll->scrollToX(to);
} else {
_tabsScrollAnimation.start(
[=](float64 v) { _tabsScroll->scrollToX(v); },
_tabsScroll->scrollLeft(),
std::min(to, _tabsScroll->scrollLeftMax()),
st::defaultTabsSlider.duration);
}
};
rpl::single(-1) | rpl::then(
_tabs->sectionActivated()
) | rpl::combine_previous(
) | rpl::start_with_next([=](int was, int index) {
if (was != index) {
scrollToIndex(index, anim::type::normal);
}
}, _tabs->lifetime());
const auto shadow = Ui::CreateChild<Ui::PlainShadow>(this);
shadow->lower();
_tabs->move(st::dialogsSearchTabsPadding, 0);
_tabsScroll->move(0, 0);
_tabs->move(0, 0);
rpl::combine(
widthValue(),
_tabs->heightValue()
@ -1338,11 +1377,12 @@ void Suggestions::setupTabs() {
shadow->showOn(_tabs->shownValue());
_tabs->setSections({
auto sections = std::vector<QString>{
tr::lng_recent_chats(tr::now),
tr::lng_recent_channels(tr::now),
tr::lng_recent_apps(tr::now),
});
};
_tabs->setSections(sections);
_tabs->sectionActivated(
) | rpl::start_with_next([=](int section) {
switchTab(section == 2
@ -1808,7 +1848,7 @@ void Suggestions::startShownAnimation(bool shown, Fn<void()> finish) {
resize(now, height());
}
}
_tabs->hide();
_tabsScroll->hide();
_chatsScroll->hide();
_channelsScroll->hide();
_appsScroll->hide();
@ -1823,7 +1863,7 @@ void Suggestions::finishShow() {
_shownAnimation.stop();
_cache = QPixmap();
_tabs->show();
_tabsScroll->show();
const auto tab = _tab.current();
_chatsScroll->setVisible(tab == Tab::Chats);
_channelsScroll->setVisible(tab == Tab::Channels);
@ -1864,8 +1904,10 @@ void Suggestions::paintEvent(QPaintEvent *e) {
void Suggestions::resizeEvent(QResizeEvent *e) {
const auto w = std::max(width(), st::columnMinimalWidthLeft);
_tabs->resizeToWidth(w);
_tabs->fitWidthToSections();
const auto tabs = _tabs->height();
_tabsScroll->setGeometry(0, 0, w, tabs);
_chatsScroll->setGeometry(0, tabs, w, height() - tabs);
_chatsContent->resizeToWidth(w);

View file

@ -24,6 +24,7 @@ class Session;
namespace Ui {
class BoxContent;
class ScrollArea;
class ElasticScroll;
class SettingsSlider;
class VerticalLayout;
@ -169,7 +170,9 @@ private:
const not_null<Window::SessionController*> _controller;
const std::unique_ptr<Ui::SettingsSlider> _tabs;
const std::unique_ptr<Ui::ScrollArea> _tabsScroll;
const not_null<Ui::SettingsSlider*> _tabs;
Ui::Animations::Simple _tabsScrollAnimation;
rpl::variable<Tab> _tab = Tab::Chats;
const std::unique_ptr<Ui::ElasticScroll> _chatsScroll;

View file

@ -15,18 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QScrollBar>
namespace Ui {
namespace {
[[nodiscard]] QMouseEvent TranslatedMouseEvent(QMouseEvent *e) {
return QMouseEvent(
e->type(),
e->pos() + QPoint(-st::dialogsSearchTabsPadding, 0),
e->button(),
e->buttons(),
e->modifiers());
}
} // namespace
ChatsFiltersTabs::ChatsFiltersTabs(
not_null<Ui::RpWidget*> parent,
@ -77,22 +65,9 @@ bool ChatsFiltersTabs::setSectionsAndCheckChanged(
return changed;
}
int ChatsFiltersTabs::centerOfSection(int section) const {
const auto widths = countSectionsWidths(0);
auto result = 0;
if (section >= 0 && section < widths.size()) {
for (auto i = 0; i < section; i++) {
result += widths[i];
}
result += widths[section] / 2;
}
return result;
}
void ChatsFiltersTabs::fitWidthToSections() {
const auto widths = countSectionsWidths(0);
const auto sliderPadding = st::dialogsSearchTabsPadding;
resizeToWidth(ranges::accumulate(widths, .0) + sliderPadding * 2);
SettingsSlider::fitWidthToSections();
_lockedFromX = calculateLockedFromX();
{
@ -197,8 +172,6 @@ void ChatsFiltersTabs::paintEvent(QPaintEvent *e) {
const auto range = getCurrentActiveRange();
const auto activeIndex = activeSection();
p.translate(st::dialogsSearchTabsPadding, 0);
auto index = 0;
auto raisedIndex = -1;
auto activeHorizontalShift = 0;
@ -310,32 +283,29 @@ void ChatsFiltersTabs::paintEvent(QPaintEvent *e) {
}
void ChatsFiltersTabs::mousePressEvent(QMouseEvent *e) {
auto m = TranslatedMouseEvent(e);
const auto mouseButton = m.button();
const auto mouseButton = e->button();
if (mouseButton == Qt::MouseButton::LeftButton) {
_lockedPressed = (m.pos().x() >= _lockedFromX);
_lockedPressed = (e->pos().x() >= _lockedFromX);
if (_lockedPressed) {
Ui::RpWidget::mousePressEvent(&m);
Ui::RpWidget::mousePressEvent(e);
} else {
Ui::SettingsSlider::mousePressEvent(&m);
Ui::SettingsSlider::mousePressEvent(e);
}
} else {
Ui::RpWidget::mousePressEvent(&m);
Ui::RpWidget::mousePressEvent(e);
}
}
void ChatsFiltersTabs::mouseMoveEvent(QMouseEvent *e) {
auto m = TranslatedMouseEvent(e);
if (_reordering) {
Ui::RpWidget::mouseMoveEvent(&m);
Ui::RpWidget::mouseMoveEvent(e);
} else {
Ui::SettingsSlider::mouseMoveEvent(&m);
Ui::SettingsSlider::mouseMoveEvent(e);
}
}
void ChatsFiltersTabs::mouseReleaseEvent(QMouseEvent *e) {
auto m = TranslatedMouseEvent(e);
const auto mouseButton = m.button();
const auto mouseButton = e->button();
if (mouseButton == Qt::MouseButton::LeftButton) {
if (base::take(_lockedPressed)) {
_lockedPressed = false;
@ -348,16 +318,16 @@ void ChatsFiltersTabs::mouseReleaseEvent(QMouseEvent *e) {
}
}
} else {
Ui::SettingsSlider::mouseReleaseEvent(&m);
Ui::SettingsSlider::mouseReleaseEvent(e);
}
}
} else {
Ui::RpWidget::mouseReleaseEvent(&m);
Ui::RpWidget::mouseReleaseEvent(e);
}
}
void ChatsFiltersTabs::contextMenuEvent(QContextMenuEvent *e) {
const auto pos = e->pos() + QPoint(-st::dialogsSearchTabsPadding, 0);
const auto pos = e->pos();
if (pos.x() >= _lockedFromX) {
return;
}

View file

@ -29,8 +29,7 @@ public:
bool setSectionsAndCheckChanged(std::vector<QString> &&sections);
[[nodiscard]] int centerOfSection(int section) const;
void fitWidthToSections();
void fitWidthToSections() override;
void setUnreadCount(int index, int unreadCount, bool muted);
void setLockedFrom(int index);

View file

@ -180,7 +180,6 @@ not_null<Ui::RpWidget*> AddChatFiltersTabsStrip(
Window::SessionController *controller,
bool trackActiveFilterAndUnreadAndReorder) {
const auto &scrollSt = st::defaultScrollArea;
const auto wrap = Ui::CreateChild<Ui::SlideWrap<Ui::RpWidget>>(
parent,
object_ptr<Ui::RpWidget>(parent));
@ -194,7 +193,7 @@ not_null<Ui::RpWidget*> AddChatFiltersTabsStrip(
const auto container = wrap->entity();
const auto scroll = Ui::CreateChild<Ui::ScrollArea>(
container,
scrollSt,
st::dialogsTabsScroll,
true);
const auto slider = scroll->setOwnedWidget(
object_ptr<Ui::ChatsFiltersTabs>(
@ -457,7 +456,7 @@ not_null<Ui::RpWidget*> AddChatFiltersTabsStrip(
parent->widthValue() | rpl::filter(rpl::mappers::_1 > 0),
slider->heightValue() | rpl::filter(rpl::mappers::_1 > 0)
) | rpl::start_with_next([=](int w, int h) {
scroll->resize(w, h + scrollSt.deltax * 4);
scroll->resize(w, h);
container->resize(w, h);
wrap->resize(w, h);
}, wrap->lifetime());

View file

@ -242,6 +242,27 @@ SettingsSlider::SettingsSlider(
setSelectOnPress(_st.ripple.showDuration == 0);
}
const style::SettingsSlider &SettingsSlider::st() const {
return _st;
}
int SettingsSlider::centerOfSection(int section) const {
const auto widths = countSectionsWidths(0);
auto result = 0;
if (section >= 0 && section < widths.size()) {
for (auto i = 0; i < section; i++) {
result += widths[i];
}
result += widths[section] / 2;
}
return result;
}
void SettingsSlider::fitWidthToSections() {
const auto widths = countSectionsWidths(0);
resizeToWidth(ranges::accumulate(widths, .0) + _st.padding * 2);
}
void SettingsSlider::setRippleTopRoundRadius(int radius) {
_rippleTopRoundRadius = radius;
}
@ -263,7 +284,7 @@ void SettingsSlider::resizeSections(int newWidth) {
const auto sectionWidths = countSectionsWidths(newWidth);
auto skip = 0;
auto x = 0.;
auto x = _st.padding * 1.;
auto sectionWidth = sectionWidths.begin();
enumerateSections([&](Section &section) {
Expects(sectionWidth != sectionWidths.end());
@ -280,7 +301,9 @@ void SettingsSlider::resizeSections(int newWidth) {
std::vector<float64> SettingsSlider::countSectionsWidths(int newWidth) const {
const auto count = getSectionsCount();
const auto sectionsWidth = newWidth - (count - 1) * _st.barSkip;
const auto sectionsWidth = newWidth
- 2 * _st.padding
- (count - 1) * _st.barSkip;
const auto sectionWidth = sectionsWidth / float64(count);
auto result = std::vector<float64>(count, sectionWidth);

View file

@ -130,6 +130,11 @@ public:
QWidget *parent,
const style::SettingsSlider &st = st::defaultSettingsSlider);
[[nodiscard]] const style::SettingsSlider &st() const;
[[nodiscard]] int centerOfSection(int section) const;
virtual void fitWidthToSections();
void setRippleTopRoundRadius(int radius);
protected: