mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 23:24:01 +02:00
Allow removing a bot from attach menu.
This commit is contained in:
parent
72ae2f0269
commit
b38ac32898
5 changed files with 128 additions and 26 deletions
|
@ -1722,6 +1722,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_bot_sure_add_text_group" = "Are you sure you want to add this bot as an admin in the group {group}?";
|
"lng_bot_sure_add_text_group" = "Are you sure you want to add this bot as an admin in the group {group}?";
|
||||||
"lng_bot_sure_add_text_channel" = "Are you sure you want to add this bot as an admin in the channel {group}?";
|
"lng_bot_sure_add_text_channel" = "Are you sure you want to add this bot as an admin in the channel {group}?";
|
||||||
"lng_bot_sure_add" = "Add as admin";
|
"lng_bot_sure_add" = "Add as admin";
|
||||||
|
"lng_bot_no_webview" = "Unfortunately, you can't open such menu with current system configuration.";
|
||||||
|
"lng_bot_remove_from_menu" = "Remove from menu";
|
||||||
|
"lng_bot_remove_from_menu_done" = "Bot removed from the menu.";
|
||||||
|
"lng_bot_add_to_menu" = "{bot} asks your permission to be added as an option to your attachments menu so you can access it from any chat.";
|
||||||
|
"lng_bot_add_to_menu_done" = "Bot added to the menu.";
|
||||||
|
"lng_bot_menu_not_supported" = "This bot isn't supported in the attach menu.";
|
||||||
|
"lng_bot_menu_already_added" = "This bot is already added in your attach menu.";
|
||||||
|
|
||||||
"lng_typing" = "typing";
|
"lng_typing" = "typing";
|
||||||
"lng_user_typing" = "{user} is typing";
|
"lng_user_typing" = "{user} is typing";
|
||||||
|
|
|
@ -489,9 +489,18 @@ HistoryWidget::HistoryWidget(
|
||||||
_attachBotsMenu = nullptr;
|
_attachBotsMenu = nullptr;
|
||||||
return;
|
return;
|
||||||
} else if (!_attachBotsMenu) {
|
} else if (!_attachBotsMenu) {
|
||||||
|
const auto forceShown = [=](bool shown) {
|
||||||
|
if (shown) {
|
||||||
|
_attachBotsMenu->setAutoHiding(false);
|
||||||
|
} else {
|
||||||
|
_attachBotsMenu->hideAnimated();
|
||||||
|
_attachBotsMenu->setAutoHiding(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
||||||
this,
|
this,
|
||||||
controller);
|
controller,
|
||||||
|
forceShown);
|
||||||
_attachBotsMenu->setOrigin(
|
_attachBotsMenu->setOrigin(
|
||||||
Ui::PanelAnimation::Origin::BottomLeft);
|
Ui::PanelAnimation::Origin::BottomLeft);
|
||||||
if (_history && _history->peer->isUser()) {
|
if (_history && _history->peer->isUser()) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_document_media.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "main/main_domain.h"
|
#include "main/main_domain.h"
|
||||||
|
@ -19,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/toasts/common_toasts.h"
|
#include "ui/toasts/common_toasts.h"
|
||||||
#include "ui/chat/attach/attach_bot_webview.h"
|
#include "ui/chat/attach/attach_bot_webview.h"
|
||||||
#include "ui/widgets/dropdown_menu.h"
|
#include "ui/widgets/dropdown_menu.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/widgets/menu/menu_item_base.h"
|
#include "ui/widgets/menu/menu_item_base.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
|
@ -32,6 +34,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "styles/style_menu_icons.h"
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
namespace InlineBots {
|
namespace InlineBots {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -81,23 +85,32 @@ public:
|
||||||
bool isEnabled() const override;
|
bool isEnabled() const override;
|
||||||
not_null<QAction*> action() const override;
|
not_null<QAction*> action() const override;
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<bool> forceShown() const;
|
||||||
|
|
||||||
void handleKeyPress(not_null<QKeyEvent*> e) override;
|
void handleKeyPress(not_null<QKeyEvent*> e) override;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
|
|
||||||
QPoint prepareRippleStartPosition() const override;
|
QPoint prepareRippleStartPosition() const override;
|
||||||
QImage prepareRippleMask() const override;
|
QImage prepareRippleMask() const override;
|
||||||
|
|
||||||
int contentHeight() const override;
|
int contentHeight() const override;
|
||||||
|
|
||||||
private:
|
|
||||||
void prepare();
|
void prepare();
|
||||||
|
void validateIcon();
|
||||||
void paint(Painter &p);
|
void paint(Painter &p);
|
||||||
|
|
||||||
const not_null<QAction*> _dummyAction;
|
const not_null<QAction*> _dummyAction;
|
||||||
const style::Menu &_st;
|
const style::Menu &_st;
|
||||||
const AttachWebViewBot _bot;
|
const AttachWebViewBot _bot;
|
||||||
|
|
||||||
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
rpl::event_stream<bool> _forceShown;
|
||||||
|
|
||||||
Ui::Text::String _text;
|
Ui::Text::String _text;
|
||||||
|
QImage _mask;
|
||||||
|
QImage _icon;
|
||||||
int _textWidth = 0;
|
int _textWidth = 0;
|
||||||
const int _height;
|
const int _height;
|
||||||
|
|
||||||
|
@ -115,7 +128,7 @@ BotAction::BotAction(
|
||||||
, _height(_st.itemPadding.top()
|
, _height(_st.itemPadding.top()
|
||||||
+ _st.itemStyle.font->height
|
+ _st.itemStyle.font->height
|
||||||
+ _st.itemPadding.bottom()) {
|
+ _st.itemPadding.bottom()) {
|
||||||
setAcceptBoth(true);
|
setAcceptBoth(false);
|
||||||
initResizeHook(parent->sizeValue());
|
initResizeHook(parent->sizeValue());
|
||||||
setClickedCallback(std::move(callback));
|
setClickedCallback(std::move(callback));
|
||||||
|
|
||||||
|
@ -125,11 +138,48 @@ BotAction::BotAction(
|
||||||
paint(p);
|
paint(p);
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
|
style::PaletteChanged(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
_icon = QImage();
|
||||||
|
update();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
enableMouseSelecting();
|
enableMouseSelecting();
|
||||||
prepare();
|
prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BotAction::validateIcon() {
|
||||||
|
if (_mask.isNull()) {
|
||||||
|
if (!_bot.media->loaded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto icon = QSvgRenderer(_bot.media->bytes());
|
||||||
|
if (!icon.isValid()) {
|
||||||
|
_mask = QImage(
|
||||||
|
QSize(1, 1) * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
_mask.fill(Qt::transparent);
|
||||||
|
} else {
|
||||||
|
const auto size = style::ConvertScale(icon.defaultSize());
|
||||||
|
_mask = QImage(
|
||||||
|
size * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
_mask.fill(Qt::transparent);
|
||||||
|
{
|
||||||
|
auto p = QPainter(&_mask);
|
||||||
|
icon.render(&p, QRect(QPoint(), size));
|
||||||
|
}
|
||||||
|
_mask = Images::Colored(std::move(_mask), QColor(255, 255, 255));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_icon.isNull()) {
|
||||||
|
_icon = style::colorizeImage(_mask, st::menuIconColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BotAction::paint(Painter &p) {
|
void BotAction::paint(Painter &p) {
|
||||||
|
validateIcon();
|
||||||
|
|
||||||
const auto selected = isSelected();
|
const auto selected = isSelected();
|
||||||
if (selected && _st.itemBgOver->c.alpha() < 255) {
|
if (selected && _st.itemBgOver->c.alpha() < 255) {
|
||||||
p.fillRect(0, 0, width(), _height, _st.itemBg);
|
p.fillRect(0, 0, width(), _height, _st.itemBg);
|
||||||
|
@ -139,14 +189,9 @@ void BotAction::paint(Painter &p) {
|
||||||
paintRipple(p, 0, 0);
|
paintRipple(p, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto normalHeight = _st.itemPadding.top()
|
if (!_icon.isNull()) {
|
||||||
+ _st.itemStyle.font->height
|
p.drawImage(_st.itemIconPosition, _icon);
|
||||||
+ _st.itemPadding.bottom();
|
}
|
||||||
const auto deltaHeight = _height - normalHeight;
|
|
||||||
st::menuIconDelete.paint(
|
|
||||||
p,
|
|
||||||
_st.itemIconPosition + QPoint(0, deltaHeight / 2),
|
|
||||||
width());
|
|
||||||
|
|
||||||
p.setPen(selected ? _st.itemFgOver : _st.itemFg);
|
p.setPen(selected ? _st.itemFgOver : _st.itemFg);
|
||||||
_text.drawLeftElided(
|
_text.drawLeftElided(
|
||||||
|
@ -180,6 +225,24 @@ not_null<QAction*> BotAction::action() const {
|
||||||
return _dummyAction;
|
return _dummyAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BotAction::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
|
_menu = nullptr;
|
||||||
|
_menu = base::make_unique_q<Ui::PopupMenu>(
|
||||||
|
this,
|
||||||
|
st::popupMenuWithIcons);
|
||||||
|
_menu->addAction(tr::lng_bot_remove_from_menu(tr::now), [=] {
|
||||||
|
_bot.user->session().attachWebView().removeFromMenu(_bot.user);
|
||||||
|
}, &st::menuIconDelete);
|
||||||
|
|
||||||
|
QObject::connect(_menu, &QObject::destroyed, [=] {
|
||||||
|
_forceShown.fire(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
_forceShown.fire(true);
|
||||||
|
_menu->popup(e->globalPos());
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
|
||||||
QPoint BotAction::prepareRippleStartPosition() const {
|
QPoint BotAction::prepareRippleStartPosition() const {
|
||||||
return mapFromGlobal(QCursor::pos());
|
return mapFromGlobal(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
@ -192,6 +255,10 @@ int BotAction::contentHeight() const {
|
||||||
return _height;
|
return _height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> BotAction::forceShown() const {
|
||||||
|
return _forceShown.events();
|
||||||
|
}
|
||||||
|
|
||||||
void BotAction::handleKeyPress(not_null<QKeyEvent*> e) {
|
void BotAction::handleKeyPress(not_null<QKeyEvent*> e) {
|
||||||
if (!isSelected()) {
|
if (!isSelected()) {
|
||||||
return;
|
return;
|
||||||
|
@ -348,7 +415,8 @@ void AttachWebView::requestAddToMenu(not_null<UserData*> bot) {
|
||||||
} else {
|
} else {
|
||||||
requestBots();
|
requestBots();
|
||||||
Ui::ShowMultilineToast({
|
Ui::ShowMultilineToast({
|
||||||
.text = { u"Bot is already added."_q },
|
.text = {
|
||||||
|
tr::lng_bot_menu_already_added(tr::now) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,13 +426,17 @@ void AttachWebView::requestAddToMenu(not_null<UserData*> bot) {
|
||||||
_addToMenuId = 0;
|
_addToMenuId = 0;
|
||||||
_addToMenuBot = nullptr;
|
_addToMenuBot = nullptr;
|
||||||
Ui::ShowMultilineToast({
|
Ui::ShowMultilineToast({
|
||||||
.text = { u"Bot cannot be added to the menu."_q },
|
.text = { tr::lng_bot_menu_not_supported(tr::now) },
|
||||||
});
|
});
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::removeFromMenu(not_null<UserData*> bot) {
|
void AttachWebView::removeFromMenu(not_null<UserData*> bot) {
|
||||||
toggleInMenu(bot, false, nullptr);
|
toggleInMenu(bot, false, [=] {
|
||||||
|
Ui::ShowMultilineToast({
|
||||||
|
.text = { tr::lng_bot_remove_from_menu_done(tr::now) },
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::resolve() {
|
void AttachWebView::resolve() {
|
||||||
|
@ -378,8 +450,7 @@ void AttachWebView::requestByUsername() {
|
||||||
_bot = bot->asUser();
|
_bot = bot->asUser();
|
||||||
if (!_bot || !_bot->isBot() || !_bot->botInfo->supportsAttachMenu) {
|
if (!_bot || !_bot->isBot() || !_bot->botInfo->supportsAttachMenu) {
|
||||||
Ui::ShowMultilineToast({
|
Ui::ShowMultilineToast({
|
||||||
// #TODO webview lang
|
.text = { tr::lng_bot_menu_not_supported(tr::now) }
|
||||||
.text = { u"This bot isn't supported in the attach menu."_q }
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -529,15 +600,18 @@ void AttachWebView::confirmAddToMenu(
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
close();
|
Ui::ShowMultilineToast({
|
||||||
|
.text = { tr::lng_bot_add_to_menu_done(tr::now) },
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
close();
|
||||||
};
|
};
|
||||||
const auto active = Core::App().activeWindow();
|
const auto active = Core::App().activeWindow();
|
||||||
if (!active) {
|
if (!active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_confirmAddBox = active->show(Ui::MakeConfirmBox({
|
_confirmAddBox = active->show(Ui::MakeConfirmBox({
|
||||||
u"Do you want to? "_q + bot.name,
|
tr::lng_bot_add_to_menu(tr::now, lt_bot, bot.name),
|
||||||
done,
|
done,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -562,7 +636,8 @@ void AttachWebView::toggleInMenu(
|
||||||
|
|
||||||
std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::SessionController*> controller) {
|
not_null<Window::SessionController*> controller,
|
||||||
|
Fn<void(bool)> forceShown) {
|
||||||
auto result = std::make_unique<Ui::DropdownMenu>(
|
auto result = std::make_unique<Ui::DropdownMenu>(
|
||||||
parent,
|
parent,
|
||||||
st::dropdownMenuWithIcons);
|
st::dropdownMenuWithIcons);
|
||||||
|
@ -571,12 +646,22 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
||||||
const auto refresh = [=] {
|
const auto refresh = [=] {
|
||||||
raw->clearActions();
|
raw->clearActions();
|
||||||
for (const auto &bot : bots->attachBots()) {
|
for (const auto &bot : bots->attachBots()) {
|
||||||
raw->addAction(base::make_unique_q<BotAction>(raw, bot, raw->menu()->st(), [=] {
|
const auto callback = [=] {
|
||||||
const auto active = controller->activeChatCurrent();
|
const auto active = controller->activeChatCurrent();
|
||||||
if (const auto history = active.history()) {
|
if (const auto history = active.history()) {
|
||||||
bots->request(history->peer, bot.user);
|
bots->request(history->peer, bot.user);
|
||||||
}
|
}
|
||||||
}));
|
};
|
||||||
|
auto action = base::make_unique_q<BotAction>(
|
||||||
|
raw,
|
||||||
|
raw->menu()->st(),
|
||||||
|
bot,
|
||||||
|
callback);
|
||||||
|
action->forceShown(
|
||||||
|
) | rpl::start_with_next([=](bool shown) {
|
||||||
|
forceShown(shown);
|
||||||
|
}, action->lifetime());
|
||||||
|
raw->addAction(std::move(action));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
refresh();
|
refresh();
|
||||||
|
|
|
@ -85,7 +85,7 @@ private:
|
||||||
void toggleInMenu(
|
void toggleInMenu(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
bool enabled,
|
bool enabled,
|
||||||
Fn<void()> callback);
|
Fn<void()> callback = nullptr);
|
||||||
|
|
||||||
void show(
|
void show(
|
||||||
uint64 queryId,
|
uint64 queryId,
|
||||||
|
@ -122,6 +122,7 @@ private:
|
||||||
|
|
||||||
[[nodiscard]] std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
[[nodiscard]] std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
not_null<Window::SessionController*> controller);
|
not_null<Window::SessionController*> controller,
|
||||||
|
Fn<void(bool)> forceShown);
|
||||||
|
|
||||||
} // namespace InlineBots
|
} // namespace InlineBots
|
||||||
|
|
|
@ -482,7 +482,7 @@ std::unique_ptr<Panel> Show(Args &&args) {
|
||||||
const auto available = Webview::Availability();
|
const auto available = Webview::Availability();
|
||||||
if (available.error != Webview::Available::Error::None) {
|
if (available.error != Webview::Available::Error::None) {
|
||||||
result->showWebviewError(
|
result->showWebviewError(
|
||||||
tr::lng_payments_webview_no_card(tr::now),
|
tr::lng_bot_no_webview(tr::now),
|
||||||
available);
|
available);
|
||||||
} else {
|
} else {
|
||||||
result->showCriticalError({
|
result->showCriticalError({
|
||||||
|
|
Loading…
Add table
Reference in a new issue