mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 15:43:55 +02:00
Improved VoiceRecordBar support in ComposeControls.
This commit is contained in:
parent
6ed7615653
commit
ad4bf9b5c8
7 changed files with 110 additions and 18 deletions
|
@ -730,6 +730,8 @@ void HistoryWidget::initVoiceRecordBar() {
|
|||
return _replyToId || (_nonEmptySelection && _list);
|
||||
});
|
||||
|
||||
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
|
||||
|
||||
_voiceRecordBar->startRecordingRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto error = _peer
|
||||
|
|
|
@ -494,7 +494,7 @@ MessageToEdit FieldHeader::queryToEdit() {
|
|||
}
|
||||
|
||||
ComposeControls::ComposeControls(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Window::SessionController*> window,
|
||||
Mode mode)
|
||||
: _parent(parent)
|
||||
|
@ -520,6 +520,7 @@ ComposeControls::ComposeControls(
|
|||
&_window->session().data()))
|
||||
, _voiceRecordBar(std::make_unique<VoiceRecordBar>(
|
||||
_wrap.get(),
|
||||
parent,
|
||||
window,
|
||||
_send,
|
||||
st::historySendSize.height()))
|
||||
|
@ -671,6 +672,7 @@ void ComposeControls::showFinished() {
|
|||
_tabbedPanel->hideFast();
|
||||
}
|
||||
updateWrappingVisibility();
|
||||
_voiceRecordBar->orderControls();
|
||||
}
|
||||
|
||||
void ComposeControls::showForGrab() {
|
||||
|
@ -928,6 +930,30 @@ void ComposeControls::initVoiceRecordBar() {
|
|||
}
|
||||
_voiceRecordBar->startRecording();
|
||||
}, _wrap->lifetime());
|
||||
|
||||
{
|
||||
auto geometry = rpl::merge(
|
||||
_wrap->geometryValue(),
|
||||
_send->geometryValue()
|
||||
) | rpl::map([=](QRect geometry) {
|
||||
auto r = _send->geometry();
|
||||
r.setY(r.y() + _wrap->y());
|
||||
return r;
|
||||
});
|
||||
_voiceRecordBar->setSendButtonGeometryValue(std::move(geometry));
|
||||
}
|
||||
|
||||
{
|
||||
auto bottom = _wrap->geometryValue(
|
||||
) | rpl::map([=](QRect geometry) {
|
||||
return geometry.y() - st::historyRecordLockPosition.y();
|
||||
});
|
||||
_voiceRecordBar->setLockBottom(std::move(bottom));
|
||||
}
|
||||
|
||||
_voiceRecordBar->setEscFilter([=] {
|
||||
return (isEditingMessage() || replyingToMessage());
|
||||
});
|
||||
}
|
||||
|
||||
void ComposeControls::updateWrappingVisibility() {
|
||||
|
@ -1311,4 +1337,12 @@ FullMsgId ComposeControls::replyingToMessage() const {
|
|||
return _header->replyingToMessage();
|
||||
}
|
||||
|
||||
bool ComposeControls::isLockPresent() const {
|
||||
return _voiceRecordBar->isLockPresent();
|
||||
}
|
||||
|
||||
rpl::producer<bool> ComposeControls::lockShowStarts() const {
|
||||
return _voiceRecordBar->lockShowStarts();
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
};
|
||||
|
||||
ComposeControls(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Window::SessionController*> window,
|
||||
Mode mode);
|
||||
~ComposeControls();
|
||||
|
@ -135,6 +135,9 @@ public:
|
|||
void clear();
|
||||
void hidePanelsAnimated();
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> lockShowStarts() const;
|
||||
[[nodiscard]] bool isLockPresent() const;
|
||||
|
||||
private:
|
||||
enum class TextUpdateEvent {
|
||||
//SaveDraft = (1 << 0),
|
||||
|
|
|
@ -156,8 +156,15 @@ bool RecordLevel::recordingAnimationCallback(crl::time now) {
|
|||
}
|
||||
|
||||
void RecordLevel::init() {
|
||||
const auto hasProgress = [](auto value) { return value != 0.; };
|
||||
|
||||
// Do not allow the widget to be shown from the outside.
|
||||
shownValue(
|
||||
) | rpl::start_with_next([=](bool shown) {
|
||||
const auto shouldShown = hasProgress(_showProgress.current());
|
||||
if (shown != shouldShown) {
|
||||
setVisible(shouldShown);
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
paintRequest(
|
||||
|
@ -170,9 +177,7 @@ void RecordLevel::init() {
|
|||
}, lifetime());
|
||||
|
||||
_showProgress.changes(
|
||||
) | rpl::map([](auto value) {
|
||||
return value != 0.;
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::map(hasProgress) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=](bool show) {
|
||||
setVisible(show);
|
||||
setMouseTracking(show);
|
||||
|
@ -395,21 +400,31 @@ rpl::producer<> RecordLock::locks() const {
|
|||
|
||||
VoiceRecordBar::VoiceRecordBar(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Ui::RpWidget*> sectionWidget,
|
||||
not_null<Window::SessionController*> controller,
|
||||
std::shared_ptr<Ui::SendButton> send,
|
||||
int recorderHeight)
|
||||
: RpWidget(parent)
|
||||
, _sectionWidget(sectionWidget)
|
||||
, _controller(controller)
|
||||
, _send(send)
|
||||
, _lock(std::make_unique<RecordLock>(parent))
|
||||
, _lock(std::make_unique<RecordLock>(sectionWidget))
|
||||
, _level(std::make_unique<RecordLevel>(
|
||||
parent,
|
||||
sectionWidget,
|
||||
_controller->widget()->leaveEvents()))
|
||||
, _cancelFont(st::historyRecordFont) {
|
||||
resize(QSize(parent->width(), recorderHeight));
|
||||
init();
|
||||
}
|
||||
|
||||
VoiceRecordBar::VoiceRecordBar(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
std::shared_ptr<Ui::SendButton> send,
|
||||
int recorderHeight)
|
||||
: VoiceRecordBar(parent, parent, controller, send, recorderHeight) {
|
||||
}
|
||||
|
||||
VoiceRecordBar::~VoiceRecordBar() {
|
||||
if (isRecording()) {
|
||||
stopRecording(false);
|
||||
|
@ -444,11 +459,6 @@ void VoiceRecordBar::updateLockGeometry() {
|
|||
_lock->moveToRight(right, _lock->y());
|
||||
}
|
||||
|
||||
void VoiceRecordBar::updateLevelGeometry() {
|
||||
const auto center = (_send->width() - _level->width()) / 2;
|
||||
_level->moveToRight(st::historySendRight + center, y() + center);
|
||||
}
|
||||
|
||||
void VoiceRecordBar::init() {
|
||||
hide();
|
||||
// Keep VoiceRecordBar behind SendButton.
|
||||
|
@ -459,8 +469,7 @@ void VoiceRecordBar::init() {
|
|||
return e->type() == QEvent::ZOrderChange;
|
||||
}) | rpl::to_empty
|
||||
) | rpl::start_with_next([=] {
|
||||
stackUnder(_send.get());
|
||||
_level->raise();
|
||||
orderControls();
|
||||
}, lifetime());
|
||||
|
||||
sizeValue(
|
||||
|
@ -484,7 +493,6 @@ void VoiceRecordBar::init() {
|
|||
}
|
||||
updateMessageGeometry();
|
||||
updateLockGeometry();
|
||||
updateLevelGeometry();
|
||||
}, lifetime());
|
||||
|
||||
paintRequest(
|
||||
|
@ -606,7 +614,16 @@ void VoiceRecordBar::setLockBottom(rpl::producer<int> &&bottom) {
|
|||
bottom
|
||||
) | rpl::start_with_next([=](int value) {
|
||||
_lock->moveToLeft(_lock->x(), value - _lock->height());
|
||||
updateLevelGeometry();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void VoiceRecordBar::setSendButtonGeometryValue(
|
||||
rpl::producer<QRect> &&geometry) {
|
||||
std::move(
|
||||
geometry
|
||||
) | rpl::start_with_next([=](QRect r) {
|
||||
const auto center = (r.width() - _level->width()) / 2;
|
||||
_level->moveToLeft(r.x() + center, r.y() + center);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
|
@ -660,7 +677,7 @@ void VoiceRecordBar::startRecording() {
|
|||
? inField
|
||||
: _level->inCircle(_level->mapFromGlobal(globalPos));
|
||||
|
||||
if (_showLockAnimation.animating()) {
|
||||
if (_showLockAnimation.animating() || !hasDuration()) {
|
||||
return;
|
||||
}
|
||||
computeAndSetLockProgress(mouse->globalPos());
|
||||
|
@ -813,6 +830,10 @@ bool VoiceRecordBar::isTypeRecord() const {
|
|||
return (_send->type() == Ui::SendButton::Type::Record);
|
||||
}
|
||||
|
||||
bool VoiceRecordBar::hasDuration() const {
|
||||
return _recordingSamples > 0;
|
||||
}
|
||||
|
||||
float64 VoiceRecordBar::activeAnimationRatio() const {
|
||||
return _activeAnimation.value(_inField.current() ? 1. : 0.);
|
||||
}
|
||||
|
@ -837,6 +858,12 @@ void VoiceRecordBar::computeAndSetLockProgress(QPoint globalPos) {
|
|||
_lock->requestPaintProgress(std::clamp(progress, 0., 1.));
|
||||
}
|
||||
|
||||
void VoiceRecordBar::orderControls() {
|
||||
stackUnder(_send.get());
|
||||
_level->raise();
|
||||
_lock->raise();
|
||||
}
|
||||
|
||||
void VoiceRecordBar::installClickOutsideFilter() {
|
||||
const auto box = _recordingLifetime.make_state<QPointer<ConfirmBox>>();
|
||||
const auto showBox = [=] {
|
||||
|
|
|
@ -30,6 +30,12 @@ public:
|
|||
using SendActionUpdate = Controls::SendActionUpdate;
|
||||
using VoiceToSend = Controls::VoiceToSend;
|
||||
|
||||
VoiceRecordBar(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Ui::RpWidget*> sectionWidget,
|
||||
not_null<Window::SessionController*> controller,
|
||||
std::shared_ptr<Ui::SendButton> send,
|
||||
int recorderHeight);
|
||||
VoiceRecordBar(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
|
@ -40,6 +46,8 @@ public:
|
|||
void startRecording();
|
||||
void finishAnimating();
|
||||
|
||||
void orderControls();
|
||||
|
||||
[[nodiscard]] rpl::producer<SendActionUpdate> sendActionUpdates() const;
|
||||
[[nodiscard]] rpl::producer<VoiceToSend> sendVoiceRequests() const;
|
||||
[[nodiscard]] rpl::producer<bool> recordingStateChanges() const;
|
||||
|
@ -47,6 +55,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<bool> lockShowStarts() const;
|
||||
|
||||
void setLockBottom(rpl::producer<int> &&bottom);
|
||||
void setSendButtonGeometryValue(rpl::producer<QRect> &&geometry);
|
||||
void setEscFilter(Fn<bool()> &&callback);
|
||||
|
||||
[[nodiscard]] bool isRecording() const;
|
||||
|
@ -57,7 +66,6 @@ private:
|
|||
|
||||
void updateMessageGeometry();
|
||||
void updateLockGeometry();
|
||||
void updateLevelGeometry();
|
||||
|
||||
void recordError();
|
||||
void recordUpdated(quint16 level, int samples);
|
||||
|
@ -78,6 +86,7 @@ private:
|
|||
void installClickOutsideFilter();
|
||||
|
||||
bool isTypeRecord() const;
|
||||
bool hasDuration() const;
|
||||
|
||||
void activeAnimate(bool active);
|
||||
float64 showAnimationRatio() const;
|
||||
|
@ -87,6 +96,7 @@ private:
|
|||
|
||||
QString cancelMessage() const;
|
||||
|
||||
const not_null<Ui::RpWidget*> _sectionWidget;
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const std::shared_ptr<Ui::SendButton> _send;
|
||||
const std::unique_ptr<RecordLock> _lock;
|
||||
|
|
|
@ -507,6 +507,11 @@ void RepliesWidget::setupComposeControls() {
|
|||
Unexpected("action in MimeData hook.");
|
||||
});
|
||||
|
||||
_composeControls->lockShowStarts(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateScrollDownVisibility();
|
||||
}, lifetime());
|
||||
|
||||
_composeControls->finishAnimating();
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1218,9 @@ void RepliesWidget::updateScrollDownVisibility() {
|
|||
}
|
||||
|
||||
const auto scrollDownIsVisible = [&]() -> std::optional<bool> {
|
||||
if (_composeControls->isLockPresent()) {
|
||||
return false;
|
||||
}
|
||||
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
|
||||
if (top < _scroll->scrollTopMax() || _replyReturn) {
|
||||
return true;
|
||||
|
|
|
@ -253,6 +253,11 @@ void ScheduledWidget::setupComposeControls() {
|
|||
}
|
||||
Unexpected("action in MimeData hook.");
|
||||
});
|
||||
|
||||
_composeControls->lockShowStarts(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateScrollDownVisibility();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void ScheduledWidget::chooseAttach() {
|
||||
|
@ -820,6 +825,9 @@ void ScheduledWidget::updateScrollDownVisibility() {
|
|||
}
|
||||
|
||||
const auto scrollDownIsVisible = [&]() -> std::optional<bool> {
|
||||
if (_composeControls->isLockPresent()) {
|
||||
return false;
|
||||
}
|
||||
const auto top = _scroll->scrollTop() + st::historyToDownShownAfter;
|
||||
if (top < _scroll->scrollTopMax()) {
|
||||
return true;
|
||||
|
|
Loading…
Add table
Reference in a new issue