diff --git a/Telegram/Resources/day-blue.tdesktop-theme b/Telegram/Resources/day-blue.tdesktop-theme
new file mode 100644
index 000000000..ae703848a
Binary files /dev/null and b/Telegram/Resources/day-blue.tdesktop-theme differ
diff --git a/Telegram/Resources/night-green.tdesktop-theme b/Telegram/Resources/night-green.tdesktop-theme
new file mode 100644
index 000000000..3b25f9d55
Binary files /dev/null and b/Telegram/Resources/night-green.tdesktop-theme differ
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();
}
}
});