diff --git a/Telegram/Resources/icons/account_check.png b/Telegram/Resources/icons/account_check.png new file mode 100644 index 000000000..ac2cd9058 Binary files /dev/null and b/Telegram/Resources/icons/account_check.png differ diff --git a/Telegram/Resources/icons/account_check@2x.png b/Telegram/Resources/icons/account_check@2x.png new file mode 100644 index 000000000..48883f5b9 Binary files /dev/null and b/Telegram/Resources/icons/account_check@2x.png differ diff --git a/Telegram/Resources/icons/account_check@3x.png b/Telegram/Resources/icons/account_check@3x.png new file mode 100644 index 000000000..4ee2abd6e Binary files /dev/null and b/Telegram/Resources/icons/account_check@3x.png differ diff --git a/Telegram/Resources/icons/menu_add_account.png b/Telegram/Resources/icons/menu_add_account.png new file mode 100644 index 000000000..25de7ef71 Binary files /dev/null and b/Telegram/Resources/icons/menu_add_account.png differ diff --git a/Telegram/Resources/icons/menu_add_account@2x.png b/Telegram/Resources/icons/menu_add_account@2x.png new file mode 100644 index 000000000..70265c3b3 Binary files /dev/null and b/Telegram/Resources/icons/menu_add_account@2x.png differ diff --git a/Telegram/Resources/icons/menu_add_account@3x.png b/Telegram/Resources/icons/menu_add_account@3x.png new file mode 100644 index 000000000..9a111d9bf Binary files /dev/null and b/Telegram/Resources/icons/menu_add_account@3x.png differ diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp index 39599e6d1..7e3e0cf17 100644 --- a/Telegram/SourceFiles/main/main_session.cpp +++ b/Telegram/SourceFiles/main/main_session.cpp @@ -92,6 +92,15 @@ Session::Session( _api->instance().setUserPhone(_user->phone()); + // Load current userpic and keep it loaded. + changes().peerFlagsValue( + _user, + Data::PeerUpdate::Flag::Photo + ) | rpl::start_with_next([=] { + [[maybe_unused]] const auto image = _user->currentUserpic( + _selfUserpicView); + }, lifetime()); + crl::on_main(this, [=] { using Flag = Data::PeerUpdate::Flag; changes().peerUpdates( diff --git a/Telegram/SourceFiles/main/main_session.h b/Telegram/SourceFiles/main/main_session.h index f23f8957d..9039dbf27 100644 --- a/Telegram/SourceFiles/main/main_session.h +++ b/Telegram/SourceFiles/main/main_session.h @@ -31,6 +31,7 @@ class Templates; namespace Data { class Session; class Changes; +class CloudImageView; } // namespace Data namespace Storage { @@ -174,6 +175,8 @@ private: const std::unique_ptr _supportHelper; + std::shared_ptr _selfUserpicView; + base::flat_set> _windows; base::Timer _saveSettingsTimer; diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index be3dab507..9a8e796a2 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -243,15 +243,6 @@ MainWidget::MainWidget( floatPlayerClosed(itemId); }, lifetime()); - // Load current userpic and keep it loaded. - session().changes().peerFlagsValue( - session().user(), - Data::PeerUpdate::Flag::Photo - ) | rpl::start_with_next([=] { - [[maybe_unused]] const auto image = session().user()->currentUserpic( - _selfUserpicView); - }, lifetime()); - updateScrollColors(); setupConnectingWidget(); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 217ed65b4..21b3f16ce 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -34,7 +34,6 @@ class Session; namespace Data { class WallPaper; -class CloudImageView; } // namespace Data namespace Dialogs { @@ -360,8 +359,6 @@ private: int _thirdColumnWidth = 0; Ui::Animations::Simple _a_dialogsWidth; - std::shared_ptr _selfUserpicView; - object_ptr _sideShadow; object_ptr _thirdShadow = { nullptr }; object_ptr _firstColumnResizeArea = { nullptr }; diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index 3f117c6b2..7e75ef589 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -145,8 +145,18 @@ mainMenuReload: icon {{ "menu_reload", menuIconFg }}; mainMenuReloadOver: icon {{ "menu_reload", menuIconFgOver }}; mainMenuFixOrder: icon {{ "menu_fix_order", menuIconFg }}; mainMenuFixOrderOver: icon {{ "menu_fix_order", menuIconFgOver }}; -mainMenuAddAccount: icon {{ "menu_fix_order", menuIconFg }}; -mainMenuAddAccountOver: icon {{ "menu_fix_order", menuIconFgOver }}; +mainMenuAddAccount: icon {{ "menu_add_account", menuIconFg }}; +mainMenuAddAccountOver: icon {{ "menu_add_account", menuIconFgOver }}; +mainMenuAccountSize: 32px; +mainMenuAccountCheckPosition: point(7px, 5px); +mainMenuAccountCheckLine: 2px; +mainMenuAccountCheck: RoundCheckbox(defaultRoundCheckbox) { + size: 18px; + bgInactive: overviewCheckBg; + bgActive: overviewCheckBgActive; + check: icon {{ "account_check", overviewCheckFgActive }}; +} + mainMenuFooterLeft: 30px; mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) { align: align(left); diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 0b50dc952..56c5ab5b5 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -88,10 +88,13 @@ public: private: void paintEvent(QPaintEvent *e) override; + void paintUserpic(Painter &p); const not_null _account; const style::Menu &_st; std::shared_ptr _userpicView; + InMemoryKey _userpicKey = {}; + QImage _userpicCache; Dialogs::Layout::UnreadBadgeStyle _unreadSt; int _unreadBadge = 0; @@ -154,26 +157,68 @@ MainMenu::AccountButton::AccountButton( }, lifetime()); } -void MainMenu::AccountButton::paintEvent(QPaintEvent *e) { +void MainMenu::AccountButton::paintUserpic(Painter &p) { Expects(_account->sessionExists()); - const auto &session = _account->session(); + const auto size = st::mainMenuAccountSize; + const auto iconSize = height() - 2 * _st.itemIconPosition.y(); + const auto shift = (size - iconSize) / 2; + const auto x = _st.itemIconPosition.x() - shift; + const auto y = (height() - size) / 2; + + const auto check = (_account == &Core::App().domain().active()); + const auto user = _account->session().user(); + if (!check) { + user->paintUserpicLeft(p, _userpicView, x, y, width(), size); + return; + } + const auto added = y; + const auto cacheSize = QSize(size + added, size + added) + * cIntRetinaFactor(); + const auto key = user->userpicUniqueKey(_userpicView); + if (_userpicKey != key) { + _userpicKey = key; + if (_userpicCache.size() != cacheSize) { + _userpicCache = QImage(cacheSize, QImage::Format_ARGB32_Premultiplied); + _userpicCache.setDevicePixelRatio(cRetinaFactor()); + } + _userpicCache.fill(Qt::transparent); + + auto q = Painter(&_userpicCache); + user->paintUserpicLeft(q, _userpicView, 0, 0, width(), size); + + const auto iconDiameter = st::mainMenuAccountCheck.size; + const auto iconLeft = size + st::mainMenuAccountCheckPosition.x() - iconDiameter; + const auto iconTop = size + st::mainMenuAccountCheckPosition.y() - iconDiameter; + const auto iconEllipse = QRect(iconLeft, iconTop, iconDiameter, iconDiameter); + auto iconBorderPen = QPen(Qt::transparent); + const auto line = st::mainMenuAccountCheckLine; + iconBorderPen.setWidth(line); + + PainterHighQualityEnabler hq(q); + q.setCompositionMode(QPainter::CompositionMode_Source); + q.setPen(iconBorderPen); + q.setBrush(st::dialogsUnreadBg); + q.drawEllipse(iconEllipse); + + q.setCompositionMode(QPainter::CompositionMode_SourceOver); + st::mainMenuAccountCheck.check.paintInCenter(q, iconEllipse); + } + p.drawImage(x, y, _userpicCache); +} + +void MainMenu::AccountButton::paintEvent(QPaintEvent *e) { + Expects(_account->sessionExists()); auto p = Painter(this); const auto over = isOver(); p.fillRect(rect(), over ? _st.itemBgOver : _st.itemBg); paintRipple(p, 0, 0); - session.user()->paintUserpicLeft( - p, - _userpicView, - _st.itemIconPosition.x(), - _st.itemIconPosition.y(), - width(), - height() - 2 * _st.itemIconPosition.y()); + paintUserpic(p); auto available = width() - _st.itemPadding.left(); - if (_unreadBadge && _account != &Core::App().domain().active()) { + if (_unreadBadge) { _unreadSt.muted = _unreadBadgeMuted; const auto string = (_unreadBadge > 99) ? "99+" @@ -196,7 +241,7 @@ void MainMenu::AccountButton::paintEvent(QPaintEvent *e) { } p.setPen(over ? _st.itemFgOver : _st.itemFg); - session.user()->nameText().drawElided( + _account->session().user()->nameText().drawElided( p, _st.itemPadding.left(), _st.itemPadding.top(), @@ -514,7 +559,12 @@ void MainMenu::rebuildAccounts() { const auto inner = _accounts->entity(); auto count = 0; - for (auto &[account, button] : _watched) { + for (const auto &[index, pointer] : Core::App().domain().accounts()) { + const auto account = pointer.get(); + auto i = _watched.find(account); + Assert(i != _watched.end()); + + auto &button = i->second; if (!account->sessionExists()) { button = nullptr; } else if (!button) { @@ -522,6 +572,10 @@ void MainMenu::rebuildAccounts() { ++count, object_ptr(inner, account))); button->setClickedCallback([=] { + if (account == &Core::App().domain().active()) { + closeLayer(); + return; + } auto activate = [=, guard = _accountSwitchGuard.make_guard()]{ if (guard) { Core::App().domain().activate(account); diff --git a/Telegram/lib_ui b/Telegram/lib_ui index d31d94e8f..2a0d189ee 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit d31d94e8fb47b8492fbf341b93c19ddfbcb42fa2 +Subproject commit 2a0d189ee22d8573bd4f9f0971ef1aa27a12f02d