diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 8823ce1ab..13c8a8cd1 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1345,6 +1345,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_record_cancel" = "Release outside this field to cancel"; "lng_record_lock_cancel" = "Click outside of the circle to cancel"; "lng_record_lock_cancel_sure" = "Are you sure you want to stop recording and discard your voice message?"; +"lng_record_listen_cancel_sure" = "Are you sure you want to discard your recorded voice message?"; "lng_record_lock_discard" = "Discard"; "lng_will_be_notified" = "Members will be notified when you post"; "lng_wont_be_notified" = "Members will not be notified when you post"; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 829025603..617c42bda 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -757,9 +757,6 @@ void HistoryWidget::initVoiceRecordBar() { }); _voiceRecordBar->setLockBottom(std::move(scrollHeight)); } - _voiceRecordBar->setEscFilter([=]() -> bool { - return _replyToId || (_nonEmptySelection && _list); - }); _voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue()); @@ -1629,7 +1626,7 @@ void HistoryWidget::applyDraft(FieldHistoryAction fieldHistoryAction) { ? _history->localEditDraft() : _history->localDraft(); auto fieldAvailable = canWriteMessage() - && !_voiceRecordBar->preventDraftApply(); + && !_voiceRecordBar->isActive(); if (!draft || (!_history->localEditDraft() && !fieldAvailable)) { auto fieldWillBeHiddenAfterEdit = (!fieldAvailable && _editMsgId != 0); clearFieldText(0, fieldHistoryAction); @@ -3099,7 +3096,7 @@ void HistoryWidget::send(Api::SendOptions options) { return; } - if (_voiceRecordBar && _voiceRecordBar->isListenState()) { + if (_voiceRecordBar->isListenState()) { _voiceRecordBar->requestToSendWithOptions(options); return; } @@ -3915,8 +3912,8 @@ void HistoryWidget::setTabbedPanel(std::unique_ptr panel) { } bool HistoryWidget::preventsClose(Fn &&continueCallback) const { - if (isRecording()) { - _voiceRecordBar->showDiscardRecordingBox(std::move(continueCallback)); + if (_voiceRecordBar->isActive()) { + _voiceRecordBar->showDiscardBox(std::move(continueCallback)); return true; } return false; @@ -5648,7 +5645,7 @@ void HistoryWidget::editMessage(FullMsgId itemId) { } void HistoryWidget::editMessage(not_null item) { - if (_voiceRecordBar && _voiceRecordBar->isListenState()) { + if (_voiceRecordBar->isListenState()) { Ui::show(Box(tr::lng_edit_caption_voice(tr::now))); return; } @@ -6122,6 +6119,8 @@ void HistoryWidget::escape() { _fieldAutocomplete->hideAnimated(); } else if (_replyToId && _field->getTextWithTags().text.isEmpty()) { cancelReply(); + } else if (auto &voice = _voiceRecordBar; voice->isActive()) { + voice->showDiscardBox(nullptr, anim::type::normal); } else { _cancelRequests.fire({}); } diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 8b0d40b03..236af8558 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -1567,10 +1567,6 @@ void ComposeControls::initVoiceRecordBar() { _voiceRecordBar->setLockBottom(std::move(bottom)); } - _voiceRecordBar->setEscFilter([=] { - return (isEditingMessage() || replyingToMessage()); - }); - _voiceRecordBar->updateSendButtonTypeRequests( ) | rpl::start_with_next([=] { updateSendButtonType(); @@ -1716,7 +1712,11 @@ void ComposeControls::paintBackground(QRect clip) { } void ComposeControls::escape() { - _cancelRequests.fire({}); + if (auto &voice = _voiceRecordBar; !voice->isActive()) { + voice->showDiscardBox(nullptr, anim::type::normal); + } else { + _cancelRequests.fire({}); + } } bool ComposeControls::pushTabbedSelectorToThirdSection( @@ -2139,8 +2139,8 @@ bool ComposeControls::isRecording() const { } bool ComposeControls::preventsClose(Fn &&continueCallback) const { - if (isRecording()) { - _voiceRecordBar->showDiscardRecordingBox(std::move(continueCallback)); + if (_voiceRecordBar->isActive()) { + _voiceRecordBar->showDiscardBox(std::move(continueCallback)); return true; } return false; 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 5866a8ad5..f6505a1d5 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 @@ -1070,7 +1070,6 @@ void VoiceRecordBar::init() { _lock->locks( ) | rpl::start_with_next([=] { - installClickOutsideFilter(); _level->setType(VoiceRecordButton::Type::Send); _level->clicks( @@ -1173,10 +1172,6 @@ void VoiceRecordBar::visibilityAnimate(bool show, Fn &&callback) { _showAnimation.start(std::move(animationCallback), from, to, duration); } -void VoiceRecordBar::setEscFilter(Fn &&callback) { - _escFilter = std::move(callback); -} - void VoiceRecordBar::setStartRecordingFilter(Fn &&callback) { _startRecordingFilter = std::move(callback); } @@ -1227,6 +1222,9 @@ void VoiceRecordBar::startRecording() { }, [=] { stop(false); }, _recordingLifetime); + _recordingLifetime.add([=] { + _recording = false; + }); }; visibilityAnimate(true, std::move(appearanceCallback)); show(); @@ -1287,7 +1285,6 @@ void VoiceRecordBar::stop(bool send) { void VoiceRecordBar::finish() { _recordingLifetime.destroy(); _lockShowing = false; - _recording = false; _inField = false; _redCircleProgress = 0.; _recordingSamples = 0; @@ -1411,7 +1408,7 @@ bool VoiceRecordBar::isRecording() const { return _recording.current(); } -bool VoiceRecordBar::preventDraftApply() const { +bool VoiceRecordBar::isActive() const { return isRecording() || isListenState(); } @@ -1419,7 +1416,7 @@ void VoiceRecordBar::hideAnimated() { if (isHidden()) { return; } - visibilityAnimate(false, [=] { hide(); }); + visibilityAnimate(false, [=] { hideFast(); }); } void VoiceRecordBar::finishAnimating() { @@ -1494,77 +1491,6 @@ void VoiceRecordBar::orderControls() { _lock->raise(); } -void VoiceRecordBar::installClickOutsideFilter() { - const auto box = _recordingLifetime.make_state>(); - const auto showBox = [=] { - if (*box) { - return; - } - auto sure = [=](Fn &&close) { - stop(false); - close(); - }; - *box = Ui::show(Box( - tr::lng_record_lock_cancel_sure(tr::now), - tr::lng_record_lock_discard(tr::now), - st::attentionBoxButton, - std::move(sure))); - }; - - const auto computeResult = [=](not_null e) { - using Type = FilterType; - if (!_lock->isLocked()) { - return Type::Continue; - } - const auto type = e->type(); - const auto noBox = !(*box); - if (type == QEvent::KeyPress) { - const auto key = static_cast(e.get())->key(); - const auto isEsc = (key == Qt::Key_Escape); - const auto isEnter = (key == Qt::Key_Enter - || key == Qt::Key_Return); - if (noBox) { - if (isEnter) { - stop(true); - return Type::Cancel; - } else if (isEsc && (_escFilter && _escFilter())) { - return Type::Continue; - } - return Type::ShowBox; - } - return (isEsc || isEnter) ? Type::Continue : Type::ShowBox; - } else if (type == QEvent::ContextMenu || type == QEvent::Shortcut) { - return Type::ShowBox; - } else if (type == QEvent::MouseButtonPress) { - return Type::Continue; - // return (noBox && !_inField.current() && !_lock->underMouse()) - // ? Type::ShowBox - // : Type::Continue; - } - return Type::Continue; - }; - - auto filterCallback = [=](not_null e) { - using Result = base::EventFilterResult; - switch(computeResult(e)) { - case FilterType::ShowBox: { - showBox(); - return Result::Cancel; - } - case FilterType::Continue: return Result::Continue; - case FilterType::Cancel: return Result::Cancel; - default: return Result::Continue; - } - }; - - auto filter = base::install_event_filter( - QCoreApplication::instance(), - std::move(filterCallback)); - - _recordingLifetime.make_state>( - std::move(filter)); -} - void VoiceRecordBar::installListenStateFilter() { auto keyFilterCallback = [=](not_null e) { using Result = base::EventFilterResult; @@ -1577,7 +1503,6 @@ void VoiceRecordBar::installListenStateFilter() { const auto keyEvent = static_cast(e.get()); const auto key = keyEvent->key(); const auto isSpace = (key == Qt::Key_Space); - const auto isEsc = (key == Qt::Key_Escape); const auto isEnter = (key == Qt::Key_Enter || key == Qt::Key_Return); if (isSpace && !keyEvent->isAutoRepeat() && _listen) { @@ -1588,14 +1513,6 @@ void VoiceRecordBar::installListenStateFilter() { requestToSendWithOptions({}); return Result::Cancel; } - if (isEsc) { - if (_escFilter && _escFilter()) { - return Result::Continue; - } else { - hideAnimated(); - return Result::Cancel; - } - } return Result::Continue; } default: return Result::Continue; @@ -1610,19 +1527,27 @@ void VoiceRecordBar::installListenStateFilter() { std::move(keyFilter)); } -void VoiceRecordBar::showDiscardRecordingBox(Fn &&callback) { - if (!isRecording()) { +void VoiceRecordBar::showDiscardBox( + Fn &&callback, + anim::type animated) { + if (!isActive()) { return; } auto sure = [=, callback = std::move(callback)](Fn &&close) { - hideFast(); + if (animated == anim::type::instant) { + hideFast(); + } else { + hideAnimated(); + } close(); if (callback) { callback(); } }; Ui::show(Box( - tr::lng_record_lock_cancel_sure(tr::now), + (isListenState() + ? tr::lng_record_listen_cancel_sure + : tr::lng_record_lock_cancel_sure)(tr::now), tr::lng_record_lock_discard(tr::now), st::attentionBoxButton, std::move(sure))); 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 ff25e279f..c7653ebc4 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 @@ -47,7 +47,9 @@ public: int recorderHeight); ~VoiceRecordBar(); - void showDiscardRecordingBox(Fn &&callback); + void showDiscardBox( + Fn &&callback, + anim::type animated = anim::type::instant); void startRecording(); void finishAnimating(); @@ -68,13 +70,12 @@ public: void setLockBottom(rpl::producer &&bottom); void setSendButtonGeometryValue(rpl::producer &&geometry); - void setEscFilter(Fn &&callback); void setStartRecordingFilter(Fn &&callback); [[nodiscard]] bool isRecording() const; [[nodiscard]] bool isLockPresent() const; [[nodiscard]] bool isListenState() const; - [[nodiscard]] bool preventDraftApply() const; + [[nodiscard]] bool isActive() const; private: enum class StopType { @@ -102,7 +103,6 @@ private: void drawMessage(Painter &p, float64 recordActive); void startRedCircleAnimation(); - void installClickOutsideFilter(); void installListenStateFilter(); bool isTypeRecord() const; @@ -137,7 +137,6 @@ private: Ui::Text::String _message; - Fn _escFilter; Fn _startRecordingFilter; rpl::variable _recording = false;