diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 4909768bb..ded6f8b6f 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "chat_helpers/gifs_list_widget.h" +#include "api/api_common.h" #include "base/const_string.h" #include "data/data_photo.h" #include "data/data_document.h" @@ -16,8 +17,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document_media.h" #include "data/stickers/data_stickers.h" +#include "chat_helpers/message_field.h" // FillSendMenu #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" +#include "ui/widgets/popup_menu.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image.h" #include "boxes/stickers_box.h" @@ -28,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "window/window_session_controller.h" #include "history/view/history_view_cursor_state.h" +#include "history/view/history_view_schedule_box.h" #include "app.h" #include "styles/style_chat_helpers.h" @@ -343,6 +347,32 @@ void GifsListWidget::mousePressEvent(QMouseEvent *e) { _previewTimer.callOnce(QApplication::startDragTime()); } +void GifsListWidget::fillContextMenu(not_null menu) { + if (_selected < 0 || _pressed >= 0) { + return; + } + const auto row = _selected / MatrixRowShift; + const auto column = _selected % MatrixRowShift; + + const auto send = [=](Api::SendOptions options) { + selectInlineResult(row, column, options, true); + }; + const auto silent = [=] { send({ .silent = true }); }; + const auto schedule = [=] { + Ui::show( + HistoryView::PrepareScheduleBox( + this, + SendMenuType::Scheduled, + [=](Api::SendOptions options) { send(options); }), + Ui::LayerOption::KeepOther); + }; + FillSendMenu( + menu, + [] { return SendMenuType::Scheduled; }, + silent, + schedule); +} + void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) { _previewTimer.cancel(); @@ -370,17 +400,25 @@ void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) { } void GifsListWidget::selectInlineResult(int row, int column) { + selectInlineResult(row, column, Api::SendOptions()); +} + +void GifsListWidget::selectInlineResult( + int row, + int column, + Api::SendOptions options, + bool forceSend) { if (row >= _rows.size() || column >= _rows[row].items.size()) { return; } - const auto ctrl = (QGuiApplication::keyboardModifiers() + forceSend |= (QGuiApplication::keyboardModifiers() == Qt::ControlModifier); auto item = _rows[row].items[column]; if (const auto photo = item->getPhoto()) { using Data::PhotoSize; const auto media = photo->activeMediaView(); - if (ctrl + if (forceSend || (media && media->image(PhotoSize::Thumbnail)) || (media && media->image(PhotoSize::Large))) { _photoChosen.fire_copy(photo); @@ -390,8 +428,10 @@ void GifsListWidget::selectInlineResult(int row, int column) { } else if (const auto document = item->getDocument()) { const auto media = document->activeMediaView(); const auto preview = Data::VideoPreviewState(media.get()); - if (ctrl || (media && preview.loaded())) { - _fileChosen.fire_copy({ .document = document }); + if (forceSend || (media && preview.loaded())) { + _fileChosen.fire_copy({ + .document = document, + .options = options }); } else if (!preview.usingThumbnail()) { if (preview.loading()) { document->cancel(); diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h index 84925eb1c..366e1279c 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.h @@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include +namespace Api { +struct SendOptions; +} // namespace Api + namespace InlineBots { namespace Layout { class ItemBase; @@ -22,6 +26,7 @@ class Result; } // namespace InlineBots namespace Ui { +class PopupMenu; class RoundButton; } // namespace Ui @@ -66,6 +71,8 @@ public: void cancelled(); rpl::producer<> cancelRequests() const; + void fillContextMenu(not_null menu) override; + ~GifsListWidget(); protected: @@ -158,6 +165,11 @@ private: int validateExistingInlineRows(const InlineResults &results); void selectInlineResult(int row, int column); + void selectInlineResult( + int row, + int column, + Api::SendOptions options, + bool forceSend = false); Footer *_footer = nullptr; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index ef0ba93f0..896949164 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -14,8 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_cloud_file.h" #include "data/data_changes.h" +#include "chat_helpers/message_field.h" // FillSendMenu #include "chat_helpers/stickers_lottie.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/popup_menu.h" #include "ui/effects/animations.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image.h" @@ -24,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lottie/lottie_animation.h" #include "boxes/stickers_box.h" #include "inline_bots/inline_bot_result.h" +#include "history/view/history_view_schedule_box.h" #include "storage/storage_account.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -2043,6 +2046,40 @@ QPoint StickersListWidget::buttonRippleTopLeft(int section) const { return myrtlrect(removeButtonRect(section)).topLeft() + st::stickerPanRemoveSet.rippleAreaPosition; } +void StickersListWidget::fillContextMenu(not_null menu) { + auto selected = _selected; + auto &sets = shownSets(); + if (!selected || _pressed) { + return; + } + if (auto sticker = base::get_if(&selected)) { + Assert(sticker->section >= 0 && sticker->section < sets.size()); + auto &set = sets[sticker->section]; + Assert(sticker->index >= 0 && sticker->index < set.stickers.size()); + + const auto document = set.stickers[sticker->index].document; + const auto send = [=](Api::SendOptions options) { + _chosen.fire_copy({ + .document = document, + .options = options }); + }; + const auto silent = [=] { send({ .silent = true }); }; + const auto schedule = [=] { + checkHideWithBox(Ui::show( + HistoryView::PrepareScheduleBox( + this, + SendMenuType::Scheduled, + [=](Api::SendOptions options) { send(options); }), + Ui::LayerOption::KeepOther).data()); + }; + FillSendMenu( + menu, + [] { return SendMenuType::Scheduled; }, + silent, + schedule); + } +} + void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { _previewTimer.cancel(); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 9238cfe32..2e7adc729 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -22,6 +22,7 @@ class SessionController; namespace Ui { class LinkButton; +class PopupMenu; class RippleAnimation; class BoxContent; } // namespace Ui @@ -82,6 +83,8 @@ public: std::shared_ptr getLottieRenderer(); + void fillContextMenu(not_null menu) override; + ~StickersListWidget(); protected: diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp index 8fba46c57..86c5e97ec 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.cpp @@ -364,6 +364,10 @@ void TabbedPanel::hideAnimated() { } else { startOpacityAnimation(true); } + + // There is no reason to worry about the message scheduling box + // while it moves the user to the separate scheduled section. + _shouldFinishHide = _selector->hasMenu(); } void TabbedPanel::toggleAnimated() { @@ -380,6 +384,7 @@ void TabbedPanel::hideFinished() { _showAnimation.reset(); _cache = QPixmap(); _hiding = false; + _shouldFinishHide = false; _selector->hideFinished(); } @@ -390,6 +395,9 @@ void TabbedPanel::showAnimated() { } void TabbedPanel::showStarted() { + if (_shouldFinishHide) { + return; + } if (isHidden()) { _selector->showStarted(); moveByBottom(); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h index b05966792..edaa45fa0 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_panel.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_panel.h @@ -110,6 +110,8 @@ private: std::unique_ptr _showAnimation; Ui::Animations::Simple _a_show; + bool _shouldFinishHide = false; + bool _hiding = false; bool _hideAfterSlide = false; QPixmap _cache; diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 132f8ba70..03daa863f 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/shadow.h" #include "ui/widgets/discrete_sliders.h" +#include "ui/widgets/popup_menu.h" #include "ui/widgets/scroll_area.h" #include "ui/image/image_prepare.h" #include "window/window_session_controller.h" @@ -584,7 +585,13 @@ void TabbedSelector::refreshStickers() { } bool TabbedSelector::preventAutoHide() const { - return full() ? stickers()->preventAutoHide() : false; + return full() + ? (stickers()->preventAutoHide() || hasMenu()) + : false; +} + +bool TabbedSelector::hasMenu() const { + return (_menu && !_menu->actions().empty()); } QImage TabbedSelector::grabForAnimation() { @@ -867,6 +874,15 @@ void TabbedSelector::scrollToY(int y) { } } +void TabbedSelector::contextMenuEvent(QContextMenuEvent *e) { + _menu = base::make_unique_q(this); + currentTab()->widget()->fillContextMenu(_menu); + + if (!_menu->actions().empty()) { + _menu->popup(QCursor::pos()); + } +} + TabbedSelector::Inner::Inner( QWidget *parent, not_null controller) diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index eec1e74fa..eb719b6f2 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -24,6 +24,7 @@ class Session; namespace Ui { class PlainShadow; +class PopupMenu; class ScrollArea; class SettingsSlider; class FlatLabel; @@ -94,6 +95,7 @@ public: bool isSliding() const { return _a_slide.animating(); } + bool hasMenu() const; void setAfterShownCallback(Fn callback) { _afterShownCallback = std::move(callback); @@ -116,6 +118,7 @@ public: protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void contextMenuEvent(QContextMenuEvent *e) override; private: class Tab { @@ -211,6 +214,8 @@ private: std::array _tabs; SelectorTab _currentTabType = SelectorTab::Emoji; + base::unique_qptr _menu; + Fn _afterShownCallback; Fn _beforeHidingCallback; @@ -246,6 +251,8 @@ public: } virtual void beforeHiding() { } + virtual void fillContextMenu(not_null menu) { + } rpl::producer scrollToRequests() const; rpl::producer disableScrollRequests() const;