From efe3dfad5c3ddfb4ee06cd5580d782b0c16ed548 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 5 Dec 2018 13:55:56 +0400 Subject: [PATCH] Fix crash in radiobutton destruction. It crashed if the button was destroyed from group _changedCallback. --- Telegram/SourceFiles/boxes/connection_box.cpp | 11 ++-- .../boxes/edit_participant_box.cpp | 29 ++++++--- .../boxes/peer_list_controllers.cpp | 25 +++++--- .../export/view/export_view_settings.cpp | 21 +++---- .../admin_log/history_admin_log_filter.cpp | 63 ++++++++++++++----- .../info/profile/info_profile_cover.cpp | 4 +- .../settings/settings_advanced.cpp | 21 ++----- .../SourceFiles/settings/settings_chat.cpp | 32 +++++----- .../settings/settings_notifications.cpp | 23 +++---- Telegram/SourceFiles/ui/abstract_button.cpp | 9 ++- Telegram/SourceFiles/ui/widgets/checkbox.cpp | 27 +++++--- Telegram/SourceFiles/ui/widgets/checkbox.h | 14 +++-- .../window/window_lock_widgets.cpp | 5 +- 13 files changed, 165 insertions(+), 119 deletions(-) diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index bbe8892bb..a34056626 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -569,17 +569,20 @@ void ProxiesBox::setupContent() { } refreshProxyForCalls(); }); - subscribe(_tryIPv6->checkedChanged, [=](bool checked) { + _tryIPv6->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { _controller->setTryIPv6(checked); - }); + }, _tryIPv6->lifetime()); + _controller->proxySettingsValue( ) | rpl::start_with_next([=](ProxyData::Settings value) { _proxySettings->setValue(value); }, inner->lifetime()); - subscribe(_proxyForCalls->entity()->checkedChanged, [=](bool checked) { + _proxyForCalls->entity()->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { _controller->setProxyForCalls(checked); - }); + }, _proxyForCalls->lifetime()); if (_rows.empty()) { createNoRowsLabel(); diff --git a/Telegram/SourceFiles/boxes/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/edit_participant_box.cpp index a749a50e7..b69d406e1 100644 --- a/Telegram/SourceFiles/boxes/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_participant_box.cpp @@ -236,9 +236,12 @@ void EditAdminBox::prepare() { auto addCheckbox = [&](Flags flags, const QString &text) { const auto checked = (prepareFlags & flags) != 0; auto control = addControl(object_ptr(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin); - subscribe(control->checkedChanged, [this, control](bool checked) { - InvokeQueued(this, [this, control] { applyDependencies(control); }); - }); + control->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { + InvokeQueued(this, [=] { + applyDependencies(control); + }); + }, control->lifetime()); if (!channel()->amCreator()) { if (!(channel()->adminRights() & flags)) { control->setDisabled(true); // Grey out options that we don't have ourselves. @@ -267,11 +270,14 @@ void EditAdminBox::prepare() { auto addAdmins = _checkboxes.find(Flag::f_add_admins); if (addAdmins != _checkboxes.end()) { - _aboutAddAdmins = addControl(object_ptr(this, st::boxLabel), st::rightsAboutMargin); + _aboutAddAdmins = addControl( + object_ptr(this, st::boxLabel), + st::rightsAboutMargin); Assert(addAdmins != _checkboxes.end()); - subscribe(addAdmins->second->checkedChanged, [this](bool checked) { + addAdmins->second->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { refreshAboutAddAdminsText(); - }); + }, addAdmins->second->lifetime()); refreshAboutAddAdminsText(); } @@ -354,12 +360,15 @@ void EditRestrictedBox::prepare() { auto prepareRights = (_oldRights.c_channelBannedRights().vflags.v ? _oldRights : DefaultRights(channel())); _until = prepareRights.c_channelBannedRights().vuntil_date.v; - auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) { + auto addCheckbox = [&](Flags flags, const QString &text) { auto checked = (prepareRights.c_channelBannedRights().vflags.v & flags) == 0; auto control = addControl(object_ptr(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin); - subscribe(control->checkedChanged, [this, control](bool checked) { - InvokeQueued(this, [this, control] { applyDependencies(control); }); - }); + control->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { + InvokeQueued(this, [=] { + applyDependencies(control); + }); + }, control->lifetime()); if (!canSave()) { control->setDisabled(true); } diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 62271ef8c..4db299b98 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -127,15 +127,24 @@ void AddBotToGroup(not_null bot, not_null chat) { // return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; //} -class EditChatAdminsBoxController::LabeledCheckbox : public TWidget, private base::Subscriber { +class EditChatAdminsBoxController::LabeledCheckbox : public Ui::RpWidget { public: - LabeledCheckbox(QWidget *parent, const QString &text, bool checked = false, const style::Checkbox &st = st::defaultCheckbox, const style::Check &checkSt = st::defaultCheck); - - base::Observable checkedChanged; + LabeledCheckbox( + QWidget *parent, + const QString &text, + bool checked = false, + const style::Checkbox &st = st::defaultCheckbox, + const style::Check &checkSt = st::defaultCheck); bool checked() const { return _checkbox->checked(); } + rpl::producer checkedChanges() const { + return _checkbox->checkedChanges(); + } + rpl::producer checkedValue() const { + return _checkbox->checkedValue(); + } void setLabelText( bool checked, @@ -605,9 +614,8 @@ EditChatAdminsBoxController::LabeledCheckbox::LabeledCheckbox( bool checked, const style::Checkbox &st, const style::Check &checkSt) -: TWidget(parent) +: RpWidget(parent) , _checkbox(this, text, checked, st, checkSt) { - subscribe(_checkbox->checkedChanged, [this](bool value) { checkedChanged.notify(value, true); }); } void EditChatAdminsBoxController::LabeledCheckbox::setLabelText( @@ -676,7 +684,8 @@ void EditChatAdminsBoxController::prepare() { })); } - subscribe(_allAdmins->checkedChanged, [this](bool checked) { + _allAdmins->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { delegate()->peerListSetSearchMode(checked ? PeerListSearchMode::Disabled : PeerListSearchMode::Enabled); for (auto i = 0, count = delegate()->peerListFullRowsCount(); i != count; ++i) { auto row = delegate()->peerListRowAt(i); @@ -687,7 +696,7 @@ void EditChatAdminsBoxController::prepare() { row->setDisabledState(PeerListRow::State::Active); } } - }); + }, _allAdmins->lifetime()); } void EditChatAdminsBoxController::createAllAdminsCheckbox() { diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp index fa7317f0f..8cff8f13d 100644 --- a/Telegram/SourceFiles/export/view/export_view_settings.cpp +++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp @@ -464,8 +464,7 @@ not_null SettingsWidget::addOption( ((readData().types & types) == types), st::defaultBoxCheckbox), st::exportSettingPadding); - base::ObservableViewer( - checkbox->checkedChanged + checkbox->checkedChanges( ) | rpl::start_with_next([=](bool checked) { changeData([&](Settings &data) { if (checked) { @@ -474,7 +473,7 @@ not_null SettingsWidget::addOption( data.types &= ~types; } }); - }, lifetime()); + }, checkbox->lifetime()); return checkbox; } @@ -509,8 +508,7 @@ void SettingsWidget::addChatOption( st::defaultBoxCheckbox), st::exportSubSettingPadding)); - base::ObservableViewer( - onlyMy->entity()->checkedChanged + onlyMy->entity()->checkedChanges( ) | rpl::start_with_next([=](bool checked) { changeData([&](Settings &data) { if (checked) { @@ -519,13 +517,9 @@ void SettingsWidget::addChatOption( data.fullChats |= types; } }); - }, checkbox->lifetime()); + }, onlyMy->lifetime()); - onlyMy->toggleOn(base::ObservableViewer( - checkbox->checkedChanged - )); - - onlyMy->toggle(checkbox->checked(), anim::type::instant); + onlyMy->toggleOn(checkbox->checkedValue()); if (types & (Type::PublicGroups | Type::PublicChannels)) { onlyMy->entity()->setChecked(true); @@ -568,8 +562,7 @@ void SettingsWidget::addMediaOption( ((readData().media.types & type) == type), st::defaultBoxCheckbox), st::exportSettingPadding); - base::ObservableViewer( - checkbox->checkedChanged + checkbox->checkedChanges( ) | rpl::start_with_next([=](bool checked) { changeData([&](Settings &data) { if (checked) { @@ -578,7 +571,7 @@ void SettingsWidget::addMediaOption( data.media.types &= ~type; } }); - }, lifetime()); + }, checkbox->lifetime()); } void SettingsWidget::addSizeSlider( diff --git a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp index 61c66654e..0a0099042 100644 --- a/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp +++ b/Telegram/SourceFiles/history/admin_log/history_admin_log_filter.cpp @@ -23,13 +23,16 @@ public: bool checked() const { return _check->checked(); } - base::Observable checkedChanged; + rpl::producer checkedChanges() const; + rpl::producer checkedValue() const; enum class NotifyAboutChange { Notify, DontNotify, }; - void setChecked(bool checked, NotifyAboutChange notify = NotifyAboutChange::Notify); + void setChecked( + bool checked, + NotifyAboutChange notify = NotifyAboutChange::Notify); void finishAnimating(); @@ -48,6 +51,7 @@ protected: private: const style::Checkbox &_st; std::unique_ptr _check; + rpl::event_stream _checkedChanges; QRect _checkRect; @@ -73,11 +77,19 @@ UserCheckbox::UserCheckbox(QWidget *parent, not_null user, bool check _checkRect = { QPoint(_st.margin.left(), (st::contactsPhotoSize - checkSize.height()) / 2), checkSize }; } +rpl::producer UserCheckbox::checkedChanges() const { + return _checkedChanges.events(); +} + +rpl::producer UserCheckbox::checkedValue() const { + return _checkedChanges.events_starting_with(checked()); +} + void UserCheckbox::setChecked(bool checked, NotifyAboutChange notify) { if (_check->checked() != checked) { _check->setChecked(checked, anim::type::normal); if (notify == NotifyAboutChange::Notify) { - checkedChanged.notify(checked, true); + _checkedChanges.fire_copy(checked); } } } @@ -132,9 +144,14 @@ QPoint UserCheckbox::prepareRippleStartPosition() const { } // namespace -class FilterBox::Inner : public TWidget, private base::Subscriber { +class FilterBox::Inner : public Ui::RpWidget { public: - Inner(QWidget *parent, not_null channel, const std::vector> &admins, const FilterValue &filter, Fn changedCallback); + Inner( + QWidget *parent, + not_null channel, + const std::vector> &admins, + const FilterValue &filter, + Fn changedCallback); template QPointer addRow(object_ptr widget, int marginTop) { @@ -155,11 +172,15 @@ protected: void resizeEvent(QResizeEvent *e) override; private: - void createControls(const std::vector> &admins, const FilterValue &filter); + void createControls( + const std::vector> &admins, + const FilterValue &filter); void createAllActionsCheckbox(const FilterValue &filter); void createActionsCheckboxes(const FilterValue &filter); void createAllUsersCheckbox(const FilterValue &filter); - void createAdminsCheckboxes(const std::vector> &admins, const FilterValue &filter); + void createAdminsCheckboxes( + const std::vector> &admins, + const FilterValue &filter); not_null _channel; @@ -180,7 +201,13 @@ private: }; -FilterBox::Inner::Inner(QWidget *parent, not_null channel, const std::vector> &admins, const FilterValue &filter, Fn changedCallback) : TWidget(parent) +FilterBox::Inner::Inner( + QWidget *parent, + not_null channel, + const std::vector> &admins, + const FilterValue &filter, + Fn changedCallback) +: RpWidget(parent) , _channel(channel) , _changedCallback(std::move(changedCallback)) { createControls(admins, filter); @@ -196,7 +223,8 @@ void FilterBox::Inner::createControls(const std::vector> &ad void FilterBox::Inner::createAllActionsCheckbox(const FilterValue &filter) { auto checked = (filter.flags == 0); _allFlags = addRow(object_ptr(this, lang(lng_admin_log_filter_all_actions), checked, st::adminLogFilterCheckbox), st::adminLogFilterCheckbox.margin.top()); - subscribe(_allFlags->checkedChanged, [this](bool checked) { + _allFlags->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { if (!std::exchange(_restoringInvariant, true)) { auto allChecked = _allFlags->checked(); for_const (auto &&checkbox, _filterFlags) { @@ -207,7 +235,7 @@ void FilterBox::Inner::createAllActionsCheckbox(const FilterValue &filter) { _changedCallback(); } } - }); + }, _allFlags->lifetime()); } void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) { @@ -217,7 +245,8 @@ void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) { auto checked = (filter.flags == 0) || (filter.flags & flag); auto checkbox = addRow(object_ptr(this, std::move(text), checked, st::defaultBoxCheckbox), st::adminLogFilterLittleSkip); _filterFlags.insert(flag, checkbox); - subscribe(checkbox->checkedChanged, [this](bool checked) { + checkbox->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { if (!std::exchange(_restoringInvariant, true)) { auto allChecked = true; for_const (auto &&checkbox, _filterFlags) { @@ -232,7 +261,7 @@ void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) { _changedCallback(); } } - }); + }, checkbox->lifetime()); }; auto isGroup = _channel->isMegagroup(); if (isGroup) { @@ -251,7 +280,8 @@ void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) { void FilterBox::Inner::createAllUsersCheckbox(const FilterValue &filter) { _allUsers = addRow(object_ptr(this, lang(lng_admin_log_filter_all_admins), filter.allUsers, st::adminLogFilterCheckbox), st::adminLogFilterSkip); - subscribe(_allUsers->checkedChanged, [this](bool checked) { + _allUsers->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { if (checked && !std::exchange(_restoringInvariant, true)) { for_const (auto &&checkbox, _admins) { checkbox->setChecked(true); @@ -261,14 +291,15 @@ void FilterBox::Inner::createAllUsersCheckbox(const FilterValue &filter) { _changedCallback(); } } - }); + }, _allUsers->lifetime()); } void FilterBox::Inner::createAdminsCheckboxes(const std::vector> &admins, const FilterValue &filter) { for (auto user : admins) { auto checked = filter.allUsers || base::contains(filter.admins, user); auto checkbox = addRow(object_ptr(this, user, checked), st::adminLogFilterLittleSkip); - subscribe(checkbox->checkedChanged, [this](bool checked) { + checkbox->checkedChanges( + ) | rpl::start_with_next([=](bool checked) { if (!std::exchange(_restoringInvariant, true)) { auto allChecked = true; for_const (auto &&checkbox, _admins) { @@ -285,7 +316,7 @@ void FilterBox::Inner::createAdminsCheckboxes(const std::vectorlifetime()); _admins.insert(user, checkbox); } } diff --git a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp index fb4656f0b..1d3ca5c14 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_cover.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_cover.cpp @@ -191,9 +191,7 @@ bool SectionWithToggle::toggled() const { rpl::producer SectionWithToggle::toggledValue() const { if (_toggle) { - return rpl::single( - _toggle->checked() - ) | rpl::then(base::ObservableViewer(_toggle->checkedChanged)); + return _toggle->checkedValue(); } return rpl::never(); } diff --git a/Telegram/SourceFiles/settings/settings_advanced.cpp b/Telegram/SourceFiles/settings/settings_advanced.cpp index e6ba35736..6040e5eba 100644 --- a/Telegram/SourceFiles/settings/settings_advanced.cpp +++ b/Telegram/SourceFiles/settings/settings_advanced.cpp @@ -296,8 +296,7 @@ void SetupTrayContent(not_null container) { Local::writeSettings(); }; - base::ObservableViewer( - tray->checkedChanged + tray->checkedChanges( ) | rpl::filter([=](bool checked) { return (checked != trayEnabled()); }) | rpl::start_with_next([=](bool checked) { @@ -309,8 +308,7 @@ void SetupTrayContent(not_null container) { }, tray->lifetime()); if (taskbar) { - base::ObservableViewer( - taskbar->checkedChanged + taskbar->checkedChanges( ) | rpl::filter([=](bool checked) { return (checked != taskbarEnabled()); }) | rpl::start_with_next([=](bool checked) { @@ -338,8 +336,7 @@ void SetupTrayContent(not_null container) { lng_settings_add_sendto, cSendToMenu()); - base::ObservableViewer( - autostart->checkedChanged + autostart->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != cAutoStart()); }) | rpl::start_with_next([=](bool checked) { @@ -354,13 +351,8 @@ void SetupTrayContent(not_null container) { } }, autostart->lifetime()); - minimized->toggleOn(rpl::single( - autostart->checked() - ) | rpl::then(base::ObservableViewer( - autostart->checkedChanged - ))); - base::ObservableViewer( - minimized->entity()->checkedChanged + minimized->toggleOn(autostart->checkedValue()); + minimized->entity()->checkedChanges( ) | rpl::filter([=](bool checked) { return (checked != minimizedToggled()); }) | rpl::start_with_next([=](bool checked) { @@ -380,8 +372,7 @@ void SetupTrayContent(not_null container) { minimized->entity()->setChecked(minimizedToggled()); }, minimized->lifetime()); - base::ObservableViewer( - sendto->checkedChanged + sendto->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != cSendToMenu()); }) | rpl::start_with_next([](bool checked) { diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp index 2b97c59fd..d2941ab9e 100644 --- a/Telegram/SourceFiles/settings/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/settings_chat.cpp @@ -441,11 +441,10 @@ void SetupStickersEmoji(not_null container) { st::settingsCheckbox); }; const auto add = [&](LangKey label, bool checked, auto &&handle) { - base::ObservableViewer( - inner->add( - checkbox(label, checked), - st::settingsCheckboxPadding - )->checkedChanged + inner->add( + checkbox(label, checked), + st::settingsCheckboxPadding + )->checkedChanges( ) | rpl::start_with_next( std::move(handle), inner->lifetime()); @@ -670,8 +669,7 @@ void SetupChatBackground(not_null container) { st::settingsCheckbox), st::settingsSendTypePadding)); - base::ObservableViewer( - tile->checkedChanged + tile->checkedChanges( ) | rpl::start_with_next([](bool checked) { Window::Theme::Background()->setTile(checked); }, tile->lifetime()); @@ -695,8 +693,7 @@ void SetupChatBackground(not_null container) { return (Global::AdaptiveChatLayout() == Adaptive::ChatLayout::Wide); })); - base::ObservableViewer( - adaptive->entity()->checkedChanged + adaptive->entity()->checkedChanges( ) | rpl::start_with_next([](bool checked) { Global::SetAdaptiveForWide(checked); Adaptive::Changed().notify(); @@ -986,15 +983,14 @@ void SetupSupport(not_null container) { AddSkip(inner, st::settingsCheckboxesSkip); - base::ObservableViewer( - inner->add( - object_ptr( - inner, - "Enable templates autocomplete", - Auth().settings().supportTemplatesAutocomplete(), - st::settingsCheckbox), - st::settingsSendTypePadding - )->checkedChanged + inner->add( + object_ptr( + inner, + "Enable templates autocomplete", + Auth().settings().supportTemplatesAutocomplete(), + st::settingsCheckbox), + st::settingsSendTypePadding + )->checkedChanges( ) | rpl::start_with_next([=](bool checked) { Auth().settings().setSupportTemplatesAutocomplete(checked); Local::writeUserSettings(); diff --git a/Telegram/SourceFiles/settings/settings_notifications.cpp b/Telegram/SourceFiles/settings/settings_notifications.cpp index fdef59180..1cffcbd1b 100644 --- a/Telegram/SourceFiles/settings/settings_notifications.cpp +++ b/Telegram/SourceFiles/settings/settings_notifications.cpp @@ -594,8 +594,7 @@ void SetupNotificationsContent(not_null container) { Local::writeUserSettings(); Auth().notifications().settingsChanged().notify(change); }; - base::ObservableViewer( - desktop->checkedChanged + desktop->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != Global::DesktopNotify()); }) | rpl::start_with_next([=](bool checked) { @@ -603,8 +602,7 @@ void SetupNotificationsContent(not_null container) { changed(Change::DesktopEnabled); }, desktop->lifetime()); - base::ObservableViewer( - name->entity()->checkedChanged + name->entity()->checkedChanges( ) | rpl::map([=](bool checked) { if (!checked) { return dbinvShowNothing; @@ -619,8 +617,7 @@ void SetupNotificationsContent(not_null container) { changed(Change::ViewParams); }, name->lifetime()); - base::ObservableViewer( - preview->entity()->checkedChanged + preview->entity()->checkedChanges( ) | rpl::map([=](bool checked) { if (checked) { return dbinvShowPreview; @@ -635,8 +632,7 @@ void SetupNotificationsContent(not_null container) { changed(Change::ViewParams); }, preview->lifetime()); - base::ObservableViewer( - sound->checkedChanged + sound->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != Global::SoundNotify()); }) | rpl::start_with_next([=](bool checked) { @@ -644,8 +640,7 @@ void SetupNotificationsContent(not_null container) { changed(Change::SoundEnabled); }, sound->lifetime()); - base::ObservableViewer( - muted->checkedChanged + muted->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != Auth().settings().includeMutedCounter()); }) | rpl::start_with_next([=](bool checked) { @@ -653,14 +648,13 @@ void SetupNotificationsContent(not_null container) { changed(Change::IncludeMuted); }, muted->lifetime()); - base::ObservableViewer( - count->checkedChanged + count->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != Auth().settings().countUnreadMessages()); }) | rpl::start_with_next([=](bool checked) { Auth().settings().setCountUnreadMessages(checked); changed(Change::CountMessages); - }, muted->lifetime()); + }, count->lifetime()); base::ObservableViewer( Auth().notifications().settingsChanged() @@ -679,8 +673,7 @@ void SetupNotificationsContent(not_null container) { }, desktop->lifetime()); if (native) { - base::ObservableViewer( - native->checkedChanged + native->checkedChanges( ) | rpl::filter([](bool checked) { return (checked != Global::NativeNotifications()); }) | rpl::start_with_next([=](bool checked) { diff --git a/Telegram/SourceFiles/ui/abstract_button.cpp b/Telegram/SourceFiles/ui/abstract_button.cpp index f51158492..748940c74 100644 --- a/Telegram/SourceFiles/ui/abstract_button.cpp +++ b/Telegram/SourceFiles/ui/abstract_button.cpp @@ -66,12 +66,17 @@ void AbstractButton::mouseMoveEvent(QMouseEvent *e) { void AbstractButton::mouseReleaseEvent(QMouseEvent *e) { if (_state & StateFlag::Down) { - auto was = _state; + const auto was = _state; _state &= ~State(StateFlag::Down); + + auto weak = make_weak(this); onStateChanged(was, StateChangeSource::ByPress); + if (!weak) { + return; + } + if (was & StateFlag::Over) { _modifiers = e->modifiers(); - auto weak = make_weak(this); if (const auto callback = _clickedCallback) { callback(); } else { diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.cpp b/Telegram/SourceFiles/ui/widgets/checkbox.cpp index 405c323ca..2069df308 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.cpp +++ b/Telegram/SourceFiles/ui/widgets/checkbox.cpp @@ -428,6 +428,14 @@ bool Checkbox::checked() const { return _check->checked(); } +rpl::producer Checkbox::checkedChanges() const { + return _checkedChanges.events(); +} + +rpl::producer Checkbox::checkedValue() const { + return _checkedChanges.events_starting_with(checked()); +} + void Checkbox::resizeToText() { if (_st.width <= 0) { resizeToWidth(_text.maxWidth() - _st.width); @@ -440,7 +448,7 @@ void Checkbox::setChecked(bool checked, NotifyAboutChange notify) { if (_check->checked() != checked) { _check->setChecked(checked, anim::type::normal); if (notify == NotifyAboutChange::Notify) { - checkedChanged.notify(checked, true); + _checkedChanges.fire_copy(checked); } } } @@ -635,19 +643,24 @@ Radiobutton::Radiobutton( std::move(check)) , _group(group) , _value(value) { + using namespace rpl::mappers; + checkbox()->setChecked(group->hasValue() && group->value() == value); _group->registerButton(this); - subscribe(checkbox()->checkedChanged, [this](bool checked) { - if (checked) { - _group->setValue(_value); - } - }); + checkbox()->checkedChanges( + ) | rpl::filter( + _1 + ) | rpl::start_with_next([=] { + _group->setValue(_value); + }, lifetime()); } void Radiobutton::handleNewGroupValue(int value) { auto checked = (value == _value); if (checkbox()->checked() != checked) { - checkbox()->setChecked(checked, Ui::Checkbox::NotifyAboutChange::DontNotify); + checkbox()->setChecked( + checked, + Ui::Checkbox::NotifyAboutChange::DontNotify); } } diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.h b/Telegram/SourceFiles/ui/widgets/checkbox.h index 32a1d8379..a41ca3814 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.h +++ b/Telegram/SourceFiles/ui/widgets/checkbox.h @@ -156,12 +156,15 @@ public: void setCheckAlignment(style::align alignment); bool checked() const; + rpl::producer checkedChanges() const; + rpl::producer checkedValue() const; enum class NotifyAboutChange { Notify, DontNotify, }; - void setChecked(bool checked, NotifyAboutChange notify = NotifyAboutChange::Notify); - base::Observable checkedChanged; + void setChecked( + bool checked, + NotifyAboutChange notify = NotifyAboutChange::Notify); void finishAnimating(); @@ -192,6 +195,7 @@ private: const style::Checkbox &_st; std::unique_ptr _check; + rpl::event_stream _checkedChanges; QPixmap _checkCache; Text _text; @@ -237,7 +241,7 @@ private: }; -class Radiobutton : public Checkbox, private base::Subscriber { +class Radiobutton : public Checkbox { public: Radiobutton( QWidget *parent, @@ -261,8 +265,10 @@ protected: private: // Hide the names from Checkbox. bool checked() const; + void checkedChanges() const; + void checkedValue() const; void setChecked(bool checked, NotifyAboutChange notify); - void checkedChanged(); + Checkbox *checkbox() { return this; } diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index f6f48084e..8fa08f974 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -305,11 +305,10 @@ void TermsBox::prepare() { } if (age) { - base::ObservableViewer( - age->entity()->checkedChanged + age->entity()->checkedChanges( ) | rpl::start_with_next([=] { toggleAgeError(false); - }, lifetime()); + }, age->lifetime()); heightValue( ) | rpl::start_with_next([=](int height) {