mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Migrate all notification settings to builder.
This commit is contained in:
@@ -1571,6 +1571,8 @@ PRIVATE
|
||||
settings/builder/settings_builder.h
|
||||
settings/builder/settings_main_builder.cpp
|
||||
settings/builder/settings_main_builder.h
|
||||
settings/builder/settings_notifications_builder.cpp
|
||||
settings/builder/settings_notifications_builder.h
|
||||
settings/settings_notifications.cpp
|
||||
settings/settings_notifications.h
|
||||
settings/settings_notifications_type.cpp
|
||||
|
||||
@@ -250,6 +250,75 @@ Ui::SettingsButton *SectionBuilder::addPremiumButton(PremiumButtonArgs &&args) {
|
||||
});
|
||||
}
|
||||
|
||||
Ui::SettingsButton *SectionBuilder::addToggle(ToggleArgs &&args) {
|
||||
return v::match(_context, [&](const WidgetContext &ctx)
|
||||
-> Ui::SettingsButton* {
|
||||
const auto &st = args.st ? *args.st : st::settingsButton;
|
||||
const auto button = ctx.container->add(CreateButtonWithIcon(
|
||||
ctx.container,
|
||||
rpl::duplicate(args.title),
|
||||
st,
|
||||
std::move(args.icon)));
|
||||
button->toggleOn(std::move(args.toggled));
|
||||
return button;
|
||||
}, [&](const SearchContext &ctx) -> Ui::SettingsButton* {
|
||||
if (!args.id.isEmpty()) {
|
||||
ctx.entries->push_back({
|
||||
.id = std::move(args.id),
|
||||
.title = ResolveTitle(std::move(args.title)),
|
||||
.keywords = std::move(args.keywords),
|
||||
});
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
Ui::SlideWrap<Ui::SettingsButton> *SectionBuilder::addSlideToggle(
|
||||
SlideToggleArgs &&args) {
|
||||
return v::match(_context, [&](const WidgetContext &ctx)
|
||||
-> Ui::SlideWrap<Ui::SettingsButton>* {
|
||||
const auto &st = args.st ? *args.st : st::settingsButton;
|
||||
const auto wrap = ctx.container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
||||
ctx.container,
|
||||
CreateButtonWithIcon(
|
||||
ctx.container,
|
||||
rpl::duplicate(args.title),
|
||||
st,
|
||||
std::move(args.icon))));
|
||||
if (args.shown) {
|
||||
wrap->toggleOn(std::move(args.shown));
|
||||
}
|
||||
const auto button = wrap->entity();
|
||||
button->toggleOn(std::move(args.toggled));
|
||||
return wrap;
|
||||
}, [&](const SearchContext &ctx) -> Ui::SlideWrap<Ui::SettingsButton>* {
|
||||
if (!args.id.isEmpty()) {
|
||||
ctx.entries->push_back({
|
||||
.id = std::move(args.id),
|
||||
.title = ResolveTitle(std::move(args.title)),
|
||||
.keywords = std::move(args.keywords),
|
||||
});
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void SectionBuilder::addSubsectionTitle(rpl::producer<QString> text) {
|
||||
v::match(_context, [&](const WidgetContext &ctx) {
|
||||
AddSubsectionTitle(ctx.container, std::move(text));
|
||||
}, [](const SearchContext &) {
|
||||
});
|
||||
}
|
||||
|
||||
Ui::VerticalLayout *SectionBuilder::container() const {
|
||||
return v::match(_context, [](const WidgetContext &ctx) {
|
||||
return ctx.container.get();
|
||||
}, [](const SearchContext &) -> Ui::VerticalLayout* {
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
Window::SessionController *SectionBuilder::controller() const {
|
||||
return v::match(_context, [](const WidgetContext &ctx) {
|
||||
return ctx.controller.get();
|
||||
|
||||
@@ -121,11 +121,34 @@ public:
|
||||
};
|
||||
Ui::SettingsButton *addPremiumButton(PremiumButtonArgs &&args);
|
||||
|
||||
struct ToggleArgs {
|
||||
QString id;
|
||||
rpl::producer<QString> title;
|
||||
const style::SettingsButton *st = nullptr;
|
||||
IconDescriptor icon;
|
||||
rpl::producer<bool> toggled;
|
||||
QStringList keywords;
|
||||
};
|
||||
Ui::SettingsButton *addToggle(ToggleArgs &&args);
|
||||
|
||||
struct SlideToggleArgs {
|
||||
QString id;
|
||||
rpl::producer<QString> title;
|
||||
const style::SettingsButton *st = nullptr;
|
||||
IconDescriptor icon;
|
||||
rpl::producer<bool> toggled;
|
||||
rpl::producer<bool> shown;
|
||||
QStringList keywords;
|
||||
};
|
||||
Ui::SlideWrap<Ui::SettingsButton> *addSlideToggle(SlideToggleArgs &&args);
|
||||
|
||||
void addSubsectionTitle(rpl::producer<QString> text);
|
||||
void addDivider();
|
||||
void addDividerText(rpl::producer<QString> text);
|
||||
void addSkip();
|
||||
void addSkip(int height);
|
||||
|
||||
[[nodiscard]] Ui::VerticalLayout *container() const;
|
||||
[[nodiscard]] Window::SessionController *controller() const;
|
||||
[[nodiscard]] Fn<void(Type)> showOther() const;
|
||||
|
||||
|
||||
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "settings/builder/settings_notifications_builder.h"
|
||||
|
||||
#include "api/api_authorizations.h"
|
||||
#include "api/api_ringtones.h"
|
||||
#include "apiwrap.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "boxes/ringtones_box.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "data/notify/data_peer_notify_volume.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwindow.h"
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "settings/builder/settings_builder.h"
|
||||
#include "settings/settings_notifications_common.h"
|
||||
#include "settings/settings_notifications_type.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/continuous_sliders.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
namespace Settings::Builder {
|
||||
namespace {
|
||||
|
||||
constexpr auto kDefaultDisplayIndex = -1;
|
||||
|
||||
using NotifyView = Core::Settings::NotifyView;
|
||||
using ChangeType = Window::Notifications::ChangeType;
|
||||
|
||||
void BuildMultiAccountSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
if (Core::App().domain().accounts().size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
builder.addSubsectionTitle(tr::lng_settings_show_from());
|
||||
|
||||
const auto container = builder.container();
|
||||
if (!container) {
|
||||
builder.addToggle({
|
||||
.id = u"notifications/multi_account"_q,
|
||||
.title = tr::lng_settings_notify_all(),
|
||||
.toggled = rpl::single(Core::App().settings().notifyFromAll()),
|
||||
.keywords = { u"all accounts"_q, u"multiple"_q },
|
||||
});
|
||||
builder.addSkip();
|
||||
builder.addDividerText(tr::lng_settings_notify_all_about());
|
||||
builder.addSkip();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto fromAll = builder.addToggle({
|
||||
.id = u"notifications/multi_account"_q,
|
||||
.title = tr::lng_settings_notify_all(),
|
||||
.st = &st::settingsButtonNoIcon,
|
||||
.toggled = rpl::single(Core::App().settings().notifyFromAll()),
|
||||
.keywords = { u"all accounts"_q, u"multiple"_q },
|
||||
});
|
||||
|
||||
if (fromAll) {
|
||||
fromAll->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().notifyFromAll());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setNotifyFromAll(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (!checked) {
|
||||
auto ¬ifications = Core::App().notifications();
|
||||
const auto &list = Core::App().domain().accounts();
|
||||
for (const auto &[index, account] : list) {
|
||||
if (account.get() == &Core::App().domain().active()) {
|
||||
continue;
|
||||
} else if (const auto session = account->maybeSession()) {
|
||||
notifications.clearFromSession(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, fromAll->lifetime());
|
||||
}
|
||||
|
||||
builder.addSkip();
|
||||
builder.addDividerText(tr::lng_settings_notify_all_about());
|
||||
builder.addSkip();
|
||||
}
|
||||
|
||||
void BuildGlobalNotificationsSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
builder.addSubsectionTitle(tr::lng_settings_notify_global());
|
||||
|
||||
const auto container = builder.container();
|
||||
const auto &settings = Core::App().settings();
|
||||
|
||||
const auto desktopToggles = container
|
||||
? container->lifetime().make_state<rpl::event_stream<bool>>()
|
||||
: nullptr;
|
||||
const auto desktop = builder.addToggle({
|
||||
.id = u"notifications/desktop"_q,
|
||||
.title = tr::lng_settings_desktop_notify(),
|
||||
.icon = { &st::menuIconNotifications },
|
||||
.toggled = desktopToggles
|
||||
? desktopToggles->events_starting_with(settings.desktopNotify())
|
||||
: rpl::single(settings.desktopNotify()),
|
||||
.keywords = { u"desktop"_q, u"popup"_q, u"show"_q },
|
||||
});
|
||||
|
||||
const auto flashbounceToggles = container
|
||||
? container->lifetime().make_state<rpl::event_stream<bool>>()
|
||||
: nullptr;
|
||||
const auto flashbounce = builder.addToggle({
|
||||
.id = u"notifications/flash"_q,
|
||||
.title = (Platform::IsWindows()
|
||||
? tr::lng_settings_alert_windows
|
||||
: Platform::IsMac()
|
||||
? tr::lng_settings_alert_mac
|
||||
: tr::lng_settings_alert_linux)(),
|
||||
.icon = { &st::menuIconDockBounce },
|
||||
.toggled = flashbounceToggles
|
||||
? flashbounceToggles->events_starting_with(settings.flashBounceNotify())
|
||||
: rpl::single(settings.flashBounceNotify()),
|
||||
.keywords = { u"flash"_q, u"bounce"_q, u"taskbar"_q },
|
||||
});
|
||||
|
||||
const auto soundAllowed = container
|
||||
? container->lifetime().make_state<rpl::event_stream<bool>>()
|
||||
: nullptr;
|
||||
const auto allowed = [=] {
|
||||
return Core::App().settings().soundNotify();
|
||||
};
|
||||
const auto sound = builder.addToggle({
|
||||
.id = u"notifications/sound"_q,
|
||||
.title = tr::lng_settings_sound_allowed(),
|
||||
.icon = { &st::menuIconUnmute },
|
||||
.toggled = soundAllowed
|
||||
? soundAllowed->events_starting_with(allowed())
|
||||
: rpl::single(allowed()),
|
||||
.keywords = { u"sound"_q, u"audio"_q, u"mute"_q },
|
||||
});
|
||||
|
||||
if (container && controller) {
|
||||
const auto session = &controller->session();
|
||||
Ui::AddRingtonesVolumeSlider(
|
||||
container,
|
||||
rpl::single(true),
|
||||
tr::lng_settings_master_volume_notifications(),
|
||||
Data::VolumeController{
|
||||
.volume = []() -> ushort {
|
||||
const auto volume
|
||||
= Core::App().settings().notificationsVolume();
|
||||
return volume ? volume : 100;
|
||||
},
|
||||
.saveVolume = [=](ushort volume) {
|
||||
Core::App().notifications().playSound(
|
||||
session,
|
||||
0,
|
||||
volume / 100.);
|
||||
Core::App().settings().setNotificationsVolume(volume);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}});
|
||||
}
|
||||
|
||||
builder.addSkip();
|
||||
|
||||
if (desktop) {
|
||||
const auto changed = [=](ChangeType change) {
|
||||
Core::App().saveSettingsDelayed();
|
||||
Core::App().notifications().notifySettingsChanged(change);
|
||||
};
|
||||
|
||||
desktop->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().desktopNotify());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setDesktopNotify(checked);
|
||||
changed(ChangeType::DesktopEnabled);
|
||||
}, desktop->lifetime());
|
||||
|
||||
if (sound) {
|
||||
sound->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().soundNotify());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setSoundNotify(checked);
|
||||
changed(ChangeType::SoundEnabled);
|
||||
}, sound->lifetime());
|
||||
}
|
||||
|
||||
if (flashbounce) {
|
||||
flashbounce->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().flashBounceNotify());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setFlashBounceNotify(checked);
|
||||
changed(ChangeType::FlashBounceEnabled);
|
||||
}, flashbounce->lifetime());
|
||||
}
|
||||
|
||||
Core::App().notifications().settingsChanged(
|
||||
) | rpl::on_next([=](ChangeType change) {
|
||||
if (change == ChangeType::DesktopEnabled) {
|
||||
desktopToggles->fire(Core::App().settings().desktopNotify());
|
||||
} else if (change == ChangeType::SoundEnabled) {
|
||||
soundAllowed->fire(allowed());
|
||||
} else if (change == ChangeType::FlashBounceEnabled) {
|
||||
flashbounceToggles->fire(
|
||||
Core::App().settings().flashBounceNotify());
|
||||
}
|
||||
}, desktop->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void BuildNotifyViewSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller,
|
||||
rpl::lifetime &lifetime) {
|
||||
const auto container = builder.container();
|
||||
if (!container || !controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto checkboxes = SetupNotifyViewOptions(
|
||||
controller,
|
||||
container,
|
||||
(settings.notifyView() <= NotifyView::ShowName),
|
||||
(settings.notifyView() <= NotifyView::ShowPreview));
|
||||
const auto name = checkboxes.name;
|
||||
const auto preview = checkboxes.preview;
|
||||
const auto previewWrap = checkboxes.wrap;
|
||||
|
||||
const auto previewDivider = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::BoxContentDivider>>(
|
||||
container,
|
||||
object_ptr<Ui::BoxContentDivider>(container)));
|
||||
previewWrap->toggle(settings.desktopNotify(), anim::type::instant);
|
||||
previewDivider->toggle(!settings.desktopNotify(), anim::type::instant);
|
||||
|
||||
const auto changed = [=](ChangeType change) {
|
||||
Core::App().saveSettingsDelayed();
|
||||
Core::App().notifications().notifySettingsChanged(change);
|
||||
};
|
||||
|
||||
name->checkedChanges(
|
||||
) | rpl::map([=](bool checked) {
|
||||
if (!checked) {
|
||||
preview->setChecked(false);
|
||||
return NotifyView::ShowNothing;
|
||||
} else if (!preview->checked()) {
|
||||
return NotifyView::ShowName;
|
||||
}
|
||||
return NotifyView::ShowPreview;
|
||||
}) | rpl::filter([=](NotifyView value) {
|
||||
return (value != Core::App().settings().notifyView());
|
||||
}) | rpl::on_next([=](NotifyView value) {
|
||||
Core::App().settings().setNotifyView(value);
|
||||
changed(ChangeType::ViewParams);
|
||||
}, name->lifetime());
|
||||
|
||||
preview->checkedChanges(
|
||||
) | rpl::map([=](bool checked) {
|
||||
if (checked) {
|
||||
name->setChecked(true);
|
||||
return NotifyView::ShowPreview;
|
||||
} else if (name->checked()) {
|
||||
return NotifyView::ShowName;
|
||||
}
|
||||
return NotifyView::ShowNothing;
|
||||
}) | rpl::filter([=](NotifyView value) {
|
||||
return (value != Core::App().settings().notifyView());
|
||||
}) | rpl::on_next([=](NotifyView value) {
|
||||
Core::App().settings().setNotifyView(value);
|
||||
changed(ChangeType::ViewParams);
|
||||
}, preview->lifetime());
|
||||
|
||||
Core::App().notifications().settingsChanged(
|
||||
) | rpl::on_next([=](ChangeType change) {
|
||||
if (change == ChangeType::DesktopEnabled) {
|
||||
previewWrap->toggle(
|
||||
Core::App().settings().desktopNotify(),
|
||||
anim::type::normal);
|
||||
previewDivider->toggle(
|
||||
!Core::App().settings().desktopNotify(),
|
||||
anim::type::normal);
|
||||
}
|
||||
}, lifetime);
|
||||
}
|
||||
|
||||
void BuildNotifyTypeSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
const auto container = builder.container();
|
||||
const auto showOther = builder.showOther();
|
||||
|
||||
builder.addSkip(st::notifyPreviewBottomSkip);
|
||||
builder.addSubsectionTitle(tr::lng_settings_notify_title());
|
||||
|
||||
if (container && controller && showOther) {
|
||||
controller->session().data().notifySettings().loadExceptions();
|
||||
AddTypeButton(container, controller, Data::DefaultNotify::User, showOther);
|
||||
AddTypeButton(container, controller, Data::DefaultNotify::Group, showOther);
|
||||
AddTypeButton(container, controller, Data::DefaultNotify::Broadcast, showOther);
|
||||
} else {
|
||||
builder.addSettingsButton({
|
||||
.id = u"notifications/private"_q,
|
||||
.title = tr::lng_notification_private_chats(),
|
||||
.icon = { &st::menuIconProfile },
|
||||
.keywords = { u"private"_q, u"chats"_q, u"direct"_q },
|
||||
});
|
||||
builder.addSettingsButton({
|
||||
.id = u"notifications/groups"_q,
|
||||
.title = tr::lng_notification_groups(),
|
||||
.icon = { &st::menuIconGroups },
|
||||
.keywords = { u"groups"_q, u"chats"_q },
|
||||
});
|
||||
builder.addSettingsButton({
|
||||
.id = u"notifications/channels"_q,
|
||||
.title = tr::lng_notification_channels(),
|
||||
.icon = { &st::menuIconChannel },
|
||||
.keywords = { u"channels"_q, u"broadcast"_q },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void BuildEventNotificationsSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addDivider();
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addSubsectionTitle(tr::lng_settings_events_title());
|
||||
|
||||
if (!controller) {
|
||||
builder.addToggle({
|
||||
.id = u"notifications/events/joined"_q,
|
||||
.title = tr::lng_settings_events_joined(),
|
||||
.icon = { &st::menuIconInvite },
|
||||
.toggled = rpl::single(false),
|
||||
.keywords = { u"joined"_q, u"contacts"_q, u"signup"_q },
|
||||
});
|
||||
builder.addToggle({
|
||||
.id = u"notifications/events/pinned"_q,
|
||||
.title = tr::lng_settings_events_pinned(),
|
||||
.icon = { &st::menuIconPin },
|
||||
.toggled = rpl::single(Core::App().settings().notifyAboutPinned()),
|
||||
.keywords = { u"pinned"_q, u"message"_q },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const auto session = &controller->session();
|
||||
const auto &settings = Core::App().settings();
|
||||
|
||||
auto joinSilent = rpl::single(
|
||||
session->api().contactSignupSilentCurrent().value_or(false)
|
||||
) | rpl::then(session->api().contactSignupSilent());
|
||||
|
||||
const auto joined = builder.addToggle({
|
||||
.id = u"notifications/events/joined"_q,
|
||||
.title = tr::lng_settings_events_joined(),
|
||||
.icon = { &st::menuIconInvite },
|
||||
.toggled = std::move(joinSilent) | rpl::map([](bool s) { return !s; }),
|
||||
.keywords = { u"joined"_q, u"contacts"_q, u"signup"_q },
|
||||
});
|
||||
if (joined) {
|
||||
joined->toggledChanges(
|
||||
) | rpl::filter([=](bool enabled) {
|
||||
const auto silent = session->api().contactSignupSilentCurrent();
|
||||
return (enabled == silent.value_or(false));
|
||||
}) | rpl::on_next([=](bool enabled) {
|
||||
session->api().saveContactSignupSilent(!enabled);
|
||||
}, joined->lifetime());
|
||||
}
|
||||
|
||||
const auto pinned = builder.addToggle({
|
||||
.id = u"notifications/events/pinned"_q,
|
||||
.title = tr::lng_settings_events_pinned(),
|
||||
.icon = { &st::menuIconPin },
|
||||
.toggled = rpl::single(
|
||||
settings.notifyAboutPinned()
|
||||
) | rpl::then(settings.notifyAboutPinnedChanges()),
|
||||
.keywords = { u"pinned"_q, u"message"_q },
|
||||
});
|
||||
if (pinned) {
|
||||
pinned->toggledChanges(
|
||||
) | rpl::filter([=](bool notify) {
|
||||
return (notify != Core::App().settings().notifyAboutPinned());
|
||||
}) | rpl::on_next([=](bool notify) {
|
||||
Core::App().settings().setNotifyAboutPinned(notify);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}, pinned->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void BuildCallNotificationsSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addDivider();
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addSubsectionTitle(tr::lng_settings_notifications_calls_title());
|
||||
|
||||
if (!controller) {
|
||||
builder.addToggle({
|
||||
.id = u"notifications/calls/accept"_q,
|
||||
.title = tr::lng_settings_call_accept_calls(),
|
||||
.icon = { &st::menuIconCallsReceive },
|
||||
.toggled = rpl::single(true),
|
||||
.keywords = { u"calls"_q, u"receive"_q, u"incoming"_q },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const auto session = &controller->session();
|
||||
const auto authorizations = &session->api().authorizations();
|
||||
authorizations->reload();
|
||||
|
||||
const auto acceptCalls = builder.addToggle({
|
||||
.id = u"notifications/calls/accept"_q,
|
||||
.title = tr::lng_settings_call_accept_calls(),
|
||||
.icon = { &st::menuIconCallsReceive },
|
||||
.toggled = authorizations->callsDisabledHereValue()
|
||||
| rpl::map([](bool disabled) { return !disabled; }),
|
||||
.keywords = { u"calls"_q, u"receive"_q, u"incoming"_q },
|
||||
});
|
||||
if (acceptCalls) {
|
||||
const auto container = builder.container();
|
||||
acceptCalls->toggledChanges(
|
||||
) | rpl::filter([=](bool toggled) {
|
||||
return (toggled == authorizations->callsDisabledHere());
|
||||
}) | rpl::on_next([=](bool toggled) {
|
||||
authorizations->toggleCallsDisabledHere(!toggled);
|
||||
}, container->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void BuildBadgeCounterSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addDivider();
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addSubsectionTitle(tr::lng_settings_badge_title());
|
||||
|
||||
const auto &settings = Core::App().settings();
|
||||
|
||||
const auto muted = builder.addToggle({
|
||||
.id = u"notifications/badge/muted"_q,
|
||||
.title = tr::lng_settings_include_muted(),
|
||||
.st = &st::settingsButtonNoIcon,
|
||||
.toggled = rpl::single(settings.includeMutedCounter()),
|
||||
.keywords = { u"muted"_q, u"badge"_q, u"counter"_q },
|
||||
});
|
||||
|
||||
const auto hasFolders = controller
|
||||
&& controller->session().data().chatsFilters().has();
|
||||
const auto mutedFolders = hasFolders ? builder.addToggle({
|
||||
.id = u"notifications/badge/muted_folders"_q,
|
||||
.title = tr::lng_settings_include_muted_folders(),
|
||||
.st = &st::settingsButtonNoIcon,
|
||||
.toggled = rpl::single(settings.includeMutedCounterFolders()),
|
||||
.keywords = { u"muted"_q, u"folders"_q },
|
||||
}) : nullptr;
|
||||
|
||||
const auto count = builder.addToggle({
|
||||
.id = u"notifications/badge/count"_q,
|
||||
.title = tr::lng_settings_count_unread(),
|
||||
.st = &st::settingsButtonNoIcon,
|
||||
.toggled = rpl::single(settings.countUnreadMessages()),
|
||||
.keywords = { u"unread"_q, u"messages"_q, u"count"_q },
|
||||
});
|
||||
|
||||
const auto changed = [=](ChangeType change) {
|
||||
Core::App().saveSettingsDelayed();
|
||||
Core::App().notifications().notifySettingsChanged(change);
|
||||
};
|
||||
|
||||
if (muted) {
|
||||
muted->toggledChanges(
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != Core::App().settings().includeMutedCounter());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setIncludeMutedCounter(checked);
|
||||
changed(ChangeType::IncludeMuted);
|
||||
}, muted->lifetime());
|
||||
}
|
||||
|
||||
if (mutedFolders) {
|
||||
mutedFolders->toggledChanges(
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked
|
||||
!= Core::App().settings().includeMutedCounterFolders());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setIncludeMutedCounterFolders(checked);
|
||||
changed(ChangeType::IncludeMuted);
|
||||
}, mutedFolders->lifetime());
|
||||
}
|
||||
|
||||
if (count) {
|
||||
count->toggledChanges(
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != Core::App().settings().countUnreadMessages());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setCountUnreadMessages(checked);
|
||||
changed(ChangeType::CountMessages);
|
||||
}, count->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void BuildSystemIntegrationAndAdvancedSection(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
const auto container = builder.container();
|
||||
|
||||
auto nativeText = [&]() -> rpl::producer<QString> {
|
||||
if (!Platform::Notifications::Supported()
|
||||
|| Core::App().notifications().nativeEnforced()) {
|
||||
return rpl::producer<QString>();
|
||||
} else if (Platform::IsWindows()) {
|
||||
return tr::lng_settings_use_windows();
|
||||
}
|
||||
return tr::lng_settings_use_native_notifications();
|
||||
}();
|
||||
|
||||
if (nativeText) {
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addDivider();
|
||||
builder.addSkip(st::settingsCheckboxesSkip);
|
||||
builder.addSubsectionTitle(tr::lng_settings_native_title());
|
||||
}
|
||||
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto native = nativeText ? builder.addToggle({
|
||||
.id = u"notifications/native"_q,
|
||||
.title = std::move(nativeText),
|
||||
.st = &st::settingsButtonNoIcon,
|
||||
.toggled = rpl::single(settings.nativeNotifications()),
|
||||
.keywords = { u"native"_q, u"system"_q, u"windows"_q },
|
||||
}) : nullptr;
|
||||
|
||||
if (Core::App().notifications().nativeEnforced()) {
|
||||
return;
|
||||
}
|
||||
if (!container || !controller) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto advancedSlide = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::VerticalLayout>(container)));
|
||||
const auto advancedWrap = advancedSlide->entity();
|
||||
|
||||
if (native) {
|
||||
native->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().nativeNotifications());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setNativeNotifications(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
Core::App().notifications().createManager();
|
||||
advancedSlide->toggle(!checked, anim::type::normal);
|
||||
}, native->lifetime());
|
||||
}
|
||||
|
||||
if (Platform::IsWindows()) {
|
||||
const auto skipInFocus = advancedWrap->add(object_ptr<Ui::SettingsButton>(
|
||||
advancedWrap,
|
||||
tr::lng_settings_skip_in_focus(),
|
||||
st::settingsButtonNoIcon
|
||||
))->toggleOn(rpl::single(Core::App().settings().skipToastsInFocus()));
|
||||
|
||||
skipInFocus->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().skipToastsInFocus());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setSkipToastsInFocus(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (checked && Platform::Notifications::SkipToastForCustom()) {
|
||||
Core::App().notifications().notifySettingsChanged(
|
||||
ChangeType::DesktopEnabled);
|
||||
}
|
||||
}, skipInFocus->lifetime());
|
||||
}
|
||||
|
||||
const auto screens = QGuiApplication::screens();
|
||||
if (screens.size() > 1) {
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(advancedWrap);
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(
|
||||
advancedWrap,
|
||||
tr::lng_settings_notifications_display());
|
||||
|
||||
const auto currentChecksum
|
||||
= Core::App().settings().notificationsDisplayChecksum();
|
||||
auto currentIndex = (currentChecksum == 0)
|
||||
? kDefaultDisplayIndex
|
||||
: 0;
|
||||
for (auto i = 0; i < screens.size(); ++i) {
|
||||
if (Platform::ScreenNameChecksum(screens[i]) == currentChecksum) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto group = std::make_shared<Ui::RadiobuttonGroup>(
|
||||
currentIndex);
|
||||
|
||||
advancedWrap->add(
|
||||
object_ptr<Ui::Radiobutton>(
|
||||
advancedWrap,
|
||||
group,
|
||||
kDefaultDisplayIndex,
|
||||
tr::lng_settings_notifications_display_default(tr::now),
|
||||
st::settingsSendType),
|
||||
st::settingsSendTypePadding);
|
||||
|
||||
for (auto i = 0; i < screens.size(); ++i) {
|
||||
const auto &screen = screens[i];
|
||||
const auto name = Platform::ScreenDisplayLabel(screen);
|
||||
const auto geometry = screen->geometry();
|
||||
const auto resolution = QString::number(geometry.width())
|
||||
+ QChar(0x00D7)
|
||||
+ QString::number(geometry.height());
|
||||
const auto label = name.isEmpty()
|
||||
? QString("Display (%1)").arg(resolution)
|
||||
: QString("%1 (%2)").arg(name).arg(resolution);
|
||||
advancedWrap->add(
|
||||
object_ptr<Ui::Radiobutton>(
|
||||
advancedWrap,
|
||||
group,
|
||||
i,
|
||||
label,
|
||||
st::settingsSendType),
|
||||
st::settingsSendTypePadding);
|
||||
}
|
||||
group->setChangedCallback([=](int selectedIndex) {
|
||||
if (selectedIndex == kDefaultDisplayIndex) {
|
||||
Core::App().settings().setNotificationsDisplayChecksum(0);
|
||||
Core::App().saveSettings();
|
||||
Core::App().notifications().notifySettingsChanged(
|
||||
ChangeType::Corner);
|
||||
} else {
|
||||
const auto screens = QGuiApplication::screens();
|
||||
if (selectedIndex >= 0 && selectedIndex < screens.size()) {
|
||||
const auto checksum = Platform::ScreenNameChecksum(
|
||||
screens[selectedIndex]);
|
||||
Core::App().settings().setNotificationsDisplayChecksum(
|
||||
checksum);
|
||||
Core::App().saveSettings();
|
||||
Core::App().notifications().notifySettingsChanged(
|
||||
ChangeType::Corner);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(advancedWrap);
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(
|
||||
advancedWrap,
|
||||
tr::lng_settings_notifications_position());
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
|
||||
const auto position = advancedWrap->add(
|
||||
object_ptr<NotificationsCount>(advancedWrap, controller));
|
||||
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(advancedWrap, tr::lng_settings_notifications_count());
|
||||
|
||||
const auto countSlider = advancedWrap->add(
|
||||
object_ptr<Ui::SettingsSlider>(advancedWrap, st::settingsSlider),
|
||||
st::settingsBigScalePadding);
|
||||
for (int i = 0; i != kMaxNotificationsCount; ++i) {
|
||||
countSlider->addSection(QString::number(i + 1));
|
||||
}
|
||||
countSlider->setActiveSectionFast(CurrentNotificationsCount() - 1);
|
||||
countSlider->sectionActivated(
|
||||
) | rpl::on_next([=](int section) {
|
||||
position->setCount(section + 1);
|
||||
}, countSlider->lifetime());
|
||||
Ui::AddSkip(advancedWrap, st::settingsCheckboxesSkip);
|
||||
|
||||
if (Core::App().settings().nativeNotifications()) {
|
||||
advancedSlide->hide(anim::type::instant);
|
||||
}
|
||||
|
||||
Core::App().notifications().settingsChanged(
|
||||
) | rpl::on_next([=](ChangeType change) {
|
||||
if (change == ChangeType::DesktopEnabled) {
|
||||
const auto native = Core::App().settings().nativeNotifications();
|
||||
advancedSlide->toggle(!native, anim::type::normal);
|
||||
}
|
||||
}, advancedSlide->lifetime());
|
||||
}
|
||||
|
||||
void BuildNotificationsSectionContent(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
const auto container = builder.container();
|
||||
|
||||
builder.addSkip(st::settingsPrivacySkip);
|
||||
|
||||
BuildMultiAccountSection(builder, controller);
|
||||
BuildGlobalNotificationsSection(builder, controller);
|
||||
|
||||
if (container && controller) {
|
||||
BuildNotifyViewSection(builder, controller, container->lifetime());
|
||||
}
|
||||
|
||||
BuildNotifyTypeSection(builder, controller);
|
||||
BuildEventNotificationsSection(builder, controller);
|
||||
BuildCallNotificationsSection(builder, controller);
|
||||
BuildBadgeCounterSection(builder, controller);
|
||||
BuildSystemIntegrationAndAdvancedSection(builder, controller);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void BuildNotificationsSection(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Fn<void(Type)> showOther) {
|
||||
const auto isPaused = Window::PausedIn(
|
||||
controller,
|
||||
Window::GifPauseReason::Layer);
|
||||
auto builder = SectionBuilder(WidgetContext{
|
||||
.container = container,
|
||||
.controller = controller,
|
||||
.showOther = std::move(showOther),
|
||||
.isPaused = isPaused,
|
||||
});
|
||||
BuildNotificationsSectionContent(builder, controller);
|
||||
}
|
||||
|
||||
std::vector<SearchEntry> BuildNotificationsSectionForSearch() {
|
||||
auto entries = std::vector<SearchEntry>();
|
||||
auto builder = SectionBuilder(SearchContext{
|
||||
.entries = &entries,
|
||||
});
|
||||
BuildNotificationsSectionContent(builder, nullptr);
|
||||
return entries;
|
||||
}
|
||||
|
||||
} // namespace Settings::Builder
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "settings/builder/settings_builder.h"
|
||||
|
||||
namespace Ui {
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Settings::Builder {
|
||||
|
||||
void BuildNotificationsSection(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Fn<void(Type)> showOther);
|
||||
|
||||
[[nodiscard]] std::vector<SearchEntry> BuildNotificationsSectionForSearch();
|
||||
|
||||
} // namespace Settings::Builder
|
||||
@@ -7,124 +7,50 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "settings/settings_notifications.h"
|
||||
|
||||
#include "ui/widgets/continuous_sliders.h"
|
||||
#include "settings/builder/settings_notifications_builder.h"
|
||||
#include "settings/settings_notifications_common.h"
|
||||
#include "settings/settings_notifications_type.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/controls/chat_service_checkbox.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "data/notify/data_peer_notify_volume.h"
|
||||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/widgets/box_content_divider.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/discrete_sliders.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "core/application.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "main/main_session.h"
|
||||
#include "mainwindow.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "window/section_widget.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "platform/platform_specific.h"
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "mainwindow.h"
|
||||
#include "core/application.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_domain.h"
|
||||
#include "api/api_authorizations.h"
|
||||
#include "api/api_ringtones.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "boxes/ringtones_box.h"
|
||||
#include "apiwrap.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_window.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
#include <QSvgRenderer>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
constexpr auto kMaxNotificationsCount = 5;
|
||||
constexpr auto kDefaultDisplayIndex = -1;
|
||||
using ChangeType = Window::Notifications::ChangeType;
|
||||
|
||||
[[nodiscard]] int CurrentCount() {
|
||||
int CurrentNotificationsCount() {
|
||||
return std::clamp(
|
||||
Core::App().settings().notificationsCount(),
|
||||
1,
|
||||
kMaxNotificationsCount);
|
||||
}
|
||||
|
||||
using ChangeType = Window::Notifications::ChangeType;
|
||||
|
||||
class NotificationsCount : public Ui::RpWidget {
|
||||
public:
|
||||
NotificationsCount(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
|
||||
void setCount(int count);
|
||||
|
||||
~NotificationsCount();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
private:
|
||||
using ScreenCorner = Core::Settings::ScreenCorner;
|
||||
void setOverCorner(ScreenCorner corner);
|
||||
void clearOverCorner();
|
||||
|
||||
class SampleWidget;
|
||||
void removeSample(SampleWidget *widget);
|
||||
|
||||
QRect getScreenRect() const;
|
||||
QRect getScreenRect(int width) const;
|
||||
int getContentLeft() const;
|
||||
void prepareNotificationSampleSmall();
|
||||
void prepareNotificationSampleLarge();
|
||||
void prepareNotificationSampleUserpic();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
|
||||
QPixmap _notificationSampleUserpic;
|
||||
QPixmap _notificationSampleSmall;
|
||||
QPixmap _notificationSampleLarge;
|
||||
ScreenCorner _chosenCorner;
|
||||
std::vector<Ui::Animations::Simple> _sampleOpacities;
|
||||
|
||||
bool _isOverCorner = false;
|
||||
ScreenCorner _overCorner = ScreenCorner::TopLeft;
|
||||
bool _isDownCorner = false;
|
||||
ScreenCorner _downCorner = ScreenCorner::TopLeft;
|
||||
|
||||
int _oldCount;
|
||||
|
||||
std::vector<SampleWidget*> _cornerSamples[4];
|
||||
|
||||
};
|
||||
|
||||
class NotificationsCount::SampleWidget : public QWidget {
|
||||
public:
|
||||
SampleWidget(NotificationsCount *owner, const QPixmap &cache);
|
||||
@@ -306,7 +232,7 @@ NotificationsCount::NotificationsCount(
|
||||
not_null<Window::SessionController*> controller)
|
||||
: _controller(controller)
|
||||
, _chosenCorner(Core::App().settings().notificationsCorner())
|
||||
, _oldCount(CurrentCount()) {
|
||||
, _oldCount(CurrentNotificationsCount()) {
|
||||
setMouseTracking(true);
|
||||
|
||||
_sampleOpacities.resize(kMaxNotificationsCount);
|
||||
@@ -780,12 +706,6 @@ void NotifyPreview::paint(Painter &p, int x, int y) {
|
||||
2);
|
||||
}
|
||||
|
||||
struct NotifyViewCheckboxes {
|
||||
not_null<Ui::SlideWrap<>*> wrap;
|
||||
not_null<Ui::Checkbox*> name;
|
||||
not_null<Ui::Checkbox*> preview;
|
||||
};
|
||||
|
||||
NotifyViewCheckboxes SetupNotifyViewOptions(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
@@ -873,539 +793,6 @@ NotifyViewCheckboxes SetupNotifyViewOptions(
|
||||
};
|
||||
}
|
||||
|
||||
void SetupAdvancedNotifications(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container) {
|
||||
if (Platform::IsWindows()) {
|
||||
const auto skipInFocus = container->add(object_ptr<Button>(
|
||||
container,
|
||||
tr::lng_settings_skip_in_focus(),
|
||||
st::settingsButtonNoIcon
|
||||
))->toggleOn(rpl::single(Core::App().settings().skipToastsInFocus()));
|
||||
|
||||
skipInFocus->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().skipToastsInFocus());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setSkipToastsInFocus(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (checked && Platform::Notifications::SkipToastForCustom()) {
|
||||
using Change = Window::Notifications::ChangeType;
|
||||
Core::App().notifications().notifySettingsChanged(
|
||||
Change::DesktopEnabled);
|
||||
}
|
||||
}, skipInFocus->lifetime());
|
||||
}
|
||||
|
||||
const auto screens = QGuiApplication::screens();
|
||||
if (screens.size() > 1) {
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_settings_notifications_display());
|
||||
|
||||
const auto currentChecksum
|
||||
= Core::App().settings().notificationsDisplayChecksum();
|
||||
auto currentIndex = (currentChecksum == 0)
|
||||
? kDefaultDisplayIndex
|
||||
: 0;
|
||||
for (auto i = 0; i < screens.size(); ++i) {
|
||||
if (Platform::ScreenNameChecksum(screens[i]) == currentChecksum) {
|
||||
currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto group = std::make_shared<Ui::RadiobuttonGroup>(
|
||||
currentIndex);
|
||||
|
||||
container->add(
|
||||
object_ptr<Ui::Radiobutton>(
|
||||
container,
|
||||
group,
|
||||
kDefaultDisplayIndex,
|
||||
tr::lng_settings_notifications_display_default(tr::now),
|
||||
st::settingsSendType),
|
||||
st::settingsSendTypePadding);
|
||||
|
||||
for (auto i = 0; i < screens.size(); ++i) {
|
||||
const auto &screen = screens[i];
|
||||
const auto name = Platform::ScreenDisplayLabel(screen);
|
||||
const auto geometry = screen->geometry();
|
||||
const auto resolution = QString::number(geometry.width())
|
||||
+ QChar(0x00D7)
|
||||
+ QString::number(geometry.height());
|
||||
const auto label = name.isEmpty()
|
||||
? QString("Display (%1)").arg(resolution)
|
||||
: QString("%1 (%2)").arg(name).arg(resolution);
|
||||
container->add(
|
||||
object_ptr<Ui::Radiobutton>(
|
||||
container,
|
||||
group,
|
||||
i,
|
||||
label,
|
||||
st::settingsSendType),
|
||||
st::settingsSendTypePadding);
|
||||
}
|
||||
group->setChangedCallback([=](int selectedIndex) {
|
||||
if (selectedIndex == kDefaultDisplayIndex) {
|
||||
Core::App().settings().setNotificationsDisplayChecksum(0);
|
||||
Core::App().saveSettings();
|
||||
Core::App().notifications().notifySettingsChanged(
|
||||
ChangeType::Corner);
|
||||
} else {
|
||||
const auto screens = QGuiApplication::screens();
|
||||
if (selectedIndex >= 0 && selectedIndex < screens.size()) {
|
||||
const auto checksum = Platform::ScreenNameChecksum(
|
||||
screens[selectedIndex]);
|
||||
Core::App().settings().setNotificationsDisplayChecksum(
|
||||
checksum);
|
||||
Core::App().saveSettings();
|
||||
Core::App().notifications().notifySettingsChanged(
|
||||
ChangeType::Corner);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_settings_notifications_position());
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
|
||||
const auto position = container->add(
|
||||
object_ptr<NotificationsCount>(container, controller));
|
||||
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(container, tr::lng_settings_notifications_count());
|
||||
|
||||
const auto count = container->add(
|
||||
object_ptr<Ui::SettingsSlider>(container, st::settingsSlider),
|
||||
st::settingsBigScalePadding);
|
||||
for (int i = 0; i != kMaxNotificationsCount; ++i) {
|
||||
count->addSection(QString::number(i + 1));
|
||||
}
|
||||
count->setActiveSectionFast(CurrentCount() - 1);
|
||||
count->sectionActivated(
|
||||
) | rpl::on_next([=](int section) {
|
||||
position->setCount(section + 1);
|
||||
}, count->lifetime());
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
}
|
||||
|
||||
void SetupMultiAccountNotifications(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container) {
|
||||
if (Core::App().domain().accounts().size() < 2) {
|
||||
return;
|
||||
}
|
||||
Ui::AddSubsectionTitle(container, tr::lng_settings_show_from());
|
||||
|
||||
const auto fromAll = container->add(object_ptr<Button>(
|
||||
container,
|
||||
tr::lng_settings_notify_all(),
|
||||
st::settingsButtonNoIcon
|
||||
))->toggleOn(rpl::single(Core::App().settings().notifyFromAll()));
|
||||
fromAll->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().notifyFromAll());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setNotifyFromAll(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (!checked) {
|
||||
auto ¬ifications = Core::App().notifications();
|
||||
const auto &list = Core::App().domain().accounts();
|
||||
for (const auto &[index, account] : list) {
|
||||
if (account.get() == &Core::App().domain().active()) {
|
||||
continue;
|
||||
} else if (const auto session = account->maybeSession()) {
|
||||
notifications.clearFromSession(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, fromAll->lifetime());
|
||||
|
||||
Ui::AddSkip(container);
|
||||
Ui::AddDividerText(container, tr::lng_settings_notify_all_about());
|
||||
Ui::AddSkip(container);
|
||||
}
|
||||
|
||||
void SetupNotificationsContent(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(Type)> showOther) {
|
||||
using namespace rpl::mappers;
|
||||
|
||||
Ui::AddSkip(container, st::settingsPrivacySkip);
|
||||
|
||||
using NotifyView = Core::Settings::NotifyView;
|
||||
SetupMultiAccountNotifications(controller, container);
|
||||
|
||||
AddSubsectionTitle(container, tr::lng_settings_notify_global());
|
||||
|
||||
const auto session = &controller->session();
|
||||
const auto checkbox = [&](
|
||||
rpl::producer<QString> label,
|
||||
IconDescriptor &&descriptor,
|
||||
rpl::producer<bool> checked) {
|
||||
auto result = CreateButtonWithIcon(
|
||||
container,
|
||||
std::move(label),
|
||||
st::settingsButton,
|
||||
std::move(descriptor)
|
||||
);
|
||||
result->toggleOn(std::move(checked));
|
||||
return result;
|
||||
};
|
||||
const auto addCheckbox = [&](
|
||||
rpl::producer<QString> label,
|
||||
IconDescriptor &&descriptor,
|
||||
rpl::producer<bool> checked) {
|
||||
return container->add(
|
||||
checkbox(
|
||||
std::move(label),
|
||||
std::move(descriptor),
|
||||
std::move(checked)));
|
||||
};
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto desktopToggles = container->lifetime(
|
||||
).make_state<rpl::event_stream<bool>>();
|
||||
const auto desktop = addCheckbox(
|
||||
tr::lng_settings_desktop_notify(),
|
||||
{ &st::menuIconNotifications },
|
||||
desktopToggles->events_starting_with(settings.desktopNotify()));
|
||||
|
||||
const auto flashbounceToggles = container->lifetime(
|
||||
).make_state<rpl::event_stream<bool>>();
|
||||
const auto flashbounce = addCheckbox(
|
||||
(Platform::IsWindows()
|
||||
? tr::lng_settings_alert_windows
|
||||
: Platform::IsMac()
|
||||
? tr::lng_settings_alert_mac
|
||||
: tr::lng_settings_alert_linux)(),
|
||||
{ &st::menuIconDockBounce },
|
||||
flashbounceToggles->events_starting_with(
|
||||
settings.flashBounceNotify()));
|
||||
|
||||
const auto soundAllowed = container->lifetime(
|
||||
).make_state<rpl::event_stream<bool>>();
|
||||
const auto allowed = [=] {
|
||||
return Core::App().settings().soundNotify();
|
||||
};
|
||||
const auto sound = addCheckbox(
|
||||
tr::lng_settings_sound_allowed(),
|
||||
{ &st::menuIconUnmute },
|
||||
soundAllowed->events_starting_with(allowed()));
|
||||
|
||||
Ui::AddRingtonesVolumeSlider(
|
||||
container,
|
||||
rpl::single(true),
|
||||
tr::lng_settings_master_volume_notifications(),
|
||||
Data::VolumeController{
|
||||
.volume = []() -> ushort {
|
||||
const auto volume
|
||||
= Core::App().settings().notificationsVolume();
|
||||
return volume ? volume : 100;
|
||||
},
|
||||
.saveVolume = [=](ushort volume) {
|
||||
Core::App().notifications().playSound(
|
||||
session,
|
||||
0,
|
||||
volume / 100.);
|
||||
Core::App().settings().setNotificationsVolume(volume);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}});
|
||||
|
||||
Ui::AddSkip(container);
|
||||
|
||||
const auto checkboxes = SetupNotifyViewOptions(
|
||||
controller,
|
||||
container,
|
||||
(settings.notifyView() <= NotifyView::ShowName),
|
||||
(settings.notifyView() <= NotifyView::ShowPreview));
|
||||
const auto name = checkboxes.name;
|
||||
const auto preview = checkboxes.preview;
|
||||
const auto previewWrap = checkboxes.wrap;
|
||||
const auto previewDivider = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::BoxContentDivider>>(
|
||||
container,
|
||||
object_ptr<Ui::BoxContentDivider>(container)));
|
||||
previewWrap->toggle(settings.desktopNotify(), anim::type::instant);
|
||||
previewDivider->toggle(!settings.desktopNotify(), anim::type::instant);
|
||||
|
||||
controller->session().data().notifySettings().loadExceptions();
|
||||
|
||||
Ui::AddSkip(container, st::notifyPreviewBottomSkip);
|
||||
Ui::AddSubsectionTitle(container, tr::lng_settings_notify_title());
|
||||
const auto addType = [&](Data::DefaultNotify type) {
|
||||
AddTypeButton(container, controller, type, showOther);
|
||||
};
|
||||
addType(Data::DefaultNotify::User);
|
||||
addType(Data::DefaultNotify::Group);
|
||||
addType(Data::DefaultNotify::Broadcast);
|
||||
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(container, tr::lng_settings_events_title());
|
||||
|
||||
auto joinSilent = rpl::single(
|
||||
session->api().contactSignupSilentCurrent().value_or(false)
|
||||
) | rpl::then(session->api().contactSignupSilent());
|
||||
const auto joined = addCheckbox(
|
||||
tr::lng_settings_events_joined(),
|
||||
{ &st::menuIconInvite },
|
||||
std::move(joinSilent) | rpl::map(!_1));
|
||||
joined->toggledChanges(
|
||||
) | rpl::filter([=](bool enabled) {
|
||||
const auto silent = session->api().contactSignupSilentCurrent();
|
||||
return (enabled == silent.value_or(false));
|
||||
}) | rpl::on_next([=](bool enabled) {
|
||||
session->api().saveContactSignupSilent(!enabled);
|
||||
}, joined->lifetime());
|
||||
|
||||
const auto pinned = addCheckbox(
|
||||
tr::lng_settings_events_pinned(),
|
||||
{ &st::menuIconPin },
|
||||
rpl::single(
|
||||
settings.notifyAboutPinned()
|
||||
) | rpl::then(settings.notifyAboutPinnedChanges()));
|
||||
pinned->toggledChanges(
|
||||
) | rpl::filter([=](bool notify) {
|
||||
return (notify != Core::App().settings().notifyAboutPinned());
|
||||
}) | rpl::on_next([=](bool notify) {
|
||||
Core::App().settings().setNotifyAboutPinned(notify);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}, joined->lifetime());
|
||||
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(
|
||||
container,
|
||||
tr::lng_settings_notifications_calls_title());
|
||||
const auto authorizations = &session->api().authorizations();
|
||||
// Request valid value of calls disabled flag.
|
||||
authorizations->reload();
|
||||
const auto acceptCalls = addCheckbox(
|
||||
tr::lng_settings_call_accept_calls(),
|
||||
{ &st::menuIconCallsReceive },
|
||||
authorizations->callsDisabledHereValue() | rpl::map(!_1));
|
||||
acceptCalls->toggledChanges(
|
||||
) | rpl::filter([=](bool toggled) {
|
||||
return (toggled == authorizations->callsDisabledHere());
|
||||
}) | rpl::on_next([=](bool toggled) {
|
||||
authorizations->toggleCallsDisabledHere(!toggled);
|
||||
}, container->lifetime());
|
||||
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(container, tr::lng_settings_badge_title());
|
||||
|
||||
const auto muted = container->add(object_ptr<Button>(
|
||||
container,
|
||||
tr::lng_settings_include_muted(),
|
||||
st::settingsButtonNoIcon));
|
||||
muted->toggleOn(rpl::single(settings.includeMutedCounter()));
|
||||
const auto mutedFolders = session->data().chatsFilters().has()
|
||||
? container->add(object_ptr<Button>(
|
||||
container,
|
||||
tr::lng_settings_include_muted_folders(),
|
||||
st::settingsButtonNoIcon))
|
||||
: nullptr;
|
||||
if (mutedFolders) {
|
||||
mutedFolders->toggleOn(
|
||||
rpl::single(settings.includeMutedCounterFolders()));
|
||||
}
|
||||
const auto count = container->add(object_ptr<Button>(
|
||||
container,
|
||||
tr::lng_settings_count_unread(),
|
||||
st::settingsButtonNoIcon));
|
||||
count->toggleOn(rpl::single(settings.countUnreadMessages()));
|
||||
|
||||
auto nativeText = [&] {
|
||||
if (!Platform::Notifications::Supported()
|
||||
|| Core::App().notifications().nativeEnforced()) {
|
||||
return rpl::producer<QString>();
|
||||
} else if (Platform::IsWindows()) {
|
||||
return tr::lng_settings_use_windows();
|
||||
}
|
||||
return tr::lng_settings_use_native_notifications();
|
||||
}();
|
||||
const auto native = [&]() -> Ui::SettingsButton* {
|
||||
if (!nativeText) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddDivider(container);
|
||||
Ui::AddSkip(container, st::settingsCheckboxesSkip);
|
||||
Ui::AddSubsectionTitle(container, tr::lng_settings_native_title());
|
||||
return container->add(object_ptr<Button>(
|
||||
container,
|
||||
std::move(nativeText),
|
||||
st::settingsButtonNoIcon
|
||||
))->toggleOn(rpl::single(settings.nativeNotifications()));
|
||||
}();
|
||||
|
||||
const auto advancedSlide = !Core::App().notifications().nativeEnforced()
|
||||
? container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
container,
|
||||
object_ptr<Ui::VerticalLayout>(container)))
|
||||
: nullptr;
|
||||
const auto advancedWrap = advancedSlide
|
||||
? advancedSlide->entity()
|
||||
: nullptr;
|
||||
if (advancedWrap) {
|
||||
SetupAdvancedNotifications(controller, advancedWrap);
|
||||
}
|
||||
|
||||
if (native && advancedSlide && settings.nativeNotifications()) {
|
||||
advancedSlide->hide(anim::type::instant);
|
||||
}
|
||||
|
||||
using Change = Window::Notifications::ChangeType;
|
||||
const auto changed = [=](Change change) {
|
||||
Core::App().saveSettingsDelayed();
|
||||
Core::App().notifications().notifySettingsChanged(change);
|
||||
};
|
||||
desktop->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().desktopNotify());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setDesktopNotify(checked);
|
||||
changed(Change::DesktopEnabled);
|
||||
}, desktop->lifetime());
|
||||
|
||||
sound->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().soundNotify());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setSoundNotify(checked);
|
||||
changed(Change::SoundEnabled);
|
||||
}, sound->lifetime());
|
||||
|
||||
name->checkedChanges(
|
||||
) | rpl::map([=](bool checked) {
|
||||
if (!checked) {
|
||||
preview->setChecked(false);
|
||||
return NotifyView::ShowNothing;
|
||||
} else if (!preview->checked()) {
|
||||
return NotifyView::ShowName;
|
||||
}
|
||||
return NotifyView::ShowPreview;
|
||||
}) | rpl::filter([=](NotifyView value) {
|
||||
return (value != Core::App().settings().notifyView());
|
||||
}) | rpl::on_next([=](NotifyView value) {
|
||||
Core::App().settings().setNotifyView(value);
|
||||
changed(Change::ViewParams);
|
||||
}, name->lifetime());
|
||||
|
||||
preview->checkedChanges(
|
||||
) | rpl::map([=](bool checked) {
|
||||
if (checked) {
|
||||
name->setChecked(true);
|
||||
return NotifyView::ShowPreview;
|
||||
} else if (name->checked()) {
|
||||
return NotifyView::ShowName;
|
||||
}
|
||||
return NotifyView::ShowNothing;
|
||||
}) | rpl::filter([=](NotifyView value) {
|
||||
return (value != Core::App().settings().notifyView());
|
||||
}) | rpl::on_next([=](NotifyView value) {
|
||||
Core::App().settings().setNotifyView(value);
|
||||
changed(Change::ViewParams);
|
||||
}, preview->lifetime());
|
||||
|
||||
flashbounce->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().flashBounceNotify());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setFlashBounceNotify(checked);
|
||||
changed(Change::FlashBounceEnabled);
|
||||
}, flashbounce->lifetime());
|
||||
|
||||
muted->toggledChanges(
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != Core::App().settings().includeMutedCounter());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setIncludeMutedCounter(checked);
|
||||
changed(Change::IncludeMuted);
|
||||
}, muted->lifetime());
|
||||
|
||||
if (mutedFolders) {
|
||||
mutedFolders->toggledChanges(
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked
|
||||
!= Core::App().settings().includeMutedCounterFolders());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setIncludeMutedCounterFolders(checked);
|
||||
changed(Change::IncludeMuted);
|
||||
}, mutedFolders->lifetime());
|
||||
}
|
||||
|
||||
count->toggledChanges(
|
||||
) | rpl::filter([=](bool checked) {
|
||||
return (checked != Core::App().settings().countUnreadMessages());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setCountUnreadMessages(checked);
|
||||
changed(Change::CountMessages);
|
||||
}, count->lifetime());
|
||||
|
||||
Core::App().notifications().settingsChanged(
|
||||
) | rpl::on_next([=](Change change) {
|
||||
if (change == Change::DesktopEnabled) {
|
||||
desktopToggles->fire(Core::App().settings().desktopNotify());
|
||||
previewWrap->toggle(
|
||||
Core::App().settings().desktopNotify(),
|
||||
anim::type::normal);
|
||||
previewDivider->toggle(
|
||||
!Core::App().settings().desktopNotify(),
|
||||
anim::type::normal);
|
||||
} else if (change == Change::ViewParams) {
|
||||
//
|
||||
} else if (change == Change::SoundEnabled) {
|
||||
soundAllowed->fire(allowed());
|
||||
} else if (change == Change::FlashBounceEnabled) {
|
||||
flashbounceToggles->fire(
|
||||
Core::App().settings().flashBounceNotify());
|
||||
}
|
||||
}, desktop->lifetime());
|
||||
|
||||
if (native) {
|
||||
native->toggledChanges(
|
||||
) | rpl::filter([](bool checked) {
|
||||
return (checked != Core::App().settings().nativeNotifications());
|
||||
}) | rpl::on_next([=](bool checked) {
|
||||
Core::App().settings().setNativeNotifications(checked);
|
||||
Core::App().saveSettingsDelayed();
|
||||
Core::App().notifications().createManager();
|
||||
|
||||
if (advancedSlide) {
|
||||
advancedSlide->toggle(
|
||||
!Core::App().settings().nativeNotifications(),
|
||||
anim::type::normal);
|
||||
}
|
||||
}, native->lifetime());
|
||||
}
|
||||
}
|
||||
|
||||
void SetupNotifications(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(Type)> showOther) {
|
||||
SetupNotificationsContent(controller, container, std::move(showOther));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Notifications::Notifications(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller)
|
||||
@@ -1421,7 +808,10 @@ void Notifications::setupContent(
|
||||
not_null<Window::SessionController*> controller) {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
SetupNotifications(controller, content, showOtherMethod());
|
||||
Builder::BuildNotificationsSection(
|
||||
content,
|
||||
controller,
|
||||
showOtherMethod());
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "settings/settings_common_session.h"
|
||||
|
||||
namespace Ui {
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Settings {
|
||||
|
||||
class Notifications : public Section<Notifications> {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "base/object_ptr.h"
|
||||
#include "core/core_settings.h"
|
||||
#include "settings/settings_type.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace Ui {
|
||||
class Checkbox;
|
||||
class VerticalLayout;
|
||||
template <typename Widget>
|
||||
class SlideWrap;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Data {
|
||||
enum class DefaultNotify : uint8_t;
|
||||
} // namespace Data
|
||||
|
||||
namespace Settings {
|
||||
|
||||
constexpr auto kMaxNotificationsCount = 5;
|
||||
|
||||
[[nodiscard]] int CurrentNotificationsCount();
|
||||
|
||||
class NotificationsCount : public Ui::RpWidget {
|
||||
public:
|
||||
NotificationsCount(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller);
|
||||
|
||||
void setCount(int count);
|
||||
|
||||
~NotificationsCount();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
void leaveEventHook(QEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
int resizeGetHeight(int newWidth) override;
|
||||
|
||||
private:
|
||||
using ScreenCorner = Core::Settings::ScreenCorner;
|
||||
void setOverCorner(ScreenCorner corner);
|
||||
void clearOverCorner();
|
||||
|
||||
class SampleWidget;
|
||||
void removeSample(SampleWidget *widget);
|
||||
|
||||
QRect getScreenRect() const;
|
||||
QRect getScreenRect(int width) const;
|
||||
int getContentLeft() const;
|
||||
void prepareNotificationSampleSmall();
|
||||
void prepareNotificationSampleLarge();
|
||||
void prepareNotificationSampleUserpic();
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
|
||||
QPixmap _notificationSampleUserpic;
|
||||
QPixmap _notificationSampleSmall;
|
||||
QPixmap _notificationSampleLarge;
|
||||
ScreenCorner _chosenCorner;
|
||||
std::vector<Ui::Animations::Simple> _sampleOpacities;
|
||||
|
||||
bool _isOverCorner = false;
|
||||
ScreenCorner _overCorner = ScreenCorner::TopLeft;
|
||||
bool _isDownCorner = false;
|
||||
ScreenCorner _downCorner = ScreenCorner::TopLeft;
|
||||
|
||||
int _oldCount;
|
||||
|
||||
std::vector<SampleWidget*> _cornerSamples[4];
|
||||
|
||||
};
|
||||
|
||||
struct NotifyViewCheckboxes {
|
||||
not_null<Ui::SlideWrap<Ui::RpWidget>*> wrap;
|
||||
not_null<Ui::Checkbox*> name;
|
||||
not_null<Ui::Checkbox*> preview;
|
||||
};
|
||||
|
||||
[[nodiscard]] NotifyViewCheckboxes SetupNotifyViewOptions(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
bool nameShown,
|
||||
bool previewShown);
|
||||
|
||||
void AddTypeButton(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Data::DefaultNotify type,
|
||||
Fn<void(Type)> showOther);
|
||||
|
||||
} // namespace Settings
|
||||
Reference in New Issue
Block a user