mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-04-29 23:00:53 +00:00
Improve main menu bots disclaimer acceptance.
This commit is contained in:
parent
229f7a2c15
commit
ef969df86e
@ -2268,6 +2268,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
"lng_bot_reload_page" = "Reload Page";
|
"lng_bot_reload_page" = "Reload Page";
|
||||||
"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" = "{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_add_to_menu_done" = "Bot added to the menu.";
|
||||||
|
"lng_bot_will_be_added" = "{bot} shortcuts will be added to the attachment options and the main menu.";
|
||||||
|
"lng_bot_side_menu_new" = "NEW";
|
||||||
"lng_bot_menu_not_supported" = "This bot isn't supported in the attach 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_bot_menu_already_added" = "This bot is already added in your attach menu.";
|
||||||
"lng_bot_menu_button" = "Menu";
|
"lng_bot_menu_button" = "Menu";
|
||||||
|
@ -24,4 +24,5 @@ struct BotAppData {
|
|||||||
|
|
||||||
uint64 accessHash = 0;
|
uint64 accessHash = 0;
|
||||||
uint64 hash = 0;
|
uint64 hash = 0;
|
||||||
|
bool hasSettings = false;
|
||||||
};
|
};
|
||||||
|
@ -124,6 +124,10 @@ constexpr auto kRefreshBotsTimeout = 60 * 60 * crl::time(1000);
|
|||||||
if (result && result->icon) {
|
if (result && result->icon) {
|
||||||
result->icon->forceToCache(true);
|
result->icon->forceToCache(true);
|
||||||
}
|
}
|
||||||
|
if (const auto icon = result->icon) {
|
||||||
|
result->media = icon->createMediaView();
|
||||||
|
icon->save(Data::FileOrigin(), {});
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +198,78 @@ void ShowChooseBox(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FillDisclaimerBox(not_null<Ui::GenericBox*> box, Fn<void()> done) {
|
||||||
|
const auto updateCheck = std::make_shared<Fn<void()>>();
|
||||||
|
const auto validateCheck = std::make_shared<Fn<bool()>>();
|
||||||
|
|
||||||
|
const auto callback = [=](Fn<void()> close) {
|
||||||
|
if (validateCheck && (*validateCheck)()) {
|
||||||
|
done();
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto padding = st::boxRowPadding;
|
||||||
|
Ui::ConfirmBox(box, {
|
||||||
|
.text = tr::lng_mini_apps_disclaimer_text(
|
||||||
|
tr::now,
|
||||||
|
Ui::Text::RichLangValue),
|
||||||
|
.confirmed = callback,
|
||||||
|
.confirmText = tr::lng_box_ok(),
|
||||||
|
.labelPadding = QMargins(padding.left(), 0, padding.right(), 0),
|
||||||
|
.title = tr::lng_mini_apps_disclaimer_title(),
|
||||||
|
});
|
||||||
|
|
||||||
|
auto checkView = std::make_unique<Ui::CheckView>(
|
||||||
|
st::defaultCheck,
|
||||||
|
false,
|
||||||
|
[=] { if (*updateCheck) { (*updateCheck)(); } });
|
||||||
|
const auto check = checkView.get();
|
||||||
|
const auto row = box->addRow(
|
||||||
|
object_ptr<Ui::Checkbox>(
|
||||||
|
box.get(),
|
||||||
|
tr::lng_mini_apps_disclaimer_button(
|
||||||
|
lt_link,
|
||||||
|
rpl::single(Ui::Text::Link(
|
||||||
|
tr::lng_mini_apps_disclaimer_link(tr::now),
|
||||||
|
tr::lng_mini_apps_tos_url(tr::now))),
|
||||||
|
Ui::Text::WithEntities),
|
||||||
|
st::defaultBoxCheckbox,
|
||||||
|
std::move(checkView)),
|
||||||
|
{
|
||||||
|
st::boxRowPadding.left(),
|
||||||
|
st::boxRowPadding.left(),
|
||||||
|
st::boxRowPadding.right(),
|
||||||
|
0,
|
||||||
|
});
|
||||||
|
row->setAllowTextLines(5);
|
||||||
|
row->setClickHandlerFilter([=](
|
||||||
|
const ClickHandlerPtr &link,
|
||||||
|
Qt::MouseButton button) {
|
||||||
|
ActivateClickHandler(row, link, ClickContext{
|
||||||
|
.button = button,
|
||||||
|
.other = QVariant::fromValue(ClickHandlerContext{
|
||||||
|
.show = box->uiShow(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
(*updateCheck) = [=] { row->update(); };
|
||||||
|
|
||||||
|
const auto showError = Ui::CheckView::PrepareNonToggledError(
|
||||||
|
check,
|
||||||
|
box->lifetime());
|
||||||
|
|
||||||
|
(*validateCheck) = [=] {
|
||||||
|
if (check->checked()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
showError();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class BotAction final : public Ui::Menu::ItemBase {
|
class BotAction final : public Ui::Menu::ItemBase {
|
||||||
public:
|
public:
|
||||||
BotAction(
|
BotAction(
|
||||||
@ -818,10 +894,6 @@ void AttachWebView::requestBots() {
|
|||||||
_attachBots.reserve(data.vbots().v.size());
|
_attachBots.reserve(data.vbots().v.size());
|
||||||
for (const auto &bot : data.vbots().v) {
|
for (const auto &bot : data.vbots().v) {
|
||||||
if (auto parsed = ParseAttachBot(_session, bot)) {
|
if (auto parsed = ParseAttachBot(_session, bot)) {
|
||||||
if (const auto icon = parsed->icon) {
|
|
||||||
parsed->media = icon->createMediaView();
|
|
||||||
icon->save(Data::FileOrigin(), {});
|
|
||||||
}
|
|
||||||
_attachBots.push_back(std::move(*parsed));
|
_attachBots.push_back(std::move(*parsed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -832,6 +904,11 @@ void AttachWebView::requestBots() {
|
|||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AttachWebView::showingDisclaimer(const AttachWebViewBot &bot) const {
|
||||||
|
return bot.disclaimerRequired
|
||||||
|
&& !_disclaimerAccepted.contains(bot.user);
|
||||||
|
}
|
||||||
|
|
||||||
void AttachWebView::requestAddToMenu(
|
void AttachWebView::requestAddToMenu(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
std::optional<QString> startCommand) {
|
std::optional<QString> startCommand) {
|
||||||
@ -885,9 +962,7 @@ void AttachWebView::requestAddToMenu(
|
|||||||
}
|
}
|
||||||
} else if (!startCommand) {
|
} else if (!startCommand) {
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
acceptDisclaimer(strong, [=] {
|
|
||||||
requestSimple(strong, bot, { .fromMainMenu = true });
|
requestSimple(strong, bot, { .fromMainMenu = true });
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
} else if (const auto useTypes = chooseTypes & types) {
|
} else if (const auto useTypes = chooseTypes & types) {
|
||||||
const auto done = [=](not_null<Data::Thread*> thread) {
|
const auto done = [=](not_null<Data::Thread*> thread) {
|
||||||
@ -1128,6 +1203,7 @@ void AttachWebView::requestApp(
|
|||||||
_bot->id,
|
_bot->id,
|
||||||
data.vapp());
|
data.vapp());
|
||||||
_app = received ? received : already;
|
_app = received ? received : already;
|
||||||
|
_app->hasSettings = data.is_has_settings();
|
||||||
if (!_app) {
|
if (!_app) {
|
||||||
cancel();
|
cancel();
|
||||||
showToast(tr::lng_username_app_not_found(tr::now));
|
showToast(tr::lng_username_app_not_found(tr::now));
|
||||||
@ -1140,8 +1216,8 @@ void AttachWebView::requestApp(
|
|||||||
requestAppView(false);
|
requestAppView(false);
|
||||||
}
|
}
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
cancel();
|
|
||||||
showToast(tr::lng_username_app_not_found(tr::now));
|
showToast(tr::lng_username_app_not_found(tr::now));
|
||||||
|
cancel();
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1190,13 +1266,14 @@ void AttachWebView::requestAppView(bool allowWrite) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using Flag = MTPmessages_RequestAppWebView::Flag;
|
using Flag = MTPmessages_RequestAppWebView::Flag;
|
||||||
|
const auto app = _app;
|
||||||
const auto flags = Flag::f_theme_params
|
const auto flags = Flag::f_theme_params
|
||||||
| (_startCommand.isEmpty() ? Flag(0) : Flag::f_start_param)
|
| (_startCommand.isEmpty() ? Flag(0) : Flag::f_start_param)
|
||||||
| (allowWrite ? Flag::f_write_allowed : Flag(0));
|
| (allowWrite ? Flag::f_write_allowed : Flag(0));
|
||||||
_requestId = _session->api().request(MTPmessages_RequestAppWebView(
|
_requestId = _session->api().request(MTPmessages_RequestAppWebView(
|
||||||
MTP_flags(flags),
|
MTP_flags(flags),
|
||||||
_context->action.history->peer->input,
|
_context->action.history->peer->input,
|
||||||
MTP_inputBotAppID(MTP_long(_app->id), MTP_long(_app->accessHash)),
|
MTP_inputBotAppID(MTP_long(app->id), MTP_long(app->accessHash)),
|
||||||
MTP_string(_startCommand),
|
MTP_string(_startCommand),
|
||||||
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
||||||
MTP_string("tdesktop")
|
MTP_string("tdesktop")
|
||||||
@ -1204,7 +1281,7 @@ void AttachWebView::requestAppView(bool allowWrite) {
|
|||||||
_requestId = 0;
|
_requestId = 0;
|
||||||
const auto &data = result.data();
|
const auto &data = result.data();
|
||||||
const auto queryId = uint64();
|
const auto queryId = uint64();
|
||||||
show(queryId, qs(data.vurl()));
|
show(queryId, qs(data.vurl()), QString(), false, app);
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
_requestId = 0;
|
_requestId = 0;
|
||||||
if (error.type() == u"BOT_INVALID"_q) {
|
if (error.type() == u"BOT_INVALID"_q) {
|
||||||
@ -1256,93 +1333,17 @@ void AttachWebView::acceptDisclaimer(
|
|||||||
} else if (i->inactive) {
|
} else if (i->inactive) {
|
||||||
requestAddToMenu(_bot, {}, controller, {}, {});
|
requestAddToMenu(_bot, {}, controller, {}, {});
|
||||||
return;
|
return;
|
||||||
} else if (!i->disclaimerRequired) {
|
} else if (!showingDisclaimer(*i)) {
|
||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto weak = base::make_weak(this);
|
const auto weak = base::make_weak(this);
|
||||||
controller->show(Box([=](not_null<Ui::GenericBox*> box) {
|
controller->show(Box(FillDisclaimerBox, crl::guard(this, [=] {
|
||||||
const auto updateCheck = std::make_shared<Fn<void()>>();
|
_disclaimerAccepted.emplace(_bot);
|
||||||
const auto validateCheck = std::make_shared<Fn<bool()>>();
|
|
||||||
|
|
||||||
const auto callback = [=](Fn<void()> close) {
|
|
||||||
if (validateCheck && (*validateCheck)() && weak) {
|
|
||||||
const auto i = ranges::find(
|
|
||||||
_attachBots,
|
|
||||||
not_null(_bot),
|
|
||||||
&AttachWebViewBot::user);
|
|
||||||
if (i == end(_attachBots)) {
|
|
||||||
_attachBotsUpdates.fire({});
|
_attachBotsUpdates.fire({});
|
||||||
} else if (i->inactive) {
|
|
||||||
requestAddToMenu(_bot, std::nullopt);
|
|
||||||
} else {
|
|
||||||
i->disclaimerRequired = false;
|
|
||||||
requestBots();
|
|
||||||
done();
|
done();
|
||||||
}
|
})));
|
||||||
close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ui::ConfirmBox(box, {
|
|
||||||
.text = tr::lng_mini_apps_disclaimer_text(
|
|
||||||
tr::now,
|
|
||||||
Ui::Text::RichLangValue),
|
|
||||||
.confirmed = callback,
|
|
||||||
.confirmText = tr::lng_box_ok(),
|
|
||||||
.title = tr::lng_mini_apps_disclaimer_title(),
|
|
||||||
});
|
|
||||||
|
|
||||||
auto checkView = std::make_unique<Ui::CheckView>(
|
|
||||||
st::defaultCheck,
|
|
||||||
false,
|
|
||||||
[=] { if (*updateCheck) { (*updateCheck)(); } });
|
|
||||||
const auto check = checkView.get();
|
|
||||||
const auto row = box->addRow(
|
|
||||||
object_ptr<Ui::Checkbox>(
|
|
||||||
box.get(),
|
|
||||||
tr::lng_mini_apps_disclaimer_button(
|
|
||||||
lt_link,
|
|
||||||
rpl::single(Ui::Text::Link(
|
|
||||||
tr::lng_mini_apps_disclaimer_link(tr::now),
|
|
||||||
tr::lng_mini_apps_tos_url(tr::now))),
|
|
||||||
Ui::Text::WithEntities),
|
|
||||||
st::defaultBoxCheckbox,
|
|
||||||
std::move(checkView)),
|
|
||||||
{
|
|
||||||
st::boxRowPadding.left(),
|
|
||||||
st::boxRowPadding.left(),
|
|
||||||
st::boxRowPadding.right(),
|
|
||||||
st::defaultBoxCheckbox.margin.bottom(),
|
|
||||||
});
|
|
||||||
row->setAllowTextLines(5);
|
|
||||||
row->setClickHandlerFilter([=](
|
|
||||||
const ClickHandlerPtr &link,
|
|
||||||
Qt::MouseButton button) {
|
|
||||||
ActivateClickHandler(row, link, ClickContext{
|
|
||||||
.button = button,
|
|
||||||
.other = QVariant::fromValue(ClickHandlerContext{
|
|
||||||
.show = box->uiShow(),
|
|
||||||
})
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
(*updateCheck) = [=] { row->update(); };
|
|
||||||
|
|
||||||
const auto showError = Ui::CheckView::PrepareNonToggledError(
|
|
||||||
check,
|
|
||||||
box->lifetime());
|
|
||||||
|
|
||||||
(*validateCheck) = [=] {
|
|
||||||
if (check->checked()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
showError();
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::ClearAll() {
|
void AttachWebView::ClearAll() {
|
||||||
@ -1355,7 +1356,8 @@ void AttachWebView::show(
|
|||||||
uint64 queryId,
|
uint64 queryId,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &buttonText,
|
const QString &buttonText,
|
||||||
bool allowClipboardRead) {
|
bool allowClipboardRead,
|
||||||
|
const BotAppData *app) {
|
||||||
Expects(_bot != nullptr && _context != nullptr);
|
Expects(_bot != nullptr && _context != nullptr);
|
||||||
|
|
||||||
auto title = Info::Profile::NameValue(_bot);
|
auto title = Info::Profile::NameValue(_bot);
|
||||||
@ -1366,12 +1368,15 @@ void AttachWebView::show(
|
|||||||
_attachBots,
|
_attachBots,
|
||||||
not_null{ _bot },
|
not_null{ _bot },
|
||||||
&AttachWebViewBot::user);
|
&AttachWebViewBot::user);
|
||||||
const auto hasSettings = (attached != end(_attachBots))
|
const auto hasSettings = app
|
||||||
|
? app->hasSettings
|
||||||
|
: ((attached != end(_attachBots))
|
||||||
&& !attached->inactive
|
&& !attached->inactive
|
||||||
&& attached->hasSettings;
|
&& attached->hasSettings);
|
||||||
const auto hasOpenBot = !_context
|
const auto hasOpenBot = !_context
|
||||||
|| (_bot != _context->action.history->peer);
|
|| (_bot != _context->action.history->peer);
|
||||||
const auto hasRemoveFromMenu = (attached != end(_attachBots))
|
const auto hasRemoveFromMenu = !app
|
||||||
|
&& (attached != end(_attachBots))
|
||||||
&& (!attached->inactive || attached->inMainMenu);
|
&& (!attached->inactive || attached->inMainMenu);
|
||||||
const auto buttons = (hasSettings ? Button::Settings : Button::None)
|
const auto buttons = (hasSettings ? Button::Settings : Button::None)
|
||||||
| (hasOpenBot ? Button::OpenBot : Button::None)
|
| (hasOpenBot ? Button::OpenBot : Button::None)
|
||||||
@ -1473,6 +1478,14 @@ void AttachWebView::confirmAddToMenu(
|
|||||||
});
|
});
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
const auto disclaimer = showingDisclaimer(bot);
|
||||||
|
if (disclaimer) {
|
||||||
|
FillDisclaimerBox(box, [=] {
|
||||||
|
_disclaimerAccepted.emplace(bot.user);
|
||||||
|
_attachBotsUpdates.fire({});
|
||||||
|
done([] {});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
Ui::ConfirmBox(box, {
|
Ui::ConfirmBox(box, {
|
||||||
(bot.inMainMenu
|
(bot.inMainMenu
|
||||||
? tr::lng_bot_add_to_side_menu
|
? tr::lng_bot_add_to_side_menu
|
||||||
@ -1483,6 +1496,7 @@ void AttachWebView::confirmAddToMenu(
|
|||||||
Ui::Text::WithEntities),
|
Ui::Text::WithEntities),
|
||||||
done,
|
done,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
if (bot.requestWriteAccess) {
|
if (bot.requestWriteAccess) {
|
||||||
(*allowed) = box->addRow(
|
(*allowed) = box->addRow(
|
||||||
object_ptr<Ui::Checkbox>(
|
object_ptr<Ui::Checkbox>(
|
||||||
@ -1496,11 +1510,27 @@ void AttachWebView::confirmAddToMenu(
|
|||||||
st::urlAuthCheckbox),
|
st::urlAuthCheckbox),
|
||||||
style::margins(
|
style::margins(
|
||||||
st::boxRowPadding.left(),
|
st::boxRowPadding.left(),
|
||||||
st::boxPhotoCaptionSkip,
|
(disclaimer
|
||||||
|
? st::boxPhotoCaptionSkip
|
||||||
|
: st::boxRowPadding.left()),
|
||||||
st::boxRowPadding.right(),
|
st::boxRowPadding.right(),
|
||||||
st::boxPhotoCaptionSkip));
|
st::boxRowPadding.left()));
|
||||||
(*allowed)->setAllowTextLines();
|
(*allowed)->setAllowTextLines();
|
||||||
}
|
}
|
||||||
|
if (disclaimer) {
|
||||||
|
if (!bot.requestWriteAccess) {
|
||||||
|
box->addRow(object_ptr<Ui::FixedHeightWidget>(
|
||||||
|
box,
|
||||||
|
st::boxRowPadding.left()));
|
||||||
|
}
|
||||||
|
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||||
|
box,
|
||||||
|
tr::lng_bot_will_be_added(
|
||||||
|
lt_bot,
|
||||||
|
rpl::single(Ui::Text::Bold(bot.name)),
|
||||||
|
Ui::Text::WithEntities),
|
||||||
|
st::boxLabel));
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ public:
|
|||||||
[[nodiscard]] rpl::producer<> attachBotsUpdates() const {
|
[[nodiscard]] rpl::producer<> attachBotsUpdates() const {
|
||||||
return _attachBotsUpdates.events();
|
return _attachBotsUpdates.events();
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] bool showingDisclaimer(const AttachWebViewBot &bot) const;
|
||||||
|
|
||||||
void requestAddToMenu(
|
void requestAddToMenu(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
@ -195,7 +196,8 @@ private:
|
|||||||
uint64 queryId,
|
uint64 queryId,
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &buttonText = QString(),
|
const QString &buttonText = QString(),
|
||||||
bool allowClipboardRead = false);
|
bool allowClipboardRead = false,
|
||||||
|
const BotAppData *app = nullptr);
|
||||||
void confirmAddToMenu(
|
void confirmAddToMenu(
|
||||||
AttachWebViewBot bot,
|
AttachWebViewBot bot,
|
||||||
Fn<void()> callback = nullptr);
|
Fn<void()> callback = nullptr);
|
||||||
@ -238,6 +240,7 @@ private:
|
|||||||
|
|
||||||
std::vector<AttachWebViewBot> _attachBots;
|
std::vector<AttachWebViewBot> _attachBots;
|
||||||
rpl::event_stream<> _attachBotsUpdates;
|
rpl::event_stream<> _attachBotsUpdates;
|
||||||
|
base::flat_set<not_null<UserData*>> _disclaimerAccepted;
|
||||||
|
|
||||||
std::unique_ptr<Ui::BotWebView::Panel> _panel;
|
std::unique_ptr<Ui::BotWebView::Panel> _panel;
|
||||||
|
|
||||||
|
@ -24,7 +24,9 @@ void ConfirmBox(not_null<Ui::GenericBox*> box, ConfirmBoxArgs &&args) {
|
|||||||
|
|
||||||
if (!v::is_null(args.text)) {
|
if (!v::is_null(args.text)) {
|
||||||
const auto padding = st::boxPadding;
|
const auto padding = st::boxPadding;
|
||||||
const auto use = withTitle
|
const auto use = args.labelPadding
|
||||||
|
? *args.labelPadding
|
||||||
|
: withTitle
|
||||||
? QMargins(padding.left(), 0, padding.right(), padding.bottom())
|
? QMargins(padding.left(), 0, padding.right(), padding.bottom())
|
||||||
: padding;
|
: padding;
|
||||||
const auto label = box->addRow(
|
const auto label = box->addRow(
|
||||||
|
@ -30,6 +30,7 @@ struct ConfirmBoxArgs {
|
|||||||
|
|
||||||
const style::FlatLabel *labelStyle = nullptr;
|
const style::FlatLabel *labelStyle = nullptr;
|
||||||
Fn<bool(const ClickHandlerPtr&, Qt::MouseButton)> labelFilter;
|
Fn<bool(const ClickHandlerPtr&, Qt::MouseButton)> labelFilter;
|
||||||
|
std::optional<QMargins> labelPadding;
|
||||||
|
|
||||||
v::text::data title = v::null;
|
v::text::data title = v::null;
|
||||||
|
|
||||||
|
@ -561,10 +561,6 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
|||||||
_widget->showInner(std::move(outer));
|
_widget->showInner(std::move(outer));
|
||||||
_webviewParent = container;
|
_webviewParent = container;
|
||||||
|
|
||||||
container->paintRequest() | rpl::start_with_next([=] {
|
|
||||||
QPainter(container).fillRect(container->rect(), QColor(0, 128, 0, 255));
|
|
||||||
}, container->lifetime());
|
|
||||||
|
|
||||||
_webviewBottom = std::make_unique<RpWidget>(_widget.get());
|
_webviewBottom = std::make_unique<RpWidget>(_widget.get());
|
||||||
const auto bottom = _webviewBottom.get();
|
const auto bottom = _webviewBottom.get();
|
||||||
bottom->show();
|
bottom->show();
|
||||||
|
@ -211,15 +211,19 @@ void SetupMenuBots(
|
|||||||
) | rpl::then(
|
) | rpl::then(
|
||||||
bots->attachBotsUpdates()
|
bots->attachBotsUpdates()
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
|
const auto width = wrap->widthNoMargins();
|
||||||
wrap->clear();
|
wrap->clear();
|
||||||
for (const auto &bot : bots->attachBots()) {
|
for (const auto &bot : bots->attachBots()) {
|
||||||
if (!bot.inMainMenu) {
|
if (!bot.inMainMenu) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto button = Settings::AddButton(
|
const auto button = Settings::AddButton(
|
||||||
container,
|
wrap,
|
||||||
rpl::single(bot.name),
|
rpl::single(bot.name),
|
||||||
st::mainMenuButton);
|
st::mainMenuButton);
|
||||||
|
const auto menu = button->lifetime().make_state<
|
||||||
|
base::unique_qptr<Ui::PopupMenu>
|
||||||
|
>();
|
||||||
const auto icon = Ui::CreateChild<InlineBots::MenuBotIcon>(
|
const auto icon = Ui::CreateChild<InlineBots::MenuBotIcon>(
|
||||||
button.get(),
|
button.get(),
|
||||||
bot.media);
|
bot.media);
|
||||||
@ -229,12 +233,57 @@ void SetupMenuBots(
|
|||||||
st::mainMenuButton.iconLeft,
|
st::mainMenuButton.iconLeft,
|
||||||
(height - icon->height()) / 2);
|
(height - icon->height()) / 2);
|
||||||
}, button->lifetime());
|
}, button->lifetime());
|
||||||
button->setClickedCallback([=] {
|
const auto user = bot.user;
|
||||||
bots->requestSimple(controller, bot.user, {
|
button->setAcceptBoth(true);
|
||||||
|
button->clicks(
|
||||||
|
) | rpl::start_with_next([=](Qt::MouseButton which) {
|
||||||
|
if (which == Qt::LeftButton) {
|
||||||
|
bots->requestSimple(controller, user, {
|
||||||
.fromMainMenu = true,
|
.fromMainMenu = true,
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
(*menu) = nullptr;
|
||||||
|
(*menu) = base::make_unique_q<Ui::PopupMenu>(
|
||||||
|
button,
|
||||||
|
st::popupMenuWithIcons);
|
||||||
|
(*menu)->addAction(
|
||||||
|
tr::lng_bot_remove_from_menu(tr::now),
|
||||||
|
[=] { bots->removeFromMenu(user); },
|
||||||
|
&st::menuIconDelete);
|
||||||
|
(*menu)->popup(QCursor::pos());
|
||||||
}
|
}
|
||||||
|
}, button->lifetime());
|
||||||
|
|
||||||
|
const auto badge = bots->showingDisclaimer(bot)
|
||||||
|
? Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
|
||||||
|
button.get(),
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
button,
|
||||||
|
tr::lng_bot_side_menu_new(),
|
||||||
|
st::settingsPremiumNewBadge),
|
||||||
|
st::settingsPremiumNewBadgePadding)
|
||||||
|
: nullptr;
|
||||||
|
if (badge) {
|
||||||
|
badge->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
badge->paintRequest() | rpl::start_with_next([=] {
|
||||||
|
auto p = QPainter(badge);
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(st::windowBgActive);
|
||||||
|
const auto r = st::settingsPremiumNewBadgePadding.left();
|
||||||
|
p.drawRoundedRect(badge->rect(), r, r);
|
||||||
|
}, badge->lifetime());
|
||||||
|
|
||||||
|
button->sizeValue(
|
||||||
|
) | rpl::start_with_next([=](QSize size) {
|
||||||
|
badge->moveToRight(
|
||||||
|
st::mainMenuButton.padding.right(),
|
||||||
|
(size.height() - badge->height()) / 2,
|
||||||
|
size.width());
|
||||||
|
}, badge->lifetime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrap->resizeToWidth(width);
|
||||||
}, wrap->lifetime());
|
}, wrap->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user