Added initial ability to send recorded voice data from listen state.

This commit is contained in:
23rd 2020-11-07 21:02:08 +03:00 committed by John Preston
parent 647cbc5464
commit a19e3ca3dc
4 changed files with 86 additions and 16 deletions

View File

@ -804,6 +804,11 @@ void HistoryWidget::initVoiceRecordBar() {
updateUnreadMentionsVisibility();
}, lifetime());
_voiceRecordBar->updateSendButtonTypeRequests(
) | rpl::start_with_next([=] {
updateSendButtonType();
}, lifetime());
_voiceRecordBar->hideFast();
}
@ -3639,6 +3644,7 @@ bool HistoryWidget::isMuteUnmute() const {
bool HistoryWidget::showRecordButton() const {
return Media::Capture::instance()->available()
&& !_voiceRecordBar->isListenState()
&& !HasSendText(_field)
&& !readyToForward()
&& !_editMsgId;

View File

@ -994,6 +994,7 @@ void ComposeControls::orderControls() {
bool ComposeControls::showRecordButton() const {
return ::Media::Capture::instance()->available()
&& !_voiceRecordBar->isListenState()
&& !HasSendText(_field)
//&& !readyToForward()
&& !isEditingMessage();
@ -1533,6 +1534,11 @@ void ComposeControls::initVoiceRecordBar() {
_voiceRecordBar->setEscFilter([=] {
return (isEditingMessage() || replyingToMessage());
});
_voiceRecordBar->updateSendButtonTypeRequests(
) | rpl::start_with_next([=] {
updateSendButtonType();
}, _wrap->lifetime());
}
void ComposeControls::updateWrappingVisibility() {

View File

@ -78,10 +78,11 @@ class ListenWrap final {
public:
ListenWrap(
not_null<Ui::RpWidget*> parent,
const ::Media::Capture::Result &data);
::Media::Capture::Result &&data);
void requestPaintProgress(float64 progress);
rpl::producer<> stopRequests() const;
::Media::Capture::Result *data() const;
rpl::lifetime &lifetime();
@ -90,7 +91,8 @@ private:
not_null<Ui::RpWidget*> _parent;
const std::unique_ptr<VoiceData> _voiceData;
const std::unique_ptr<::Media::Capture::Result> _data;
// const std::unique_ptr<VoiceData> _voiceData;
const style::IconButton &_stDelete;
base::unique_qptr<Ui::IconButton> _delete;
@ -102,9 +104,10 @@ private:
ListenWrap::ListenWrap(
not_null<Ui::RpWidget*> parent,
const ::Media::Capture::Result &data)
::Media::Capture::Result &&data)
: _parent(parent)
, _voiceData(ProcessCaptureResult(data))
, _data(std::make_unique<::Media::Capture::Result>(std::move(data)))
// , _voiceData(ProcessCaptureResult(_data))
, _stDelete(st::historyRecordDelete)
, _delete(base::make_unique_q<Ui::IconButton>(parent, _stDelete)) {
init();
@ -137,6 +140,10 @@ rpl::producer<> ListenWrap::stopRequests() const {
return _delete->clicks() | rpl::to_empty;
}
::Media::Capture::Result *ListenWrap::data() const {
return _data.get();
}
rpl::lifetime &ListenWrap::lifetime() {
return _lifetime;
}
@ -533,11 +540,9 @@ void VoiceRecordBar::init() {
_lock->stops(
) | rpl::start_with_next([=] {
::Media::Capture::instance()->startedChanges(
) | rpl::filter([](auto capturing) {
return !capturing;
) | rpl::filter([=](auto capturing) {
return !capturing && _listen;
}) | rpl::take(1) | rpl::start_with_next([=] {
Assert(_listen != nullptr);
_lockShowing = false;
const auto to = 1.;
@ -605,6 +610,50 @@ void VoiceRecordBar::init() {
_startTimer.cancel();
}
}, lifetime());
_listenChanges.events(
) | rpl::filter([=] {
return _listen != nullptr;
}) | rpl::start_with_next([=] {
_listen->stopRequests(
) | rpl::take(1) | rpl::start_with_next([=] {
visibilityAnimate(false, [=] { hide(); });
}, _listen->lifetime());
_listen->lifetime().add([=] { _listenChanges.fire({}); });
auto filterCallback = [=](not_null<QEvent*> e) {
using Result = base::EventFilterResult;
if (_send->type() != Ui::SendButton::Type::Send
&& _send->type() != Ui::SendButton::Type::Schedule) {
return Result::Continue;
}
switch(e->type()) {
case QEvent::MouseButtonRelease: {
auto callback = [=] {
const auto data = _listen->data();
_sendVoiceRequests.fire({
data->bytes,
data->waveform,
Duration(data->samples) });
hide();
};
visibilityAnimate(false, std::move(callback));
_send->clearState();
return Result::Cancel;
}
default: return Result::Continue;
}
};
auto filter = base::install_event_filter(
_send.get(),
std::move(filterCallback));
_listen->lifetime().make_state<base::unique_qptr<QObject>>(
std::move(filter));
}, lifetime());
}
void VoiceRecordBar::activeAnimate(bool active) {
@ -783,8 +832,10 @@ void VoiceRecordBar::stopRecording(StopType type) {
instance()->stop();
return;
}
instance()->stop(crl::guard(this, [=](const Result &data) {
instance()->stop(crl::guard(this, [=](Result &&data) {
if (data.bytes.isEmpty()) {
// Close everything.
stop(false);
return;
}
@ -793,11 +844,8 @@ void VoiceRecordBar::stopRecording(StopType type) {
if (type == StopType::Send) {
_sendVoiceRequests.fire({ data.bytes, data.waveform, duration });
} else if (type == StopType::Listen) {
_listen = std::make_unique<ListenWrap>(this, data);
_listen->stopRequests(
) | rpl::take(1) | rpl::start_with_next([=] {
visibilityAnimate(false, [=] { hide(); });
}, _listen->lifetime());
_listen = std::make_unique<ListenWrap>(this, std::move(data));
_listenChanges.fire({});
_lockShowing = false;
}
@ -879,10 +927,18 @@ rpl::producer<bool> VoiceRecordBar::lockShowStarts() const {
return _lockShowing.changes();
}
rpl::producer<> VoiceRecordBar::updateSendButtonTypeRequests() const {
return _listenChanges.events();
}
bool VoiceRecordBar::isLockPresent() const {
return _lockShowing.current();
}
bool VoiceRecordBar::isListenState() const {
return _listen != nullptr;
}
bool VoiceRecordBar::isTypeRecord() const {
return (_send->type() == Ui::SendButton::Type::Record);
}

View File

@ -57,6 +57,7 @@ public:
[[nodiscard]] rpl::producer<VoiceToSend> sendVoiceRequests() const;
[[nodiscard]] rpl::producer<bool> recordingStateChanges() const;
[[nodiscard]] rpl::producer<bool> lockShowStarts() const;
[[nodiscard]] rpl::producer<> updateSendButtonTypeRequests() const;
void setLockBottom(rpl::producer<int> &&bottom);
void setSendButtonGeometryValue(rpl::producer<QRect> &&geometry);
@ -65,6 +66,7 @@ public:
[[nodiscard]] bool isRecording() const;
[[nodiscard]] bool isLockPresent() const;
[[nodiscard]] bool isListenState() const;
private:
enum class StopType {
@ -117,6 +119,7 @@ private:
rpl::event_stream<SendActionUpdate> _sendActionUpdates;
rpl::event_stream<VoiceToSend> _sendVoiceRequests;
rpl::event_stream<> _listenChanges;
int _centerY = 0;
QRect _redCircleRect;
@ -130,6 +133,7 @@ private:
rpl::variable<bool> _recording = false;
rpl::variable<bool> _inField = false;
rpl::variable<bool> _lockShowing = false;
int _recordingSamples = 0;
float64 _redCircleProgress = 0.;
@ -137,8 +141,6 @@ private:
rpl::lifetime _recordingLifetime;
rpl::variable<bool> _lockShowing = false;
Ui::Animations::Simple _showLockAnimation;
Ui::Animations::Simple _showListenAnimation;
Ui::Animations::Simple _activeAnimation;