| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323 |
- /*
- 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/settings_notifications.h"
- #include "settings/settings_notifications_type.h"
- #include "ui/boxes/confirm_box.h"
- #include "ui/controls/chat_service_checkbox.h"
- #include "ui/effects/animations.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 "lang/lang_keys.h"
- #include "window/notifications_manager.h"
- #include "window/window_session_controller.h"
- #include "window/section_widget.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_layers.h"
- #include "styles/style_menu_icons.h"
- #include "styles/style_chat.h"
- #include "styles/style_window.h"
- #include "styles/style_dialogs.h"
- #include <QSvgRenderer>
- namespace Settings {
- namespace {
- constexpr auto kMaxNotificationsCount = 5;
- [[nodiscard]] int CurrentCount() {
- 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);
- void detach();
- void showFast();
- void hideFast();
- protected:
- void paintEvent(QPaintEvent *e) override;
- private:
- void startAnimation();
- void animationCallback();
- NotificationsCount *_owner;
- QPixmap _cache;
- Ui::Animations::Simple _opacity;
- bool _hiding = false;
- };
- void AddTypeButton(
- not_null<Ui::VerticalLayout*> container,
- not_null<Window::SessionController*> controller,
- Data::DefaultNotify type,
- Fn<void(Type)> showOther) {
- using Type = Data::DefaultNotify;
- auto label = [&] {
- switch (type) {
- case Type::User: return tr::lng_notification_private_chats();
- case Type::Group: return tr::lng_notification_groups();
- case Type::Broadcast: return tr::lng_notification_channels();
- }
- Unexpected("Type value in AddTypeButton.");
- }();
- const auto icon = [&] {
- switch (type) {
- case Type::User: return &st::menuIconProfile;
- case Type::Group: return &st::menuIconGroups;
- case Type::Broadcast: return &st::menuIconChannel;
- }
- Unexpected("Type value in AddTypeButton.");
- }();
- const auto button = AddButtonWithIcon(
- container,
- std::move(label),
- st::settingsNotificationType,
- { icon });
- button->setClickedCallback([=] {
- showOther(NotificationsType::Id(type));
- });
- const auto session = &controller->session();
- const auto settings = &session->data().notifySettings();
- const auto &st = st::settingsNotificationType;
- auto status = rpl::combine(
- NotificationsEnabledForTypeValue(session, type),
- rpl::single(
- type
- ) | rpl::then(settings->exceptionsUpdates(
- ) | rpl::filter(rpl::mappers::_1 == type))
- ) | rpl::map([=](bool enabled, const auto &) {
- const auto count = int(settings->exceptions(type).size());
- return !count
- ? tr::lng_notification_click_to_change()
- : (enabled
- ? tr::lng_notification_on
- : tr::lng_notification_off)(
- lt_exceptions,
- tr::lng_notification_exceptions(
- lt_count,
- rpl::single(float64(count))));
- }) | rpl::flatten_latest();
- const auto details = Ui::CreateChild<Ui::FlatLabel>(
- button.get(),
- std::move(status),
- st::settingsNotificationTypeDetails);
- details->show();
- details->moveToLeft(
- st.padding.left(),
- st.padding.top() + st.height - details->height());
- details->setAttribute(Qt::WA_TransparentForMouseEvents);
- const auto toggleButton = Ui::CreateChild<Ui::SettingsButton>(
- container.get(),
- nullptr,
- st);
- const auto checkView = button->lifetime().make_state<Ui::ToggleView>(
- st.toggle,
- NotificationsEnabledForType(session, type),
- [=] { toggleButton->update(); });
- const auto separator = Ui::CreateChild<Ui::RpWidget>(container.get());
- separator->paintRequest(
- ) | rpl::start_with_next([=, bg = st.textBgOver] {
- auto p = QPainter(separator);
- p.fillRect(separator->rect(), bg);
- }, separator->lifetime());
- const auto separatorHeight = st.height - 2 * st.toggle.border;
- button->geometryValue(
- ) | rpl::start_with_next([=](const QRect &r) {
- const auto w = st::rightsButtonToggleWidth;
- toggleButton->setGeometry(
- r.x() + r.width() - w,
- r.y(),
- w,
- r.height());
- separator->setGeometry(
- toggleButton->x() - st::lineWidth,
- r.y() + (r.height() - separatorHeight) / 2,
- st::lineWidth,
- separatorHeight);
- }, toggleButton->lifetime());
- const auto checkWidget = Ui::CreateChild<Ui::RpWidget>(toggleButton);
- checkWidget->resize(checkView->getSize());
- checkWidget->paintRequest(
- ) | rpl::start_with_next([=] {
- auto p = QPainter(checkWidget);
- checkView->paint(p, 0, 0, checkWidget->width());
- }, checkWidget->lifetime());
- toggleButton->sizeValue(
- ) | rpl::start_with_next([=](const QSize &s) {
- checkWidget->moveToRight(
- st.toggleSkip,
- (s.height() - checkWidget->height()) / 2);
- }, toggleButton->lifetime());
- const auto toggle = crl::guard(toggleButton, [=] {
- const auto enabled = !checkView->checked();
- checkView->setChecked(enabled, anim::type::normal);
- settings->defaultUpdate(type, Data::MuteValue{
- .unmute = enabled,
- .forever = !enabled,
- });
- });
- toggleButton->clicks(
- ) | rpl::start_with_next([=] {
- const auto count = int(settings->exceptions(type).size());
- if (!count) {
- toggle();
- } else {
- controller->show(Box([=](not_null<Ui::GenericBox*> box) {
- const auto phrase = [&] {
- switch (type) {
- case Type::User:
- return tr::lng_notification_about_private_chats;
- case Type::Group:
- return tr::lng_notification_about_groups;
- case Type::Broadcast:
- return tr::lng_notification_about_channels;
- }
- Unexpected("Type in AddTypeButton.");
- }();
- Ui::ConfirmBox(box, {
- .text = phrase(
- lt_count,
- rpl::single(float64(count)),
- Ui::Text::RichLangValue),
- .confirmed = [=](auto close) { toggle(); close(); },
- .confirmText = tr::lng_box_ok(),
- .title = tr::lng_notification_exceptions_title(),
- .inform = true,
- });
- box->addLeftButton(
- tr::lng_notification_exceptions_view(),
- [=] {
- box->closeBox();
- showOther(NotificationsType::Id(type));
- });
- }));
- }
- }, toggleButton->lifetime());
- }
- NotificationsCount::NotificationsCount(
- QWidget *parent,
- not_null<Window::SessionController*> controller)
- : _controller(controller)
- , _chosenCorner(Core::App().settings().notificationsCorner())
- , _oldCount(CurrentCount()) {
- setMouseTracking(true);
- _sampleOpacities.resize(kMaxNotificationsCount);
- prepareNotificationSampleSmall();
- prepareNotificationSampleLarge();
- }
- void NotificationsCount::paintEvent(QPaintEvent *e) {
- Painter p(this);
- auto contentLeft = getContentLeft();
- auto screenRect = getScreenRect();
- p.fillRect(
- screenRect.x(),
- screenRect.y(),
- st::notificationsBoxScreenSize.width(),
- st::notificationsBoxScreenSize.height(),
- st::notificationsBoxScreenBg);
- auto monitorTop = 0;
- st::notificationsBoxMonitor.paint(p, contentLeft, monitorTop, width());
- for (int corner = 0; corner != 4; ++corner) {
- auto screenCorner = static_cast<ScreenCorner>(corner);
- auto isLeft = Core::Settings::IsLeftCorner(screenCorner);
- auto isTop = Core::Settings::IsTopCorner(screenCorner);
- auto sampleLeft = isLeft ? (screenRect.x() + st::notificationsSampleSkip) : (screenRect.x() + screenRect.width() - st::notificationsSampleSkip - st::notificationSampleSize.width());
- auto sampleTop = isTop ? (screenRect.y() + st::notificationsSampleTopSkip) : (screenRect.y() + screenRect.height() - st::notificationsSampleBottomSkip - st::notificationSampleSize.height());
- if (corner == static_cast<int>(_chosenCorner)) {
- auto count = _oldCount;
- for (int i = 0; i != kMaxNotificationsCount; ++i) {
- auto opacity = _sampleOpacities[i].value((i < count) ? 1. : 0.);
- p.setOpacity(opacity);
- p.drawPixmapLeft(sampleLeft, sampleTop, width(), _notificationSampleSmall);
- sampleTop += (isTop ? 1 : -1) * (st::notificationSampleSize.height() + st::notificationsSampleMargin);
- }
- p.setOpacity(1.);
- } else {
- p.setOpacity(st::notificationSampleOpacity);
- p.drawPixmapLeft(sampleLeft, sampleTop, width(), _notificationSampleSmall);
- p.setOpacity(1.);
- }
- }
- }
- void NotificationsCount::setCount(int count) {
- auto moreSamples = (count > _oldCount);
- auto from = moreSamples ? 0. : 1.;
- auto to = moreSamples ? 1. : 0.;
- auto indexDelta = moreSamples ? 1 : -1;
- auto animatedDelta = moreSamples ? 0 : -1;
- for (; _oldCount != count; _oldCount += indexDelta) {
- _sampleOpacities[_oldCount + animatedDelta].start([this] { update(); }, from, to, st::notifyFastAnim);
- }
- if (count != Core::App().settings().notificationsCount()) {
- Core::App().settings().setNotificationsCount(count);
- Core::App().saveSettingsDelayed();
- Core::App().notifications().notifySettingsChanged(
- ChangeType::MaxCount);
- }
- }
- int NotificationsCount::getContentLeft() const {
- return (width() - st::notificationsBoxMonitor.width()) / 2;
- }
- QRect NotificationsCount::getScreenRect() const {
- return getScreenRect(width());
- }
- QRect NotificationsCount::getScreenRect(int width) const {
- auto screenLeft = (width - st::notificationsBoxScreenSize.width()) / 2;
- auto screenTop = st::notificationsBoxScreenTop;
- return QRect(screenLeft, screenTop, st::notificationsBoxScreenSize.width(), st::notificationsBoxScreenSize.height());
- }
- int NotificationsCount::resizeGetHeight(int newWidth) {
- update();
- return st::notificationsBoxMonitor.height();
- }
- void NotificationsCount::prepareNotificationSampleSmall() {
- auto width = st::notificationSampleSize.width();
- auto height = st::notificationSampleSize.height();
- auto sampleImage = QImage(
- QSize(width, height) * style::DevicePixelRatio(),
- QImage::Format_ARGB32_Premultiplied);
- sampleImage.setDevicePixelRatio(style::DevicePixelRatio());
- sampleImage.fill(st::notificationBg->c);
- {
- Painter p(&sampleImage);
- PainterHighQualityEnabler hq(p);
- p.setPen(Qt::NoPen);
- auto padding = height / 8;
- auto userpicSize = height - 2 * padding;
- p.setBrush(st::notificationSampleUserpicFg);
- p.drawEllipse(style::rtlrect(padding, padding, userpicSize, userpicSize, width));
- auto rowLeft = height;
- auto rowHeight = padding;
- auto nameTop = (height - 5 * padding) / 2;
- auto nameWidth = height;
- p.setBrush(st::notificationSampleNameFg);
- p.drawRoundedRect(style::rtlrect(rowLeft, nameTop, nameWidth, rowHeight, width), rowHeight / 2, rowHeight / 2);
- auto rowWidth = (width - rowLeft - 3 * padding);
- auto rowTop = nameTop + rowHeight + padding;
- p.setBrush(st::notificationSampleTextFg);
- p.drawRoundedRect(style::rtlrect(rowLeft, rowTop, rowWidth, rowHeight, width), rowHeight / 2, rowHeight / 2);
- rowTop += rowHeight + padding;
- p.drawRoundedRect(style::rtlrect(rowLeft, rowTop, rowWidth, rowHeight, width), rowHeight / 2, rowHeight / 2);
- auto closeLeft = width - 2 * padding;
- p.fillRect(style::rtlrect(closeLeft, padding, padding, padding, width), st::notificationSampleCloseFg);
- }
- _notificationSampleSmall = Ui::PixmapFromImage(std::move(sampleImage));
- _notificationSampleSmall.setDevicePixelRatio(style::DevicePixelRatio());
- }
- void NotificationsCount::prepareNotificationSampleUserpic() {
- if (_notificationSampleUserpic.isNull()) {
- _notificationSampleUserpic = Ui::PixmapFromImage(
- Window::LogoNoMargin().scaled(
- st::notifyPhotoSize * style::DevicePixelRatio(),
- st::notifyPhotoSize * style::DevicePixelRatio(),
- Qt::IgnoreAspectRatio,
- Qt::SmoothTransformation));
- _notificationSampleUserpic.setDevicePixelRatio(
- style::DevicePixelRatio());
- }
- }
- void NotificationsCount::prepareNotificationSampleLarge() {
- int w = st::notifyWidth, h = st::notifyMinHeight;
- auto sampleImage = QImage(
- w * style::DevicePixelRatio(),
- h * style::DevicePixelRatio(),
- QImage::Format_ARGB32_Premultiplied);
- sampleImage.setDevicePixelRatio(style::DevicePixelRatio());
- sampleImage.fill(st::notificationBg->c);
- {
- Painter p(&sampleImage);
- p.fillRect(0, 0, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
- p.fillRect(w - st::notifyBorderWidth, 0, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
- p.fillRect(st::notifyBorderWidth, h - st::notifyBorderWidth, w - st::notifyBorderWidth, st::notifyBorderWidth, st::notifyBorder->b);
- p.fillRect(0, st::notifyBorderWidth, st::notifyBorderWidth, h - st::notifyBorderWidth, st::notifyBorder->b);
- prepareNotificationSampleUserpic();
- p.drawPixmap(st::notifyPhotoPos.x(), st::notifyPhotoPos.y(), _notificationSampleUserpic);
- int itemWidth = w - st::notifyPhotoPos.x() - st::notifyPhotoSize - st::notifyTextLeft - st::notifyClosePos.x() - st::notifyClose.width;
- auto rectForName = style::rtlrect(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyTextTop, itemWidth, st::msgNameFont->height, w);
- auto notifyText = st::dialogsTextFont->elided(tr::lng_notification_sample(tr::now), itemWidth);
- p.setFont(st::dialogsTextFont);
- p.setPen(st::dialogsTextFgService);
- p.drawText(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height + st::dialogsTextFont->ascent, notifyText);
- p.setPen(st::dialogsNameFg);
- p.setFont(st::msgNameFont);
- auto notifyTitle = st::msgNameFont->elided(u"Telegram Desktop"_q, rectForName.width());
- p.drawText(rectForName.left(), rectForName.top() + st::msgNameFont->ascent, notifyTitle);
- st::notifyClose.icon.paint(p, w - st::notifyClosePos.x() - st::notifyClose.width + st::notifyClose.iconPosition.x(), st::notifyClosePos.y() + st::notifyClose.iconPosition.y(), w);
- }
- _notificationSampleLarge = Ui::PixmapFromImage(std::move(sampleImage));
- }
- void NotificationsCount::removeSample(SampleWidget *widget) {
- for (auto &samples : _cornerSamples) {
- for (int i = 0, size = samples.size(); i != size; ++i) {
- if (samples[i] == widget) {
- for (int j = i + 1; j != size; ++j) {
- samples[j]->detach();
- }
- samples.resize(i);
- break;
- }
- }
- }
- }
- void NotificationsCount::mouseMoveEvent(QMouseEvent *e) {
- auto screenRect = getScreenRect();
- auto cornerWidth = screenRect.width() / 3;
- auto cornerHeight = screenRect.height() / 3;
- auto topLeft = style::rtlrect(screenRect.x(), screenRect.y(), cornerWidth, cornerHeight, width());
- auto topRight = style::rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y(), cornerWidth, cornerHeight, width());
- auto bottomRight = style::rtlrect(screenRect.x() + screenRect.width() - cornerWidth, screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
- auto bottomLeft = style::rtlrect(screenRect.x(), screenRect.y() + screenRect.height() - cornerHeight, cornerWidth, cornerHeight, width());
- if (topLeft.contains(e->pos())) {
- setOverCorner(ScreenCorner::TopLeft);
- } else if (topRight.contains(e->pos())) {
- setOverCorner(ScreenCorner::TopRight);
- } else if (bottomRight.contains(e->pos())) {
- setOverCorner(ScreenCorner::BottomRight);
- } else if (bottomLeft.contains(e->pos())) {
- setOverCorner(ScreenCorner::BottomLeft);
- } else {
- clearOverCorner();
- }
- }
- void NotificationsCount::leaveEventHook(QEvent *e) {
- clearOverCorner();
- }
- void NotificationsCount::setOverCorner(ScreenCorner corner) {
- if (_isOverCorner) {
- if (corner == _overCorner) {
- return;
- }
- const auto index = static_cast<int>(_overCorner);
- for (const auto widget : _cornerSamples[index]) {
- widget->hideFast();
- }
- } else {
- _isOverCorner = true;
- setCursor(style::cur_pointer);
- Core::App().notifications().notifySettingsChanged(
- ChangeType::DemoIsShown);
- }
- _overCorner = corner;
- auto &samples = _cornerSamples[static_cast<int>(_overCorner)];
- auto samplesAlready = int(samples.size());
- auto samplesNeeded = _oldCount;
- auto samplesLeave = qMin(samplesAlready, samplesNeeded);
- for (int i = 0; i != samplesLeave; ++i) {
- samples[i]->showFast();
- }
- if (samplesNeeded > samplesLeave) {
- auto r = _controller->widget()->desktopRect();
- auto isLeft = Core::Settings::IsLeftCorner(_overCorner);
- auto isTop = Core::Settings::IsTopCorner(_overCorner);
- auto sampleLeft = (isLeft == rtl()) ? (r.x() + r.width() - st::notifyWidth - st::notifyDeltaX) : (r.x() + st::notifyDeltaX);
- auto sampleTop = isTop ? (r.y() + st::notifyDeltaY) : (r.y() + r.height() - st::notifyDeltaY - st::notifyMinHeight);
- for (int i = samplesLeave; i != samplesNeeded; ++i) {
- auto widget = std::make_unique<SampleWidget>(this, _notificationSampleLarge);
- widget->move(sampleLeft, sampleTop + (isTop ? 1 : -1) * i * (st::notifyMinHeight + st::notifyDeltaY));
- widget->showFast();
- samples.push_back(widget.release());
- }
- } else {
- for (int i = samplesLeave; i != samplesAlready; ++i) {
- samples[i]->hideFast();
- }
- }
- }
- void NotificationsCount::clearOverCorner() {
- if (_isOverCorner) {
- _isOverCorner = false;
- setCursor(style::cur_default);
- Core::App().notifications().notifySettingsChanged(
- ChangeType::DemoIsHidden);
- for (const auto &samples : _cornerSamples) {
- for (const auto widget : samples) {
- widget->hideFast();
- }
- }
- }
- }
- void NotificationsCount::mousePressEvent(QMouseEvent *e) {
- _isDownCorner = _isOverCorner;
- _downCorner = _overCorner;
- }
- void NotificationsCount::mouseReleaseEvent(QMouseEvent *e) {
- auto isDownCorner = base::take(_isDownCorner);
- if (isDownCorner
- && _isOverCorner
- && _downCorner == _overCorner
- && _downCorner != _chosenCorner) {
- _chosenCorner = _downCorner;
- update();
- if (_chosenCorner != Core::App().settings().notificationsCorner()) {
- Core::App().settings().setNotificationsCorner(_chosenCorner);
- Core::App().saveSettingsDelayed();
- Core::App().notifications().notifySettingsChanged(
- ChangeType::Corner);
- }
- }
- }
- NotificationsCount::~NotificationsCount() {
- for (const auto &samples : _cornerSamples) {
- for (const auto widget : samples) {
- widget->detach();
- }
- }
- clearOverCorner();
- }
- NotificationsCount::SampleWidget::SampleWidget(
- NotificationsCount *owner,
- const QPixmap &cache)
- : _owner(owner)
- , _cache(cache) {
- setFixedSize(
- cache.width() / cache.devicePixelRatio(),
- cache.height() / cache.devicePixelRatio());
- setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint)
- | Qt::WindowStaysOnTopHint
- | Qt::BypassWindowManagerHint
- | Qt::NoDropShadowWindowHint
- | Qt::Tool);
- setAttribute(Qt::WA_MacAlwaysShowToolWindow);
- setAttribute(Qt::WA_TransparentForMouseEvents);
- setAttribute(Qt::WA_OpaquePaintEvent);
- setWindowOpacity(0.);
- show();
- }
- void NotificationsCount::SampleWidget::detach() {
- _owner = nullptr;
- hideFast();
- }
- void NotificationsCount::SampleWidget::showFast() {
- _hiding = false;
- startAnimation();
- }
- void NotificationsCount::SampleWidget::hideFast() {
- _hiding = true;
- startAnimation();
- }
- void NotificationsCount::SampleWidget::paintEvent(QPaintEvent *e) {
- Painter p(this);
- p.drawPixmap(0, 0, _cache);
- }
- void NotificationsCount::SampleWidget::startAnimation() {
- _opacity.start(
- [=] { animationCallback(); },
- _hiding ? 1. : 0.,
- _hiding ? 0. : 1.,
- st::notifyFastAnim);
- }
- void NotificationsCount::SampleWidget::animationCallback() {
- setWindowOpacity(_opacity.value(_hiding ? 0. : 1.));
- if (!_opacity.animating() && _hiding) {
- if (_owner) {
- _owner->removeSample(this);
- }
- hide();
- deleteLater();
- }
- }
- class NotifyPreview final {
- public:
- NotifyPreview(bool nameShown, bool previewShown);
- void setNameShown(bool shown);
- void setPreviewShown(bool shown);
- int resizeGetHeight(int newWidth);
- void paint(Painter &p, int x, int y);
- private:
- int _width = 0;
- int _height = 0;
- bool _nameShown = false;
- bool _previewShown = false;
- Ui::RoundRect _roundRect;
- Ui::Text::String _name, _title;
- Ui::Text::String _text, _preview;
- QSvgRenderer _userpic;
- QImage _logo;
- };
- NotifyPreview::NotifyPreview(bool nameShown, bool previewShown)
- : _nameShown(nameShown)
- , _previewShown(previewShown)
- , _roundRect(st::boxRadius, st::msgInBg)
- , _userpic(u":/gui/icons/settings/dino.svg"_q)
- , _logo(Window::LogoNoMargin()) {
- const auto ratio = style::DevicePixelRatio();
- _logo = _logo.scaledToWidth(
- st::notifyPreviewUserpicSize * ratio,
- Qt::SmoothTransformation);
- _logo.setDevicePixelRatio(ratio);
- _name.setText(
- st::defaultSubsectionTitle.style,
- tr::lng_notification_preview_title(tr::now));
- _title.setText(st::defaultSubsectionTitle.style, AppName.utf16());
- _text.setText(
- st::boxTextStyle,
- tr::lng_notification_preview_text(tr::now));
- _preview.setText(
- st::boxTextStyle,
- tr::lng_notification_preview(tr::now));
- }
- void NotifyPreview::setNameShown(bool shown) {
- _nameShown = shown;
- }
- void NotifyPreview::setPreviewShown(bool shown) {
- _previewShown = shown;
- }
- int NotifyPreview::resizeGetHeight(int newWidth) {
- _width = newWidth;
- _height = st::notifyPreviewUserpicPosition.y()
- + st::notifyPreviewUserpicSize
- + st::notifyPreviewUserpicPosition.y();
- const auto available = _width
- - st::notifyPreviewTextPosition.x()
- - st::notifyPreviewUserpicPosition.x();
- if (std::max(_text.maxWidth(), _preview.maxWidth()) >= available) {
- _height += st::defaultTextStyle.font->height;
- }
- return _height;
- }
- void NotifyPreview::paint(Painter &p, int x, int y) {
- if (!_width || !_height) {
- return;
- }
- p.translate(x, y);
- const auto guard = gsl::finally([&] { p.translate(-x, -y); });
- _roundRect.paint(p, { 0, 0, _width, _height });
- const auto userpic = QRect(
- st::notifyPreviewUserpicPosition,
- QSize{ st::notifyPreviewUserpicSize, st::notifyPreviewUserpicSize });
- if (_nameShown) {
- _userpic.render(&p, QRectF(userpic));
- } else {
- p.drawImage(userpic.topLeft(), _logo);
- }
- p.setPen(st::historyTextInFg);
- const auto &title = _nameShown ? _name : _title;
- title.drawElided(
- p,
- st::notifyPreviewTitlePosition.x(),
- st::notifyPreviewTitlePosition.y(),
- _width - st::notifyPreviewTitlePosition.x() - userpic.x());
- const auto &text = _previewShown ? _text : _preview;
- text.drawElided(
- p,
- st::notifyPreviewTextPosition.x(),
- st::notifyPreviewTextPosition.y(),
- _width - st::notifyPreviewTextPosition.x() - userpic.x(),
- 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,
- bool nameShown,
- bool previewShown) {
- using namespace rpl::mappers;
- auto wrap = container->add(object_ptr<Ui::SlideWrap<>>(
- container,
- object_ptr<Ui::RpWidget>(container)));
- const auto widget = wrap->entity();
- const auto makeCheckbox = [&](const QString &text, bool checked) {
- return Ui::MakeChatServiceCheckbox(
- widget,
- text,
- st::backgroundCheckbox,
- st::backgroundCheck,
- checked).release();
- };
- const auto name = makeCheckbox(
- tr::lng_notification_show_name(tr::now),
- nameShown);
- const auto preview = makeCheckbox(
- tr::lng_notification_show_text(tr::now),
- previewShown);
- const auto view = widget->lifetime().make_state<NotifyPreview>(
- nameShown,
- previewShown);
- widget->widthValue(
- ) | rpl::filter(
- _1 >= (st::historyMinimalWidth / 2)
- ) | rpl::start_with_next([=](int width) {
- const auto margins = st::notifyPreviewMargins;
- const auto bubblew = width - margins.left() - margins.right();
- const auto bubbleh = view->resizeGetHeight(bubblew);
- const auto height = bubbleh + margins.top() + margins.bottom();
- widget->resize(width, height);
- const auto skip = st::notifyPreviewChecksSkip;
- const auto checksWidth = name->width() + skip + preview->width();
- const auto checksLeft = (width - checksWidth) / 2;
- const auto checksTop = height
- - (margins.bottom() + name->height()) / 2;
- name->move(checksLeft, checksTop);
- preview->move(checksLeft + name->width() + skip, checksTop);
- }, widget->lifetime());
- widget->paintRequest(
- ) | rpl::start_with_next([=](QRect rect) {
- Window::SectionWidget::PaintBackground(
- controller,
- controller->defaultChatTheme().get(), // #TODO themes
- widget,
- rect);
- Painter p(widget);
- view->paint(
- p,
- st::notifyPreviewMargins.left(),
- st::notifyPreviewMargins.top());
- }, widget->lifetime());
- name->checkedChanges(
- ) | rpl::start_with_next([=](bool checked) {
- view->setNameShown(checked);
- widget->update();
- }, name->lifetime());
- preview->checkedChanges(
- ) | rpl::start_with_next([=](bool checked) {
- view->setPreviewShown(checked);
- widget->update();
- }, preview->lifetime());
- return {
- .wrap = wrap,
- .name = name,
- .preview = preview,
- };
- }
- 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::start_with_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());
- }
- 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::start_with_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::start_with_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::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::start_with_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::start_with_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();
- 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::start_with_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()
- || Platform::Notifications::Enforced()) {
- 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 = !Platform::Notifications::Enforced()
- ? 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::start_with_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::start_with_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::start_with_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::start_with_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::start_with_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::start_with_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::start_with_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::start_with_next([=](bool checked) {
- Core::App().settings().setCountUnreadMessages(checked);
- changed(Change::CountMessages);
- }, count->lifetime());
- Core::App().notifications().settingsChanged(
- ) | rpl::start_with_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::start_with_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)
- : Section(parent) {
- setupContent(controller);
- }
- rpl::producer<QString> Notifications::title() {
- return tr::lng_settings_section_notify();
- }
- void Notifications::setupContent(
- not_null<Window::SessionController*> controller) {
- const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
- SetupNotifications(controller, content, showOtherMethod());
- Ui::ResizeFitChild(this, content);
- }
- } // namespace Settings
|