diff --git a/Telegram/SourceFiles/boxes/stickersetbox.cpp b/Telegram/SourceFiles/boxes/stickersetbox.cpp index 5f094e7951..93b1bbb96f 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.cpp +++ b/Telegram/SourceFiles/boxes/stickersetbox.cpp @@ -39,7 +39,7 @@ constexpr int kArchivedLimitPerPage = 30; } // namespace -StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget() +StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : ScrolledWidget() , _input(set) { connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update())); switch (set.type()) { @@ -49,6 +49,8 @@ StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget() MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&StickerSetInner::gotSet), rpcFail(&StickerSetInner::failedSet)); App::main()->updateStickers(); + setMouseTracking(true); + _previewTimer.setSingleShot(true); connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview())); } @@ -56,15 +58,20 @@ StickerSetInner::StickerSetInner(const MTPInputStickerSet &set) : TWidget() void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { _pack.clear(); _emoji.clear(); + _packOvers.clear(); + _selected = -1; + setCursor(style::cur_default); if (set.type() == mtpc_messages_stickerSet) { auto &d(set.c_messages_stickerSet()); auto &v(d.vdocuments.c_vector().v); _pack.reserve(v.size()); + _packOvers.reserve(v.size()); for (int i = 0, l = v.size(); i < l; ++i) { auto doc = App::feedDocument(v.at(i)); if (!doc || !doc->sticker()) continue; _pack.push_back(doc); + _packOvers.push_back(FloatAnimation()); } auto &packs(d.vpacks.c_vector().v); for (int i = 0, l = packs.size(); i < l; ++i) { @@ -113,6 +120,8 @@ void StickerSetInner::gotSet(const MTPmessages_StickerSet &set) { } _loaded = true; + updateSelected(); + emit updateButtons(); } @@ -188,15 +197,16 @@ bool StickerSetInner::installFail(const RPCError &error) { } void StickerSetInner::mousePressEvent(QMouseEvent *e) { - int32 index = stickerFromGlobalPos(e->globalPos()); + int index = stickerFromGlobalPos(e->globalPos()); if (index >= 0 && index < _pack.size()) { _previewTimer.start(QApplication::startDragTime()); } } void StickerSetInner::mouseMoveEvent(QMouseEvent *e) { + updateSelected(); if (_previewShown >= 0) { - int32 index = stickerFromGlobalPos(e->globalPos()); + int index = stickerFromGlobalPos(e->globalPos()); if (index >= 0 && index < _pack.size() && index != _previewShown) { _previewShown = index; Ui::showMediaPreview(_pack.at(_previewShown)); @@ -205,11 +215,47 @@ void StickerSetInner::mouseMoveEvent(QMouseEvent *e) { } void StickerSetInner::mouseReleaseEvent(QMouseEvent *e) { - _previewTimer.stop(); + if (_previewShown >= 0) { + _previewShown = -1; + return; + } + if (_previewTimer.isActive()) { + _previewTimer.stop(); + int index = stickerFromGlobalPos(e->globalPos()); + if (index >= 0 && index < _pack.size()) { + if (auto main = App::main()) { + if (main->onSendSticker(_pack.at(index))) { + Ui::hideSettingsAndLayer(); + } + } + } + } +} + +void StickerSetInner::updateSelected() { + auto index = stickerFromGlobalPos(QCursor::pos()); + if (index != _selected) { + startOverAnimation(_selected, 1., 0.); + _selected = index; + startOverAnimation(_selected, 0., 1.); + setCursor(_selected >= 0 ? style::cur_pointer : style::cur_default); + } +} + +void StickerSetInner::startOverAnimation(int index, float64 from, float64 to) { + if (index >= 0 && index < _packOvers.size()) { + START_ANIMATION(_packOvers[index], func([this, index]() { + int row = index / StickerPanPerRow; + int column = index % StickerPanPerRow; + int left = st::stickersPadding.left() + column * st::stickersSize.width(); + int top = st::stickersPadding.top() + row * st::stickersSize.height(); + rtlupdate(left, top, st::stickersSize.width(), st::stickersSize.height()); + }), from, to, st::emojiPanDuration, anim::linear); + } } void StickerSetInner::onPreview() { - int32 index = stickerFromGlobalPos(QCursor::pos()); + int index = stickerFromGlobalPos(QCursor::pos()); if (index >= 0 && index < _pack.size()) { _previewShown = index; Ui::showMediaPreview(_pack.at(_previewShown)); @@ -241,10 +287,19 @@ void StickerSetInner::paintEvent(QPaintEvent *e) { for (int32 j = 0; j < StickerPanPerRow; ++j) { int32 index = i * StickerPanPerRow + j; if (index >= _pack.size()) break; + t_assert(index < _packOvers.size()); DocumentData *doc = _pack.at(index); QPoint pos(st::stickersPadding.left() + j * st::stickersSize.width(), st::stickersPadding.top() + i * st::stickersSize.height()); + if (auto over = _packOvers[index].current((index == _selected) ? 1. : 0.)) { + p.setOpacity(over); + QPoint tl(pos); + if (rtl()) tl.setX(width() - tl.x() - st::stickersSize.width()); + App::roundRect(p, QRect(tl, st::stickersSize), st::emojiPanHover, StickerHoverCorners); + p.setOpacity(1); + + } bool goodThumb = !doc->thumb->isNull() && ((doc->thumb->width() >= 128) || (doc->thumb->height() >= 128)); if (goodThumb) { doc->thumb->load(); @@ -272,10 +327,9 @@ void StickerSetInner::paintEvent(QPaintEvent *e) { } } -void StickerSetInner::setScrollBottom(int32 bottom) { - if (bottom == _bottom) return; - - _bottom = bottom; +void StickerSetInner::setVisibleTopBottom(int visibleTop, int visibleBottom) { + _visibleTop = visibleTop; + _visibleBottom = visibleBottom; } bool StickerSetInner::loaded() const { @@ -364,7 +418,9 @@ void StickerSetBox::onUpdateButtons() { } void StickerSetBox::onScroll() { - _inner.setScrollBottom(scrollArea()->scrollTop() + scrollArea()->height()); + auto scroll = scrollArea(); + auto scrollTop = scroll->scrollTop(); + _inner.setVisibleTopBottom(scrollTop, scrollTop + scroll->height()); } void StickerSetBox::showAll() { diff --git a/Telegram/SourceFiles/boxes/stickersetbox.h b/Telegram/SourceFiles/boxes/stickersetbox.h index 99bc272b9f..d5c4d2f81c 100644 --- a/Telegram/SourceFiles/boxes/stickersetbox.h +++ b/Telegram/SourceFiles/boxes/stickersetbox.h @@ -24,30 +24,30 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org class ConfirmBox; -class StickerSetInner : public TWidget, public RPCSender { +class StickerSetInner : public ScrolledWidget, public RPCSender { Q_OBJECT public: StickerSetInner(const MTPInputStickerSet &set); - void mousePressEvent(QMouseEvent *e); - void mouseMoveEvent(QMouseEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - - void paintEvent(QPaintEvent *e); - bool loaded() const; int32 notInstalled() const; bool official() const; QString title() const; QString shortName() const; - void setScrollBottom(int32 bottom); + void setVisibleTopBottom(int visibleTop, int visibleBottom) override; void install(); ~StickerSetInner(); -public slots: +protected: + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void paintEvent(QPaintEvent *e) override; + +private slots: void onPreview(); signals: @@ -55,7 +55,9 @@ signals: void installed(uint64 id); private: - int32 stickerFromGlobalPos(const QPoint &p) const; + void updateSelected(); + void startOverAnimation(int index, float64 from, float64 to); + int stickerFromGlobalPos(const QPoint &p) const; void gotSet(const MTPmessages_StickerSet &set); bool failedSet(const RPCError &error); @@ -63,6 +65,7 @@ private: void installDone(const MTPmessages_StickerSetInstallResult &result); bool installFail(const RPCError &error); + QVector _packOvers; StickerPack _pack; StickersByEmojiMap _emoji; bool _loaded = false; @@ -73,13 +76,17 @@ private: int32 _setHash = 0; MTPDstickerSet::Flags _setFlags = 0; - int32 _bottom = 0; + int _visibleTop = 0; + int _visibleBottom = 0; MTPInputStickerSet _input; mtpRequestId _installRequest = 0; + int _selected = -1; + QTimer _previewTimer; - int32 _previewShown = -1; + int _previewShown = -1; + }; class StickerSetBox : public ScrollableBox, public RPCSender { diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 604c6c204e..adaadf6a0a 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -7458,8 +7458,8 @@ void HistoryWidget::onFieldTabbed() { } } -void HistoryWidget::onStickerSend(DocumentData *sticker) { - sendExistingDocument(sticker, QString()); +bool HistoryWidget::onStickerSend(DocumentData *sticker) { + return sendExistingDocument(sticker, QString()); } void HistoryWidget::onPhotoSend(PhotoData *photo) { @@ -7646,14 +7646,14 @@ void HistoryWidget::ReplyEditMessageDataCallback::call(ChannelData *channel, Msg } } -void HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &caption) { +bool HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &caption) { if (!_history || !doc || !canSendMessages(_peer)) { - return; + return false; } MTPInputDocument mtpInput = doc->mtpInput(); if (mtpInput.type() == mtpc_inputDocumentEmpty) { - return; + return false; } App::main()->readServerHistory(_history); @@ -7707,6 +7707,7 @@ void HistoryWidget::sendExistingDocument(DocumentData *doc, const QString &capti if (!_emojiPan->isHidden()) _emojiPan->hideStart(); _field.setFocus(); + return true; } void HistoryWidget::sendExistingPhoto(PhotoData *photo, const QString &caption) { diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h index 7d41334878..e55451ae19 100644 --- a/Telegram/SourceFiles/historywidget.h +++ b/Telegram/SourceFiles/historywidget.h @@ -803,7 +803,7 @@ public slots: void onTextChange(); void onFieldTabbed(); - void onStickerSend(DocumentData *sticker); + bool onStickerSend(DocumentData *sticker); void onPhotoSend(PhotoData *photo); void onInlineResultSend(InlineBots::Result *result, UserData *bot); @@ -913,7 +913,7 @@ private: void call(ChannelData *channel, MsgId msgId) const override; }; - void sendExistingDocument(DocumentData *doc, const QString &caption); + bool sendExistingDocument(DocumentData *doc, const QString &caption); void sendExistingPhoto(PhotoData *photo, const QString &caption); void drawField(Painter &p, const QRect &rect); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index cde8d0048d..5bedb07b1c 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -1712,6 +1712,10 @@ void MainWidget::onShareContactCancel() { _history->cancelShareContact(); } +bool MainWidget::onSendSticker(DocumentData *document) { + return _history->onStickerSend(document); +} + void MainWidget::dialogsCancelled() { if (_hider) { _hider->startHide(); diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 8925f7091c..9394949670 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -212,6 +212,7 @@ public: void onSendFileCancel(const FileLoadResultPtr &file); void onShareContactConfirm(const QString &phone, const QString &fname, const QString &lname, MsgId replyTo, bool ctrlShiftEnter); void onShareContactCancel(); + bool onSendSticker(DocumentData *sticker); void destroyData(); void updateOnlineDisplayIn(int32 msecs);