mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 22:27:20 +02:00
Added ability to use application while recording voice message.
This commit is contained in:
parent
dc7a754418
commit
77775b5f7c
5 changed files with 36 additions and 112 deletions
|
@ -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";
|
||||
|
|
|
@ -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<TabbedPanel> panel) {
|
|||
}
|
||||
|
||||
bool HistoryWidget::preventsClose(Fn<void()> &&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<HistoryItem*> item) {
|
||||
if (_voiceRecordBar && _voiceRecordBar->isListenState()) {
|
||||
if (_voiceRecordBar->isListenState()) {
|
||||
Ui::show(Box<InformBox>(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({});
|
||||
}
|
||||
|
|
|
@ -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<void()> &&continueCallback) const {
|
||||
if (isRecording()) {
|
||||
_voiceRecordBar->showDiscardRecordingBox(std::move(continueCallback));
|
||||
if (_voiceRecordBar->isActive()) {
|
||||
_voiceRecordBar->showDiscardBox(std::move(continueCallback));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -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<void()> &&callback) {
|
|||
_showAnimation.start(std::move(animationCallback), from, to, duration);
|
||||
}
|
||||
|
||||
void VoiceRecordBar::setEscFilter(Fn<bool()> &&callback) {
|
||||
_escFilter = std::move(callback);
|
||||
}
|
||||
|
||||
void VoiceRecordBar::setStartRecordingFilter(Fn<bool()> &&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<QPointer<ConfirmBox>>();
|
||||
const auto showBox = [=] {
|
||||
if (*box) {
|
||||
return;
|
||||
}
|
||||
auto sure = [=](Fn<void()> &&close) {
|
||||
stop(false);
|
||||
close();
|
||||
};
|
||||
*box = Ui::show(Box<ConfirmBox>(
|
||||
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<QEvent*> 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<QKeyEvent*>(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<QEvent*> 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<base::unique_qptr<QObject>>(
|
||||
std::move(filter));
|
||||
}
|
||||
|
||||
void VoiceRecordBar::installListenStateFilter() {
|
||||
auto keyFilterCallback = [=](not_null<QEvent*> e) {
|
||||
using Result = base::EventFilterResult;
|
||||
|
@ -1577,7 +1503,6 @@ void VoiceRecordBar::installListenStateFilter() {
|
|||
const auto keyEvent = static_cast<QKeyEvent*>(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<void()> &&callback) {
|
||||
if (!isRecording()) {
|
||||
void VoiceRecordBar::showDiscardBox(
|
||||
Fn<void()> &&callback,
|
||||
anim::type animated) {
|
||||
if (!isActive()) {
|
||||
return;
|
||||
}
|
||||
auto sure = [=, callback = std::move(callback)](Fn<void()> &&close) {
|
||||
hideFast();
|
||||
if (animated == anim::type::instant) {
|
||||
hideFast();
|
||||
} else {
|
||||
hideAnimated();
|
||||
}
|
||||
close();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
Ui::show(Box<ConfirmBox>(
|
||||
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)));
|
||||
|
|
|
@ -47,7 +47,9 @@ public:
|
|||
int recorderHeight);
|
||||
~VoiceRecordBar();
|
||||
|
||||
void showDiscardRecordingBox(Fn<void()> &&callback);
|
||||
void showDiscardBox(
|
||||
Fn<void()> &&callback,
|
||||
anim::type animated = anim::type::instant);
|
||||
|
||||
void startRecording();
|
||||
void finishAnimating();
|
||||
|
@ -68,13 +70,12 @@ public:
|
|||
|
||||
void setLockBottom(rpl::producer<int> &&bottom);
|
||||
void setSendButtonGeometryValue(rpl::producer<QRect> &&geometry);
|
||||
void setEscFilter(Fn<bool()> &&callback);
|
||||
void setStartRecordingFilter(Fn<bool()> &&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<bool()> _escFilter;
|
||||
Fn<bool()> _startRecordingFilter;
|
||||
|
||||
rpl::variable<bool> _recording = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue