Show progress left to close by timer in polls.

This commit is contained in:
John Preston 2020-04-10 13:29:49 +04:00
parent 423daecbde
commit 71637d2a0e
6 changed files with 112 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -622,6 +622,10 @@ historyQuizExplainIn: icon {{ "quiz_explain", msgInDateFg }};
historyQuizExplainInSelected: icon {{ "quiz_explain", msgInDateFgSelected }};
historyQuizExplainOut: icon {{ "quiz_explain", msgOutDateFg }};
historyQuizExplainOutSelected: icon {{ "quiz_explain", msgOutDateFgSelected }};
historyQuizTimerIn: icon {{ "quiz_timer", msgInDateFg }};
historyQuizTimerInSelected: icon {{ "quiz_timer", msgInDateFgSelected }};
historyQuizTimerOut: icon {{ "quiz_timer", msgOutDateFg }};
historyQuizTimerOutSelected: icon {{ "quiz_timer", msgOutDateFgSelected }};
historySlowmodeCounterMargins: margins(0px, 0px, 10px, 0px);

View File

@ -24,6 +24,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_poll.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "base/unixtime.h"
#include "base/timer.h"
#include "layout.h"
#include "main/main_session.h"
#include "apiwrap.h"
@ -40,6 +42,8 @@ constexpr auto kRotateAmplitude = 3.;
constexpr auto kScaleSegments = 2;
constexpr auto kScaleAmplitude = 0.03;
constexpr auto kRollDuration = crl::time(400);
constexpr auto kLargestRadialDuration = 30 * crl::time(1000);
constexpr auto kCriticalCloseDuration = 5 * crl::time(1000);
struct PercentCounterItem {
int index = 0;
@ -170,6 +174,16 @@ struct Poll::Answer {
mutable std::unique_ptr<Ui::RippleAnimation> ripple;
};
struct Poll::CloseInformation {
CloseInformation(TimeId date, TimeId period, Fn<void()> repaint);
crl::time start = 0;
crl::time finish = 0;
crl::time duration = 0;
base::Timer timer;
Ui::Animations::Basic radial;
};
template <typename Callback>
Poll::SendingAnimation::SendingAnimation(
const QByteArray &option,
@ -197,6 +211,16 @@ void Poll::Answer::fillData(
Ui::WebpageTextTitleOptions());
}
Poll::CloseInformation::CloseInformation(
TimeId date,
TimeId period,
Fn<void()> repaint)
: duration(period * crl::time(1000))
, timer(std::move(repaint)) {
const auto left = std::clamp(date - base::unixtime::now(), 0, period);
finish = crl::now() + left * crl::time(1000);
}
Poll::Poll(
not_null<Element*> parent,
not_null<PollData*> poll)
@ -676,6 +700,7 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
p.setPen(regular);
_subtitle.drawLeftElided(p, padding.left(), tshift, paintw, width());
paintRecentVoters(p, padding.left() + _subtitle.maxWidth(), tshift, selection);
paintCloseByTimer(p, padding.left() + paintw, tshift, selection);
paintShowSolution(p, padding.left() + paintw, tshift, selection);
tshift += st::msgDateFont->height + st::historyPollAnswersSkip;
@ -823,6 +848,80 @@ void Poll::paintRecentVoters(
}
}
void Poll::paintCloseByTimer(
Painter &p,
int right,
int top,
TextSelection selection) const {
if (!canVote() || _poll->closeDate <= 0 || _poll->closePeriod <= 0) {
_close = nullptr;
return;
}
if (!_close) {
_close = std::make_unique<CloseInformation>(
_poll->closeDate,
_poll->closePeriod,
[=] { history()->owner().requestViewRepaint(_parent); });
}
const auto now = crl::now();
const auto left = std::max(_close->finish - now, crl::time(0));
const auto radial = std::min(_close->duration, kLargestRadialDuration);
if (!left) {
_close->radial.stop();
} else if (left < radial && !anim::Disabled()) {
if (!_close->radial.animating()) {
_close->radial.init([=] {
history()->owner().requestViewRepaint(_parent);
});
_close->radial.start();
}
} else {
_close->radial.stop();
}
const auto time = formatDurationText(int(std::ceil(left / 1000.)));
const auto outbg = _parent->hasOutLayout();
const auto selected = (selection == FullSelection);
const auto &icon = selected
? (outbg
? st::historyQuizTimerOutSelected
: st::historyQuizTimerInSelected)
: (outbg ? st::historyQuizTimerOut : st::historyQuizTimerIn);
const auto x = right - icon.width();
const auto y = top
+ (st::normalFont->height - icon.height()) / 2
- st::lineWidth;
const auto &regular = (left < kCriticalCloseDuration)
? st::boxTextFgError
: selected
? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected)
: (outbg ? st::msgOutDateFg : st::msgInDateFg);
p.setPen(regular);
const auto timeWidth = st::normalFont->width(time);
p.drawTextLeft(x - timeWidth, top, width(), time, timeWidth);
if (left < radial) {
auto hq = PainterHighQualityEnabler(p);
const auto part = std::max(
left / float64(radial),
1. / FullArcLength);
const auto length = int(std::round(FullArcLength * part));
auto pen = regular->p;
pen.setWidth(st::historyPollRadio.thickness);
pen.setCapStyle(Qt::RoundCap);
p.setPen(pen);
const auto size = icon.width() / 2;
const auto left = (x + (icon.width() - size) / 2);
const auto top = (y + (icon.height() - size) / 2) + st::lineWidth;
p.drawArc(left, top, size, size, (FullArcLength / 4), length);
} else {
icon.paint(p, x, y, width());
}
if (left > (anim::Disabled() ? 0 : (radial - 1))) {
const auto next = (left % 1000);
_close->timer.callOnce((next ? next : 1000) + 1);
}
}
void Poll::paintShowSolution(
Painter &p,
int right,

View File

@ -24,6 +24,7 @@ public:
Poll(
not_null<Element*> parent,
not_null<PollData*> poll);
~Poll();
void draw(Painter &p, const QRect &r, TextSelection selection, crl::time ms) const override;
TextState textState(QPoint point, StateRequest request) const override;
@ -53,13 +54,12 @@ public:
const ClickHandlerPtr &handler,
bool pressed) override;
~Poll();
private:
struct AnswerAnimation;
struct AnswersAnimation;
struct SendingAnimation;
struct Answer;
struct CloseInformation;
QSize countOptimalSize() override;
QSize countCurrentSize(int newWidth) override;
@ -96,6 +96,11 @@ private:
int left,
int top,
TextSelection selection) const;
void paintCloseByTimer(
Painter &p,
int right,
int top,
TextSelection selection) const;
void paintShowSolution(
Painter &p,
int right,
@ -194,6 +199,8 @@ private:
Ui::Animations::Simple _wrongAnswerAnimation;
mutable QPoint _lastLinkPoint;
mutable std::unique_ptr<CloseInformation> _close;
bool _hasSelected = false;
bool _votedFromHere = false;
mutable bool _wrongAnswerAnimated = false;