mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +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_cancel" = "Release outside this field to cancel";
|
||||||
"lng_record_lock_cancel" = "Click outside of the circle 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_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_record_lock_discard" = "Discard";
|
||||||
"lng_will_be_notified" = "Members will be notified when you post";
|
"lng_will_be_notified" = "Members will be notified when you post";
|
||||||
"lng_wont_be_notified" = "Members will not 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->setLockBottom(std::move(scrollHeight));
|
||||||
}
|
}
|
||||||
_voiceRecordBar->setEscFilter([=]() -> bool {
|
|
||||||
return _replyToId || (_nonEmptySelection && _list);
|
|
||||||
});
|
|
||||||
|
|
||||||
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
|
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
|
||||||
|
|
||||||
|
@ -1629,7 +1626,7 @@ void HistoryWidget::applyDraft(FieldHistoryAction fieldHistoryAction) {
|
||||||
? _history->localEditDraft()
|
? _history->localEditDraft()
|
||||||
: _history->localDraft();
|
: _history->localDraft();
|
||||||
auto fieldAvailable = canWriteMessage()
|
auto fieldAvailable = canWriteMessage()
|
||||||
&& !_voiceRecordBar->preventDraftApply();
|
&& !_voiceRecordBar->isActive();
|
||||||
if (!draft || (!_history->localEditDraft() && !fieldAvailable)) {
|
if (!draft || (!_history->localEditDraft() && !fieldAvailable)) {
|
||||||
auto fieldWillBeHiddenAfterEdit = (!fieldAvailable && _editMsgId != 0);
|
auto fieldWillBeHiddenAfterEdit = (!fieldAvailable && _editMsgId != 0);
|
||||||
clearFieldText(0, fieldHistoryAction);
|
clearFieldText(0, fieldHistoryAction);
|
||||||
|
@ -3099,7 +3096,7 @@ void HistoryWidget::send(Api::SendOptions options) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_voiceRecordBar && _voiceRecordBar->isListenState()) {
|
if (_voiceRecordBar->isListenState()) {
|
||||||
_voiceRecordBar->requestToSendWithOptions(options);
|
_voiceRecordBar->requestToSendWithOptions(options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3915,8 +3912,8 @@ void HistoryWidget::setTabbedPanel(std::unique_ptr<TabbedPanel> panel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::preventsClose(Fn<void()> &&continueCallback) const {
|
bool HistoryWidget::preventsClose(Fn<void()> &&continueCallback) const {
|
||||||
if (isRecording()) {
|
if (_voiceRecordBar->isActive()) {
|
||||||
_voiceRecordBar->showDiscardRecordingBox(std::move(continueCallback));
|
_voiceRecordBar->showDiscardBox(std::move(continueCallback));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -5648,7 +5645,7 @@ void HistoryWidget::editMessage(FullMsgId itemId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::editMessage(not_null<HistoryItem*> item) {
|
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)));
|
Ui::show(Box<InformBox>(tr::lng_edit_caption_voice(tr::now)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -6122,6 +6119,8 @@ void HistoryWidget::escape() {
|
||||||
_fieldAutocomplete->hideAnimated();
|
_fieldAutocomplete->hideAnimated();
|
||||||
} else if (_replyToId && _field->getTextWithTags().text.isEmpty()) {
|
} else if (_replyToId && _field->getTextWithTags().text.isEmpty()) {
|
||||||
cancelReply();
|
cancelReply();
|
||||||
|
} else if (auto &voice = _voiceRecordBar; voice->isActive()) {
|
||||||
|
voice->showDiscardBox(nullptr, anim::type::normal);
|
||||||
} else {
|
} else {
|
||||||
_cancelRequests.fire({});
|
_cancelRequests.fire({});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1567,10 +1567,6 @@ void ComposeControls::initVoiceRecordBar() {
|
||||||
_voiceRecordBar->setLockBottom(std::move(bottom));
|
_voiceRecordBar->setLockBottom(std::move(bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
_voiceRecordBar->setEscFilter([=] {
|
|
||||||
return (isEditingMessage() || replyingToMessage());
|
|
||||||
});
|
|
||||||
|
|
||||||
_voiceRecordBar->updateSendButtonTypeRequests(
|
_voiceRecordBar->updateSendButtonTypeRequests(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
updateSendButtonType();
|
updateSendButtonType();
|
||||||
|
@ -1716,7 +1712,11 @@ void ComposeControls::paintBackground(QRect clip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComposeControls::escape() {
|
void ComposeControls::escape() {
|
||||||
|
if (auto &voice = _voiceRecordBar; !voice->isActive()) {
|
||||||
|
voice->showDiscardBox(nullptr, anim::type::normal);
|
||||||
|
} else {
|
||||||
_cancelRequests.fire({});
|
_cancelRequests.fire({});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ComposeControls::pushTabbedSelectorToThirdSection(
|
bool ComposeControls::pushTabbedSelectorToThirdSection(
|
||||||
|
@ -2139,8 +2139,8 @@ bool ComposeControls::isRecording() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ComposeControls::preventsClose(Fn<void()> &&continueCallback) const {
|
bool ComposeControls::preventsClose(Fn<void()> &&continueCallback) const {
|
||||||
if (isRecording()) {
|
if (_voiceRecordBar->isActive()) {
|
||||||
_voiceRecordBar->showDiscardRecordingBox(std::move(continueCallback));
|
_voiceRecordBar->showDiscardBox(std::move(continueCallback));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1070,7 +1070,6 @@ void VoiceRecordBar::init() {
|
||||||
|
|
||||||
_lock->locks(
|
_lock->locks(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
installClickOutsideFilter();
|
|
||||||
_level->setType(VoiceRecordButton::Type::Send);
|
_level->setType(VoiceRecordButton::Type::Send);
|
||||||
|
|
||||||
_level->clicks(
|
_level->clicks(
|
||||||
|
@ -1173,10 +1172,6 @@ void VoiceRecordBar::visibilityAnimate(bool show, Fn<void()> &&callback) {
|
||||||
_showAnimation.start(std::move(animationCallback), from, to, duration);
|
_showAnimation.start(std::move(animationCallback), from, to, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::setEscFilter(Fn<bool()> &&callback) {
|
|
||||||
_escFilter = std::move(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceRecordBar::setStartRecordingFilter(Fn<bool()> &&callback) {
|
void VoiceRecordBar::setStartRecordingFilter(Fn<bool()> &&callback) {
|
||||||
_startRecordingFilter = std::move(callback);
|
_startRecordingFilter = std::move(callback);
|
||||||
}
|
}
|
||||||
|
@ -1227,6 +1222,9 @@ void VoiceRecordBar::startRecording() {
|
||||||
}, [=] {
|
}, [=] {
|
||||||
stop(false);
|
stop(false);
|
||||||
}, _recordingLifetime);
|
}, _recordingLifetime);
|
||||||
|
_recordingLifetime.add([=] {
|
||||||
|
_recording = false;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
visibilityAnimate(true, std::move(appearanceCallback));
|
visibilityAnimate(true, std::move(appearanceCallback));
|
||||||
show();
|
show();
|
||||||
|
@ -1287,7 +1285,6 @@ void VoiceRecordBar::stop(bool send) {
|
||||||
void VoiceRecordBar::finish() {
|
void VoiceRecordBar::finish() {
|
||||||
_recordingLifetime.destroy();
|
_recordingLifetime.destroy();
|
||||||
_lockShowing = false;
|
_lockShowing = false;
|
||||||
_recording = false;
|
|
||||||
_inField = false;
|
_inField = false;
|
||||||
_redCircleProgress = 0.;
|
_redCircleProgress = 0.;
|
||||||
_recordingSamples = 0;
|
_recordingSamples = 0;
|
||||||
|
@ -1411,7 +1408,7 @@ bool VoiceRecordBar::isRecording() const {
|
||||||
return _recording.current();
|
return _recording.current();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoiceRecordBar::preventDraftApply() const {
|
bool VoiceRecordBar::isActive() const {
|
||||||
return isRecording() || isListenState();
|
return isRecording() || isListenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1419,7 +1416,7 @@ void VoiceRecordBar::hideAnimated() {
|
||||||
if (isHidden()) {
|
if (isHidden()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
visibilityAnimate(false, [=] { hide(); });
|
visibilityAnimate(false, [=] { hideFast(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::finishAnimating() {
|
void VoiceRecordBar::finishAnimating() {
|
||||||
|
@ -1494,77 +1491,6 @@ void VoiceRecordBar::orderControls() {
|
||||||
_lock->raise();
|
_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() {
|
void VoiceRecordBar::installListenStateFilter() {
|
||||||
auto keyFilterCallback = [=](not_null<QEvent*> e) {
|
auto keyFilterCallback = [=](not_null<QEvent*> e) {
|
||||||
using Result = base::EventFilterResult;
|
using Result = base::EventFilterResult;
|
||||||
|
@ -1577,7 +1503,6 @@ void VoiceRecordBar::installListenStateFilter() {
|
||||||
const auto keyEvent = static_cast<QKeyEvent*>(e.get());
|
const auto keyEvent = static_cast<QKeyEvent*>(e.get());
|
||||||
const auto key = keyEvent->key();
|
const auto key = keyEvent->key();
|
||||||
const auto isSpace = (key == Qt::Key_Space);
|
const auto isSpace = (key == Qt::Key_Space);
|
||||||
const auto isEsc = (key == Qt::Key_Escape);
|
|
||||||
const auto isEnter = (key == Qt::Key_Enter
|
const auto isEnter = (key == Qt::Key_Enter
|
||||||
|| key == Qt::Key_Return);
|
|| key == Qt::Key_Return);
|
||||||
if (isSpace && !keyEvent->isAutoRepeat() && _listen) {
|
if (isSpace && !keyEvent->isAutoRepeat() && _listen) {
|
||||||
|
@ -1588,14 +1513,6 @@ void VoiceRecordBar::installListenStateFilter() {
|
||||||
requestToSendWithOptions({});
|
requestToSendWithOptions({});
|
||||||
return Result::Cancel;
|
return Result::Cancel;
|
||||||
}
|
}
|
||||||
if (isEsc) {
|
|
||||||
if (_escFilter && _escFilter()) {
|
|
||||||
return Result::Continue;
|
|
||||||
} else {
|
|
||||||
hideAnimated();
|
|
||||||
return Result::Cancel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Result::Continue;
|
return Result::Continue;
|
||||||
}
|
}
|
||||||
default: return Result::Continue;
|
default: return Result::Continue;
|
||||||
|
@ -1610,19 +1527,27 @@ void VoiceRecordBar::installListenStateFilter() {
|
||||||
std::move(keyFilter));
|
std::move(keyFilter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::showDiscardRecordingBox(Fn<void()> &&callback) {
|
void VoiceRecordBar::showDiscardBox(
|
||||||
if (!isRecording()) {
|
Fn<void()> &&callback,
|
||||||
|
anim::type animated) {
|
||||||
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto sure = [=, callback = std::move(callback)](Fn<void()> &&close) {
|
auto sure = [=, callback = std::move(callback)](Fn<void()> &&close) {
|
||||||
|
if (animated == anim::type::instant) {
|
||||||
hideFast();
|
hideFast();
|
||||||
|
} else {
|
||||||
|
hideAnimated();
|
||||||
|
}
|
||||||
close();
|
close();
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ui::show(Box<ConfirmBox>(
|
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),
|
tr::lng_record_lock_discard(tr::now),
|
||||||
st::attentionBoxButton,
|
st::attentionBoxButton,
|
||||||
std::move(sure)));
|
std::move(sure)));
|
||||||
|
|
|
@ -47,7 +47,9 @@ public:
|
||||||
int recorderHeight);
|
int recorderHeight);
|
||||||
~VoiceRecordBar();
|
~VoiceRecordBar();
|
||||||
|
|
||||||
void showDiscardRecordingBox(Fn<void()> &&callback);
|
void showDiscardBox(
|
||||||
|
Fn<void()> &&callback,
|
||||||
|
anim::type animated = anim::type::instant);
|
||||||
|
|
||||||
void startRecording();
|
void startRecording();
|
||||||
void finishAnimating();
|
void finishAnimating();
|
||||||
|
@ -68,13 +70,12 @@ public:
|
||||||
|
|
||||||
void setLockBottom(rpl::producer<int> &&bottom);
|
void setLockBottom(rpl::producer<int> &&bottom);
|
||||||
void setSendButtonGeometryValue(rpl::producer<QRect> &&geometry);
|
void setSendButtonGeometryValue(rpl::producer<QRect> &&geometry);
|
||||||
void setEscFilter(Fn<bool()> &&callback);
|
|
||||||
void setStartRecordingFilter(Fn<bool()> &&callback);
|
void setStartRecordingFilter(Fn<bool()> &&callback);
|
||||||
|
|
||||||
[[nodiscard]] bool isRecording() const;
|
[[nodiscard]] bool isRecording() const;
|
||||||
[[nodiscard]] bool isLockPresent() const;
|
[[nodiscard]] bool isLockPresent() const;
|
||||||
[[nodiscard]] bool isListenState() const;
|
[[nodiscard]] bool isListenState() const;
|
||||||
[[nodiscard]] bool preventDraftApply() const;
|
[[nodiscard]] bool isActive() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class StopType {
|
enum class StopType {
|
||||||
|
@ -102,7 +103,6 @@ private:
|
||||||
void drawMessage(Painter &p, float64 recordActive);
|
void drawMessage(Painter &p, float64 recordActive);
|
||||||
|
|
||||||
void startRedCircleAnimation();
|
void startRedCircleAnimation();
|
||||||
void installClickOutsideFilter();
|
|
||||||
void installListenStateFilter();
|
void installListenStateFilter();
|
||||||
|
|
||||||
bool isTypeRecord() const;
|
bool isTypeRecord() const;
|
||||||
|
@ -137,7 +137,6 @@ private:
|
||||||
|
|
||||||
Ui::Text::String _message;
|
Ui::Text::String _message;
|
||||||
|
|
||||||
Fn<bool()> _escFilter;
|
|
||||||
Fn<bool()> _startRecordingFilter;
|
Fn<bool()> _startRecordingFilter;
|
||||||
|
|
||||||
rpl::variable<bool> _recording = false;
|
rpl::variable<bool> _recording = false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue