mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 15:43:55 +02:00
Added initial api support of bank card entity in messages.
This commit is contained in:
parent
75b33c906d
commit
0fe9dad515
9 changed files with 305 additions and 1 deletions
|
@ -446,6 +446,8 @@ PRIVATE
|
||||||
chat_helpers/ttl_media_layer_widget.h
|
chat_helpers/ttl_media_layer_widget.h
|
||||||
core/application.cpp
|
core/application.cpp
|
||||||
core/application.h
|
core/application.h
|
||||||
|
core/bank_card_click_handler.cpp
|
||||||
|
core/bank_card_click_handler.h
|
||||||
core/base_integration.cpp
|
core/base_integration.cpp
|
||||||
core/base_integration.h
|
core/base_integration.h
|
||||||
core/changelogs.cpp
|
core/changelogs.cpp
|
||||||
|
|
|
@ -6440,6 +6440,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_frozen_text3" = "Appeal via {link} before {date}, or your account will be deleted.";
|
"lng_frozen_text3" = "Appeal via {link} before {date}, or your account will be deleted.";
|
||||||
"lng_frozen_appeal_button" = "Submit an Appeal";
|
"lng_frozen_appeal_button" = "Submit an Appeal";
|
||||||
|
|
||||||
|
"lng_context_bank_card_copy" = "Copy Card Number";
|
||||||
|
"lng_context_bank_card_copied" = "Card number copied to clipboard.";
|
||||||
|
|
||||||
// Wnd specific
|
// Wnd specific
|
||||||
|
|
||||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||||
|
|
|
@ -202,7 +202,11 @@ EntitiesInText EntitiesFromMTP(
|
||||||
d.vlength().v,
|
d.vlength().v,
|
||||||
});
|
});
|
||||||
}, [&](const MTPDmessageEntityBankCard &d) {
|
}, [&](const MTPDmessageEntityBankCard &d) {
|
||||||
// Skipping cards. // #TODO entities
|
result.push_back({
|
||||||
|
EntityType::BankCard,
|
||||||
|
d.voffset().v,
|
||||||
|
d.vlength().v,
|
||||||
|
});
|
||||||
}, [&](const MTPDmessageEntitySpoiler &d) {
|
}, [&](const MTPDmessageEntitySpoiler &d) {
|
||||||
result.push_back({
|
result.push_back({
|
||||||
EntityType::Spoiler,
|
EntityType::Spoiler,
|
||||||
|
@ -273,6 +277,9 @@ MTPVector<MTPMessageEntity> EntitiesToMTP(
|
||||||
case EntityType::Phone: {
|
case EntityType::Phone: {
|
||||||
v.push_back(MTP_messageEntityPhone(offset, length));
|
v.push_back(MTP_messageEntityPhone(offset, length));
|
||||||
} break;
|
} break;
|
||||||
|
case EntityType::BankCard: {
|
||||||
|
v.push_back(MTP_messageEntityBankCard(offset, length));
|
||||||
|
} break;
|
||||||
case EntityType::Hashtag: {
|
case EntityType::Hashtag: {
|
||||||
v.push_back(MTP_messageEntityHashtag(offset, length));
|
v.push_back(MTP_messageEntityHashtag(offset, length));
|
||||||
} break;
|
} break;
|
||||||
|
|
254
Telegram/SourceFiles/core/bank_card_click_handler.cpp
Normal file
254
Telegram/SourceFiles/core/bank_card_click_handler.cpp
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "core/bank_card_click_handler.h"
|
||||||
|
|
||||||
|
#include "core/click_handler_types.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_user.h"
|
||||||
|
#include "lang/lang_keys.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
#include "mtproto/sender.h"
|
||||||
|
#include "ui/painter.h"
|
||||||
|
#include "ui/rect.h"
|
||||||
|
#include "ui/widgets/menu/menu_multiline_action.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
|
#include "window/window_controller.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
#include "styles/style_calls.h"
|
||||||
|
#include "styles/style_chat.h" // popupMenuExpandedSeparator.
|
||||||
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct State final {
|
||||||
|
State(not_null<Main::Session*> session) : sender(&session->mtp()) {
|
||||||
|
}
|
||||||
|
MTP::Sender sender;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BankCardData final {
|
||||||
|
QString title;
|
||||||
|
std::vector<EntityLinkData> links;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Status {
|
||||||
|
Loading,
|
||||||
|
Resolved,
|
||||||
|
Failed,
|
||||||
|
};
|
||||||
|
|
||||||
|
void RequestResolveBankCard(
|
||||||
|
not_null<State*> state,
|
||||||
|
const QString &bankCard,
|
||||||
|
Fn<void(BankCardData)> done,
|
||||||
|
Fn<void(QString)> fail) {
|
||||||
|
state->sender.request(MTPpayments_GetBankCardData(
|
||||||
|
MTP_string(bankCard)
|
||||||
|
)).done([=](const MTPpayments_BankCardData &result) {
|
||||||
|
auto bankCardData = BankCardData{
|
||||||
|
.title = qs(result.data().vtitle()),
|
||||||
|
};
|
||||||
|
for (const auto &tl : result.data().vopen_urls().v) {
|
||||||
|
const auto url = qs(tl.data().vurl());
|
||||||
|
const auto name = qs(tl.data().vname());
|
||||||
|
|
||||||
|
bankCardData.links.emplace_back(EntityLinkData{
|
||||||
|
.text = name,
|
||||||
|
.data = url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
done(std::move(bankCardData));
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
fail(error.type());
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResolveBankCardAction final : public Ui::Menu::ItemBase {
|
||||||
|
public:
|
||||||
|
ResolveBankCardAction(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::Menu &st);
|
||||||
|
|
||||||
|
void setStatus(Status status);
|
||||||
|
|
||||||
|
bool isEnabled() const override;
|
||||||
|
not_null<QAction*> action() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int contentHeight() const override;
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paint(Painter &p);
|
||||||
|
|
||||||
|
const not_null<QAction*> _dummyAction;
|
||||||
|
const style::Menu &_st;
|
||||||
|
const int _height = 0;
|
||||||
|
Status _status = Status::Loading;
|
||||||
|
|
||||||
|
Ui::Text::String _text;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ResolveBankCardAction::ResolveBankCardAction(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const style::Menu &st)
|
||||||
|
: ItemBase(parent, st)
|
||||||
|
, _dummyAction(Ui::CreateChild<QAction>(parent))
|
||||||
|
, _st(st)
|
||||||
|
, _height(st::groupCallJoinAsPhotoSize) {
|
||||||
|
setAcceptBoth(true);
|
||||||
|
initResizeHook(parent->sizeValue());
|
||||||
|
setStatus(Status::Loading);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResolveBankCardAction::setStatus(Status status) {
|
||||||
|
_status = status;
|
||||||
|
if (status == Status::Resolved) {
|
||||||
|
resize(width(), 0);
|
||||||
|
} else if (status == Status::Failed) {
|
||||||
|
_text.setText(_st.itemStyle, tr::lng_attach_failed(tr::now));
|
||||||
|
} else if (status == Status::Loading) {
|
||||||
|
_text.setText(_st.itemStyle, tr::lng_contacts_loading(tr::now));
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResolveBankCardAction::paintEvent(QPaintEvent *e) {
|
||||||
|
auto p = QPainter(this);
|
||||||
|
|
||||||
|
const auto selected = false;
|
||||||
|
const auto height = contentHeight();
|
||||||
|
if (selected && _st.itemBgOver->c.alpha() < 255) {
|
||||||
|
p.fillRect(0, 0, width(), height, _st.itemBg);
|
||||||
|
}
|
||||||
|
p.fillRect(0, 0, width(), height, selected ? _st.itemBgOver : _st.itemBg);
|
||||||
|
|
||||||
|
const auto &padding = st::groupCallJoinAsPadding;
|
||||||
|
const auto textLeft = padding.left()
|
||||||
|
+ st::groupCallJoinAsPhotoSize
|
||||||
|
+ padding.left();
|
||||||
|
{
|
||||||
|
p.setPen(selected ? _st.itemFgShortcutOver : _st.itemFgShortcut);
|
||||||
|
const auto w = width() - padding.left() - padding.right();
|
||||||
|
_text.draw(p, Ui::Text::PaintContext{
|
||||||
|
.position = QPoint(
|
||||||
|
(width() - w) / 2,
|
||||||
|
(height - _text.countHeight(w)) / 2),
|
||||||
|
.outerWidth = w,
|
||||||
|
.availableWidth = w,
|
||||||
|
.align = style::al_center,
|
||||||
|
.elisionLines = 2,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResolveBankCardAction::isEnabled() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<QAction*> ResolveBankCardAction::action() const {
|
||||||
|
return _dummyAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResolveBankCardAction::contentHeight() const {
|
||||||
|
if (_status == Status::Resolved) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return _height;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
BankCardClickHandler::BankCardClickHandler(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
QString text)
|
||||||
|
: _session(session)
|
||||||
|
, _text(text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void BankCardClickHandler::onClick(ClickContext context) const {
|
||||||
|
if (context.button != Qt::LeftButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto my = context.other.value<ClickHandlerContext>();
|
||||||
|
const auto controller = my.sessionWindow.get();
|
||||||
|
const auto pos = QCursor::pos();
|
||||||
|
if (!controller) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto menu = Ui::CreateChild<Ui::PopupMenu>(
|
||||||
|
controller->content(),
|
||||||
|
st::popupMenuWithIcons);
|
||||||
|
|
||||||
|
const auto bankCard = _text;
|
||||||
|
|
||||||
|
const auto copy = [bankCard, show = controller->uiShow()] {
|
||||||
|
TextUtilities::SetClipboardText(
|
||||||
|
TextForMimeData::Simple(bankCard));
|
||||||
|
show->showToast(tr::lng_context_bank_card_copied(tr::now));
|
||||||
|
};
|
||||||
|
|
||||||
|
menu->addAction(
|
||||||
|
tr::lng_context_bank_card_copy(tr::now),
|
||||||
|
copy,
|
||||||
|
&st::menuIconCopy);
|
||||||
|
|
||||||
|
auto resolveBankCardAction = base::make_unique_q<ResolveBankCardAction>(
|
||||||
|
menu,
|
||||||
|
menu->st().menu);
|
||||||
|
const auto resolveBankCardRaw = resolveBankCardAction.get();
|
||||||
|
|
||||||
|
menu->addSeparator(&st::popupMenuExpandedSeparator.menu.separator);
|
||||||
|
|
||||||
|
menu->addAction(std::move(resolveBankCardAction));
|
||||||
|
|
||||||
|
const auto addTitle = [=](const QString &name) {
|
||||||
|
auto button = base::make_unique_q<Ui::Menu::MultilineAction>(
|
||||||
|
menu,
|
||||||
|
menu->st().menu,
|
||||||
|
st::historyHasCustomEmoji,
|
||||||
|
st::historyBankCardMenuMultilinePosition,
|
||||||
|
TextWithEntities{ name });
|
||||||
|
button->setClickedCallback(copy);
|
||||||
|
menu->addAction(std::move(button));
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto state = menu->lifetime().make_state<State>(
|
||||||
|
&controller->session());
|
||||||
|
RequestResolveBankCard(
|
||||||
|
state,
|
||||||
|
bankCard,
|
||||||
|
[=](BankCardData data) {
|
||||||
|
resolveBankCardRaw->setStatus(Status::Resolved);
|
||||||
|
for (auto &link : data.links) {
|
||||||
|
menu->addAction(
|
||||||
|
base::take(link.text),
|
||||||
|
[u = base::take(link.data)] { UrlClickHandler::Open(u); },
|
||||||
|
&st::menuIconPayment);
|
||||||
|
}
|
||||||
|
if (!data.title.isEmpty()) {
|
||||||
|
addTitle(base::take(data.title));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[=](const QString &) {
|
||||||
|
resolveBankCardRaw->setStatus(Status::Failed);
|
||||||
|
});
|
||||||
|
|
||||||
|
menu->popup(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BankCardClickHandler::getTextEntity() const -> TextEntity {
|
||||||
|
return { EntityType::BankCard };
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BankCardClickHandler::tooltip() const {
|
||||||
|
return _text;
|
||||||
|
}
|
30
Telegram/SourceFiles/core/bank_card_click_handler.h
Normal file
30
Telegram/SourceFiles/core/bank_card_click_handler.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui/basic_click_handlers.h"
|
||||||
|
|
||||||
|
namespace Main {
|
||||||
|
class Session;
|
||||||
|
} // namespace Main
|
||||||
|
|
||||||
|
class BankCardClickHandler : public ClickHandler {
|
||||||
|
public:
|
||||||
|
BankCardClickHandler(not_null<Main::Session*> session, QString text);
|
||||||
|
|
||||||
|
void onClick(ClickContext context) const override;
|
||||||
|
|
||||||
|
TextEntity getTextEntity() const override;
|
||||||
|
|
||||||
|
QString tooltip() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const not_null<Main::Session*> _session;
|
||||||
|
QString _text;
|
||||||
|
|
||||||
|
};
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/local_url_handlers.h"
|
#include "core/local_url_handlers.h"
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#include "core/bank_card_click_handler.h"
|
||||||
#include "core/sandbox.h"
|
#include "core/sandbox.h"
|
||||||
#include "core/click_handler_types.h"
|
#include "core/click_handler_types.h"
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
|
@ -256,6 +257,10 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
|
||||||
return my->session
|
return my->session
|
||||||
? std::make_shared<PhoneClickHandler>(my->session, data.text)
|
? std::make_shared<PhoneClickHandler>(my->session, data.text)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
case EntityType::BankCard:
|
||||||
|
return my->session
|
||||||
|
? std::make_shared<BankCardClickHandler>(my->session, data.text)
|
||||||
|
: nullptr;
|
||||||
}
|
}
|
||||||
return Integration::createLinkHandler(data, context);
|
return Integration::createLinkHandler(data, context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3464,6 +3464,7 @@ void HistoryItem::setText(const TextWithEntities &textWithEntities) {
|
||||||
if (type == EntityType::Url
|
if (type == EntityType::Url
|
||||||
|| type == EntityType::CustomUrl
|
|| type == EntityType::CustomUrl
|
||||||
|| type == EntityType::Phone
|
|| type == EntityType::Phone
|
||||||
|
|| type == EntityType::BankCard
|
||||||
|| type == EntityType::Email) {
|
|| type == EntityType::Email) {
|
||||||
_flags |= MessageFlag::HasTextLinks;
|
_flags |= MessageFlag::HasTextLinks;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -949,6 +949,7 @@ historyHasCustomEmoji: FlatLabel(defaultFlatLabel) {
|
||||||
minWidth: 80px;
|
minWidth: 80px;
|
||||||
}
|
}
|
||||||
historyHasCustomEmojiPosition: point(12px, 4px);
|
historyHasCustomEmojiPosition: point(12px, 4px);
|
||||||
|
historyBankCardMenuMultilinePosition: point(18px, 4px);
|
||||||
|
|
||||||
historyTranslateLabel: FlatLabel(defaultFlatLabel) {
|
historyTranslateLabel: FlatLabel(defaultFlatLabel) {
|
||||||
style: semiboldTextStyle;
|
style: semiboldTextStyle;
|
||||||
|
|
|
@ -178,6 +178,7 @@ menuIconNftWear: icon {{ "menu/nft_wear", menuIconColor }};
|
||||||
menuIconNftTakeOff: icon {{ "menu/nft_takeoff", menuIconColor }};
|
menuIconNftTakeOff: icon {{ "menu/nft_takeoff", menuIconColor }};
|
||||||
menuIconShortcut: icon {{ "menu/shortcut", menuIconColor }};
|
menuIconShortcut: icon {{ "menu/shortcut", menuIconColor }};
|
||||||
menuIconHourglass: icon {{ "menu/hourglass", menuIconColor }};
|
menuIconHourglass: icon {{ "menu/hourglass", menuIconColor }};
|
||||||
|
menuIconPayment: icon {{ "payments/payment_card", menuIconColor }};
|
||||||
|
|
||||||
menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }};
|
menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }};
|
||||||
menuIconTTLAnyTextPosition: point(11px, 22px);
|
menuIconTTLAnyTextPosition: point(11px, 22px);
|
||||||
|
|
Loading…
Add table
Reference in a new issue