mirror of https://github.com/procxx/kepka.git
Add poll vote sending animation.
This commit is contained in:
parent
ac2dce4bb1
commit
93c8e9aa1f
|
@ -5360,10 +5360,26 @@ void ApiWrap::sendPollVotes(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto item = App::histItemById(itemId);
|
const auto item = App::histItemById(itemId);
|
||||||
|
const auto media = item ? item->media() : nullptr;
|
||||||
|
const auto poll = media ? media->poll() : nullptr;
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto showSending = poll && !options.empty();
|
||||||
|
const auto hideSending = [=] {
|
||||||
|
if (showSending) {
|
||||||
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
|
poll->sendingVote = QByteArray();
|
||||||
|
_session->data().requestItemRepaint(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (showSending) {
|
||||||
|
poll->sendingVote = options.front();
|
||||||
|
_session->data().requestItemRepaint(item);
|
||||||
|
}
|
||||||
|
|
||||||
auto prepared = QVector<MTPbytes>();
|
auto prepared = QVector<MTPbytes>();
|
||||||
prepared.reserve(options.size());
|
prepared.reserve(options.size());
|
||||||
ranges::transform(
|
ranges::transform(
|
||||||
|
@ -5376,9 +5392,11 @@ void ApiWrap::sendPollVotes(
|
||||||
MTP_vector<MTPbytes>(prepared)
|
MTP_vector<MTPbytes>(prepared)
|
||||||
)).done([=](const MTPUpdates &result) {
|
)).done([=](const MTPUpdates &result) {
|
||||||
_pollVotesRequestIds.erase(itemId);
|
_pollVotesRequestIds.erase(itemId);
|
||||||
|
hideSending();
|
||||||
applyUpdates(result);
|
applyUpdates(result);
|
||||||
}).fail([=](const RPCError &error) {
|
}).fail([=](const RPCError &error) {
|
||||||
_pollVotesRequestIds.erase(itemId);
|
_pollVotesRequestIds.erase(itemId);
|
||||||
|
hideSending();
|
||||||
}).send();
|
}).send();
|
||||||
_pollVotesRequestIds.emplace(itemId, requestId);
|
_pollVotesRequestIds.emplace(itemId, requestId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ struct PollData {
|
||||||
std::vector<PollAnswer> answers;
|
std::vector<PollAnswer> answers;
|
||||||
int totalVoters = 0;
|
int totalVoters = 0;
|
||||||
bool closed = false;
|
bool closed = false;
|
||||||
|
QByteArray sendingVote;
|
||||||
|
|
||||||
int version = 0;
|
int version = 0;
|
||||||
|
|
||||||
|
|
|
@ -525,6 +525,10 @@ historyPollRadio: Radio(defaultRadio) {
|
||||||
historyPollRadioOpacity: 0.7;
|
historyPollRadioOpacity: 0.7;
|
||||||
historyPollRadioOpacityOver: 1.;
|
historyPollRadioOpacityOver: 1.;
|
||||||
historyPollDuration: 300;
|
historyPollDuration: 300;
|
||||||
|
historyPollRadialAnimation: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) {
|
||||||
|
thickness: 2px;
|
||||||
|
size: size(18px, 18px);
|
||||||
|
}
|
||||||
|
|
||||||
boxAttachEmoji: IconButton(historyAttachEmoji) {
|
boxAttachEmoji: IconButton(historyAttachEmoji) {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/history_view_cursor_state.h"
|
#include "history/view/history_view_cursor_state.h"
|
||||||
#include "calls/calls_instance.h"
|
#include "calls/calls_instance.h"
|
||||||
#include "ui/text_options.h"
|
#include "ui/text_options.h"
|
||||||
|
#include "ui/effects/radial_animation.h"
|
||||||
#include "data/data_media_types.h"
|
#include "data/data_media_types.h"
|
||||||
#include "data/data_poll.h"
|
#include "data/data_poll.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -61,6 +62,48 @@ FormattedLargeNumber FormatLargeNumber(int64 number) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
struct HistoryPoll::AnswerAnimation {
|
||||||
|
anim::value percent;
|
||||||
|
anim::value filling;
|
||||||
|
anim::value opacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HistoryPoll::AnswersAnimation {
|
||||||
|
std::vector<AnswerAnimation> data;
|
||||||
|
Animation progress;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HistoryPoll::SendingAnimation {
|
||||||
|
SendingAnimation(
|
||||||
|
const QByteArray &option,
|
||||||
|
AnimationCallbacks &&callbacks);
|
||||||
|
|
||||||
|
QByteArray option;
|
||||||
|
Ui::InfiniteRadialAnimation animation;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HistoryPoll::Answer {
|
||||||
|
Answer();
|
||||||
|
|
||||||
|
void fillText(const PollAnswer &original);
|
||||||
|
|
||||||
|
Text text;
|
||||||
|
QByteArray option;
|
||||||
|
mutable int votes = 0;
|
||||||
|
mutable int votesPercentWidth = 0;
|
||||||
|
mutable float64 filling = 0.;
|
||||||
|
mutable QString votesPercent;
|
||||||
|
mutable bool chosen = false;
|
||||||
|
ClickHandlerPtr handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
HistoryPoll::SendingAnimation::SendingAnimation(
|
||||||
|
const QByteArray &option,
|
||||||
|
AnimationCallbacks &&callbacks)
|
||||||
|
: option(option)
|
||||||
|
, animation(std::move(callbacks), st::historyPollRadialAnimation) {
|
||||||
|
}
|
||||||
|
|
||||||
HistoryPoll::Answer::Answer() : text(st::msgMinWidth / 2) {
|
HistoryPoll::Answer::Answer() : text(st::msgMinWidth / 2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +230,7 @@ void HistoryPoll::updateTexts() {
|
||||||
updateVotes();
|
updateVotes();
|
||||||
|
|
||||||
if (willStartAnimation) {
|
if (willStartAnimation) {
|
||||||
startAnimation();
|
startAnswersAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +261,7 @@ void HistoryPoll::updateAnswers() {
|
||||||
answer.handler = createAnswerClickHandler(answer);
|
answer.handler = createAnswerClickHandler(answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
_answersAnimation = nullptr;
|
resetAnswersAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClickHandlerPtr HistoryPoll::createAnswerClickHandler(
|
ClickHandlerPtr HistoryPoll::createAnswerClickHandler(
|
||||||
|
@ -236,12 +279,32 @@ void HistoryPoll::updateVotes() const {
|
||||||
updateTotalVotes();
|
updateTotalVotes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryPoll::updateVotesCheckAnimation() const {
|
void HistoryPoll::updateVotesCheckAnimations() const {
|
||||||
const auto willStartAnimation = checkAnimationStart();
|
const auto willStartAnimation = checkAnimationStart();
|
||||||
updateVotes();
|
updateVotes();
|
||||||
if (willStartAnimation) {
|
if (willStartAnimation) {
|
||||||
startAnimation();
|
startAnswersAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto &sending = _poll->sendingVote;
|
||||||
|
if (sending.isEmpty() == !_sendingAnimation) {
|
||||||
|
if (_sendingAnimation) {
|
||||||
|
_sendingAnimation->option = sending;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sending.isEmpty()) {
|
||||||
|
if (!_answersAnimation) {
|
||||||
|
_sendingAnimation = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_sendingAnimation = std::make_unique<SendingAnimation>(
|
||||||
|
sending,
|
||||||
|
animation(
|
||||||
|
const_cast<HistoryPoll*>(this),
|
||||||
|
&HistoryPoll::step_radial));
|
||||||
|
_sendingAnimation->animation.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryPoll::updateTotalVotes() const {
|
void HistoryPoll::updateTotalVotes() const {
|
||||||
|
@ -307,7 +370,7 @@ void HistoryPoll::draw(Painter &p, const QRect &r, TextSelection selection, Time
|
||||||
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
if (width() < st::msgPadding.left() + st::msgPadding.right() + 1) return;
|
||||||
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
auto paintx = 0, painty = 0, paintw = width(), painth = height();
|
||||||
|
|
||||||
updateVotesCheckAnimation();
|
updateVotesCheckAnimations();
|
||||||
|
|
||||||
const auto outbg = _parent->hasOutLayout();
|
const auto outbg = _parent->hasOutLayout();
|
||||||
const auto selected = (selection == FullSelection);
|
const auto selected = (selection == FullSelection);
|
||||||
|
@ -332,7 +395,7 @@ void HistoryPoll::draw(Painter &p, const QRect &r, TextSelection selection, Time
|
||||||
? _answersAnimation->progress.current(ms, 1.)
|
? _answersAnimation->progress.current(ms, 1.)
|
||||||
: 1.;
|
: 1.;
|
||||||
if (progress == 1.) {
|
if (progress == 1.) {
|
||||||
_answersAnimation = nullptr;
|
resetAnswersAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &&answers = ranges::view::zip(
|
auto &&answers = ranges::view::zip(
|
||||||
|
@ -366,6 +429,19 @@ void HistoryPoll::draw(Painter &p, const QRect &r, TextSelection selection, Time
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryPoll::resetAnswersAnimation() const {
|
||||||
|
_answersAnimation = nullptr;
|
||||||
|
if (_poll->sendingVote.isEmpty()) {
|
||||||
|
_sendingAnimation = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryPoll::step_radial(TimeMs ms, bool timer) {
|
||||||
|
if (timer && !anim::Disabled()) {
|
||||||
|
Auth().data().requestViewRepaint(_parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int HistoryPoll::paintAnswer(
|
int HistoryPoll::paintAnswer(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const Answer &answer,
|
const Answer &answer,
|
||||||
|
@ -457,13 +533,34 @@ void HistoryPoll::paintRadio(
|
||||||
const auto &st = st::historyPollRadio;
|
const auto &st = st::historyPollRadio;
|
||||||
const auto over = ClickHandler::showAsActive(answer.handler);
|
const auto over = ClickHandler::showAsActive(answer.handler);
|
||||||
const auto ®ular = selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg);
|
const auto ®ular = selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg);
|
||||||
auto pen = regular->p;
|
|
||||||
pen.setWidth(st.thickness);
|
|
||||||
p.setPen(pen);
|
|
||||||
p.setBrush(Qt::NoBrush);
|
p.setBrush(Qt::NoBrush);
|
||||||
const auto o = p.opacity();
|
const auto o = p.opacity();
|
||||||
p.setOpacity(o * (over ? st::historyPollRadioOpacityOver : st::historyPollRadioOpacity));
|
p.setOpacity(o * (over ? st::historyPollRadioOpacityOver : st::historyPollRadioOpacity));
|
||||||
p.drawEllipse(QRectF(left, top, st.diameter, st.diameter).marginsRemoved(QMarginsF(st.thickness / 2., st.thickness / 2., st.thickness / 2., st.thickness / 2.)));
|
|
||||||
|
const auto rect = QRectF(left, top, st.diameter, st.diameter).marginsRemoved(QMarginsF(st.thickness / 2., st.thickness / 2., st.thickness / 2., st.thickness / 2.));
|
||||||
|
if (_sendingAnimation && _sendingAnimation->option == answer.option) {
|
||||||
|
const auto &active = selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg);
|
||||||
|
if (anim::Disabled()) {
|
||||||
|
anim::DrawStaticLoading(p, rect, st.thickness, active);
|
||||||
|
} else {
|
||||||
|
const auto state = _sendingAnimation->animation.computeState();
|
||||||
|
auto pen = anim::pen(regular, active, state.shown);
|
||||||
|
pen.setWidth(st.thickness);
|
||||||
|
pen.setCapStyle(Qt::RoundCap);
|
||||||
|
p.setPen(pen);
|
||||||
|
p.drawArc(
|
||||||
|
rect,
|
||||||
|
state.arcFrom,
|
||||||
|
state.arcLength);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto pen = regular->p;
|
||||||
|
pen.setWidth(st.thickness);
|
||||||
|
p.setPen(pen);
|
||||||
|
p.drawEllipse(rect);
|
||||||
|
}
|
||||||
|
|
||||||
p.setOpacity(o);
|
p.setOpacity(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,7 +661,7 @@ bool HistoryPoll::checkAnimationStart() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryPoll::startAnimation() const {
|
void HistoryPoll::startAnswersAnimation() const {
|
||||||
if (!_answersAnimation) {
|
if (!_answersAnimation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -587,7 +684,7 @@ void HistoryPoll::startAnimation() const {
|
||||||
|
|
||||||
TextState HistoryPoll::textState(QPoint point, StateRequest request) const {
|
TextState HistoryPoll::textState(QPoint point, StateRequest request) const {
|
||||||
auto result = TextState(_parent);
|
auto result = TextState(_parent);
|
||||||
if (!canVote()) {
|
if (!canVote() || !_poll->sendingVote.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,31 +37,10 @@ public:
|
||||||
~HistoryPoll();
|
~HistoryPoll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct AnswerAnimation {
|
struct AnswerAnimation;
|
||||||
anim::value percent;
|
struct AnswersAnimation;
|
||||||
anim::value filling;
|
struct SendingAnimation;
|
||||||
anim::value opacity;
|
struct Answer;
|
||||||
};
|
|
||||||
|
|
||||||
struct AnswersAnimation {
|
|
||||||
std::vector<AnswerAnimation> data;
|
|
||||||
Animation progress;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Answer {
|
|
||||||
Answer();
|
|
||||||
|
|
||||||
void fillText(const PollAnswer &original);
|
|
||||||
|
|
||||||
Text text;
|
|
||||||
QByteArray option;
|
|
||||||
mutable int votes = 0;
|
|
||||||
mutable int votesPercentWidth = 0;
|
|
||||||
mutable float64 filling = 0.;
|
|
||||||
mutable QString votesPercent;
|
|
||||||
mutable bool chosen = false;
|
|
||||||
ClickHandlerPtr handler;
|
|
||||||
};
|
|
||||||
|
|
||||||
QSize countOptimalSize() override;
|
QSize countOptimalSize() override;
|
||||||
QSize countCurrentSize(int newWidth) override;
|
QSize countCurrentSize(int newWidth) override;
|
||||||
|
@ -81,7 +60,7 @@ private:
|
||||||
const PollAnswer &original,
|
const PollAnswer &original,
|
||||||
int totalVotes,
|
int totalVotes,
|
||||||
int maxVotes) const;
|
int maxVotes) const;
|
||||||
void updateVotesCheckAnimation() const;
|
void updateVotesCheckAnimations() const;
|
||||||
|
|
||||||
int paintAnswer(
|
int paintAnswer(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
@ -119,7 +98,9 @@ private:
|
||||||
bool checkAnimationStart() const;
|
bool checkAnimationStart() const;
|
||||||
bool answerVotesChanged() const;
|
bool answerVotesChanged() const;
|
||||||
void saveStateInAnimation() const;
|
void saveStateInAnimation() const;
|
||||||
void startAnimation() const;
|
void startAnswersAnimation() const;
|
||||||
|
void resetAnswersAnimation() const;
|
||||||
|
void step_radial(TimeMs ms, bool timer);
|
||||||
|
|
||||||
not_null<PollData*> _poll;
|
not_null<PollData*> _poll;
|
||||||
int _pollVersion = 0;
|
int _pollVersion = 0;
|
||||||
|
@ -133,5 +114,6 @@ private:
|
||||||
mutable Text _totalVotesLabel;
|
mutable Text _totalVotesLabel;
|
||||||
|
|
||||||
mutable std::unique_ptr<AnswersAnimation> _answersAnimation;
|
mutable std::unique_ptr<AnswersAnimation> _answersAnimation;
|
||||||
|
mutable std::unique_ptr<SendingAnimation> _sendingAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue