diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index e5462d0e1..8359ea980 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1317,6 +1317,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_mark_read" = "Mark as read"; "lng_context_archive_expand" = "Expand"; "lng_context_archive_collapse" = "Collapse"; +"lng_context_archive_to_menu" = "Move to main menu"; +"lng_context_archive_to_list" = "Move to chats list"; +"lng_context_archive_to_menu_info" = "Archive moved in the main menu!\nYou can return it with context menu of archive button."; "lng_context_promote_admin" = "Promote to admin"; "lng_context_edit_permissions" = "Edit permissions"; diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp index d62f32d7c..0359ef826 100644 --- a/Telegram/SourceFiles/auth_session.cpp +++ b/Telegram/SourceFiles/auth_session.cpp @@ -96,6 +96,7 @@ QByteArray AuthSessionSettings::serialize() const { stream << qint32(_variables.supportAllSearchResults.current() ? 1 : 0); stream << qint32(_variables.archiveCollapsed.current() ? 1 : 0); stream << qint32(_variables.notifyAboutPinned.current() ? 1 : 0); + stream << qint32(_variables.archiveInMainMenu.current() ? 1 : 0); } return result; } @@ -134,6 +135,7 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized) qint32 supportAllSearchResults = _variables.supportAllSearchResults.current() ? 1 : 0; qint32 archiveCollapsed = _variables.archiveCollapsed.current() ? 1 : 0; qint32 notifyAboutPinned = _variables.notifyAboutPinned.current() ? 1 : 0; + qint32 archiveInMainMenu = _variables.archiveInMainMenu.current() ? 1 : 0; stream >> selectorTab; stream >> lastSeenWarningSeen; @@ -219,6 +221,9 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized) if (!stream.atEnd()) { stream >> notifyAboutPinned; } + if (!stream.atEnd()) { + stream >> archiveInMainMenu; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for AuthSessionSettings::constructFromSerialized()")); @@ -290,6 +295,7 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized) _variables.supportAllSearchResults = (supportAllSearchResults == 1); _variables.archiveCollapsed = (archiveCollapsed == 1); _variables.notifyAboutPinned = (notifyAboutPinned == 1); + _variables.archiveInMainMenu = (archiveInMainMenu == 1); } void AuthSessionSettings::setSupportChatsTimeSlice(int slice) { @@ -408,6 +414,18 @@ rpl::producer AuthSessionSettings::notifyAboutPinnedChanges() const { return _variables.notifyAboutPinned.changes(); } +void AuthSessionSettings::setArchiveInMainMenu(bool inMainMenu) { + _variables.archiveInMainMenu = inMainMenu; +} + +bool AuthSessionSettings::archiveInMainMenu() const { + return _variables.archiveInMainMenu.current(); +} + +rpl::producer AuthSessionSettings::archiveInMainMenuChanges() const { + return _variables.archiveInMainMenu.changes(); +} + AuthSession &Auth() { return Core::App().activeAccount().session(); } diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h index ee6cd7806..f91bad6d1 100644 --- a/Telegram/SourceFiles/auth_session.h +++ b/Telegram/SourceFiles/auth_session.h @@ -200,6 +200,10 @@ public: bool notifyAboutPinned() const; rpl::producer notifyAboutPinnedChanges() const; + void setArchiveInMainMenu(bool inMainMenu); + bool archiveInMainMenu() const; + rpl::producer archiveInMainMenuChanges() const; + bool hadLegacyCallsPeerToPeerNobody() const { return _variables.hadLegacyCallsPeerToPeerNobody; } @@ -254,6 +258,7 @@ private: Data::AutoDownload::Full autoDownload; rpl::variable archiveCollapsed = false; rpl::variable notifyAboutPinned = true; + rpl::variable archiveInMainMenu = false; static constexpr auto kDefaultSupportChatsLimitSlice = 7 * 24 * 60 * 60; diff --git a/Telegram/SourceFiles/data/data_folder.cpp b/Telegram/SourceFiles/data/data_folder.cpp index 10645139b..536c82e7c 100644 --- a/Telegram/SourceFiles/data/data_folder.cpp +++ b/Telegram/SourceFiles/data/data_folder.cpp @@ -220,14 +220,30 @@ void Folder::paintUserpic( int x, int y, int size) const { + paintUserpic( + p, + x, + y, + size, + st::historyPeerArchiveUserpicBg, + st::historyPeerUserpicFg); +} + +void Folder::paintUserpic( + Painter &p, + int x, + int y, + int size, + const style::color &bg, + const style::color &fg) const { p.setPen(Qt::NoPen); - p.setBrush(st::historyPeerArchiveUserpicBg); + p.setBrush(bg); { PainterHighQualityEnabler hq(p); p.drawEllipse(x, y, size, size); } if (size == st::dialogsPhotoSize) { - st::dialogsArchiveUserpic.paintInCenter(p, { x, y, size, size }); + st::dialogsArchiveUserpic.paintInCenter(p, { x, y, size, size }, fg->c); } else { p.save(); const auto ratio = size / float64(st::dialogsPhotoSize); @@ -236,7 +252,8 @@ void Folder::paintUserpic( const auto skip = st::dialogsPhotoSize; st::dialogsArchiveUserpic.paintInCenter( p, - { -skip, -skip, 2 * skip, 2 * skip }); + { -skip, -skip, 2 * skip, 2 * skip }, + fg->c); p.restore(); } //const auto small = (size - st::lineWidth) / 2; // #feed diff --git a/Telegram/SourceFiles/data/data_folder.h b/Telegram/SourceFiles/data/data_folder.h index fd5ea6be4..2f71b7429 100644 --- a/Telegram/SourceFiles/data/data_folder.h +++ b/Telegram/SourceFiles/data/data_folder.h @@ -75,6 +75,14 @@ public: int y, int size) const override; + void paintUserpic( + Painter &p, + int x, + int y, + int size, + const style::color &bg, + const style::color &fg) const; + bool chatsListLoaded() const; void setChatsListLoaded(bool loaded = true); void setCloudChatsListSize(int size); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 5b09aa80a..c8fceb444 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -217,6 +217,11 @@ InnerWidget::InnerWidget( refreshWithCollapsedRows(); }, lifetime()); + session().settings().archiveInMainMenuChanges( + ) | rpl::start_with_next([=] { + refreshWithCollapsedRows(); + }, lifetime()); + subscribe(Window::Theme::Background(), [=](const Window::Theme::BackgroundUpdate &data) { if (data.paletteChanged()) { Layout::clearUnreadBadgesCache(); @@ -302,7 +307,8 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) { const auto archive = !list->empty() ? (*list->begin())->folder() : nullptr; - if (archive && session().settings().archiveCollapsed()) { + if (archive && session().settings().archiveCollapsed() + && !session().settings().archiveInMainMenu()) { if (_selected && _selected->folder() == archive) { _selected = nullptr; } @@ -2105,8 +2111,9 @@ Data::Folder *InnerWidget::shownFolder() const { } bool InnerWidget::needCollapsedRowsRefresh() const { - const auto archive = !shownDialogs()->empty() - ? (*shownDialogs()->begin())->folder() + const auto list = shownDialogs(); + const auto archive = !list->empty() + ? (*list->begin())->folder() : nullptr; const auto collapsedHasArchive = !_collapsedRows.empty() && (_collapsedRows.back()->folder != nullptr); diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index f1f55265b..06dfdf4be 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -96,8 +96,8 @@ mainMenuUserpic: UserpicButton(defaultUserpicButton) { photoSize: 48px; } mainMenuCloudButton: IconButton { - width: 64px; - height: 64px; + width: 48px; + height: 48px; icon: icon { // { "menu_cloud", mainMenuCloudFg }, diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 657cfd2fd..32b3d6f3b 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/menu.h" +#include "ui/widgets/popup_menu.h" #include "ui/special_buttons.h" #include "ui/empty_userpic.h" #include "mainwindow.h" @@ -26,6 +27,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/click_handler_types.h" #include "observer_peer.h" #include "auth_session.h" +#include "data/data_folder.h" +#include "data/data_session.h" #include "data/data_user.h" #include "mainwidget.h" #include "styles/style_window.h" @@ -124,9 +127,21 @@ MainMenu::MainMenu( , _version(this, st::mainMenuVersionLabel) { setAttribute(Qt::WA_OpaquePaintEvent); - auto showSelfChat = [] { + const auto showSelfChat = [] { App::main()->choosePeer(Auth().userPeerId(), ShowAtUnreadMsgId); }; + const auto showArchive = [=] { + if (const auto folder = Auth().data().folderLoaded(Data::Folder::kId)) { + App::wnd()->sessionController()->openFolder(folder); + Ui::hideSettingsAndLayer(); + } + }; + const auto checkArchive = [=] { + const auto folder = Auth().data().folderLoaded(Data::Folder::kId); + return folder + && !folder->chatsList()->empty() + && _controller->session().settings().archiveInMainMenu(); + }; _userpicButton.create( this, _controller, @@ -139,6 +154,27 @@ MainMenu::MainMenu( _cloudButton->setClickedCallback(showSelfChat); _cloudButton->show(); + _archiveButton.create(this, st::mainMenuCloudButton); + _archiveButton->setHidden(!checkArchive()); + _archiveButton->setAcceptBoth(true); + _archiveButton->clicks( + ) | rpl::start_with_next([=](Qt::MouseButton which) { + if (which == Qt::LeftButton) { + showArchive(); + return; + } else if (which != Qt::RightButton) { + return; + } + _contextMenu = base::make_unique_q(this); + _contextMenu->addAction( + lang(lng_context_archive_to_list), [=] { + _controller->session().settings().setArchiveInMainMenu(false); + _controller->session().saveSettingsDelayed(); + Ui::hideSettingsAndLayer(); + }); + _contextMenu->popup(QCursor::pos()); + }, _archiveButton->lifetime()); + _nightThemeSwitch.setCallback([this] { if (const auto action = *_nightThemeAction) { const auto nightMode = Window::Theme::IsNightMode(); @@ -178,6 +214,13 @@ MainMenu::MainMenu( refreshBackground(); } }); + Auth().data().chatsListChanges( + ) | rpl::filter([](Data::Folder *folder) { + return folder && (folder->id() == Data::Folder::kId); + }) | rpl::start_with_next([=](Data::Folder *folder) { + _archiveButton->setHidden(!checkArchive()); + update(); + }, lifetime()); updatePhone(); initResetScaleButton(); } @@ -310,7 +353,16 @@ void MainMenu::updateControlsGeometry() { _userpicButton->moveToLeft(st::mainMenuUserpicLeft, st::mainMenuUserpicTop); } if (_cloudButton) { - _cloudButton->moveToRight(0, st::mainMenuCoverHeight - _cloudButton->height()); + const auto offset = st::mainMenuCloudSize / 4; + const auto y = st::mainMenuCoverHeight + - _cloudButton->height() + - offset; + _cloudButton->moveToRight(offset, y); + if (_archiveButton) { + _archiveButton->moveToRight( + offset, + y - _cloudButton->height()); + } } if (_resetScaleButton) { _resetScaleButton->moveToRight(0, 0); @@ -371,6 +423,19 @@ void MainMenu::paintEvent(QPaintEvent *e) { isFill ? st::mainMenuCloudBg : st::msgServiceBg, isFill ? st::mainMenuCloudFg : st::msgServiceFg); } + + // Draw Archive button. + if (!_archiveButton->isHidden()) { + if (const auto folder = Auth().data().folderLoaded(Data::Folder::kId)) { + folder->paintUserpic( + p, + _archiveButton->x() + (_archiveButton->width() - st::mainMenuCloudSize) / 2, + _archiveButton->y() + (_archiveButton->height() - st::mainMenuCloudSize) / 2, + st::mainMenuCloudSize, + isFill ? st::mainMenuCloudBg : st::msgServiceBg, + isFill ? st::mainMenuCloudFg : st::msgServiceFg); + } + } } auto other = QRect(0, st::mainMenuCoverHeight, width(), height() - st::mainMenuCoverHeight).intersected(clip); if (!other.isEmpty()) { diff --git a/Telegram/SourceFiles/window/window_main_menu.h b/Telegram/SourceFiles/window/window_main_menu.h index 41bebca36..081a92270 100644 --- a/Telegram/SourceFiles/window/window_main_menu.h +++ b/Telegram/SourceFiles/window/window_main_menu.h @@ -15,6 +15,7 @@ class IconButton; class FlatLabel; class Menu; class UserpicButton; +class PopupMenu; } // namespace Ui namespace Window { @@ -44,12 +45,14 @@ private: not_null _controller; object_ptr _userpicButton = { nullptr }; object_ptr _cloudButton = { nullptr }; + object_ptr _archiveButton = { nullptr }; object_ptr _resetScaleButton = { nullptr }; object_ptr _menu; object_ptr _telegram; object_ptr _version; std::shared_ptr> _nightThemeAction; base::Timer _nightThemeSwitch; + base::unique_qptr _contextMenu; QString _phoneText; QImage _background; diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index d5f781a88..344154728 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -84,7 +84,7 @@ public: void fill(); private: - void addToggleCollapse(); + void addTogglesForArchive(); //bool showInfo(); //void addTogglePin(); //void addInfo(); @@ -544,11 +544,11 @@ FolderFiller::FolderFiller( void FolderFiller::fill() { if (_source == PeerMenuSource::ChatsList) { - addToggleCollapse(); + addTogglesForArchive(); } } -void FolderFiller::addToggleCollapse() { +void FolderFiller::addTogglesForArchive() { if (_folder->id() != Data::Folder::kId) { return; } @@ -561,6 +561,18 @@ void FolderFiller::addToggleCollapse() { controller->session().settings().setArchiveCollapsed(!hidden); controller->session().saveSettingsDelayed(); }); + + _addAction(lang(lng_context_archive_to_menu), [=] { + Ui::Toast::Config toast; + toast.text = lang(lng_context_archive_to_menu_info); + toast.maxWidth = st::boxWideWidth; + toast.durationMs = kArchivedToastDuration; + Ui::Toast::Show(toast); + + controller->session().settings().setArchiveInMainMenu( + !controller->session().settings().archiveInMainMenu()); + controller->session().saveSettingsDelayed(); + }); } // //void FolderFiller::addInfo() {