diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp index 42953122cf..08b1669d1a 100644 --- a/Telegram/SourceFiles/application.cpp +++ b/Telegram/SourceFiles/application.cpp @@ -834,7 +834,7 @@ void AppClass::cancelPhotoUpdate(const PeerId &peer) { void AppClass::mtpPause() { MTP::pause(); - _mtpUnpauseTimer.start(st::slideDuration * 2); + _mtpUnpauseTimer.start(st::layerSlideDuration * 2); } void AppClass::mtpUnpause() { diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index 79226dfb5d..4a68d29980 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -100,18 +100,20 @@ dialogsFilter: flatInput(inpDefGray) { width: 240px; height: 32px; - textMrg: margins(12px, 3px, 12px, 3px); + textMrg: margins(12px, 3px, 30px, 3px); } dialogsCancelSearch: IconButton(dialogsMenuToggle) { icon: icon {{ "dialogs_cancel_search", dialogsMenuIconFg, point(0px, 1px) }}; iconOver: icon {{ "dialogs_cancel_search", dialogsMenuIconFgOver, point(0px, 1px) }}; } -dialogsMenu: DropdownMenu(defaultDropdownMenu) { - menu: Menu(defaultMenu) { - itemIconPosition: point(15px, 8px); - itemPadding: margins(56px, 10px, 56px, 12px); - } +dialogsMenu: Menu(defaultMenu) { + itemFont: semiboldFont; + itemIconPosition: point(28px, 11px); + itemPadding: margins(76px, 14px, 28px, 14px); +} +dialogsMenuWrap: DropdownMenu(defaultDropdownMenu) { + menu: dialogsMenu; } dialogsMenuPosition: point(-3px, -2px); dialogsMenuNewGroup: icon {{ "menu_new_group", menuIconFg }}; diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 779b7a2a1d..32fd61b7c7 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -2012,8 +2012,11 @@ void DialogsWidget::onChooseByDrag() { } void DialogsWidget::showMainMenu() { + App::wnd()->showMainMenu(); + return; + if (!_mainMenu) { - _mainMenu.create(this, st::dialogsMenu); + _mainMenu.create(this, st::dialogsMenuWrap); _mainMenu->addAction(lang(lng_create_group_title), [] { App::wnd()->onShowNewGroup(); }, &st::dialogsMenuNewGroup, &st::dialogsMenuNewGroupOver); diff --git a/Telegram/SourceFiles/layerwidget.cpp b/Telegram/SourceFiles/layerwidget.cpp index f6de4cce51..2499295509 100644 --- a/Telegram/SourceFiles/layerwidget.cpp +++ b/Telegram/SourceFiles/layerwidget.cpp @@ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "ui/filedialog.h" #include "styles/style_stickers.h" +#include "window/window_main_menu.h" namespace { @@ -48,6 +49,19 @@ public: , _shadow(st::boxShadow) { } + void setBodyCache(QPixmap &&bodyCache) { + _bodyCache = std_::move(bodyCache); + } + void setMainMenuCache(QPixmap &&mainMenuCache) { + _mainMenuCache = std_::move(mainMenuCache); + if (!_mainMenuCache.isNull()) { + _mainMenuWidth = _mainMenuCache.width() / cIntRetinaFactor(); + _mainMenuRight = 0; + } + } + void setMainMenuRight(int right) { + _mainMenuRight = right; + } void setLayerBox(const QRect &box, const QRect &hiddenSpecialBox) { _box = box; _hiddenSpecialBox = hiddenSpecialBox; @@ -61,6 +75,25 @@ protected: void paintEvent(QPaintEvent *e) override { Painter p(this); + auto hasMainMenuCache = !_mainMenuCache.isNull(); + if (hasMainMenuCache || _mainMenuRight) { + auto boxLeft = _mainMenuRight; + auto cacheWidth = boxLeft * cIntRetinaFactor(); + if (left > 0 && hasMainMenuCache) { + p.drawPixmapLeft(0, 0, width(), _mainMenuCache, rtlrect(_mainMenuCache.width() - cacheWidth, 0, cacheWidth, height() * cIntRetinaFactor(), _mainMenuCache.width())); + } + if (!_bodyCache.isNull()) { + p.drawPixmapLeft(boxLeft, 0, width(), _bodyCache, rtlrect(cacheWidth, 0, _bodyCache.width() - cacheWidth, height() * cIntRetinaFactor(), _bodyCache.width() - cacheWidth)); + } + _shadow.paint(p, QRect(0, 0, boxLeft, height()), 0, Ui::RectShadow::Side::Right); + + p.setOpacity(_opacity); + p.fillRect(myrtlrect(boxLeft, 0, width() - boxLeft, height()), st::layerBg); + return; + } + if (!_bodyCache.isNull()) { + p.drawPixmap(0, 0, _bodyCache); + } p.setOpacity(_opacity); if (_box.isNull()) { p.fillRect(rect(), st::layerBg); @@ -79,6 +112,11 @@ protected: } private: + QPixmap _bodyCache; + QPixmap _mainMenuCache; + int _mainMenuWidth = 0; + int _mainMenuRight = 0; + QRect _box, _hiddenSpecialBox; float64 _opacity = 0.; @@ -224,6 +262,16 @@ void LayerStackWidget::startHide() { } void LayerStackWidget::startAnimation(float64 toOpacity) { + if (_mainMenu) { + setAttribute(Qt::WA_OpaquePaintEvent); + hide(); + _background->setBodyCache(myGrab(App::wnd()->bodyWidget())); + show(); + _mainMenu->hide(); + _background->setMainMenuCache(myGrab(_mainMenu)); + _background->setMainMenuRight(toOpacity ? 0 : _mainMenu->width()); + } + if (App::app()) App::app()->mtpPause(); a_bg.start(toOpacity); a_layer.start(toOpacity); @@ -283,6 +331,9 @@ void LayerStackWidget::resizeEvent(QResizeEvent *e) { if (auto l = layer()) { l->parentResized(); } + if (_mainMenu) { + _mainMenu->resize(_mainMenu->width(), height()); + } updateLayerBox(); } @@ -300,6 +351,28 @@ void LayerStackWidget::showSpecialLayer(LayerWidget *l) { activateLayer(l); } +void LayerStackWidget::showMainMenu() { + clearLayers(); + if (_specialLayer) { + _specialLayer.destroyDelayed(); + } + _mainMenu.create(this); + _mainMenu->setGeometryToLeft(0, 0, _mainMenu->width(), height()); + + _mainMenu->setParent(this); + fixOrder(); + + if (isHidden()) { + startShow(); + } else { + _mainMenu->show(); + if (App::wnd()) App::wnd()->setInnerFocus(); + updateLayerBox(); + } + fixOrder(); + sendFakeMouseEvent(); +} + void LayerStackWidget::appendLayer(LayerWidget *l) { if (auto oldLayer = layer()) { oldLayer->hide(); @@ -338,6 +411,11 @@ void LayerStackWidget::initChildLayer(LayerWidget *l) { } void LayerStackWidget::activateLayer(LayerWidget *l) { + if (_mainMenu) { + _mainMenu.destroyDelayed(); + _background->setMainMenuRight(0); + _background->setMainMenuCache(QPixmap()); + } initChildLayer(l); if (isHidden()) { startShow(); @@ -358,6 +436,9 @@ void LayerStackWidget::fixOrder() { } else if (_specialLayer) { _specialLayer->raise(); } + if (_mainMenu) { + _mainMenu->raise(); + } } void LayerStackWidget::sendFakeMouseEvent() { @@ -371,8 +452,15 @@ void LayerStackWidget::step_background(float64 ms, bool timer) { a_layer.finish(); _a_background.stop(); _layerCache = _hiddenSpecialLayerCache = QPixmap(); + setAttribute(Qt::WA_OpaquePaintEvent, false); + _background->setBodyCache(QPixmap()); if (_hiding) { App::wnd()->layerFinishedHide(this); + if (_mainMenu) { + _background->setMainMenuRight(0); + _background->setMainMenuCache(QPixmap()); + _mainMenu.destroyDelayed(); + } } else { if (_specialLayer) { _specialLayer->show(); @@ -382,7 +470,11 @@ void LayerStackWidget::step_background(float64 ms, bool timer) { l->show(); l->showDone(); } - fixOrder(); + if (_mainMenu) { + _background->setMainMenuRight(_mainMenu->width()); + _background->setMainMenuCache(QPixmap()); + _mainMenu->show(); + } if (App::wnd()) App::wnd()->setInnerFocus(); } updateLayerBox(); @@ -390,6 +482,9 @@ void LayerStackWidget::step_background(float64 ms, bool timer) { } else { a_bg.update(dt, anim::easeOutCirc); a_layer.update(dt, anim::linear); + if (_mainMenu) { + _background->setMainMenuRight(a_bg.current() * _mainMenu->width()); + } } _background->setOpacity(a_bg.current()); if (timer) { diff --git a/Telegram/SourceFiles/layerwidget.h b/Telegram/SourceFiles/layerwidget.h index b44b4bc321..bd0eb45a19 100644 --- a/Telegram/SourceFiles/layerwidget.h +++ b/Telegram/SourceFiles/layerwidget.h @@ -20,6 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once +namespace Window { +class MainMenu; +} // namespace Window + #include "ui/effects/rect_shadow.h" class LayerWidget : public TWidget { @@ -65,6 +69,7 @@ public: void showLayer(LayerWidget *l); void showSpecialLayer(LayerWidget *l); + void showMainMenu(); void appendLayer(LayerWidget *l); void prependLayer(LayerWidget *l); @@ -115,6 +120,7 @@ private: Layers _layers; ChildWidget _specialLayer = { nullptr }; + ChildWidget _mainMenu = { nullptr }; class BackgroundWidget; ChildWidget _background; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index bb6f4982ba..f6a68ca785 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -48,6 +48,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "window/notifications_manager.h" #include "window/window_theme.h" #include "window/window_theme_warning.h" +#include "window/window_main_menu.h" ConnectingWidget::ConnectingWidget(QWidget *parent, const QString &text, const QString &reconnect) : TWidget(parent) , _shadow(st::boxShadow) @@ -406,6 +407,17 @@ void MainWindow::showSettings() { _layerBg->showSpecialLayer(_settings); } +void MainWindow::showMainMenu() { + if (_passcode) return; + + if (isHidden()) showFromTray(); + + if (!_layerBg) { + _layerBg.create(bodyWidget()); + } + _layerBg->showMainMenu(); +} + void MainWindow::ui_hideSettingsAndLayer(ShowLayerOptions options) { if (_layerBg) { _layerBg->onClose(); diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index 8f53d7d329..452b416116 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -157,6 +157,8 @@ public: return contentOverlapped(QRect(w->mapToGlobal(r.boundingRect().topLeft()), r.boundingRect().size())); } + void showMainMenu(); + void ui_showLayer(LayerWidget *box, ShowLayerOptions options); void ui_hideSettingsAndLayer(ShowLayerOptions options); bool ui_isLayerShown(); diff --git a/Telegram/SourceFiles/window/main_window.h b/Telegram/SourceFiles/window/main_window.h index 1e3f11f9b6..d287a03707 100644 --- a/Telegram/SourceFiles/window/main_window.h +++ b/Telegram/SourceFiles/window/main_window.h @@ -50,7 +50,7 @@ public: virtual ~MainWindow(); - QWidget *bodyWidget() { + TWidget *bodyWidget() { return _body; } @@ -90,7 +90,7 @@ private: bool _positionInited = false; ChildWidget _title = { nullptr }; - ChildWidget _body; + ChildWidget _body; QString _titleText; diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index 06a2cdfe07..a6db6a26c1 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -84,6 +84,40 @@ notifySendReply: IconButton { titleUnreadCounterTop: 5px; titleUnreadCounterRight: 35px; +mainMenuBg: #ffffff; +mainMenuWidth: 274px; +mainMenuCoverBg: #419fd9; +mainMenuCoverFg: windowActiveFg; +mainMenuCoverHeight: 140px; +mainMenuUserpicLeft: 24px; +mainMenuUserpicTop: 22px; +mainMenuUserpicSize: 48px; +mainMenuCoverTextLeft: 30px; +mainMenuCoverNameTop: 88px; +mainMenuCoverStatusTop: 106px; +mainMenuSkip: 13px; +mainMenuFooterLeft: 30px; +mainMenuTelegramLabel: flatLabel(labelDefFlat) { + font: semiboldFont; + align: align(left); + textFg: windowSubTextFg; +} +mainMenuTelegramStyle: textStyle(defaultTextStyle) { + linkFlags: semiboldFont; + linkFlagsOver: font(fsize semibold underline); + linkFg: windowSubTextFg; + linkFgDown: windowSubTextFg; +} +mainMenuTelegramBottom: 43px; +mainMenuVersionLabel: flatLabel(mainMenuTelegramLabel) { + font: normalFont; +} +mainMenuVersionStyle: textStyle(mainMenuTelegramStyle) { + linkFlags: normalFont; + linkFlagsOver: font(fsize underline); +} +mainMenuVersionBottom: 21px; + // Windows specific title titleHeight: 21px; diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp new file mode 100644 index 0000000000..1e2cc1e90b --- /dev/null +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -0,0 +1,105 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "window/window_main_menu.h" + +#include "styles/style_window.h" +#include "ui/flatlabel.h" +#include "ui/widgets/menu.h" +#include "mainwindow.h" +#include "boxes/contactsbox.h" +#include "boxes/aboutbox.h" +#include "lang.h" +#include "core/click_handler_types.h" +#include "styles/style_dialogs.h" + +namespace Window { +namespace { + +class AboutClickHandler : public ClickHandler { +public: + void onClick(Qt::MouseButton) const override { + Ui::showLayer(new AboutBox()); + } + +}; + +} // namespace + +MainMenu::MainMenu(QWidget *parent) : TWidget(parent) +, _menu(this, st::dialogsMenu) +, _telegram(this, st::mainMenuTelegramLabel, st::mainMenuTelegramStyle) +, _version(this, st::mainMenuVersionLabel, st::mainMenuVersionStyle) { + setAttribute(Qt::WA_OpaquePaintEvent); + resize(st::mainMenuWidth, parentWidget()->height()); + _menu->setTriggeredCallback([](QAction *action, int actionTop, Ui::Menu::TriggeredSource source) { + emit action->triggered(); + }); + _menu->addAction(lang(lng_create_group_title), [] { + App::wnd()->onShowNewGroup(); + }, &st::dialogsMenuNewGroup, &st::dialogsMenuNewGroupOver); + _menu->addAction(lang(lng_create_channel_title), [] { + App::wnd()->onShowNewChannel(); + }, &st::dialogsMenuNewChannel, &st::dialogsMenuNewChannelOver); + _menu->addAction(lang(lng_menu_contacts), [] { + Ui::showLayer(new ContactsBox()); + }, &st::dialogsMenuContacts, &st::dialogsMenuContactsOver); + _menu->addAction(lang(lng_menu_settings), [] { + App::wnd()->showSettings(); + }, &st::dialogsMenuSettings, &st::dialogsMenuSettingsOver); + _menu->addAction(lang(lng_settings_faq), [] { + QDesktopServices::openUrl(telegramFaqLink()); + }, &st::dialogsMenuHelp, &st::dialogsMenuHelpOver); + + _telegram->setRichText(textcmdLink(1, qsl("Telegram Desktop"))); + _telegram->setLink(1, ClickHandlerPtr(new UrlClickHandler(qsl("https://desktop.telegram.org")))); + _version->setRichText(textcmdLink(1, qsl("Version 1.2.3")) + QChar(' ') + QChar(8211) + QChar(' ') + textcmdLink(2, qsl("About"))); + _version->setLink(1, ClickHandlerPtr(new UrlClickHandler(qsl("https://desktop.telegram.org/?_hash=changelog")))); + _version->setLink(2, ClickHandlerPtr(new AboutClickHandler())); +} + +void MainMenu::resizeEvent(QResizeEvent *e) { + _menu->setGeometry(0, st::mainMenuCoverHeight + st::mainMenuSkip, width(), _menu->height()); + _telegram->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuTelegramBottom - _telegram->height()); + _version->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuVersionBottom - _version->height()); +} + +void MainMenu::paintEvent(QPaintEvent *e) { + Painter p(this); + auto cover = QRect(0, 0, width(), st::mainMenuCoverHeight).intersected(e->rect()); + if (!cover.isEmpty()) { + p.fillRect(cover, st::mainMenuCoverBg); + p.setPen(st::mainMenuCoverFg); + p.setFont(st::semiboldFont); + if (auto self = App::self()) { + self->paintUserpicLeft(p, st::mainMenuUserpicSize, st::mainMenuUserpicLeft, st::mainMenuUserpicTop, width()); + self->nameText.drawLeftElided(p, st::mainMenuCoverTextLeft, st::mainMenuCoverNameTop, width() - 2 * st::mainMenuCoverTextLeft, width()); + p.setFont(st::normalFont); + p.drawTextLeft(st::mainMenuCoverTextLeft, st::mainMenuCoverStatusTop, width(), qsl("online")); + } + } + auto other = QRect(0, st::mainMenuCoverHeight, width(), height() - st::mainMenuCoverHeight); + if (!other.isEmpty()) { + p.fillRect(other, st::mainMenuBg); + } +} + +} // namespace Window diff --git a/Telegram/SourceFiles/window/window_main_menu.h b/Telegram/SourceFiles/window/window_main_menu.h new file mode 100644 index 0000000000..62f68b4a47 --- /dev/null +++ b/Telegram/SourceFiles/window/window_main_menu.h @@ -0,0 +1,48 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "ui/effects/rect_shadow.h" + +class FlatLabel; + +namespace Ui { +class Menu; +} // namespace Ui + +namespace Window { + +class MainMenu : public TWidget { +public: + MainMenu(QWidget *parent); + +protected: + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + +private: + ChildWidget _menu; + ChildWidget _telegram; + ChildWidget _version; + +}; + +} // namespace Window diff --git a/Telegram/gyp/Telegram.gyp b/Telegram/gyp/Telegram.gyp index 788c110234..dc7818dfd9 100644 --- a/Telegram/gyp/Telegram.gyp +++ b/Telegram/gyp/Telegram.gyp @@ -555,6 +555,8 @@ '<(src_loc)/window/slide_animation.h', '<(src_loc)/window/top_bar_widget.cpp', '<(src_loc)/window/top_bar_widget.h', + '<(src_loc)/window/window_main_menu.cpp', + '<(src_loc)/window/window_main_menu.h', '<(src_loc)/window/window_theme.cpp', '<(src_loc)/window/window_theme.h', '<(src_loc)/window/window_theme_warning.cpp',