From 61659244b7b3dca1cc23d762d960d5b14768cd2a Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 29 Jun 2017 22:09:10 +0300 Subject: [PATCH] Add night mode switch to the main menu. Also fix a bug with the default background applying. --- Telegram/Resources/icons/menu_night_mode.png | Bin 0 -> 522 bytes .../Resources/icons/menu_night_mode@2x.png | Bin 0 -> 805 bytes Telegram/Resources/langs/lang.strings | 3 + Telegram/Resources/night.tdesktop-theme | Bin 0 -> 8883 bytes Telegram/Resources/qrc/telegram.qrc | 1 + .../settings/settings_advanced_widget.cpp | 18 +++++- .../settings/settings_advanced_widget.h | 3 + .../settings/settings_background_widget.cpp | 2 +- Telegram/SourceFiles/storage/localstorage.cpp | 9 ++- Telegram/SourceFiles/storage/localstorage.h | 1 + Telegram/SourceFiles/ui/widgets/menu.cpp | 44 +++++++++++--- Telegram/SourceFiles/ui/widgets/menu.h | 2 + .../window/themes/window_theme.cpp | 56 +++++++++++++++--- .../SourceFiles/window/themes/window_theme.h | 3 + .../window/themes/window_theme_preview.cpp | 2 +- Telegram/SourceFiles/window/window.style | 11 +++- .../SourceFiles/window/window_main_menu.cpp | 35 +++++++++-- .../SourceFiles/window/window_main_menu.h | 4 ++ 18 files changed, 166 insertions(+), 28 deletions(-) create mode 100644 Telegram/Resources/icons/menu_night_mode.png create mode 100644 Telegram/Resources/icons/menu_night_mode@2x.png create mode 100644 Telegram/Resources/night.tdesktop-theme diff --git a/Telegram/Resources/icons/menu_night_mode.png b/Telegram/Resources/icons/menu_night_mode.png new file mode 100644 index 0000000000000000000000000000000000000000..8f31cc222a379454faa729ed68eac85458b5dcd4 GIT binary patch literal 522 zcmV+l0`>igP)y$FIJ1VQ{M7eNw&mbMzIp`kHo>JtPF?LoXlQ&XQHXbYjKRf@p1&!Et% zLl6y;oI6~+G97P~tyU`%1mU6n zhZBCl7<(`$BC;%t>h*e7^DuzpIGWGr59UNfx~>z?^S=XVnnu^_H4-qJ&7Lu*&=mE0 zJqUsj8C2F_1BC#sRx7qJpU?jupeRagVWm>ZH2;x+xX%LswOS3GPA4+}xC_LxtjK@^ znWjmlQtA0A+VA&?03xF8c1zW2H8p?(@F!@cSS+I5ZYQ>@swx_d1`34&0KoTsh@yyc zxs1VJfNr;o-EQ|?{}!|X0Gg)ZcswR%5yfW1^@s6 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/menu_night_mode@2x.png b/Telegram/Resources/icons/menu_night_mode@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..34be71f66877107f27823043140ba53d9453b2e1 GIT binary patch literal 805 zcmV+=1KRwFP)L>pS6(3n+))D{GnZ5OpJ6)ZkM`ULG>O8Y2MbmgiKptx!UD^is1%alL@)5ORnqEXf&c+E*I9V{sFR0RaMxwjn~&#c%BD8o}Zs_aBv`f4~`~x zVX;_*<2b&d=X5$9XqvXl@ZtiAL;|&1?Z@B%z!<~c-rlOiiwPKpfw#A}h2f{uDbCN& z*Abpyz%UFj#ukPLfO@^YuJC*Ux~^j|7;uI6JP*gm$D1Ya`1r^b9spimUe+0Yu|Tm{ zFMc-G)-HoA0B+oZf|dw8i6^jR%_KG;eX)h=t!!R@WXK& zoSvRahm6PL;sQi+#as}x*$nl19hppqJ9s9O!NbFY+z1fKmD4;T-EJ4vY8Cl>9;RtR z(==$B2GcZ=&*xFCR?+QtF`La`+qS%bs;Ue3epZR&I8aqpUVupalQK+7rIP$4{FAXO2sWeL`bDl7!HRk3qKqVkxHdR z!ixzI5q5TVxHfl1snu#oBodruPirjL)0Fm6ks j2}H&AFJ;th1)}B~(!Ck}LG>7p00000NkvXXu0mjf-Ozj> literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index d52c09e700..20fbbb29bc 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_menu_update" = "Update"; "lng_menu_restart" = "Restart"; "lng_menu_back" = "Back"; +"lng_menu_night_mode" = "Night mode"; "lng_disable_notifications_from_tray" = "Disable notifications"; "lng_enable_notifications_from_tray" = "Enable notifications"; @@ -368,6 +369,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_local_storage_clear_failed" = "Clear failed :("; "lng_settings_section_advanced_settings" = "Advanced Settings"; +"lng_settings_enable_night_theme" = "Enable night mode"; +"lng_settings_disable_night_theme" = "Disable night mode"; "lng_passcode_remove_button" = "Remove"; diff --git a/Telegram/Resources/night.tdesktop-theme b/Telegram/Resources/night.tdesktop-theme new file mode 100644 index 0000000000000000000000000000000000000000..fa7ba86f6d9f262ec7e718c4e5c6b2e49201e3aa GIT binary patch literal 8883 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 Ra{}hy^!#VPQv7H4e*m_-I$Qt% literal 0 HcmV?d00001 diff --git a/Telegram/Resources/qrc/telegram.qrc b/Telegram/Resources/qrc/telegram.qrc index 111f5c7ee8..e9ae810439 100644 --- a/Telegram/Resources/qrc/telegram.qrc +++ b/Telegram/Resources/qrc/telegram.qrc @@ -8,6 +8,7 @@ ../art/logo_256.png ../art/logo_256_no_margin.png ../art/sunrise.jpg + ../night.tdesktop-theme ../sounds/msg_incoming.mp3 diff --git a/Telegram/SourceFiles/settings/settings_advanced_widget.cpp b/Telegram/SourceFiles/settings/settings_advanced_widget.cpp index ac1f9bb2b6..4cbe7ca082 100644 --- a/Telegram/SourceFiles/settings/settings_advanced_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced_widget.cpp @@ -75,9 +75,13 @@ void AdvancedWidget::createControls() { } else { style::margins slidedPadding(0, marginLarge.bottom() / 2, 0, marginLarge.bottom() - (marginLarge.bottom() / 2)); addChildRow(_useDefaultTheme, marginLarge, slidedPadding, lang(lng_settings_bg_use_default), SLOT(onUseDefaultTheme())); - if (!Local::hasTheme()) { + if (!Window::Theme::IsNonDefaultUsed()) { _useDefaultTheme->hideFast(); } + addChildRow(_toggleNightTheme, marginLarge, slidedPadding, getNightThemeToggleText(), SLOT(onToggleNightTheme())); + if (Window::Theme::IsNonDefaultUsed()) { + _toggleNightTheme->hideFast(); + } } addChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ())); if (self()) { @@ -88,7 +92,9 @@ void AdvancedWidget::createControls() { void AdvancedWidget::checkNonDefaultTheme() { if (self()) return; - _useDefaultTheme->toggleAnimated(Local::hasTheme()); + _useDefaultTheme->toggleAnimated(Window::Theme::IsNonDefaultUsed()); + _toggleNightTheme->entity()->setText(getNightThemeToggleText()); + _toggleNightTheme->toggleAnimated(!Window::Theme::IsNonDefaultUsed()); } void AdvancedWidget::onManageLocalStorage() { @@ -124,6 +130,10 @@ void AdvancedWidget::onUseDefaultTheme() { Window::Theme::ApplyDefault(); } +void AdvancedWidget::onToggleNightTheme() { + Window::Theme::SwitchNightTheme(!Window::Theme::IsNightTheme()); +} + void AdvancedWidget::onAskQuestion() { auto box = Box(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button), base::lambda_guarded(this, [this] { onAskQuestionSure(); @@ -149,6 +159,10 @@ void AdvancedWidget::supportGot(const MTPhelp_Support &support) { } } +QString AdvancedWidget::getNightThemeToggleText() const { + return lang(Window::Theme::IsNightTheme() ? lng_settings_disable_night_theme : lng_settings_enable_night_theme); +} + void AdvancedWidget::onTelegramFAQ() { QDesktopServices::openUrl(telegramFaqLink()); } diff --git a/Telegram/SourceFiles/settings/settings_advanced_widget.h b/Telegram/SourceFiles/settings/settings_advanced_widget.h index 89dfa359ae..5c4a9a486d 100644 --- a/Telegram/SourceFiles/settings/settings_advanced_widget.h +++ b/Telegram/SourceFiles/settings/settings_advanced_widget.h @@ -39,6 +39,7 @@ private slots: void onAskQuestion(); void onAskQuestionSure(); void onUseDefaultTheme(); + void onToggleNightTheme(); void onTelegramFAQ(); void onLogOut(); @@ -49,12 +50,14 @@ private: void connectionTypeUpdated(); #endif // !TDESKTOP_DISABLE_NETWORK_PROXY void supportGot(const MTPhelp_Support &support); + QString getNightThemeToggleText() const; object_ptr _manageLocalStorage = { nullptr }; #ifndef TDESKTOP_DISABLE_NETWORK_PROXY object_ptr _connectionType = { nullptr }; #endif // !TDESKTOP_DISABLE_NETWORK_PROXY object_ptr> _useDefaultTheme = { nullptr }; + object_ptr> _toggleNightTheme = { nullptr }; object_ptr _askQuestion = { nullptr }; object_ptr _telegramFAQ = { nullptr }; object_ptr _logOut = { nullptr }; diff --git a/Telegram/SourceFiles/settings/settings_background_widget.cpp b/Telegram/SourceFiles/settings/settings_background_widget.cpp index 84f023c3fd..339bed22f8 100644 --- a/Telegram/SourceFiles/settings/settings_background_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_background_widget.cpp @@ -54,7 +54,7 @@ BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent) } void BackgroundRow::checkNonDefaultTheme() { - if (Local::hasTheme()) { + if (Window::Theme::IsNonDefaultUsed()) { if (!_useDefaultTheme) { _useDefaultTheme.create(this, lang(lng_settings_bg_use_default), st::boxLinkButton); _useDefaultTheme->show(); diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 597f8f4d1a..9b22a33e14 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -619,6 +619,7 @@ bool _backgroundWasRead = false; bool _backgroundCanWrite = true; FileKey _themeKey = 0; +QString _themeAbsolutePath; QString _themePaletteAbsolutePath; bool _readingUserSettings = false; @@ -3811,6 +3812,7 @@ bool readThemeUsingKey(FileKey key) { return false; } + _themeAbsolutePath = pathAbsolute; _themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString(); QFile file(pathRelative); @@ -3844,7 +3846,7 @@ bool readThemeUsingKey(FileKey key) { void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) { if (content.isEmpty()) { - _themePaletteAbsolutePath = QString(); + _themeAbsolutePath = _themePaletteAbsolutePath = QString(); if (_themeKey) { clearKey(_themeKey); _themeKey = 0; @@ -3853,6 +3855,7 @@ void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const return; } + _themeAbsolutePath = pathAbsolute; _themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString(); if (!_themeKey) { _themeKey = genKey(FileOption::Safe); @@ -3916,6 +3919,10 @@ QString themePaletteAbsolutePath() { return _themePaletteAbsolutePath; } +QString themeAbsolutePath() { + return _themeAbsolutePath; +} + bool copyThemeColorsToPalette(const QString &path) { if (!_themeKey) { return false; diff --git a/Telegram/SourceFiles/storage/localstorage.h b/Telegram/SourceFiles/storage/localstorage.h index f990511321..e00ea2c08c 100644 --- a/Telegram/SourceFiles/storage/localstorage.h +++ b/Telegram/SourceFiles/storage/localstorage.h @@ -160,6 +160,7 @@ bool readBackground(); void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache); void clearTheme(); bool hasTheme(); +QString themeAbsolutePath(); QString themePaletteAbsolutePath(); bool copyThemeColorsToPalette(const QString &file); diff --git a/Telegram/SourceFiles/ui/widgets/menu.cpp b/Telegram/SourceFiles/ui/widgets/menu.cpp index c4ec5ef1da..4b74e06141 100644 --- a/Telegram/SourceFiles/ui/widgets/menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/menu.cpp @@ -67,7 +67,6 @@ QAction *Menu::addAction(const QString &text, base::lambda callback, con QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) { connect(action, SIGNAL(changed()), this, SLOT(actionChanged())); - connect(action, SIGNAL(toggled(bool)), this, SLOT(actionToggled(bool))); _actions.push_back(action); auto createData = [icon, iconOver, action] { @@ -86,6 +85,7 @@ QAction *Menu::addAction(QAction *action, const style::icon *icon, const style:: if (_resizedCallback) { _resizedCallback(); } + updateSelected(QCursor::pos()); update(); return action; @@ -98,6 +98,8 @@ QAction *Menu::addSeparator() { } void Menu::clearActions() { + setSelected(-1); + setPressed(-1); _actionsData.clear(); for (auto action : base::take(_actions)) { if (action->parent() == this) { @@ -110,6 +112,17 @@ void Menu::clearActions() { } } +void Menu::finishAnimations() { + for (auto &data : _actionsData) { + if (data.ripple) { + data.ripple.reset(); + } + if (data.toggle) { + data.toggle->finishAnimation(); + } + } +} + int Menu::processAction(QAction *action, int index, int width) { auto &data = _actionsData[index]; if (action->isSeparator() || action->text().isEmpty()) { @@ -243,7 +256,7 @@ void Menu::itemPressed(TriggeredSource source) { return; } if (_selected >= 0 && _selected < _actions.size() && _actions[_selected]->isEnabled()) { - _pressed = _selected; + setPressed(_selected); if (source == TriggeredSource::Mouse) { if (!_actionsData[_pressed].ripple) { auto mask = RippleAnimation::rectMask(QSize(width(), _itemHeight)); @@ -259,11 +272,9 @@ void Menu::itemPressed(TriggeredSource source) { } void Menu::itemReleased(TriggeredSource source) { - auto pressed = std::exchange(_pressed, -1); - if (pressed >= 0 && pressed < _actions.size()) { - if (pressed != _selected && _actionsData[pressed].toggle) { - _actionsData[pressed].toggle->setStyle(_st.itemToggle); - } + if (_pressed >= 0 && _pressed < _actions.size()) { + auto pressed = _pressed; + setPressed(-1); if (source == TriggeredSource::Mouse && _actionsData[pressed].ripple) { _actionsData[pressed].ripple->lastStop(); } @@ -308,9 +319,9 @@ void Menu::handleKeyPress(int key) { } else if (newSelected >= _actions.size()) { newSelected -= _actions.size(); } - } while (newSelected != start && (!_actions.at(newSelected)->isEnabled() || _actions.at(newSelected)->isSeparator())); + } while (newSelected != start && (!_actions[newSelected]->isEnabled() || _actions[newSelected]->isSeparator())); - if (_actions.at(newSelected)->isEnabled() && !_actions.at(newSelected)->isSeparator()) { + if (_actions[newSelected]->isEnabled() && !_actions[newSelected]->isSeparator()) { _mouseSelection = false; setSelected(newSelected); } @@ -361,6 +372,21 @@ void Menu::setSelected(int selected) { } } +void Menu::setPressed(int pressed) { + if (pressed >= _actions.size()) { + pressed = -1; + } + if (_pressed != pressed) { + if (_pressed >= 0 && _pressed != _selected && _actionsData[_pressed].toggle) { + _actionsData[_pressed].toggle->setStyle(_st.itemToggle); + } + _pressed = pressed; + if (_pressed >= 0 && _actionsData[_pressed].toggle && _actions[_pressed]->isEnabled()) { + _actionsData[_pressed].toggle->setStyle(_st.itemToggleOver); + } + } +} + int Menu::itemTop(int index) { if (index > _actions.size()) { index = _actions.size(); diff --git a/Telegram/SourceFiles/ui/widgets/menu.h b/Telegram/SourceFiles/ui/widgets/menu.h index 51b7036bf1..99124ec0b9 100644 --- a/Telegram/SourceFiles/ui/widgets/menu.h +++ b/Telegram/SourceFiles/ui/widgets/menu.h @@ -38,6 +38,7 @@ public: QAction *addAction(const QString &text, base::lambda callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addSeparator(); void clearActions(); + void finishAnimations(); void clearSelection(); @@ -106,6 +107,7 @@ private: QAction *addAction(QAction *a, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); void setSelected(int selected); + void setPressed(int pressed); void clearMouseSelection(); int itemTop(int index); diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index e337a1ed37..51ef19f1b8 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -32,11 +32,11 @@ namespace Window { namespace Theme { namespace { -constexpr int kThemeFileSizeLimit = 5 * 1024 * 1024; -constexpr int kThemeBackgroundSizeLimit = 4 * 1024 * 1024; -constexpr int kThemeSchemeSizeLimit = 1024 * 1024; - -constexpr int kMinimumTiledSize = 512; +constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024; +constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024; +constexpr auto kThemeSchemeSizeLimit = 1024 * 1024; +constexpr auto kMinimumTiledSize = 512; +constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme"); struct Data { struct Applying { @@ -393,8 +393,15 @@ void ChatBackground::start() { } void ChatBackground::setImage(int32 id, QImage &&image) { + auto resetPalette = (id == kDefaultBackground && _id != kDefaultBackground && !Local::hasTheme()); if (id == kThemeBackground && _themeImage.isNull()) { id = kDefaultBackground; + } else if (resetPalette) { + // If we had a default color theme with non-default background, + // and we switch to default background we must somehow switch from + // adjusted service colors to default (non-adjusted) service colors. + // The only way to do that right now is through full palette reset. + style::main_palette::reset(); } _id = id; if (_id == kThemeBackground) { @@ -425,6 +432,10 @@ void ChatBackground::setImage(int32 id, QImage &&image) { } t_assert(!_pixmap.isNull() && !_pixmapForTiled.isNull()); notify(BackgroundUpdate(BackgroundUpdate::Type::New, _tile)); + if (resetPalette) { + notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true); + notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, _tile), true); + } } void ChatBackground::setPreparedImage(QImage &&image) { @@ -432,11 +443,11 @@ void ChatBackground::setPreparedImage(QImage &&image) { image.setDevicePixelRatio(cRetinaFactor()); auto adjustColors = [this] { - auto someCustomThemeApplied = [] { + auto someThemeApplied = [] { if (AreTestingTheme()) { return !instance->applying.path.isEmpty(); } - return Local::hasTheme(); + return IsNonDefaultUsed() || IsNightTheme(); }; auto usingThemeBackground = [this] { return (_id == kThemeBackground || _id == internal::kTestingThemeBackground); @@ -451,7 +462,7 @@ void ChatBackground::setPreparedImage(QImage &&image) { return !Local::themePaletteAbsolutePath().isEmpty(); }; - if (someCustomThemeApplied()) { + if (someThemeApplied()) { return !usingThemeBackground() && !testingPalette(); } return !usingDefaultBackground(); @@ -660,6 +671,27 @@ bool Apply(const QString &filepath) { return Apply(std::move(preview)); } +void SwitchNightTheme(bool enabled) { + if (enabled) { + auto preview = std::make_unique(); + preview->path = str_const_toString(kNightThemeFile); + if (!LoadFromFile(preview->path, &preview->instance, &preview->content)) { + return; + } + instance.createIfNull(); + instance->applying.path = std::move(preview->path); + instance->applying.content = std::move(preview->content); + instance->applying.cached = std::move(preview->instance.cached); + if (instance->applying.paletteForRevert.isEmpty()) { + instance->applying.paletteForRevert = style::main_palette::save(); + } + Background()->setTestingTheme(std::move(preview->instance)); + } else { + Window::Theme::ApplyDefault(); + } + KeepApplied(); +} + bool Apply(std::unique_ptr preview) { instance.createIfNull(); instance->applying.path = std::move(preview->path); @@ -724,6 +756,14 @@ void Revert() { Background()->revert(); } +bool IsNightTheme() { + return (Local::themeAbsolutePath() == str_const_toString(kNightThemeFile)); +} + +bool IsNonDefaultUsed() { + return Local::hasTheme() && !IsNightTheme(); +} + bool LoadFromFile(const QString &path, Instance *out, QByteArray *outContent) { *outContent = readThemeContent(path); if (outContent->size() < 4) { diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index cf18fb70dd..5cd67fda67 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -65,6 +65,9 @@ bool Apply(std::unique_ptr preview); void ApplyDefault(); bool ApplyEditedPalette(const QString &path, const QByteArray &content); void KeepApplied(); +bool IsNonDefaultUsed(); +bool IsNightTheme(); +void SwitchNightTheme(bool enabled); void Revert(); bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent); diff --git a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp index 6066bcedbb..619577f50d 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp @@ -524,7 +524,7 @@ void Generator::paintDialogs() { auto filterLeft = _dialogs.x() + st::dialogsFilterPadding.x() + st::dialogsMenuToggle.width + st::dialogsFilterPadding.x(); auto filterRight = st::dialogsFilterSkip + st::dialogsFilterPadding.x(); - auto filterWidth = _dialogs.width() - filterLeft - filterRight; + auto filterWidth = _dialogs.x() + _dialogs.width() - filterLeft - filterRight; auto filterAreaHeight = st::dialogsFilterPadding.y() + st::dialogsMenuToggle.height + st::dialogsFilterPadding.y(); auto filterTop = _dialogs.y() + (filterAreaHeight - st::dialogsFilter.height) / 2; auto filter = QRect(filterLeft, filterTop, filterWidth, st::dialogsFilter.height); diff --git a/Telegram/SourceFiles/window/window.style b/Telegram/SourceFiles/window/window.style index 309b4cbb2e..b9515a4507 100644 --- a/Telegram/SourceFiles/window/window.style +++ b/Telegram/SourceFiles/window/window.style @@ -118,6 +118,13 @@ mainMenu: Menu(defaultMenu) { itemFont: semiboldFont; itemIconPosition: point(28px, 10px); itemPadding: margins(76px, 13px, 28px, 13px); + itemToggle: Toggle(defaultMenuToggle) { + toggledFg: mainMenuCoverBg; + } + itemToggleOver: Toggle(defaultMenuToggleOver) { + toggledFg: mainMenuCoverBg; + } + itemToggleShift: 11px; } mainMenuNewGroup: icon {{ "menu_new_group", menuIconFg }}; mainMenuNewGroupOver: icon {{ "menu_new_group", menuIconFgOver }}; @@ -129,8 +136,8 @@ mainMenuCalls: icon {{ "menu_calls", menuIconFg }}; mainMenuCallsOver: icon {{ "menu_calls", menuIconFgOver }}; mainMenuSettings: icon {{ "menu_settings", menuIconFg }}; mainMenuSettingsOver: icon {{ "menu_settings", menuIconFgOver }}; -mainMenuHelp: icon {{ "menu_help", menuIconFg }}; -mainMenuHelpOver: icon {{ "menu_help", menuIconFgOver }}; +mainMenuNightMode: icon {{ "menu_night_mode", menuIconFg }}; +mainMenuNightModeOver: icon {{ "menu_night_mode", menuIconFgOver }}; 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 bf49302c9e..adf8fba295 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -23,10 +23,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "styles/style_window.h" #include "styles/style_dialogs.h" #include "profile/profile_userpic_button.h" +#include "window/themes/window_theme.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/menu.h" #include "mainwindow.h" +#include "storage/localstorage.h" #include "boxes/contacts_box.h" #include "boxes/about_box.h" #include "boxes/peer_list_box.h" @@ -50,6 +52,14 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent) }); checkSelf(); + _nightThemeSwitch.setCallback([this] { + if (auto action = *_nightThemeAction) { + if (action->isChecked() != Window::Theme::IsNightTheme()) { + Window::Theme::SwitchNightTheme(action->isChecked()); + } + } + }); + resize(st::mainMenuWidth, parentWidget()->height()); _menu->setTriggeredCallback([](QAction *action, int actionTop, Ui::Menu::TriggeredSource source) { emit action->triggered(); @@ -70,6 +80,11 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent) } })); subscribe(Global::RefPhoneCallsEnabledChanged(), [this] { refreshMenu(); }); + subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) { + if (update.type == Window::Theme::BackgroundUpdate::Type::ApplyingTheme) { + refreshMenu(); + } + }); updatePhone(); } @@ -94,9 +109,20 @@ void MainMenu::refreshMenu() { _menu->addAction(lang(lng_menu_settings), [] { App::wnd()->showSettings(); }, &st::mainMenuSettings, &st::mainMenuSettingsOver); - _menu->addAction(lang(lng_settings_faq), [] { - QDesktopServices::openUrl(telegramFaqLink()); - }, &st::mainMenuHelp, &st::mainMenuHelpOver); + + if (!Window::Theme::IsNonDefaultUsed()) { + _nightThemeAction = std::make_shared>(nullptr); + auto action = _menu->addAction(lang(lng_menu_night_mode), [this] { + if (auto action = *_nightThemeAction) { + action->setChecked(!action->isChecked()); + _nightThemeSwitch.callOnce(st::mainMenu.itemToggle.duration); + } + }, &st::mainMenuNightMode, &st::mainMenuNightModeOver); + *_nightThemeAction = action; + action->setCheckable(true); + action->setChecked(Window::Theme::IsNightTheme()); + _menu->finishAnimations(); + } updatePhone(); } @@ -133,6 +159,7 @@ void MainMenu::showFinished() { } void MainMenu::resizeEvent(QResizeEvent *e) { + _menu->setForceWidth(width()); updateControlsGeometry(); } @@ -143,7 +170,7 @@ void MainMenu::updateControlsGeometry() { if (_cloudButton) { _cloudButton->moveToRight(0, st::mainMenuCoverHeight - _cloudButton->height()); } - _menu->setGeometry(0, st::mainMenuCoverHeight + st::mainMenuSkip, width(), _menu->height()); + _menu->moveToLeft(0, st::mainMenuCoverHeight + st::mainMenuSkip); _telegram->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuTelegramBottom - _telegram->height()); _version->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuVersionBottom - _version->height()); } diff --git a/Telegram/SourceFiles/window/window_main_menu.h b/Telegram/SourceFiles/window/window_main_menu.h index dd2185e08a..ed6f4f6e6a 100644 --- a/Telegram/SourceFiles/window/window_main_menu.h +++ b/Telegram/SourceFiles/window/window_main_menu.h @@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once +#include "base/timer.h" + namespace Ui { class IconButton; class FlatLabel; @@ -56,6 +58,8 @@ private: object_ptr _menu; object_ptr _telegram; object_ptr _version; + std::shared_ptr> _nightThemeAction; + base::Timer _nightThemeSwitch; bool _showFinished = false; QString _phoneText;