From 5c006002b6c94cd4783769dc95ffe66cdc0cbbd7 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 4 Oct 2020 21:19:34 +0300 Subject: [PATCH] Added appearance animation to VoiceRecordBar. --- .../history_view_voice_record_bar.cpp | 117 +++++++++++------- .../controls/history_view_voice_record_bar.h | 4 + Telegram/SourceFiles/ui/chat/chat.style | 1 + 3 files changed, 77 insertions(+), 45 deletions(-) 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 0a42498b12..5933067b78 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 @@ -90,6 +90,7 @@ void VoiceRecordBar::init() { paintRequest( ) | rpl::start_with_next([=] { Painter p(this); + p.setOpacity(_showAnimation.value(1.)); p.fillRect(rect(), st::historyComposeAreaBg); drawRecording(p, activeAnimationRatio()); @@ -116,28 +117,46 @@ void VoiceRecordBar::activeAnimate(bool active) { } } -void VoiceRecordBar::startRecording() { - using namespace ::Media::Capture; - if (!instance()->available()) { - return; - } - show(); - _recording = true; +void VoiceRecordBar::visibilityAnimate(bool show, Fn &&callback) { + const auto to = show ? 1. : 0.; + const auto from = show ? 0. : 1.; + const auto duration = st::historyRecordVoiceShowDuration; + auto animationCallback = [=, callback = std::move(callback)](auto value) { + update(); + if ((show && value == 1.) || (!show && value == 0.)) { + if (callback) { + callback(); + } + } + }; + _showAnimation.start(std::move(animationCallback), from, to, duration); +} - instance()->start(); - instance()->updated( - ) | rpl::start_with_next_error([=](const Update &update) { - recordUpdated(update.level, update.samples); - }, [=] { - stopRecording(false); - }, _recordingLifetime); +void VoiceRecordBar::startRecording() { + auto appearanceCallback = [=] { + Expects(!_showAnimation.animating()); + + using namespace ::Media::Capture; + if (!instance()->available()) { + stop(false); + return; + } + + _recording = true; + instance()->start(); + instance()->updated( + ) | rpl::start_with_next_error([=](const Update &update) { + recordUpdated(update.level, update.samples); + }, [=] { + stop(false); + }, _recordingLifetime); + }; + visibilityAnimate(true, std::move(appearanceCallback)); + show(); _inField = true; _controller->widget()->setInnerFocus(); - update(); - activeAnimate(true); - _send->events( ) | rpl::filter([=](not_null e) { return isTypeRecord() @@ -149,7 +168,7 @@ void VoiceRecordBar::startRecording() { const auto mouse = static_cast(e.get()); _inField = rect().contains(mapFromGlobal(mouse->globalPos())); } else if (type == QEvent::MouseButtonRelease) { - stopRecording(_inField.current()); + stop(_inField.current()); } }, _recordingLifetime); } @@ -175,44 +194,51 @@ void VoiceRecordBar::recordUpdated(quint16 level, int samples) { _recordingAnimation.start(); _recordingSamples = samples; if (samples < 0 || samples >= kMaxSamples) { - stopRecording(samples > 0 && _inField.current()); + stop(samples > 0 && _inField.current()); } Core::App().updateNonIdle(); update(); _sendActionUpdates.fire({ Api::SendProgressType::RecordVoice }); } +void VoiceRecordBar::stop(bool send) { + auto disappearanceCallback = [=] { + Expects(!_showAnimation.animating()); + + hide(); + _recording = false; + + stopRecording(send); + + _recordingLevel = anim::value(); + _recordingAnimation.stop(); + + _inField = false; + + _recordingLifetime.destroy(); + _recordingSamples = 0; + _sendActionUpdates.fire({ Api::SendProgressType::RecordVoice, -1 }); + + _controller->widget()->setInnerFocus(); + }; + visibilityAnimate(false, std::move(disappearanceCallback)); +} + void VoiceRecordBar::stopRecording(bool send) { - hide(); - _recording = false; - using namespace ::Media::Capture; - if (send) { - instance()->stop(crl::guard(this, [=](const Result &data) { - if (data.bytes.isEmpty()) { - return; - } - - Window::ActivateWindow(_controller); - const auto duration = Duration(data.samples); - _sendVoiceRequests.fire({ data.bytes, data.waveform, duration }); - })); - } else { + if (!send) { instance()->stop(); + return; } + instance()->stop(crl::guard(this, [=](const Result &data) { + if (data.bytes.isEmpty()) { + return; + } - _recordingLevel = anim::value(); - _recordingAnimation.stop(); - - _inField = false; - - _recordingLifetime.destroy(); - _recordingSamples = 0; - _sendActionUpdates.fire({ Api::SendProgressType::RecordVoice, -1 }); - - _controller->widget()->setInnerFocus(); - - update(); + Window::ActivateWindow(_controller); + const auto duration = Duration(data.samples); + _sendVoiceRequests.fire({ data.bytes, data.waveform, duration }); + })); } void VoiceRecordBar::drawRecording(Painter &p, float64 recordActive) { @@ -276,6 +302,7 @@ bool VoiceRecordBar::isRecording() const { void VoiceRecordBar::finishAnimating() { _recordingAnimation.stop(); + _showAnimation.stop(); } rpl::producer VoiceRecordBar::recordingStateChanges() const { 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 f33a1dc279..667d9a5583 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 @@ -53,7 +53,10 @@ private: void recordUpdated(quint16 level, int samples); bool recordingAnimationCallback(crl::time now); + + void stop(bool send); void stopRecording(bool send); + void visibilityAnimate(bool show, Fn &&callback); void recordStopCallback(bool active); void recordUpdateCallback(QPoint globalPos); @@ -90,6 +93,7 @@ private: // so it should be a Basic, not a Simple animation. Ui::Animations::Basic _recordingAnimation; Ui::Animations::Simple _activeAnimation; + Ui::Animations::Simple _showAnimation; anim::value _recordingLevel; }; diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index ed8a05b06c..625ef7a59b 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -328,6 +328,7 @@ historyScheduledToggle: IconButton(historyAttach) { historyRecordVoiceFg: historyComposeIconFg; historyRecordVoiceFgOver: historyComposeIconFgOver; historyRecordVoiceFgActive: windowBgActive; +historyRecordVoiceShowDuration: 120; historyRecordVoiceDuration: 120; historyRecordVoice: icon {{ "send_control_record", historyRecordVoiceFg }}; historyRecordVoiceOver: icon {{ "send_control_record", historyRecordVoiceFgOver }};