Formatted classes for send actions.

This commit is contained in:
23rd 2021-08-30 16:11:43 +03:00
parent ccea6ce492
commit 0852dbc40f
3 changed files with 185 additions and 49 deletions

View file

@ -67,9 +67,13 @@ bool SendActionPainter::updateNeedsAnimating(
}, [&](const MTPDsendMessageRecordRoundAction &) { }, [&](const MTPDsendMessageRecordRoundAction &) {
emplaceAction(Type::RecordRound, kStatusShowClientsideRecordRound); emplaceAction(Type::RecordRound, kStatusShowClientsideRecordRound);
}, [&](const MTPDsendMessageGeoLocationAction &) { }, [&](const MTPDsendMessageGeoLocationAction &) {
emplaceAction(Type::ChooseLocation, kStatusShowClientsideChooseLocation); emplaceAction(
Type::ChooseLocation,
kStatusShowClientsideChooseLocation);
}, [&](const MTPDsendMessageChooseContactAction &) { }, [&](const MTPDsendMessageChooseContactAction &) {
emplaceAction(Type::ChooseContact, kStatusShowClientsideChooseContact); emplaceAction(
Type::ChooseContact,
kStatusShowClientsideChooseContact);
}, [&](const MTPDsendMessageUploadVideoAction &data) { }, [&](const MTPDsendMessageUploadVideoAction &data) {
emplaceAction( emplaceAction(
Type::UploadVideo, Type::UploadVideo,
@ -221,19 +225,41 @@ bool SendActionPainter::updateNeedsAnimating(crl::time now, bool force) {
} else if (!_sendActions.empty()) { } else if (!_sendActions.empty()) {
// Handles all actions except game playing. // Handles all actions except game playing.
using Type = Api::SendProgressType; using Type = Api::SendProgressType;
auto sendActionString = [](Type type, const QString &name) -> QString { const auto sendActionString = [](
Type type,
const QString &name) -> QString {
switch (type) { switch (type) {
case Type::RecordVideo: return name.isEmpty() ? tr::lng_send_action_record_video(tr::now) : tr::lng_user_action_record_video(tr::now, lt_user, name); case Type::RecordVideo: return name.isEmpty()
case Type::UploadVideo: return name.isEmpty() ? tr::lng_send_action_upload_video(tr::now) : tr::lng_user_action_upload_video(tr::now, lt_user, name); ? tr::lng_send_action_record_video({})
case Type::RecordVoice: return name.isEmpty() ? tr::lng_send_action_record_audio(tr::now) : tr::lng_user_action_record_audio(tr::now, lt_user, name); : tr::lng_user_action_record_video({}, lt_user, name);
case Type::UploadVoice: return name.isEmpty() ? tr::lng_send_action_upload_audio(tr::now) : tr::lng_user_action_upload_audio(tr::now, lt_user, name); case Type::UploadVideo: return name.isEmpty()
case Type::RecordRound: return name.isEmpty() ? tr::lng_send_action_record_round(tr::now) : tr::lng_user_action_record_round(tr::now, lt_user, name); ? tr::lng_send_action_upload_video({})
case Type::UploadRound: return name.isEmpty() ? tr::lng_send_action_upload_round(tr::now) : tr::lng_user_action_upload_round(tr::now, lt_user, name); : tr::lng_user_action_upload_video({}, lt_user, name);
case Type::UploadPhoto: return name.isEmpty() ? tr::lng_send_action_upload_photo(tr::now) : tr::lng_user_action_upload_photo(tr::now, lt_user, name); case Type::RecordVoice: return name.isEmpty()
case Type::UploadFile: return name.isEmpty() ? tr::lng_send_action_upload_file(tr::now) : tr::lng_user_action_upload_file(tr::now, lt_user, name); ? tr::lng_send_action_record_audio({})
: tr::lng_user_action_record_audio({}, lt_user, name);
case Type::UploadVoice: return name.isEmpty()
? tr::lng_send_action_upload_audio({})
: tr::lng_user_action_upload_audio({}, lt_user, name);
case Type::RecordRound: return name.isEmpty()
? tr::lng_send_action_record_round({})
: tr::lng_user_action_record_round({}, lt_user, name);
case Type::UploadRound: return name.isEmpty()
? tr::lng_send_action_upload_round({})
: tr::lng_user_action_upload_round({}, lt_user, name);
case Type::UploadPhoto: return name.isEmpty()
? tr::lng_send_action_upload_photo({})
: tr::lng_user_action_upload_photo({}, lt_user, name);
case Type::UploadFile: return name.isEmpty()
? tr::lng_send_action_upload_file({})
: tr::lng_user_action_upload_file({}, lt_user, name);
case Type::ChooseLocation: case Type::ChooseLocation:
case Type::ChooseContact: return name.isEmpty() ? tr::lng_typing(tr::now) : tr::lng_user_typing(tr::now, lt_user, name); case Type::ChooseContact: return name.isEmpty()
case Type::ChooseSticker: return name.isEmpty() ? tr::lng_send_action_choose_sticker(tr::now) : tr::lng_user_action_choose_sticker(tr::now, lt_user, name); ? tr::lng_typing({})
: tr::lng_user_typing({}, lt_user, name);
case Type::ChooseSticker: return name.isEmpty()
? tr::lng_send_action_choose_sticker({})
: tr::lng_user_action_choose_sticker({}, lt_user, name);
default: break; default: break;
}; };
return QString(); return QString();

View file

@ -62,7 +62,9 @@ protected:
return _started; return _started;
} }
[[nodiscard]] int frameTime(crl::time now) const { [[nodiscard]] int frameTime(crl::time now) const {
return anim::Disabled() ? 0 : (std::max(now - _started, crl::time(0)) % _period); return anim::Disabled()
? 0
: (std::max(now - _started, crl::time(0)) % _period);
} }
private: private:
@ -73,7 +75,9 @@ private:
namespace { namespace {
using ImplementationsMap = QMap<Api::SendProgressType, const SendActionAnimation::Impl::MetaData*>; using ImplementationsMap = QMap<
Api::SendProgressType,
const SendActionAnimation::Impl::MetaData*>;
NeverFreedPointer<ImplementationsMap> Implementations; NeverFreedPointer<ImplementationsMap> Implementations;
class TypingAnimation : public SendActionAnimation::Impl { class TypingAnimation : public SendActionAnimation::Impl {
@ -90,34 +94,64 @@ public:
} }
int width() const override { int width() const override {
return st::historySendActionTypingPosition.x() + kTypingDotsCount * st::historySendActionTypingDelta; return st::historySendActionTypingPosition.x()
+ kTypingDotsCount * st::historySendActionTypingDelta;
} }
void paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time now) override; void paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time now) override;
}; };
const TypingAnimation::MetaData TypingAnimation::kMeta = { 0, &TypingAnimation::create }; const TypingAnimation::MetaData TypingAnimation::kMeta = {
0,
&TypingAnimation::create,
};
void TypingAnimation::paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time now) { void TypingAnimation::paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time now) {
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(color); p.setBrush(color);
auto frameMs = frameTime(now); auto frameMs = frameTime(now);
auto position = QPointF(x + 0.5, y - 0.5) + st::historySendActionTypingPosition; auto position = QPointF(x + 0.5, y - 0.5)
+ st::historySendActionTypingPosition;
for (auto i = 0; i != kTypingDotsCount; ++i) { for (auto i = 0; i != kTypingDotsCount; ++i) {
auto r = st::historySendActionTypingSmallNumerator / st::historySendActionTypingDenominator; auto r = st::historySendActionTypingSmallNumerator
/ st::historySendActionTypingDenominator;
if (frameMs < 2 * st::historySendActionTypingHalfPeriod) { if (frameMs < 2 * st::historySendActionTypingHalfPeriod) {
auto delta = (st::historySendActionTypingLargeNumerator - st::historySendActionTypingSmallNumerator) / st::historySendActionTypingDenominator; const auto delta = (st::historySendActionTypingLargeNumerator
- st::historySendActionTypingSmallNumerator)
/ st::historySendActionTypingDenominator;
if (frameMs < st::historySendActionTypingHalfPeriod) { if (frameMs < st::historySendActionTypingHalfPeriod) {
r += delta * anim::easeOutCirc(1., float64(frameMs) / st::historySendActionTypingHalfPeriod); r += delta
* anim::easeOutCirc(
1.,
float64(frameMs)
/ st::historySendActionTypingHalfPeriod);
} else { } else {
r += delta * (1. - anim::easeOutCirc(1., float64(frameMs - st::historySendActionTypingHalfPeriod) / st::historySendActionTypingHalfPeriod)); r += delta
* (1. - anim::easeOutCirc(
1.,
float64(frameMs
- st::historySendActionTypingHalfPeriod)
/ st::historySendActionTypingHalfPeriod));
} }
} }
p.drawEllipse(position, r, r); p.drawEllipse(position, r, r);
position.setX(position.x() + st::historySendActionTypingDelta); position.setX(position.x() + st::historySendActionTypingDelta);
frameMs = (frameMs + st::historySendActionTypingDuration - st::historySendActionTypingDeltaTime) % st::historySendActionTypingDuration; frameMs = (frameMs + period() - st::historySendActionTypingDeltaTime)
% period();
} }
} }
@ -135,29 +169,51 @@ public:
} }
int width() const override { int width() const override {
return st::historySendActionRecordPosition.x() + (kRecordArcsCount + 1) * st::historySendActionRecordDelta; return st::historySendActionRecordPosition.x()
+ (kRecordArcsCount + 1) * st::historySendActionRecordDelta;
} }
void paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time now) override; void paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time now) override;
}; };
const RecordAnimation::MetaData RecordAnimation::kMeta = { 0, &RecordAnimation::create }; const RecordAnimation::MetaData RecordAnimation::kMeta = {
0,
&RecordAnimation::create,
};
void RecordAnimation::paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time now) { void RecordAnimation::paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time now) {
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
const auto frameMs = frameTime(now); const auto frameMs = frameTime(now);
auto pen = color->p; auto pen = color->p;
pen.setWidth(st::historySendActionRecordStrokeNumerator / st::historySendActionRecordDenominator); pen.setWidth(st::historySendActionRecordStrokeNumerator
/ st::historySendActionRecordDenominator);
pen.setJoinStyle(Qt::RoundJoin); pen.setJoinStyle(Qt::RoundJoin);
pen.setCapStyle(Qt::RoundCap); pen.setCapStyle(Qt::RoundCap);
p.setPen(pen); p.setPen(pen);
p.setBrush(Qt::NoBrush); p.setBrush(Qt::NoBrush);
auto progress = frameMs / float64(st::historySendActionRecordDuration); auto progress = frameMs / float64(period());
auto size = st::historySendActionRecordPosition.x() + st::historySendActionRecordDelta * progress; auto size = st::historySendActionRecordPosition.x()
+ st::historySendActionRecordDelta * progress;
y += st::historySendActionRecordPosition.y(); y += st::historySendActionRecordPosition.y();
for (auto i = 0; i != kRecordArcsCount; ++i) { for (auto i = 0; i != kRecordArcsCount; ++i) {
p.setOpacity((i == 0) ? progress : (i == kRecordArcsCount - 1) ? (1. - progress) : 1.); p.setOpacity((i == 0)
? progress
: (i == kRecordArcsCount - 1)
? (1. - progress)
: 1.);
auto rect = QRectF(x - size, y - size, 2 * size, 2 * size); auto rect = QRectF(x - size, y - size, 2 * size, 2 * size);
p.drawArc(rect, -FullArcLength / 24, FullArcLength / 12); p.drawArc(rect, -FullArcLength / 24, FullArcLength / 12);
size += st::historySendActionRecordDelta; size += st::historySendActionRecordDelta;
@ -179,33 +235,64 @@ public:
} }
int width() const override { int width() const override {
return st::historySendActionUploadPosition.x() + (kUploadArrowsCount + 1) * st::historySendActionUploadDelta; return st::historySendActionUploadPosition.x()
+ (kUploadArrowsCount + 1) * st::historySendActionUploadDelta;
} }
void paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time now) override; void paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time now) override;
}; };
const UploadAnimation::MetaData UploadAnimation::kMeta = { 0, &UploadAnimation::create }; const UploadAnimation::MetaData UploadAnimation::kMeta = {
0,
&UploadAnimation::create,
};
void UploadAnimation::paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time now) { void UploadAnimation::paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time now) {
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);
const auto frameMs = frameTime(now); const auto frameMs = frameTime(now);
auto pen = color->p; auto pen = color->p;
pen.setWidth(st::historySendActionUploadStrokeNumerator / st::historySendActionUploadDenominator); pen.setWidth(st::historySendActionUploadStrokeNumerator
/ st::historySendActionUploadDenominator);
pen.setJoinStyle(Qt::RoundJoin); pen.setJoinStyle(Qt::RoundJoin);
pen.setCapStyle(Qt::RoundCap); pen.setCapStyle(Qt::RoundCap);
p.setPen(pen); p.setPen(pen);
p.setBrush(Qt::NoBrush); p.setBrush(Qt::NoBrush);
auto progress = frameMs / float64(st::historySendActionUploadDuration); auto progress = frameMs / float64(period());
auto position = QPointF(x + st::historySendActionUploadDelta * progress, y) + st::historySendActionUploadPosition; auto position = st::historySendActionUploadPosition
+ QPointF(x + st::historySendActionUploadDelta * progress, y);
auto path = QPainterPath(); auto path = QPainterPath();
path.moveTo(0., -st::historySendActionUploadSizeNumerator / st::historySendActionUploadDenominator); path.moveTo(
path.lineTo(st::historySendActionUploadSizeNumerator / st::historySendActionUploadDenominator, 0.); 0.,
path.lineTo(0., st::historySendActionUploadSizeNumerator / st::historySendActionUploadDenominator); -st::historySendActionUploadSizeNumerator
/ st::historySendActionUploadDenominator);
path.lineTo(
st::historySendActionUploadSizeNumerator
/ st::historySendActionUploadDenominator,
0.);
path.lineTo(
0.,
st::historySendActionUploadSizeNumerator
/ st::historySendActionUploadDenominator);
p.translate(position); p.translate(position);
for (auto i = 0; i != kUploadArrowsCount; ++i) { for (auto i = 0; i != kUploadArrowsCount; ++i) {
p.setOpacity((i == 0) ? progress : (i == kUploadArrowsCount - 1) ? (1. - progress) : 1.); p.setOpacity((i == 0)
? progress
: (i == kUploadArrowsCount - 1)
? (1. - progress)
: 1.);
p.drawPath(path); p.drawPath(path);
position.setX(position.x() + st::historySendActionUploadDelta); position.setX(position.x() + st::historySendActionUploadDelta);
p.translate(st::historySendActionUploadDelta, 0); p.translate(st::historySendActionUploadDelta, 0);
@ -570,7 +657,8 @@ SendActionAnimation::~SendActionAnimation() = default;
bool SendActionAnimation::Impl::supports(Type type) const { bool SendActionAnimation::Impl::supports(Type type) const {
CreateImplementationsMap(); CreateImplementationsMap();
return Implementations->value(type, &TypingAnimation::kMeta) == metaData(); return Implementations->value(type, &TypingAnimation::kMeta)
== metaData();
} }
void SendActionAnimation::start(Type type) { void SendActionAnimation::start(Type type) {
@ -593,13 +681,24 @@ int SendActionAnimation::width() const {
return _impl ? _impl->width() : 0; return _impl ? _impl->width() : 0;
} }
void SendActionAnimation::paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time ms) const { void SendActionAnimation::paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time ms) const {
if (_impl) { if (_impl) {
_impl->paint(p, color, x, y, outerWidth, ms); _impl->paint(p, color, x, y, outerWidth, ms);
} }
} }
void SendActionAnimation::PaintSpeakingIdle(Painter &p, style::color color, int x, int y, int outerWidth) { void SendActionAnimation::PaintSpeakingIdle(
Painter &p,
style::color color,
int x,
int y,
int outerWidth) {
SpeakingAnimation::PaintIdle(p, color, x, y, outerWidth); SpeakingAnimation::PaintIdle(p, color, x, y, outerWidth);
} }

View file

@ -25,13 +25,24 @@ public:
void tryToFinish(); void tryToFinish();
int width() const; int width() const;
void paint(Painter &p, style::color color, int x, int y, int outerWidth, crl::time ms) const; void paint(
Painter &p,
style::color color,
int x,
int y,
int outerWidth,
crl::time ms) const;
explicit operator bool() const { explicit operator bool() const {
return _impl != nullptr; return _impl != nullptr;
} }
static void PaintSpeakingIdle(Painter &p, style::color color, int x, int y, int outerWidth); static void PaintSpeakingIdle(
Painter &p,
style::color color,
int x,
int y,
int outerWidth);
private: private:
[[nodiscard]] static std::unique_ptr<Impl> CreateByType(Type type); [[nodiscard]] static std::unique_ptr<Impl> CreateByType(Type type);