Finish theming for voice recording in stories.
This commit is contained in:
parent
a02876562a
commit
00b4f77384
|
@ -139,6 +139,29 @@ SendButton {
|
||||||
sendDisabledFg: color;
|
sendDisabledFg: color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordBarLock {
|
||||||
|
ripple: RippleAnimation;
|
||||||
|
originTop: icon;
|
||||||
|
originBottom: icon;
|
||||||
|
originBody: icon;
|
||||||
|
shadowTop: icon;
|
||||||
|
shadowBottom: icon;
|
||||||
|
shadowBody: icon;
|
||||||
|
arrow: icon;
|
||||||
|
fg: color;
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordBar {
|
||||||
|
radius: pixels;
|
||||||
|
bg: color;
|
||||||
|
durationFg: color;
|
||||||
|
cancel: color;
|
||||||
|
cancelActive: color;
|
||||||
|
cancelRipple: RippleAnimation;
|
||||||
|
lock: RecordBarLock;
|
||||||
|
remove: IconButton;
|
||||||
|
}
|
||||||
|
|
||||||
ComposeControls {
|
ComposeControls {
|
||||||
bg: color;
|
bg: color;
|
||||||
radius: pixels;
|
radius: pixels;
|
||||||
|
@ -149,6 +172,7 @@ ComposeControls {
|
||||||
emoji: EmojiButton;
|
emoji: EmojiButton;
|
||||||
suggestions: EmojiSuggestions;
|
suggestions: EmojiSuggestions;
|
||||||
tabbed: EmojiPan;
|
tabbed: EmojiPan;
|
||||||
|
record: RecordBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchPmButton: RoundButton(defaultBoxButton) {
|
switchPmButton: RoundButton(defaultBoxButton) {
|
||||||
|
@ -875,7 +899,6 @@ historyRecordTextRight: 25px;
|
||||||
historyRecordLockShowDuration: historyToDownDuration;
|
historyRecordLockShowDuration: historyToDownDuration;
|
||||||
historyRecordLockSize: size(75px, 133px);
|
historyRecordLockSize: size(75px, 133px);
|
||||||
|
|
||||||
historyRecordLockIconFg: historyToDownFg;
|
|
||||||
historyRecordLockIconSize: size(14px, 17px);
|
historyRecordLockIconSize: size(14px, 17px);
|
||||||
historyRecordLockIconBottomHeight: 9px;
|
historyRecordLockIconBottomHeight: 9px;
|
||||||
historyRecordLockIconLineHeight: 2px;
|
historyRecordLockIconLineHeight: 2px;
|
||||||
|
@ -916,6 +939,29 @@ historySilentToggle: IconButton(historyBotKeyboardShow) {
|
||||||
historySilentToggleOn: icon {{ "chat/input_silent_on", historyComposeIconFg }};
|
historySilentToggleOn: icon {{ "chat/input_silent_on", historyComposeIconFg }};
|
||||||
historySilentToggleOnOver: icon {{ "chat/input_silent_on", historyComposeIconFgOver }};
|
historySilentToggleOnOver: icon {{ "chat/input_silent_on", historyComposeIconFgOver }};
|
||||||
|
|
||||||
|
defaultRecordBarLock: RecordBarLock {
|
||||||
|
ripple: defaultRippleAnimation;
|
||||||
|
originTop: historyRecordLockTop;
|
||||||
|
originBottom: historyRecordLockBottom;
|
||||||
|
originBody: historyRecordLockBody;
|
||||||
|
shadowTop: historyRecordLockTopShadow;
|
||||||
|
shadowBottom: historyRecordLockBottomShadow;
|
||||||
|
shadowBody: historyRecordLockBodyShadow;
|
||||||
|
arrow: historyRecordLockArrow;
|
||||||
|
fg: historyToDownFg;
|
||||||
|
}
|
||||||
|
defaultRecordBar: RecordBar {
|
||||||
|
bg: historyComposeAreaBg;
|
||||||
|
durationFg: historyRecordDurationFg;
|
||||||
|
cancel: historyRecordCancel;
|
||||||
|
cancelActive: historyRecordCancelActive;
|
||||||
|
cancelRipple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: lightButtonBgRipple;
|
||||||
|
}
|
||||||
|
lock: defaultRecordBarLock;
|
||||||
|
remove: historyRecordDelete;
|
||||||
|
}
|
||||||
|
|
||||||
historySend: SendButton {
|
historySend: SendButton {
|
||||||
inner: IconButton(historyAttach) {
|
inner: IconButton(historyAttach) {
|
||||||
icon: historySendIcon;
|
icon: historySendIcon;
|
||||||
|
@ -936,4 +982,5 @@ defaultComposeControls: ComposeControls {
|
||||||
emoji: historyAttachEmoji;
|
emoji: historyAttachEmoji;
|
||||||
suggestions: defaultEmojiSuggestions;
|
suggestions: defaultEmojiSuggestions;
|
||||||
tabbed: defaultEmojiPan;
|
tabbed: defaultEmojiPan;
|
||||||
|
record: defaultRecordBar;
|
||||||
}
|
}
|
||||||
|
|
|
@ -943,18 +943,6 @@ void HistoryWidget::refreshTabbedPanel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::initVoiceRecordBar() {
|
void HistoryWidget::initVoiceRecordBar() {
|
||||||
{
|
|
||||||
auto scrollHeight = rpl::combine(
|
|
||||||
_scroll->topValue(),
|
|
||||||
_scroll->heightValue()
|
|
||||||
) | rpl::map([](int top, int height) {
|
|
||||||
return top + height - st::historyRecordLockPosition.y();
|
|
||||||
});
|
|
||||||
_voiceRecordBar->setLockBottom(std::move(scrollHeight));
|
|
||||||
}
|
|
||||||
|
|
||||||
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
|
|
||||||
|
|
||||||
_voiceRecordBar->setStartRecordingFilter([=] {
|
_voiceRecordBar->setStartRecordingFilter([=] {
|
||||||
const auto error = [&]() -> std::optional<QString> {
|
const auto error = [&]() -> std::optional<QString> {
|
||||||
if (_peer) {
|
if (_peer) {
|
||||||
|
|
|
@ -989,10 +989,14 @@ ComposeControls::ComposeControls(
|
||||||
, _header(std::make_unique<FieldHeader>(_wrap.get(), _show))
|
, _header(std::make_unique<FieldHeader>(_wrap.get(), _show))
|
||||||
, _voiceRecordBar(std::make_unique<VoiceRecordBar>(
|
, _voiceRecordBar(std::make_unique<VoiceRecordBar>(
|
||||||
_wrap.get(),
|
_wrap.get(),
|
||||||
parent,
|
Controls::VoiceRecordBarDescriptor{
|
||||||
_show,
|
.outerContainer = parent,
|
||||||
_send,
|
.show = _show,
|
||||||
st::historySendSize.height()))
|
.send = _send,
|
||||||
|
.stOverride = &_st.record,
|
||||||
|
.recorderHeight = st::historySendSize.height(),
|
||||||
|
.lockFromBottom = descriptor.voiceLockFromBottom,
|
||||||
|
}))
|
||||||
, _sendMenuType(descriptor.sendMenuType)
|
, _sendMenuType(descriptor.sendMenuType)
|
||||||
, _unavailableEmojiPasted(std::move(descriptor.unavailableEmojiPasted))
|
, _unavailableEmojiPasted(std::move(descriptor.unavailableEmojiPasted))
|
||||||
, _saveDraftTimer([=] { saveDraft(); })
|
, _saveDraftTimer([=] { saveDraft(); })
|
||||||
|
@ -2278,26 +2282,6 @@ void ComposeControls::initVoiceRecordBar() {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
|
||||||
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->updateSendButtonTypeRequests(
|
_voiceRecordBar->updateSendButtonTypeRequests(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
updateSendButtonType();
|
updateSendButtonType();
|
||||||
|
|
|
@ -102,6 +102,7 @@ struct ComposeControlsDescriptor {
|
||||||
SendMenu::Type sendMenuType = {};
|
SendMenu::Type sendMenuType = {};
|
||||||
Window::SessionController *regularWindow = nullptr;
|
Window::SessionController *regularWindow = nullptr;
|
||||||
rpl::producer<ChatHelpers::FileChosen> stickerOrEmojiChosen;
|
rpl::producer<ChatHelpers::FileChosen> stickerOrEmojiChosen;
|
||||||
|
bool voiceLockFromBottom = false;
|
||||||
ChatHelpers::ComposeFeatures features;
|
ChatHelpers::ComposeFeatures features;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,17 +27,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "media/audio/media_audio_capture.h"
|
#include "media/audio/media_audio_capture.h"
|
||||||
#include "media/player/media_player_button.h"
|
#include "media/player/media_player_button.h"
|
||||||
#include "media/player/media_player_instance.h"
|
#include "media/player/media_player_instance.h"
|
||||||
#include "styles/style_chat.h"
|
|
||||||
#include "styles/style_layers.h"
|
|
||||||
#include "styles/style_media_player.h"
|
|
||||||
#include "ui/controls/send_button.h"
|
#include "ui/controls/send_button.h"
|
||||||
#include "ui/effects/animation_value.h"
|
#include "ui/effects/animation_value.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
#include "styles/style_chat_helpers.h"
|
||||||
|
#include "styles/style_layers.h"
|
||||||
|
#include "styles/style_media_player.h"
|
||||||
|
|
||||||
namespace HistoryView::Controls {
|
namespace HistoryView::Controls {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using SendActionUpdate = VoiceRecordBar::SendActionUpdate;
|
using SendActionUpdate = VoiceRecordBar::SendActionUpdate;
|
||||||
|
@ -206,6 +206,7 @@ class ListenWrap final {
|
||||||
public:
|
public:
|
||||||
ListenWrap(
|
ListenWrap(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBar &st,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
::Media::Capture::Result &&data,
|
::Media::Capture::Result &&data,
|
||||||
const style::font &font);
|
const style::font &font);
|
||||||
|
@ -231,12 +232,12 @@ private:
|
||||||
|
|
||||||
not_null<Ui::RpWidget*> _parent;
|
not_null<Ui::RpWidget*> _parent;
|
||||||
|
|
||||||
|
const style::RecordBar &_st;
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
const not_null<DocumentData*> _document;
|
const not_null<DocumentData*> _document;
|
||||||
const std::unique_ptr<VoiceData> _voiceData;
|
const std::unique_ptr<VoiceData> _voiceData;
|
||||||
const std::shared_ptr<Data::DocumentMedia> _mediaView;
|
const std::shared_ptr<Data::DocumentMedia> _mediaView;
|
||||||
const std::unique_ptr<::Media::Capture::Result> _data;
|
const std::unique_ptr<::Media::Capture::Result> _data;
|
||||||
const style::IconButton &_stDelete;
|
|
||||||
const base::unique_qptr<Ui::IconButton> _delete;
|
const base::unique_qptr<Ui::IconButton> _delete;
|
||||||
const style::font &_durationFont;
|
const style::font &_durationFont;
|
||||||
const QString _duration;
|
const QString _duration;
|
||||||
|
@ -264,17 +265,18 @@ private:
|
||||||
|
|
||||||
ListenWrap::ListenWrap(
|
ListenWrap::ListenWrap(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBar &st,
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
::Media::Capture::Result &&data,
|
::Media::Capture::Result &&data,
|
||||||
const style::font &font)
|
const style::font &font)
|
||||||
: _parent(parent)
|
: _parent(parent)
|
||||||
|
, _st(st)
|
||||||
, _session(session)
|
, _session(session)
|
||||||
, _document(DummyDocument(&session->data()))
|
, _document(DummyDocument(&session->data()))
|
||||||
, _voiceData(ProcessCaptureResult(data))
|
, _voiceData(ProcessCaptureResult(data))
|
||||||
, _mediaView(_document->createMediaView())
|
, _mediaView(_document->createMediaView())
|
||||||
, _data(std::make_unique<::Media::Capture::Result>(std::move(data)))
|
, _data(std::make_unique<::Media::Capture::Result>(std::move(data)))
|
||||||
, _stDelete(st::historyRecordDelete)
|
, _delete(base::make_unique_q<Ui::IconButton>(parent, _st.remove))
|
||||||
, _delete(base::make_unique_q<Ui::IconButton>(parent, _stDelete))
|
|
||||||
, _durationFont(font)
|
, _durationFont(font)
|
||||||
, _duration(Ui::FormatDurationText(
|
, _duration(Ui::FormatDurationText(
|
||||||
float64(_data->samples) / ::Media::Player::kDefaultFrequency))
|
float64(_data->samples) / ::Media::Player::kDefaultFrequency))
|
||||||
|
@ -299,7 +301,7 @@ void ListenWrap::init() {
|
||||||
_waveformBgRect = QRect({ 0, 0 }, size)
|
_waveformBgRect = QRect({ 0, 0 }, size)
|
||||||
.marginsRemoved(st::historyRecordWaveformBgMargins);
|
.marginsRemoved(st::historyRecordWaveformBgMargins);
|
||||||
{
|
{
|
||||||
const auto m = _stDelete.width + _waveformBgRect.height() / 2;
|
const auto m = _st.remove.width + _waveformBgRect.height() / 2;
|
||||||
_waveformBgFinalCenterRect = _waveformBgRect.marginsRemoved(
|
_waveformBgFinalCenterRect = _waveformBgRect.marginsRemoved(
|
||||||
style::margins(m, 0, m, 0));
|
style::margins(m, 0, m, 0));
|
||||||
}
|
}
|
||||||
|
@ -319,22 +321,23 @@ void ListenWrap::init() {
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
const auto progress = _showProgress.current();
|
const auto progress = _showProgress.current();
|
||||||
p.setOpacity(progress);
|
p.setOpacity(progress);
|
||||||
|
const auto &remove = _st.remove;
|
||||||
if (progress > 0. && progress < 1.) {
|
if (progress > 0. && progress < 1.) {
|
||||||
_stDelete.icon.paint(p, _stDelete.iconPosition, _parent->width());
|
remove.icon.paint(p, remove.iconPosition, _parent->width());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto hideOffset = _isShowAnimation
|
const auto hideOffset = _isShowAnimation
|
||||||
? 0
|
? 0
|
||||||
: anim::interpolate(kHideWaveformBgOffset, 0, progress);
|
: anim::interpolate(kHideWaveformBgOffset, 0, progress);
|
||||||
const auto deleteIconLeft = _stDelete.iconPosition.x();
|
const auto deleteIconLeft = remove.iconPosition.x();
|
||||||
const auto bgRectRight = anim::interpolate(
|
const auto bgRectRight = anim::interpolate(
|
||||||
deleteIconLeft,
|
deleteIconLeft,
|
||||||
_stDelete.width,
|
remove.width,
|
||||||
_isShowAnimation ? progress : 1.);
|
_isShowAnimation ? progress : 1.);
|
||||||
const auto bgRectLeft = anim::interpolate(
|
const auto bgRectLeft = anim::interpolate(
|
||||||
_parent->width() - deleteIconLeft - _waveformBgRect.height(),
|
_parent->width() - deleteIconLeft - _waveformBgRect.height(),
|
||||||
_stDelete.width,
|
remove.width,
|
||||||
_isShowAnimation ? progress : 1.);
|
_isShowAnimation ? progress : 1.);
|
||||||
const auto bgRectMargins = style::margins(
|
const auto bgRectMargins = style::margins(
|
||||||
bgRectLeft - hideOffset,
|
bgRectLeft - hideOffset,
|
||||||
|
@ -357,7 +360,7 @@ void ListenWrap::init() {
|
||||||
p.setOpacity(progress);
|
p.setOpacity(progress);
|
||||||
}
|
}
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.setBrush(st::historyRecordCancelActive);
|
p.setBrush(_st.cancelActive);
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
path.setFillRule(Qt::WindingFill);
|
path.setFillRule(Qt::WindingFill);
|
||||||
path.addEllipse(bgLeftCircleRect);
|
path.addEllipse(bgLeftCircleRect);
|
||||||
|
@ -605,10 +608,13 @@ rpl::lifetime &ListenWrap::lifetime() {
|
||||||
|
|
||||||
class RecordLock final : public Ui::RippleButton {
|
class RecordLock final : public Ui::RippleButton {
|
||||||
public:
|
public:
|
||||||
RecordLock(not_null<Ui::RpWidget*> parent);
|
RecordLock(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBarLock &st);
|
||||||
|
|
||||||
void requestPaintProgress(float64 progress);
|
void requestPaintProgress(float64 progress);
|
||||||
void requestPaintLockToStopProgress(float64 progress);
|
void requestPaintLockToStopProgress(float64 progress);
|
||||||
|
void setVisibleTopPart(int part);
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<> locks() const;
|
[[nodiscard]] rpl::producer<> locks() const;
|
||||||
[[nodiscard]] bool isLocked() const;
|
[[nodiscard]] bool isLocked() const;
|
||||||
|
@ -627,6 +633,7 @@ private:
|
||||||
void setProgress(float64 progress);
|
void setProgress(float64 progress);
|
||||||
void startLockingAnimation(float64 to);
|
void startLockingAnimation(float64 to);
|
||||||
|
|
||||||
|
const style::RecordBarLock &_st;
|
||||||
const QRect _rippleRect;
|
const QRect _rippleRect;
|
||||||
const QPen _arcPen;
|
const QPen _arcPen;
|
||||||
|
|
||||||
|
@ -634,10 +641,15 @@ private:
|
||||||
|
|
||||||
float64 _lockToStopProgress = 0.;
|
float64 _lockToStopProgress = 0.;
|
||||||
rpl::variable<float64> _progress = 0.;
|
rpl::variable<float64> _progress = 0.;
|
||||||
|
int _visibleTopPart = -1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RecordLock::RecordLock(not_null<Ui::RpWidget*> parent)
|
RecordLock::RecordLock(
|
||||||
: RippleButton(parent, st::defaultRippleAnimation)
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBarLock &st)
|
||||||
|
: RippleButton(parent, st.ripple)
|
||||||
|
, _st(st)
|
||||||
, _rippleRect(QRect(
|
, _rippleRect(QRect(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -653,6 +665,10 @@ RecordLock::RecordLock(not_null<Ui::RpWidget*> parent)
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecordLock::setVisibleTopPart(int part) {
|
||||||
|
_visibleTopPart = part;
|
||||||
|
}
|
||||||
|
|
||||||
void RecordLock::init() {
|
void RecordLock::init() {
|
||||||
shownValue(
|
shownValue(
|
||||||
) | rpl::start_with_next([=](bool shown) {
|
) | rpl::start_with_next([=](bool shown) {
|
||||||
|
@ -670,7 +686,13 @@ void RecordLock::init() {
|
||||||
|
|
||||||
paintRequest(
|
paintRequest(
|
||||||
) | rpl::start_with_next([=](const QRect &clip) {
|
) | rpl::start_with_next([=](const QRect &clip) {
|
||||||
|
if (!_visibleTopPart) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
if (_visibleTopPart > 0 && _visibleTopPart < height()) {
|
||||||
|
p.setClipRect(0, 0, width(), _visibleTopPart);
|
||||||
|
}
|
||||||
if (isLocked()) {
|
if (isLocked()) {
|
||||||
const auto top = anim::interpolate(
|
const auto top = anim::interpolate(
|
||||||
0,
|
0,
|
||||||
|
@ -687,12 +709,12 @@ void RecordLock::init() {
|
||||||
void RecordLock::drawProgress(Painter &p) {
|
void RecordLock::drawProgress(Painter &p) {
|
||||||
const auto progress = _progress.current();
|
const auto progress = _progress.current();
|
||||||
|
|
||||||
const auto &originTop = st::historyRecordLockTop;
|
const auto &originTop = _st.originTop;
|
||||||
const auto &originBottom = st::historyRecordLockBottom;
|
const auto &originBottom = _st.originBottom;
|
||||||
const auto &originBody = st::historyRecordLockBody;
|
const auto &originBody = _st.originBody;
|
||||||
const auto &shadowTop = st::historyRecordLockTopShadow;
|
const auto &shadowTop = _st.shadowTop;
|
||||||
const auto &shadowBottom = st::historyRecordLockBottomShadow;
|
const auto &shadowBottom = _st.shadowBottom;
|
||||||
const auto &shadowBody = st::historyRecordLockBodyShadow;
|
const auto &shadowBody = _st.shadowBody;
|
||||||
const auto &shadowMargins = st::historyRecordLockMargin;
|
const auto &shadowMargins = st::historyRecordLockMargin;
|
||||||
|
|
||||||
const auto bottomMargin = anim::interpolate(
|
const auto bottomMargin = anim::interpolate(
|
||||||
|
@ -739,7 +761,7 @@ void RecordLock::drawProgress(Painter &p) {
|
||||||
originBody.fill(p, content);
|
originBody.fill(p, content);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto &arrow = st::historyRecordLockArrow;
|
const auto &arrow = _st.arrow;
|
||||||
const auto arrowRect = QRect(
|
const auto arrowRect = QRect(
|
||||||
inner.x(),
|
inner.x(),
|
||||||
content.y() + content.height() - arrow.height() / 2,
|
content.y() + content.height() - arrow.height() / 2,
|
||||||
|
@ -791,7 +813,7 @@ void RecordLock::drawProgress(Painter &p) {
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
p.translate(inner.topLeft() + lockTranslation);
|
p.translate(inner.topLeft() + lockTranslation);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.setBrush(st::historyRecordLockIconFg);
|
p.setBrush(_st.fg);
|
||||||
p.drawRoundedRect(blockRect, xRadius, 3);
|
p.drawRoundedRect(blockRect, xRadius, 3);
|
||||||
} else {
|
} else {
|
||||||
// Paint an animation frame.
|
// Paint an animation frame.
|
||||||
|
@ -844,7 +866,7 @@ void RecordLock::drawProgress(Painter &p) {
|
||||||
|
|
||||||
p.drawImage(
|
p.drawImage(
|
||||||
inner.topLeft(),
|
inner.topLeft(),
|
||||||
style::colorizeImage(frame, st::historyRecordLockIconFg));
|
style::colorizeImage(frame, _st.fg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -914,7 +936,10 @@ QPoint RecordLock::prepareRippleStartPosition() const {
|
||||||
|
|
||||||
class CancelButton final : public Ui::RippleButton {
|
class CancelButton final : public Ui::RippleButton {
|
||||||
public:
|
public:
|
||||||
CancelButton(not_null<Ui::RpWidget*> parent, int height);
|
CancelButton(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBar &st,
|
||||||
|
int height);
|
||||||
|
|
||||||
void requestPaintProgress(float64 progress);
|
void requestPaintProgress(float64 progress);
|
||||||
|
|
||||||
|
@ -925,6 +950,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
const style::RecordBar &_st;
|
||||||
const int _width;
|
const int _width;
|
||||||
const QRect _rippleRect;
|
const QRect _rippleRect;
|
||||||
|
|
||||||
|
@ -934,8 +960,12 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CancelButton::CancelButton(not_null<Ui::RpWidget*> parent, int height)
|
CancelButton::CancelButton(
|
||||||
: Ui::RippleButton(parent, st::defaultLightButton.ripple)
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBar &st,
|
||||||
|
int height)
|
||||||
|
: Ui::RippleButton(parent, st.cancelRipple)
|
||||||
|
, _st(st)
|
||||||
, _width(st::historyRecordCancelButtonWidth)
|
, _width(st::historyRecordCancelButtonWidth)
|
||||||
, _rippleRect(QRect(0, (height - _width) / 2, _width, _width))
|
, _rippleRect(QRect(0, (height - _width) / 2, _width, _width))
|
||||||
, _text(st::semiboldTextStyle, tr::lng_selected_clear(tr::now)) {
|
, _text(st::semiboldTextStyle, tr::lng_selected_clear(tr::now)) {
|
||||||
|
@ -958,7 +988,7 @@ void CancelButton::init() {
|
||||||
|
|
||||||
paintRipple(p, _rippleRect.x(), _rippleRect.y());
|
paintRipple(p, _rippleRect.x(), _rippleRect.y());
|
||||||
|
|
||||||
p.setPen(st::historyRecordCancelButtonFg);
|
p.setPen(_st.cancelActive);
|
||||||
_text.draw(
|
_text.draw(
|
||||||
p,
|
p,
|
||||||
0,
|
0,
|
||||||
|
@ -983,24 +1013,23 @@ void CancelButton::requestPaintProgress(float64 progress) {
|
||||||
|
|
||||||
VoiceRecordBar::VoiceRecordBar(
|
VoiceRecordBar::VoiceRecordBar(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<Ui::RpWidget*> sectionWidget,
|
VoiceRecordBarDescriptor &&descriptor)
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
|
||||||
std::shared_ptr<Ui::SendButton> send,
|
|
||||||
int recorderHeight)
|
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _sectionWidget(sectionWidget)
|
, _st(descriptor.stOverride ? *descriptor.stOverride : st::defaultRecordBar)
|
||||||
, _show(std::move(show))
|
, _outerContainer(descriptor.outerContainer)
|
||||||
, _send(send)
|
, _show(std::move(descriptor.show))
|
||||||
, _lock(std::make_unique<RecordLock>(sectionWidget))
|
, _send(std::move(descriptor.send))
|
||||||
, _level(std::make_unique<VoiceRecordButton>(sectionWidget))
|
, _lock(std::make_unique<RecordLock>(_outerContainer, _st.lock))
|
||||||
, _cancel(std::make_unique<CancelButton>(this, recorderHeight))
|
, _level(std::make_unique<VoiceRecordButton>(_outerContainer, _st))
|
||||||
|
, _cancel(std::make_unique<CancelButton>(this, _st, descriptor.recorderHeight))
|
||||||
, _startTimer([=] { startRecording(); })
|
, _startTimer([=] { startRecording(); })
|
||||||
, _message(
|
, _message(
|
||||||
st::historyRecordTextStyle,
|
st::historyRecordTextStyle,
|
||||||
tr::lng_record_cancel(tr::now),
|
tr::lng_record_cancel(tr::now),
|
||||||
TextParseOptions{ TextParseMultiline, 0, 0, Qt::LayoutDirectionAuto })
|
TextParseOptions{ TextParseMultiline, 0, 0, Qt::LayoutDirectionAuto })
|
||||||
|
, _lockFromBottom(descriptor.lockFromBottom)
|
||||||
, _cancelFont(st::historyRecordFont) {
|
, _cancelFont(st::historyRecordFont) {
|
||||||
resize(QSize(parent->width(), recorderHeight));
|
resize(QSize(parent->width(), descriptor.recorderHeight));
|
||||||
init();
|
init();
|
||||||
hideFast();
|
hideFast();
|
||||||
}
|
}
|
||||||
|
@ -1010,7 +1039,12 @@ VoiceRecordBar::VoiceRecordBar(
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
std::shared_ptr<Ui::SendButton> send,
|
std::shared_ptr<Ui::SendButton> send,
|
||||||
int recorderHeight)
|
int recorderHeight)
|
||||||
: VoiceRecordBar(parent, parent, std::move(show), send, recorderHeight) {
|
: VoiceRecordBar(parent, {
|
||||||
|
.outerContainer = parent,
|
||||||
|
.show = std::move(show),
|
||||||
|
.send = std::move(send),
|
||||||
|
.recorderHeight = recorderHeight,
|
||||||
|
}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceRecordBar::~VoiceRecordBar() {
|
VoiceRecordBar::~VoiceRecordBar() {
|
||||||
|
@ -1040,14 +1074,32 @@ void VoiceRecordBar::updateMessageGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::updateLockGeometry() {
|
void VoiceRecordBar::updateLockGeometry() {
|
||||||
const auto right = anim::interpolate(
|
const auto parent = parentWidget();
|
||||||
-_lock->width(),
|
const auto me = Ui::MapFrom(_outerContainer, parent, geometry());
|
||||||
st::historyRecordLockPosition.x(),
|
const auto finalTop = me.y()
|
||||||
_showLockAnimation.value(_lockShowing.current() ? 1. : 0.));
|
- st::historyRecordLockPosition.y()
|
||||||
_lock->moveToRight(right, _lock->y());
|
- _lock->height();
|
||||||
|
const auto finalRight = _outerContainer->width()
|
||||||
|
- (me.x() + me.width())
|
||||||
|
+ st::historyRecordLockPosition.x();
|
||||||
|
const auto progress = _showLockAnimation.value(
|
||||||
|
_lockShowing.current() ? 1. : 0.);
|
||||||
|
if (_lockFromBottom) {
|
||||||
|
const auto top = anim::interpolate(me.y(), finalTop, progress);
|
||||||
|
_lock->moveToRight(finalRight, top);
|
||||||
|
_lock->setVisibleTopPart(me.y() - top);
|
||||||
|
} else {
|
||||||
|
const auto from = -_lock->width();
|
||||||
|
const auto right = anim::interpolate(from, finalRight, progress);
|
||||||
|
_lock->moveToRight(right, finalTop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::init() {
|
void VoiceRecordBar::init() {
|
||||||
|
if (_st.radius > 0) {
|
||||||
|
_backgroundRect.emplace(_st.radius, _st.bg);
|
||||||
|
}
|
||||||
|
|
||||||
// Keep VoiceRecordBar behind SendButton.
|
// Keep VoiceRecordBar behind SendButton.
|
||||||
rpl::single(
|
rpl::single(
|
||||||
) | rpl::then(
|
) | rpl::then(
|
||||||
|
@ -1087,7 +1139,6 @@ void VoiceRecordBar::init() {
|
||||||
}
|
}
|
||||||
_cancel->moveToLeft((size.width() - _cancel->width()) / 2, 0);
|
_cancel->moveToLeft((size.width() - _cancel->width()) / 2, 0);
|
||||||
updateMessageGeometry();
|
updateMessageGeometry();
|
||||||
updateLockGeometry();
|
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
paintRequest(
|
paintRequest(
|
||||||
|
@ -1096,7 +1147,11 @@ void VoiceRecordBar::init() {
|
||||||
if (_showAnimation.animating()) {
|
if (_showAnimation.animating()) {
|
||||||
p.setOpacity(showAnimationRatio());
|
p.setOpacity(showAnimationRatio());
|
||||||
}
|
}
|
||||||
p.fillRect(clip, st::historyComposeAreaBg);
|
if (_backgroundRect) {
|
||||||
|
_backgroundRect->paint(p, rect());
|
||||||
|
} else {
|
||||||
|
p.fillRect(clip, _st.bg);
|
||||||
|
}
|
||||||
|
|
||||||
p.setOpacity(std::min(p.opacity(), 1. - showListenAnimationRatio()));
|
p.setOpacity(std::min(p.opacity(), 1. - showListenAnimationRatio()));
|
||||||
const auto opacity = p.opacity();
|
const auto opacity = p.opacity();
|
||||||
|
@ -1237,6 +1292,9 @@ void VoiceRecordBar::init() {
|
||||||
_cancel->setClickedCallback([=] {
|
_cancel->setClickedCallback([=] {
|
||||||
hideAnimated();
|
hideAnimated();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
initLockGeometry();
|
||||||
|
initLevelGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::activeAnimate(bool active) {
|
void VoiceRecordBar::activeAnimate(bool active) {
|
||||||
|
@ -1278,22 +1336,25 @@ void VoiceRecordBar::setStartRecordingFilter(Fn<bool()> &&callback) {
|
||||||
_startRecordingFilter = std::move(callback);
|
_startRecordingFilter = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::setLockBottom(rpl::producer<int> &&bottom) {
|
void VoiceRecordBar::initLockGeometry() {
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
std::move(bottom),
|
_lock->heightValue(),
|
||||||
_lock->sizeValue() | rpl::map_to(true) // Dummy value.
|
geometryValue(),
|
||||||
) | rpl::start_with_next([=](int value, bool dummy) {
|
static_cast<Ui::RpWidget*>(parentWidget())->geometryValue()
|
||||||
_lock->moveToLeft(_lock->x(), value - _lock->height());
|
) | rpl::start_with_next([=] {
|
||||||
|
updateLockGeometry();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::setSendButtonGeometryValue(
|
void VoiceRecordBar::initLevelGeometry() {
|
||||||
rpl::producer<QRect> &&geometry) {
|
rpl::combine(
|
||||||
std::move(
|
_send->geometryValue(),
|
||||||
geometry
|
geometryValue(),
|
||||||
) | rpl::start_with_next([=](QRect r) {
|
static_cast<Ui::RpWidget*>(parentWidget())->geometryValue()
|
||||||
const auto center = (r.width() - _level->width()) / 2;
|
) | rpl::start_with_next([=](QRect send, QRect me, QRect parent) {
|
||||||
_level->moveToLeft(r.x() + center, r.y() + center);
|
const auto mapped = Ui::MapFrom(_outerContainer, this, send);
|
||||||
|
const auto center = (send.width() - _level->width()) / 2;
|
||||||
|
_level->moveToLeft(mapped.x() + center, mapped.y() + center);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1431,6 +1492,7 @@ void VoiceRecordBar::stopRecording(StopType type) {
|
||||||
} else if (type == StopType::Listen) {
|
} else if (type == StopType::Listen) {
|
||||||
_listen = std::make_unique<ListenWrap>(
|
_listen = std::make_unique<ListenWrap>(
|
||||||
this,
|
this,
|
||||||
|
_st,
|
||||||
&_show->session(),
|
&_show->session(),
|
||||||
std::move(data),
|
std::move(data),
|
||||||
_cancelFont);
|
_cancelFont);
|
||||||
|
@ -1444,7 +1506,7 @@ void VoiceRecordBar::stopRecording(StopType type) {
|
||||||
void VoiceRecordBar::drawDuration(Painter &p) {
|
void VoiceRecordBar::drawDuration(Painter &p) {
|
||||||
const auto duration = FormatVoiceDuration(_recordingSamples);
|
const auto duration = FormatVoiceDuration(_recordingSamples);
|
||||||
p.setFont(_cancelFont);
|
p.setFont(_cancelFont);
|
||||||
p.setPen(st::historyRecordDurationFg);
|
p.setPen(_st.durationFg);
|
||||||
|
|
||||||
p.drawText(_durationRect, style::al_left, duration);
|
p.drawText(_durationRect, style::al_left, duration);
|
||||||
}
|
}
|
||||||
|
@ -1478,11 +1540,7 @@ void VoiceRecordBar::drawRedCircle(Painter &p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::drawMessage(Painter &p, float64 recordActive) {
|
void VoiceRecordBar::drawMessage(Painter &p, float64 recordActive) {
|
||||||
p.setPen(
|
p.setPen(anim::pen(_st.cancel, _st.cancelActive, 1. - recordActive));
|
||||||
anim::pen(
|
|
||||||
st::historyRecordCancel,
|
|
||||||
st::historyRecordCancelActive,
|
|
||||||
1. - recordActive));
|
|
||||||
|
|
||||||
const auto opacity = p.opacity();
|
const auto opacity = p.opacity();
|
||||||
p.setOpacity(opacity * (1. - _lock->lockToStopProgress()));
|
p.setOpacity(opacity * (1. - _lock->lockToStopProgress()));
|
||||||
|
@ -1621,8 +1679,8 @@ void VoiceRecordBar::computeAndSetLockProgress(QPoint globalPos) {
|
||||||
|
|
||||||
void VoiceRecordBar::orderControls() {
|
void VoiceRecordBar::orderControls() {
|
||||||
stackUnder(_send.get());
|
stackUnder(_send.get());
|
||||||
_level->raise();
|
|
||||||
_lock->raise();
|
_lock->raise();
|
||||||
|
_level->raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceRecordBar::installListenStateFilter() {
|
void VoiceRecordBar::installListenStateFilter() {
|
||||||
|
|
|
@ -11,10 +11,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
#include "history/view/controls/compose_controls_common.h"
|
#include "history/view/controls/compose_controls_common.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
|
#include "ui/round_rect.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
struct VoiceData;
|
struct VoiceData;
|
||||||
|
|
||||||
|
namespace style {
|
||||||
|
struct RecordBar;
|
||||||
|
} // namespace style
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SendButton;
|
class SendButton;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -34,6 +39,15 @@ class ListenWrap;
|
||||||
class RecordLock;
|
class RecordLock;
|
||||||
class CancelButton;
|
class CancelButton;
|
||||||
|
|
||||||
|
struct VoiceRecordBarDescriptor {
|
||||||
|
not_null<Ui::RpWidget*> outerContainer;
|
||||||
|
std::shared_ptr<ChatHelpers::Show> show;
|
||||||
|
std::shared_ptr<Ui::SendButton> send;
|
||||||
|
const style::RecordBar *stOverride = nullptr;
|
||||||
|
int recorderHeight = 0;
|
||||||
|
bool lockFromBottom = false;
|
||||||
|
};
|
||||||
|
|
||||||
class VoiceRecordBar final : public Ui::RpWidget {
|
class VoiceRecordBar final : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
using SendActionUpdate = Controls::SendActionUpdate;
|
using SendActionUpdate = Controls::SendActionUpdate;
|
||||||
|
@ -41,10 +55,7 @@ public:
|
||||||
|
|
||||||
VoiceRecordBar(
|
VoiceRecordBar(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<Ui::RpWidget*> sectionWidget,
|
VoiceRecordBarDescriptor &&descriptor);
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
|
||||||
std::shared_ptr<Ui::SendButton> send,
|
|
||||||
int recorderHeight);
|
|
||||||
VoiceRecordBar(
|
VoiceRecordBar(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
@ -75,8 +86,6 @@ public:
|
||||||
|
|
||||||
void requestToSendWithOptions(Api::SendOptions options);
|
void requestToSendWithOptions(Api::SendOptions options);
|
||||||
|
|
||||||
void setLockBottom(rpl::producer<int> &&bottom);
|
|
||||||
void setSendButtonGeometryValue(rpl::producer<QRect> &&geometry);
|
|
||||||
void setStartRecordingFilter(Fn<bool()> &&callback);
|
void setStartRecordingFilter(Fn<bool()> &&callback);
|
||||||
|
|
||||||
[[nodiscard]] bool isRecording() const;
|
[[nodiscard]] bool isRecording() const;
|
||||||
|
@ -93,6 +102,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void initLockGeometry();
|
||||||
|
void initLevelGeometry();
|
||||||
|
|
||||||
void updateMessageGeometry();
|
void updateMessageGeometry();
|
||||||
void updateLockGeometry();
|
void updateLockGeometry();
|
||||||
|
@ -125,7 +136,8 @@ private:
|
||||||
|
|
||||||
void computeAndSetLockProgress(QPoint globalPos);
|
void computeAndSetLockProgress(QPoint globalPos);
|
||||||
|
|
||||||
const not_null<Ui::RpWidget*> _sectionWidget;
|
const style::RecordBar &_st;
|
||||||
|
const not_null<Ui::RpWidget*> _outerContainer;
|
||||||
const std::shared_ptr<ChatHelpers::Show> _show;
|
const std::shared_ptr<ChatHelpers::Show> _show;
|
||||||
const std::shared_ptr<Ui::SendButton> _send;
|
const std::shared_ptr<Ui::SendButton> _send;
|
||||||
const std::unique_ptr<RecordLock> _lock;
|
const std::unique_ptr<RecordLock> _lock;
|
||||||
|
@ -159,11 +171,13 @@ private:
|
||||||
|
|
||||||
rpl::event_stream<> _recordingTipRequests;
|
rpl::event_stream<> _recordingTipRequests;
|
||||||
bool _recordingTipRequired = false;
|
bool _recordingTipRequired = false;
|
||||||
|
bool _lockFromBottom = false;
|
||||||
|
|
||||||
const style::font &_cancelFont;
|
const style::font &_cancelFont;
|
||||||
|
|
||||||
rpl::lifetime _recordingLifetime;
|
rpl::lifetime _recordingLifetime;
|
||||||
|
|
||||||
|
std::optional<Ui::RoundRect> _backgroundRect;
|
||||||
Ui::Animations::Simple _showLockAnimation;
|
Ui::Animations::Simple _showLockAnimation;
|
||||||
Ui::Animations::Simple _lockToStopAnimation;
|
Ui::Animations::Simple _lockToStopAnimation;
|
||||||
Ui::Animations::Simple _showListenAnimation;
|
Ui::Animations::Simple _showListenAnimation;
|
||||||
|
|
|
@ -47,8 +47,11 @@ auto Blobs() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
VoiceRecordButton::VoiceRecordButton(not_null<Ui::RpWidget*> parent)
|
VoiceRecordButton::VoiceRecordButton(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBar &st)
|
||||||
: AbstractButton(parent)
|
: AbstractButton(parent)
|
||||||
|
, _st(st)
|
||||||
, _blobs(std::make_unique<Ui::Paint::Blobs>(
|
, _blobs(std::make_unique<Ui::Paint::Blobs>(
|
||||||
Blobs(),
|
Blobs(),
|
||||||
kLevelDuration,
|
kLevelDuration,
|
||||||
|
|
|
@ -11,17 +11,21 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace style {
|
||||||
namespace Paint {
|
struct RecordBar;
|
||||||
|
} // namespace style
|
||||||
|
|
||||||
|
namespace Ui::Paint {
|
||||||
class Blobs;
|
class Blobs;
|
||||||
} // namespace Paint
|
} // namespace Ui::Paint
|
||||||
} // namespace Ui
|
|
||||||
|
|
||||||
namespace HistoryView::Controls {
|
namespace HistoryView::Controls {
|
||||||
|
|
||||||
class VoiceRecordButton final : public Ui::AbstractButton {
|
class VoiceRecordButton final : public Ui::AbstractButton {
|
||||||
public:
|
public:
|
||||||
explicit VoiceRecordButton(not_null<Ui::RpWidget*> parent);
|
VoiceRecordButton(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::RecordBar &st);
|
||||||
~VoiceRecordButton();
|
~VoiceRecordButton();
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
|
@ -43,6 +47,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
const style::RecordBar &_st;
|
||||||
std::unique_ptr<Ui::Paint::Blobs> _blobs;
|
std::unique_ptr<Ui::Paint::Blobs> _blobs;
|
||||||
|
|
||||||
crl::time _lastUpdateTime = 0;
|
crl::time _lastUpdateTime = 0;
|
||||||
|
|
|
@ -35,6 +35,7 @@ ReplyArea::ReplyArea(not_null<Controller*> controller)
|
||||||
.mode = HistoryView::ComposeControlsMode::Normal,
|
.mode = HistoryView::ComposeControlsMode::Normal,
|
||||||
.sendMenuType = SendMenu::Type::SilentOnly,
|
.sendMenuType = SendMenu::Type::SilentOnly,
|
||||||
.stickerOrEmojiChosen = _controller->stickerOrEmojiChosen(),
|
.stickerOrEmojiChosen = _controller->stickerOrEmojiChosen(),
|
||||||
|
.voiceLockFromBottom = true,
|
||||||
.features = {
|
.features = {
|
||||||
.sendAs = false,
|
.sendAs = false,
|
||||||
.ttlInfo = false,
|
.ttlInfo = false,
|
||||||
|
|
|
@ -448,24 +448,23 @@ storiesComposeWhiteText: groupCallMembersFg;
|
||||||
storiesComposeGrayText: groupCallMemberNotJoinedStatus;
|
storiesComposeGrayText: groupCallMemberNotJoinedStatus;
|
||||||
storiesComposeGrayIcon: groupCallMemberInactiveIcon;
|
storiesComposeGrayIcon: groupCallMemberInactiveIcon;
|
||||||
storiesComposeBlue: groupCallActiveFg;
|
storiesComposeBlue: groupCallActiveFg;
|
||||||
|
storiesComposeRippleLight: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: storiesComposeBgOver;
|
||||||
|
}
|
||||||
storiesComposeRipple: RippleAnimation(defaultRippleAnimation) {
|
storiesComposeRipple: RippleAnimation(defaultRippleAnimation) {
|
||||||
color: groupCallMembersBgRipple;
|
color: groupCallMembersBgRipple;
|
||||||
}
|
}
|
||||||
storiesAttach: IconButton(historyAttach) {
|
storiesAttach: IconButton(historyAttach) {
|
||||||
icon: icon {{ "chat/input_attach", storiesComposeGrayIcon }};
|
icon: icon {{ "chat/input_attach", storiesComposeGrayIcon }};
|
||||||
iconOver: icon {{ "chat/input_attach", storiesComposeGrayIcon }};
|
iconOver: icon {{ "chat/input_attach", storiesComposeGrayIcon }};
|
||||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
ripple: storiesComposeRippleLight;
|
||||||
color: storiesComposeBgOver;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
storiesRecordVoice: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
storiesRecordVoice: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
||||||
storiesRecordVoiceOver: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
storiesRecordVoiceOver: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
||||||
storiesRemoveSet: IconButton(stickerPanRemoveSet) {
|
storiesRemoveSet: IconButton(stickerPanRemoveSet) {
|
||||||
icon: icon {{ "simple_close", storiesComposeGrayIcon }};
|
icon: icon {{ "simple_close", storiesComposeGrayIcon }};
|
||||||
iconOver: icon {{ "simple_close", storiesComposeGrayIcon }};
|
iconOver: icon {{ "simple_close", storiesComposeGrayIcon }};
|
||||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
ripple: storiesComposeRippleLight;
|
||||||
color: storiesComposeBgOver;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
storiesMenu: Menu(defaultMenu) {
|
storiesMenu: Menu(defaultMenu) {
|
||||||
itemBg: groupCallMenuBg;
|
itemBg: groupCallMenuBg;
|
||||||
|
@ -641,4 +640,25 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
||||||
}
|
}
|
||||||
autocompleteBottomSkip: 10px;
|
autocompleteBottomSkip: 10px;
|
||||||
}
|
}
|
||||||
|
record: RecordBar(defaultRecordBar) {
|
||||||
|
bg: storiesComposeBg;
|
||||||
|
durationFg: storiesComposeWhiteText;
|
||||||
|
radius: storiesRadius;
|
||||||
|
cancel: storiesComposeGrayText;
|
||||||
|
cancelActive: storiesComposeBlue;
|
||||||
|
cancelRipple: storiesComposeRippleLight;
|
||||||
|
lock: RecordBarLock(defaultRecordBarLock) {
|
||||||
|
ripple: storiesComposeRipple;
|
||||||
|
originTop: icon {{ "voice_lock/record_lock_top", storiesComposeBg }};
|
||||||
|
originBottom: icon {{ "voice_lock/record_lock_bottom", storiesComposeBg }};
|
||||||
|
originBody: icon {{ "voice_lock/record_lock_body", storiesComposeBg }};
|
||||||
|
arrow: icon {{ "voice_lock/voice_arrow", storiesComposeGrayIcon }};
|
||||||
|
fg: storiesComposeGrayIcon;
|
||||||
|
}
|
||||||
|
remove: IconButton(storiesAttach) {
|
||||||
|
icon: icon {{ "info/info_media_delete", storiesComposeGrayIcon }};
|
||||||
|
iconOver: icon {{ "info/info_media_delete", storiesComposeGrayIcon }};
|
||||||
|
iconPosition: point(10px, 11px);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user