mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Use lottie for voice/round message icon.
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -17,6 +17,8 @@
|
||||
<file alias="stats_earn.tgs">../../animations/stats_earn.tgs</file>
|
||||
<file alias="voice_ttl_idle.tgs">../../animations/voice_ttl_idle.tgs</file>
|
||||
<file alias="voice_ttl_start.tgs">../../animations/voice_ttl_start.tgs</file>
|
||||
<file alias="chat/voice_to_video.tgs">../../animations/chat/voice_to_video.tgs</file>
|
||||
<file alias="chat/video_to_voice.tgs">../../animations/chat/video_to_voice.tgs</file>
|
||||
<file alias="palette.tgs">../../animations/palette.tgs</file>
|
||||
<file alias="sleep.tgs">../../animations/sleep.tgs</file>
|
||||
<file alias="greeting.tgs">../../animations/greeting.tgs</file>
|
||||
|
||||
@@ -153,10 +153,7 @@ SendButton {
|
||||
sendIconFillPadding: pixels;
|
||||
inner: IconButton;
|
||||
stars: RoundButton;
|
||||
record: icon;
|
||||
recordOver: icon;
|
||||
round: icon;
|
||||
roundOver: icon;
|
||||
recordSize: size;
|
||||
sendDisabledFg: color;
|
||||
}
|
||||
|
||||
@@ -1287,18 +1284,11 @@ historyRecordVoiceFgOver: historyComposeIconFgOver;
|
||||
historyRecordVoiceFgInactive: attentionButtonFg;
|
||||
historyRecordVoiceFgActive: windowBgActive;
|
||||
historyRecordVoiceFgActiveIcon: windowFgActive;
|
||||
historyRecordVoice: icon {{ "chat/input_record", historyRecordVoiceFg }};
|
||||
historyRecordVoiceOver: icon {{ "chat/input_record", historyRecordVoiceFgOver }};
|
||||
historyRecordVoiceOnceBg: icon {{ "voice_lock/audio_once_bg", historySendIconFg }};
|
||||
historyRecordVoiceOnceBgOver: icon {{ "voice_lock/audio_once_bg", historySendIconFgOver }};
|
||||
historyRecordVoiceOnceFg: icon {{ "voice_lock/audio_once_number", windowFgActive }};
|
||||
historyRecordVoiceOnceFgOver: icon {{ "voice_lock/audio_once_number", windowFgActive }};
|
||||
historyRecordVoiceOnceInactive: icon {{ "chat/audio_once", windowSubTextFg }};
|
||||
historyRecordVoiceActive: icon {{ "chat/input_record_filled", historyRecordVoiceFgActiveIcon }};
|
||||
historyRecordRound: icon {{ "chat/input_video", historyRecordVoiceFg }};
|
||||
historyRecordRoundOver: icon {{ "chat/input_video", historyRecordVoiceFgOver }};
|
||||
historyRecordRoundActive: icon {{ "chat/input_video", historyRecordVoiceFgActiveIcon }};
|
||||
historyRecordRoundIconPosition: point(0px, 0px);
|
||||
historyRecordSendIconPosition: point(2px, 0px);
|
||||
historyRecordVoiceRippleBgActive: lightButtonBgOver;
|
||||
historyRecordSignalRadius: 5px;
|
||||
@@ -1411,12 +1401,10 @@ historySend: SendButton {
|
||||
textTop: 5px;
|
||||
width: -8px;
|
||||
}
|
||||
record: historyRecordVoice;
|
||||
recordOver: historyRecordVoiceOver;
|
||||
round: historyRecordRound;
|
||||
roundOver: historyRecordRoundOver;
|
||||
recordSize: size(26px, 26px);
|
||||
sendDisabledFg: historyComposeIconFg;
|
||||
}
|
||||
historyRecordFrameIndex: 30;
|
||||
|
||||
defaultComposeFilesMenu: IconButton(defaultIconButton) {
|
||||
width: 48px;
|
||||
|
||||
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "history/view/controls/history_view_voice_record_button.h"
|
||||
|
||||
#include "lottie/lottie_icon.h"
|
||||
#include "ui/paint/blobs.h"
|
||||
#include "ui/painter.h"
|
||||
#include "styles/style_chat.h"
|
||||
@@ -24,6 +25,8 @@ constexpr auto kBlobAlpha = 76. / 255.;
|
||||
constexpr auto kBlobMaxSpeed = 5.0;
|
||||
constexpr auto kLevelDuration = 100. + 500. * 0.33;
|
||||
constexpr auto kBlobsScaleEnterDuration = crl::time(250);
|
||||
constexpr auto kVoiceIconIndex = 0;
|
||||
constexpr auto kRoundIconIndex = 1;
|
||||
|
||||
auto Blobs() {
|
||||
return std::vector<Ui::Paint::Blobs::BlobData>{
|
||||
@@ -135,22 +138,28 @@ void VoiceRecordButton::init() {
|
||||
p.scale(scale, scale);
|
||||
}
|
||||
const auto state = *currentState;
|
||||
const auto icon = (state == Type::Send)
|
||||
? st::historySendIcon
|
||||
: (state == Type::Record)
|
||||
? st::historyRecordVoiceActive
|
||||
: st::historyRecordRoundActive;
|
||||
const auto position = (state == Type::Send)
|
||||
? st::historyRecordSendIconPosition
|
||||
: (state == Type::Record)
|
||||
? QPoint(0, 0)
|
||||
: st::historyRecordRoundIconPosition;
|
||||
icon.paint(
|
||||
p,
|
||||
-icon.width() / 2 + position.x(),
|
||||
-icon.height() / 2 + position.y(),
|
||||
0,
|
||||
st::historyRecordVoiceFgActiveIcon->c);
|
||||
if (state == Type::Send) {
|
||||
const auto icon = st::historySendIcon;
|
||||
const auto position = st::historyRecordSendIconPosition;
|
||||
icon.paint(
|
||||
p,
|
||||
-icon.width() / 2 + position.x(),
|
||||
-icon.height() / 2 + position.y(),
|
||||
0,
|
||||
st::historyRecordVoiceFgActiveIcon->c);
|
||||
} else {
|
||||
const auto index = (state == Type::Record)
|
||||
? kVoiceIconIndex
|
||||
: kRoundIconIndex;
|
||||
auto &icon = _voiceRoundIcons[index];
|
||||
if (!icon) {
|
||||
initVoiceRoundIcon(index);
|
||||
}
|
||||
icon->paintInCenter(
|
||||
p,
|
||||
rect().translated(-_center, -_center),
|
||||
st::historyRecordVoiceFgActiveIcon->c);
|
||||
}
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
@@ -205,6 +214,18 @@ void VoiceRecordButton::init() {
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void VoiceRecordButton::initVoiceRoundIcon(int index) {
|
||||
Expects(index >= 0 && index < 2);
|
||||
|
||||
_voiceRoundIcons[index] = Lottie::MakeIcon({
|
||||
.path = ((index == kVoiceIconIndex)
|
||||
? u":/animations/chat/voice_to_video.tgs"_q
|
||||
: u":/animations/chat/video_to_voice.tgs"_q),
|
||||
.sizeOverride = st::historySend.recordSize,
|
||||
.colorizeUsingAlpha = true,
|
||||
});
|
||||
}
|
||||
|
||||
rpl::producer<bool> VoiceRecordButton::actives() const {
|
||||
return events(
|
||||
) | rpl::filter([=](not_null<QEvent*> e) {
|
||||
|
||||
@@ -15,6 +15,10 @@ namespace style {
|
||||
struct RecordBar;
|
||||
} // namespace style
|
||||
|
||||
namespace Lottie {
|
||||
class Icon;
|
||||
} // namespace Lottie
|
||||
|
||||
namespace Ui::Paint {
|
||||
class Blobs;
|
||||
} // namespace Ui::Paint
|
||||
@@ -47,8 +51,10 @@ public:
|
||||
|
||||
private:
|
||||
void init();
|
||||
void initVoiceRoundIcon(int index);
|
||||
|
||||
std::unique_ptr<Ui::Paint::Blobs> _blobs;
|
||||
std::array<std::unique_ptr<Lottie::Icon>, 2> _voiceRoundIcons;
|
||||
|
||||
crl::time _lastUpdateTime = 0;
|
||||
crl::time _blobsHideLastTime = 0;
|
||||
|
||||
@@ -493,10 +493,6 @@ storiesLike: IconButton(storiesAttach) {
|
||||
icon: icon {{ "chat/input_like", storiesComposeGrayIcon }};
|
||||
iconOver: icon {{ "chat/input_like", storiesComposeGrayIcon }};
|
||||
}
|
||||
storiesRecordVoice: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
||||
storiesRecordVoiceOver: icon {{ "chat/input_record", storiesComposeGrayIcon }};
|
||||
storiesRecordRound: icon {{ "chat/input_video", storiesComposeGrayIcon }};
|
||||
storiesRecordRoundOver: icon {{ "chat/input_video", storiesComposeGrayIcon }};
|
||||
storiesEditStars: IconButton(storiesAttach) {
|
||||
icon: icon{{ "chat/input_paid", storiesComposeGrayIcon }};
|
||||
iconOver: icon{{ "chat/input_paid", storiesComposeGrayIcon }};
|
||||
@@ -727,10 +723,6 @@ storiesComposeControls: ComposeControls(defaultComposeControls) {
|
||||
rippleAreaSize: 40px;
|
||||
rippleAreaPosition: point(1px, 1px);
|
||||
}
|
||||
record: storiesRecordVoice;
|
||||
recordOver: storiesRecordVoiceOver;
|
||||
round: storiesRecordRound;
|
||||
roundOver: storiesRecordRoundOver;
|
||||
sendDisabledFg: storiesComposeGrayText;
|
||||
}
|
||||
attach: storiesAttach;
|
||||
|
||||
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/controls/send_button.h"
|
||||
|
||||
#include "lang/lang_tag.h"
|
||||
#include "lottie/lottie_icon.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/painter.h"
|
||||
@@ -19,7 +20,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Ui {
|
||||
namespace {
|
||||
|
||||
constexpr int kWideScale = 5;
|
||||
constexpr auto kWideScale = 5;
|
||||
constexpr auto kVoiceToRoundIndex = 0;
|
||||
constexpr auto kRoundToVoiceIndex = 1;
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -29,19 +32,34 @@ SendButton::SendButton(QWidget *parent, const style::SendButton &st)
|
||||
updateSize();
|
||||
}
|
||||
|
||||
SendButton::~SendButton() = default;
|
||||
|
||||
void SendButton::setState(State state) {
|
||||
if (_state == state) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto previousType = _state.type;
|
||||
const auto newType = state.type;
|
||||
const auto voiceRoundTransition = isVoiceRoundTransition(
|
||||
previousType,
|
||||
newType);
|
||||
|
||||
const auto hasSlowmode = (_state.slowmodeDelay > 0);
|
||||
const auto hasSlowmodeChanged = hasSlowmode != (state.slowmodeDelay > 0);
|
||||
auto withSameSlowmode = state;
|
||||
withSameSlowmode.slowmodeDelay = _state.slowmodeDelay;
|
||||
const auto animate = hasSlowmodeChanged
|
||||
|| (!hasSlowmode && withSameSlowmode != _state);
|
||||
if (animate) {
|
||||
|
||||
if (animate && !voiceRoundTransition) {
|
||||
_contentFrom = grabContent();
|
||||
}
|
||||
|
||||
if (_voiceRoundAnimating && !voiceRoundTransition) {
|
||||
_voiceRoundAnimating = false;
|
||||
}
|
||||
|
||||
if (_state.slowmodeDelay != state.slowmodeDelay) {
|
||||
const auto seconds = state.slowmodeDelay;
|
||||
const auto minutes = seconds / 60;
|
||||
@@ -60,7 +78,29 @@ void SendButton::setState(State state) {
|
||||
kMarkupTextOptions);
|
||||
}
|
||||
_state = state;
|
||||
if (animate) {
|
||||
|
||||
if (voiceRoundTransition) {
|
||||
_voiceRoundAnimating = true;
|
||||
|
||||
const auto toRound = (newType == Type::Round);
|
||||
const auto index = toRound ? kVoiceToRoundIndex : kRoundToVoiceIndex;
|
||||
auto &icon = _voiceRoundIcons[index];
|
||||
if (!icon) {
|
||||
initVoiceRoundIcon(index);
|
||||
}
|
||||
icon->animate([=, raw = icon.get()] {
|
||||
update();
|
||||
if (!raw->animating()) {
|
||||
_voiceRoundAnimating = false;
|
||||
}
|
||||
}, 0, icon->framesCount() - 1);
|
||||
auto &after = _voiceRoundIcons[1 - index];
|
||||
if (!after) {
|
||||
initVoiceRoundIcon(1 - index);
|
||||
} else if (after->frameIndex() != 0) {
|
||||
after->jumpTo(0, nullptr);
|
||||
}
|
||||
} else if (animate) {
|
||||
_stateChangeFromWidth = width();
|
||||
_stateChangeAnimation.stop();
|
||||
updateSize();
|
||||
@@ -86,6 +126,12 @@ void SendButton::paintEvent(QPaintEvent *e) {
|
||||
auto p = QPainter(this);
|
||||
|
||||
auto over = (isDown() || isOver());
|
||||
|
||||
if (_voiceRoundAnimating) {
|
||||
paintVoiceRoundIcon(p, over);
|
||||
return;
|
||||
}
|
||||
|
||||
auto changed = _stateChangeAnimation.value(1.);
|
||||
if (changed < 1.) {
|
||||
PainterHighQualityEnabler hq(p);
|
||||
@@ -153,11 +199,7 @@ void SendButton::paintRecord(QPainter &p, bool over) {
|
||||
(width() - _st.inner.rippleAreaSize) / 2,
|
||||
_st.inner.rippleAreaPosition.y());
|
||||
}
|
||||
|
||||
const auto &icon = (isDisabled() || !over)
|
||||
? _st.record
|
||||
: _st.recordOver;
|
||||
icon.paintInCenter(p, rect());
|
||||
paintLottieIcon(p, kVoiceToRoundIndex, over);
|
||||
}
|
||||
|
||||
void SendButton::paintRound(QPainter &p, bool over) {
|
||||
@@ -167,11 +209,20 @@ void SendButton::paintRound(QPainter &p, bool over) {
|
||||
(width() - _st.inner.rippleAreaSize) / 2,
|
||||
_st.inner.rippleAreaPosition.y());
|
||||
}
|
||||
paintLottieIcon(p, kRoundToVoiceIndex, over);
|
||||
}
|
||||
|
||||
const auto &icon = (isDisabled() || !over)
|
||||
? _st.round
|
||||
: _st.roundOver;
|
||||
icon.paintInCenter(p, rect());
|
||||
void SendButton::paintLottieIcon(QPainter &p, int index, bool over) {
|
||||
auto &icon = _voiceRoundIcons[index];
|
||||
if (!icon) {
|
||||
initVoiceRoundIcon(index);
|
||||
} else if (!_voiceRoundAnimating && icon->frameIndex() != 0) {
|
||||
icon->jumpTo(0, [=] { update(); });
|
||||
}
|
||||
const auto color = (isDisabled() || !over)
|
||||
? st::historyRecordVoiceFg->c
|
||||
: st::historyRecordVoiceFgOver->c;
|
||||
icon->paintInCenter(p, rect(), color);
|
||||
}
|
||||
|
||||
void SendButton::paintSave(QPainter &p, bool over) {
|
||||
@@ -330,6 +381,39 @@ QPoint SendButton::prepareRippleStartPosition() const {
|
||||
return real - QPoint((width() - size) / 2, y);
|
||||
}
|
||||
|
||||
void SendButton::initVoiceRoundIcon(int index) {
|
||||
Expects(index >= 0 && index < 2);
|
||||
|
||||
_voiceRoundIcons[index] = Lottie::MakeIcon({
|
||||
.path = ((index == kVoiceToRoundIndex)
|
||||
? u":/animations/chat/voice_to_video.tgs"_q
|
||||
: u":/animations/chat/video_to_voice.tgs"_q),
|
||||
.sizeOverride = _st.recordSize,
|
||||
.colorizeUsingAlpha = true,
|
||||
});
|
||||
}
|
||||
|
||||
void SendButton::paintVoiceRoundIcon(QPainter &p, bool over) {
|
||||
if (!isDisabled()) {
|
||||
paintRipple(
|
||||
p,
|
||||
(width() - _st.inner.rippleAreaSize) / 2,
|
||||
_st.inner.rippleAreaPosition.y());
|
||||
}
|
||||
|
||||
const auto color = (isDisabled() || !over)
|
||||
? st::historyRecordVoiceFg->c
|
||||
: st::historyRecordVoiceFgOver->c;
|
||||
const auto toVideo = (_state.type == Type::Round);
|
||||
const auto index = toVideo ? kVoiceToRoundIndex : kRoundToVoiceIndex;
|
||||
_voiceRoundIcons[index]->paintInCenter(p, rect(), color);
|
||||
}
|
||||
|
||||
bool SendButton::isVoiceRoundTransition(Type from, Type to) {
|
||||
return (from == Type::Record && to == Type::Round)
|
||||
|| (from == Type::Round && to == Type::Record);
|
||||
}
|
||||
|
||||
SendStarButton::SendStarButton(
|
||||
QWidget *parent,
|
||||
const style::IconButton &st,
|
||||
|
||||
@@ -9,6 +9,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "ui/widgets/buttons.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Lottie {
|
||||
class Icon;
|
||||
} // namespace Lottie
|
||||
|
||||
namespace style {
|
||||
struct SendButton;
|
||||
struct IconButton;
|
||||
@@ -20,6 +26,7 @@ namespace Ui {
|
||||
class SendButton final : public RippleButton {
|
||||
public:
|
||||
SendButton(QWidget *parent, const style::SendButton &st);
|
||||
~SendButton();
|
||||
|
||||
static constexpr auto kSlowmodeDelayLimit = 100 * 60;
|
||||
|
||||
@@ -76,6 +83,11 @@ private:
|
||||
void paintSlowmode(QPainter &p);
|
||||
void paintStarsToSend(QPainter &p, bool over);
|
||||
|
||||
void initVoiceRoundIcon(int index);
|
||||
void paintVoiceRoundIcon(QPainter &p, bool over);
|
||||
[[nodiscard]] static bool isVoiceRoundTransition(Type from, Type to);
|
||||
void paintLottieIcon(QPainter &p, int index, bool over);
|
||||
|
||||
const style::SendButton &_st;
|
||||
|
||||
State _state;
|
||||
@@ -87,6 +99,9 @@ private:
|
||||
QString _slowmodeDelayText;
|
||||
Ui::Text::String _starsToSendText;
|
||||
|
||||
std::array<std::unique_ptr<Lottie::Icon>, 2> _voiceRoundIcons;
|
||||
bool _voiceRoundAnimating = false;
|
||||
|
||||
};
|
||||
|
||||
struct SendStarButtonState {
|
||||
|
||||
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
|
||||
#include "dialogs/dialogs_three_state_icon.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "lottie/lottie_icon.h"
|
||||
#include "platform/platform_window_title.h"
|
||||
#include "ui/text/text_options.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
@@ -565,7 +566,13 @@ void Generator::paintComposeArea() {
|
||||
: st::historyAttach.iconPosition.y();
|
||||
st::historyAttach.icon[_palette].paint(*_p, _composeArea.x() + attachIconLeft, controlsTop + attachIconTop, _rect.width());
|
||||
auto right = st::historySendRight + st::historySendSize.width();
|
||||
st::historyRecordVoice[_palette].paintInCenter(*_p, QRect(_composeArea.x() + _composeArea.width() - right, controlsTop, st::historySendSize.width(), st::historySendSize.height()));
|
||||
|
||||
const auto recordIcon = Lottie::MakeIcon({
|
||||
.path = u":/animations/chat/voice_to_video.tgs"_q,
|
||||
.sizeOverride = st::historySend.recordSize,
|
||||
.colorizeUsingAlpha = true,
|
||||
});
|
||||
recordIcon->paintInCenter(*_p, QRect(_composeArea.x() + _composeArea.width() - right, controlsTop, st::historySendSize.width(), st::historySendSize.height()), st::historyRecordVoiceFg[_palette]->c);
|
||||
|
||||
const auto &emojiButton = st::historyAttachEmoji.inner;
|
||||
const auto emojiIconLeft = (emojiButton.iconPosition.x() < 0)
|
||||
|
||||
+1
-1
Submodule Telegram/lib_lottie updated: 99d8cc4d18...cba5d113eb
Reference in New Issue
Block a user