Make date service messages clickable.
Open jump to date box when clicking on dates including floating date.
This commit is contained in:
		
							parent
							
								
									f663a2bf08
								
							
						
					
					
						commit
						ed3b2cc017
					
				
					 5 changed files with 126 additions and 34 deletions
				
			
		| 
						 | 
				
			
			@ -2293,7 +2293,7 @@ DialogsWidget::DialogsWidget(QWidget *parent) : TWidget(parent)
 | 
			
		|||
	subscribe(Adaptive::Changed(), [this] { updateForwardBar(); });
 | 
			
		||||
 | 
			
		||||
	_cancelSearch->setClickedCallback([this] { onCancelSearch(); });
 | 
			
		||||
	_jumpToDate->entity()->setClickedCallback([this] { if (_searchInPeer) App::main()->showJumpToDate(_searchInPeer); });
 | 
			
		||||
	_jumpToDate->entity()->setClickedCallback([this] { if (_searchInPeer) App::main()->showJumpToDate(_searchInPeer, QDate()); });
 | 
			
		||||
	_lockUnlock->setVisible(Global::LocalPasscode());
 | 
			
		||||
	subscribe(Global::RefLocalPasscodeChanged(), [this] { updateLockUnlockVisibility(); });
 | 
			
		||||
	_lockUnlock->setClickedCallback([this] {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ public:
 | 
			
		|||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
constexpr int ScrollDateHideTimeout = 1000;
 | 
			
		||||
constexpr auto kScrollDateHideTimeout = 1000;
 | 
			
		||||
 | 
			
		||||
ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() {
 | 
			
		||||
	return [](ChannelData *channel, MsgId msgId) {
 | 
			
		||||
| 
						 | 
				
			
			@ -119,6 +119,26 @@ ApiWrap::RequestMessageDataCallback replyEditMessageDataCallback() {
 | 
			
		|||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class DateClickHandler : public ClickHandler {
 | 
			
		||||
public:
 | 
			
		||||
	DateClickHandler(PeerData *peer, QDate date) : _peer(peer), _date(date) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void setDate(QDate date) {
 | 
			
		||||
		_date = date;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void onClick(Qt::MouseButton) const override {
 | 
			
		||||
		App::main()->showJumpToDate(_peer, _date);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	PeerData *_peer = nullptr;
 | 
			
		||||
	QDate _date;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // namespace
 | 
			
		||||
 | 
			
		||||
// flick scroll taken from http://qt-project.org/doc/qt-4.8/demos-embedded-anomaly-src-flickcharm-cpp.html
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +157,7 @@ HistoryInner::HistoryInner(HistoryWidget *historyWidget, Ui::ScrollArea *scroll,
 | 
			
		|||
 | 
			
		||||
	_trippleClickTimer.setSingleShot(true);
 | 
			
		||||
 | 
			
		||||
	connect(&_scrollDateHideTimer, SIGNAL(timeout()), this, SLOT(onScrollDateHide()));
 | 
			
		||||
	connect(&_scrollDateHideTimer, SIGNAL(timeout()), this, SLOT(onScrollDateHideByTimer()));
 | 
			
		||||
 | 
			
		||||
	notifyIsBotChanged();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -845,9 +865,13 @@ void HistoryInner::touchEvent(QTouchEvent *e) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void HistoryInner::mouseMoveEvent(QMouseEvent *e) {
 | 
			
		||||
	if (!(e->buttons() & (Qt::LeftButton | Qt::MiddleButton)) && _dragAction != NoDrag) {
 | 
			
		||||
	auto buttonsPressed = (e->buttons() & (Qt::LeftButton | Qt::MiddleButton));
 | 
			
		||||
	if (!buttonsPressed && _dragAction != NoDrag) {
 | 
			
		||||
		mouseReleaseEvent(e);
 | 
			
		||||
	}
 | 
			
		||||
	if (!buttonsPressed || ClickHandler::getPressed() == _scrollDateLink) {
 | 
			
		||||
		keepScrollDateForNow();
 | 
			
		||||
	}
 | 
			
		||||
	dragActionUpdate(e->globalPos());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1800,7 +1824,7 @@ void HistoryInner::onScrollDateCheck() {
 | 
			
		|||
	if (!newScrollDateItem) {
 | 
			
		||||
		_scrollDateLastItem = nullptr;
 | 
			
		||||
		_scrollDateLastItemTop = 0;
 | 
			
		||||
		onScrollDateHide();
 | 
			
		||||
		scrollDateHide();
 | 
			
		||||
	} else if (newScrollDateItem != _scrollDateLastItem || newScrollDateItemTop != _scrollDateLastItemTop) {
 | 
			
		||||
		// Show scroll date only if it is not the initial onScroll() event (with empty _scrollDateLastItem).
 | 
			
		||||
		if (_scrollDateLastItem && !_scrollDateShown) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1808,17 +1832,30 @@ void HistoryInner::onScrollDateCheck() {
 | 
			
		|||
		}
 | 
			
		||||
		_scrollDateLastItem = newScrollDateItem;
 | 
			
		||||
		_scrollDateLastItemTop = newScrollDateItemTop;
 | 
			
		||||
		_scrollDateHideTimer.start(ScrollDateHideTimeout);
 | 
			
		||||
		_scrollDateHideTimer.start(kScrollDateHideTimeout);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HistoryInner::onScrollDateHide() {
 | 
			
		||||
void HistoryInner::onScrollDateHideByTimer() {
 | 
			
		||||
	_scrollDateHideTimer.stop();
 | 
			
		||||
	if (ClickHandler::getPressed() != _scrollDateLink) {
 | 
			
		||||
		scrollDateHide();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HistoryInner::scrollDateHide() {
 | 
			
		||||
	if (_scrollDateShown) {
 | 
			
		||||
		toggleScrollDateShown();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HistoryInner::keepScrollDateForNow() {
 | 
			
		||||
	if (!_scrollDateShown && _scrollDateLastItem && _scrollDateOpacity.animating()) {
 | 
			
		||||
		toggleScrollDateShown();
 | 
			
		||||
	}
 | 
			
		||||
	_scrollDateHideTimer.start(kScrollDateHideTimeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HistoryInner::toggleScrollDateShown() {
 | 
			
		||||
	_scrollDateShown = !_scrollDateShown;
 | 
			
		||||
	auto from = _scrollDateShown ? 0. : 1.;
 | 
			
		||||
| 
						 | 
				
			
			@ -2086,31 +2123,82 @@ void HistoryInner::onUpdateSelected() {
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		HistoryStateRequest request;
 | 
			
		||||
		if (_dragAction == Selecting) {
 | 
			
		||||
			request.flags |= Text::StateRequest::Flag::LookupSymbol;
 | 
			
		||||
		} else {
 | 
			
		||||
			selectingText = false;
 | 
			
		||||
		}
 | 
			
		||||
		dragState = item->getState(m.x(), m.y(), request);
 | 
			
		||||
		lnkhost = item;
 | 
			
		||||
		if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) {
 | 
			
		||||
			if (auto msg = item->toHistoryMessage()) {
 | 
			
		||||
				if (msg->hasFromPhoto()) {
 | 
			
		||||
					enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
 | 
			
		||||
						// stop enumeration if the userpic is below our point
 | 
			
		||||
						if (userpicTop > point.y()) {
 | 
			
		||||
							return false;
 | 
			
		||||
						}
 | 
			
		||||
		auto dateHeight = st::msgServicePadding.bottom() + st::msgServiceFont->height + st::msgServicePadding.top();
 | 
			
		||||
		auto scrollDateOpacity = _scrollDateOpacity.current(_scrollDateShown ? 1. : 0.);
 | 
			
		||||
		enumerateDates([this, &dragState, &lnkhost, &point, scrollDateOpacity, dateHeight/*, lastDate, showFloatingBefore*/](HistoryItem *item, int itemtop, int dateTop) {
 | 
			
		||||
			// stop enumeration if the date is above our point
 | 
			
		||||
			if (dateTop + dateHeight <= point.y()) {
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
						// stop enumeration if we've found a userpic under the cursor
 | 
			
		||||
						if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
 | 
			
		||||
							dragState.link = message->from()->openLink();
 | 
			
		||||
							lnkhost = message;
 | 
			
		||||
							return false;
 | 
			
		||||
			bool displayDate = item->displayDate();
 | 
			
		||||
			bool dateInPlace = displayDate;
 | 
			
		||||
			if (dateInPlace) {
 | 
			
		||||
				int correctDateTop = itemtop + st::msgServiceMargin.top();
 | 
			
		||||
				dateInPlace = (dateTop < correctDateTop + dateHeight);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// stop enumeration if we've found a date under the cursor
 | 
			
		||||
			if (dateTop <= point.y()) {
 | 
			
		||||
				auto opacity = (dateInPlace/* || noFloatingDate*/) ? 1. : scrollDateOpacity;
 | 
			
		||||
				if (opacity > 0.) {
 | 
			
		||||
					auto dateWidth = 0;
 | 
			
		||||
					if (auto date = item->Get<HistoryMessageDate>()) {
 | 
			
		||||
						dateWidth = date->_width;
 | 
			
		||||
					} else {
 | 
			
		||||
						dateWidth = st::msgServiceFont->width(langDayOfMonthFull(item->date.date()));
 | 
			
		||||
					}
 | 
			
		||||
					dateWidth += st::msgServicePadding.left() + st::msgServicePadding.right();
 | 
			
		||||
					auto dateLeft = st::msgServiceMargin.left();
 | 
			
		||||
					auto maxwidth = item->history()->width;
 | 
			
		||||
					if (Adaptive::ChatWide()) {
 | 
			
		||||
						maxwidth = qMin(maxwidth, int32(st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left()));
 | 
			
		||||
					}
 | 
			
		||||
					auto widthForDate = maxwidth - st::msgServiceMargin.left() - st::msgServiceMargin.left();
 | 
			
		||||
 | 
			
		||||
					dateLeft += (widthForDate - dateWidth) / 2;
 | 
			
		||||
 | 
			
		||||
					if (point.x() >= dateLeft && point.x() < dateLeft + dateWidth) {
 | 
			
		||||
						if (!_scrollDateLink) {
 | 
			
		||||
							_scrollDateLink = MakeShared<DateClickHandler>(item->history()->peer, item->date.date());
 | 
			
		||||
						} else {
 | 
			
		||||
							static_cast<DateClickHandler*>(_scrollDateLink.data())->setDate(item->date.date());
 | 
			
		||||
						}
 | 
			
		||||
						return true;
 | 
			
		||||
					});
 | 
			
		||||
						dragState.link = _scrollDateLink;
 | 
			
		||||
						lnkhost = item;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		});
 | 
			
		||||
		if (!dragState.link) {
 | 
			
		||||
			HistoryStateRequest request;
 | 
			
		||||
			if (_dragAction == Selecting) {
 | 
			
		||||
				request.flags |= Text::StateRequest::Flag::LookupSymbol;
 | 
			
		||||
			} else {
 | 
			
		||||
				selectingText = false;
 | 
			
		||||
			}
 | 
			
		||||
			dragState = item->getState(m.x(), m.y(), request);
 | 
			
		||||
			lnkhost = item;
 | 
			
		||||
			if (!dragState.link && m.x() >= st::historyPhotoLeft && m.x() < st::historyPhotoLeft + st::msgPhotoSize) {
 | 
			
		||||
				if (auto msg = item->toHistoryMessage()) {
 | 
			
		||||
					if (msg->hasFromPhoto()) {
 | 
			
		||||
						enumerateUserpics([&dragState, &lnkhost, &point](HistoryMessage *message, int userpicTop) -> bool {
 | 
			
		||||
							// stop enumeration if the userpic is below our point
 | 
			
		||||
							if (userpicTop > point.y()) {
 | 
			
		||||
								return false;
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							// stop enumeration if we've found a userpic under the cursor
 | 
			
		||||
							if (point.y() >= userpicTop && point.y() < userpicTop + st::msgPhotoSize) {
 | 
			
		||||
								dragState.link = message->from()->openLink();
 | 
			
		||||
								lnkhost = message;
 | 
			
		||||
								return false;
 | 
			
		||||
							}
 | 
			
		||||
							return true;
 | 
			
		||||
						});
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -152,7 +152,7 @@ public slots:
 | 
			
		|||
 | 
			
		||||
private slots:
 | 
			
		||||
	void onScrollDateCheck();
 | 
			
		||||
	void onScrollDateHide();
 | 
			
		||||
	void onScrollDateHideByTimer();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void itemRemoved(HistoryItem *item);
 | 
			
		||||
| 
						 | 
				
			
			@ -174,6 +174,8 @@ private:
 | 
			
		|||
	void toggleScrollDateShown();
 | 
			
		||||
	void repaintScrollDateCallback();
 | 
			
		||||
	bool displayScrollDate() const;
 | 
			
		||||
	void scrollDateHide();
 | 
			
		||||
	void keepScrollDateForNow();
 | 
			
		||||
 | 
			
		||||
	PeerData *_peer = nullptr;
 | 
			
		||||
	History *_migrated = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -278,6 +280,7 @@ private:
 | 
			
		|||
	SingleTimer _scrollDateHideTimer;
 | 
			
		||||
	HistoryItem *_scrollDateLastItem = nullptr;
 | 
			
		||||
	int _scrollDateLastItemTop = 0;
 | 
			
		||||
	ClickHandlerPtr _scrollDateLink;
 | 
			
		||||
 | 
			
		||||
	enum class EnumItemsDirection {
 | 
			
		||||
		TopToBottom,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2759,7 +2759,7 @@ void MainWidget::dlgUpdated(PeerData *peer, MsgId msgId) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWidget::showJumpToDate(PeerData *peer) {
 | 
			
		||||
void MainWidget::showJumpToDate(PeerData *peer, QDate requestedDate) {
 | 
			
		||||
	t_assert(peer != nullptr);
 | 
			
		||||
	auto currentPeerDate = [peer] {
 | 
			
		||||
		if (auto history = App::historyLoaded(peer)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2798,7 +2798,8 @@ void MainWidget::showJumpToDate(PeerData *peer) {
 | 
			
		|||
		}
 | 
			
		||||
		return QDate(2013, 8, 1); // Telegram was launched in August 2013 :)
 | 
			
		||||
	};
 | 
			
		||||
	auto highlighted = currentPeerDate(), month = highlighted;
 | 
			
		||||
	auto highlighted = requestedDate.isNull() ? currentPeerDate() : requestedDate;
 | 
			
		||||
	auto month = highlighted;
 | 
			
		||||
	auto box = Box<CalendarBox>(month, highlighted, [this, peer](const QDate &date) { jumpToDate(peer, date); });
 | 
			
		||||
	box->setMinDate(minPeerDate());
 | 
			
		||||
	box->setMaxDate(maxPeerDate());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ public:
 | 
			
		|||
	void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
 | 
			
		||||
	void dlgUpdated(PeerData *peer, MsgId msgId);
 | 
			
		||||
 | 
			
		||||
	void showJumpToDate(PeerData *peer);
 | 
			
		||||
	void showJumpToDate(PeerData *peer, QDate requestedDate);
 | 
			
		||||
 | 
			
		||||
	void windowShown();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue