First version of the filters side bar.

This commit is contained in:
John Preston 2020-03-03 16:07:22 +04:00
parent 11d31ffc84
commit d4b9b65724
42 changed files with 235 additions and 65 deletions

View File

@ -937,6 +937,8 @@ PRIVATE
window/window_connecting_widget.h
window/window_controller.cpp
window/window_controller.h
window/window_filters_menu.cpp
window/window_filters_menu.h
window/window_history_hider.cpp
window/window_history_hider.h
window/window_lock_widgets.cpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -82,12 +82,10 @@ int PinnedDialogsCount(not_null<Dialogs::IndexedList*> list) {
} // namespace
struct InnerWidget::CollapsedRow {
CollapsedRow(Data::Folder *folder, FilterId filterId)
: folder(folder), filterId(filterId) {
CollapsedRow(Data::Folder *folder) : folder(folder) {
}
Data::Folder *folder = nullptr;
FilterId filterId = 0;
BasicRow row;
};
@ -121,10 +119,6 @@ InnerWidget::InnerWidget(
setAttribute(Qt::WA_OpaquePaintEvent, true);
#endif // OS_MAC_OLD
_filterId = Global::DialogsFiltersEnabled()
? Global::DialogsFilterId()
: 0;
_addContactLnk->addClickHandler([] { App::wnd()->onShowAddContact(); });
_cancelSearchInChat->setClickedCallback([=] { cancelSearchInChat(); });
_cancelSearchInChat->hide();
@ -262,6 +256,11 @@ InnerWidget::InnerWidget(
updateDialogRow(next);
}, lifetime());
_controller->activeChatsFilter(
) | rpl::start_with_next([=](FilterId filterId) {
switchToFilter(filterId);
}, lifetime());
refreshWithCollapsedRows(true);
setupShortcuts();
@ -294,21 +293,6 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) {
_collapsedSelected = -1;
_collapsedRows.clear();
if (!_openedFolder && Global::DialogsFiltersEnabled()) {
const auto &list = session().data().chatsFilters().list();
if (_filterId
&& ranges::find(list, _filterId, &Data::ChatFilter::id) == end(list)) {
switchToFilter(0);
}
if (_filterId) {
_collapsedRows.push_back(std::make_unique<CollapsedRow>(nullptr, 0));
} else {
for (const auto &filter : session().data().chatsFilters().list()) {
_collapsedRows.push_back(
std::make_unique<CollapsedRow>(nullptr, filter.id()));
}
}
}
const auto list = shownDialogs();
const auto archive = !list->empty()
? (*list->begin())->folder()
@ -323,7 +307,8 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) {
}
_skipTopDialogs = 1;
if (!inMainMenu && !_filterId) {
_collapsedRows.push_back(std::make_unique<CollapsedRow>(archive, 0));
_collapsedRows.push_back(
std::make_unique<CollapsedRow>(archive));
}
} else {
_skipTopDialogs = 0;
@ -394,7 +379,7 @@ void InnerWidget::changeOpenedFolder(Data::Folder *folder) {
//const auto lastMousePosition = _lastMousePosition;
clearSelection();
_openedFolder = folder;
_filterId = _openedFolder ? 0 : Global::DialogsFilterId();
_filterId = _openedFolder ? 0 : _controller->activeChatsFilterCurrent();
refreshWithCollapsedRows(true);
// This doesn't work, because we clear selection in leaveEvent on hide.
//if (mouseSelection && lastMousePosition) {
@ -706,23 +691,14 @@ void InnerWidget::paintCollapsedRow(
Painter &p,
not_null<const CollapsedRow*> row,
bool selected) const {
Expects(row->folder != nullptr);
const auto smallWidth = st::dialogsPadding.x()
+ st::dialogsPhotoSize
+ st::dialogsPhotoPadding;
const auto narrow = (width() <= smallWidth);
const auto text = row->folder
? row->folder->chatListName()
: _filterId
? (narrow ? "Show" : tr::lng_dialogs_show_all_chats(tr::now))
: ranges::find(
session().data().chatsFilters().list(),
row->filterId,
&Data::ChatFilter::id)->title();
const auto unread = row->folder
? row->folder->chatListUnreadCount()
: _filterId
? session().data().unreadOnlyMutedBadge()
: 0;
const auto text = row->folder->chatListName();
const auto unread = row->folder->chatListUnreadCount();
Layout::PaintCollapsedRow(
p,
row->row,
@ -1721,12 +1697,6 @@ FilterId InnerWidget::filterId() const {
return _filterId;
}
void InnerWidget::closeFilter() {
if (_filterId) {
switchToFilter(0);
}
}
void InnerWidget::clearSelection() {
_mouseSelection = false;
_lastMousePosition = std::nullopt;
@ -2551,11 +2521,8 @@ bool InnerWidget::chooseCollapsedRow() {
return false;
}
const auto &row = _collapsedRows[_collapsedSelected];
if (row->folder) {
_controller->openFolder(row->folder);
} else {
switchToFilter(row->filterId);
}
Assert(row->folder != nullptr);
_controller->openFolder(row->folder);
return true;
}
@ -2568,9 +2535,7 @@ void InnerWidget::switchToFilter(FilterId filterId) {
&Data::ChatFilter::id)) {
filterId = 0;
}
Global::SetDialogsFilterId(filterId);
_filterId = Global::DialogsFilterId();
Local::writeUserSettings();
_filterId = filterId;
refreshWithCollapsedRows(true);
_collapsedSelected = 0;
}

View File

@ -81,7 +81,6 @@ public:
const QVector<MTPPeer> &result);
[[nodiscard]] FilterId filterId() const;
void closeFilter();
void clearSelection();

View File

@ -1575,7 +1575,7 @@ void Widget::keyPressEvent(QKeyEvent *e) {
if (_openedFolder) {
controller()->closeFolder();
} else if (_inner->filterId()) {
_inner->closeFilter();
controller()->setActiveChatsFilter(0);
} else {
e->ignore();
}

View File

@ -118,6 +118,8 @@ public:
not_null<PhotoData*> photo);
void hideMediaPreview();
void updateControlsGeometry() override;
protected:
bool eventFilter(QObject *o, QEvent *e) override;
void closeEvent(QCloseEvent *e) override;
@ -126,8 +128,6 @@ protected:
void updateIsActiveHook() override;
void clearWidgetsHook() override;
void updateControlsGeometry() override;
public slots:
void showSettings();
void setInnerFocus();

View File

@ -373,6 +373,19 @@ HitTestResult MainWindow::hitTest(const QPoint &p) const {
return Window::HitTestResult::None;
}
int MainWindow::computeMinWidth() const {
auto result = st::windowMinWidth;
if (const auto session = _controller->sessionController()) {
if (const auto add = session->filtersWidth()) {
result += add;
}
}
if (_rightColumn) {
result += _rightColumn->width();
}
return result;
}
int MainWindow::computeMinHeight() const {
const auto title = _title ? _title->height() : 0;
const auto outdated = [&] {
@ -386,7 +399,7 @@ int MainWindow::computeMinHeight() const {
}
void MainWindow::initSize() {
setMinimumWidth(st::windowMinWidth);
setMinimumWidth(computeMinWidth());
setMinimumHeight(computeMinHeight());
auto position = cWindowPos();
@ -492,6 +505,7 @@ void MainWindow::leaveEventHook(QEvent *e) {
}
void MainWindow::updateControlsGeometry() {
auto bodyLeft = 0;
auto bodyTop = 0;
auto bodyWidth = width();
if (_title && !_title->isHidden()) {
@ -508,7 +522,13 @@ void MainWindow::updateControlsGeometry() {
bodyWidth -= _rightColumn->width();
_rightColumn->setGeometry(bodyWidth, bodyTop, width() - bodyWidth, height() - bodyTop);
}
_body->setGeometry(0, bodyTop, bodyWidth, height() - bodyTop);
if (const auto session = _controller->sessionController()) {
if (const auto skip = session->filtersWidth()) {
bodyLeft += skip;
bodyWidth -= skip;
}
}
_body->setGeometry(bodyLeft, bodyTop, bodyWidth, height() - bodyTop);
}
void MainWindow::updateUnreadCounter() {
@ -621,7 +641,7 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
const auto nowRightWidth = _rightColumn ? _rightColumn->width() : 0;
const auto wasMaximized = isMaximized();
const auto wasMinimumWidth = minimumWidth();
const auto nowMinimumWidth = st::windowMinWidth + nowRightWidth;
const auto nowMinimumWidth = computeMinWidth();
const auto firstResize = (nowMinimumWidth < wasMinimumWidth);
if (firstResize) {
setMinimumWidth(nowMinimumWidth);

View File

@ -80,7 +80,7 @@ public:
virtual ~MainWindow();
TWidget *bodyWidget() {
Ui::RpWidget *bodyWidget() {
return _body.data();
}
@ -95,6 +95,11 @@ public:
void clearWidgets();
int computeMinWidth() const;
int computeMinHeight() const;
virtual void updateControlsGeometry();
public slots:
bool minimizeToTray();
void updateGlobalMenu() {
@ -148,8 +153,6 @@ protected:
virtual void workmodeUpdated(DBIWorkMode mode) {
}
virtual void updateControlsGeometry();
virtual void createGlobalMenu() {
}
virtual void initShadows() {
@ -175,8 +178,6 @@ private:
void showTermsDecline();
void showTermsDelete();
int computeMinHeight() const;
not_null<Window::Controller*> _controller;
base::Timer _positionUpdatedTimer;
@ -184,7 +185,7 @@ private:
object_ptr<TitleWidget> _title = { nullptr };
object_ptr<Ui::RpWidget> _outdated;
object_ptr<TWidget> _body;
object_ptr<Ui::RpWidget> _body;
object_ptr<TWidget> _rightColumn = { nullptr };
QPointer<Ui::BoxContent> _termsBox;

View File

@ -245,6 +245,18 @@ createThemeLink: InputField(defaultInputField) {
font: boxTextFont;
}
windowFiltersWidth: 72px;
windowFiltersIconTop: 8px;
windowFiltersAll: icon {{ "filters_all", sideBarIconFg }};
windowFiltersAllActive: icon {{ "filters_all_active", sideBarIconFgActive }};
windowFiltersUnread: icon {{ "filters_unread", sideBarIconFg }};
windowFiltersUnreadActive: icon {{ "filters_unread_active", sideBarIconFgActive }};
windowFiltersUnmuted: icon {{ "filters_unmuted", sideBarIconFg }};
windowFiltersUnmutedActive: icon {{ "filters_unmuted_active", sideBarIconFgActive }};
windowFiltersCustom: icon {{ "filters_custom", sideBarIconFg }};
windowFiltersCustomActive: icon {{ "filters_custom_active", sideBarIconFgActive }};
windowFiltersSetup: icon {{ "filters_setup", sideBarIconFg }};
// Mac specific
macAccessoryWidth: 450.;

View File

@ -31,6 +31,11 @@ Controller::Controller(not_null<Main::Account*> account)
_sessionController = session
? std::make_unique<SessionController>(session, this)
: nullptr;
if (_sessionController && Global::DialogsFiltersEnabled()) {
_sessionController->toggleFiltersMenu(true);
} else {
sideBarChanged();
}
_widget.updateWindowIcon();
}, _lifetime);
@ -86,6 +91,11 @@ void Controller::showRightColumn(object_ptr<TWidget> widget) {
_widget.showRightColumn(std::move(widget));
}
void Controller::sideBarChanged() {
_widget.setMinimumWidth(_widget.computeMinWidth());
_widget.updateControlsGeometry();
}
void Controller::activate() {
_widget.activate();
}

View File

@ -54,6 +54,7 @@ public:
}
void showRightColumn(object_ptr<TWidget> widget);
void sideBarChanged();
void activate();
void reActivate();

View File

@ -0,0 +1,92 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "window/window_filters_menu.h"
#include "mainwindow.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_chat_filters.h"
#include "styles/style_widgets.h"
#include "styles/style_window.h"
namespace Window {
FiltersMenu::FiltersMenu(not_null<SessionController*> session)
: _session(session)
, _widget(session->widget(), st::defaultSideBarMenu) {
setup();
}
void FiltersMenu::setup() {
const auto body = _session->widget()->bodyWidget();
rpl::combine(
body->topValue(),
body->heightValue()
) | rpl::start_with_next([=](int top, int height) {
_widget.setGeometry({ 0, top, st::windowFiltersWidth, height });
}, _widget.lifetime());
const auto filters = &_session->session().data().chatsFilters();
rpl::single(
rpl::empty_value()
) | rpl::then(
filters->changed()
) | rpl::start_with_next([=] {
refresh();
}, _widget.lifetime());
_session->activeChatsFilter(
) | rpl::start_with_next([=](FilterId id) {
_widget.setActive(QString::number(id));
}, _widget.lifetime());
_widget.activateRequests(
) | rpl::start_with_next([=](const QString &id) {
if (id == "setup") {
} else if (const auto filterId = id.toInt()) {
_session->setActiveChatsFilter(filterId);
} else {
_session->setActiveChatsFilter(0);
}
}, _widget.lifetime());
}
void FiltersMenu::refresh() {
auto items = std::vector<Ui::SideBarMenu::Item>();
items.push_back({
QString::number(0),
"All Chats",
QString(),
&st::windowFiltersCustom,
&st::windowFiltersCustomActive,
st::windowFiltersIconTop
});
const auto filters = &_session->session().data().chatsFilters();
for (const auto &filter : filters->list()) {
items.push_back({
QString::number(filter.id()),
filter.title(),
QString(),
&st::windowFiltersCustom,
&st::windowFiltersCustomActive,
st::windowFiltersIconTop
});
}
items.push_back({
"setup",
"Setup",
QString(),
&st::windowFiltersSetup,
&st::windowFiltersSetup,
st::windowFiltersIconTop
});
_widget.setItems(items);
}
} // namespace Window

View File

@ -0,0 +1,29 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "ui/widgets/side_bar_menu.h"
namespace Window {
class SessionController;
class FiltersMenu final {
public:
explicit FiltersMenu(not_null<SessionController*> session);
private:
void setup();
void refresh();
const not_null<SessionController*> _session;
Ui::SideBarMenu _widget;
};
} // namespace Window

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_info_box.h"
#include "window/window_controller.h"
#include "window/main_window.h"
#include "window/window_filters_menu.h"
#include "info/info_memento.h"
#include "info/info_controller.h"
#include "history/history.h"
@ -189,6 +190,17 @@ void SessionController::initSupportMode() {
}, lifetime());
}
void SessionController::toggleFiltersMenu(bool enabled) {
if (!enabled == !_filters) {
return;
} else if (enabled) {
_filters = std::make_unique<FiltersMenu>(this);
} else {
_filters = nullptr;
}
_window->sideBarChanged();
}
bool SessionController::uniqueChatsInSearchResults() const {
return session().supportMode()
&& !session().settings().supportAllSearchResults()
@ -713,6 +725,22 @@ rpl::producer<FullMsgId> SessionController::floatPlayerClosed() const {
return _floatPlayers->closeEvents();
}
int SessionController::filtersWidth() const {
return _filters ? st::windowFiltersWidth : 0;
}
rpl::producer<FilterId> SessionController::activeChatsFilter() const {
return _activeChatsFilter.value();
}
FilterId SessionController::activeChatsFilterCurrent() const {
return _activeChatsFilter.current();
}
void SessionController::setActiveChatsFilter(FilterId id) {
_activeChatsFilter = id;
}
SessionController::~SessionController() = default;
} // namespace Window

View File

@ -56,6 +56,7 @@ namespace Window {
class MainWindow;
class SectionMemento;
class Controller;
class FiltersMenu;
enum class GifPauseReason {
Any = 0,
@ -292,6 +293,13 @@ public:
not_null<Media::Player::FloatDelegate*> replacement);
rpl::producer<FullMsgId> floatPlayerClosed() const;
[[nodiscard]] int filtersWidth() const;
[[nodiscard]] rpl::producer<FilterId> activeChatsFilter() const;
[[nodiscard]] FilterId activeChatsFilterCurrent() const;
void setActiveChatsFilter(FilterId id);
void toggleFiltersMenu(bool enabled);
rpl::lifetime &lifetime() {
return _lifetime;
}
@ -321,6 +329,7 @@ private:
const not_null<Controller*> _window;
std::unique_ptr<Passport::FormController> _passportForm;
std::unique_ptr<FiltersMenu> _filters;
GifPauseReasons _gifPauseReasons = 0;
base::Observable<void> _gifPauseLevelChanged;
@ -335,6 +344,8 @@ private:
std::deque<Dialogs::RowDescriptor> _chatEntryHistory;
int _chatEntryHistoryPosition = -1;
rpl::variable<FilterId> _activeChatsFilter;
std::unique_ptr<Media::Player::FloatController> _floatPlayers;
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;

@ -1 +1 @@
Subproject commit ccc12ce3da8f9ac30f30228c225585f732f74d5f
Subproject commit 81e9a80831555ae7908ee86fb15ea791fadd0891