Use new animations engine in all Basic-s.

This commit is contained in:
John Preston 2019-04-01 21:44:54 +04:00
parent cd3c1c6dc0
commit a6e96f9a28
41 changed files with 479 additions and 487 deletions

View File

@ -400,7 +400,7 @@ BackgroundPreviewBox::BackgroundPreviewBox(
lang(lng_background_text2), lang(lng_background_text2),
true)) true))
, _paper(paper) , _paper(paper)
, _radial(animation(this, &BackgroundPreviewBox::step_radial)) { , _radial([=](crl::time now) { return radialAnimationCallback(now); }) {
subscribe(Auth().downloaderTaskFinished(), [=] { update(); }); subscribe(Auth().downloaderTaskFinished(), [=] { update(); });
} }
@ -549,13 +549,8 @@ void BackgroundPreviewBox::paintImage(Painter &p, crl::time ms) {
} }
void BackgroundPreviewBox::paintRadial(Painter &p, crl::time ms) { void BackgroundPreviewBox::paintRadial(Painter &p, crl::time ms) {
bool radial = false; const auto radial = _radial.animating();
float64 radialOpacity = 0; const auto radialOpacity = radial ? _radial.opacity() : 0.;
if (_radial.animating()) {
_radial.step(ms);
radial = _radial.animating();
radialOpacity = _radial.opacity();
}
if (!radial) { if (!radial) {
return; return;
} }
@ -623,7 +618,7 @@ void BackgroundPreviewBox::paintDate(Painter &p) {
p.drawText(bubbleLeft + st::msgServicePadding.left(), bubbleTop + st::msgServicePadding.top() + st::msgServiceFont->ascent, text); p.drawText(bubbleLeft + st::msgServicePadding.left(), bubbleTop + st::msgServicePadding.top() + st::msgServiceFont->ascent, text);
} }
void BackgroundPreviewBox::step_radial(crl::time ms, bool timer) { void BackgroundPreviewBox::radialAnimationCallback(crl::time now) {
Expects(_paper.document() != nullptr); Expects(_paper.document() != nullptr);
const auto document = _paper.document(); const auto document = _paper.document();
@ -631,9 +626,8 @@ void BackgroundPreviewBox::step_radial(crl::time ms, bool timer) {
const auto updated = _radial.update( const auto updated = _radial.update(
document->progress(), document->progress(),
!document->loading(), !document->loading(),
ms); now);
if (timer if ((wasAnimating || _radial.animating())
&& (wasAnimating || _radial.animating())
&& (!anim::Disabled() || updated)) { && (!anim::Disabled() || updated)) {
update(radialRect()); update(radialRect());
} }

View File

@ -50,7 +50,7 @@ private:
void apply(); void apply();
void share(); void share();
void step_radial(crl::time ms, bool timer); void radialAnimationCallback(crl::time now);
QRect radialRect() const; QRect radialRect() const;
void checkLoadedDocument(); void checkLoadedDocument();

View File

@ -52,7 +52,7 @@ protected:
private: private:
void setupControls(View &&view); void setupControls(View &&view);
int countAvailableWidth() const; int countAvailableWidth() const;
void step_radial(crl::time ms, bool timer); void radialAnimationCallback();
void paintCheck(Painter &p, crl::time ms); void paintCheck(Painter &p, crl::time ms);
void showMenu(); void showMenu();
@ -209,7 +209,7 @@ void ProxyRow::updateFields(View &&view) {
if (state == State::Connecting) { if (state == State::Connecting) {
if (!_progress) { if (!_progress) {
_progress = std::make_unique<Ui::InfiniteRadialAnimation>( _progress = std::make_unique<Ui::InfiniteRadialAnimation>(
animation(this, &ProxyRow::step_radial), [=] { radialAnimationCallback(); },
st::proxyCheckingAnimation); st::proxyCheckingAnimation);
} }
_progress->start(); _progress->start();
@ -219,7 +219,7 @@ void ProxyRow::updateFields(View &&view) {
if (state == State::Checking) { if (state == State::Checking) {
if (!_checking) { if (!_checking) {
_checking = std::make_unique<Ui::InfiniteRadialAnimation>( _checking = std::make_unique<Ui::InfiniteRadialAnimation>(
animation(this, &ProxyRow::step_radial), [=] { radialAnimationCallback(); },
st::proxyCheckingAnimation); st::proxyCheckingAnimation);
_checking->start(); _checking->start();
} }
@ -241,8 +241,8 @@ void ProxyRow::updateFields(View &&view) {
update(); update();
} }
void ProxyRow::step_radial(crl::time ms, bool timer) { void ProxyRow::radialAnimationCallback() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(); update();
} }
} }
@ -323,28 +323,22 @@ void ProxyRow::paintEvent(QPaintEvent *e) {
auto statusLeft = left; auto statusLeft = left;
if (_checking) { if (_checking) {
_checking->step(ms); _checking->draw(
if (_checking) { p,
_checking->draw( {
p, st::proxyCheckingPosition.x() + statusLeft,
{ st::proxyCheckingPosition.y() + top
st::proxyCheckingPosition.x() + statusLeft, },
st::proxyCheckingPosition.y() + top width());
}, statusLeft += st::proxyCheckingPosition.x()
width()); + st::proxyCheckingAnimation.size.width()
statusLeft += st::proxyCheckingPosition.x() + st::proxyCheckingSkip;
+ st::proxyCheckingAnimation.size.width()
+ st::proxyCheckingSkip;
}
} }
p.drawTextLeft(statusLeft, top, width(), status); p.drawTextLeft(statusLeft, top, width(), status);
top += st::normalFont->height + st::proxyRowPadding.bottom(); top += st::normalFont->height + st::proxyRowPadding.bottom();
} }
void ProxyRow::paintCheck(Painter &p, crl::time ms) { void ProxyRow::paintCheck(Painter &p, crl::time ms) {
if (_progress) {
_progress->step(ms);
}
const auto loading = _progress const auto loading = _progress
? _progress->computeState() ? _progress->computeState()
: Ui::RadialState{ 0., 0, FullArcLength }; : Ui::RadialState{ 0., 0, FullArcLength };

View File

@ -139,7 +139,7 @@ protected:
private: private:
QString titleText(const Database::TaggedSummary &data) const; QString titleText(const Database::TaggedSummary &data) const;
QString sizeText(const Database::TaggedSummary &data) const; QString sizeText(const Database::TaggedSummary &data) const;
void step_radial(crl::time ms, bool timer); void radialAnimationCallback();
Fn<QString(size_type)> _titleFactory; Fn<QString(size_type)> _titleFactory;
object_ptr<Ui::FlatLabel> _title; object_ptr<Ui::FlatLabel> _title;
@ -186,7 +186,7 @@ void LocalStorageBox::Row::toggleProgress(bool shown) {
_clearing.destroy(); _clearing.destroy();
} else if (!_progress) { } else if (!_progress) {
_progress = std::make_unique<Ui::InfiniteRadialAnimation>( _progress = std::make_unique<Ui::InfiniteRadialAnimation>(
animation(this, &Row::step_radial), [=] { radialAnimationCallback(); },
st::proxyCheckingAnimation); st::proxyCheckingAnimation);
_progress->start(); _progress->start();
_clearing = object_ptr<Ui::FlatLabel>( _clearing = object_ptr<Ui::FlatLabel>(
@ -201,8 +201,8 @@ void LocalStorageBox::Row::toggleProgress(bool shown) {
} }
} }
void LocalStorageBox::Row::step_radial(crl::time ms, bool timer) { void LocalStorageBox::Row::radialAnimationCallback() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
RpWidget::update(); RpWidget::update();
} }
} }
@ -247,7 +247,6 @@ void LocalStorageBox::Row::paintEvent(QPaintEvent *e) {
const auto padding = st::localStorageRowPadding; const auto padding = st::localStorageRowPadding;
const auto height = st::localStorageRowHeight; const auto height = st::localStorageRowHeight;
const auto bottom = height - padding.bottom() - _description->height(); const auto bottom = height - padding.bottom() - _description->height();
_progress->step(crl::now());
_progress->draw( _progress->draw(
p, p,
{ {

View File

@ -44,8 +44,8 @@ int stickerPacksCount(bool includeArchivedOfficial) {
auto result = 0; auto result = 0;
auto &order = Auth().data().stickerSetsOrder(); auto &order = Auth().data().stickerSetsOrder();
auto &sets = Auth().data().stickerSets(); auto &sets = Auth().data().stickerSets();
for (auto i = 0, l = order.size(); i < l; ++i) { for (const auto setId : order) {
auto it = sets.constFind(order.at(i)); const auto it = sets.constFind(setId);
if (it != sets.cend()) { if (it != sets.cend()) {
if (!(it->flags & MTPDstickerSet::Flag::f_archived) || ((it->flags & MTPDstickerSet::Flag::f_official) && includeArchivedOfficial)) { if (!(it->flags & MTPDstickerSet::Flag::f_archived) || ((it->flags & MTPDstickerSet::Flag::f_official) && includeArchivedOfficial)) {
++result; ++result;
@ -653,7 +653,9 @@ StickersBox::Inner::Row::~Row() = default;
StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidget(parent) StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidget(parent)
, _section(section) , _section(section)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _a_shifting(animation(this, &Inner::step_shifting)) , _shiftingAnimation([=](crl::time now) {
return shiftingAnimationCallback(now);
})
, _itemsTop(st::membersMarginTop) , _itemsTop(st::membersMarginTop)
, _addText(lang(lng_stickers_featured_add).toUpper()) , _addText(lang(lng_stickers_featured_add).toUpper())
, _addWidth(st::stickersTrendingAdd.font->width(_addText)) , _addWidth(st::stickersTrendingAdd.font->width(_addText))
@ -665,7 +667,9 @@ StickersBox::Inner::Inner(QWidget *parent, StickersBox::Section section) : TWidg
StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> megagroup) : TWidget(parent) StickersBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> megagroup) : TWidget(parent)
, _section(StickersBox::Section::Installed) , _section(StickersBox::Section::Installed)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _a_shifting(animation(this, &Inner::step_shifting)) , _shiftingAnimation([=](crl::time now) {
return shiftingAnimationCallback(now);
})
, _itemsTop(st::membersMarginTop) , _itemsTop(st::membersMarginTop)
, _megagroupSet(megagroup) , _megagroupSet(megagroup)
, _megagroupSetInput(_megagroupSet->mgInfo->stickerSet) , _megagroupSetInput(_megagroupSet->mgInfo->stickerSet)
@ -710,10 +714,6 @@ void StickersBox::Inner::setInnerFocus() {
void StickersBox::Inner::paintEvent(QPaintEvent *e) { void StickersBox::Inner::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
if (_a_shifting.animating()) {
_a_shifting.step();
}
auto clip = e->rect(); auto clip = e->rect();
auto ms = crl::now(); auto ms = crl::now();
p.fillRect(clip, st::boxBg); p.fillRect(clip, st::boxBg);
@ -1071,7 +1071,7 @@ void StickersBox::Inner::onUpdateSelected() {
auto local = mapFromGlobal(_mouse); auto local = mapFromGlobal(_mouse);
if (_dragging >= 0) { if (_dragging >= 0) {
auto shift = 0; auto shift = 0;
auto ms = crl::now(); auto now = crl::now();
int firstSetIndex = 0; int firstSetIndex = 0;
if (_rows.at(firstSetIndex)->isRecentSet()) { if (_rows.at(firstSetIndex)->isRecentSet()) {
++firstSetIndex; ++firstSetIndex;
@ -1081,27 +1081,27 @@ void StickersBox::Inner::onUpdateSelected() {
for (int32 from = _dragging, to = _dragging + shift; from > to; --from) { for (int32 from = _dragging, to = _dragging + shift; from > to; --from) {
qSwap(_rows[from], _rows[from - 1]); qSwap(_rows[from], _rows[from - 1]);
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() - _rowHeight, 0); _rows[from]->yadd = anim::value(_rows[from]->yadd.current() - _rowHeight, 0);
_animStartTimes[from] = ms; _shiftingStartTimes[from] = now;
} }
} else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) { } else if (_dragStart.y() < local.y() && _dragging + 1 < _rows.size()) {
shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1); shift = floorclamp(local.y() - _dragStart.y() + (_rowHeight / 2), _rowHeight, 0, _rows.size() - _dragging - 1);
for (int32 from = _dragging, to = _dragging + shift; from < to; ++from) { for (int32 from = _dragging, to = _dragging + shift; from < to; ++from) {
qSwap(_rows[from], _rows[from + 1]); qSwap(_rows[from], _rows[from + 1]);
_rows[from]->yadd = anim::value(_rows[from]->yadd.current() + _rowHeight, 0); _rows[from]->yadd = anim::value(_rows[from]->yadd.current() + _rowHeight, 0);
_animStartTimes[from] = ms; _shiftingStartTimes[from] = now;
} }
} }
if (shift) { if (shift) {
_dragging += shift; _dragging += shift;
_above = _dragging; _above = _dragging;
_dragStart.setY(_dragStart.y() + shift * _rowHeight); _dragStart.setY(_dragStart.y() + shift * _rowHeight);
if (!_a_shifting.animating()) { if (!_shiftingAnimation.animating()) {
_a_shifting.start(); _shiftingAnimation.start();
} }
} }
_rows[_dragging]->yadd = anim::value(local.y() - _dragStart.y(), local.y() - _dragStart.y()); _rows[_dragging]->yadd = anim::value(local.y() - _dragStart.y(), local.y() - _dragStart.y());
_animStartTimes[_dragging] = 0; _shiftingStartTimes[_dragging] = 0;
_a_shifting.step(ms, true); shiftingAnimationCallback(now);
auto countDraggingScrollDelta = [this, local] { auto countDraggingScrollDelta = [this, local] {
if (local.y() < _visibleTop) { if (local.y() < _visibleTop) {
@ -1181,10 +1181,10 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
} else if (_dragging >= 0) { } else if (_dragging >= 0) {
QPoint local(mapFromGlobal(_mouse)); QPoint local(mapFromGlobal(_mouse));
_rows[_dragging]->yadd.start(0.); _rows[_dragging]->yadd.start(0.);
_aboveShadowFadeStart = _animStartTimes[_dragging] = crl::now(); _aboveShadowFadeStart = _shiftingStartTimes[_dragging] = crl::now();
_aboveShadowFadeOpacity = anim::value(aboveShadowOpacity(), 0); _aboveShadowFadeOpacity = anim::value(aboveShadowOpacity(), 0);
if (!_a_shifting.animating()) { if (!_shiftingAnimation.animating()) {
_a_shifting.start(); _shiftingAnimation.start();
} }
_dragging = _started = -1; _dragging = _started = -1;
@ -1262,64 +1262,64 @@ void StickersBox::Inner::leaveToChildEvent(QEvent *e, QWidget *child) {
onUpdateSelected(); onUpdateSelected();
} }
void StickersBox::Inner::step_shifting(crl::time ms, bool timer) { bool StickersBox::Inner::shiftingAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
ms += st::stickersRowDuration; now += st::stickersRowDuration;
} }
auto animating = false; auto animating = false;
auto updateMin = -1; auto updateMin = -1;
auto updateMax = 0; auto updateMax = 0;
for (auto i = 0, l = _animStartTimes.size(); i < l; ++i) { for (auto i = 0, count = int(_shiftingStartTimes.size()); i != count; ++i) {
auto start = _animStartTimes.at(i); const auto start = _shiftingStartTimes[i];
if (start) { if (start) {
if (updateMin < 0) updateMin = i; if (updateMin < 0) {
updateMin = i;
}
updateMax = i; updateMax = i;
if (start + st::stickersRowDuration > ms && ms >= start) { if (start + st::stickersRowDuration > now && now >= start) {
_rows[i]->yadd.update(float64(ms - start) / st::stickersRowDuration, anim::sineInOut); _rows[i]->yadd.update(float64(now - start) / st::stickersRowDuration, anim::sineInOut);
animating = true; animating = true;
} else { } else {
_rows[i]->yadd.finish(); _rows[i]->yadd.finish();
_animStartTimes[i] = 0; _shiftingStartTimes[i] = 0;
} }
} }
} }
if (_aboveShadowFadeStart) { if (_aboveShadowFadeStart) {
if (updateMin < 0 || updateMin > _above) updateMin = _above; if (updateMin < 0 || updateMin > _above) updateMin = _above;
if (updateMax < _above) updateMin = _above; if (updateMax < _above) updateMin = _above;
if (_aboveShadowFadeStart + st::stickersRowDuration > ms && ms > _aboveShadowFadeStart) { if (_aboveShadowFadeStart + st::stickersRowDuration > now && now > _aboveShadowFadeStart) {
_aboveShadowFadeOpacity.update(float64(ms - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut); _aboveShadowFadeOpacity.update(float64(now - _aboveShadowFadeStart) / st::stickersRowDuration, anim::sineInOut);
animating = true; animating = true;
} else { } else {
_aboveShadowFadeOpacity.finish(); _aboveShadowFadeOpacity.finish();
_aboveShadowFadeStart = 0; _aboveShadowFadeStart = 0;
} }
} }
if (timer) { if (_dragging >= 0) {
if (_dragging >= 0) { if (updateMin < 0 || updateMin > _dragging) {
if (updateMin < 0 || updateMin > _dragging) { updateMin = _dragging;
updateMin = _dragging;
}
if (updateMax < _dragging) updateMax = _dragging;
}
if (updateMin == 1 && _rows[0]->isRecentSet()) {
updateMin = 0; // Repaint from the very top of the content.
}
if (updateMin >= 0) {
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
} }
if (updateMax < _dragging) updateMax = _dragging;
}
if (updateMin == 1 && _rows[0]->isRecentSet()) {
updateMin = 0; // Repaint from the very top of the content.
}
if (updateMin >= 0) {
update(0, _itemsTop + _rowHeight * (updateMin - 1), width(), _rowHeight * (updateMax - updateMin + 3));
} }
if (!animating) { if (!animating) {
_above = _dragging; _above = _dragging;
_a_shifting.stop();
} }
return animating;
} }
void StickersBox::Inner::clear() { void StickersBox::Inner::clear() {
_rows.clear(); _rows.clear();
_animStartTimes.clear(); _shiftingStartTimes.clear();
_aboveShadowFadeStart = 0; _aboveShadowFadeStart = 0;
_aboveShadowFadeOpacity = anim::value(); _aboveShadowFadeOpacity = anim::value();
_a_shifting.stop(); _shiftingAnimation.stop();
_above = _dragging = _started = -1; _above = _dragging = _started = -1;
setSelected(SelectedRow()); setSelected(SelectedRow());
setPressed(SelectedRow()); setPressed(SelectedRow());
@ -1476,7 +1476,7 @@ void StickersBox::Inner::rebuild() {
return Auth().data().archivedStickerSetsOrder(); return Auth().data().archivedStickerSetsOrder();
})(); })();
_rows.reserve(order.size() + 1); _rows.reserve(order.size() + 1);
_animStartTimes.reserve(order.size() + 1); _shiftingStartTimes.reserve(order.size() + 1);
auto &sets = Auth().data().stickerSets(); auto &sets = Auth().data().stickerSets();
if (_megagroupSet) { if (_megagroupSet) {
@ -1625,7 +1625,7 @@ void StickersBox::Inner::rebuildAppendSet(const Stickers::Set &set, int maxNameW
removed, removed,
pixw, pixw,
pixh)); pixh));
_animStartTimes.push_back(0); _shiftingStartTimes.push_back(0);
} }
void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbnail, DocumentData **outSticker, int *outWidth, int *outHeight) const { void StickersBox::Inner::fillSetCover(const Stickers::Set &set, ImagePtr *thumbnail, DocumentData **outSticker, int *outWidth, int *outHeight) const {

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer.h" #include "base/timer.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "ui/effects/animations.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
class ConfirmBox; class ConfirmBox;
@ -270,7 +271,7 @@ private:
QRect relativeButtonRect(bool removeButton) const; QRect relativeButtonRect(bool removeButton) const;
void ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton); void ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton);
void step_shifting(crl::time ms, bool timer); bool shiftingAnimationCallback(crl::time now);
void paintRow(Painter &p, Row *set, int index, crl::time ms); void paintRow(Painter &p, Row *set, int index, crl::time ms);
void paintFakeButton(Painter &p, Row *set, int index, crl::time ms); void paintFakeButton(Painter &p, Row *set, int index, crl::time ms);
void clear(); void clear();
@ -297,10 +298,10 @@ private:
int32 _rowHeight; int32 _rowHeight;
std::vector<std::unique_ptr<Row>> _rows; std::vector<std::unique_ptr<Row>> _rows;
QList<crl::time> _animStartTimes; std::vector<crl::time> _shiftingStartTimes;
crl::time _aboveShadowFadeStart = 0; crl::time _aboveShadowFadeStart = 0;
anim::value _aboveShadowFadeOpacity; anim::value _aboveShadowFadeOpacity;
BasicAnimation _a_shifting; Ui::Animations::Basic _shiftingAnimation;
Fn<void(uint64 setId)> _installSetCallback; Fn<void(uint64 setId)> _installSetCallback;
Fn<void()> _loadMoreCallback; Fn<void()> _loadMoreCallback;

View File

@ -124,7 +124,7 @@ private:
void setupHandler(); void setupHandler();
void load(); void load();
void step_radial(crl::time ms, bool timer); void radialAnimationCallback();
int _id = 0; int _id = 0;
bool _switching = false; bool _switching = false;
@ -582,8 +582,8 @@ void Row::setupPreview(const Set &set) {
} }
} }
void Row::step_radial(crl::time ms, bool timer) { void Row::radialAnimationCallback() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(); update();
} }
} }
@ -633,7 +633,7 @@ void Row::updateAnimation(crl::time ms) {
: 0.; : 0.;
if (!_loading) { if (!_loading) {
_loading = std::make_unique<Ui::RadialAnimation>( _loading = std::make_unique<Ui::RadialAnimation>(
animation(this, &Row::step_radial)); [=] { radialAnimationCallback(); });
_loading->start(progress); _loading->start(progress);
} else { } else {
_loading->update(progress, false, crl::now()); _loading->update(progress, false, crl::now());

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/effects/animations.h"
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "boxes/stickers_box.h" #include "boxes/stickers_box.h"
@ -105,7 +106,7 @@ private:
template <typename Callback> template <typename Callback>
void enumerateVisibleIcons(Callback callback); void enumerateVisibleIcons(Callback callback);
void step_icons(crl::time ms, bool timer); bool iconsAnimationCallback(crl::time now);
void setSelectedIcon( void setSelectedIcon(
int newSelected, int newSelected,
ValidateIconAnimations animations); ValidateIconAnimations animations);
@ -134,7 +135,7 @@ private:
int _iconSel = 0; int _iconSel = 0;
OverState _iconDown = SpecialOver::None; OverState _iconDown = SpecialOver::None;
bool _iconsDragging = false; bool _iconsDragging = false;
BasicAnimation _a_icons; Ui::Animations::Basic _iconsAnimation;
QPoint _iconsMousePos, _iconsMouseDown; QPoint _iconsMousePos, _iconsMouseDown;
int _iconsLeft = 0; int _iconsLeft = 0;
int _iconsRight = 0; int _iconsRight = 0;
@ -180,7 +181,9 @@ StickersListWidget::Set::~Set() = default;
StickersListWidget::Footer::Footer(not_null<StickersListWidget*> parent) : InnerFooter(parent) StickersListWidget::Footer::Footer(not_null<StickersListWidget*> parent) : InnerFooter(parent)
, _pan(parent) , _pan(parent)
, _a_icons(animation(this, &Footer::step_icons)) { , _iconsAnimation([=](crl::time now) {
return iconsAnimationCallback(now);
}) {
setMouseTracking(true); setMouseTracking(true);
_iconsLeft = _iconsRight = st::emojiCategorySkip + st::stickerIconWidth; _iconsLeft = _iconsRight = st::emojiCategorySkip + st::stickerIconWidth;
@ -323,11 +326,11 @@ void StickersListWidget::Footer::setSelectedIcon(
_iconsMax); _iconsMax);
if (animations == ValidateIconAnimations::None) { if (animations == ValidateIconAnimations::None) {
_iconsX = anim::value(iconsXFinal, iconsXFinal); _iconsX = anim::value(iconsXFinal, iconsXFinal);
_a_icons.stop(); _iconsAnimation.stop();
} else { } else {
_iconsX.start(iconsXFinal); _iconsX.start(iconsXFinal);
_iconsStartAnim = crl::now(); _iconsStartAnim = crl::now();
_a_icons.start(); _iconsAnimation.start();
} }
updateSelected(); updateSelected();
update(); update();
@ -336,7 +339,7 @@ void StickersListWidget::Footer::setSelectedIcon(
void StickersListWidget::Footer::processHideFinished() { void StickersListWidget::Footer::processHideFinished() {
_iconOver = _iconDown = SpecialOver::None; _iconOver = _iconDown = SpecialOver::None;
_iconsStartAnim = 0; _iconsStartAnim = 0;
_a_icons.stop(); _iconsAnimation.stop();
_iconsX.finish(); _iconsX.finish();
_iconSelX.finish(); _iconSelX.finish();
_horizontal = false; _horizontal = false;
@ -469,7 +472,7 @@ void StickersListWidget::Footer::mouseMoveEvent(QMouseEvent *e) {
if (newX != qRound(_iconsX.current())) { if (newX != qRound(_iconsX.current())) {
_iconsX = anim::value(newX, newX); _iconsX = anim::value(newX, newX);
_iconsStartAnim = 0; _iconsStartAnim = 0;
_a_icons.stop(); _iconsAnimation.stop();
update(); update();
} }
} }
@ -504,7 +507,7 @@ void StickersListWidget::Footer::finishDragging() {
if (newX != qRound(_iconsX.current())) { if (newX != qRound(_iconsX.current())) {
_iconsX = anim::value(newX, newX); _iconsX = anim::value(newX, newX);
_iconsStartAnim = 0; _iconsStartAnim = 0;
_a_icons.stop(); _iconsAnimation.stop();
update(); update();
} }
_iconsDragging = false; _iconsDragging = false;
@ -539,7 +542,7 @@ void StickersListWidget::Footer::scrollByWheelEvent(
if (newX != qRound(_iconsX.current())) { if (newX != qRound(_iconsX.current())) {
_iconsX = anim::value(newX, newX); _iconsX = anim::value(newX, newX);
_iconsStartAnim = 0; _iconsStartAnim = 0;
_a_icons.stop(); _iconsAnimation.stop();
updateSelected(); updateSelected();
update(); update();
} }
@ -601,7 +604,7 @@ void StickersListWidget::Footer::refreshIconsGeometry(
_iconsX.finish(); _iconsX.finish();
_iconSelX.finish(); _iconSelX.finish();
_iconsStartAnim = 0; _iconsStartAnim = 0;
_a_icons.stop(); _iconsAnimation.stop();
_iconsMax = std::max( _iconsMax = std::max(
_iconsLeft + int(_icons.size()) * st::stickerIconWidth + _iconsRight - width(), _iconsLeft + int(_icons.size()) * st::stickerIconWidth + _iconsRight - width(),
0); 0);
@ -673,13 +676,13 @@ void StickersListWidget::Footer::paintSetIcon(
} }
} }
void StickersListWidget::Footer::step_icons(crl::time ms, bool timer) { bool StickersListWidget::Footer::iconsAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
ms += st::stickerIconMove; now += st::stickerIconMove;
} }
if (_iconsStartAnim) { if (_iconsStartAnim) {
auto dt = (ms - _iconsStartAnim) / float64(st::stickerIconMove); const auto dt = (now - _iconsStartAnim) / float64(st::stickerIconMove);
if (dt >= 1) { if (dt >= 1.) {
_iconsStartAnim = 0; _iconsStartAnim = 0;
_iconsX.finish(); _iconsX.finish();
_iconSelX.finish(); _iconSelX.finish();
@ -689,11 +692,9 @@ void StickersListWidget::Footer::step_icons(crl::time ms, bool timer) {
} }
} }
if (timer) update(); update();
if (!_iconsStartAnim) { return (_iconsStartAnim != 0);
_a_icons.stop();
}
} }
StickersListWidget::StickersListWidget(QWidget *parent, not_null<Window::Controller*> controller) : Inner(parent, controller) StickersListWidget::StickersListWidget(QWidget *parent, not_null<Window::Controller*> controller) : Inner(parent, controller)

View File

@ -46,7 +46,6 @@ enum {
MediaOverviewStartPerPage = 5, MediaOverviewStartPerPage = 5,
AudioVoiceMsgMaxLength = 100 * 60, // 100 minutes AudioVoiceMsgMaxLength = 100 * 60, // 100 minutes
AudioVoiceMsgUpdateView = 100, // 100ms
AudioVoiceMsgChannels = 2, // stereo AudioVoiceMsgChannels = 2, // stereo
StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker StickerMaxSize = 2048, // 2048x2048 is a max image size for sticker

View File

@ -71,7 +71,9 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
, _dialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date)) , _dialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date))
, _contactsNoDialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , _contactsNoDialogs(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, _contacts(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name)) , _contacts(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, _a_pinnedShifting(animation(this, &DialogsInner::step_pinnedShifting)) , _pinnedShiftAnimation([=](crl::time now) {
return pinnedShiftAnimationCallback(now);
})
, _addContactLnk(this, lang(lng_add_contact_button)) , _addContactLnk(this, lang(lng_add_contact_button))
, _cancelSearchInChat(this, st::dialogsCancelSearchInPeer) , _cancelSearchInChat(this, st::dialogsCancelSearchInPeer)
, _cancelSearchFromUser(this, st::dialogsCancelSearchInPeer) { , _cancelSearchFromUser(this, st::dialogsCancelSearchInPeer) {
@ -255,10 +257,6 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
auto fullWidth = getFullWidth(); auto fullWidth = getFullWidth();
auto ms = crl::now(); auto ms = crl::now();
if (_state == State::Default) { if (_state == State::Default) {
if (_a_pinnedShifting.animating()) {
_a_pinnedShifting.step(ms, false);
}
auto rows = shownDialogs(); auto rows = shownDialogs();
auto dialogsClip = r; auto dialogsClip = r;
if (_dialogsImportant) { if (_dialogsImportant) {
@ -855,7 +853,7 @@ void DialogsInner::mousePressEvent(QMouseEvent *e) {
} else if (_pressed) { } else if (_pressed) {
auto row = _pressed; auto row = _pressed;
row->addRipple(e->pos() - QPoint(0, dialogsOffset() + _pressed->pos() * st::dialogsRowHeight), QSize(getFullWidth(), st::dialogsRowHeight), [this, row] { row->addRipple(e->pos() - QPoint(0, dialogsOffset() + _pressed->pos() * st::dialogsRowHeight), QSize(getFullWidth(), st::dialogsRowHeight), [this, row] {
if (!_a_pinnedShifting.animating()) { if (!_pinnedShiftAnimation.animating()) {
row->entry()->updateChatListEntry(); row->entry()->updateChatListEntry();
} }
}); });
@ -901,7 +899,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) {
_pinnedOrder = Auth().data().pinnedDialogsOrder(); _pinnedOrder = Auth().data().pinnedDialogsOrder();
_pinnedRows[_draggingIndex].yadd = anim::value(0, localPosition.y() - _dragStart.y()); _pinnedRows[_draggingIndex].yadd = anim::value(0, localPosition.y() - _dragStart.y());
_pinnedRows[_draggingIndex].animStartTime = crl::now(); _pinnedRows[_draggingIndex].animStartTime = crl::now();
_a_pinnedShifting.start(); _pinnedShiftAnimation.start();
} }
} }
} }
@ -959,7 +957,7 @@ void DialogsInner::finishReorderPinned() {
} }
_draggingIndex = -1; _draggingIndex = -1;
if (!_a_pinnedShifting.animating()) { if (!_pinnedShiftAnimation.animating()) {
_pinnedRows.clear(); _pinnedRows.clear();
_aboveIndex = -1; _aboveIndex = -1;
} }
@ -969,7 +967,7 @@ void DialogsInner::finishReorderPinned() {
} }
void DialogsInner::stopReorderPinned() { void DialogsInner::stopReorderPinned() {
_a_pinnedShifting.stop(); _pinnedShiftAnimation.stop();
finishReorderPinned(); finishReorderPinned();
} }
@ -990,7 +988,7 @@ int DialogsInner::updateReorderIndexGetCount() {
_draggingIndex = index; _draggingIndex = index;
_aboveIndex = _draggingIndex; _aboveIndex = _draggingIndex;
while (count > _pinnedRows.size()) { while (count > _pinnedRows.size()) {
_pinnedRows.push_back(PinnedRow()); _pinnedRows.emplace_back();
} }
while (count < _pinnedRows.size()) { while (count < _pinnedRows.size()) {
_pinnedRows.pop_back(); _pinnedRows.pop_back();
@ -1007,7 +1005,7 @@ bool DialogsInner::updateReorderPinned(QPoint localPosition) {
auto yaddWas = _pinnedRows[_draggingIndex].yadd.current(); auto yaddWas = _pinnedRows[_draggingIndex].yadd.current();
auto shift = 0; auto shift = 0;
auto ms = crl::now(); auto now = crl::now();
auto rowHeight = st::dialogsRowHeight; auto rowHeight = st::dialogsRowHeight;
if (_dragStart.y() > localPosition.y() && _draggingIndex > 0) { if (_dragStart.y() > localPosition.y() && _draggingIndex > 0) {
shift = -floorclamp(_dragStart.y() - localPosition.y() + (rowHeight / 2), rowHeight, 0, _draggingIndex); shift = -floorclamp(_dragStart.y() - localPosition.y() + (rowHeight / 2), rowHeight, 0, _draggingIndex);
@ -1016,7 +1014,7 @@ bool DialogsInner::updateReorderPinned(QPoint localPosition) {
shownDialogs()->movePinned(_dragging, -1); shownDialogs()->movePinned(_dragging, -1);
std::swap(_pinnedRows[from], _pinnedRows[from - 1]); std::swap(_pinnedRows[from], _pinnedRows[from - 1]);
_pinnedRows[from].yadd = anim::value(_pinnedRows[from].yadd.current() - rowHeight, 0); _pinnedRows[from].yadd = anim::value(_pinnedRows[from].yadd.current() - rowHeight, 0);
_pinnedRows[from].animStartTime = ms; _pinnedRows[from].animStartTime = now;
} }
} else if (_dragStart.y() < localPosition.y() && _draggingIndex + 1 < pinnedCount) { } else if (_dragStart.y() < localPosition.y() && _draggingIndex + 1 < pinnedCount) {
shift = floorclamp(localPosition.y() - _dragStart.y() + (rowHeight / 2), rowHeight, 0, pinnedCount - _draggingIndex - 1); shift = floorclamp(localPosition.y() - _dragStart.y() + (rowHeight / 2), rowHeight, 0, pinnedCount - _draggingIndex - 1);
@ -1025,15 +1023,15 @@ bool DialogsInner::updateReorderPinned(QPoint localPosition) {
shownDialogs()->movePinned(_dragging, 1); shownDialogs()->movePinned(_dragging, 1);
std::swap(_pinnedRows[from], _pinnedRows[from + 1]); std::swap(_pinnedRows[from], _pinnedRows[from + 1]);
_pinnedRows[from].yadd = anim::value(_pinnedRows[from].yadd.current() + rowHeight, 0); _pinnedRows[from].yadd = anim::value(_pinnedRows[from].yadd.current() + rowHeight, 0);
_pinnedRows[from].animStartTime = ms; _pinnedRows[from].animStartTime = now;
} }
} }
if (shift) { if (shift) {
_draggingIndex += shift; _draggingIndex += shift;
_aboveIndex = _draggingIndex; _aboveIndex = _draggingIndex;
_dragStart.setY(_dragStart.y() + shift * rowHeight); _dragStart.setY(_dragStart.y() + shift * rowHeight);
if (!_a_pinnedShifting.animating()) { if (!_pinnedShiftAnimation.animating()) {
_a_pinnedShifting.start(); _pinnedShiftAnimation.start();
} }
} }
_aboveTopShift = qCeil(_pinnedRows[_aboveIndex].yadd.current()); _aboveTopShift = qCeil(_pinnedRows[_aboveIndex].yadd.current());
@ -1041,22 +1039,22 @@ bool DialogsInner::updateReorderPinned(QPoint localPosition) {
if (!_pinnedRows[_draggingIndex].animStartTime) { if (!_pinnedRows[_draggingIndex].animStartTime) {
_pinnedRows[_draggingIndex].yadd.finish(); _pinnedRows[_draggingIndex].yadd.finish();
} }
_a_pinnedShifting.step(ms, true); pinnedShiftAnimationCallback(now);
auto countDraggingScrollDelta = [this, localPosition] { const auto delta = [&] {
if (localPosition.y() < _visibleTop) { if (localPosition.y() < _visibleTop) {
return localPosition.y() - _visibleTop; return localPosition.y() - _visibleTop;
} }
return 0; return 0;
}; }();
emit draggingScrollDelta(countDraggingScrollDelta()); emit draggingScrollDelta(delta);
return true; return true;
} }
void DialogsInner::step_pinnedShifting(crl::time ms, bool timer) { bool DialogsInner::pinnedShiftAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
ms += st::stickersRowDuration; now += st::stickersRowDuration;
} }
auto wasAnimating = false; auto wasAnimating = false;
@ -1069,8 +1067,8 @@ void DialogsInner::step_pinnedShifting(crl::time ms, bool timer) {
wasAnimating = true; wasAnimating = true;
if (updateMin < 0) updateMin = i; if (updateMin < 0) updateMin = i;
updateMax = i; updateMax = i;
if (start + st::stickersRowDuration > ms && ms >= start) { if (start + st::stickersRowDuration > now && now >= start) {
_pinnedRows[i].yadd.update(float64(ms - start) / st::stickersRowDuration, anim::sineInOut); _pinnedRows[i].yadd.update(float64(now - start) / st::stickersRowDuration, anim::sineInOut);
animating = true; animating = true;
} else { } else {
_pinnedRows[i].yadd.finish(); _pinnedRows[i].yadd.finish();
@ -1078,33 +1076,31 @@ void DialogsInner::step_pinnedShifting(crl::time ms, bool timer) {
} }
} }
} }
if (timer || (wasAnimating && !animating)) { updateReorderIndexGetCount();
updateReorderIndexGetCount(); if (_draggingIndex >= 0) {
if (_draggingIndex >= 0) { if (updateMin < 0 || updateMin > _draggingIndex) {
if (updateMin < 0 || updateMin > _draggingIndex) { updateMin = _draggingIndex;
updateMin = _draggingIndex;
}
if (updateMax < _draggingIndex) updateMax = _draggingIndex;
} }
if (updateMin >= 0) { if (updateMax < _draggingIndex) updateMax = _draggingIndex;
auto top = pinnedOffset(); }
auto updateFrom = top + st::dialogsRowHeight * (updateMin - 1); if (updateMin >= 0) {
auto updateHeight = st::dialogsRowHeight * (updateMax - updateMin + 3); auto top = pinnedOffset();
if (base::in_range(_aboveIndex, 0, _pinnedRows.size())) { auto updateFrom = top + st::dialogsRowHeight * (updateMin - 1);
// Always include currently dragged chat in its current and old positions. auto updateHeight = st::dialogsRowHeight * (updateMax - updateMin + 3);
auto aboveRowBottom = top + (_aboveIndex + 1) * st::dialogsRowHeight; if (base::in_range(_aboveIndex, 0, _pinnedRows.size())) {
auto aboveTopShift = qCeil(_pinnedRows[_aboveIndex].yadd.current()); // Always include currently dragged chat in its current and old positions.
accumulate_max(updateHeight, (aboveRowBottom - updateFrom) + _aboveTopShift); auto aboveRowBottom = top + (_aboveIndex + 1) * st::dialogsRowHeight;
accumulate_max(updateHeight, (aboveRowBottom - updateFrom) + aboveTopShift); auto aboveTopShift = qCeil(_pinnedRows[_aboveIndex].yadd.current());
_aboveTopShift = aboveTopShift; accumulate_max(updateHeight, (aboveRowBottom - updateFrom) + _aboveTopShift);
} accumulate_max(updateHeight, (aboveRowBottom - updateFrom) + aboveTopShift);
update(0, updateFrom, getFullWidth(), updateHeight); _aboveTopShift = aboveTopShift;
} }
update(0, updateFrom, getFullWidth(), updateHeight);
} }
if (!animating) { if (!animating) {
_aboveIndex = _draggingIndex; _aboveIndex = _draggingIndex;
_a_pinnedShifting.stop();
} }
return animating;
} }
void DialogsInner::mouseReleaseEvent(QMouseEvent *e) { void DialogsInner::mouseReleaseEvent(QMouseEvent *e) {
@ -1120,8 +1116,8 @@ void DialogsInner::mousePressReleased(
if (_draggingIndex >= 0) { if (_draggingIndex >= 0) {
_pinnedRows[_draggingIndex].yadd.start(0.); _pinnedRows[_draggingIndex].yadd.start(0.);
_pinnedRows[_draggingIndex].animStartTime = crl::now(); _pinnedRows[_draggingIndex].animStartTime = crl::now();
if (!_a_pinnedShifting.animating()) { if (!_pinnedShiftAnimation.animating()) {
_a_pinnedShifting.start(); _pinnedShiftAnimation.start();
} }
} }
finishReorderPinned(); finishReorderPinned();

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "dialogs/dialogs_widget.h" #include "dialogs/dialogs_widget.h"
#include "dialogs/dialogs_key.h" #include "dialogs/dialogs_key.h"
#include "data/data_messages.h" #include "data/data_messages.h"
#include "ui/effects/animations.h"
#include "base/flags.h" #include "base/flags.h"
namespace Dialogs { namespace Dialogs {
@ -283,7 +284,7 @@ private:
void stopReorderPinned(); void stopReorderPinned();
int countPinnedIndex(Dialogs::Row *ofRow); int countPinnedIndex(Dialogs::Row *ofRow);
void savePinnedOrder(); void savePinnedOrder();
void step_pinnedShifting(crl::time ms, bool timer); bool pinnedShiftAnimationCallback(crl::time now);
void handleChatMigration(not_null<ChatData*> chat); void handleChatMigration(not_null<ChatData*> chat);
not_null<Window::Controller*> _controller; not_null<Window::Controller*> _controller;
@ -313,7 +314,7 @@ private:
crl::time animStartTime = 0; crl::time animStartTime = 0;
}; };
std::vector<PinnedRow> _pinnedRows; std::vector<PinnedRow> _pinnedRows;
BasicAnimation _a_pinnedShifting; Ui::Animations::Basic _pinnedShiftAnimation;
std::deque<Dialogs::Key> _pinnedOrder; std::deque<Dialogs::Key> _pinnedOrder;
// Remember the last currently dragged row top shift for updating area. // Remember the last currently dragged row top shift for updating area.

View File

@ -66,7 +66,7 @@ protected:
void onStateChanged(State was, StateChangeSource source) override; void onStateChanged(State was, StateChangeSource source) override;
private: private:
void step_radial(crl::time ms, bool timer); void radialAnimationCallback();
QString _text; QString _text;
const style::FlatButton &_st; const style::FlatButton &_st;
@ -95,8 +95,8 @@ void DialogsWidget::BottomButton::setText(const QString &text) {
update(); update();
} }
void DialogsWidget::BottomButton::step_radial(crl::time ms, bool timer) { void DialogsWidget::BottomButton::radialAnimationCallback() {
if (timer && !anim::Disabled() && width() < st::columnMinimalWidthLeft) { if (!anim::Disabled() && width() < st::columnMinimalWidthLeft) {
update(); update();
} }
} }
@ -106,7 +106,7 @@ void DialogsWidget::BottomButton::onStateChanged(State was, StateChangeSource so
if ((was & StateFlag::Disabled) != (state() & StateFlag::Disabled)) { if ((was & StateFlag::Disabled) != (state() & StateFlag::Disabled)) {
_loading = isDisabled() _loading = isDisabled()
? std::make_unique<Ui::InfiniteRadialAnimation>( ? std::make_unique<Ui::InfiniteRadialAnimation>(
animation(this, &BottomButton::step_radial), [=] { radialAnimationCallback(); },
st::dialogsLoadMoreLoading) st::dialogsLoadMoreLoading)
: nullptr; : nullptr;
if (_loading) { if (_loading) {

View File

@ -396,7 +396,9 @@ ReplyKeyboard::ReplyKeyboard(
not_null<const HistoryItem*> item, not_null<const HistoryItem*> item,
std::unique_ptr<Style> &&s) std::unique_ptr<Style> &&s)
: _item(item) : _item(item)
, _a_selected(animation(this, &ReplyKeyboard::step_selected)) , _selectedAnimation([=](crl::time now) {
return selectedAnimationCallback(now);
})
, _st(std::move(s)) { , _st(std::move(s)) {
if (const auto markup = _item->Get<HistoryMessageReplyMarkup>()) { if (const auto markup = _item->Get<HistoryMessageReplyMarkup>()) {
const auto context = _item->fullId(); const auto context = _item->fullId();
@ -640,20 +642,20 @@ void ReplyKeyboard::startAnimation(int i, int j, int direction) {
_animations.emplace(indexForAnimation, crl::now()); _animations.emplace(indexForAnimation, crl::now());
} }
if (notStarted && !_a_selected.animating()) { if (notStarted && !_selectedAnimation.animating()) {
_a_selected.start(); _selectedAnimation.start();
} }
} }
void ReplyKeyboard::step_selected(crl::time ms, bool timer) { bool ReplyKeyboard::selectedAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
ms += st::botKbDuration; now += st::botKbDuration;
} }
for (auto i = _animations.begin(); i != _animations.end();) { for (auto i = _animations.begin(); i != _animations.end();) {
const auto index = std::abs(i->first) - 1; const auto index = std::abs(i->first) - 1;
const auto row = (index / MatrixRowShift); const auto row = (index / MatrixRowShift);
const auto col = index % MatrixRowShift; const auto col = index % MatrixRowShift;
const auto dt = float64(ms - i->second) / st::botKbDuration; const auto dt = float64(now - i->second) / st::botKbDuration;
if (dt >= 1) { if (dt >= 1) {
_rows[row][col].howMuchOver = (i->first > 0) ? 1 : 0; _rows[row][col].howMuchOver = (i->first > 0) ? 1 : 0;
i = _animations.erase(i); i = _animations.erase(i);
@ -662,10 +664,8 @@ void ReplyKeyboard::step_selected(crl::time ms, bool timer) {
++i; ++i;
} }
} }
if (timer) _st->repaint(_item); _st->repaint(_item);
if (_animations.empty()) { return !_animations.empty();
_a_selected.stop();
}
} }
void ReplyKeyboard::clearSelection() { void ReplyKeyboard::clearSelection() {
@ -676,7 +676,7 @@ void ReplyKeyboard::clearSelection() {
_rows[row][col].howMuchOver = 0; _rows[row][col].howMuchOver = 0;
} }
_animations.clear(); _animations.clear();
_a_selected.stop(); _selectedAnimation.stop();
} }
int ReplyKeyboard::Style::buttonSkip() const { int ReplyKeyboard::Style::buttonSkip() const {
@ -857,19 +857,24 @@ HistoryDocumentCaptioned::HistoryDocumentCaptioned()
: _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) { : _caption(st::msgFileMinWidth - st::msgPadding.left() - st::msgPadding.right()) {
} }
HistoryDocumentVoicePlayback::HistoryDocumentVoicePlayback(const HistoryDocument *that) HistoryDocumentVoicePlayback::HistoryDocumentVoicePlayback(
: a_progress(0., 0.) const HistoryDocument *that)
, _a_progress(animation(const_cast<HistoryDocument*>(that), &HistoryDocument::step_voiceProgress)) { : progress(0., 0.)
, progressAnimation([=](crl::time now) {
const auto nonconst = const_cast<HistoryDocument*>(that);
return nonconst->voiceProgressAnimationCallback(now);
}) {
} }
void HistoryDocumentVoice::ensurePlayback(const HistoryDocument *that) const { void HistoryDocumentVoice::ensurePlayback(
const HistoryDocument *that) const {
if (!_playback) { if (!_playback) {
_playback = std::make_unique<HistoryDocumentVoicePlayback>(that); _playback = std::make_unique<HistoryDocumentVoicePlayback>(that);
} }
} }
void HistoryDocumentVoice::checkPlaybackFinished() const { void HistoryDocumentVoice::checkPlaybackFinished() const {
if (_playback && !_playback->_a_progress.animating()) { if (_playback && !_playback->progressAnimation.animating()) {
_playback.reset(); _playback.reset();
} }
} }

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h" #include "history/history_item.h"
#include "ui/empty_userpic.h" #include "ui/empty_userpic.h"
#include "ui/effects/animations.h"
class HistoryDocument; class HistoryDocument;
struct WebPageData; struct WebPageData;
@ -329,7 +330,7 @@ private:
ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p); ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p);
void step_selected(crl::time ms, bool timer); bool selectedAnimationCallback(crl::time now);
const not_null<const HistoryItem*> _item; const not_null<const HistoryItem*> _item;
int _width = 0; int _width = 0;
@ -337,7 +338,7 @@ private:
std::vector<std::vector<Button>> _rows; std::vector<std::vector<Button>> _rows;
base::flat_map<int, crl::time> _animations; base::flat_map<int, crl::time> _animations;
BasicAnimation _a_selected; Ui::Animations::Basic _selectedAnimation;
std::unique_ptr<Style> _st; std::unique_ptr<Style> _st;
ClickHandlerPtr _savedPressed; ClickHandlerPtr _savedPressed;
@ -383,9 +384,9 @@ struct HistoryDocumentNamed : public RuntimeComponent<HistoryDocumentNamed, Hist
struct HistoryDocumentVoicePlayback { struct HistoryDocumentVoicePlayback {
HistoryDocumentVoicePlayback(const HistoryDocument *that); HistoryDocumentVoicePlayback(const HistoryDocument *that);
int32 _position = 0; int32 position = 0;
anim::value a_progress; anim::value progress;
BasicAnimation _a_progress; Ui::Animations::Basic progressAnimation;
}; };
class HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice, HistoryDocument> { class HistoryDocumentVoice : public RuntimeComponent<HistoryDocumentVoice, HistoryDocument> {

View File

@ -105,6 +105,7 @@ constexpr auto kCancelTypingActionTimeout = crl::time(5000);
constexpr auto kSaveDraftTimeout = 1000; constexpr auto kSaveDraftTimeout = 1000;
constexpr auto kSaveDraftAnywayTimeout = 5000; constexpr auto kSaveDraftAnywayTimeout = 5000;
constexpr auto kSaveCloudDraftIdleTimeout = 14000; constexpr auto kSaveCloudDraftIdleTimeout = 14000;
constexpr auto kRecordingUpdateDelta = crl::time(100);
ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() { ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() {
return [](ChannelData *channel, MsgId msgId) { return [](ChannelData *channel, MsgId msgId) {
@ -189,7 +190,10 @@ HistoryWidget::HistoryWidget(
, _send(this) , _send(this)
, _unblock(this, lang(lng_unblock_button).toUpper(), st::historyUnblock) , _unblock(this, lang(lng_unblock_button).toUpper(), st::historyUnblock)
, _botStart(this, lang(lng_bot_start).toUpper(), st::historyComposeButton) , _botStart(this, lang(lng_bot_start).toUpper(), st::historyComposeButton)
, _joinChannel(this, lang(lng_profile_join_channel).toUpper(), st::historyComposeButton) , _joinChannel(
this,
lang(lng_profile_join_channel).toUpper(),
st::historyComposeButton)
, _muteUnmute(this, lang(lng_channel_mute).toUpper(), st::historyComposeButton) , _muteUnmute(this, lang(lng_channel_mute).toUpper(), st::historyComposeButton)
, _attachToggle(this, st::historyAttach) , _attachToggle(this, st::historyAttach)
, _tabbedSelectorToggle(this, st::historyAttachEmoji) , _tabbedSelectorToggle(this, st::historyAttachEmoji)
@ -202,7 +206,9 @@ HistoryWidget::HistoryWidget(
Ui::InputField::Mode::MultiLine, Ui::InputField::Mode::MultiLine,
langFactory(lng_message_ph)) langFactory(lng_message_ph))
, _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel))) , _recordCancelWidth(st::historyRecordFont->width(lang(lng_record_cancel)))
, _a_recording(animation(this, &HistoryWidget::step_recording)) , _recordingAnimation([=](crl::time now) {
return recordingAnimationCallback(now);
})
, _kbScroll(this, st::botKbScroll) , _kbScroll(this, st::botKbScroll)
, _tabbedPanel(this, controller) , _tabbedPanel(this, controller)
, _tabbedSelector(_tabbedPanel->getSelector()) , _tabbedSelector(_tabbedPanel->getSelector())
@ -1235,8 +1241,8 @@ void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
return; return;
} }
a_recordingLevel.start(level); _recordingLevel.start(level);
_a_recording.start(); _recordingAnimation.start();
_recordingSamples = samples; _recordingSamples = samples;
if (samples < 0 || samples >= Media::Player::kDefaultFrequency * AudioVoiceMsgMaxLength) { if (samples < 0 || samples >= Media::Player::kDefaultFrequency * AudioVoiceMsgMaxLength) {
stopRecording(_peer && samples > 0 && _inField); stopRecording(_peer && samples > 0 && _inField);
@ -1364,7 +1370,7 @@ void HistoryWidget::setReplyReturns(PeerId peer, const QList<MsgId> &replyReturn
_replyReturns = replyReturns; _replyReturns = replyReturns;
if (_replyReturns.isEmpty()) { if (_replyReturns.isEmpty()) {
_replyReturn = 0; _replyReturn = nullptr;
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) { } else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
_replyReturn = App::histItemById(0, -_replyReturns.back()); _replyReturn = App::histItemById(0, -_replyReturns.back());
} else { } else {
@ -1373,7 +1379,7 @@ void HistoryWidget::setReplyReturns(PeerId peer, const QList<MsgId> &replyReturn
while (!_replyReturns.isEmpty() && !_replyReturn) { while (!_replyReturns.isEmpty() && !_replyReturn) {
_replyReturns.pop_back(); _replyReturns.pop_back();
if (_replyReturns.isEmpty()) { if (_replyReturns.isEmpty()) {
_replyReturn = 0; _replyReturn = nullptr;
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) { } else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
_replyReturn = App::histItemById(0, -_replyReturns.back()); _replyReturn = App::histItemById(0, -_replyReturns.back());
} else { } else {
@ -1383,11 +1389,11 @@ void HistoryWidget::setReplyReturns(PeerId peer, const QList<MsgId> &replyReturn
} }
void HistoryWidget::calcNextReplyReturn() { void HistoryWidget::calcNextReplyReturn() {
_replyReturn = 0; _replyReturn = nullptr;
while (!_replyReturns.isEmpty() && !_replyReturn) { while (!_replyReturns.isEmpty() && !_replyReturn) {
_replyReturns.pop_back(); _replyReturns.pop_back();
if (_replyReturns.isEmpty()) { if (_replyReturns.isEmpty()) {
_replyReturn = 0; _replyReturn = nullptr;
} else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) { } else if (_replyReturns.back() < 0 && -_replyReturns.back() < ServerMaxMsgId) {
_replyReturn = App::histItemById(0, -_replyReturns.back()); _replyReturn = App::histItemById(0, -_replyReturns.back());
} else { } else {
@ -2784,7 +2790,7 @@ bool HistoryWidget::saveEditMsgFail(History *history, const RPCError &error, mtp
} }
} }
QString err = error.type(); const auto &err = error.type();
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) { if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::show(Box<InformBox>(lang(lng_edit_error))); Ui::show(Box<InformBox>(lang(lng_edit_error)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) { } else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
@ -2989,17 +2995,20 @@ void HistoryWidget::unreadMentionsAnimationFinish() {
updateUnreadMentionsPosition(); updateUnreadMentionsPosition();
} }
void HistoryWidget::step_recording(float64 ms, bool timer) { bool HistoryWidget::recordingAnimationCallback(crl::time now) {
const auto dt = anim::Disabled() ? 1. : (ms / AudioVoiceMsgUpdateView); const auto dt = anim::Disabled()
if (dt >= 1) { ? 1.
_a_recording.stop(); : ((now - _recordingAnimation.started())
a_recordingLevel.finish(); / float64(kRecordingUpdateDelta));
if (dt >= 1.) {
_recordingLevel.finish();
} else { } else {
a_recordingLevel.update(dt, anim::linear); _recordingLevel.update(dt, anim::linear);
} }
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(_attachToggle->geometry()); update(_attachToggle->geometry());
} }
return (dt < 1.);
} }
void HistoryWidget::chooseAttach() { void HistoryWidget::chooseAttach() {
@ -3080,7 +3089,9 @@ void HistoryWidget::leaveEventHook(QEvent *e) {
_attachDragState = DragState::None; _attachDragState = DragState::None;
updateDragAreas(); updateDragAreas();
} }
if (hasMouseTracking()) mouseMoveEvent(0); if (hasMouseTracking()) {
mouseMoveEvent(nullptr);
}
} }
void HistoryWidget::mouseMoveEvent(QMouseEvent *e) { void HistoryWidget::mouseMoveEvent(QMouseEvent *e) {
@ -3158,8 +3169,8 @@ void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) {
void HistoryWidget::stopRecording(bool send) { void HistoryWidget::stopRecording(bool send) {
emit Media::Capture::instance()->stop(send); emit Media::Capture::instance()->stop(send);
a_recordingLevel = anim::value(); _recordingLevel = anim::value();
_a_recording.stop(); _recordingAnimation.stop();
_recording = false; _recording = false;
_recordingSamples = 0; _recordingSamples = 0;
@ -3581,7 +3592,7 @@ void HistoryWidget::onKbToggle(bool manual) {
_field->setMaxHeight(st::historyComposeFieldMaxHeight); _field->setMaxHeight(st::historyComposeFieldMaxHeight);
_kbReplyTo = 0; _kbReplyTo = nullptr;
if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_editMsgId && !_replyToId) { if (!readyToForward() && (!_previewData || _previewData->pendingTill < 0) && !_editMsgId && !_replyToId) {
_fieldBarCancel->hide(); _fieldBarCancel->hide();
updateMouseTracking(); updateMouseTracking();
@ -3604,7 +3615,9 @@ void HistoryWidget::onKbToggle(bool manual) {
_field->setMaxHeight(st::historyComposeFieldMaxHeight); _field->setMaxHeight(st::historyComposeFieldMaxHeight);
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard->forceReply()) ? App::histItemById(_keyboard->forMsgId()) : 0; _kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard->forceReply())
? App::histItemById(_keyboard->forMsgId())
: nullptr;
if (_kbReplyTo && !_editMsgId && !_replyToId && fieldEnabled) { if (_kbReplyTo && !_editMsgId && !_replyToId && fieldEnabled) {
updateReplyToName(); updateReplyToName();
updateReplyEditText(_kbReplyTo); updateReplyEditText(_kbReplyTo);
@ -3621,7 +3634,9 @@ void HistoryWidget::onKbToggle(bool manual) {
int32 maxh = qMin(_keyboard->height(), st::historyComposeFieldMaxHeight - (st::historyComposeFieldMaxHeight / 2)); int32 maxh = qMin(_keyboard->height(), st::historyComposeFieldMaxHeight - (st::historyComposeFieldMaxHeight / 2));
_field->setMaxHeight(st::historyComposeFieldMaxHeight - maxh); _field->setMaxHeight(st::historyComposeFieldMaxHeight - maxh);
_kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard->forceReply()) ? App::histItemById(_keyboard->forMsgId()) : 0; _kbReplyTo = (_peer->isChat() || _peer->isChannel() || _keyboard->forceReply())
? App::histItemById(_keyboard->forMsgId())
: nullptr;
if (_kbReplyTo && !_editMsgId && !_replyToId) { if (_kbReplyTo && !_editMsgId && !_replyToId) {
updateReplyToName(); updateReplyToName();
updateReplyEditText(_kbReplyTo); updateReplyEditText(_kbReplyTo);
@ -6461,7 +6476,7 @@ void HistoryWidget::drawRecording(Painter &p, float64 recordActive) {
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(st::historyRecordSignalColor); p.setBrush(st::historyRecordSignalColor);
auto delta = qMin(a_recordingLevel.current() / 0x4000, 1.); auto delta = qMin(_recordingLevel.current() / 0x4000, 1.);
auto d = 2 * qRound(st::historyRecordSignalMin + (delta * (st::historyRecordSignalMax - st::historyRecordSignalMin))); auto d = 2 * qRound(st::historyRecordSignalMin + (delta * (st::historyRecordSignalMax - st::historyRecordSignalMin)));
{ {
PainterHighQualityEnabler hq(p); PainterHighQualityEnabler hq(p);

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/field_autocomplete.h" #include "chat_helpers/field_autocomplete.h"
#include "window/section_widget.h" #include "window/section_widget.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/effects/animations.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "base/flags.h" #include "base/flags.h"
#include "base/timer.h" #include "base/timer.h"
@ -219,7 +220,7 @@ public:
void updatePreview(); void updatePreview();
void previewCancel(); void previewCancel();
void step_recording(float64 ms, bool timer); bool recordingAnimationCallback(crl::time now);
void stopRecording(bool send); void stopRecording(bool send);
void onListEscapePressed(); void onListEscapePressed();
@ -768,9 +769,9 @@ private:
rpl::lifetime _uploaderSubscriptions; rpl::lifetime _uploaderSubscriptions;
// This can animate for a very long time (like in music playing), // This can animate for a very long time (like in music playing),
// so it should be a BasicAnimation, not an Animation. // so it should be a Basic, not a Simple animation.
BasicAnimation _a_recording; Ui::Animations::Basic _recordingAnimation;
anim::value a_recordingLevel; anim::value _recordingLevel;
bool kbWasHidden() const; bool kbWasHidden() const;

View File

@ -25,6 +25,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
constexpr auto kAudioVoiceMsgUpdateView = crl::time(100);
using TextState = HistoryView::TextState; using TextState = HistoryView::TextState;
} // namespace } // namespace
@ -364,7 +366,7 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection,
if (voice->seeking()) { if (voice->seeking()) {
return voice->seekingCurrent(); return voice->seekingCurrent();
} else if (voice->_playback) { } else if (voice->_playback) {
return voice->_playback->a_progress.current(); return voice->_playback->progress.current();
} }
return 0.; return 0.;
})(); })();
@ -707,15 +709,15 @@ bool HistoryDocument::updateStatusText() const {
if (auto voice = Get<HistoryDocumentVoice>()) { if (auto voice = Get<HistoryDocumentVoice>()) {
bool was = (voice->_playback != nullptr); bool was = (voice->_playback != nullptr);
voice->ensurePlayback(this); voice->ensurePlayback(this);
if (!was || state.position != voice->_playback->_position) { if (!was || state.position != voice->_playback->position) {
auto prg = state.length ? snap(float64(state.position) / state.length, 0., 1.) : 0.; auto prg = state.length ? snap(float64(state.position) / state.length, 0., 1.) : 0.;
if (voice->_playback->_position < state.position) { if (voice->_playback->position < state.position) {
voice->_playback->a_progress.start(prg); voice->_playback->progress.start(prg);
} else { } else {
voice->_playback->a_progress = anim::value(0., prg); voice->_playback->progress = anim::value(0., prg);
} }
voice->_playback->_position = state.position; voice->_playback->position = state.position;
voice->_playback->_a_progress.start(); voice->_playback->progressAnimation.start();
} }
voice->_lastDurationMs = static_cast<int>((state.length * 1000LL) / state.frequency); // Bad :( voice->_lastDurationMs = static_cast<int>((state.length * 1000LL) / state.frequency); // Bad :(
} }
@ -759,24 +761,25 @@ bool HistoryDocument::hideForwardedFrom() const {
return _data->isSong(); return _data->isSong();
} }
void HistoryDocument::step_voiceProgress(float64 ms, bool timer) { bool HistoryDocument::voiceProgressAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
ms += (2 * AudioVoiceMsgUpdateView); now += (2 * kAudioVoiceMsgUpdateView);
} }
if (auto voice = Get<HistoryDocumentVoice>()) { if (const auto voice = Get<HistoryDocumentVoice>()) {
if (voice->_playback) { if (voice->_playback) {
float64 dt = ms / (2 * AudioVoiceMsgUpdateView); const auto dt = (now - voice->_playback->progressAnimation.started())
if (dt >= 1) { / float64(2 * kAudioVoiceMsgUpdateView);
voice->_playback->_a_progress.stop(); if (dt >= 1.) {
voice->_playback->a_progress.finish(); voice->_playback->progressAnimation.stop();
voice->_playback->progress.finish();
} else { } else {
voice->_playback->a_progress.update(qMin(dt, 1.), anim::linear); voice->_playback->progress.update(qMin(dt, 1.), anim::linear);
}
if (timer) {
history()->owner().requestViewRepaint(_parent);
} }
history()->owner().requestViewRepaint(_parent);
return (dt < 1.);
} }
} }
return false;
} }
void HistoryDocument::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) { void HistoryDocument::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
@ -793,8 +796,8 @@ void HistoryDocument::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool
currentProgress); currentProgress);
voice->ensurePlayback(this); voice->ensurePlayback(this);
voice->_playback->_position = 0; voice->_playback->position = 0;
voice->_playback->a_progress = anim::value(currentProgress, currentProgress); voice->_playback->progress = anim::value(currentProgress, currentProgress);
} }
voice->stopSeeking(); voice->stopSeeking();
} }

View File

@ -48,7 +48,7 @@ public:
QMargins bubbleMargins() const override; QMargins bubbleMargins() const override;
bool hideForwardedFrom() const override; bool hideForwardedFrom() const override;
void step_voiceProgress(float64 ms, bool timer); bool voiceProgressAnimationCallback(crl::time now);
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override; void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;

View File

@ -67,28 +67,28 @@ void HistoryFileMedia::setStatusSize(int newSize, int fullSize, int duration, qi
} }
} }
void HistoryFileMedia::step_radial(crl::time ms, bool timer) { bool HistoryFileMedia::radialAnimationCallback(crl::time now) const {
const auto updateRadial = [&] { const auto radialUpdated = [&] {
return _animation->radial.update( return _animation->radial.update(
dataProgress(), dataProgress(),
dataFinished(), dataFinished(),
ms); now);
}; }();
if (timer) { if (!anim::Disabled() || radialUpdated) {
if (!anim::Disabled() || updateRadial()) { history()->owner().requestViewRepaint(_parent);
history()->owner().requestViewRepaint(_parent);
}
} else {
updateRadial();
if (!_animation->radial.animating()) {
checkAnimationFinished();
}
} }
if (!_animation->radial.animating()) {
checkAnimationFinished();
return false;
}
return true;
} }
void HistoryFileMedia::ensureAnimation() const { void HistoryFileMedia::ensureAnimation() const {
if (!_animation) { if (!_animation) {
_animation = std::make_unique<AnimationData>(animation(const_cast<HistoryFileMedia*>(this), &HistoryFileMedia::step_radial)); _animation = std::make_unique<AnimationData>([=](crl::time now) {
return radialAnimationCallback(now);
});
} }
} }

View File

@ -62,17 +62,16 @@ protected:
// duration = -1 - no duration, duration = -2 - "GIF" duration // duration = -1 - no duration, duration = -2 - "GIF" duration
void setStatusSize(int newSize, int fullSize, int duration, qint64 realDuration) const; void setStatusSize(int newSize, int fullSize, int duration, qint64 realDuration) const;
void step_radial(crl::time ms, bool timer); bool radialAnimationCallback(crl::time now) const;
void thumbAnimationCallback(); void thumbAnimationCallback();
void ensureAnimation() const; void ensureAnimation() const;
void checkAnimationFinished() const; void checkAnimationFinished() const;
bool isRadialAnimation(crl::time ms) const { bool isRadialAnimation(crl::time now) const {
if (!_animation || !_animation->radial.animating()) return false; return _animation
&& _animation->radial.animating()
_animation->radial.step(ms); && radialAnimationCallback(now);
return _animation && _animation->radial.animating();
} }
bool isThumbAnimation(crl::time ms) const { bool isThumbAnimation(crl::time ms) const {
if (_animation) { if (_animation) {
@ -89,9 +88,11 @@ protected:
virtual bool dataLoaded() const = 0; virtual bool dataLoaded() const = 0;
struct AnimationData { struct AnimationData {
AnimationData(AnimationCallbacks &&radialCallbacks) template <typename Callback>
: radial(std::move(radialCallbacks)) { AnimationData(Callback &&radialCallback)
: radial(std::forward<Callback>(radialCallback)) {
} }
Animation a_thumbOver; Animation a_thumbOver;
Ui::RadialAnimation radial; Ui::RadialAnimation radial;
}; };

View File

@ -142,9 +142,10 @@ struct HistoryPoll::AnswersAnimation {
}; };
struct HistoryPoll::SendingAnimation { struct HistoryPoll::SendingAnimation {
template <typename Callback>
SendingAnimation( SendingAnimation(
const QByteArray &option, const QByteArray &option,
AnimationCallbacks &&callbacks); Callback &&callback);
QByteArray option; QByteArray option;
Ui::InfiniteRadialAnimation animation; Ui::InfiniteRadialAnimation animation;
@ -167,11 +168,14 @@ struct HistoryPoll::Answer {
mutable std::unique_ptr<Ui::RippleAnimation> ripple; mutable std::unique_ptr<Ui::RippleAnimation> ripple;
}; };
template <typename Callback>
HistoryPoll::SendingAnimation::SendingAnimation( HistoryPoll::SendingAnimation::SendingAnimation(
const QByteArray &option, const QByteArray &option,
AnimationCallbacks &&callbacks) Callback &&callback)
: option(option) : option(option)
, animation(std::move(callbacks), st::historyPollRadialAnimation) { , animation(
std::forward<Callback>(callback),
st::historyPollRadialAnimation) {
} }
HistoryPoll::Answer::Answer() : text(st::msgMinWidth / 2) { HistoryPoll::Answer::Answer() : text(st::msgMinWidth / 2) {
@ -397,9 +401,7 @@ void HistoryPoll::checkSendingAnimation() const {
} }
_sendingAnimation = std::make_unique<SendingAnimation>( _sendingAnimation = std::make_unique<SendingAnimation>(
sending, sending,
animation( [=] { radialAnimationCallback(); });
const_cast<HistoryPoll*>(this),
&HistoryPoll::step_radial));
_sendingAnimation->animation.start(); _sendingAnimation->animation.start();
} }
@ -561,8 +563,8 @@ void HistoryPoll::resetAnswersAnimation() const {
} }
} }
void HistoryPoll::step_radial(crl::time ms, bool timer) { void HistoryPoll::radialAnimationCallback() const {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
history()->owner().requestViewRepaint(_parent); history()->owner().requestViewRepaint(_parent);
} }
} }

View File

@ -109,7 +109,7 @@ private:
void saveStateInAnimation() const; void saveStateInAnimation() const;
void startAnswersAnimation() const; void startAnswersAnimation() const;
void resetAnswersAnimation() const; void resetAnswersAnimation() const;
void step_radial(crl::time ms, bool timer); void radialAnimationCallback() const;
void toggleRipple(Answer &answer, bool pressed); void toggleRipple(Answer &answer, bool pressed);

View File

@ -154,15 +154,15 @@ void TopBarWidget::updateConnectingState() {
} }
} else if (!_connecting) { } else if (!_connecting) {
_connecting = std::make_unique<Ui::InfiniteRadialAnimation>( _connecting = std::make_unique<Ui::InfiniteRadialAnimation>(
animation(this, &TopBarWidget::step_connecting), [=] { connectingAnimationCallback(); },
st::topBarConnectingAnimation); st::topBarConnectingAnimation);
_connecting->start(); _connecting->start();
update(); update();
} }
} }
void TopBarWidget::step_connecting(crl::time ms, bool timer) { void TopBarWidget::connectingAnimationCallback() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(); update();
} }
} }
@ -362,9 +362,6 @@ bool TopBarWidget::paintConnectingState(
int top, int top,
int outerWidth, int outerWidth,
crl::time ms) { crl::time ms) {
if (_connecting) {
_connecting->step(ms);
}
if (!_connecting) { if (!_connecting) {
return false; return false;
} }

View File

@ -84,7 +84,7 @@ private:
void updateConnectingState(); void updateConnectingState();
void updateAdaptiveLayout(); void updateAdaptiveLayout();
int countSelectedButtonsTop(float64 selectedShown); int countSelectedButtonsTop(float64 selectedShown);
void step_connecting(crl::time ms, bool timer); void connectingAnimationCallback();
void paintTopBar(Painter &p, crl::time ms); void paintTopBar(Painter &p, crl::time ms);
void paintStatus( void paintStatus(

View File

@ -321,35 +321,34 @@ void Gif::prepareThumbnail(QSize size, QSize frame) const {
void Gif::ensureAnimation() const { void Gif::ensureAnimation() const {
if (!_animation) { if (!_animation) {
_animation = std::make_unique<AnimationData>(animation(const_cast<Gif*>(this), &Gif::step_radial)); _animation = std::make_unique<AnimationData>([=](crl::time now) {
return radialAnimationCallback(now);
});
} }
} }
bool Gif::isRadialAnimation(crl::time ms) const { bool Gif::isRadialAnimation(crl::time now) const {
if (!_animation || !_animation->radial.animating()) return false; return _animation
&& _animation->radial.animating()
_animation->radial.step(ms); && radialAnimationCallback(now);
return _animation && _animation->radial.animating();
} }
void Gif::step_radial(crl::time ms, bool timer) { bool Gif::radialAnimationCallback(crl::time now) const {
const auto document = getShownDocument(); const auto document = getShownDocument();
const auto updateRadial = [&] { const auto radialUpdated = [&] {
return _animation->radial.update( return _animation->radial.update(
document->progress(), document->progress(),
!document->loading() || document->loaded(), !document->loading() || document->loaded(),
ms); now);
}; }();
if (timer) { if (!anim::Disabled() || radialUpdated) {
if (!anim::Disabled() || updateRadial()) { update();
update();
}
} else {
updateRadial();
if (!_animation->radial.animating() && document->loaded()) {
_animation.reset();
}
} }
if (!_animation->radial.animating() && document->loaded()) {
_animation.reset();
return false;
}
return true;
} }
void Gif::clipCallback(Media::Clip::Notification notification) { void Gif::clipCallback(Media::Clip::Notification notification) {
@ -845,28 +844,28 @@ void File::thumbAnimationCallback() {
update(); update();
} }
void File::step_radial(crl::time ms, bool timer) { bool File::radialAnimationCallback(crl::time now) const {
const auto updateRadial = [&] { const auto radialUpdated = [&] {
return _animation->radial.update( return _animation->radial.update(
_document->progress(), _document->progress(),
!_document->loading() || _document->loaded(), !_document->loading() || _document->loaded(),
ms); now);
}; }();
if (timer) { if (!anim::Disabled() || radialUpdated) {
if (!anim::Disabled() || updateRadial()) { update();
update();
}
} else {
updateRadial();
if (!_animation->radial.animating()) {
checkAnimationFinished();
}
} }
if (!_animation->radial.animating()) {
checkAnimationFinished();
return false;
}
return true;
} }
void File::ensureAnimation() const { void File::ensureAnimation() const {
if (!_animation) { if (!_animation) {
_animation = std::make_unique<AnimationData>(animation(const_cast<File*>(this), &File::step_radial)); _animation = std::make_unique<AnimationData>([=](crl::time now) {
return radialAnimationCallback(now);
});
} }
} }
@ -1251,7 +1250,9 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con
bool animating = (_gif && _gif->started()); bool animating = (_gif && _gif->started());
if (displayLoading) { if (displayLoading) {
if (!_radial) { if (!_radial) {
_radial = std::make_unique<Ui::RadialAnimation>(animation(const_cast<Game*>(this), &Game::step_radial)); _radial = std::make_unique<Ui::RadialAnimation>([=](crl::time now) {
return radialAnimationCallback(now);
});
} }
if (!_radial->animating()) { if (!_radial->animating()) {
_radial->start(document->progress()); _radial->start(document->progress());
@ -1360,31 +1361,28 @@ void Game::validateThumbnail(Image *image, QSize size, bool good) const {
size.height()); size.height());
} }
bool Game::isRadialAnimation(crl::time ms) const { bool Game::isRadialAnimation(crl::time now) const {
if (!_radial || !_radial->animating()) return false; return _radial
&& _radial->animating()
_radial->step(ms); && radialAnimationCallback(now);
return _radial && _radial->animating();
} }
void Game::step_radial(crl::time ms, bool timer) { bool Game::radialAnimationCallback(crl::time now) const {
const auto document = getResultDocument(); const auto document = getResultDocument();
const auto updateRadial = [&] { const auto radialUpdated = [&] {
return _radial->update( return _radial->update(
document->progress(), document->progress(),
!document->loading() || document->loaded(), !document->loading() || document->loaded(),
ms); now);
}; }();
if (timer) { if (!anim::Disabled() || radialUpdated) {
if (!anim::Disabled() || updateRadial()) { update();
update();
}
} else {
updateRadial();
if (!_radial->animating() && document->loaded()) {
_radial.reset();
}
} }
if (!_radial->animating() && document->loaded()) {
_radial.reset();
return false;
}
return true;
} }
void Game::clipCallback(Media::Clip::Notification notification) { void Game::clipCallback(Media::Clip::Notification notification) {

View File

@ -92,17 +92,17 @@ private:
void prepareThumbnail(QSize size, QSize frame) const; void prepareThumbnail(QSize size, QSize frame) const;
void ensureAnimation() const; void ensureAnimation() const;
bool isRadialAnimation(crl::time ms) const; bool isRadialAnimation(crl::time now) const;
void step_radial(crl::time ms, bool timer); bool radialAnimationCallback(crl::time now) const;
void clipCallback(Media::Clip::Notification notification); void clipCallback(Media::Clip::Notification notification);
struct AnimationData { struct AnimationData {
AnimationData(AnimationCallbacks &&callbacks) template <typename Callback>
: over(false) AnimationData(Callback &&callback)
, radial(std::move(callbacks)) { : radial(std::forward<Callback>(callback)) {
} }
bool over; bool over = false;
Animation _a_over; Animation _a_over;
Ui::RadialAnimation radial; Ui::RadialAnimation radial;
}; };
@ -250,17 +250,16 @@ public:
private: private:
void thumbAnimationCallback(); void thumbAnimationCallback();
void step_radial(crl::time ms, bool timer); bool radialAnimationCallback(crl::time now) const;
void ensureAnimation() const; void ensureAnimation() const;
void checkAnimationFinished() const; void checkAnimationFinished() const;
bool updateStatusText() const; bool updateStatusText() const;
bool isRadialAnimation(crl::time ms) const { bool isRadialAnimation(crl::time now) const {
if (!_animation || !_animation->radial.animating()) return false; return _animation
&& _animation->radial.animating()
_animation->radial.step(ms); && radialAnimationCallback(now);
return _animation && _animation->radial.animating();
} }
bool isThumbAnimation(crl::time ms) const { bool isThumbAnimation(crl::time ms) const {
if (_animation) { if (_animation) {
@ -273,7 +272,9 @@ private:
} }
struct AnimationData { struct AnimationData {
AnimationData(AnimationCallbacks &&radialCallbacks) : radial(std::move(radialCallbacks)) { template <typename Callback>
AnimationData(Callback &&radialCallback)
: radial(std::forward<Callback>(radialCallback)) {
} }
Animation a_thumbOver; Animation a_thumbOver;
Ui::RadialAnimation radial; Ui::RadialAnimation radial;
@ -360,8 +361,8 @@ private:
void prepareThumbnail(QSize size) const; void prepareThumbnail(QSize size) const;
void validateThumbnail(Image *image, QSize size, bool good) const; void validateThumbnail(Image *image, QSize size, bool good) const;
bool isRadialAnimation(crl::time ms) const; bool isRadialAnimation(crl::time now) const;
void step_radial(crl::time ms, bool timer); bool radialAnimationCallback(crl::time now) const;
void clipCallback(Media::Clip::Notification notification); void clipCallback(Media::Clip::Notification notification);

View File

@ -91,7 +91,7 @@ void ItemBase::preload() const {
} }
} }
void ItemBase::update() { void ItemBase::update() const {
if (_position >= 0) { if (_position >= 0) {
context()->inlineItemRepaint(this); context()->inlineItemRepaint(this);
} }

View File

@ -78,7 +78,7 @@ public:
virtual void preload() const; virtual void preload() const;
void update(); void update() const;
void layoutChanged(); void layoutChanged();
// ClickHandlerHost interface // ClickHandlerHost interface

View File

@ -23,6 +23,7 @@ constexpr auto kCaptureFrequency = Player::kDefaultFrequency;
constexpr auto kCaptureSkipDuration = crl::time(400); constexpr auto kCaptureSkipDuration = crl::time(400);
constexpr auto kCaptureFadeInDuration = crl::time(300); constexpr auto kCaptureFadeInDuration = crl::time(300);
constexpr auto kCaptureBufferSlice = 256 * 1024; constexpr auto kCaptureBufferSlice = 256 * 1024;
constexpr auto kCaptureUpdateDelta = crl::time(100);
Instance *CaptureInstance = nullptr; Instance *CaptureInstance = nullptr;
@ -517,7 +518,7 @@ void Instance::Inner::onTimeout() {
} }
} }
qint32 samplesFull = d->fullSamples + _captured.size() / sizeof(short), samplesSinceUpdate = samplesFull - d->lastUpdate; qint32 samplesFull = d->fullSamples + _captured.size() / sizeof(short), samplesSinceUpdate = samplesFull - d->lastUpdate;
if (samplesSinceUpdate > AudioVoiceMsgUpdateView * kCaptureFrequency / 1000) { if (samplesSinceUpdate > kCaptureUpdateDelta * kCaptureFrequency / 1000) {
emit updated(d->levelMax, samplesFull); emit updated(d->levelMax, samplesFull);
d->lastUpdate = samplesFull; d->lastUpdate = samplesFull;
d->levelMax = 0; d->levelMax = 0;

View File

@ -147,12 +147,13 @@ struct OverlayWidget::Collage {
}; };
struct OverlayWidget::Streamed { struct OverlayWidget::Streamed {
template <typename Callback>
Streamed( Streamed(
not_null<Data::Session*> owner, not_null<Data::Session*> owner,
std::unique_ptr<Streaming::Loader> loader, std::unique_ptr<Streaming::Loader> loader,
QWidget *controlsParent, QWidget *controlsParent,
not_null<PlaybackControls::Delegate*> controlsDelegate, not_null<PlaybackControls::Delegate*> controlsDelegate,
AnimationCallbacks loadingCallbacks); Callback &&loadingCallback);
Streaming::Player player; Streaming::Player player;
Streaming::Information info; Streaming::Information info;
@ -160,22 +161,25 @@ struct OverlayWidget::Streamed {
bool waiting = false; bool waiting = false;
Ui::InfiniteRadialAnimation radial; Ui::InfiniteRadialAnimation radial;
Animation fading; Ui::Animations::Simple fading;
base::Timer timer; base::Timer timer;
QImage frameForDirectPaint; QImage frameForDirectPaint;
bool resumeOnCallEnd = false; bool resumeOnCallEnd = false;
}; };
template <typename Callback>
OverlayWidget::Streamed::Streamed( OverlayWidget::Streamed::Streamed(
not_null<Data::Session*> owner, not_null<Data::Session*> owner,
std::unique_ptr<Streaming::Loader> loader, std::unique_ptr<Streaming::Loader> loader,
QWidget *controlsParent, QWidget *controlsParent,
not_null<PlaybackControls::Delegate*> controlsDelegate, not_null<PlaybackControls::Delegate*> controlsDelegate,
AnimationCallbacks loadingCallbacks) Callback &&loadingCallback)
: player(owner, std::move(loader)) : player(owner, std::move(loader))
, controls(controlsParent, controlsDelegate) , controls(controlsParent, controlsDelegate)
, radial(std::move(loadingCallbacks), st::mediaviewStreamingRadial) { , radial(
std::forward<Callback>(loadingCallback),
st::mediaviewStreamingRadial) {
} }
OverlayWidget::OverlayWidget() OverlayWidget::OverlayWidget()
@ -184,7 +188,7 @@ OverlayWidget::OverlayWidget()
, _docDownload(this, lang(lng_media_download), st::mediaviewFileLink) , _docDownload(this, lang(lng_media_download), st::mediaviewFileLink)
, _docSaveAs(this, lang(lng_mediaview_save_as), st::mediaviewFileLink) , _docSaveAs(this, lang(lng_mediaview_save_as), st::mediaviewFileLink)
, _docCancel(this, lang(lng_cancel), st::mediaviewFileLink) , _docCancel(this, lang(lng_cancel), st::mediaviewFileLink)
, _radial(animation(this, &OverlayWidget::step_radial)) , _radial([=](crl::time now) { return radialAnimationCallback(now); })
, _lastAction(-st::mediaviewDeltaFromLastAction, -st::mediaviewDeltaFromLastAction) , _lastAction(-st::mediaviewDeltaFromLastAction, -st::mediaviewDeltaFromLastAction)
, _stateAnimation([=](crl::time now) { return stateAnimationCallback(now); }) , _stateAnimation([=](crl::time now) { return stateAnimationCallback(now); })
, _dropdown(this, st::mediaviewDropdownMenu) , _dropdown(this, st::mediaviewDropdownMenu)
@ -704,8 +708,8 @@ bool OverlayWidget::updateControlsAnimation(crl::time now) {
return (dt < 1); return (dt < 1);
} }
void OverlayWidget::step_waiting(crl::time ms, bool timer) { void OverlayWidget::waitingAnimationCallback() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(radialRect()); update(radialRect());
} }
} }
@ -802,17 +806,17 @@ crl::time OverlayWidget::radialTimeShift() const {
return _photo ? st::radialDuration : 0; return _photo ? st::radialDuration : 0;
} }
void OverlayWidget::step_radial(crl::time ms, bool timer) { bool OverlayWidget::radialAnimationCallback(crl::time now) {
if ((!_doc && !_photo) || _streamed) { if ((!_doc && !_photo) || _streamed) {
_radial.stop(); return false;
return;
} }
const auto wasAnimating = _radial.animating(); const auto wasAnimating = _radial.animating();
const auto updated = _radial.update( const auto updated = _radial.update(
radialProgress(), radialProgress(),
!radialLoading(), !radialLoading(),
ms + radialTimeShift()); now + radialTimeShift());
if (timer && (wasAnimating || _radial.animating()) && (!anim::Disabled() || updated)) { if ((wasAnimating || _radial.animating())
&& (!anim::Disabled() || updated)) {
update(radialRect()); update(radialRect());
} }
const auto ready = _doc && _doc->loaded(); const auto ready = _doc && _doc->loaded();
@ -833,6 +837,7 @@ void OverlayWidget::step_radial(crl::time ms, bool timer) {
} }
} }
} }
return true;
} }
void OverlayWidget::zoomIn() { void OverlayWidget::zoomIn() {
@ -1986,7 +1991,7 @@ void OverlayWidget::createStreamingObjects() {
_doc->createStreamingLoader(fileOrigin()), _doc->createStreamingLoader(fileOrigin()),
this, this,
static_cast<PlaybackControls::Delegate*>(this), static_cast<PlaybackControls::Delegate*>(this),
animation(this, &OverlayWidget::step_waiting)); [=] { waitingAnimationCallback(); });
if (videoIsGifv()) { if (videoIsGifv()) {
_streamed->controls.hide(); _streamed->controls.hide();
@ -2449,13 +2454,8 @@ void OverlayWidget::paintEvent(QPaintEvent *e) {
} }
} }
bool radial = false; const auto radial = _radial.animating();
float64 radialOpacity = 0; const auto radialOpacity = radial ? _radial.opacity() : 0.;
if (_radial.animating()) {
_radial.step(ms);
radial = _radial.animating();
radialOpacity = _radial.opacity();
}
paintRadialLoading(p, radial, radialOpacity); paintRadialLoading(p, radial, radialOpacity);
} }
if (_saveMsgStarted && _saveMsg.intersects(r)) { if (_saveMsgStarted && _saveMsg.intersects(r)) {
@ -2491,13 +2491,8 @@ void OverlayWidget::paintEvent(QPaintEvent *e) {
if (_docRect.intersects(r)) { if (_docRect.intersects(r)) {
p.fillRect(_docRect, st::mediaviewFileBg); p.fillRect(_docRect, st::mediaviewFileBg);
if (_docIconRect.intersects(r)) { if (_docIconRect.intersects(r)) {
bool radial = false; const auto radial = _radial.animating();
float64 radialOpacity = 0; const auto radialOpacity = radial ? _radial.opacity() : 0.;
if (_radial.animating()) {
_radial.step(ms);
radial = _radial.animating();
radialOpacity = _radial.opacity();
}
if (!_doc || !_doc->hasThumbnail()) { if (!_doc || !_doc->hasThumbnail()) {
p.fillRect(_docIconRect, _docIconColor); p.fillRect(_docIconRect, _docIconColor);
if ((!_doc || _doc->loaded()) && (!radial || radialOpacity < 1) && _docIcon) { if ((!_doc || _doc->loaded()) && (!radial || radialOpacity < 1) && _docIcon) {
@ -2721,12 +2716,9 @@ void OverlayWidget::paintRadialLoading(
bool radial, bool radial,
float64 radialOpacity) { float64 radialOpacity) {
if (_streamed) { if (_streamed) {
const auto ms = crl::now();
_streamed->radial.step(ms);
if (!_streamed->radial.animating()) { if (!_streamed->radial.animating()) {
return; return;
} }
_streamed->fading.step(ms);
if (!_streamed->fading.animating() && !_streamed->waiting) { if (!_streamed->fading.animating() && !_streamed->waiting) {
if (!_streamed->waiting) { if (!_streamed->waiting) {
_streamed->radial.stop(anim::type::instant); _streamed->radial.stop(anim::type::instant);
@ -2783,7 +2775,7 @@ void OverlayWidget::paintRadialLoadingContent(
if (_streamed) { if (_streamed) {
paintBg( paintBg(
_streamed->fading.current(_streamed->waiting ? 1. : 0.), _streamed->fading.value(_streamed->waiting ? 1. : 0.),
st::radialBg); st::radialBg);
_streamed->radial.draw(p, arc.topLeft(), arc.size(), width()); _streamed->radial.draw(p, arc.topLeft(), arc.size(), width());
return; return;

View File

@ -276,8 +276,8 @@ private:
void clearControlsState(); void clearControlsState();
bool stateAnimationCallback(crl::time ms); bool stateAnimationCallback(crl::time ms);
void step_radial(crl::time ms, bool timer); bool radialAnimationCallback(crl::time now);
void step_waiting(crl::time ms, bool timer); void waitingAnimationCallback();
bool updateControlsAnimation(crl::time now); bool updateControlsAnimation(crl::time now);
void zoomIn(); void zoomIn();

View File

@ -218,29 +218,29 @@ void RadialProgressItem::setLinks(
_cancell = std::move(cancell); _cancell = std::move(cancell);
} }
void RadialProgressItem::step_radial(crl::time ms, bool timer) { bool RadialProgressItem::radialAnimationCallback(crl::time now) const {
const auto updateRadial = [&] { const auto radialUpdated = [&] {
return _radial->update(dataProgress(), dataFinished(), ms); return _radial->update(dataProgress(), dataFinished(), now);
}; }();
if (timer) { if (!anim::Disabled() || radialUpdated) {
if (!anim::Disabled() || updateRadial()) { Auth().data().requestItemRepaint(parent());
Auth().data().requestItemRepaint(parent());
}
} else {
updateRadial();
if (!_radial->animating()) {
checkRadialFinished();
}
} }
if (!_radial->animating()) {
checkRadialFinished();
return false;
}
return true;
} }
void RadialProgressItem::ensureRadial() { void RadialProgressItem::ensureRadial() {
if (!_radial) { if (!_radial) {
_radial = std::make_unique<Ui::RadialAnimation>(animation(const_cast<RadialProgressItem*>(this), &RadialProgressItem::step_radial)); _radial = std::make_unique<Ui::RadialAnimation>([=](crl::time now) {
return radialAnimationCallback(now);
});
} }
} }
void RadialProgressItem::checkRadialFinished() { void RadialProgressItem::checkRadialFinished() const {
if (_radial && !_radial->animating() && dataLoaded()) { if (_radial && !_radial->animating() && dataLoaded()) {
_radial.reset(); _radial.reset();
} }

View File

@ -129,16 +129,15 @@ protected:
ClickHandlerPtr &&cancell); ClickHandlerPtr &&cancell);
void setDocumentLinks(not_null<DocumentData*> document); void setDocumentLinks(not_null<DocumentData*> document);
void step_radial(crl::time ms, bool timer); bool radialAnimationCallback(crl::time now) const;
void ensureRadial(); void ensureRadial();
void checkRadialFinished(); void checkRadialFinished() const;
bool isRadialAnimation(crl::time ms) const { bool isRadialAnimation(crl::time now) const {
if (!_radial || !_radial->animating()) return false; return _radial
&& _radial->animating()
_radial->step(ms); && radialAnimationCallback(now);
return _radial && _radial->animating();
} }
virtual float64 dataProgress() const = 0; virtual float64 dataProgress() const = 0;
@ -148,7 +147,7 @@ protected:
return false; return false;
} }
std::unique_ptr<Ui::RadialAnimation> _radial; mutable std::unique_ptr<Ui::RadialAnimation> _radial;
Animation _a_iconOver; Animation _a_iconOver;
}; };

View File

@ -58,7 +58,7 @@ private:
QRect radialRect() const; QRect radialRect() const;
void radialStart(); void radialStart();
crl::time radialTimeShift() const; crl::time radialTimeShift() const;
void step_radial(crl::time ms, bool timer); void radialAnimationCallback(crl::time now);
QPixmap _background; QPixmap _background;
object_ptr<Ui::LinkButton> _chooseFromGallery; object_ptr<Ui::LinkButton> _chooseFromGallery;
@ -114,7 +114,7 @@ BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent)
lang(lng_settings_bg_from_gallery), lang(lng_settings_bg_from_gallery),
st::settingsLink) st::settingsLink)
, _chooseFromFile(this, lang(lng_settings_bg_from_file), st::settingsLink) , _chooseFromFile(this, lang(lng_settings_bg_from_file), st::settingsLink)
, _radial(animation(this, &BackgroundRow::step_radial)) { , _radial([=](crl::time now) { radialAnimationCallback(now); }) {
updateImage(); updateImage();
_chooseFromGallery->addClickHandler([] { _chooseFromGallery->addClickHandler([] {
@ -139,13 +139,8 @@ BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent)
void BackgroundRow::paintEvent(QPaintEvent *e) { void BackgroundRow::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
bool radial = false; const auto radial = _radial.animating();
float64 radialOpacity = 0; const auto radialOpacity = radial ? _radial.opacity() : 0.;
if (_radial.animating()) {
_radial.step(crl::now());
radial = _radial.animating();
radialOpacity = _radial.opacity();
}
if (radial) { if (radial) {
const auto backThumb = App::main()->newBackgroundThumb(); const auto backThumb = App::main()->newBackgroundThumb();
if (!backThumb) { if (!backThumb) {
@ -249,12 +244,12 @@ crl::time BackgroundRow::radialTimeShift() const {
return st::radialDuration; return st::radialDuration;
} }
void BackgroundRow::step_radial(crl::time ms, bool timer) { void BackgroundRow::radialAnimationCallback(crl::time now) {
const auto updated = _radial.update( const auto updated = _radial.update(
radialProgress(), radialProgress(),
!radialLoading(), !radialLoading(),
ms + radialTimeShift()); now + radialTimeShift());
if (timer && _radial.animating() && (!anim::Disabled() || updated)) { if (!anim::Disabled() || updated) {
rtlupdate(radialRect()); rtlupdate(radialRect());
} }
} }

View File

@ -11,27 +11,23 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui { namespace Ui {
RadialAnimation::RadialAnimation(AnimationCallbacks &&callbacks)
: a_arcStart(0, FullArcLength)
, _animation(std::move(callbacks)) {
}
void RadialAnimation::start(float64 prg) { void RadialAnimation::start(float64 prg) {
_firstStart = _lastStart = _lastTime = crl::now(); _firstStart = _lastStart = _lastTime = crl::now();
int32 iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength), iprgstrict = qRound(prg * AlmostFullArcLength); const auto iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength);
a_arcEnd = anim::value(iprgstrict, iprg); const auto iprgstrict = qRound(prg * AlmostFullArcLength);
_arcEnd = anim::value(iprgstrict, iprg);
_animation.start(); _animation.start();
} }
bool RadialAnimation::update(float64 prg, bool finished, crl::time ms) { bool RadialAnimation::update(float64 prg, bool finished, crl::time ms) {
const auto iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength); const auto iprg = qRound(qMax(prg, 0.0001) * AlmostFullArcLength);
const auto result = (iprg != qRound(a_arcEnd.to())); const auto result = (iprg != qRound(_arcEnd.to()));
if (_finished != finished) { if (_finished != finished) {
a_arcEnd.start(iprg); _arcEnd.start(iprg);
_finished = finished; _finished = finished;
_lastStart = _lastTime; _lastStart = _lastTime;
} else if (result) { } else if (result) {
a_arcEnd.start(iprg); _arcEnd.start(iprg);
_lastStart = _lastTime; _lastStart = _lastTime;
} }
_lastTime = ms; _lastTime = ms;
@ -43,35 +39,31 @@ bool RadialAnimation::update(float64 prg, bool finished, crl::time ms) {
: fulldt; : fulldt;
_opacity = qMin(opacitydt / st::radialDuration, 1.); _opacity = qMin(opacitydt / st::radialDuration, 1.);
if (anim::Disabled()) { if (anim::Disabled()) {
a_arcEnd.update(1., anim::linear); _arcEnd.update(1., anim::linear);
if (finished) { if (finished) {
stop(); stop();
} }
} else if (!finished) { } else if (!finished) {
a_arcEnd.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear); _arcEnd.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear);
} else if (dt >= st::radialDuration) { } else if (dt >= st::radialDuration) {
a_arcEnd.update(1., anim::linear); _arcEnd.update(1., anim::linear);
stop(); stop();
} else { } else {
auto r = dt / st::radialDuration; auto r = dt / st::radialDuration;
a_arcEnd.update(r, anim::linear); _arcEnd.update(r, anim::linear);
_opacity *= 1 - r; _opacity *= 1 - r;
} }
auto fromstart = fulldt / st::radialPeriod; auto fromstart = fulldt / st::radialPeriod;
a_arcStart.update(fromstart - std::floor(fromstart), anim::linear); _arcStart.update(fromstart - std::floor(fromstart), anim::linear);
return result; return result;
} }
void RadialAnimation::stop() { void RadialAnimation::stop() {
_firstStart = _lastStart = _lastTime = 0; _firstStart = _lastStart = _lastTime = 0;
a_arcEnd = anim::value(); _arcEnd = anim::value();
_animation.stop(); _animation.stop();
} }
void RadialAnimation::step(crl::time ms) {
_animation.step(ms);
}
void RadialAnimation::draw( void RadialAnimation::draw(
Painter &p, Painter &p,
const QRect &inner, const QRect &inner,
@ -98,10 +90,10 @@ void RadialAnimation::draw(
} }
RadialState RadialAnimation::computeState() const { RadialState RadialAnimation::computeState() const {
auto length = MinArcLength + qRound(a_arcEnd.current()); auto length = MinArcLength + qRound(_arcEnd.current());
auto from = QuarterArcLength auto from = QuarterArcLength
- length - length
- (anim::Disabled() ? 0 : qRound(a_arcStart.current())); - (anim::Disabled() ? 0 : qRound(_arcStart.current()));
if (rtl()) { if (rtl()) {
from = QuarterArcLength - (from - QuarterArcLength) - length; from = QuarterArcLength - (from - QuarterArcLength) - length;
if (from < 0) from += FullArcLength; if (from < 0) from += FullArcLength;
@ -109,13 +101,6 @@ RadialState RadialAnimation::computeState() const {
return { _opacity, from, length }; return { _opacity, from, length };
} }
InfiniteRadialAnimation::InfiniteRadialAnimation(
AnimationCallbacks &&callbacks,
const style::InfiniteRadialAnimation &st)
: _st(st)
, _animation(std::move(callbacks)) {
}
void InfiniteRadialAnimation::start(crl::time skip) { void InfiniteRadialAnimation::start(crl::time skip) {
const auto now = crl::now(); const auto now = crl::now();
if (_workFinished <= now && (_workFinished || !_workStarted)) { if (_workFinished <= now && (_workFinished || !_workStarted)) {
@ -145,10 +130,6 @@ void InfiniteRadialAnimation::stop(anim::type animated) {
} }
} }
void InfiniteRadialAnimation::step(crl::time ms) {
_animation.step(ms);
}
void InfiniteRadialAnimation::draw( void InfiniteRadialAnimation::draw(
Painter &p, Painter &p,
QPoint position, QPoint position,

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "ui/effects/animations.h"
namespace style { namespace style {
struct InfiniteRadialAnimation; struct InfiniteRadialAnimation;
} // namespace style } // namespace style
@ -21,7 +23,8 @@ struct RadialState {
class RadialAnimation { class RadialAnimation {
public: public:
RadialAnimation(AnimationCallbacks &&callbacks); template <typename Callback>
RadialAnimation(Callback &&callback);
float64 opacity() const { float64 opacity() const {
return _opacity; return _opacity;
@ -34,11 +37,6 @@ public:
bool update(float64 prg, bool finished, crl::time ms); bool update(float64 prg, bool finished, crl::time ms);
void stop(); void stop();
void step(crl::time ms);
void step() {
step(crl::now());
}
void draw( void draw(
Painter &p, Painter &p,
const QRect &inner, const QRect &inner,
@ -52,17 +50,25 @@ private:
crl::time _lastStart = 0; crl::time _lastStart = 0;
crl::time _lastTime = 0; crl::time _lastTime = 0;
float64 _opacity = 0.; float64 _opacity = 0.;
anim::value a_arcEnd; anim::value _arcEnd;
anim::value a_arcStart; anim::value _arcStart;
BasicAnimation _animation; Ui::Animations::Basic _animation;
bool _finished = false; bool _finished = false;
}; };
template <typename Callback>
inline RadialAnimation::RadialAnimation(Callback &&callback)
: _arcStart(0, FullArcLength)
, _animation(std::forward<Callback>(callback)) {
}
class InfiniteRadialAnimation { class InfiniteRadialAnimation {
public: public:
template <typename Callback>
InfiniteRadialAnimation( InfiniteRadialAnimation(
AnimationCallbacks &&callbacks, Callback &&callback,
const style::InfiniteRadialAnimation &st); const style::InfiniteRadialAnimation &st);
bool animating() const { bool animating() const {
@ -72,11 +78,6 @@ public:
void start(crl::time skip = 0); void start(crl::time skip = 0);
void stop(anim::type animated = anim::type::normal); void stop(anim::type animated = anim::type::normal);
void step(crl::time ms);
void step() {
step(crl::now());
}
void draw( void draw(
Painter &p, Painter &p,
QPoint position, QPoint position,
@ -93,8 +94,16 @@ private:
const style::InfiniteRadialAnimation &_st; const style::InfiniteRadialAnimation &_st;
crl::time _workStarted = 0; crl::time _workStarted = 0;
crl::time _workFinished = 0; crl::time _workFinished = 0;
BasicAnimation _animation; Ui::Animations::Basic _animation;
}; };
template <typename Callback>
inline InfiniteRadialAnimation::InfiniteRadialAnimation(
Callback &&callback,
const style::InfiniteRadialAnimation &st)
: _st(st)
, _animation(std::forward<Callback>(callback)) {
}
} // namespace Ui } // namespace Ui

View File

@ -242,8 +242,8 @@ void EmojiButton::paintEvent(QPaintEvent *e) {
} }
} }
void EmojiButton::step_loading(crl::time ms, bool timer) { void EmojiButton::loadingAnimationCallback() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(); update();
} }
} }
@ -251,7 +251,7 @@ void EmojiButton::step_loading(crl::time ms, bool timer) {
void EmojiButton::setLoading(bool loading) { void EmojiButton::setLoading(bool loading) {
if (loading && !_loading) { if (loading && !_loading) {
_loading = std::make_unique<Ui::InfiniteRadialAnimation>( _loading = std::make_unique<Ui::InfiniteRadialAnimation>(
animation(this, &EmojiButton::step_loading), [=] { loadingAnimationCallback(); },
st::defaultInfiniteRadialAnimation); st::defaultInfiniteRadialAnimation);
} }
if (loading) { if (loading) {

View File

@ -65,7 +65,7 @@ protected:
QPoint prepareRippleStartPosition() const override; QPoint prepareRippleStartPosition() const override;
private: private:
void step_loading(crl::time ms, bool timer); void loadingAnimationCallback();
const style::IconButton &_st; const style::IconButton &_st;

View File

@ -277,10 +277,11 @@ void Manager::removeWidget(internal::Widget *remove) {
if (remove == _hideAll.get()) { if (remove == _hideAll.get()) {
_hideAll.reset(); _hideAll.reset();
} else if (remove) { } else if (remove) {
auto it = std::find_if(_notifications.cbegin(), _notifications.cend(), [remove](auto &item) { const auto it = ranges::find(
return item.get() == remove; _notifications,
}); remove,
if (it != _notifications.cend()) { &std::unique_ptr<Notification>::get);
if (it != end(_notifications)) {
_notifications.erase(it); _notifications.erase(it);
_positionsOutdated = true; _positionsOutdated = true;
} }
@ -289,13 +290,13 @@ void Manager::removeWidget(internal::Widget *remove) {
} }
void Manager::doShowNotification(HistoryItem *item, int forwardedCount) { void Manager::doShowNotification(HistoryItem *item, int forwardedCount) {
_queuedNotifications.push_back(QueuedNotification(item, forwardedCount)); _queuedNotifications.emplace_back(item, forwardedCount);
showNextFromQueue(); showNextFromQueue();
} }
void Manager::doClearAll() { void Manager::doClearAll() {
_queuedNotifications.clear(); _queuedNotifications.clear();
for_const (auto &notification, _notifications) { for (const auto &notification : _notifications) {
notification->unlinkHistory(); notification->unlinkHistory();
} }
showNextFromQueue(); showNextFromQueue();
@ -356,8 +357,10 @@ Widget::Widget(Manager *manager, QPoint startPosition, int shift, Direction shif
, _manager(manager) , _manager(manager)
, _startPosition(startPosition) , _startPosition(startPosition)
, _direction(shiftDirection) , _direction(shiftDirection)
, a_shift(shift) , _shift(shift)
, _a_shift(animation(this, &Widget::step_shift)) { , _shiftAnimation([=](crl::time now) {
return shiftAnimationCallback(now);
}) {
setWindowOpacity(0.); setWindowOpacity(0.);
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint)
@ -392,17 +395,19 @@ void Widget::opacityAnimationCallback() {
} }
} }
void Widget::step_shift(float64 ms, bool timer) { bool Widget::shiftAnimationCallback(crl::time now) {
if (anim::Disabled()) { if (anim::Disabled()) {
ms += st::notifyFastAnim; now += st::notifyFastAnim;
} }
float64 dt = ms / float64(st::notifyFastAnim); const auto dt = (now - _shiftAnimation.started())
if (dt >= 1) { / float64(st::notifyFastAnim);
a_shift.finish(); if (dt >= 1.) {
_shift.finish();
} else { } else {
a_shift.update(dt, anim::linear); _shift.update(dt, anim::linear);
} }
moveByShift(); moveByShift();
return (dt < 1.);
} }
void Widget::hideSlow() { void Widget::hideSlow() {
@ -443,8 +448,8 @@ void Widget::updateOpacity() {
} }
void Widget::changeShift(int top) { void Widget::changeShift(int top) {
a_shift.start(top); _shift.start(top);
_a_shift.start(); _shiftAnimation.start();
} }
void Widget::updatePosition(QPoint startPosition, Direction shiftDirection) { void Widget::updatePosition(QPoint startPosition, Direction shiftDirection) {
@ -466,7 +471,7 @@ void Widget::updateGeometry(int x, int y, int width, int height) {
} }
void Widget::addToShift(int add) { void Widget::addToShift(int add) {
a_shift.add(add); _shift.add(add);
moveByShift(); moveByShift();
} }
@ -475,7 +480,7 @@ void Widget::moveByShift() {
} }
QPoint Widget::computePosition(int height) const { QPoint Widget::computePosition(int height) const {
auto realShift = qRound(a_shift.current()); auto realShift = qRound(_shift.current());
if (_direction == Direction::Up) { if (_direction == Direction::Up) {
realShift = -realShift - height; realShift = -realShift - height;
} }
@ -678,7 +683,7 @@ void Notification::updateNotifyDisplay() {
} }
if (!options.hideMessageText) { if (!options.hideMessageText) {
const HistoryItem *textCachedFor = 0; const HistoryItem *textCachedFor = nullptr;
Text itemTextCache(itemWidth); Text itemTextCache(itemWidth);
QRect r(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dialogsTextFont->height); QRect r(st::notifyPhotoPos.x() + st::notifyPhotoSize + st::notifyTextLeft, st::notifyItemTop + st::msgNameFont->height, itemWidth, 2 * st::dialogsTextFont->height);
if (_item) { if (_item) {

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "ui/effects/animations.h"
#include "base/timer.h" #include "base/timer.h"
namespace Ui { namespace Ui {
@ -115,7 +116,7 @@ public:
void updateOpacity(); void updateOpacity();
void changeShift(int top); void changeShift(int top);
int currentShift() const { int currentShift() const {
return a_shift.current(); return _shift.current();
} }
void updatePosition(QPoint startPosition, Direction shiftDirection); void updatePosition(QPoint startPosition, Direction shiftDirection);
void addToHeight(int add); void addToHeight(int add);
@ -139,7 +140,7 @@ private:
void destroyDelayed(); void destroyDelayed();
void moveByShift(); void moveByShift();
void hideAnimated(float64 duration, const anim::transition &func); void hideAnimated(float64 duration, const anim::transition &func);
void step_shift(float64 ms, bool timer); bool shiftAnimationCallback(crl::time now);
Manager *_manager = nullptr; Manager *_manager = nullptr;
@ -150,8 +151,8 @@ private:
QPoint _startPosition; QPoint _startPosition;
Direction _direction; Direction _direction;
anim::value a_shift; anim::value _shift;
BasicAnimation _a_shift; Ui::Animations::Basic _shiftAnimation;
}; };

View File

@ -30,7 +30,7 @@ protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
private: private:
void step(crl::time ms, bool timer); void animationStep();
Ui::InfiniteRadialAnimation _animation; Ui::InfiniteRadialAnimation _animation;
@ -38,7 +38,7 @@ private:
Progress::Progress(QWidget *parent) Progress::Progress(QWidget *parent)
: RpWidget(parent) : RpWidget(parent)
, _animation(animation(this, &Progress::step), st::connectingRadial) { , _animation([=] { animationStep(); }, st::connectingRadial) {
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_TransparentForMouseEvents);
resize(st::connectingRadial.size); resize(st::connectingRadial.size);
@ -58,8 +58,8 @@ void Progress::paintEvent(QPaintEvent *e) {
width()); width());
} }
void Progress::step(crl::time ms, bool timer) { void Progress::animationStep() {
if (timer && !anim::Disabled()) { if (!anim::Disabled()) {
update(); update();
} }
} }