From 9b85dd27cad7ccbbaf6050ed5e71eb512e4c1101 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 26 Sep 2018 14:28:16 +0300 Subject: [PATCH] Allow to choose one of four default themes. --- Telegram/Resources/day-blue.tdesktop-theme | Bin 0 -> 10722 bytes Telegram/Resources/night-green.tdesktop-theme | Bin 0 -> 8877 bytes Telegram/Resources/qrc/telegram.qrc | 2 + .../admin_log/history_admin_log_filter.cpp | 2 +- .../info/profile/info_profile_button.cpp | 4 +- Telegram/SourceFiles/settings/settings.style | 23 ++ .../SourceFiles/settings/settings_chat.cpp | 283 +++++++++++++++++- Telegram/SourceFiles/settings/settings_chat.h | 1 + .../SourceFiles/settings/settings_intro.cpp | 3 +- Telegram/SourceFiles/ui/widgets/checkbox.cpp | 85 ++++-- Telegram/SourceFiles/ui/widgets/checkbox.h | 9 +- Telegram/SourceFiles/ui/widgets/menu.cpp | 2 +- Telegram/SourceFiles/ui/widgets/widgets.style | 1 + Telegram/SourceFiles/ui/wrap/padding_wrap.h | 2 +- .../window/themes/window_theme.cpp | 104 ++++--- .../SourceFiles/window/themes/window_theme.h | 8 +- .../SourceFiles/window/window_main_menu.cpp | 1 + 17 files changed, 452 insertions(+), 78 deletions(-) create mode 100644 Telegram/Resources/day-blue.tdesktop-theme create mode 100644 Telegram/Resources/night-green.tdesktop-theme diff --git a/Telegram/Resources/day-blue.tdesktop-theme b/Telegram/Resources/day-blue.tdesktop-theme new file mode 100644 index 0000000000000000000000000000000000000000..ae703848a57df1cbbccfb3292951582efd0d993f GIT binary patch literal 10722 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 R&kL~s((k`hj{1MP{{=f?m%9J} literal 0 HcmV?d00001 diff --git a/Telegram/Resources/night-green.tdesktop-theme b/Telegram/Resources/night-green.tdesktop-theme new file mode 100644 index 0000000000000000000000000000000000000000..3b25f9d55eb6df084a70c66a554d4c9a7a21f62c GIT binary patch literal 8877 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 J0x18p`#%7A6^sA? literal 0 HcmV?d00001 diff --git a/Telegram/Resources/qrc/telegram.qrc b/Telegram/Resources/qrc/telegram.qrc index 91cbeee5c..5d4433627 100644 --- a/Telegram/Resources/qrc/telegram.qrc +++ b/Telegram/Resources/qrc/telegram.qrc @@ -50,7 +50,9 @@ ../art/logo_256.png ../art/logo_256_no_margin.png ../art/sunrise.jpg + ../day-blue.tdesktop-theme ../night.tdesktop-theme + ../night-green.tdesktop-theme ../sounds/msg_incoming.mp3 diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp index ae7cb41e6..61c66654e 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp @@ -75,7 +75,7 @@ UserCheckbox::UserCheckbox(QWidget *parent, not_null user, bool check void UserCheckbox::setChecked(bool checked, NotifyAboutChange notify) { if (_check->checked() != checked) { - _check->setCheckedAnimated(checked); + _check->setChecked(checked, anim::type::normal); if (notify == NotifyAboutChange::Notify) { checkedChanged.notify(checked, true); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_button.cpp b/Telegram/SourceFiles/info/profile/info_profile_button.cpp index e1b10caf0..1a924d323 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_button.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_button.cpp @@ -40,12 +40,12 @@ Button *Button::toggleOn(rpl::producer &&toggled) { false, [this] { rtlupdate(toggleRect()); }); addClickHandler([this] { - _toggle->setCheckedAnimated(!_toggle->checked()); + _toggle->setChecked(!_toggle->checked(), anim::type::normal); }); std::move( toggled ) | rpl::start_with_next([this](bool toggled) { - _toggle->setCheckedAnimated(toggled); + _toggle->setChecked(toggled, anim::type::normal); }, lifetime()); _toggle->finishAnimating(); return this; diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 05a93207a..75338efdb 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -152,3 +152,26 @@ settingsBioCountdown: FlatLabel(defaultFlatLabel) { settingsBioLabelPadding: margins(22px, 11px, 22px, 0px); settingsPrivacyEditLabelPadding: margins(22px, 11px, 22px, 11px); + +settingsTheme: Checkbox(defaultCheckbox) { + textFg: windowSubTextFg; + textFgActive: windowActiveTextFg; + + width: 80px; + margin: margins(0px, 0px, 0px, 0px); + + textPosition: point(0px, 88px); + checkPosition: point(0px, 0px); + + style: defaultTextStyle; + + disabledOpacity: 0.5; +} + +settingsThemePreviewSize: size(80px, 80px); +settingsThemeBubbleSize: size(40px, 14px); +settingsThemeBubbleRadius: 2px; +settingsThemeBubblePosition: point(6px, 8px); +settingsThemeBubbleSkip: 4px; +settingsThemeRadioBottom: 8px; +settingsThemeMinSkip: 4px; diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp index 2f9a524a4..2adfbc421 100644 --- a/Telegram/SourceFiles/settings/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/settings_chat.cpp @@ -59,6 +59,44 @@ private: }; +class DefaultTheme final : public Ui::AbstractCheckView { +public: + enum class Type { + DayBlue, + Default, + Night, + NightGreen, + }; + struct Scheme { + Type type = Type(); + QColor background; + QColor sent; + QColor received; + QColor radiobuttonInactive; + QColor radiobuttonActive; + QString name; + QString path; + }; + DefaultTheme(Scheme scheme, bool checked); + + QSize getSize() const override; + void paint( + Painter &p, + int left, + int top, + int outerWidth, + TimeMs ms) override; + QImage prepareRippleMask() const override; + bool checkRippleStartPosition(QPoint position) const override; + +private: + void checkedChangedHook(anim::type animated) override; + + Scheme _scheme; + Ui::RadioView _radio; + +}; + void ChooseFromFile(not_null parent); BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent) @@ -252,6 +290,66 @@ void BackgroundRow::updateImage() { } } +DefaultTheme::DefaultTheme(Scheme scheme, bool checked) +: AbstractCheckView(st::defaultRadio.duration, checked, nullptr) +, _scheme(scheme) +, _radio(st::defaultRadio, checked, [=] { update(); }) { + _radio.setToggledOverride(_scheme.radiobuttonActive); + _radio.setUntoggledOverride(_scheme.radiobuttonInactive); +} + +QSize DefaultTheme::getSize() const { + return st::settingsThemePreviewSize; +} + +void DefaultTheme::paint( + Painter &p, + int left, + int top, + int outerWidth, + TimeMs ms) { + const auto received = QRect( + st::settingsThemeBubblePosition, + st::settingsThemeBubbleSize); + const auto sent = QRect( + outerWidth - received.width() - st::settingsThemeBubblePosition.x(), + received.y() + received.height() + st::settingsThemeBubbleSkip, + received.width(), + received.height()); + const auto radius = st::settingsThemeBubbleRadius; + + p.fillRect( + QRect(QPoint(), st::settingsThemePreviewSize), + _scheme.background); + + PainterHighQualityEnabler hq(p); + p.setPen(Qt::NoPen); + p.setBrush(_scheme.received); + p.drawRoundedRect(rtlrect(received, outerWidth), radius, radius); + p.setBrush(_scheme.sent); + p.drawRoundedRect(rtlrect(sent, outerWidth), radius, radius); + + const auto radio = _radio.getSize(); + _radio.paint( + p, + (outerWidth - radio.width()) / 2, + getSize().height() - radio.height() - st::settingsThemeRadioBottom, + outerWidth, + getms()); +} + +QImage DefaultTheme::prepareRippleMask() const { + return QImage(); +} + +bool DefaultTheme::checkRippleStartPosition(QPoint position) const { + return false; +} + +void DefaultTheme::checkedChangedHook(anim::type animated) { + _radio.setChecked(checked(), animated); +} + void ChooseFromFile(not_null parent) { const auto imgExtensions = cImgExtensions(); auto filters = QStringList( @@ -623,6 +721,7 @@ void SetupNightMode(not_null container) { const auto change = [=] { if (!--*calling && toggled != Window::Theme::IsNightMode()) { Window::Theme::ToggleNightMode(); + Window::Theme::KeepApplied(); } }; App::CallDelayed( @@ -655,13 +754,193 @@ void SetupUseDefaultTheme(not_null container) { }); } +void SetupDefaultThemes(not_null container) { + using Type = DefaultTheme::Type; + using Scheme = DefaultTheme::Scheme; + const auto block = container->add(object_ptr( + container)); + const auto scheme = DefaultTheme::Scheme(); + const auto color = [](str_const hex) { + Expects(hex.size() == 6); + + const auto component = [](char a, char b) { + const auto convert = [](char ch) { + Expects((ch >= '0' && ch <= '9') + || (ch >= 'A' && ch <= 'F') + || (ch >= 'a' && ch <= 'f')); + + return (ch >= '0' && ch <= '9') + ? int(ch - '0') + : int(ch - ((ch >= 'A' && ch <= 'F') ? 'A' : 'a') + 10); + }; + return convert(a) * 16 + convert(b); + }; + + return QColor( + component(hex[0], hex[1]), + component(hex[2], hex[3]), + component(hex[4], hex[5])); + }; + static const auto schemes = { + Scheme{ + Type::DayBlue, + color("7ec4ea"), + color("d7f0ff"), + color("ffffff"), + color("d7f0ff"), + color("ffffff"), + "Blue", + ":/gui/day-blue.tdesktop-theme" + }, + Scheme{ + Type::Default, + color("90ce89"), + color("eaffdc"), + color("ffffff"), + color("eaffdc"), + color("ffffff"), + "Classic", + QString() + }, + Scheme{ + Type::Night, + color("485761"), + color("5ca7d4"), + color("6b808d"), + color("6b808d"), + color("5ca7d4"), + "Night #1", + ":/gui/night.tdesktop-theme" + }, + Scheme{ + Type::NightGreen, + color("485761"), + color("74bf93"), + color("6b808d"), + color("6b808d"), + color("74bf93"), + "Night #2", + ":/gui/night-green.tdesktop-theme" + }, + }; + const auto chosen = [&] { + if (Window::Theme::IsNonDefaultBackground()) { + return Type(-1); + } + const auto path = Window::Theme::Background()->themeAbsolutePath(); + for (const auto scheme : schemes) { + if (path == scheme.path) { + return scheme.type; + } + } + return Type(-1); + }; + const auto group = std::make_shared>(chosen()); + auto buttons = ranges::view::all( + schemes + ) | ranges::view::transform([&](const Scheme &scheme) { + auto check = std::make_unique(scheme, false); + const auto weak = check.get(); + const auto result = Ui::CreateChild>( + block, + group, + scheme.type, + scheme.name, + st::settingsTheme, + std::move(check)); + weak->setUpdateCallback([=] { result->update(); }); + return result; + }) | ranges::to_vector; + + using Update = const Window::Theme::BackgroundUpdate; + const auto apply = [=](const Scheme &scheme) { + const auto isNight = [](const Scheme &scheme) { + const auto type = scheme.type; + return (type != Type::DayBlue) && (type != Type::Default); + }; + const auto currentlyIsCustom = (chosen() == Type(-1)); + if (Window::Theme::IsNightMode() == isNight(scheme)) { + Window::Theme::ApplyDefaultWithPath(scheme.path); + } else { + Window::Theme::ToggleNightMode(scheme.path); + } + if (!currentlyIsCustom) { + Window::Theme::KeepApplied(); + } + }; + group->setChangedCallback([=](Type type) { + const auto i = ranges::find_if(schemes, [&](const Scheme &scheme) { + return (type == scheme.type && type != chosen()); + }); + if (i != end(schemes)) { + apply(*i); + } + }); + base::ObservableViewer( + *Window::Theme::Background() + ) | rpl::filter([](const Update &update) { + return (update.type == Update::Type::ApplyingTheme + || update.type == Update::Type::New); + }) | rpl::map([=] { + return chosen(); + }) | rpl::start_with_next([=](Type type) { + group->setValue(type); + }, container->lifetime()); + + for (const auto button : buttons) { + button->setCheckAlignment(style::al_top); + button->resizeToWidth(button->width()); + } + block->resize(block->width(), buttons[0]->height()); + block->widthValue( + ) | rpl::start_with_next([buttons = std::move(buttons)](int width) { + Expects(!buttons.empty()); + + // |------| |---------| |-------| |-------| + // pad | blue | skip | classic | 3*skip | night | skip | night | pad + // |------| |---------| |-------| |-------| + const auto padding = st::settingsButton.padding; + width -= padding.left() + padding.right(); + const auto desired = st::settingsThemePreviewSize.width(); + const auto count = int(buttons.size()); + const auto smallSkips = (count / 2); + const auto bigSkips = ((count - 1) / 2); + const auto skipRatio = 3; + const auto skipSegments = smallSkips + bigSkips * skipRatio; + const auto minSkip = st::settingsThemeMinSkip; + const auto single = [&] { + if (width >= skipSegments * minSkip + count * desired) { + return desired; + } + return (width - skipSegments * minSkip) / count; + }(); + if (single <= 0) { + return; + } + const auto fullSkips = width - count * single; + const auto segment = fullSkips / float64(skipSegments); + const auto smallSkip = segment; + const auto bigSkip = segment * skipRatio; + auto left = padding.left() + 0.; + auto index = 0; + for (const auto button : buttons) { + button->resizeToWidth(single); + button->moveToLeft(int(std::round(left)), 0); + left += button->width() + ((index++ % 2) ? bigSkip : smallSkip); + } + }, block->lifetime()); + + AddSkip(container); +} + void SetupThemeOptions(not_null container) { AddDivider(container); AddSkip(container); AddSubsectionTitle(container, lng_settings_themes); - SetupNightMode(container); + SetupDefaultThemes(container); + //SetupNightMode(container); AddButton( container, @@ -672,7 +951,7 @@ void SetupThemeOptions(not_null container) { container, [] { Window::Theme::Editor::Start(); })); - SetupUseDefaultTheme(container); + //SetupUseDefaultTheme(container); AddSkip(container); } diff --git a/Telegram/SourceFiles/settings/settings_chat.h b/Telegram/SourceFiles/settings/settings_chat.h index b09330c3f..a3fcb3986 100644 --- a/Telegram/SourceFiles/settings/settings_chat.h +++ b/Telegram/SourceFiles/settings/settings_chat.h @@ -14,6 +14,7 @@ namespace Settings { void SetupDataStorage(not_null container); void SetupNightMode(not_null container); void SetupUseDefaultTheme(not_null container); +void SetupDefaultThemes(not_null container); class Chat : public Section { public: diff --git a/Telegram/SourceFiles/settings/settings_intro.cpp b/Telegram/SourceFiles/settings/settings_intro.cpp index 0e31088dd..3ea3b2449 100644 --- a/Telegram/SourceFiles/settings/settings_intro.cpp +++ b/Telegram/SourceFiles/settings/settings_intro.cpp @@ -79,8 +79,7 @@ object_ptr CreateIntroSettings(QWidget *parent) { AddDivider(result); AddSkip(result); SetupInterfaceScale(result, false); - SetupNightMode(result); - SetupUseDefaultTheme(result); + SetupDefaultThemes(result); AddSkip(result); if (anim::Disabled()) { diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.cpp b/Telegram/SourceFiles/ui/widgets/checkbox.cpp index ad0c84d15..405c323ca 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.cpp +++ b/Telegram/SourceFiles/ui/widgets/checkbox.cpp @@ -28,14 +28,23 @@ AbstractCheckView::AbstractCheckView(int duration, bool checked, Fn upda , _updateCallback(std::move(updateCallback)) { } -void AbstractCheckView::setCheckedFast(bool checked) { - const auto fire = (_checked != checked); +void AbstractCheckView::setChecked(bool checked, anim::type animated) { + const auto changed = (_checked != checked); _checked = checked; - finishAnimating(); - if (_updateCallback) { - _updateCallback(); + if (animated == anim::type::instant) { + finishAnimating(); + if (_updateCallback) { + _updateCallback(); + } + } else if (changed) { + _toggleAnimation.start( + _updateCallback, + _checked ? 0. : 1., + _checked ? 1. : 0., + _duration); } - if (fire) { + if (changed) { + checkedChangedHook(animated); _checks.fire_copy(_checked); } } @@ -53,14 +62,6 @@ void AbstractCheckView::update() { } } -void AbstractCheckView::setCheckedAnimated(bool checked) { - if (_checked != checked) { - _checked = checked; - _toggleAnimation.start(_updateCallback, _checked ? 0. : 1., _checked ? 1. : 0., _duration); - _checks.fire_copy(_checked); - } -} - void AbstractCheckView::finishAnimating() { _toggleAnimation.finish(); } @@ -69,6 +70,10 @@ float64 AbstractCheckView::currentAnimationValue(TimeMs ms) { return ms ? _toggleAnimation.current(ms, _checked ? 1. : 0.) : _toggleAnimation.current(_checked ? 1. : 0.); } +bool AbstractCheckView::animating() const { + return _toggleAnimation.animating(); +} + ToggleView::ToggleView( const style::Toggle &st, bool checked, @@ -283,9 +288,13 @@ void RadioView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) PainterHighQualityEnabler hq(p); auto toggled = currentAnimationValue(ms); - auto pen = _untoggledOverride - ? anim::pen(*_untoggledOverride, _st->toggledFg, toggled) - : anim::pen(_st->untoggledFg, _st->toggledFg, toggled); + auto pen = _toggledOverride + ? (_untoggledOverride + ? anim::pen(*_untoggledOverride, *_toggledOverride, toggled) + : anim::pen(_st->untoggledFg, *_toggledOverride, toggled)) + : (_untoggledOverride + ? anim::pen(*_untoggledOverride, _st->toggledFg, toggled) + : anim::pen(_st->untoggledFg, _st->toggledFg, toggled)); pen.setWidth(_st->thickness); p.setPen(pen); p.setBrush(_st->bg); @@ -295,9 +304,13 @@ void RadioView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) if (toggled > 0) { p.setPen(Qt::NoPen); - p.setBrush(_untoggledOverride - ? anim::brush(*_untoggledOverride, _st->toggledFg, toggled) - : anim::brush(_st->untoggledFg, _st->toggledFg, toggled)); + p.setBrush(_toggledOverride + ? (_untoggledOverride + ? anim::brush(*_untoggledOverride, *_toggledOverride, toggled) + : anim::brush(_st->untoggledFg, *_toggledOverride, toggled)) + : (_untoggledOverride + ? anim::brush(*_untoggledOverride, _st->toggledFg, toggled) + : anim::brush(_st->untoggledFg, _st->toggledFg, toggled))); auto skip0 = _st->diameter / 2., skip1 = _st->skip / 10., checkSkip = skip0 * (1. - toggled) + skip1 * toggled; p.drawEllipse(rtlrect(QRectF(left, top, _st->diameter, _st->diameter).marginsRemoved(QMarginsF(checkSkip, checkSkip, checkSkip, checkSkip)), outerWidth)); @@ -327,6 +340,11 @@ bool RadioView::checkRippleStartPosition(QPoint position) const { return QRect(QPoint(0, 0), rippleSize()).contains(position); } +void RadioView::setToggledOverride(std::optional toggledOverride) { + _toggledOverride = toggledOverride; + update(); +} + void RadioView::setUntoggledOverride( std::optional untoggledOverride) { _untoggledOverride = untoggledOverride; @@ -420,7 +438,7 @@ void Checkbox::resizeToText() { void Checkbox::setChecked(bool checked, NotifyAboutChange notify) { if (_check->checked() != checked) { - _check->setCheckedAnimated(checked); + _check->setChecked(checked, anim::type::normal); if (notify == NotifyAboutChange::Notify) { checkedChanged.notify(checked, true); } @@ -447,10 +465,10 @@ void Checkbox::paintEvent(QPaintEvent *e) { auto check = checkRect(); auto ms = getms(); + auto active = _check->currentAnimationValue(ms); if (isDisabled()) { p.setOpacity(_st.disabledOpacity); } else { - auto active = _check->currentAnimationValue(ms); auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active); paintRipple( p, @@ -476,8 +494,7 @@ void Checkbox::paintEvent(QPaintEvent *e) { auto availableTextWidth = qMax(width() - leftSkip, 1); if (!_text.isEmpty()) { - Assert(!(_checkAlignment & Qt::AlignHCenter)); - p.setPen(_st.textFg); + p.setPen(anim::pen(_st.textFg, _st.textFgActive, active)); auto textSkip = _st.checkPosition.x() + check.width() + _st.textPosition.x(); @@ -489,13 +506,21 @@ void Checkbox::paintEvent(QPaintEvent *e) { textTop, availableTextWidth, width()); - } else { + } else if (_checkAlignment & Qt::AlignRight) { _text.drawRightElided( p, textSkip, textTop, availableTextWidth, width()); + } else { + _text.drawLeft( + p, + _st.margin.left(), + textTop, + width() - _st.margin.left() - _st.margin.right(), + width(), + style::al_top); } } } @@ -537,7 +562,15 @@ void Checkbox::handlePress() { } int Checkbox::resizeGetHeight(int newWidth) { - return _check->getSize().height(); + const auto result = _check->getSize().height(); + if (!(_checkAlignment & Qt::AlignHCenter)) { + return result; + } + const auto textBottom = _st.margin.top() + + _st.textPosition.y() + + _text.countHeight( + newWidth - _st.margin.left() - _st.margin.right()); + return std::max(result, textBottom); } QImage Checkbox::prepareRippleMask() const { diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.h b/Telegram/SourceFiles/ui/widgets/checkbox.h index 5a00d6cb3..32a1d8379 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.h +++ b/Telegram/SourceFiles/ui/widgets/checkbox.h @@ -17,8 +17,7 @@ class AbstractCheckView { public: AbstractCheckView(int duration, bool checked, Fn updateCallback); - void setCheckedFast(bool checked); - void setCheckedAnimated(bool checked); + void setChecked(bool checked, anim::type animated); void finishAnimating(); void setUpdateCallback(Fn updateCallback); bool checked() const { @@ -26,6 +25,7 @@ public: } void update(); float64 currentAnimationValue(TimeMs ms); + bool animating() const; auto checkedValue() const { return _checks.events_starting_with(checked()); @@ -47,6 +47,9 @@ public: virtual ~AbstractCheckView() = default; private: + virtual void checkedChangedHook(anim::type animated) { + } + int _duration = 0; bool _checked = false; Fn _updateCallback; @@ -90,6 +93,7 @@ public: void setStyle(const style::Radio &st); + void setToggledOverride(std::optional toggledOverride); void setUntoggledOverride(std::optional untoggledOverride); QSize getSize() const override; @@ -101,6 +105,7 @@ private: QSize rippleSize() const; not_null _st; + std::optional _toggledOverride; std::optional _untoggledOverride; }; diff --git a/Telegram/SourceFiles/ui/widgets/menu.cpp b/Telegram/SourceFiles/ui/widgets/menu.cpp index c0897fb15..ee16b4dea 100644 --- a/Telegram/SourceFiles/ui/widgets/menu.cpp +++ b/Telegram/SourceFiles/ui/widgets/menu.cpp @@ -132,7 +132,7 @@ int Menu::processAction(QAction *action, int index, int width) { auto updateCallback = [this, index] { updateItem(index); }; if (data.toggle) { data.toggle->setUpdateCallback(updateCallback); - data.toggle->setCheckedAnimated(action->isChecked()); + data.toggle->setChecked(action->isChecked(), anim::type::normal); } else { data.toggle = std::make_unique(_st.itemToggle, action->isChecked(), updateCallback); } diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index 3c0b09756..dfad6417f 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -142,6 +142,7 @@ Radio { Checkbox { textFg: color; + textFgActive: color; width: pixels; margin: margins; diff --git a/Telegram/SourceFiles/ui/wrap/padding_wrap.h b/Telegram/SourceFiles/ui/wrap/padding_wrap.h index 24bf1a888..d13d3477e 100644 --- a/Telegram/SourceFiles/ui/wrap/padding_wrap.h +++ b/Telegram/SourceFiles/ui/wrap/padding_wrap.h @@ -92,7 +92,7 @@ public: class FixedHeightWidget : public RpWidget { public: - FixedHeightWidget(QWidget *parent, int height) + explicit FixedHeightWidget(QWidget *parent, int height = 0) : RpWidget(parent) { resize(width(), height); } diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 6c4649de3..accddc511 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -33,6 +33,7 @@ struct Data { QByteArray content; QByteArray paletteForRevert; Cached cached; + Fn overrideKeep; }; ChatBackground background; @@ -336,24 +337,6 @@ void adjustColor(style::color color, float64 hue, float64 saturation) { color.set(original.red(), original.green(), original.blue(), original.alpha()); } -void ApplyDefaultWithNightMode(bool nightMode) { - if (nightMode) { - if (auto preview = PreviewFromFile(NightThemePath())) { - Apply(std::move(preview)); - } - } else { - instance.createIfNull(); - instance->applying.pathRelative = QString(); - instance->applying.pathAbsolute = QString(); - instance->applying.content = QByteArray(); - instance->applying.cached = Cached(); - if (instance->applying.paletteForRevert.isEmpty()) { - instance->applying.paletteForRevert = style::main_palette::save(); - } - Background()->setTestingDefaultTheme(); - } -} - void WriteAppliedTheme() { auto saved = Saved(); saved.pathRelative = instance->applying.pathRelative; @@ -723,6 +706,13 @@ bool ChatBackground::isNonDefaultThemeOrBackground() { || _id != kDefaultBackground); } +bool ChatBackground::isNonDefaultBackground() { + start(); + return _themeAbsolutePath.isEmpty() + ? (_id != kDefaultBackground) + : (_id != kThemeBackground); +} + void ChatBackground::writeNewBackgroundSettings() { if (tile() != _tileForRevert) { Local::writeUserSettings(); @@ -755,11 +745,12 @@ bool ChatBackground::nightMode() const { return _nightMode; } -void ChatBackground::toggleNightMode() { +void ChatBackground::toggleNightMode(std::optional themePath) { + const auto settingDefault = themePath.has_value(); const auto oldNightMode = _nightMode; const auto newNightMode = !_nightMode; _nightMode = newNightMode; - auto read = Local::readThemeAfterSwitch(); + auto read = settingDefault ? Saved() : Local::readThemeAfterSwitch(); auto path = read.pathAbsolute; _nightMode = oldNightMode; @@ -784,30 +775,34 @@ void ChatBackground::toggleNightMode() { return true; }(); if (!alreadyOnDisk) { - path = newNightMode ? NightThemePath() : QString(); - ApplyDefaultWithNightMode(newNightMode); + path = themePath + ? *themePath + : (newNightMode ? NightThemePath() : QString()); + ApplyDefaultWithPath(path); } // Theme editor could have already reverted the testing of this toggle. if (AreTestingTheme()) { - _nightMode = newNightMode; + instance->applying.overrideKeep = [=] { + _nightMode = newNightMode; - // Restore the value, it was set inside theme testing. - (oldNightMode ? _tileNightValue : _tileDayValue) = oldTileValue; + // Restore the value, it was set inside theme testing. + (oldNightMode ? _tileNightValue : _tileDayValue) = oldTileValue; - if (!alreadyOnDisk) { - // First-time switch to default night mode should write it. - WriteAppliedTheme(); - } - ClearApplying(); - keepApplied(path, false); - if (tile() != _tileForRevert) { - Local::writeUserSettings(); - } - Local::writeSettings(); - if (!Local::readBackground()) { - setImage(kThemeBackground); - } + if (!alreadyOnDisk) { + // First-time switch to default night mode should write it. + WriteAppliedTheme(); + } + ClearApplying(); + keepApplied(path, settingDefault); + if (tile() != _tileForRevert) { + Local::writeUserSettings(); + } + Local::writeSettings(); + if (!settingDefault && !Local::readBackground()) { + setImage(kThemeBackground); + } + }; } } @@ -863,7 +858,25 @@ bool Apply(std::unique_ptr preview) { } void ApplyDefault() { - ApplyDefaultWithNightMode(IsNightMode()); + ApplyDefaultWithPath(IsNightMode() ? NightThemePath() : QString()); +} + +void ApplyDefaultWithPath(const QString &themePath) { + if (!themePath.isEmpty()) { + if (auto preview = PreviewFromFile(themePath)) { + Apply(std::move(preview)); + } + } else { + instance.createIfNull(); + instance->applying.pathRelative = QString(); + instance->applying.pathAbsolute = QString(); + instance->applying.content = QByteArray(); + instance->applying.cached = Cached(); + if (instance->applying.paletteForRevert.isEmpty()) { + instance->applying.paletteForRevert = style::main_palette::save(); + } + Background()->setTestingDefaultTheme(); + } } bool ApplyEditedPalette(const QString &path, const QByteArray &content) { @@ -895,6 +908,9 @@ bool ApplyEditedPalette(const QString &path, const QByteArray &content) { void KeepApplied() { if (!AreTestingTheme()) { return; + } else if (instance->applying.overrideKeep) { + instance->applying.overrideKeep(); + return; } const auto path = instance->applying.pathAbsolute; WriteAppliedTheme(); @@ -921,6 +937,10 @@ bool IsNonDefaultThemeOrBackground() { return Background()->isNonDefaultThemeOrBackground(); } +bool IsNonDefaultBackground() { + return Background()->isNonDefaultBackground(); +} + bool IsNightMode() { return instance ? Background()->nightMode() : false; } @@ -932,7 +952,11 @@ void SetNightModeValue(bool nightMode) { } void ToggleNightMode() { - Background()->toggleNightMode(); + Background()->toggleNightMode(std::nullopt); +} + +void ToggleNightMode(const QString &path) { + Background()->toggleNightMode(path); } bool SuggestThemeReset() { diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index aad7d41d3..6ddf725ed 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -57,12 +57,15 @@ struct Preview { bool Apply(const QString &filepath); bool Apply(std::unique_ptr preview); void ApplyDefault(); +void ApplyDefaultWithPath(const QString &themePath); bool ApplyEditedPalette(const QString &path, const QByteArray &content); void KeepApplied(); QString NightThemePath(); bool IsNightMode(); void SetNightModeValue(bool nightMode); void ToggleNightMode(); +void ToggleNightMode(const QString &themePath); +bool IsNonDefaultBackground(); bool IsNonDefaultThemeOrBackground(); bool SuggestThemeReset(); void Revert(); @@ -140,14 +143,17 @@ private: void setNightModeValue(bool nightMode); bool nightMode() const; - void toggleNightMode(); + void toggleNightMode(std::optional themePath); void keepApplied(const QString &path, bool write); bool isNonDefaultThemeOrBackground(); + bool isNonDefaultBackground(); friend bool IsNightMode(); friend void SetNightModeValue(bool nightMode); friend void ToggleNightMode(); + friend void ToggleNightMode(const QString &themePath); friend void KeepApplied(); + friend bool IsNonDefaultBackground(); friend bool IsNonDefaultThemeOrBackground(); int32 _id = internal::kUninitializedBackground; diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp index 4546aa189..31e5338b4 100644 --- a/Telegram/SourceFiles/window/window_main_menu.cpp +++ b/Telegram/SourceFiles/window/window_main_menu.cpp @@ -58,6 +58,7 @@ MainMenu::MainMenu( const auto nightMode = Window::Theme::IsNightMode(); if (action->isChecked() != nightMode) { Window::Theme::ToggleNightMode(); + Window::Theme::KeepApplied(); } } });