mirror of https://github.com/procxx/kepka.git
				
				
				
			Use new animations engine in all Basic-s.
This commit is contained in:
		
							parent
							
								
									cd3c1c6dc0
								
							
						
					
					
						commit
						a6e96f9a28
					
				|  | @ -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()); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
|  |  | ||||||
|  | @ -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 }; | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
|  | @ -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 { | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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 ®ion, 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(); | ||||||
|  |  | ||||||
|  | @ -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.
 | ||||||
|  |  | ||||||
|  | @ -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) { | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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> { | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  | 		}); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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( | ||||||
|  |  | ||||||
|  | @ -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) { | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -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()); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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, | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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) { | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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 ¬ification, _notifications) { | 	for (const auto ¬ification : _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) { | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue