Make date service messages clickable.

Open jump to date box when clicking on dates including floating date.
This commit is contained in:
John Preston 2017-03-07 20:45:08 +03:00
parent f663a2bf08
commit ed3b2cc017
5 changed files with 126 additions and 34 deletions

View File

@ -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] {

View File

@ -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;
});
}
}
}
}

View File

@ -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,

View File

@ -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());

View File

@ -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();