mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-21 15:47:38 +00:00
Implement "Save Power on Low Battery" function.
This commit is contained in:
parent
388541a3fb
commit
ce0e07d332
@ -625,6 +625,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_settings_power_ui" = "Interface animations";
|
||||
"lng_settings_power_auto" = "Save Power on Low Battery";
|
||||
"lng_settings_power_auto_about" = "Automatically disable all animations when your laptop is in a battery saving mode.";
|
||||
"lng_settings_power_turn_off" = "Please turn off Save Power on Low Battery to change these settings.";
|
||||
|
||||
"lng_settings_cloud_password_on" = "On";
|
||||
"lng_settings_cloud_password_off" = "Off";
|
||||
|
@ -42,6 +42,7 @@ namespace {
|
||||
|
||||
constexpr auto kSlowmodeValues = 7;
|
||||
constexpr auto kSuggestGigagroupThreshold = 199000;
|
||||
constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
|
||||
|
||||
[[nodiscard]] auto Dependencies(PowerSaving::Flags)
|
||||
-> std::vector<std::pair<PowerSaving::Flag, PowerSaving::Flag>> {
|
||||
@ -453,8 +454,38 @@ template <typename Flags>
|
||||
struct State final {
|
||||
std::map<Flags, not_null<Ui::AbstractCheckView*>> checkViews;
|
||||
rpl::event_stream<> anyChanges;
|
||||
rpl::variable<QString> forceDisabledMessage;
|
||||
rpl::variable<bool> forceDisabled;
|
||||
base::flat_map<Flags, bool> realCheckedValues;
|
||||
base::weak_ptr<Ui::Toast::Instance> toast;
|
||||
};
|
||||
const auto state = container->lifetime().make_state<State>();
|
||||
if (descriptor.forceDisabledMessage) {
|
||||
state->forceDisabledMessage = std::move(
|
||||
descriptor.forceDisabledMessage);
|
||||
state->forceDisabled = state->forceDisabledMessage.value(
|
||||
) | rpl::map([=](const QString &message) {
|
||||
return !message.isEmpty();
|
||||
});
|
||||
|
||||
state->forceDisabled.value(
|
||||
) | rpl::start_with_next([=](bool disabled) {
|
||||
if (disabled) {
|
||||
for (const auto &[flags, checkView] : state->checkViews) {
|
||||
checkView->setChecked(false, anim::type::normal);
|
||||
}
|
||||
} else {
|
||||
for (const auto &[flags, checkView] : state->checkViews) {
|
||||
if (const auto i = state->realCheckedValues.find(flags)
|
||||
; i != state->realCheckedValues.end()) {
|
||||
checkView->setChecked(
|
||||
i->second,
|
||||
anim::type::normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, container->lifetime());
|
||||
}
|
||||
|
||||
const auto &st = descriptor.st ? *descriptor.st : st::rightsButton;
|
||||
const auto value = [=] {
|
||||
@ -492,7 +523,9 @@ template <typename Flags>
|
||||
const auto locked = (lockedIt != end(descriptor.disabledMessages))
|
||||
? std::make_optional(lockedIt->second)
|
||||
: std::nullopt;
|
||||
const auto toggled = ((checked & flags) != 0);
|
||||
const auto realChecked = (checked & flags) != 0;
|
||||
state->realCheckedValues.emplace(flags, realChecked);
|
||||
const auto toggled = realChecked && !state->forceDisabled.current();
|
||||
|
||||
const auto checkView = [&]() -> not_null<Ui::AbstractCheckView*> {
|
||||
if (isInner) {
|
||||
@ -559,15 +592,30 @@ template <typename Flags>
|
||||
state->checkViews.emplace(flags, checkView);
|
||||
checkView->checkedChanges(
|
||||
) | rpl::start_with_next([=](bool checked) {
|
||||
if (locked.has_value()) {
|
||||
if (checked != toggled) {
|
||||
Ui::ShowMultilineToast({
|
||||
if (checked && state->forceDisabled.current()) {
|
||||
if (!state->toast) {
|
||||
state->toast = Ui::ShowMultilineToast({
|
||||
.parentOverride = container,
|
||||
.text = { *locked },
|
||||
.text = { state->forceDisabledMessage.current() },
|
||||
.duration = kForceDisableTooltipDuration,
|
||||
});
|
||||
}
|
||||
checkView->setChecked(false, anim::type::instant);
|
||||
} else if (locked.has_value()) {
|
||||
if (checked != toggled) {
|
||||
if (!state->toast) {
|
||||
state->toast = Ui::ShowMultilineToast({
|
||||
.parentOverride = container,
|
||||
.text = { *locked },
|
||||
.duration = kForceDisableTooltipDuration,
|
||||
});
|
||||
}
|
||||
checkView->setChecked(toggled, anim::type::instant);
|
||||
}
|
||||
} else {
|
||||
if (!state->forceDisabled.current()) {
|
||||
state->realCheckedValues[flags] = checked;
|
||||
}
|
||||
InvokeQueued(container, [=] {
|
||||
applyDependencies(checkView);
|
||||
state->anyChanges.fire({});
|
||||
@ -1141,12 +1189,15 @@ ChatAdminRights AdminRightsForOwnershipTransfer(
|
||||
|
||||
EditFlagsControl<PowerSaving::Flags> CreateEditPowerSaving(
|
||||
QWidget *parent,
|
||||
PowerSaving::Flags flags) {
|
||||
PowerSaving::Flags flags,
|
||||
rpl::producer<QString> forceDisabledMessage) {
|
||||
auto widget = object_ptr<Ui::VerticalLayout>(parent);
|
||||
auto descriptor = Settings::PowerSavingLabels();
|
||||
descriptor.forceDisabledMessage = std::move(forceDisabledMessage);
|
||||
auto result = CreateEditFlags(
|
||||
widget.data(),
|
||||
flags,
|
||||
Settings::PowerSavingLabels());
|
||||
std::move(descriptor));
|
||||
result.widget = std::move(widget);
|
||||
|
||||
return result;
|
||||
|
@ -74,6 +74,7 @@ struct EditFlagsDescriptor {
|
||||
std::vector<NestedEditFlagsLabels<Flags>> labels;
|
||||
base::flat_map<Flags, QString> disabledMessages;
|
||||
const style::SettingsButton *st = nullptr;
|
||||
rpl::producer<QString> forceDisabledMessage;
|
||||
};
|
||||
|
||||
using RestrictionLabel = EditFlagsLabel<ChatRestrictions>;
|
||||
@ -109,5 +110,6 @@ using AdminRightLabel = EditFlagsLabel<ChatAdminRights>;
|
||||
|
||||
[[nodiscard]] auto CreateEditPowerSaving(
|
||||
QWidget *parent,
|
||||
PowerSaving::Flags flags
|
||||
PowerSaving::Flags flags,
|
||||
rpl::producer<QString> forceDisabledMessage
|
||||
) -> EditFlagsControl<PowerSaving::Flags>;
|
||||
|
@ -499,7 +499,7 @@ void TopBar::initBlobsUnder(
|
||||
|
||||
using namespace rpl::mappers;
|
||||
auto hideBlobs = rpl::combine(
|
||||
PowerSaving::Value(PowerSaving::kCalls),
|
||||
PowerSaving::OnValue(PowerSaving::kCalls),
|
||||
Core::App().appDeactivatedValue(),
|
||||
group->instanceStateValue()
|
||||
) | rpl::map(_1 || _2 || _3 == GroupCall::InstanceState::Disconnected);
|
||||
|
@ -235,7 +235,7 @@ Members::Controller::Controller(
|
||||
}, _lifetime);
|
||||
|
||||
rpl::combine(
|
||||
PowerSaving::Value(PowerSaving::kCalls),
|
||||
PowerSaving::OnValue(PowerSaving::kCalls),
|
||||
Core::App().appDeactivatedValue()
|
||||
) | rpl::start_with_next([=](bool disabled, bool deactivated) {
|
||||
const auto hide = disabled || deactivated;
|
||||
|
@ -14,10 +14,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_download_manager.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/battery_saving.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "base/concurrent_timer.h"
|
||||
#include "base/qt_signal_producer.h"
|
||||
#include "base/timer.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "core/update_checker.h"
|
||||
@ -78,6 +79,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/effects/spoiler_mess.h"
|
||||
#include "ui/cached_round_corners.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "storage/serialize_common.h"
|
||||
#include "storage/storage_domain.h"
|
||||
#include "storage/storage_databases.h"
|
||||
@ -143,6 +145,7 @@ Application::Application(not_null<Launcher*> launcher)
|
||||
, _launcher(launcher)
|
||||
, _private(std::make_unique<Private>())
|
||||
, _platformIntegration(Platform::Integration::Create())
|
||||
, _batterySaving(std::make_unique<base::BatterySaving>())
|
||||
, _databases(std::make_unique<Storage::Databases>())
|
||||
, _animationsManager(std::make_unique<Ui::Animations::Manager>())
|
||||
, _clearEmojiImageLoaderTimer([=] { clearEmojiSourceImages(); })
|
||||
@ -279,6 +282,13 @@ void Application::run() {
|
||||
_mediaControlsManager = std::make_unique<MediaControlsManager>();
|
||||
}
|
||||
|
||||
rpl::combine(
|
||||
_batterySaving->value(),
|
||||
settings().ignoreBatterySavingValue()
|
||||
) | rpl::start_with_next([=](bool saving, bool ignore) {
|
||||
PowerSaving::SetForceAll(saving && !ignore);
|
||||
}, _lifetime);
|
||||
|
||||
style::ShortAnimationPlaying(
|
||||
) | rpl::start_with_next([=](bool playing) {
|
||||
if (playing) {
|
||||
@ -409,14 +419,14 @@ void Application::showOpenGLCrashNotification() {
|
||||
const auto enable = [=] {
|
||||
Ui::GL::ForceDisable(false);
|
||||
Ui::GL::CrashCheckFinish();
|
||||
Core::App().settings().setDisableOpenGL(false);
|
||||
settings().setDisableOpenGL(false);
|
||||
Local::writeSettings();
|
||||
Restart();
|
||||
};
|
||||
const auto keepDisabled = [=] {
|
||||
Ui::GL::ForceDisable(true);
|
||||
Ui::GL::CrashCheckFinish();
|
||||
Core::App().settings().setDisableOpenGL(true);
|
||||
settings().setDisableOpenGL(true);
|
||||
Local::writeSettings();
|
||||
};
|
||||
_lastActivePrimaryWindow->show(Ui::MakeConfirmBox({
|
||||
@ -658,6 +668,10 @@ Settings &Application::settings() {
|
||||
return _private->settings;
|
||||
}
|
||||
|
||||
const Settings &Application::settings() const {
|
||||
return _private->settings;
|
||||
}
|
||||
|
||||
void Application::saveSettingsDelayed(crl::time delay) {
|
||||
if (_saveSettingsTimer) {
|
||||
_saveSettingsTimer->callOnce(delay);
|
||||
@ -670,7 +684,7 @@ void Application::saveSettings() {
|
||||
|
||||
bool Application::canReadDefaultDownloadPath(bool always) const {
|
||||
if (KSandbox::isInside()
|
||||
&& (always || Core::App().settings().downloadPath().isEmpty())) {
|
||||
&& (always || settings().downloadPath().isEmpty())) {
|
||||
const auto path = QStandardPaths::writableLocation(
|
||||
QStandardPaths::DownloadLocation);
|
||||
return base::CanReadDirectory(path);
|
||||
@ -679,7 +693,7 @@ bool Application::canReadDefaultDownloadPath(bool always) const {
|
||||
}
|
||||
|
||||
bool Application::canSaveFileWithoutAskingForPath() const {
|
||||
return !Core::App().settings().askDownloadPath();
|
||||
return !settings().askDownloadPath();
|
||||
}
|
||||
|
||||
MTP::Config &Application::fallbackProductionConfig() const {
|
||||
|
@ -13,6 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
class History;
|
||||
|
||||
namespace base {
|
||||
class BatterySaving;
|
||||
} // namespace base
|
||||
|
||||
namespace Platform {
|
||||
class Integration;
|
||||
} // namespace Platform
|
||||
@ -127,15 +131,14 @@ public:
|
||||
Application &operator=(const Application &other) = delete;
|
||||
~Application();
|
||||
|
||||
void run();
|
||||
|
||||
[[nodiscard]] Launcher &launcher() const {
|
||||
return *_launcher;
|
||||
}
|
||||
[[nodiscard]] Platform::Integration &platformIntegration() const {
|
||||
return *_platformIntegration;
|
||||
}
|
||||
|
||||
void run();
|
||||
|
||||
[[nodiscard]] Ui::Animations::Manager &animationManager() const {
|
||||
return *_animationsManager;
|
||||
}
|
||||
@ -150,6 +153,9 @@ public:
|
||||
[[nodiscard]] Tray &tray() const {
|
||||
return *_tray;
|
||||
}
|
||||
[[nodiscard]] base::BatterySaving &batterySaving() const {
|
||||
return *_batterySaving;
|
||||
}
|
||||
|
||||
// Windows interface.
|
||||
bool hasActiveWindow(not_null<Main::Session*> session) const;
|
||||
@ -191,6 +197,7 @@ public:
|
||||
|
||||
void startSettingsAndBackground();
|
||||
[[nodiscard]] Settings &settings();
|
||||
[[nodiscard]] const Settings &settings() const;
|
||||
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
|
||||
void saveSettings();
|
||||
|
||||
@ -373,6 +380,7 @@ private:
|
||||
struct Private;
|
||||
const std::unique_ptr<Private> _private;
|
||||
const std::unique_ptr<Platform::Integration> _platformIntegration;
|
||||
const std::unique_ptr<base::BatterySaving> _batterySaving;
|
||||
|
||||
const std::unique_ptr<Storage::Databases> _databases;
|
||||
const std::unique_ptr<Ui::Animations::Manager> _animationsManager;
|
||||
|
@ -197,7 +197,8 @@ QByteArray Settings::serialize() const {
|
||||
+ sizeof(qint32)
|
||||
+ sizeof(quint64)
|
||||
+ sizeof(qint32) * 3
|
||||
+ Serialize::bytearraySize(mediaViewPosition);
|
||||
+ Serialize::bytearraySize(mediaViewPosition)
|
||||
+ sizeof(qint32);
|
||||
|
||||
auto result = QByteArray();
|
||||
result.reserve(size);
|
||||
@ -329,7 +330,8 @@ QByteArray Settings::serialize() const {
|
||||
<< qint32(_windowTitleContent.current().hideChatName ? 1 : 0)
|
||||
<< qint32(_windowTitleContent.current().hideAccountName ? 1 : 0)
|
||||
<< qint32(_windowTitleContent.current().hideTotalUnread ? 1 : 0)
|
||||
<< mediaViewPosition;
|
||||
<< mediaViewPosition
|
||||
<< qint32(_ignoreBatterySaving.current() ? 1 : 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -433,6 +435,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||
qint32 hideAccountName = _windowTitleContent.current().hideAccountName ? 1 : 0;
|
||||
qint32 hideTotalUnread = _windowTitleContent.current().hideTotalUnread ? 1 : 0;
|
||||
QByteArray mediaViewPosition;
|
||||
qint32 ignoreBatterySaving = _ignoreBatterySaving.current() ? 1 : 0;
|
||||
|
||||
stream >> themesAccentColors;
|
||||
if (!stream.atEnd()) {
|
||||
@ -661,6 +664,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||
if (!stream.atEnd()) {
|
||||
stream >> mediaViewPosition;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
stream >> ignoreBatterySaving;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||
@ -857,6 +863,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||
_mediaViewPosition = { .maximized = 2 };
|
||||
}
|
||||
}
|
||||
_ignoreBatterySaving = (ignoreBatterySaving == 1);
|
||||
}
|
||||
|
||||
QString Settings::getSoundPath(const QString &key) const {
|
||||
|
@ -777,6 +777,15 @@ public:
|
||||
void setMediaViewPosition(const WindowPosition &position) {
|
||||
_mediaViewPosition = position;
|
||||
}
|
||||
[[nodiscard]] bool ignoreBatterySaving() const {
|
||||
return _ignoreBatterySaving.current();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<bool> ignoreBatterySavingValue() const {
|
||||
return _ignoreBatterySaving.value();
|
||||
}
|
||||
void setIgnoreBatterySavingValue(bool value) {
|
||||
_ignoreBatterySaving = value;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool ThirdColumnByDefault();
|
||||
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
|
||||
@ -900,6 +909,7 @@ private:
|
||||
rpl::event_stream<> _skipTranslationLanguagesChanges;
|
||||
bool _rememberedDeleteMessageOnlyForYou = false;
|
||||
WindowPosition _mediaViewPosition = { .maximized = 2 };
|
||||
rpl::variable<bool> _ignoreBatterySaving = false;
|
||||
|
||||
bool _tabbedReplacedWithInfo = false; // per-window
|
||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
||||
|
@ -7,11 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "settings/settings_power_saving.h"
|
||||
|
||||
#include "base/battery_saving.h"
|
||||
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/toasts/common_toasts.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/power_saving.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
@ -19,6 +22,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
constexpr auto kForceDisableTooltipDuration = 3 * crl::time(1000);
|
||||
|
||||
} // namespace
|
||||
|
||||
void PowerSavingBox(not_null<Ui::GenericBox*> box) {
|
||||
box->setStyle(st::layerBox);
|
||||
@ -26,40 +34,90 @@ void PowerSavingBox(not_null<Ui::GenericBox*> box) {
|
||||
box->setWidth(st::boxWideWidth);
|
||||
|
||||
const auto container = box->verticalLayout();
|
||||
const auto ignore = Core::App().settings().ignoreBatterySaving();
|
||||
const auto batterySaving = Core::App().batterySaving().enabled();
|
||||
|
||||
// Force top shadow visibility.
|
||||
box->setPinnedToTopContent(
|
||||
object_ptr<Ui::FixedHeightWidget>(box, st::lineWidth));
|
||||
|
||||
AddSubsectionTitle(
|
||||
const auto subtitle = AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_settings_power_subtitle(),
|
||||
st::powerSavingSubtitlePadding);
|
||||
|
||||
struct State {
|
||||
rpl::variable<QString> forceDisabledMessage;
|
||||
};
|
||||
const auto state = container->lifetime().make_state<State>();
|
||||
state->forceDisabledMessage = (batterySaving.value_or(false) && !ignore)
|
||||
? tr::lng_settings_power_turn_off(tr::now)
|
||||
: QString();
|
||||
|
||||
auto [checkboxes, getResult, changes] = CreateEditPowerSaving(
|
||||
box,
|
||||
PowerSaving::kAll & ~PowerSaving::Current());
|
||||
PowerSaving::kAll & ~PowerSaving::Current(),
|
||||
state->forceDisabledMessage.value());
|
||||
|
||||
const auto controlsRaw = checkboxes.data();
|
||||
box->addRow(std::move(checkboxes), {});
|
||||
|
||||
auto automatic = (Ui::SettingsButton*)nullptr;
|
||||
const auto hasBattery = true;
|
||||
const auto automaticEnabled = true;
|
||||
if (hasBattery) {
|
||||
if (batterySaving.has_value()) {
|
||||
AddSkip(container);
|
||||
AddDivider(container);
|
||||
AddSkip(container);
|
||||
AddButton(
|
||||
automatic = AddButton(
|
||||
container,
|
||||
tr::lng_settings_power_auto(),
|
||||
st::powerSavingButtonNoIcon
|
||||
)->toggleOn(rpl::single(automaticEnabled));
|
||||
)->toggleOn(rpl::single(!ignore));
|
||||
AddSkip(container);
|
||||
AddDividerText(container, tr::lng_settings_power_auto_about());
|
||||
|
||||
state->forceDisabledMessage = rpl::combine(
|
||||
automatic->toggledValue(),
|
||||
Core::App().batterySaving().value()
|
||||
) | rpl::map([=](bool dontIgnore, bool saving) {
|
||||
return (saving && dontIgnore)
|
||||
? tr::lng_settings_power_turn_off()
|
||||
: rpl::single(QString());
|
||||
}) | rpl::flatten_latest();
|
||||
|
||||
const auto disabler = Ui::CreateChild<Ui::AbstractButton>(container.get());
|
||||
disabler->setClickedCallback([=] {
|
||||
Ui::ShowMultilineToast({
|
||||
.parentOverride = container,
|
||||
.text = tr::lng_settings_power_turn_off(tr::now),
|
||||
.duration = kForceDisableTooltipDuration,
|
||||
});
|
||||
});
|
||||
disabler->paintRequest() | rpl::start_with_next([=](QRect clip) {
|
||||
auto color = st::boxBg->c;
|
||||
color.setAlpha(96);
|
||||
QPainter(disabler).fillRect(clip, color);
|
||||
}, disabler->lifetime());
|
||||
rpl::combine(
|
||||
subtitle->geometryValue(),
|
||||
controlsRaw->geometryValue()
|
||||
) | rpl::start_with_next([=](QRect subtitle, QRect controls) {
|
||||
disabler->setGeometry(subtitle.united(controls));
|
||||
}, disabler->lifetime());
|
||||
disabler->showOn(state->forceDisabledMessage.value(
|
||||
) | rpl::map([=](const QString &value) {
|
||||
return !value.isEmpty();
|
||||
}));
|
||||
}
|
||||
|
||||
box->addButton(tr::lng_settings_save(), [=, collect = getResult] {
|
||||
Set(PowerSaving::kAll & ~collect());
|
||||
const auto ignore = automatic
|
||||
? !automatic->toggled()
|
||||
: Core::App().settings().ignoreBatterySaving();
|
||||
const auto batterySaving = Core::App().batterySaving().enabled();
|
||||
if (ignore || !batterySaving.value_or(false)) {
|
||||
Set(PowerSaving::kAll & ~collect());
|
||||
}
|
||||
Core::App().settings().setIgnoreBatterySavingValue(ignore);
|
||||
Core::App().saveSettingsDelayed();
|
||||
box->closeBox();
|
||||
});
|
||||
|
@ -117,7 +117,7 @@ GroupCallUserpics::GroupCallUserpics(
|
||||
});
|
||||
|
||||
rpl::combine(
|
||||
PowerSaving::Value(PowerSaving::kCalls),
|
||||
PowerSaving::OnValue(PowerSaving::kCalls),
|
||||
std::move(hideBlobs)
|
||||
) | rpl::start_with_next([=](bool disabled, bool deactivated) {
|
||||
const auto hide = disabled || deactivated;
|
||||
|
@ -517,7 +517,7 @@ CallMuteButton::CallMuteButton(
|
||||
parent,
|
||||
_st->active.bgSize,
|
||||
rpl::combine(
|
||||
PowerSaving::Value(PowerSaving::kCalls),
|
||||
PowerSaving::OnValue(PowerSaving::kCalls),
|
||||
std::move(hideBlobs),
|
||||
_state.value(
|
||||
) | rpl::map([](const CallMuteButtonState &state) {
|
||||
|
@ -12,16 +12,32 @@ namespace {
|
||||
|
||||
Flags Data/* = {}*/;
|
||||
rpl::event_stream<> Events;
|
||||
bool AllForced/* = false*/;
|
||||
|
||||
} // namespace
|
||||
|
||||
void Set(Flags flags) {
|
||||
if (const auto diff = Data ^ flags) {
|
||||
Data = flags;
|
||||
if (!AllForced) {
|
||||
if (diff & kAnimations) {
|
||||
anim::SetDisabled(On(kAnimations));
|
||||
}
|
||||
Events.fire({});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flags Current() {
|
||||
return Data;
|
||||
}
|
||||
|
||||
void Set(Flags flags) {
|
||||
if (const auto diff = Data ^ flags) {
|
||||
Data = flags;
|
||||
void SetForceAll(bool force) {
|
||||
if (AllForced == force) {
|
||||
return;
|
||||
}
|
||||
AllForced = force;
|
||||
if (const auto diff = Data ^ kAll) {
|
||||
if (diff & kAnimations) {
|
||||
anim::SetDisabled(On(kAnimations));
|
||||
}
|
||||
@ -29,18 +45,12 @@ void Set(Flags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<Flags> Changes() {
|
||||
return Events.events() | rpl::map(Current);
|
||||
bool ForceAll() {
|
||||
return AllForced;
|
||||
}
|
||||
|
||||
rpl::producer<Flags> Value() {
|
||||
return rpl::single(Current()) | rpl::then(Changes());
|
||||
}
|
||||
|
||||
rpl::producer<bool> Value(Flag flag) {
|
||||
return Value() | rpl::map([=](Flags flags) {
|
||||
return (flags & flag) != 0;
|
||||
}) | rpl::distinct_until_changed();
|
||||
rpl::producer<> Changes() {
|
||||
return Events.events();
|
||||
}
|
||||
|
||||
} // namespace PowerSaving
|
||||
|
@ -25,14 +25,21 @@ enum Flag : uint32 {
|
||||
inline constexpr bool is_flag_type(Flag) { return true; }
|
||||
using Flags = base::flags<Flag>;
|
||||
|
||||
[[nodiscard]] Flags Current();
|
||||
[[nodiscard]] rpl::producer<Flags> Changes();
|
||||
[[nodiscard]] rpl::producer<Flags> Value();
|
||||
[[nodiscard]] rpl::producer<bool> Value(Flag flag);
|
||||
void Set(Flags flags);
|
||||
[[nodiscard]] Flags Current();
|
||||
|
||||
void SetForceAll(bool force);
|
||||
[[nodiscard]] bool ForceAll();
|
||||
|
||||
[[nodiscard]] rpl::producer<> Changes();
|
||||
|
||||
[[nodiscard]] inline bool On(Flag flag) {
|
||||
return Current() & flag;
|
||||
return ForceAll() || (Current() & flag);
|
||||
}
|
||||
[[nodiscard]] inline rpl::producer<bool> OnValue(Flag flag) {
|
||||
return rpl::single(On(flag)) | rpl::then(Changes() | rpl::map([=] {
|
||||
return On(flag);
|
||||
})) | rpl::distinct_until_changed();
|
||||
}
|
||||
|
||||
} // namespace PowerSaving
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2e306a7245de70b6e6943b0bc33892bf0d327320
|
||||
Subproject commit 17ac5644d1f5cdaeb79b42cdf931b819cf0dbcf3
|
@ -1 +1 @@
|
||||
Subproject commit bc7b4cae2ea69c67a7b501289ffba7c8eddc5d19
|
||||
Subproject commit 8b1015d1bd57ef03fcd07a3eeddd3f5a9b688ade
|
Loading…
Reference in New Issue
Block a user