mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Support bot emoji status access.
This commit is contained in:
parent
4198203a7f
commit
3d77bff0c9
15 changed files with 179 additions and 5 deletions
BIN
Telegram/Resources/animations/hello_status.tgs
Normal file
BIN
Telegram/Resources/animations/hello_status.tgs
Normal file
Binary file not shown.
|
@ -1461,6 +1461,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_profile_open_app" = "Open App";
|
||||
"lng_profile_open_app_about" = "By launching this mini app, you agree to the {terms}.";
|
||||
"lng_profile_open_app_terms" = "Terms of Service for Mini Apps";
|
||||
"lng_profile_bot_permissions_title" = "Allow access to";
|
||||
"lng_profile_bot_emoji_status_access" = "Emoji Status";
|
||||
"lng_info_add_as_contact" = "Add to contacts";
|
||||
"lng_profile_shared_media" = "Shared media";
|
||||
"lng_profile_suggest_photo" = "Suggest Profile Photo";
|
||||
|
@ -3421,6 +3423,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_bot_emoji_status_confirm" = "Confirm";
|
||||
"lng_bot_emoji_status_title" = "Set Emoji Status";
|
||||
"lng_bot_emoji_status_text" = "Do you want to set this emoji status suggested by {bot}?";
|
||||
"lng_bot_emoji_status_access_text" = "{bot} requests access to set your **emoji status**. You will be able to revoke this access in the profile page of {name}.";
|
||||
"lng_bot_emoji_status_access_allow" = "Allow";
|
||||
|
||||
"lng_bot_status_users#one" = "{count} monthly user";
|
||||
"lng_bot_status_users#other" = "{count} monthly users";
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
<file alias="collectible_phone.tgs">../../animations/collectible_phone.tgs</file>
|
||||
<file alias="search.tgs">../../animations/search.tgs</file>
|
||||
<file alias="noresults.tgs">../../animations/noresults.tgs</file>
|
||||
<file alias="hello_status.tgs">../../animations/hello_status.tgs</file>
|
||||
|
||||
<file alias="dice_idle.tgs">../../animations/dice/dice_idle.tgs</file>
|
||||
<file alias="dart_idle.tgs">../../animations/dice/dart_idle.tgs</file>
|
||||
|
|
|
@ -745,6 +745,14 @@ bool DocumentData::emojiUsesTextColor() const {
|
|||
return (_flags & Flag::UseTextColor);
|
||||
}
|
||||
|
||||
void DocumentData::overrideEmojiUsesTextColor(bool value) {
|
||||
if (value) {
|
||||
_flags |= Flag::UseTextColor;
|
||||
} else {
|
||||
_flags &= ~Flag::UseTextColor;
|
||||
}
|
||||
}
|
||||
|
||||
bool DocumentData::hasThumbnail() const {
|
||||
return _thumbnail.location.valid()
|
||||
&& !thumbnailFailed()
|
||||
|
|
|
@ -206,6 +206,7 @@ public:
|
|||
[[nodiscard]] bool isPremiumSticker() const;
|
||||
[[nodiscard]] bool isPremiumEmoji() const;
|
||||
[[nodiscard]] bool emojiUsesTextColor() const;
|
||||
void overrideEmojiUsesTextColor(bool value);
|
||||
|
||||
[[nodiscard]] bool hasThumbnail() const;
|
||||
[[nodiscard]] bool thumbnailLoading() const;
|
||||
|
|
|
@ -580,6 +580,9 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
|||
} else {
|
||||
user->setBotInfoVersion(-1);
|
||||
}
|
||||
if (const auto info = user->botInfo.get()) {
|
||||
info->canManageEmojiStatus = update.is_bot_can_manage_emoji_status();
|
||||
}
|
||||
if (const auto pinned = update.vpinned_msg_id()) {
|
||||
SetTopPinnedMessageId(user, pinned->v);
|
||||
}
|
||||
|
|
|
@ -2435,6 +2435,14 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
|||
if (const auto sticker = emojiStickers->stickerForEmoji(
|
||||
isolated)) {
|
||||
addDocumentActions(sticker.document, item);
|
||||
} else if (v::is<QString>(isolated.items.front())
|
||||
&& v::is_null(isolated.items[1])) {
|
||||
const auto id = v::get<QString>(isolated.items.front());
|
||||
const auto docId = id.toULongLong();
|
||||
const auto document = session->data().document(docId);
|
||||
if (document->sticker()) {
|
||||
addDocumentActions(document, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -470,6 +470,7 @@ infoIconMediaSaved: icon {{ "info/info_media_saved", infoIconFg }};
|
|||
infoIconMediaStoriesArchive: icon {{ "info/info_stories_archive", infoIconFg }};
|
||||
infoIconMediaStoriesRecent: icon {{ "info/info_stories_recent", infoIconFg }};
|
||||
infoIconMediaGifts: icon {{ "menu/gift_premium", infoIconFg, point(4px, 4px) }};
|
||||
infoIconEmojiStatusAccess: icon {{ "menu/read_reactions", infoIconFg, point(4px, 4px) }};
|
||||
|
||||
infoIconShare: icon {{ "info/info_share", infoIconFg }};
|
||||
infoIconEdit: icon {{ "info/info_edit", infoIconFg }};
|
||||
|
|
|
@ -958,6 +958,7 @@ private:
|
|||
object_ptr<Ui::RpWidget> setupInfo();
|
||||
object_ptr<Ui::RpWidget> setupMuteToggle();
|
||||
void setupMainApp();
|
||||
void setupBotPermissions();
|
||||
void setupMainButtons();
|
||||
Ui::MultiSlideTracker fillTopicButtons();
|
||||
Ui::MultiSlideTracker fillUserButtons(
|
||||
|
@ -1865,6 +1866,37 @@ void DetailsFiller::setupMainApp() {
|
|||
Ui::AddSkip(_wrap);
|
||||
}
|
||||
|
||||
void DetailsFiller::setupBotPermissions() {
|
||||
AddSkip(_wrap);
|
||||
AddSubsectionTitle(_wrap, tr::lng_profile_bot_permissions_title());
|
||||
const auto emoji = _wrap->add(
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
_wrap,
|
||||
tr::lng_profile_bot_emoji_status_access(),
|
||||
st::infoSharedMediaButton));
|
||||
object_ptr<Profile::FloatingIcon>(
|
||||
emoji,
|
||||
st::infoIconEmojiStatusAccess,
|
||||
st::infoSharedMediaButtonIconPosition);
|
||||
|
||||
const auto user = _peer->asUser();
|
||||
emoji->toggleOn(
|
||||
rpl::single(bool(user->botInfo->canManageEmojiStatus))
|
||||
)->toggledValue() | rpl::filter([=](bool allowed) {
|
||||
return allowed != user->botInfo->canManageEmojiStatus;
|
||||
}) | rpl::start_with_next([=](bool allowed) {
|
||||
user->botInfo->canManageEmojiStatus = allowed;
|
||||
const auto session = &user->session();
|
||||
session->api().request(MTPbots_ToggleUserEmojiStatusPermission(
|
||||
user->inputUser,
|
||||
MTP_bool(allowed)
|
||||
)).send();
|
||||
}, emoji->lifetime());
|
||||
AddSkip(_wrap);
|
||||
AddDivider(_wrap);
|
||||
AddSkip(_wrap);
|
||||
}
|
||||
|
||||
void DetailsFiller::setupMainButtons() {
|
||||
auto wrapButtons = [=](auto &&callback) {
|
||||
auto topSkip = _wrap->add(CreateSlideSkipWidget(_wrap));
|
||||
|
@ -2059,6 +2091,9 @@ object_ptr<Ui::RpWidget> DetailsFiller::fill() {
|
|||
if (info->hasMainApp) {
|
||||
setupMainApp();
|
||||
}
|
||||
if (info->canManageEmojiStatus) {
|
||||
setupBotPermissions();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_peer->isSelf()) {
|
||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/timer_rpl.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "chat_helpers/stickers_lottie.h"
|
||||
#include "chat_helpers/tabbed_panel.h"
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
|
@ -447,11 +448,21 @@ std::unique_ptr<Ui::RpWidget> MakeEmojiSetStatusPreview(
|
|||
raw,
|
||||
rpl::single(peer->name()),
|
||||
st::botEmojiStatusName);
|
||||
auto emojiText = TextWithEntities();
|
||||
const auto makeContext = [=](Fn<void()> update) {
|
||||
return Core::MarkedTextContext{
|
||||
.session = &peer->session(),
|
||||
.customEmojiRepaint = update,
|
||||
};
|
||||
};
|
||||
const auto emoji = raw->lifetime().make_state<Ui::FlatLabel>(
|
||||
raw,
|
||||
rpl::single(emojiText),
|
||||
st::botEmojiStatusName);
|
||||
rpl::single(
|
||||
Ui::Text::SingleCustomEmoji(
|
||||
Data::SerializeCustomEmojiId(document->id),
|
||||
document->sticker() ? document->sticker()->alt : QString())),
|
||||
st::botEmojiStatusEmoji,
|
||||
st::defaultPopupMenu,
|
||||
makeContext);
|
||||
const auto userpic = raw->lifetime().make_state<Ui::UserpicButton>(
|
||||
raw,
|
||||
peer,
|
||||
|
@ -496,6 +507,59 @@ std::unique_ptr<Ui::RpWidget> MakeEmojiSetStatusPreview(
|
|||
return result;
|
||||
}
|
||||
|
||||
void ConfirmEmojiStatusAccessBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<UserData*> bot,
|
||||
Fn<void(bool)> done) {
|
||||
box->setNoContentMargin(true);
|
||||
|
||||
const auto set = box->lifetime().make_state<bool>();
|
||||
|
||||
box->addTopButton(st::boxTitleClose, [=] {
|
||||
box->closeBox();
|
||||
});
|
||||
|
||||
AddSkip(box->verticalLayout(), 4 * st::defaultVerticalListSkip);
|
||||
|
||||
const auto statusIcon = ChatHelpers::GenerateLocalTgsSticker(
|
||||
&bot->session(),
|
||||
u"hello_status"_q);
|
||||
statusIcon->overrideEmojiUsesTextColor(true);
|
||||
|
||||
auto ownedSet = MakeEmojiSetStatusPreview(
|
||||
box,
|
||||
bot->session().user(),
|
||||
statusIcon);
|
||||
box->addRow(
|
||||
object_ptr<Ui::RpWidget>::fromRaw(ownedSet.release()));
|
||||
|
||||
AddSkip(box->verticalLayout(), 2 * st::defaultVerticalListSkip);
|
||||
|
||||
auto name = Ui::Text::Bold(bot->name());
|
||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
tr::lng_bot_emoji_status_access_text(
|
||||
lt_bot,
|
||||
rpl::single(name),
|
||||
lt_name,
|
||||
rpl::single(name),
|
||||
Ui::Text::RichLangValue),
|
||||
st::botEmojiStatusText));
|
||||
|
||||
box->addButton(tr::lng_bot_emoji_status_access_allow(), [=] {
|
||||
*set = true;
|
||||
box->closeBox();
|
||||
done(true);
|
||||
});
|
||||
box->addButton(tr::lng_cancel(), [=] {
|
||||
const auto was = *set;
|
||||
box->closeBox();
|
||||
if (!was) {
|
||||
done(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ConfirmEmojiStatusBox(
|
||||
not_null<Ui::GenericBox*> box,
|
||||
not_null<UserData*> bot,
|
||||
|
@ -511,6 +575,10 @@ void ConfirmEmojiStatusBox(
|
|||
|
||||
const auto set = box->lifetime().make_state<bool>();
|
||||
|
||||
box->addTopButton(st::boxTitleClose, [=] {
|
||||
box->closeBox();
|
||||
});
|
||||
|
||||
box->addRow(object_ptr<Ui::FlatLabel>(
|
||||
box,
|
||||
tr::lng_bot_emoji_status_title(),
|
||||
|
@ -525,7 +593,7 @@ void ConfirmEmojiStatusBox(
|
|||
Ui::Text::RichLangValue),
|
||||
st::botEmojiStatusText));
|
||||
|
||||
AddSkip(box->verticalLayout());
|
||||
AddSkip(box->verticalLayout(), 2 * st::defaultVerticalListSkip);
|
||||
|
||||
auto ownedSet = MakeEmojiSetStatusPreview(
|
||||
box,
|
||||
|
@ -1600,6 +1668,33 @@ void WebViewInstance::botAllowWriteAccess(Fn<void(bool allowed)> callback) {
|
|||
}).send();
|
||||
}
|
||||
|
||||
void WebViewInstance::botRequestEmojiStatusAccess(
|
||||
Fn<void(bool allowed)> callback) {
|
||||
if (_bot->botInfo->canManageEmojiStatus) {
|
||||
callback(true);
|
||||
} else if (const auto panel = _panel.get()) {
|
||||
const auto bot = _bot;
|
||||
panel->showBox(Box(ConfirmEmojiStatusAccessBox, bot, [=](bool ok) {
|
||||
if (!ok) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
const auto session = &bot->session();
|
||||
bot->botInfo->canManageEmojiStatus = true;
|
||||
session->api().request(MTPbots_ToggleUserEmojiStatusPermission(
|
||||
bot->inputUser,
|
||||
MTP_bool(true)
|
||||
)).done([=] {
|
||||
callback(true);
|
||||
}).fail([=] {
|
||||
callback(false);
|
||||
}).send();
|
||||
}));
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
|
||||
void WebViewInstance::botSharePhone(Fn<void(bool shared)> callback) {
|
||||
const auto history = _bot->owner().history(_bot);
|
||||
if (_bot->isBlocked()) {
|
||||
|
|
|
@ -260,6 +260,8 @@ private:
|
|||
QString query) override;
|
||||
void botCheckWriteAccess(Fn<void(bool allowed)> callback) override;
|
||||
void botAllowWriteAccess(Fn<void(bool allowed)> callback) override;
|
||||
void botRequestEmojiStatusAccess(
|
||||
Fn<void(bool allowed)> callback) override;
|
||||
void botSharePhone(Fn<void(bool shared)> callback) override;
|
||||
void botInvokeCustomMethod(
|
||||
Ui::BotWebView::CustomMethodRequest request) override;
|
||||
|
|
|
@ -774,7 +774,7 @@ void TopBarUser::updateTitle(
|
|||
{ EntityType::CustomEmoji, 0, 1, entityEmojiData },
|
||||
Ui::Text::Link(text, linkIndex).entities.front(),
|
||||
};
|
||||
auto title = (setId == coloredId)
|
||||
auto title = (setId != coloredId)
|
||||
? tr::lng_premium_emoji_status_title_colored(
|
||||
tr::now,
|
||||
lt_user,
|
||||
|
|
|
@ -826,6 +826,8 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
|||
processBottomBarColor(arguments);
|
||||
} else if (command == "web_app_set_emoji_status") {
|
||||
processEmojiStatusRequest(arguments);
|
||||
} else if (command == "web_app_request_emoji_status_access") {
|
||||
processEmojiStatusAccessRequest();
|
||||
} else if (command == "share_score") {
|
||||
_delegate->botHandleMenuButton(MenuButton::ShareGame);
|
||||
}
|
||||
|
@ -1000,6 +1002,15 @@ void Panel::processEmojiStatusRequest(const QJsonObject &args) {
|
|||
});
|
||||
}
|
||||
|
||||
void Panel::processEmojiStatusAccessRequest() {
|
||||
auto callback = crl::guard(this, [=](bool allowed) {
|
||||
postEvent("emoji_status_access_requested", allowed
|
||||
? "{ status: \"allowed\" }"
|
||||
: "{ status: \"cancelled\" }");
|
||||
});
|
||||
_delegate->botRequestEmojiStatusAccess(std::move(callback));
|
||||
}
|
||||
|
||||
void Panel::openTgLink(const QJsonObject &args) {
|
||||
if (args.isEmpty()) {
|
||||
LOG(("BotWebView Error: Bad arguments in 'web_app_open_tg_link'."));
|
||||
|
|
|
@ -71,6 +71,8 @@ public:
|
|||
QString query) = 0;
|
||||
virtual void botCheckWriteAccess(Fn<void(bool allowed)> callback) = 0;
|
||||
virtual void botAllowWriteAccess(Fn<void(bool allowed)> callback) = 0;
|
||||
virtual void botRequestEmojiStatusAccess(
|
||||
Fn<void(bool allowed)> callback) = 0;
|
||||
virtual void botSharePhone(Fn<void(bool shared)> callback) = 0;
|
||||
virtual void botInvokeCustomMethod(CustomMethodRequest request) = 0;
|
||||
virtual void botSetEmojiStatus(SetEmojiStatusRequest request) = 0;
|
||||
|
|
|
@ -1178,3 +1178,6 @@ botEmojiStatusUserpic: UserpicButton(defaultUserpicButton) {
|
|||
}
|
||||
botEmojiStatusName: FlatLabel(defaultFlatLabel) {
|
||||
}
|
||||
botEmojiStatusEmoji: FlatLabel(botEmojiStatusName) {
|
||||
textFg: profileVerifiedCheckBg;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue