Add support for bottom subsection tabs mode.

This commit is contained in:
John Preston
2026-03-13 14:55:07 +04:00
parent b4f7c0fe9b
commit 1e6f7c7f3f
10 changed files with 192 additions and 81 deletions
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="72px" height="72px" viewBox="0 0 72 72" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>General / menu_sidebar1</title>
<g id="General-/-menu_sidebar1" stroke="none" fill="none" fill-rule="nonzero">
<path d="M51,11.75 C57.7654882,11.75 63.25,17.2345118 63.25,24 L63.25,48 C63.25,54.7654882 57.7654882,60.25 51,60.25 L21,60.25 C14.2345118,60.25 8.75,54.7654882 8.75,48 L8.75,24 C8.75,17.2345118 14.2345118,11.75 21,11.75 L51,11.75 Z M33.75,16.25 L21,16.25 C16.7197932,16.25 13.25,19.7197932 13.25,24 L13.25,48 C13.25,52.2802068 16.7197932,55.75 21,55.75 L33.75,55.75 L33.75,16.25 Z M51,16.25 L38.25,16.25 L38.25,55.75 L51,55.75 C55.2802068,55.75 58.75,52.2802068 58.75,48 L58.75,24 C58.75,19.7197932 55.2802068,16.25 51,16.25 Z M27,38.75 C28.2426407,38.75 29.25,39.7573593 29.25,41 C29.25,42.2426407 28.2426407,43.25 27,43.25 L20,43.25 C18.7573593,43.25 17.75,42.2426407 17.75,41 C17.75,39.7573593 18.7573593,38.75 20,38.75 L27,38.75 Z M27,30.25 C28.2426407,30.25 29.25,31.2573593 29.25,32.5 C29.25,33.7426407 28.2426407,34.75 27,34.75 L20,34.75 C18.7573593,34.75 17.75,33.7426407 17.75,32.5 C17.75,31.2573593 18.7573593,30.25 20,30.25 L27,30.25 Z M27,21.75 C28.2426407,21.75 29.25,22.7573593 29.25,24 C29.25,25.2426407 28.2426407,26.25 27,26.25 L20,26.25 C18.7573593,26.25 17.75,25.2426407 17.75,24 C17.75,22.7573593 18.7573593,21.75 20,21.75 L27,21.75 Z" id="Shape" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="72px" height="72px" viewBox="0 0 72 72" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>General / menu_sidebar2</title>
<g id="General-/-menu_sidebar2" stroke="none" fill="none" fill-rule="nonzero">
<path d="M51,11.75 C57.7654882,11.75 63.25,17.2345118 63.25,24 L63.25,48 C63.25,54.7654882 57.7654882,60.25 51,60.25 L21,60.25 C14.2345118,60.25 8.75,54.7654882 8.75,48 L8.75,24 C8.75,17.2345118 14.2345118,11.75 21,11.75 L51,11.75 Z M58.75,40.249 L13.25,40.249 L13.25,48 C13.25,52.2802068 16.7197932,55.75 21,55.75 L51,55.75 C55.2802068,55.75 58.75,52.2802068 58.75,48 L58.75,40.249 Z M52,45.25 C53.2426407,45.25 54.25,46.2573593 54.25,47.5 C54.25,48.7426407 53.2426407,49.75 52,49.75 L47,49.75 C45.7573593,49.75 44.75,48.7426407 44.75,47.5 C44.75,46.2573593 45.7573593,45.25 47,45.25 L52,45.25 Z M38,45.25 C39.2426407,45.25 40.25,46.2573593 40.25,47.5 C40.25,48.7426407 39.2426407,49.75 38,49.75 L33,49.75 C31.7573593,49.75 30.75,48.7426407 30.75,47.5 C30.75,46.2573593 31.7573593,45.25 33,45.25 L38,45.25 Z M25,45.25 C26.2426407,45.25 27.25,46.2573593 27.25,47.5 C27.25,48.7426407 26.2426407,49.75 25,49.75 L20,49.75 C18.7573593,49.75 17.75,48.7426407 17.75,47.5 C17.75,46.2573593 18.7573593,45.25 20,45.25 L25,45.25 Z M51,16.25 L21,16.25 L20.2076076,16.2900124 C16.2996229,16.6868898 13.25,19.9873061 13.25,24 L13.25,35.749 L58.75,35.749 L58.75,24 C58.75,19.7197932 55.2802068,16.25 51,16.25 Z" id="Shape" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="72px" height="72px" viewBox="0 0 72 72" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>General / menu_sidebar3</title>
<g id="General-/-menu_sidebar3" stroke="none" fill="none" fill-rule="nonzero">
<path d="M51,11.75 C57.7654882,11.75 63.25,17.2345118 63.25,24 L63.25,48 C63.25,54.7654882 57.7654882,60.25 51,60.25 L21,60.25 C14.2345118,60.25 8.75,54.7654882 8.75,48 L8.75,24 C8.75,17.2345118 14.2345118,11.75 21,11.75 L51,11.75 Z M58.75,36.249 L13.25,36.249 L13.25,48 C13.25,52.2802068 16.7197932,55.75 21,55.75 L51,55.75 C55.2802068,55.75 58.75,52.2802068 58.75,48 L58.75,36.249 Z M51,16.25 L21,16.25 L20.2076076,16.2900124 C16.2996229,16.6868898 13.25,19.9873061 13.25,24 L13.25,31.749 L58.75,31.749 L58.75,24 C58.75,19.7197932 55.2802068,16.25 51,16.25 Z M52,22.25 C53.2426407,22.25 54.25,23.2573593 54.25,24.5 C54.25,25.7426407 53.2426407,26.75 52,26.75 L47,26.75 C45.7573593,26.75 44.75,25.7426407 44.75,24.5 C44.75,23.2573593 45.7573593,22.25 47,22.25 L52,22.25 Z M38,22.25 C39.2426407,22.25 40.25,23.2573593 40.25,24.5 C40.25,25.7426407 39.2426407,26.75 38,26.75 L33,26.75 C31.7573593,26.75 30.75,25.7426407 30.75,24.5 C30.75,23.2573593 31.7573593,22.25 33,22.25 L38,22.25 Z M25,22.25 C26.2426407,22.25 27.25,23.2573593 27.25,24.5 C27.25,25.7426407 26.2426407,26.75 25,26.75 L20,26.75 C18.7573593,26.75 17.75,25.7426407 17.75,24.5 C17.75,23.2573593 18.7573593,22.25 20,22.25 L25,22.25 Z" id="Shape" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -7034,7 +7034,8 @@ void HistoryWidget::updateHistoryGeometry(
const auto subsectionTabsTop = _topBar->bottomNoMargins();
auto newScrollHeight = height()
- subsectionTabsTop
- (_subsectionTabs ? _subsectionTabs->topSkip() : 0);
- (_subsectionTabs ? _subsectionTabs->topSkip() : 0)
- (_subsectionTabs ? _subsectionTabs->bottomSkip() : 0);
if (_translateBar) {
newScrollHeight -= _translateBar->height();
}
@@ -7113,8 +7114,11 @@ void HistoryWidget::updateHistoryGeometry(
controller()->floatPlayerAreaUpdated();
}
if (_subsectionTabs) {
const auto tabsBottomSkip = _subsectionTabs->bottomSkip();
const auto scrollBottom = _scroll->y() + newScrollHeight;
const auto areaHeight = scrollBottom - subsectionTabsTop;
const auto areaHeight = scrollBottom
+ tabsBottomSkip
- subsectionTabsTop;
_subsectionTabs->setBoundingRect(
{ 0, subsectionTabsTop, width(), areaHeight });
}
@@ -2645,6 +2645,9 @@ void ChatWidget::updateControlsGeometry() {
const auto tabsLeftSkip = _subsectionTabs
? _subsectionTabs->leftSkip()
: 0;
const auto tabsBottomSkip = _subsectionTabs
? _subsectionTabs->bottomSkip()
: 0;
const auto innerWidth = contentWidth - tabsLeftSkip;
const auto subsectionTabsTop = _topBar->bottomNoMargins();
_topBars->move(tabsLeftSkip, subsectionTabsTop
@@ -2682,6 +2685,8 @@ void ChatWidget::updateControlsGeometry() {
} else {
bottom -= _composeControls->heightCurrent();
}
const auto composeTop = bottom;
bottom -= tabsBottomSkip;
_topBars->resize(innerWidth, top + st::lineWidth);
top += _topBars->y();
@@ -2704,12 +2709,14 @@ void ChatWidget::updateControlsGeometry() {
}
updateInnerVisibleArea();
}
_composeControls->move(0, bottom);
_composeControls->move(0, composeTop);
_composeControls->setAutocompleteBoundingRect(_scroll->geometry());
if (_subsectionTabs) {
const auto scrollBottom = _scroll->y() + scrollHeight;
const auto areaHeight = scrollBottom - subsectionTabsTop;
const auto areaHeight = scrollBottom
+ tabsBottomSkip
- subsectionTabsTop;
_subsectionTabs->setBoundingRect(
{ 0, subsectionTabsTop, width(), areaHeight });
}
@@ -80,22 +80,31 @@ SubsectionTabs::SubsectionTabs(
SubsectionTabs::~SubsectionTabs() {
delete base::take(_horizontal);
delete base::take(_vertical);
delete base::take(_bottom);
delete base::take(_shadow);
}
void SubsectionTabs::setup(not_null<Ui::RpWidget*> parent) {
const auto peerId = _history->peer->id;
if (session().settings().verticalSubsectionTabs(peerId)) {
const auto mode = session().settings().subsectionTabsMode(peerId);
if (mode == qint32(SubsectionTabsMode::Left)) {
setupVertical(parent);
} else if (mode == qint32(SubsectionTabsMode::Bottom)) {
setupHorizontal(parent, true);
} else {
setupHorizontal(parent);
setupHorizontal(parent, false);
}
}
void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
void SubsectionTabs::setupHorizontal(
not_null<QWidget*> parent,
bool bottom) {
delete base::take(_vertical);
_horizontal = Ui::CreateChild<Ui::RpWidget>(parent);
_horizontal->show();
delete base::take(bottom ? _horizontal : _bottom);
auto &widgetRef = bottom ? _bottom : _horizontal;
widgetRef = Ui::CreateChild<Ui::RpWidget>(parent);
widgetRef->show();
const auto widget = widgetRef;
if (!_shadow) {
_shadow = Ui::CreateChild<Ui::PlainShadow>(parent);
@@ -105,19 +114,24 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
}
const auto toggle = Ui::CreateChild<Ui::IconButton>(
_horizontal,
widget,
st::chatTabsToggle);
toggle->show();
toggle->setIconOverride(
bottom ? &st::chatTabsToggleIconBottom : &st::chatTabsToggleIconTop,
(bottom
? &st::chatTabsToggleIconBottomOver
: &st::chatTabsToggleIconTopOver));
toggle->setClickedCallback([=] {
toggleModes();
});
toggle->move(0, 0);
const auto scroll = Ui::CreateChild<Ui::ScrollArea>(
_horizontal,
widget,
st::chatTabsScroll,
true);
scroll->show();
const auto shadow = Ui::CreateChild<Ui::PlainShadow>(_horizontal);
const auto shadow = Ui::CreateChild<Ui::PlainShadow>(widget);
const auto slider = scroll->setOwnedWidget(
object_ptr<Ui::HorizontalSlider>(scroll));
_reorder = std::make_unique<Ui::SubsectionSliderReorder>(slider, scroll);
@@ -130,8 +144,8 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
) | rpl::map([=] { return scroll->scrollLeft() > 0; }));
shadow->setAttribute(Qt::WA_TransparentForMouseEvents);
_horizontal->resize(
_horizontal->width(),
widget->resize(
widget->width(),
std::max(toggle->height(), slider->height()));
scroll->setCustomWheelProcess([=](not_null<QWheelEvent*> e) {
@@ -145,7 +159,7 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
return true;
});
_horizontal->sizeValue(
widget->sizeValue(
) | rpl::on_next([=](QSize size) {
const auto togglew = toggle->width();
const auto height = size.height();
@@ -153,13 +167,26 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
shadow->setGeometry(togglew, 0, st::lineWidth, height);
}, scroll->lifetime());
_horizontal->paintRequest() | rpl::on_next([=](QRect clip) {
QPainter(_horizontal).fillRect(
widget->paintRequest() | rpl::on_next([=](QRect clip) {
auto p = QPainter(widget);
const auto line = st::lineWidth;
p.fillRect(
clip.intersected(
_horizontal->rect().marginsRemoved(
{ 0, 0, 0, st::lineWidth })),
widget->rect().marginsRemoved(
{ 0, bottom ? line : 0, 0, bottom ? 0 : line })),
st::windowBg);
}, _horizontal->lifetime());
if (bottom) {
const auto shadow = QRect(
0,
widget->height() - line,
widget->width(),
line);
if (clip.intersects(shadow)) {
p.fillRect(clip.intersected(shadow), st::shadowFg);
}
}
}, widget->lifetime());
_layoutRequests.fire({});
@@ -168,6 +195,7 @@ void SubsectionTabs::setupHorizontal(not_null<QWidget*> parent) {
void SubsectionTabs::setupVertical(not_null<QWidget*> parent) {
delete base::take(_horizontal);
delete base::take(_bottom);
_vertical = Ui::CreateChild<Ui::RpWidget>(parent);
_vertical->show();
@@ -180,8 +208,9 @@ void SubsectionTabs::setupVertical(not_null<QWidget*> parent) {
_vertical,
st::chatTabsToggle);
toggle->show();
const auto active = &st::chatTabsToggleActive;
toggle->setIconOverride(active, active);
toggle->setIconOverride(
&st::chatTabsToggleIconLeft,
&st::chatTabsToggleIconLeftOver);
toggle->setClickedCallback([=] {
toggleModes();
});
@@ -566,7 +595,7 @@ void SubsectionTabs::startFillingSlider(
void SubsectionTabs::showThreadContextMenu(not_null<Data::Thread*> thread) {
_menu = nullptr;
_menu = base::make_unique_q<Ui::PopupMenu>(
_horizontal ? _horizontal : _vertical,
activeWidget(),
st::popupMenuExpandedSeparator);
const auto addAction = Ui::Menu::CreateAddActionCallback(_menu);
@@ -605,17 +634,27 @@ rpl::producer<> SubsectionTabs::dataChanged() const {
}
void SubsectionTabs::toggleModes() {
Expects((_horizontal || _vertical) && _shadow);
Expects((_horizontal || _vertical || _bottom) && _shadow);
const auto peerId = _history->peer->id;
const auto nowVertical = (_horizontal != nullptr);
session().settings().setVerticalSubsectionTabs(peerId, nowVertical);
const auto parent = activeWidget()->parentWidget();
const auto current = session().settings().subsectionTabsMode(peerId);
const auto next = (current == qint32(SubsectionTabsMode::Top))
? SubsectionTabsMode::Bottom
: (current == qint32(SubsectionTabsMode::Bottom))
? SubsectionTabsMode::Left
: SubsectionTabsMode::Top;
session().settings().setSubsectionTabsMode(
peerId,
qint32(next));
session().saveSettingsDelayed();
if (_horizontal) {
setupVertical(_horizontal->parentWidget());
if (next == SubsectionTabsMode::Left) {
setupVertical(parent);
} else if (next == SubsectionTabsMode::Bottom) {
setupHorizontal(parent, true);
} else {
setupHorizontal(_vertical->parentWidget());
setupHorizontal(parent, false);
}
}
@@ -634,21 +673,17 @@ rpl::producer<> SubsectionTabs::removeRequests() const {
}
void SubsectionTabs::extractToParent(not_null<Ui::RpWidget*> parent) {
Expects((_horizontal || _vertical) && _shadow);
Expects((_horizontal || _vertical || _bottom) && _shadow);
if (_vertical) {
_vertical->hide();
_vertical->setParent(parent);
} else {
_horizontal->hide();
_horizontal->setParent(parent);
}
const auto widget = activeWidget();
widget->hide();
widget->setParent(parent);
_shadow->hide();
_shadow->setParent(parent);
}
void SubsectionTabs::setBoundingRect(QRect boundingRect) {
Expects((_horizontal || _vertical) && _shadow);
Expects((_horizontal || _vertical || _bottom) && _shadow);
if (_horizontal) {
_horizontal->setGeometry(
@@ -661,7 +696,7 @@ void SubsectionTabs::setBoundingRect(QRect boundingRect) {
_horizontal->y() + _horizontal->height() - st::lineWidth,
boundingRect.width(),
st::lineWidth);
} else {
} else if (_vertical) {
_vertical->setGeometry(
boundingRect.x(),
boundingRect.y(),
@@ -672,6 +707,18 @@ void SubsectionTabs::setBoundingRect(QRect boundingRect) {
boundingRect.y(),
st::lineWidth,
boundingRect.height());
} else {
_bottom->setGeometry(
boundingRect.x(),
boundingRect.y() + boundingRect.height()
- _bottom->height(),
boundingRect.width(),
_bottom->height());
_shadow->setGeometry(
boundingRect.x(),
_bottom->y(),
boundingRect.width(),
st::lineWidth);
}
}
@@ -687,14 +734,14 @@ int SubsectionTabs::topSkip() const {
return _horizontal ? (_horizontal->height() - st::lineWidth) : 0;
}
void SubsectionTabs::raise() {
Expects((_horizontal || _vertical) && _shadow);
int SubsectionTabs::bottomSkip() const {
return _bottom ? (_bottom->height() - st::lineWidth) : 0;
}
if (_horizontal) {
_horizontal->raise();
} else {
_vertical->raise();
}
void SubsectionTabs::raise() {
Expects((_horizontal || _vertical || _bottom) && _shadow);
activeWidget()->raise();
_shadow->raise();
}
@@ -707,13 +754,9 @@ void SubsectionTabs::hide() {
}
void SubsectionTabs::setVisible(bool shown) {
Expects((_horizontal || _vertical) && _shadow);
Expects((_horizontal || _vertical || _bottom) && _shadow);
if (_horizontal) {
_horizontal->setVisible(shown);
} else {
_vertical->setVisible(shown);
}
activeWidget()->setVisible(shown);
_shadow->setVisible(shown);
}
@@ -829,7 +872,7 @@ void SubsectionTabs::refreshSlice() {
if (_slice != slice) {
_slice = std::move(slice);
_refreshed.fire({});
Assert((!_horizontal && !_vertical)
Assert((!_horizontal && !_vertical && !_bottom)
|| (_slice.size() == _sectionsSlice.size()));
}
});
@@ -908,22 +951,22 @@ Main::Session &SubsectionTabs::session() {
return _history->session();
}
Ui::RpWidget *SubsectionTabs::activeWidget() const {
return _horizontal ? _horizontal : _vertical ? _vertical : _bottom;
}
bool SubsectionTabs::switchTo(
not_null<Data::Thread*> thread,
not_null<Ui::RpWidget*> parent) {
Expects((_horizontal || _vertical) && _shadow);
Expects((_horizontal || _vertical || _bottom) && _shadow);
if (thread->owningHistory() != _history) {
return false;
}
_active = thread;
if (_vertical) {
_vertical->setParent(parent);
_vertical->show();
} else {
_horizontal->setParent(parent);
_horizontal->show();
}
const auto widget = activeWidget();
widget->setParent(parent);
widget->show();
_shadow->setParent(parent);
_shadow->show();
_refreshed.fire({});
@@ -34,6 +34,12 @@ class SubsectionSliderReorder;
namespace HistoryView {
enum class SubsectionTabsMode : qint32 {
Top = 0,
Left = 1,
Bottom = 2,
};
class SubsectionTabs final {
public:
SubsectionTabs(
@@ -59,6 +65,7 @@ public:
[[nodiscard]] rpl::producer<> layoutRequests() const;
[[nodiscard]] int leftSkip() const;
[[nodiscard]] int topSkip() const;
[[nodiscard]] int bottomSkip() const;
void raise();
void show();
@@ -80,7 +87,7 @@ private:
};
void track();
void setupHorizontal(not_null<QWidget*> parent);
void setupHorizontal(not_null<QWidget*> parent, bool bottom);
void setupVertical(not_null<QWidget*> parent);
void toggleModes();
void setVisible(bool shown);
@@ -92,6 +99,7 @@ private:
void loadMore();
void setup(not_null<Ui::RpWidget*> parent);
[[nodiscard]] rpl::producer<> dataChanged() const;
[[nodiscard]] Ui::RpWidget *activeWidget() const;
void setupSlider(
not_null<Ui::ScrollArea*> scroll,
@@ -118,6 +126,7 @@ private:
Ui::RpWidget *_horizontal = nullptr;
Ui::RpWidget *_vertical = nullptr;
Ui::RpWidget *_bottom = nullptr;
Ui::RpWidget *_shadow = nullptr;
std::unique_ptr<Ui::SubsectionSliderReorder> _reorder;
int _reordering = 0;
@@ -46,7 +46,6 @@ QByteArray SessionSettings::serialize() const {
+ sizeof(qint32) * 3
+ _hiddenPinnedMessages.size() * (sizeof(quint64) * 4)
+ sizeof(qint32)
+ _verticalSubsectionTabs.size() * sizeof(quint64)
+ sizeof(qint32) // _ringtoneDefaultVolumes size
+ (_ringtoneDefaultVolumes.size()
* (0
@@ -69,6 +68,8 @@ QByteArray SessionSettings::serialize() const {
size += sizeof(qint32) // _moderateCommonGroups size
+ (_moderateCommonGroups.size() * sizeof(qint32));
size += sizeof(qint32);
size += sizeof(qint32)
+ _subsectionTabsModes.size() * (sizeof(quint64) + sizeof(qint32));
auto result = QByteArray();
result.reserve(size);
@@ -120,10 +121,7 @@ QByteArray SessionSettings::serialize() const {
<< SerializePeerId(key.monoforumPeerId)
<< qint64(value.bare);
}
stream << qint32(_verticalSubsectionTabs.size());
for (const auto &peerId : _verticalSubsectionTabs) {
stream << SerializePeerId(peerId);
}
stream << qint32(0);
stream << qint32(_ringtoneDefaultVolumes.size());
for (const auto &[key, value] : _ringtoneDefaultVolumes) {
stream << uint8_t(key) << ushort(value);
@@ -155,6 +153,10 @@ QByteArray SessionSettings::serialize() const {
stream << qint32(filterId);
}
stream << qint32(_disableSharingBoxShowsCount);
stream << qint32(_subsectionTabsModes.size());
for (const auto &[peerId, mode] : _subsectionTabsModes) {
stream << SerializePeerId(peerId) << qint32(mode);
}
}
Ensures(result.size() == size);
@@ -214,7 +216,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
std::vector<int> appDictionariesEnabled;
qint32 appAutoDownloadDictionaries = app.autoDownloadDictionaries() ? 1 : 0;
base::flat_map<ThreadId, MsgId> hiddenPinnedMessages;
base::flat_set<PeerId> verticalSubsectionTabs;
base::flat_map<PeerId, qint32> subsectionTabsModes;
qint32 dialogsFiltersEnabled = _dialogsFiltersEnabled ? 1 : 0;
qint32 supportAllSilent = _supportAllSilent ? 1 : 0;
qint32 photoEditorHintShowsCount = _photoEditorHintShowsCount;
@@ -547,7 +549,8 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
"Bad data for SessionSettings::addFromSerialized()"));
return;
}
verticalSubsectionTabs.emplace(DeserializePeerId(peerId));
subsectionTabsModes.emplace(
DeserializePeerId(peerId), qint32(1));
}
}
}
@@ -665,6 +668,24 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
if (!stream.atEnd()) {
stream >> disableSharingBoxShowsCount;
}
if (!stream.atEnd()) {
auto count = qint32(0);
stream >> count;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != count; ++i) {
auto peerId = quint64();
auto mode = qint32(0);
stream >> peerId >> mode;
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for SessionSettings::addFromSerialized()"));
return;
}
subsectionTabsModes.emplace(
DeserializePeerId(peerId), mode);
}
}
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for SessionSettings::addFromSerialized()"));
@@ -711,7 +732,7 @@ void SessionSettings::addFromSerialized(const QByteArray &serialized) {
_mutePeriods = std::move(mutePeriods);
_lastNonPremiumLimitDownload = lastNonPremiumLimitDownload;
_lastNonPremiumLimitUpload = lastNonPremiumLimitUpload;
_verticalSubsectionTabs = std::move(verticalSubsectionTabs);
_subsectionTabsModes = std::move(subsectionTabsModes);
_ringtoneDefaultVolumes = std::move(ringtoneDefaultVolumes);
_ringtoneVolumes = std::move(ringtoneVolumes);
_ratedTranscriptions = std::move(ratedTranscriptions);
@@ -864,17 +885,18 @@ void SessionSettings::setHiddenPinnedMessageId(
}
}
bool SessionSettings::verticalSubsectionTabs(PeerId peerId) const {
return _verticalSubsectionTabs.contains(peerId);
qint32 SessionSettings::subsectionTabsMode(PeerId peerId) const {
const auto i = _subsectionTabsModes.find(peerId);
return (i != end(_subsectionTabsModes)) ? i->second : 0;
}
void SessionSettings::setVerticalSubsectionTabs(
void SessionSettings::setSubsectionTabsMode(
PeerId peerId,
bool vertical) {
if (vertical) {
_verticalSubsectionTabs.emplace(peerId);
qint32 mode) {
if (mode) {
_subsectionTabsModes[peerId] = mode;
} else {
_verticalSubsectionTabs.remove(peerId);
_subsectionTabsModes.remove(peerId);
}
}
@@ -124,8 +124,8 @@ public:
PeerId monoforumPeerId,
MsgId msgId);
[[nodiscard]] bool verticalSubsectionTabs(PeerId peerId) const;
void setVerticalSubsectionTabs(PeerId peerId, bool vertical);
[[nodiscard]] qint32 subsectionTabsMode(PeerId peerId) const;
void setSubsectionTabsMode(PeerId peerId, qint32 mode);
[[nodiscard]] bool dialogsFiltersEnabled() const {
return _dialogsFiltersEnabled;
@@ -211,7 +211,7 @@ private:
rpl::variable<bool> _archiveInMainMenu = false;
rpl::variable<bool> _skipArchiveInSearch = false;
base::flat_map<ThreadId, MsgId> _hiddenPinnedMessages;
base::flat_set<PeerId> _verticalSubsectionTabs;
base::flat_map<PeerId, qint32> _subsectionTabsModes;
base::flat_map<Data::DefaultNotify, ushort> _ringtoneDefaultVolumes;
base::flat_map<ThreadId, ushort> _ringtoneVolumes;
bool _dialogsFiltersEnabled = false;
+6 -1
View File
@@ -1376,7 +1376,12 @@ chatTabsToggle: IconButton(defaultIconButton) {
iconOver: icon {{ "top_bar_profile-flip_horizontal", menuIconFgOver }};
ripple: emptyRippleAnimation;
}
chatTabsToggleActive: icon {{ "top_bar_profile-flip_horizontal", windowActiveTextFg }};
chatTabsToggleIconTop: icon {{ "chat/menu_sidebar2-24x24", menuIconFg }};
chatTabsToggleIconTopOver: icon {{ "chat/menu_sidebar2-24x24", menuIconFgOver }};
chatTabsToggleIconLeft: icon {{ "chat/menu_sidebar3-24x24", menuIconFg }};
chatTabsToggleIconLeftOver: icon {{ "chat/menu_sidebar3-24x24", menuIconFgOver }};
chatTabsToggleIconBottom: icon {{ "chat/menu_sidebar1-24x24", menuIconFg }};
chatTabsToggleIconBottomOver: icon {{ "chat/menu_sidebar1-24x24", menuIconFgOver }};
chatTabsScroll: ScrollArea(defaultScrollArea) {
barHidden: true;
}