diff --git a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp index 6f52b02d45..0a42498b12 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.cpp @@ -92,8 +92,28 @@ void VoiceRecordBar::init() { Painter p(this); p.fillRect(rect(), st::historyComposeAreaBg); - drawRecording(p, _send->recordActiveRatio()); + drawRecording(p, activeAnimationRatio()); }, lifetime()); + + _inField.changes( + ) | rpl::start_with_next([=](bool value) { + activeAnimate(value); + }, lifetime()); +} + +void VoiceRecordBar::activeAnimate(bool active) { + const auto to = active ? 1. : 0.; + const auto duration = st::historyRecordVoiceDuration; + if (_activeAnimation.animating()) { + _activeAnimation.change(to, duration); + } else { + auto callback = [=] { + update(); + _send->requestPaintRecord(activeAnimationRatio()); + }; + const auto from = active ? 0. : 1.; + _activeAnimation.start(std::move(callback), from, to, duration); + } } void VoiceRecordBar::startRecording() { @@ -116,7 +136,7 @@ void VoiceRecordBar::startRecording() { _controller->widget()->setInnerFocus(); update(); - _send->setRecordActive(true); + activeAnimate(true); _send->events( ) | rpl::filter([=](not_null e) { @@ -127,14 +147,9 @@ void VoiceRecordBar::startRecording() { const auto type = e->type(); if (type == QEvent::MouseMove) { const auto mouse = static_cast(e.get()); - const auto pos = mapFromGlobal(mouse->globalPos()); - const auto inField = rect().contains(pos); - if (inField != _inField) { - _inField = inField; - _send->setRecordActive(_inField); - } + _inField = rect().contains(mapFromGlobal(mouse->globalPos())); } else if (type == QEvent::MouseButtonRelease) { - stopRecording(_inField); + stopRecording(_inField.current()); } }, _recordingLifetime); } @@ -160,7 +175,7 @@ void VoiceRecordBar::recordUpdated(quint16 level, int samples) { _recordingAnimation.start(); _recordingSamples = samples; if (samples < 0 || samples >= kMaxSamples) { - stopRecording(samples > 0 && _inField); + stopRecording(samples > 0 && _inField.current()); } Core::App().updateNonIdle(); update(); @@ -189,6 +204,8 @@ void VoiceRecordBar::stopRecording(bool send) { _recordingLevel = anim::value(); _recordingAnimation.stop(); + _inField = false; + _recordingLifetime.destroy(); _recordingSamples = 0; _sendActionUpdates.fire({ Api::SendProgressType::RecordVoice, -1 }); @@ -196,7 +213,6 @@ void VoiceRecordBar::stopRecording(bool send) { _controller->widget()->setInnerFocus(); update(); - _send->setRecordActive(false); } void VoiceRecordBar::drawRecording(Painter &p, float64 recordActive) { @@ -277,4 +293,8 @@ bool VoiceRecordBar::isTypeRecord() const { return (_send->type() == Ui::SendButton::Type::Record); } +float64 VoiceRecordBar::activeAnimationRatio() const { + return _activeAnimation.value(_inField.current() ? 1. : 0.); +} + } // namespace HistoryView::Controls diff --git a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h index 3e2c8ce5d0..f33a1dc279 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_voice_record_bar.h @@ -64,6 +64,9 @@ private: bool isTypeRecord() const; + void activeAnimate(bool active); + float64 activeAnimationRatio() const; + const not_null _controller; const std::unique_ptr _wrap; const std::shared_ptr _send; @@ -75,7 +78,7 @@ private: QRect _redCircleRect; rpl::variable _recording = false; - bool _inField = false; + rpl::variable _inField = false; int _recordingSamples = 0; const style::font &_cancelFont; @@ -86,6 +89,7 @@ private: // This can animate for a very long time (like in music playing), // so it should be a Basic, not a Simple animation. Ui::Animations::Basic _recordingAnimation; + Ui::Animations::Simple _activeAnimation; anim::value _recordingLevel; }; diff --git a/Telegram/SourceFiles/ui/controls/send_button.cpp b/Telegram/SourceFiles/ui/controls/send_button.cpp index 3c7df9e84a..e7ed3e87ae 100644 --- a/Telegram/SourceFiles/ui/controls/send_button.cpp +++ b/Telegram/SourceFiles/ui/controls/send_button.cpp @@ -43,20 +43,7 @@ void SendButton::setType(Type type) { update(); } if (_type != Type::Record) { - _recordActive = false; - _a_recordActive.stop(); - } -} - -void SendButton::setRecordActive(bool recordActive) { - if (_recordActive != recordActive) { - _recordActive = recordActive; - _a_recordActive.start( - [=] { recordAnimationCallback(); }, - _recordActive ? 0. : 1., - _recordActive ? 1. : 0, - st::historyRecordVoiceDuration); - update(); + _recordProgress = 0.; } } @@ -76,7 +63,6 @@ void SendButton::setSlowmodeDelay(int seconds) { void SendButton::finishAnimating() { _a_typeChanged.stop(); - _a_recordActive.stop(); update(); } @@ -89,6 +75,13 @@ void SendButton::mouseMoveEvent(QMouseEvent *e) { } } +void SendButton::requestPaintRecord(float64 progress) { + if (_type == Type::Record) { + _recordProgress = progress; + update(); + } +} + void SendButton::paintEvent(QPaintEvent *e) { Painter p(this); @@ -118,7 +111,7 @@ void SendButton::paintEvent(QPaintEvent *e) { } void SendButton::paintRecord(Painter &p, bool over) { - auto recordActive = recordActiveRatio(); + const auto recordActive = _recordProgress; if (!isDisabled()) { auto rippleColor = anim::color(st::historyAttachEmoji.ripple.color, st::historyRecordVoiceRippleBgActive, recordActive); paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y(), &rippleColor); diff --git a/Telegram/SourceFiles/ui/controls/send_button.h b/Telegram/SourceFiles/ui/controls/send_button.h index ad65006994..0b76764744 100644 --- a/Telegram/SourceFiles/ui/controls/send_button.h +++ b/Telegram/SourceFiles/ui/controls/send_button.h @@ -46,9 +46,7 @@ public: _recordAnimationCallback = std::move(callback); } - [[nodiscard]] float64 recordActiveRatio() { - return _a_recordActive.value(_recordActive ? 1. : 0.); - } + void requestPaintRecord(float64 progress); protected: void mouseMoveEvent(QMouseEvent *e) override; @@ -76,7 +74,8 @@ private: QPixmap _contentFrom, _contentTo; Ui::Animations::Simple _a_typeChanged; - Ui::Animations::Simple _a_recordActive; + + float64 _recordProgress = 0.; bool _recording = false; Fn _recordStartCallback;