mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 07:07:08 +02:00
Show recording progress.
This commit is contained in:
parent
f74dd3ca1e
commit
e59e4afd3e
4 changed files with 105 additions and 20 deletions
Telegram/SourceFiles
history/view/controls
ui/controls
|
@ -1534,13 +1534,11 @@ void VoiceRecordBar::init() {
|
|||
if (_startRecordingFilter && _startRecordingFilter()) {
|
||||
return;
|
||||
}
|
||||
_recordingTipRequired = true;
|
||||
_recordingTipRequire = crl::now();
|
||||
_recordingVideo = (_send->type() == Ui::SendButton::Type::Round);
|
||||
_startTimer.callOnce(st::universalDuration);
|
||||
} else if (e->type() == QEvent::MouseButtonRelease) {
|
||||
if (base::take(_recordingTipRequired)) {
|
||||
_recordingTipRequests.fire({});
|
||||
}
|
||||
checkTipRequired();
|
||||
_startTimer.cancel();
|
||||
}
|
||||
}, lifetime());
|
||||
|
@ -1694,7 +1692,6 @@ void VoiceRecordBar::startRecording() {
|
|||
}
|
||||
instance()->updated(
|
||||
) | rpl::start_with_next_error([=](const Update &update) {
|
||||
_recordingTipRequired = (update.samples < kMinSamples);
|
||||
recordUpdated(update.level, update.samples);
|
||||
}, [=] {
|
||||
stop(false);
|
||||
|
@ -1702,10 +1699,9 @@ void VoiceRecordBar::startRecording() {
|
|||
if (_videoRecorder) {
|
||||
_videoRecorder->updated(
|
||||
) | rpl::start_with_next_error([=](const Update &update) {
|
||||
_recordingTipRequired = (update.samples < kMinSamples);
|
||||
recordUpdated(update.level, update.samples);
|
||||
if (update.finished) {
|
||||
stop(true);
|
||||
stop(update.samples >= kMinSamples);
|
||||
}
|
||||
}, [=] {
|
||||
stop(false);
|
||||
|
@ -1742,14 +1738,22 @@ void VoiceRecordBar::startRecording() {
|
|||
}
|
||||
computeAndSetLockProgress(mouse->globalPos());
|
||||
} else if (type == QEvent::MouseButtonRelease) {
|
||||
if (base::take(_recordingTipRequired)) {
|
||||
_recordingTipRequests.fire({});
|
||||
}
|
||||
checkTipRequired();
|
||||
stop(_inField.current());
|
||||
}
|
||||
}, _recordingLifetime);
|
||||
}
|
||||
|
||||
void VoiceRecordBar::checkTipRequired() {
|
||||
const auto require = base::take(_recordingTipRequire);
|
||||
const auto duration = st::universalDuration
|
||||
+ (kMinSamples * crl::time(1000)
|
||||
/ ::Media::Player::kDefaultFrequency);
|
||||
if (require && (require + duration > crl::now())) {
|
||||
_recordingTipRequests.fire({});
|
||||
}
|
||||
}
|
||||
|
||||
void VoiceRecordBar::recordUpdated(quint16 level, int samples) {
|
||||
_level->requestPaintLevel(level);
|
||||
_recordingSamples = samples;
|
||||
|
|
|
@ -124,6 +124,7 @@ private:
|
|||
void updateTTLGeometry(TTLAnimationType type, float64 progress);
|
||||
|
||||
void recordUpdated(quint16 level, int samples);
|
||||
void checkTipRequired();
|
||||
|
||||
void stop(bool send);
|
||||
void stopRecording(StopType type, bool ttlBeforeHide = false);
|
||||
|
@ -192,7 +193,7 @@ private:
|
|||
float64 _redCircleProgress = 0.;
|
||||
|
||||
rpl::event_stream<> _recordingTipRequests;
|
||||
bool _recordingTipRequired = false;
|
||||
crl::time _recordingTipRequire = 0;
|
||||
bool _lockFromBottom = false;
|
||||
|
||||
std::unique_ptr<Ui::RoundVideoRecorder> _videoRecorder;
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ffmpeg/ffmpeg_utility.h"
|
||||
#include "media/audio/media_audio_capture.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/arc_angles.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rp_widget.h"
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
|
@ -703,10 +704,14 @@ Fn<void(Media::Capture::Chunk)> RoundVideoRecorder::audioChunkProcessor() {
|
|||
};
|
||||
}
|
||||
|
||||
auto RoundVideoRecorder::updated() const
|
||||
auto RoundVideoRecorder::updated()
|
||||
-> rpl::producer<Update, rpl::empty_error> {
|
||||
return _private.producer_on_main([](const Private &that) {
|
||||
return that.updated();
|
||||
}) | rpl::before_next([=](const Update &update) {
|
||||
const auto duration = (update.samples * crl::time(1000))
|
||||
/ kAudioFrequency;
|
||||
progressTo(duration / (1. * kMaxDuration));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -725,6 +730,19 @@ void RoundVideoRecorder::hide(Fn<void(RoundVideoResult)> done) {
|
|||
}
|
||||
}
|
||||
|
||||
void RoundVideoRecorder::progressTo(float64 progress) {
|
||||
if (_progress == progress) {
|
||||
return;
|
||||
}
|
||||
_progressAnimation.start(
|
||||
[=] { _preview->update(); },
|
||||
progress,
|
||||
_progress,
|
||||
kUpdateEach);
|
||||
_progress = progress;
|
||||
_preview->update();
|
||||
}
|
||||
|
||||
void RoundVideoRecorder::prepareFrame() {
|
||||
if (_frameOriginal.isNull() || _preparedIndex == _lastAddedIndex) {
|
||||
return;
|
||||
|
@ -755,29 +773,82 @@ void RoundVideoRecorder::prepareFrame() {
|
|||
_framePrepared.setDevicePixelRatio(ratio);
|
||||
}
|
||||
|
||||
void RoundVideoRecorder::createImages() {
|
||||
const auto ratio = style::DevicePixelRatio();
|
||||
_framePrepared = QImage(
|
||||
QSize(_side, _side) * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
_framePrepared.fill(Qt::transparent);
|
||||
_framePrepared.setDevicePixelRatio(ratio);
|
||||
auto p = QPainter(&_framePrepared);
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::black);
|
||||
p.drawEllipse(0, 0, _side, _side);
|
||||
|
||||
const auto side = _side + 2 * _extent;
|
||||
_shadow = QImage(
|
||||
QSize(side, side) * ratio,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
_shadow.fill(Qt::transparent);
|
||||
_shadow.setDevicePixelRatio(ratio);
|
||||
|
||||
auto sp = QPainter(&_shadow);
|
||||
auto shq = PainterHighQualityEnabler(sp);
|
||||
|
||||
QRadialGradient gradient(
|
||||
QPointF(_extent + _side / 2, _extent + _side / 2),
|
||||
_side / 2 + _extent);
|
||||
gradient.setColorAt(0, QColor(0, 0, 0, 128));
|
||||
gradient.setColorAt(0.8, QColor(0, 0, 0, 64));
|
||||
gradient.setColorAt(1, QColor(0, 0, 0, 0));
|
||||
|
||||
sp.setPen(Qt::NoPen);
|
||||
sp.fillRect(0, 0, side, side, gradient);
|
||||
sp.end();
|
||||
}
|
||||
|
||||
void RoundVideoRecorder::setup() {
|
||||
const auto raw = _preview.get();
|
||||
|
||||
_side = style::ConvertScale(kSide * 3 / 4);
|
||||
_progressStroke = st::radialLine;
|
||||
_extent = _progressStroke * 8;
|
||||
createImages();
|
||||
|
||||
_descriptor.container->sizeValue(
|
||||
) | rpl::start_with_next([=](QSize outer) {
|
||||
const auto side = _side + 2 * _extent;
|
||||
raw->setGeometry(
|
||||
style::centerrect(
|
||||
QRect(QPoint(), outer),
|
||||
QRect(0, 0, _side, _side)));
|
||||
QRect(0, 0, side, side)));
|
||||
}, raw->lifetime());
|
||||
|
||||
raw->paintRequest() | rpl::start_with_next([=] {
|
||||
prepareFrame();
|
||||
|
||||
auto p = QPainter(raw);
|
||||
if (!_framePrepared.isNull()) {
|
||||
p.drawImage(QRect(0, 0, _side, _side), _framePrepared);
|
||||
} else {
|
||||
p.drawImage(raw->rect(), _shadow);
|
||||
const auto inner = QRect(_extent, _extent, _side, _side);
|
||||
p.drawImage(inner, _framePrepared);
|
||||
if (_progress > 0.) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(QColor(0, 0, 0));
|
||||
p.drawEllipse(0, 0, _side, _side);
|
||||
p.setPen(QPen(
|
||||
Qt::white,
|
||||
_progressStroke,
|
||||
Qt::SolidLine,
|
||||
Qt::RoundCap));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
const auto add = _progressStroke * 3 / 2.;
|
||||
const auto full = arc::kFullLength;
|
||||
const auto length = int(base::SafeRound(
|
||||
_progressAnimation.value(_progress) * full));
|
||||
p.drawArc(
|
||||
QRectF(inner).marginsAdded({ add, add, add, add }),
|
||||
(full / 4) - length,
|
||||
length);
|
||||
}
|
||||
}, raw->lifetime());
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include "ui/effects/animations.h"
|
||||
|
||||
#include <crl/crl_object_on_queue.h>
|
||||
|
||||
namespace Media::Capture {
|
||||
|
@ -51,22 +53,29 @@ public:
|
|||
void hide(Fn<void(RoundVideoResult)> done = nullptr);
|
||||
|
||||
using Update = Media::Capture::Update;
|
||||
[[nodiscard]] rpl::producer<Update, rpl::empty_error> updated() const;
|
||||
[[nodiscard]] rpl::producer<Update, rpl::empty_error> updated();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
|
||||
void setup();
|
||||
void prepareFrame();
|
||||
void createImages();
|
||||
void progressTo(float64 progress);
|
||||
|
||||
const RoundVideoRecorderDescriptor _descriptor;
|
||||
std::unique_ptr<RpWidget> _preview;
|
||||
crl::object_on_queue<Private> _private;
|
||||
Ui::Animations::Simple _progressAnimation;
|
||||
float64 _progress = 0.;
|
||||
QImage _frameOriginal;
|
||||
QImage _framePrepared;
|
||||
QImage _shadow;
|
||||
int _lastAddedIndex = 0;
|
||||
int _preparedIndex = 0;
|
||||
int _side = 0;
|
||||
int _progressStroke = 0;
|
||||
int _extent = 0;
|
||||
bool _paused = false;
|
||||
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue