From 59574532c6299f7f9313aefa79f1ff3a9f3a8b5e Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Mon, 15 Jul 2019 16:30:17 +0200
Subject: [PATCH] Add slowmode send message button state.

---
 Telegram/SourceFiles/ui/special_buttons.cpp | 115 ++++++++++++++------
 Telegram/SourceFiles/ui/special_buttons.h   |  15 +++
 2 files changed, 99 insertions(+), 31 deletions(-)

diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp
index cca32ecf9..d68ddf229 100644
--- a/Telegram/SourceFiles/ui/special_buttons.cpp
+++ b/Telegram/SourceFiles/ui/special_buttons.cpp
@@ -288,12 +288,19 @@ SendButton::SendButton(QWidget *parent) : RippleButton(parent, st::historyReplyC
 }
 
 void SendButton::setType(Type type) {
+	Expects(isSlowmode() || type != Type::Slowmode);
+
+	if (isSlowmode() && type != Type::Slowmode) {
+		_afterSlowmodeType = type;
+		return;
+	}
 	if (_type != type) {
 		_contentFrom = grabContent();
 		_type = type;
 		_a_typeChanged.stop();
 		_contentTo = grabContent();
-		_a_typeChanged.start([this] { update(); }, 0., 1., st::historyRecordVoiceDuration);
+		_a_typeChanged.start([=] { update(); }, 0., 1., st::historyRecordVoiceDuration);
+		setPointerCursor(_type != Type::Slowmode);
 		update();
 	}
 	if (_type != Type::Record) {
@@ -310,6 +317,20 @@ void SendButton::setRecordActive(bool recordActive) {
 	}
 }
 
+void SendButton::setSlowmodeDelay(int seconds) {
+	Expects(seconds >= 0 && seconds < kSlowmodeDelayLimit);
+
+	if (_slowmodeDelay == seconds) {
+		return;
+	}
+	_slowmodeDelay = seconds;
+	_slowmodeDelayText = isSlowmode()
+		? qsl("%1:%2").arg(seconds / 60).arg(seconds % 60, 2, 10, QChar('0'))
+		: QString();
+	setType(isSlowmode() ? Type::Slowmode : _afterSlowmodeType);
+	update();
+}
+
 void SendButton::finishAnimating() {
 	_a_typeChanged.stop();
 	_a_recordActive.stop();
@@ -341,37 +362,65 @@ void SendButton::paintEvent(QPaintEvent *e) {
 		auto shownWidth = anim::interpolate((1 - kWideScale) / 2 * width(), 0, changed);
 		auto shownHeight = anim::interpolate((1 - kWideScale) / 2 * height(), 0, changed);
 		p.drawPixmap(targetRect.marginsAdded(QMargins(shownWidth, shownHeight, shownWidth, shownHeight)), _contentTo);
-	} else if (_type == Type::Record) {
-		auto recordActive = recordActiveRatio();
-		auto rippleColor = anim::color(st::historyAttachEmoji.ripple.color, st::historyRecordVoiceRippleBgActive, recordActive);
-		paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y(), &rippleColor);
-
-		auto fastIcon = [&] {
-			if (recordActive == 1.) {
-				return &st::historyRecordVoiceActive;
-			} else if (over) {
-				return &st::historyRecordVoiceOver;
-			}
-			return &st::historyRecordVoice;
-		};
-		fastIcon()->paintInCenter(p, rect());
-		if (recordActive > 0. && recordActive < 1.) {
-			p.setOpacity(recordActive);
-			st::historyRecordVoiceActive.paintInCenter(p, rect());
-			p.setOpacity(1.);
-		}
-	} else if (_type == Type::Save) {
-		auto &saveIcon = over ? st::historyEditSaveIconOver : st::historyEditSaveIcon;
-		saveIcon.paint(p, st::historySendIconPosition, width());
-	} else if (_type == Type::Cancel) {
-		paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y());
-
-		auto &cancelIcon = over ? st::historyReplyCancelIconOver : st::historyReplyCancelIcon;
-		cancelIcon.paintInCenter(p, rect());
-	} else {
-		auto &sendIcon = over ? st::historySendIconOver : st::historySendIcon;
-		sendIcon.paint(p, st::historySendIconPosition, width());
+		return;
 	}
+	switch (_type) {
+	case Type::Record: paintRecord(p, over); break;
+	case Type::Save: paintSave(p, over); break;
+	case Type::Cancel: paintCancel(p, over); break;
+	case Type::Send: paintSend(p, over); break;
+	case Type::Slowmode: paintSlowmode(p); break;
+	}
+}
+
+void SendButton::paintRecord(Painter &p, bool over) {
+	auto recordActive = recordActiveRatio();
+	auto rippleColor = anim::color(st::historyAttachEmoji.ripple.color, st::historyRecordVoiceRippleBgActive, recordActive);
+	paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y(), &rippleColor);
+
+	auto fastIcon = [&] {
+		if (recordActive == 1.) {
+			return &st::historyRecordVoiceActive;
+		} else if (over) {
+			return &st::historyRecordVoiceOver;
+		}
+		return &st::historyRecordVoice;
+	};
+	fastIcon()->paintInCenter(p, rect());
+	if (recordActive > 0. && recordActive < 1.) {
+		p.setOpacity(recordActive);
+		st::historyRecordVoiceActive.paintInCenter(p, rect());
+		p.setOpacity(1.);
+	}
+}
+
+void SendButton::paintSave(Painter &p, bool over) {
+	const auto &saveIcon = over
+		? st::historyEditSaveIconOver
+		: st::historyEditSaveIcon;
+	saveIcon.paint(p, st::historySendIconPosition, width());
+}
+
+void SendButton::paintCancel(Painter &p, bool over) {
+	paintRipple(p, (width() - st::historyAttachEmoji.rippleAreaSize) / 2, st::historyAttachEmoji.rippleAreaPosition.y());
+
+	const auto &cancelIcon = over
+		? st::historyReplyCancelIconOver
+		: st::historyReplyCancelIcon;
+	cancelIcon.paintInCenter(p, rect());
+}
+
+void SendButton::paintSend(Painter &p, bool over) {
+	const auto &sendIcon = over
+		? st::historySendIconOver
+		: st::historySendIcon;
+	sendIcon.paint(p, st::historySendIconPosition, width());
+}
+
+void SendButton::paintSlowmode(Painter &p) {
+	p.setFont(st::normalFont);
+	p.setPen(st::windowSubTextFg);
+	p.drawText(rect(), _slowmodeDelayText, style::al_center);
 }
 
 void SendButton::onStateChanged(State was, StateChangeSource source) {
@@ -395,6 +444,10 @@ void SendButton::onStateChanged(State was, StateChangeSource source) {
 	}
 }
 
+bool SendButton::isSlowmode() const {
+	return (_slowmodeDelay > 0);
+}
+
 QPixmap SendButton::grabContent() {
 	auto result = QImage(kWideScale * size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
 	result.setDevicePixelRatio(cRetinaFactor());
diff --git a/Telegram/SourceFiles/ui/special_buttons.h b/Telegram/SourceFiles/ui/special_buttons.h
index 1a07e5ca0..4261615c2 100644
--- a/Telegram/SourceFiles/ui/special_buttons.h
+++ b/Telegram/SourceFiles/ui/special_buttons.h
@@ -78,17 +78,21 @@ class SendButton : public RippleButton {
 public:
 	SendButton(QWidget *parent);
 
+	static constexpr auto kSlowmodeDelayLimit = 100 * 60;
+
 	enum class Type {
 		Send,
 		Save,
 		Record,
 		Cancel,
+		Slowmode,
 	};
 	Type type() const {
 		return _type;
 	}
 	void setType(Type state);
 	void setRecordActive(bool recordActive);
+	void setSlowmodeDelay(int seconds);
 	void finishAnimating();
 
 	void setRecordStartCallback(Fn<void()> callback) {
@@ -119,8 +123,16 @@ protected:
 private:
 	void recordAnimationCallback();
 	QPixmap grabContent();
+	bool isSlowmode() const;
+
+	void paintRecord(Painter &p, bool over);
+	void paintSave(Painter &p, bool over);
+	void paintCancel(Painter &p, bool over);
+	void paintSend(Painter &p, bool over);
+	void paintSlowmode(Painter &p);
 
 	Type _type = Type::Send;
+	Type _afterSlowmodeType = Type::Send;
 	bool _recordActive = false;
 	QPixmap _contentFrom, _contentTo;
 
@@ -133,6 +145,9 @@ private:
 	Fn<void(QPoint globalPos)> _recordUpdateCallback;
 	Fn<void()> _recordAnimationCallback;
 
+	int _slowmodeDelay = 0;
+	QString _slowmodeDelayText;
+
 };
 
 class UserpicButton : public RippleButton {