diff --git a/Telegram/SourceFiles/boxes/change_phone_box.cpp b/Telegram/SourceFiles/boxes/change_phone_box.cpp index 1589fd3dd3..8b091a7a20 100644 --- a/Telegram/SourceFiles/boxes/change_phone_box.cpp +++ b/Telegram/SourceFiles/boxes/change_phone_box.cpp @@ -20,6 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "boxes/change_phone_box.h" +#include +#include +#include #include "lang/lang_keys.h" #include "styles/style_boxes.h" #include "ui/widgets/labels.h" @@ -39,13 +42,19 @@ void createErrorLabel( int y) { if (label) { label->hide(anim::type::normal); - auto context = label.data(); - App::CallDelayed( - st::fadeWrapDuration, - context, - [old = std::move(label)]() mutable { - old.destroy(); - }); + + auto saved = label.data(); + auto destroy = [old = std::move(label)]() mutable { + old.destroyDelayed(); + }; + + using namespace rpl::mappers; + saved->shownValue() + | rpl::filter($1 == false) + | rpl::take(1) + | rpl::start_with_done( + std::move(destroy), + saved->lifetime()); } if (!text.isEmpty()) { label.create( diff --git a/Telegram/SourceFiles/rpl/operators_tests.cpp b/Telegram/SourceFiles/rpl/operators_tests.cpp index e6bc5a8a99..bd7320006b 100644 --- a/Telegram/SourceFiles/rpl/operators_tests.cpp +++ b/Telegram/SourceFiles/rpl/operators_tests.cpp @@ -388,4 +388,18 @@ TEST_CASE("basic operators tests", "[rpl::operators]") { } REQUIRE(*sum == "0-11-22-3"); } + + SECTION("take test") { + auto sum = std::make_shared(""); + { + rpl::lifetime lifetime; + rpl::ints(10) | take(3) + | start_with_next_done([=](int value) { + *sum += std::to_string(value); + }, [=] { + *sum += "done"; + }, lifetime); + } + REQUIRE(*sum == "012done"); + } } diff --git a/Telegram/SourceFiles/rpl/rpl.h b/Telegram/SourceFiles/rpl/rpl.h index 1b95382a4b..6b66b80276 100644 --- a/Telegram/SourceFiles/rpl/rpl.h +++ b/Telegram/SourceFiles/rpl/rpl.h @@ -30,6 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include #include +#include #include #include #include diff --git a/Telegram/SourceFiles/rpl/take.h b/Telegram/SourceFiles/rpl/take.h new file mode 100644 index 0000000000..1556b31a9b --- /dev/null +++ b/Telegram/SourceFiles/rpl/take.h @@ -0,0 +1,74 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +It is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org +*/ +#pragma once + +namespace rpl { +namespace details { + +class take_helper { +public: + take_helper(int count) : _count(count) { + } + + template < + typename Value, + typename Error, + typename Generator> + auto operator()(producer &&initial) { + return make_producer([ + initial = std::move(initial), + limit = _count + ](const auto &consumer) mutable { + auto count = consumer.template make_state(limit); + return std::move(initial).start( + [consumer, count](auto &&value) { + auto left = (*count)--; + if (left) { + consumer.put_next_forward( + std::forward(value)); + --left; + } + if (!left) { + consumer.put_done(); + } + }, [consumer](auto &&error) { + consumer.put_error_forward( + std::forward(error)); + }, [consumer] { + consumer.put_done(); + }); + }); + } + +private: + int _count = 0; + +}; + +} // namespace details +inline auto take(int count) +-> details::take_helper { + Expects(count >= 0); + return details::take_helper(count); +} + + +} // namespace rpl diff --git a/Telegram/SourceFiles/ui/abstract_button.cpp b/Telegram/SourceFiles/ui/abstract_button.cpp index 9379687d3f..fd516e17ad 100644 --- a/Telegram/SourceFiles/ui/abstract_button.cpp +++ b/Telegram/SourceFiles/ui/abstract_button.cpp @@ -20,8 +20,20 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "ui/abstract_button.h" +#include +#include + namespace Ui { +AbstractButton::AbstractButton(QWidget *parent) : RpWidget(parent) { + setMouseTracking(true); + + using namespace rpl::mappers; + shownValue() + | rpl::filter($1 == false) + | rpl::start_with_next([this] { clearState(); }, lifetime()); +} + void AbstractButton::leaveEventHook(QEvent *e) { if (_state & StateFlag::Down) return; diff --git a/Telegram/SourceFiles/ui/abstract_button.h b/Telegram/SourceFiles/ui/abstract_button.h index 1ec5ac58d3..0ce1e65077 100644 --- a/Telegram/SourceFiles/ui/abstract_button.h +++ b/Telegram/SourceFiles/ui/abstract_button.h @@ -30,9 +30,7 @@ class AbstractButton : public RpWidget { Q_OBJECT public: - AbstractButton(QWidget *parent) : RpWidget(parent) { - setMouseTracking(true); - } + AbstractButton(QWidget *parent); Qt::KeyboardModifiers clickModifiers() const { return _modifiers; @@ -58,13 +56,6 @@ public: _clickedCallback = std::move(callback); } - void setVisible(bool visible) override { - TWidget::setVisible(visible); - if (!visible) { - clearState(); - } - } - auto clicks() const { return _clicks.events(); } diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.cpp b/Telegram/SourceFiles/ui/effects/fade_animation.cpp index 9df63e9105..6dc46216d4 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/fade_animation.cpp @@ -100,7 +100,6 @@ void FadeAnimation::stopAnimation() { _animation.finish(); if (!_cache.isNull()) { _cache = QPixmap(); - updateCallback(); if (_visible) { _widget->showChildren(); } diff --git a/Telegram/SourceFiles/ui/rp_widget.h b/Telegram/SourceFiles/ui/rp_widget.h index 6ae57314ae..caad60d4b6 100644 --- a/Telegram/SourceFiles/ui/rp_widget.h +++ b/Telegram/SourceFiles/ui/rp_widget.h @@ -76,6 +76,10 @@ public: virtual rpl::producer desiredHeightValue() const { return heightValue(); } + auto shownValue() const { + auto &stream = eventStreams().shown; + return stream.events_starting_with(!this->isHidden()); + } auto paintRequest() const { return eventStreams().paint.events(); @@ -85,6 +89,17 @@ public: return eventStreams().alive.events(); } + void setVisible(bool visible) final override { + auto wasVisible = !this->isHidden(); + Parent::setVisible(visible); + auto nowVisible = !this->isHidden(); + if (nowVisible != wasVisible) { + if (auto streams = _eventStreams.get()) { + streams->shown.fire_copy(nowVisible); + } + } + } + template void showOn(rpl::producer &&shown) { std::move(shown) @@ -133,6 +148,7 @@ private: struct EventStreams { rpl::event_stream geometry; rpl::event_stream paint; + rpl::event_stream shown; rpl::event_stream<> alive; }; struct LifetimeHolder { diff --git a/Telegram/gyp/tests/tests.gyp b/Telegram/gyp/tests/tests.gyp index 2c018118f9..dd1c59379e 100644 --- a/Telegram/gyp/tests/tests.gyp +++ b/Telegram/gyp/tests/tests.gyp @@ -121,6 +121,7 @@ '<(src_loc)/rpl/producer_tests.cpp', '<(src_loc)/rpl/range.h', '<(src_loc)/rpl/rpl.h', + '<(src_loc)/rpl/take.h', '<(src_loc)/rpl/then.h', '<(src_loc)/rpl/type_erased.h', '<(src_loc)/rpl/variable.h',