Add night mode switch to the main menu.

Also fix a bug with the default background applying.
This commit is contained in:
John Preston 2017-06-29 22:09:10 +03:00
parent 19023b4cc2
commit 61659244b7
18 changed files with 166 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

View File

@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_menu_update" = "Update"; "lng_menu_update" = "Update";
"lng_menu_restart" = "Restart"; "lng_menu_restart" = "Restart";
"lng_menu_back" = "Back"; "lng_menu_back" = "Back";
"lng_menu_night_mode" = "Night mode";
"lng_disable_notifications_from_tray" = "Disable notifications"; "lng_disable_notifications_from_tray" = "Disable notifications";
"lng_enable_notifications_from_tray" = "Enable 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_local_storage_clear_failed" = "Clear failed :(";
"lng_settings_section_advanced_settings" = "Advanced Settings"; "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"; "lng_passcode_remove_button" = "Remove";

Binary file not shown.

View File

@ -8,6 +8,7 @@
<file alias="art/logo_256.png">../art/logo_256.png</file> <file alias="art/logo_256.png">../art/logo_256.png</file>
<file alias="art/logo_256_no_margin.png">../art/logo_256_no_margin.png</file> <file alias="art/logo_256_no_margin.png">../art/logo_256_no_margin.png</file>
<file alias="art/sunrise.jpg">../art/sunrise.jpg</file> <file alias="art/sunrise.jpg">../art/sunrise.jpg</file>
<file alias="night.tdesktop-theme">../night.tdesktop-theme</file>
</qresource> </qresource>
<qresource prefix="/sounds"> <qresource prefix="/sounds">
<file alias="msg_incoming.mp3">../sounds/msg_incoming.mp3</file> <file alias="msg_incoming.mp3">../sounds/msg_incoming.mp3</file>

View File

@ -75,9 +75,13 @@ void AdvancedWidget::createControls() {
} else { } else {
style::margins slidedPadding(0, marginLarge.bottom() / 2, 0, marginLarge.bottom() - (marginLarge.bottom() / 2)); 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())); addChildRow(_useDefaultTheme, marginLarge, slidedPadding, lang(lng_settings_bg_use_default), SLOT(onUseDefaultTheme()));
if (!Local::hasTheme()) { if (!Window::Theme::IsNonDefaultUsed()) {
_useDefaultTheme->hideFast(); _useDefaultTheme->hideFast();
} }
addChildRow(_toggleNightTheme, marginLarge, slidedPadding, getNightThemeToggleText(), SLOT(onToggleNightTheme()));
if (Window::Theme::IsNonDefaultUsed()) {
_toggleNightTheme->hideFast();
}
} }
addChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ())); addChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ()));
if (self()) { if (self()) {
@ -88,7 +92,9 @@ void AdvancedWidget::createControls() {
void AdvancedWidget::checkNonDefaultTheme() { void AdvancedWidget::checkNonDefaultTheme() {
if (self()) return; if (self()) return;
_useDefaultTheme->toggleAnimated(Local::hasTheme()); _useDefaultTheme->toggleAnimated(Window::Theme::IsNonDefaultUsed());
_toggleNightTheme->entity()->setText(getNightThemeToggleText());
_toggleNightTheme->toggleAnimated(!Window::Theme::IsNonDefaultUsed());
} }
void AdvancedWidget::onManageLocalStorage() { void AdvancedWidget::onManageLocalStorage() {
@ -124,6 +130,10 @@ void AdvancedWidget::onUseDefaultTheme() {
Window::Theme::ApplyDefault(); Window::Theme::ApplyDefault();
} }
void AdvancedWidget::onToggleNightTheme() {
Window::Theme::SwitchNightTheme(!Window::Theme::IsNightTheme());
}
void AdvancedWidget::onAskQuestion() { void AdvancedWidget::onAskQuestion() {
auto box = Box<ConfirmBox>(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button), base::lambda_guarded(this, [this] { auto box = Box<ConfirmBox>(lang(lng_settings_ask_sure), lang(lng_settings_ask_ok), lang(lng_settings_faq_button), base::lambda_guarded(this, [this] {
onAskQuestionSure(); 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() { void AdvancedWidget::onTelegramFAQ() {
QDesktopServices::openUrl(telegramFaqLink()); QDesktopServices::openUrl(telegramFaqLink());
} }

View File

@ -39,6 +39,7 @@ private slots:
void onAskQuestion(); void onAskQuestion();
void onAskQuestionSure(); void onAskQuestionSure();
void onUseDefaultTheme(); void onUseDefaultTheme();
void onToggleNightTheme();
void onTelegramFAQ(); void onTelegramFAQ();
void onLogOut(); void onLogOut();
@ -49,12 +50,14 @@ private:
void connectionTypeUpdated(); void connectionTypeUpdated();
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY #endif // !TDESKTOP_DISABLE_NETWORK_PROXY
void supportGot(const MTPhelp_Support &support); void supportGot(const MTPhelp_Support &support);
QString getNightThemeToggleText() const;
object_ptr<Ui::LinkButton> _manageLocalStorage = { nullptr }; object_ptr<Ui::LinkButton> _manageLocalStorage = { nullptr };
#ifndef TDESKTOP_DISABLE_NETWORK_PROXY #ifndef TDESKTOP_DISABLE_NETWORK_PROXY
object_ptr<LabeledLink> _connectionType = { nullptr }; object_ptr<LabeledLink> _connectionType = { nullptr };
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY #endif // !TDESKTOP_DISABLE_NETWORK_PROXY
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _useDefaultTheme = { nullptr }; object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _useDefaultTheme = { nullptr };
object_ptr<Ui::WidgetSlideWrap<Ui::LinkButton>> _toggleNightTheme = { nullptr };
object_ptr<Ui::LinkButton> _askQuestion = { nullptr }; object_ptr<Ui::LinkButton> _askQuestion = { nullptr };
object_ptr<Ui::LinkButton> _telegramFAQ = { nullptr }; object_ptr<Ui::LinkButton> _telegramFAQ = { nullptr };
object_ptr<Ui::LinkButton> _logOut = { nullptr }; object_ptr<Ui::LinkButton> _logOut = { nullptr };

View File

@ -54,7 +54,7 @@ BackgroundRow::BackgroundRow(QWidget *parent) : TWidget(parent)
} }
void BackgroundRow::checkNonDefaultTheme() { void BackgroundRow::checkNonDefaultTheme() {
if (Local::hasTheme()) { if (Window::Theme::IsNonDefaultUsed()) {
if (!_useDefaultTheme) { if (!_useDefaultTheme) {
_useDefaultTheme.create(this, lang(lng_settings_bg_use_default), st::boxLinkButton); _useDefaultTheme.create(this, lang(lng_settings_bg_use_default), st::boxLinkButton);
_useDefaultTheme->show(); _useDefaultTheme->show();

View File

@ -619,6 +619,7 @@ bool _backgroundWasRead = false;
bool _backgroundCanWrite = true; bool _backgroundCanWrite = true;
FileKey _themeKey = 0; FileKey _themeKey = 0;
QString _themeAbsolutePath;
QString _themePaletteAbsolutePath; QString _themePaletteAbsolutePath;
bool _readingUserSettings = false; bool _readingUserSettings = false;
@ -3811,6 +3812,7 @@ bool readThemeUsingKey(FileKey key) {
return false; return false;
} }
_themeAbsolutePath = pathAbsolute;
_themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString(); _themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString();
QFile file(pathRelative); 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) { void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) {
if (content.isEmpty()) { if (content.isEmpty()) {
_themePaletteAbsolutePath = QString(); _themeAbsolutePath = _themePaletteAbsolutePath = QString();
if (_themeKey) { if (_themeKey) {
clearKey(_themeKey); clearKey(_themeKey);
_themeKey = 0; _themeKey = 0;
@ -3853,6 +3855,7 @@ void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const
return; return;
} }
_themeAbsolutePath = pathAbsolute;
_themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString(); _themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString();
if (!_themeKey) { if (!_themeKey) {
_themeKey = genKey(FileOption::Safe); _themeKey = genKey(FileOption::Safe);
@ -3916,6 +3919,10 @@ QString themePaletteAbsolutePath() {
return _themePaletteAbsolutePath; return _themePaletteAbsolutePath;
} }
QString themeAbsolutePath() {
return _themeAbsolutePath;
}
bool copyThemeColorsToPalette(const QString &path) { bool copyThemeColorsToPalette(const QString &path) {
if (!_themeKey) { if (!_themeKey) {
return false; return false;

View File

@ -160,6 +160,7 @@ bool readBackground();
void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache); void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache);
void clearTheme(); void clearTheme();
bool hasTheme(); bool hasTheme();
QString themeAbsolutePath();
QString themePaletteAbsolutePath(); QString themePaletteAbsolutePath();
bool copyThemeColorsToPalette(const QString &file); bool copyThemeColorsToPalette(const QString &file);

View File

@ -67,7 +67,6 @@ QAction *Menu::addAction(const QString &text, base::lambda<void()> callback, con
QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) { QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::icon *iconOver) {
connect(action, SIGNAL(changed()), this, SLOT(actionChanged())); connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
connect(action, SIGNAL(toggled(bool)), this, SLOT(actionToggled(bool)));
_actions.push_back(action); _actions.push_back(action);
auto createData = [icon, iconOver, action] { auto createData = [icon, iconOver, action] {
@ -86,6 +85,7 @@ QAction *Menu::addAction(QAction *action, const style::icon *icon, const style::
if (_resizedCallback) { if (_resizedCallback) {
_resizedCallback(); _resizedCallback();
} }
updateSelected(QCursor::pos());
update(); update();
return action; return action;
@ -98,6 +98,8 @@ QAction *Menu::addSeparator() {
} }
void Menu::clearActions() { void Menu::clearActions() {
setSelected(-1);
setPressed(-1);
_actionsData.clear(); _actionsData.clear();
for (auto action : base::take(_actions)) { for (auto action : base::take(_actions)) {
if (action->parent() == this) { 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) { int Menu::processAction(QAction *action, int index, int width) {
auto &data = _actionsData[index]; auto &data = _actionsData[index];
if (action->isSeparator() || action->text().isEmpty()) { if (action->isSeparator() || action->text().isEmpty()) {
@ -243,7 +256,7 @@ void Menu::itemPressed(TriggeredSource source) {
return; return;
} }
if (_selected >= 0 && _selected < _actions.size() && _actions[_selected]->isEnabled()) { if (_selected >= 0 && _selected < _actions.size() && _actions[_selected]->isEnabled()) {
_pressed = _selected; setPressed(_selected);
if (source == TriggeredSource::Mouse) { if (source == TriggeredSource::Mouse) {
if (!_actionsData[_pressed].ripple) { if (!_actionsData[_pressed].ripple) {
auto mask = RippleAnimation::rectMask(QSize(width(), _itemHeight)); auto mask = RippleAnimation::rectMask(QSize(width(), _itemHeight));
@ -259,11 +272,9 @@ void Menu::itemPressed(TriggeredSource source) {
} }
void Menu::itemReleased(TriggeredSource source) { void Menu::itemReleased(TriggeredSource source) {
auto pressed = std::exchange(_pressed, -1); if (_pressed >= 0 && _pressed < _actions.size()) {
if (pressed >= 0 && pressed < _actions.size()) { auto pressed = _pressed;
if (pressed != _selected && _actionsData[pressed].toggle) { setPressed(-1);
_actionsData[pressed].toggle->setStyle(_st.itemToggle);
}
if (source == TriggeredSource::Mouse && _actionsData[pressed].ripple) { if (source == TriggeredSource::Mouse && _actionsData[pressed].ripple) {
_actionsData[pressed].ripple->lastStop(); _actionsData[pressed].ripple->lastStop();
} }
@ -308,9 +319,9 @@ void Menu::handleKeyPress(int key) {
} else if (newSelected >= _actions.size()) { } else if (newSelected >= _actions.size()) {
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; _mouseSelection = false;
setSelected(newSelected); 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) { int Menu::itemTop(int index) {
if (index > _actions.size()) { if (index > _actions.size()) {
index = _actions.size(); index = _actions.size();

View File

@ -38,6 +38,7 @@ public:
QAction *addAction(const QString &text, base::lambda<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addAction(const QString &text, base::lambda<void()> callback, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
QAction *addSeparator(); QAction *addSeparator();
void clearActions(); void clearActions();
void finishAnimations();
void clearSelection(); void clearSelection();
@ -106,6 +107,7 @@ private:
QAction *addAction(QAction *a, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr); QAction *addAction(QAction *a, const style::icon *icon = nullptr, const style::icon *iconOver = nullptr);
void setSelected(int selected); void setSelected(int selected);
void setPressed(int pressed);
void clearMouseSelection(); void clearMouseSelection();
int itemTop(int index); int itemTop(int index);

View File

@ -32,11 +32,11 @@ namespace Window {
namespace Theme { namespace Theme {
namespace { namespace {
constexpr int kThemeFileSizeLimit = 5 * 1024 * 1024; constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024;
constexpr int kThemeBackgroundSizeLimit = 4 * 1024 * 1024; constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024;
constexpr int kThemeSchemeSizeLimit = 1024 * 1024; constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
constexpr auto kMinimumTiledSize = 512;
constexpr int kMinimumTiledSize = 512; constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme");
struct Data { struct Data {
struct Applying { struct Applying {
@ -393,8 +393,15 @@ void ChatBackground::start() {
} }
void ChatBackground::setImage(int32 id, QImage &&image) { void ChatBackground::setImage(int32 id, QImage &&image) {
auto resetPalette = (id == kDefaultBackground && _id != kDefaultBackground && !Local::hasTheme());
if (id == kThemeBackground && _themeImage.isNull()) { if (id == kThemeBackground && _themeImage.isNull()) {
id = kDefaultBackground; 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; _id = id;
if (_id == kThemeBackground) { if (_id == kThemeBackground) {
@ -425,6 +432,10 @@ void ChatBackground::setImage(int32 id, QImage &&image) {
} }
t_assert(!_pixmap.isNull() && !_pixmapForTiled.isNull()); t_assert(!_pixmap.isNull() && !_pixmapForTiled.isNull());
notify(BackgroundUpdate(BackgroundUpdate::Type::New, _tile)); 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) { void ChatBackground::setPreparedImage(QImage &&image) {
@ -432,11 +443,11 @@ void ChatBackground::setPreparedImage(QImage &&image) {
image.setDevicePixelRatio(cRetinaFactor()); image.setDevicePixelRatio(cRetinaFactor());
auto adjustColors = [this] { auto adjustColors = [this] {
auto someCustomThemeApplied = [] { auto someThemeApplied = [] {
if (AreTestingTheme()) { if (AreTestingTheme()) {
return !instance->applying.path.isEmpty(); return !instance->applying.path.isEmpty();
} }
return Local::hasTheme(); return IsNonDefaultUsed() || IsNightTheme();
}; };
auto usingThemeBackground = [this] { auto usingThemeBackground = [this] {
return (_id == kThemeBackground || _id == internal::kTestingThemeBackground); return (_id == kThemeBackground || _id == internal::kTestingThemeBackground);
@ -451,7 +462,7 @@ void ChatBackground::setPreparedImage(QImage &&image) {
return !Local::themePaletteAbsolutePath().isEmpty(); return !Local::themePaletteAbsolutePath().isEmpty();
}; };
if (someCustomThemeApplied()) { if (someThemeApplied()) {
return !usingThemeBackground() && !testingPalette(); return !usingThemeBackground() && !testingPalette();
} }
return !usingDefaultBackground(); return !usingDefaultBackground();
@ -660,6 +671,27 @@ bool Apply(const QString &filepath) {
return Apply(std::move(preview)); return Apply(std::move(preview));
} }
void SwitchNightTheme(bool enabled) {
if (enabled) {
auto preview = std::make_unique<Preview>();
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> preview) { bool Apply(std::unique_ptr<Preview> preview) {
instance.createIfNull(); instance.createIfNull();
instance->applying.path = std::move(preview->path); instance->applying.path = std::move(preview->path);
@ -724,6 +756,14 @@ void Revert() {
Background()->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) { bool LoadFromFile(const QString &path, Instance *out, QByteArray *outContent) {
*outContent = readThemeContent(path); *outContent = readThemeContent(path);
if (outContent->size() < 4) { if (outContent->size() < 4) {

View File

@ -65,6 +65,9 @@ bool Apply(std::unique_ptr<Preview> preview);
void ApplyDefault(); void ApplyDefault();
bool ApplyEditedPalette(const QString &path, const QByteArray &content); bool ApplyEditedPalette(const QString &path, const QByteArray &content);
void KeepApplied(); void KeepApplied();
bool IsNonDefaultUsed();
bool IsNightTheme();
void SwitchNightTheme(bool enabled);
void Revert(); void Revert();
bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent); bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent);

View File

@ -524,7 +524,7 @@ void Generator::paintDialogs() {
auto filterLeft = _dialogs.x() + st::dialogsFilterPadding.x() + st::dialogsMenuToggle.width + st::dialogsFilterPadding.x(); auto filterLeft = _dialogs.x() + st::dialogsFilterPadding.x() + st::dialogsMenuToggle.width + st::dialogsFilterPadding.x();
auto filterRight = st::dialogsFilterSkip + 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 filterAreaHeight = st::dialogsFilterPadding.y() + st::dialogsMenuToggle.height + st::dialogsFilterPadding.y();
auto filterTop = _dialogs.y() + (filterAreaHeight - st::dialogsFilter.height) / 2; auto filterTop = _dialogs.y() + (filterAreaHeight - st::dialogsFilter.height) / 2;
auto filter = QRect(filterLeft, filterTop, filterWidth, st::dialogsFilter.height); auto filter = QRect(filterLeft, filterTop, filterWidth, st::dialogsFilter.height);

View File

@ -118,6 +118,13 @@ mainMenu: Menu(defaultMenu) {
itemFont: semiboldFont; itemFont: semiboldFont;
itemIconPosition: point(28px, 10px); itemIconPosition: point(28px, 10px);
itemPadding: margins(76px, 13px, 28px, 13px); itemPadding: margins(76px, 13px, 28px, 13px);
itemToggle: Toggle(defaultMenuToggle) {
toggledFg: mainMenuCoverBg;
}
itemToggleOver: Toggle(defaultMenuToggleOver) {
toggledFg: mainMenuCoverBg;
}
itemToggleShift: 11px;
} }
mainMenuNewGroup: icon {{ "menu_new_group", menuIconFg }}; mainMenuNewGroup: icon {{ "menu_new_group", menuIconFg }};
mainMenuNewGroupOver: icon {{ "menu_new_group", menuIconFgOver }}; mainMenuNewGroupOver: icon {{ "menu_new_group", menuIconFgOver }};
@ -129,8 +136,8 @@ mainMenuCalls: icon {{ "menu_calls", menuIconFg }};
mainMenuCallsOver: icon {{ "menu_calls", menuIconFgOver }}; mainMenuCallsOver: icon {{ "menu_calls", menuIconFgOver }};
mainMenuSettings: icon {{ "menu_settings", menuIconFg }}; mainMenuSettings: icon {{ "menu_settings", menuIconFg }};
mainMenuSettingsOver: icon {{ "menu_settings", menuIconFgOver }}; mainMenuSettingsOver: icon {{ "menu_settings", menuIconFgOver }};
mainMenuHelp: icon {{ "menu_help", menuIconFg }}; mainMenuNightMode: icon {{ "menu_night_mode", menuIconFg }};
mainMenuHelpOver: icon {{ "menu_help", menuIconFgOver }}; mainMenuNightModeOver: icon {{ "menu_night_mode", menuIconFgOver }};
mainMenuFooterLeft: 30px; mainMenuFooterLeft: 30px;
mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) { mainMenuTelegramLabel: FlatLabel(defaultFlatLabel) {
align: align(left); align: align(left);

View File

@ -23,10 +23,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_window.h" #include "styles/style_window.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "profile/profile_userpic_button.h" #include "profile/profile_userpic_button.h"
#include "window/themes/window_theme.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/menu.h" #include "ui/widgets/menu.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "storage/localstorage.h"
#include "boxes/contacts_box.h" #include "boxes/contacts_box.h"
#include "boxes/about_box.h" #include "boxes/about_box.h"
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
@ -50,6 +52,14 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent)
}); });
checkSelf(); checkSelf();
_nightThemeSwitch.setCallback([this] {
if (auto action = *_nightThemeAction) {
if (action->isChecked() != Window::Theme::IsNightTheme()) {
Window::Theme::SwitchNightTheme(action->isChecked());
}
}
});
resize(st::mainMenuWidth, parentWidget()->height()); resize(st::mainMenuWidth, parentWidget()->height());
_menu->setTriggeredCallback([](QAction *action, int actionTop, Ui::Menu::TriggeredSource source) { _menu->setTriggeredCallback([](QAction *action, int actionTop, Ui::Menu::TriggeredSource source) {
emit action->triggered(); emit action->triggered();
@ -70,6 +80,11 @@ MainMenu::MainMenu(QWidget *parent) : TWidget(parent)
} }
})); }));
subscribe(Global::RefPhoneCallsEnabledChanged(), [this] { refreshMenu(); }); 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(); updatePhone();
} }
@ -94,9 +109,20 @@ void MainMenu::refreshMenu() {
_menu->addAction(lang(lng_menu_settings), [] { _menu->addAction(lang(lng_menu_settings), [] {
App::wnd()->showSettings(); App::wnd()->showSettings();
}, &st::mainMenuSettings, &st::mainMenuSettingsOver); }, &st::mainMenuSettings, &st::mainMenuSettingsOver);
_menu->addAction(lang(lng_settings_faq), [] {
QDesktopServices::openUrl(telegramFaqLink()); if (!Window::Theme::IsNonDefaultUsed()) {
}, &st::mainMenuHelp, &st::mainMenuHelpOver); _nightThemeAction = std::make_shared<QPointer<QAction>>(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(); updatePhone();
} }
@ -133,6 +159,7 @@ void MainMenu::showFinished() {
} }
void MainMenu::resizeEvent(QResizeEvent *e) { void MainMenu::resizeEvent(QResizeEvent *e) {
_menu->setForceWidth(width());
updateControlsGeometry(); updateControlsGeometry();
} }
@ -143,7 +170,7 @@ void MainMenu::updateControlsGeometry() {
if (_cloudButton) { if (_cloudButton) {
_cloudButton->moveToRight(0, st::mainMenuCoverHeight - _cloudButton->height()); _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()); _telegram->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuTelegramBottom - _telegram->height());
_version->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuVersionBottom - _version->height()); _version->moveToLeft(st::mainMenuFooterLeft, height() - st::mainMenuVersionBottom - _version->height());
} }

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "base/timer.h"
namespace Ui { namespace Ui {
class IconButton; class IconButton;
class FlatLabel; class FlatLabel;
@ -56,6 +58,8 @@ private:
object_ptr<Ui::Menu> _menu; object_ptr<Ui::Menu> _menu;
object_ptr<Ui::FlatLabel> _telegram; object_ptr<Ui::FlatLabel> _telegram;
object_ptr<Ui::FlatLabel> _version; object_ptr<Ui::FlatLabel> _version;
std::shared_ptr<QPointer<QAction>> _nightThemeAction;
base::Timer _nightThemeSwitch;
bool _showFinished = false; bool _showFinished = false;
QString _phoneText; QString _phoneText;