Added initial context menu to TabbedPanel.

Added ability to schedule and send silently stickers and GIFs.
This commit is contained in:
23rd 2020-07-25 18:07:14 +03:00 committed by John Preston
parent a95a324401
commit 7db9843543
8 changed files with 130 additions and 5 deletions

View File

@ -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<Ui::PopupMenu*> 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();

View File

@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtCore/QTimer>
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<Ui::PopupMenu*> 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;

View File

@ -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<Ui::PopupMenu*> menu) {
auto selected = _selected;
auto &sets = shownSets();
if (!selected || _pressed) {
return;
}
if (auto sticker = base::get_if<OverSticker>(&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();

View File

@ -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<Lottie::FrameRenderer> getLottieRenderer();
void fillContextMenu(not_null<Ui::PopupMenu*> menu) override;
~StickersListWidget();
protected:

View File

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

View File

@ -110,6 +110,8 @@ private:
std::unique_ptr<Ui::PanelAnimation> _showAnimation;
Ui::Animations::Simple _a_show;
bool _shouldFinishHide = false;
bool _hiding = false;
bool _hideAfterSlide = false;
QPixmap _cache;

View File

@ -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<Ui::PopupMenu>(this);
currentTab()->widget()->fillContextMenu(_menu);
if (!_menu->actions().empty()) {
_menu->popup(QCursor::pos());
}
}
TabbedSelector::Inner::Inner(
QWidget *parent,
not_null<Window::SessionController*> controller)

View File

@ -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<void(SelectorTab)> 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<Tab, Tab::kCount> _tabs;
SelectorTab _currentTabType = SelectorTab::Emoji;
base::unique_qptr<Ui::PopupMenu> _menu;
Fn<void(SelectorTab)> _afterShownCallback;
Fn<void(SelectorTab)> _beforeHidingCallback;
@ -246,6 +251,8 @@ public:
}
virtual void beforeHiding() {
}
virtual void fillContextMenu(not_null<Ui::PopupMenu*> menu) {
}
rpl::producer<int> scrollToRequests() const;
rpl::producer<bool> disableScrollRequests() const;