feat: add settings for ReadAfterAction

feat: write formatted config
fix: don't reset config on missing field

the last one is for convenient migrating between versions
This commit is contained in:
ZavaruKitsu 2023-09-21 22:06:17 +03:00
parent e1babcf69a
commit 3a1f8459e2
4 changed files with 154 additions and 35 deletions

View file

@ -6,16 +6,19 @@
// Copyright @Radolyn, 2023
#include "ayu_settings.h"
#include "rpl/lifetime.h"
#include "rpl/producer.h"
#include "rpl/variable.h"
#include <fstream>
using json = nlohmann::json;
namespace AyuSettings
{
const QString filename = "tdata/ayu_settings.json";
const std::string filename = "tdata/ayu_settings.json";
std::optional<AyuGramSettings> settings = std::nullopt;
@ -130,16 +133,17 @@ AyuGramSettings &getInstance()
void load()
{
QFile file(filename);
if (!file.exists()) {
std::ifstream file(filename);
if (!file.good()) {
return;
}
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
file.close();
initialize();
json p = json::parse(data);
json p;
file >> p;
file.close();
try {
settings = p.get<AyuGramSettings>();
}
@ -155,9 +159,9 @@ void save()
json p = settings.value();
QFile file(filename);
file.open(QIODevice::WriteOnly);
file.write(p.dump().c_str());
std::ofstream file;
file.open(filename);
file << p.dump(4);
file.close();
postinitialize();

View file

@ -145,7 +145,7 @@ public:
void set_voiceConfirmation(bool val);
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
AyuGramSettings,
sendReadMessages,
sendReadStories,

View file

@ -47,8 +47,6 @@
#include "ui/wrap/vertical_layout.h"
#include "window/window_session_controller.h"
constexpr auto GhostModeOptionsCount = 5;
class PainterHighQualityEnabler;
const char kStreamerMode[] =
@ -160,17 +158,19 @@ not_null<Ui::RpWidget *> AddInnerToggle(
(s.height() - checkWidget->height()) / 2);
}, toggleButton->lifetime());
}
const auto totalInnerChecks = state->innerChecks.size();
state->anyChanges.events_starting_with(
rpl::empty_value()
) | rpl::map(countChecked) | start_with_next([=](int count)
{
checkView->setChecked(count == GhostModeOptionsCount,
checkView->setChecked(count == totalInnerChecks,
anim::type::normal);
}, toggleButton->lifetime());
checkView->setLocked(locked.has_value());
checkView->finishAnimating();
const auto totalInnerChecks = state->innerChecks.size();
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
combine(
@ -344,12 +344,9 @@ void Ayu::AddPlatformOption(
}
}
void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
{
void Ayu::SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container) {
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader());
const auto widget = object_ptr<Ui::VerticalLayout>(this);
widget->add(
@ -372,7 +369,7 @@ void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
label,
isCheckedOrig,
st::settingsCheckbox),
st::rightsButton.padding);
st::powerSavingButton.padding);
const auto button = Ui::CreateChild<Ui::RippleButton>(
verticalLayout.get(),
st::defaultRippleAnimation);
@ -467,7 +464,7 @@ void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
raw->hide(anim::type::instant);
AddInnerToggle(
container,
st::rightsButton,
st::powerSavingButtonNoIcon,
innerChecks,
raw,
tr::ayu_GhostModeToggle(),
@ -479,22 +476,136 @@ void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
{
raw->resizeToWidth(w);
}, raw->lifetime());
}
AddButton(
void Ayu::SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container) {
auto settings = &AyuSettings::getInstance();
const auto widget = object_ptr<Ui::VerticalLayout>(this);
widget->add(
object_ptr<Ui::FlatLabel>(
container,
tr::ayu_MarkReadAfterAction(),
st::rightsHeaderLabel),
st::rightsHeaderMargin);
const auto addCheckbox = [&](
not_null<Ui::VerticalLayout *> verticalLayout,
const QString &label,
const bool isCheckedOrig)
{
const auto checkView = [&]() -> not_null<Ui::AbstractCheckView *>
{
const auto checkbox = verticalLayout->add(
object_ptr<Ui::Checkbox>(
verticalLayout,
label,
isCheckedOrig,
st::settingsCheckbox),
st::powerSavingButton.padding);
const auto button = Ui::CreateChild<Ui::RippleButton>(
verticalLayout.get(),
st::defaultRippleAnimation);
button->stackUnder(checkbox);
combine(
verticalLayout->widthValue(),
checkbox->geometryValue()
) | start_with_next([=](int w, const QRect &r)
{
button->setGeometry(0, r.y(), w, r.height());
}, button->lifetime());
checkbox->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto checkView = checkbox->checkView();
button->setClickedCallback([=]
{
checkView->setChecked(
!checkView->checked(),
anim::type::normal);
});
return checkView;
}();
checkView->checkedChanges(
) | start_with_next([=](bool checked)
{
}, verticalLayout->lifetime());
return checkView;
};
struct NestedEntry
{
QString checkboxLabel;
bool initial;
std::function<void(bool)> callback;
};
std::vector checkboxes{
NestedEntry{
tr::ayu_MarkReadAfterSend(tr::now), false, [=](bool enabled)
{
// settings->set_sendReadMessages(!enabled);
// AyuSettings::save();
}
},
NestedEntry{
tr::ayu_MarkReadAfterReaction(tr::now), false, [=](bool enabled)
{
// settings->set_sendReadStories(!enabled);
// AyuSettings::save();
}
},
NestedEntry{
tr::ayu_MarkReadAfterPoll(tr::now), false, [=](bool enabled)
{
// settings->set_sendOnlinePackets(!enabled);
// AyuSettings::save();
}
},
};
auto wrap = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
tr::ayu_MarkReadAfterSend(),
st::settingsButtonNoIcon
)->toggleOn(
rpl::single(settings->markReadAfterSend)
)->toggledValue(
) | rpl::filter([=](bool enabled)
{
return (enabled != settings->markReadAfterSend);
}) | start_with_next([=](bool enabled)
{
settings->set_markReadAfterSend(enabled);
AyuSettings::save();
}, container->lifetime());
object_ptr<Ui::VerticalLayout>(container));
const auto verticalLayout = wrap->entity();
auto innerChecks = std::vector<not_null<Ui::AbstractCheckView *>>();
for (const auto &entry : checkboxes) {
const auto c = addCheckbox(verticalLayout, entry.checkboxLabel, entry.initial);
c->checkedValue(
) | start_with_next([=](bool enabled)
{
entry.callback(enabled);
}, container->lifetime());
innerChecks.push_back(c);
}
const auto raw = wrap.data();
raw->hide(anim::type::instant);
AddInnerToggle(
container,
st::powerSavingButtonNoIcon,
innerChecks,
raw,
tr::ayu_MarkReadAfterAction(),
std::nullopt,
{});
container->add(std::move(wrap));
container->widthValue(
) | start_with_next([=](int w)
{
raw->resizeToWidth(w);
}, raw->lifetime());
}
void Ayu::SetupGhostEssentials(not_null<Ui::VerticalLayout *> container)
{
auto settings = &AyuSettings::getInstance();
AddSubsectionTitle(container, tr::ayu_GhostEssentialsHeader());
SetupGhostModeToggle(container);
SetupReadAfterActionToggle(container);
AddButton(
container,

View file

@ -38,6 +38,10 @@ private:
base::options::option<bool> &option,
rpl::producer<> resetClicks);
void SetupGhostModeToggle(not_null<Ui::VerticalLayout *> container);
void SetupReadAfterActionToggle(not_null<Ui::VerticalLayout *> container);
void SetupGhostEssentials(not_null<Ui::VerticalLayout *> container);
void SetupSpyEssentials(not_null<Ui::VerticalLayout *> container);