mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added support of locked sections to chats filters tabs slider.
This commit is contained in:
parent
dc49c788a8
commit
4d9112283d
3 changed files with 102 additions and 1 deletions
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/chat_filters_tabs_slider.h"
|
#include "ui/widgets/chat_filters_tabs_slider.h"
|
||||||
|
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
#include "ui/widgets/side_bar_button.h"
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
|
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
@ -57,6 +58,7 @@ int ChatsFiltersTabs::centerOfSection(int section) const {
|
||||||
void ChatsFiltersTabs::fitWidthToSections() {
|
void ChatsFiltersTabs::fitWidthToSections() {
|
||||||
const auto widths = countSectionsWidths(0);
|
const auto widths = countSectionsWidths(0);
|
||||||
resizeToWidth(ranges::accumulate(widths, .0));
|
resizeToWidth(ranges::accumulate(widths, .0));
|
||||||
|
_lockedFromX = calculateLockedFromX();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatsFiltersTabs::setUnreadCount(int index, int unreadCount) {
|
void ChatsFiltersTabs::setUnreadCount(int index, int unreadCount) {
|
||||||
|
@ -90,6 +92,37 @@ void ChatsFiltersTabs::setUnreadCount(int index, int unreadCount) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ChatsFiltersTabs::calculateLockedFromX() const {
|
||||||
|
if (!_lockedFrom) {
|
||||||
|
return std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
auto left = 0;
|
||||||
|
auto index = 0;
|
||||||
|
enumerateSections([&](const Section §ion) {
|
||||||
|
const auto currentRight = section.left + section.width;
|
||||||
|
if (index == _lockedFrom) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
left = currentRight;
|
||||||
|
index++;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return left ? left : std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatsFiltersTabs::setLockedFrom(int index) {
|
||||||
|
_lockedFrom = index;
|
||||||
|
_lockedFromX = calculateLockedFromX();
|
||||||
|
if (!index) {
|
||||||
|
_paletteLifetime.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_paletteLifetime = style::PaletteChanged(
|
||||||
|
) | rpl::start_with_next([this] {
|
||||||
|
_lockCache.emplace(Ui::SideBarLockIcon(_st.labelFg));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
QImage ChatsFiltersTabs::cacheUnreadCount(int count) const {
|
QImage ChatsFiltersTabs::cacheUnreadCount(int count) const {
|
||||||
const auto widthIndex = (count < 10) ? 0 : (count < 100) ? 1 : 2;
|
const auto widthIndex = (count < 10) ? 0 : (count < 100) ? 1 : 2;
|
||||||
auto image = QImage(
|
auto image = QImage(
|
||||||
|
@ -144,6 +177,11 @@ void ChatsFiltersTabs::paintEvent(QPaintEvent *e) {
|
||||||
section.contentWidth,
|
section.contentWidth,
|
||||||
_st.labelStyle.font->height);
|
_st.labelStyle.font->height);
|
||||||
if (rect.intersects(clip)) {
|
if (rect.intersects(clip)) {
|
||||||
|
const auto locked = (_lockedFrom && (index >= _lockedFrom));
|
||||||
|
if (locked) {
|
||||||
|
constexpr auto kPremiumLockedOpacity = 0.6;
|
||||||
|
p.setOpacity(kPremiumLockedOpacity);
|
||||||
|
}
|
||||||
p.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active));
|
p.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active));
|
||||||
section.label.draw(p, {
|
section.label.draw(p, {
|
||||||
.position = QPoint(labelLeft, _st.labelTop),
|
.position = QPoint(labelLeft, _st.labelTop),
|
||||||
|
@ -161,6 +199,18 @@ void ChatsFiltersTabs::paintEvent(QPaintEvent *e) {
|
||||||
it->second.cache);
|
it->second.cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (locked) {
|
||||||
|
if (!_lockCache) {
|
||||||
|
_lockCache.emplace(Ui::SideBarLockIcon(_st.labelFg));
|
||||||
|
}
|
||||||
|
const auto size = _lockCache->size()
|
||||||
|
/ style::DevicePixelRatio();
|
||||||
|
p.drawImage(
|
||||||
|
labelLeft + (section.label.maxWidth() - size.width()) / 2,
|
||||||
|
height() - size.height() - st::lineWidth,
|
||||||
|
*_lockCache);
|
||||||
|
p.setOpacity(1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
return true;
|
return true;
|
||||||
|
@ -188,14 +238,36 @@ void ChatsFiltersTabs::paintEvent(QPaintEvent *e) {
|
||||||
void ChatsFiltersTabs::mousePressEvent(QMouseEvent *e) {
|
void ChatsFiltersTabs::mousePressEvent(QMouseEvent *e) {
|
||||||
const auto mouseButton = e->button();
|
const auto mouseButton = e->button();
|
||||||
if (mouseButton == Qt::MouseButton::LeftButton) {
|
if (mouseButton == Qt::MouseButton::LeftButton) {
|
||||||
Ui::SettingsSlider::mousePressEvent(e);
|
_lockedPressed = (e->pos().x() >= _lockedFromX);
|
||||||
|
if (_lockedPressed) {
|
||||||
|
Ui::RpWidget::mousePressEvent(e);
|
||||||
|
} else {
|
||||||
|
Ui::SettingsSlider::mousePressEvent(e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Ui::RpWidget::mousePressEvent(e);
|
Ui::RpWidget::mousePressEvent(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatsFiltersTabs::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
const auto mouseButton = e->button();
|
||||||
|
if (mouseButton == Qt::MouseButton::LeftButton) {
|
||||||
|
if (base::take(_lockedPressed)) {
|
||||||
|
_lockedPressed = false;
|
||||||
|
_lockedClicked.fire({});
|
||||||
|
} else {
|
||||||
|
Ui::SettingsSlider::mouseReleaseEvent(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ui::RpWidget::mouseReleaseEvent(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ChatsFiltersTabs::contextMenuEvent(QContextMenuEvent *e) {
|
void ChatsFiltersTabs::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
const auto pos = e->pos();
|
const auto pos = e->pos();
|
||||||
|
if (pos.x() >= _lockedFromX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto left = 0;
|
auto left = 0;
|
||||||
auto index = 0;
|
auto index = 0;
|
||||||
enumerateSections([&](const Section §ion) {
|
enumerateSections([&](const Section §ion) {
|
||||||
|
@ -214,4 +286,8 @@ rpl::producer<int> ChatsFiltersTabs::contextMenuRequested() const {
|
||||||
return _contextMenuRequested.events();
|
return _contextMenuRequested.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<> ChatsFiltersTabs::lockedClicked() const {
|
||||||
|
return _lockedClicked.events();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -28,16 +28,20 @@ public:
|
||||||
[[nodiscard]] int centerOfSection(int section) const;
|
[[nodiscard]] int centerOfSection(int section) const;
|
||||||
void fitWidthToSections();
|
void fitWidthToSections();
|
||||||
void setUnreadCount(int index, int unreadCount);
|
void setUnreadCount(int index, int unreadCount);
|
||||||
|
void setLockedFrom(int index);
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<int> contextMenuRequested() const;
|
[[nodiscard]] rpl::producer<int> contextMenuRequested() const;
|
||||||
|
[[nodiscard]] rpl::producer<> lockedClicked() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] QImage cacheUnreadCount(int count) const;
|
[[nodiscard]] QImage cacheUnreadCount(int count) const;
|
||||||
|
[[nodiscard]] int calculateLockedFromX() const;
|
||||||
|
|
||||||
using Index = int;
|
using Index = int;
|
||||||
struct Unread final {
|
struct Unread final {
|
||||||
|
@ -51,10 +55,16 @@ private:
|
||||||
const int _unreadSkip;
|
const int _unreadSkip;
|
||||||
std::vector<int> _cachedBadgeWidths;
|
std::vector<int> _cachedBadgeWidths;
|
||||||
int _cachedBadgeHeight = 0;
|
int _cachedBadgeHeight = 0;
|
||||||
|
int _lockedFrom = 0;
|
||||||
|
int _lockedFromX = 0;
|
||||||
|
bool _lockedPressed = false;
|
||||||
std::optional<Ui::RoundRect> _bar;
|
std::optional<Ui::RoundRect> _bar;
|
||||||
std::optional<Ui::RoundRect> _barActive;
|
std::optional<Ui::RoundRect> _barActive;
|
||||||
|
std::optional<QImage> _lockCache;
|
||||||
|
|
||||||
|
rpl::lifetime _paletteLifetime;
|
||||||
rpl::event_stream<int> _contextMenuRequested;
|
rpl::event_stream<int> _contextMenuRequested;
|
||||||
|
rpl::event_stream<> _lockedClicked;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "api/api_chat_filters_remove_manager.h"
|
#include "api/api_chat_filters_remove_manager.h"
|
||||||
#include "boxes/filters/edit_filter_box.h"
|
#include "boxes/filters/edit_filter_box.h"
|
||||||
|
#include "boxes/premium_limits_box.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "data/data_chat_filters.h"
|
#include "data/data_chat_filters.h"
|
||||||
|
#include "data/data_premium_limits.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_unread_value.h"
|
#include "data/data_unread_value.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "settings/settings_folders.h"
|
#include "settings/settings_folders.h"
|
||||||
|
@ -205,6 +208,18 @@ not_null<Ui::RpWidget*> AddChatFiltersTabsStrip(
|
||||||
}) | ranges::to_vector;
|
}) | ranges::to_vector;
|
||||||
slider->setSections(std::move(sections));
|
slider->setSections(std::move(sections));
|
||||||
slider->fitWidthToSections();
|
slider->fitWidthToSections();
|
||||||
|
{
|
||||||
|
const auto reorderAll = session->user()->isPremium();
|
||||||
|
const auto maxLimit = (reorderAll ? 1 : 0)
|
||||||
|
+ Data::PremiumLimits(session).dialogFiltersCurrent();
|
||||||
|
const auto premiumFrom = (reorderAll ? 0 : 1) + maxLimit;
|
||||||
|
slider->setLockedFrom((premiumFrom >= list.size())
|
||||||
|
? 0
|
||||||
|
: premiumFrom);
|
||||||
|
slider->lockedClicked() | rpl::start_with_next([=] {
|
||||||
|
controller->show(Box(FiltersLimitBox, session, std::nullopt));
|
||||||
|
}, slider->lifetime());
|
||||||
|
}
|
||||||
{
|
{
|
||||||
auto includeMuted = Data::IncludeMutedCounterFoldersValue();
|
auto includeMuted = Data::IncludeMutedCounterFoldersValue();
|
||||||
state->unreadLifetime.destroy();
|
state->unreadLifetime.destroy();
|
||||||
|
|
Loading…
Add table
Reference in a new issue