Show terms on attach bot direct link app.

This commit is contained in:
John Preston 2023-09-12 10:03:51 +04:00
parent ef969df86e
commit 36f1a18b3b
4 changed files with 99 additions and 47 deletions

View file

@ -904,23 +904,28 @@ void AttachWebView::requestBots() {
}).send(); }).send();
} }
bool AttachWebView::showingDisclaimer(const AttachWebViewBot &bot) const { bool AttachWebView::disclaimerAccepted(const AttachWebViewBot &bot) const {
return bot.disclaimerRequired return _disclaimerAccepted.contains(bot.user);
&& !_disclaimerAccepted.contains(bot.user); }
bool AttachWebView::showMainMenuNewBadge(
const AttachWebViewBot &bot) const {
return bot.inMainMenu
&& bot.disclaimerRequired
&& !disclaimerAccepted(bot);
} }
void AttachWebView::requestAddToMenu( void AttachWebView::requestAddToMenu(
not_null<UserData*> bot, not_null<UserData*> bot,
std::optional<QString> startCommand) { AddToMenuOpen open) {
requestAddToMenu(bot, startCommand, nullptr, std::nullopt, PeerTypes()); requestAddToMenu(bot, open, nullptr, std::nullopt);
} }
void AttachWebView::requestAddToMenu( void AttachWebView::requestAddToMenu(
not_null<UserData*> bot, not_null<UserData*> bot,
std::optional<QString> startCommand, AddToMenuOpen open,
Window::SessionController *controller, Window::SessionController *controller,
std::optional<Api::SendAction> action, std::optional<Api::SendAction> action) {
PeerTypes chooseTypes) {
Expects(controller != nullptr || _context != nullptr); Expects(controller != nullptr || _context != nullptr);
if (!bot->isBot() || !bot->botInfo->supportsAttachMenu) { if (!bot->isBot() || !bot->botInfo->supportsAttachMenu) {
@ -929,8 +934,7 @@ void AttachWebView::requestAddToMenu(
} }
const auto wasController = (controller != nullptr); const auto wasController = (controller != nullptr);
_addToMenuChooseController = base::make_weak(controller); _addToMenuChooseController = base::make_weak(controller);
_addToMenuStartCommand = startCommand; _addToMenuOpen = open;
_addToMenuChooseTypes = chooseTypes;
if (!controller) { if (!controller) {
_addToMenuContext = base::take(_context); _addToMenuContext = base::take(_context);
} else if (action) { } else if (action) {
@ -950,17 +954,30 @@ void AttachWebView::requestAddToMenu(
_addToMenuId = 0; _addToMenuId = 0;
const auto bot = base::take(_addToMenuBot); const auto bot = base::take(_addToMenuBot);
const auto context = std::shared_ptr(base::take(_addToMenuContext)); const auto context = std::shared_ptr(base::take(_addToMenuContext));
const auto chooseTypes = base::take(_addToMenuChooseTypes); const auto open = base::take(_addToMenuOpen);
const auto startCommand = base::take(_addToMenuStartCommand);
const auto chooseController = base::take(_addToMenuChooseController); const auto chooseController = base::take(_addToMenuChooseController);
const auto open = [=](PeerTypes types) { const auto launch = [=](PeerTypes types) {
const auto openAttach = v::is<AddToMenuOpenAttach>(open)
? v::get<AddToMenuOpenAttach>(open)
: AddToMenuOpenAttach();
const auto chooseTypes = openAttach.chooseTypes;
const auto strong = chooseController.get(); const auto strong = chooseController.get();
if (!strong) { if (v::is<AddToMenuOpenApp>(open)) {
if (wasController || !startCommand) { if (!context) {
return false;
}
const auto &openApp = v::get<AddToMenuOpenApp>(open);
_app = openApp.app;
_startCommand = openApp.startCommand;
_context = std::make_unique<Context>(*context);
requestAppView(true);
return true;
} else if (!strong) {
if (wasController || !v::is<AddToMenuOpenAttach>(open)) {
// Just ignore the click if controller was destroyed. // Just ignore the click if controller was destroyed.
return true; return true;
} }
} else if (!startCommand) { } else if (v::is<AddToMenuOpenMenu>(open)) {
_bot = bot; _bot = bot;
requestSimple(strong, bot, { .fromMainMenu = true }); requestSimple(strong, bot, { .fromMainMenu = true });
return true; return true;
@ -969,7 +986,7 @@ void AttachWebView::requestAddToMenu(
strong->showThread(thread); strong->showThread(thread);
requestWithOptionalConfirm( requestWithOptionalConfirm(
bot, bot,
{ .startCommand = *startCommand }, { .startCommand = openAttach.startCommand },
LookupContext(strong, Api::SendAction(thread))); LookupContext(strong, Api::SendAction(thread)));
}; };
ShowChooseBox(strong, useTypes, done); ShowChooseBox(strong, useTypes, done);
@ -980,7 +997,7 @@ void AttachWebView::requestAddToMenu(
} }
requestWithOptionalConfirm( requestWithOptionalConfirm(
bot, bot,
{ .startCommand = *startCommand }, { .startCommand = openAttach.startCommand },
*context); *context);
return true; return true;
}; };
@ -999,11 +1016,11 @@ void AttachWebView::requestAddToMenu(
const auto types = parsed->types; const auto types = parsed->types;
if (parsed->inactive) { if (parsed->inactive) {
confirmAddToMenu(*parsed, [=] { confirmAddToMenu(*parsed, [=] {
open(types); launch(types);
}); });
} else { } else {
requestBots(); requestBots();
if (!open(types)) { if (!launch(types)) {
showToast( showToast(
tr::lng_bot_menu_already_added(tr::now)); tr::lng_bot_menu_already_added(tr::now));
} }
@ -1014,9 +1031,20 @@ void AttachWebView::requestAddToMenu(
}).fail([=] { }).fail([=] {
_addToMenuId = 0; _addToMenuId = 0;
_addToMenuBot = nullptr; _addToMenuBot = nullptr;
_addToMenuContext = nullptr; auto context = base::take(_addToMenuContext);
_addToMenuStartCommand = std::nullopt; const auto open = base::take(_addToMenuOpen);
showToast(tr::lng_bot_menu_not_supported(tr::now)); if (const auto openApp = std::get_if<AddToMenuOpenApp>(&open)) {
_app = openApp->app;
_startCommand = openApp->startCommand;
_context = std::move(context);
if (_appConfirmationRequired) {
confirmAppOpen(_appRequestWriteAccess);
} else {
requestAppView(false);
}
} else {
showToast(tr::lng_bot_menu_not_supported(tr::now));
}
}).send(); }).send();
} }
@ -1046,7 +1074,9 @@ void AttachWebView::resolve() {
showToast(tr::lng_bot_menu_not_supported(tr::now)); showToast(tr::lng_bot_menu_not_supported(tr::now));
return; return;
} }
requestAddToMenu(_bot, _startCommand); requestAddToMenu(_bot, AddToMenuOpenAttach{
.startCommand = _startCommand,
});
}); });
} }
@ -1209,12 +1239,14 @@ void AttachWebView::requestApp(
showToast(tr::lng_username_app_not_found(tr::now)); showToast(tr::lng_username_app_not_found(tr::now));
return; return;
} }
const auto confirm = firstTime || forceConfirmation; // Check if this app can be added to main menu.
if (confirm) { // On fail it'll still be opened.
confirmAppOpen(result.data().is_request_write_access()); _appConfirmationRequired = firstTime || forceConfirmation;
} else { _appRequestWriteAccess = result.data().is_request_write_access();
requestAppView(false); requestAddToMenu(_bot, AddToMenuOpenApp{
} .app = _app,
.startCommand = _startCommand,
});
}).fail([=] { }).fail([=] {
showToast(tr::lng_username_app_not_found(tr::now)); showToast(tr::lng_username_app_not_found(tr::now));
cancel(); cancel();
@ -1331,9 +1363,9 @@ void AttachWebView::acceptDisclaimer(
_attachBotsUpdates.fire({}); _attachBotsUpdates.fire({});
return; return;
} else if (i->inactive) { } else if (i->inactive) {
requestAddToMenu(_bot, {}, controller, {}, {}); requestAddToMenu(_bot, AddToMenuOpenMenu(), controller, {});
return; return;
} else if (!showingDisclaimer(*i)) { } else if (!i->disclaimerRequired || disclaimerAccepted(*i)) {
done(); done();
return; return;
} }
@ -1478,7 +1510,7 @@ void AttachWebView::confirmAddToMenu(
}); });
close(); close();
}; };
const auto disclaimer = showingDisclaimer(bot); const auto disclaimer = !disclaimerAccepted(bot);
if (disclaimer) { if (disclaimer) {
FillDisclaimerBox(box, [=] { FillDisclaimerBox(box, [=] {
_disclaimerAccepted.emplace(bot.user); _disclaimerAccepted.emplace(bot.user);

View file

@ -70,6 +70,21 @@ struct AttachWebViewBot {
bool requestWriteAccess : 1 = false; bool requestWriteAccess : 1 = false;
}; };
struct AddToMenuOpenAttach {
QString startCommand;
PeerTypes chooseTypes;
};
struct AddToMenuOpenMenu {
};
struct AddToMenuOpenApp {
not_null<BotAppData*> app;
QString startCommand;
};
using AddToMenuOpen = std::variant<
AddToMenuOpenAttach,
AddToMenuOpenMenu,
AddToMenuOpenApp>;
class AttachWebView final class AttachWebView final
: public base::has_weak_ptr : public base::has_weak_ptr
, public Ui::BotWebView::Delegate { , public Ui::BotWebView::Delegate {
@ -119,17 +134,19 @@ public:
[[nodiscard]] rpl::producer<> attachBotsUpdates() const { [[nodiscard]] rpl::producer<> attachBotsUpdates() const {
return _attachBotsUpdates.events(); return _attachBotsUpdates.events();
} }
[[nodiscard]] bool showingDisclaimer(const AttachWebViewBot &bot) const; [[nodiscard]] bool disclaimerAccepted(
const AttachWebViewBot &bot) const;
[[nodiscard]] bool showMainMenuNewBadge(
const AttachWebViewBot &bot) const;
void requestAddToMenu( void requestAddToMenu(
not_null<UserData*> bot, not_null<UserData*> bot,
std::optional<QString> startCommand); AddToMenuOpen open);
void requestAddToMenu( void requestAddToMenu(
not_null<UserData*> bot, not_null<UserData*> bot,
std::optional<QString> startCommand, AddToMenuOpen open,
Window::SessionController *controller, Window::SessionController *controller,
std::optional<Api::SendAction> action, std::optional<Api::SendAction> action);
PeerTypes chooseTypes);
void removeFromMenu(not_null<UserData*> bot); void removeFromMenu(not_null<UserData*> bot);
[[nodiscard]] std::optional<Api::SendAction> lookupLastAction( [[nodiscard]] std::optional<Api::SendAction> lookupLastAction(
@ -140,6 +157,7 @@ public:
private: private:
struct Context; struct Context;
Webview::ThemeParams botThemeParams() override; Webview::ThemeParams botThemeParams() override;
bool botHandleLocalUri(QString uri) override; bool botHandleLocalUri(QString uri) override;
void botHandleInvoice(QString slug) override; void botHandleInvoice(QString slug) override;
@ -224,6 +242,8 @@ private:
QString _startCommand; QString _startCommand;
BotAppData *_app = nullptr; BotAppData *_app = nullptr;
QPointer<Ui::GenericBox> _confirmAddBox; QPointer<Ui::GenericBox> _confirmAddBox;
bool _appConfirmationRequired = false;
bool _appRequestWriteAccess = false;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
mtpRequestId _prolongId = 0; mtpRequestId _prolongId = 0;
@ -234,9 +254,8 @@ private:
std::unique_ptr<Context> _addToMenuContext; std::unique_ptr<Context> _addToMenuContext;
UserData *_addToMenuBot = nullptr; UserData *_addToMenuBot = nullptr;
mtpRequestId _addToMenuId = 0; mtpRequestId _addToMenuId = 0;
std::optional<QString> _addToMenuStartCommand; AddToMenuOpen _addToMenuOpen;
base::weak_ptr<Window::SessionController> _addToMenuChooseController; base::weak_ptr<Window::SessionController> _addToMenuChooseController;
PeerTypes _addToMenuChooseTypes;
std::vector<AttachWebViewBot> _attachBots; std::vector<AttachWebViewBot> _attachBots;
rpl::event_stream<> _attachBotsUpdates; rpl::event_stream<> _attachBotsUpdates;

View file

@ -254,7 +254,7 @@ void SetupMenuBots(
} }
}, button->lifetime()); }, button->lifetime());
const auto badge = bots->showingDisclaimer(bot) const auto badge = bots->showMainMenuNewBadge(bot)
? Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>( ? Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
button.get(), button.get(),
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(

View file

@ -589,20 +589,21 @@ void SessionNavigation::showPeerByLinkResolved(
: nullptr; : nullptr;
bot->session().attachWebView().requestAddToMenu( bot->session().attachWebView().requestAddToMenu(
bot, bot,
*info.attachBotToggleCommand, InlineBots::AddToMenuOpenAttach{
.startCommand = *info.attachBotToggleCommand,
.chooseTypes = info.attachBotChooseTypes,
},
parentController(), parentController(),
(contextUser (contextUser
? Api::SendAction( ? Api::SendAction(
contextUser->owner().history(contextUser)) contextUser->owner().history(contextUser))
: std::optional<Api::SendAction>()), : std::optional<Api::SendAction>()));
info.attachBotChooseTypes);
} else if (bot && info.attachBotMenuOpen) { } else if (bot && info.attachBotMenuOpen) {
bot->session().attachWebView().requestAddToMenu( bot->session().attachWebView().requestAddToMenu(
bot, bot,
std::nullopt, InlineBots::AddToMenuOpenMenu(),
parentController(), parentController(),
std::optional<Api::SendAction>(), std::optional<Api::SendAction>());
{});
} else { } else {
crl::on_main(this, [=] { crl::on_main(this, [=] {
showPeerHistory(peer, params, msgId); showPeerHistory(peer, params, msgId);