ZaStoGram_desktop/Telegram/SourceFiles/wallet/wallet_panel.cpp
John Preston 22b352e866 Show Connected Apps in the wallet menu only when apps are connected
Task: 2026/10/08/show-connected-apps-only-when-apps-are-connected
2026-10-08 23:28:04 +04:00

269 lines
7.6 KiB
C++

/*
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 "wallet/wallet_panel.h"
#include "base/qthelp_regex.h"
#include "core/application.h"
#include "core/shortcuts.h"
#include "data/data_user.h"
#include "lang/lang_keys.h"
#include "main/session/session_show.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_domain.h"
#include "main/main_session.h"
#include "ui/controls/ton_common.h"
#include "ui/widgets/menu/menu_add_action_callback.h"
#include "ui/widgets/separate_panel.h"
#include "wallet/wallet_address.h"
#include "wallet/wallet_content.h"
#include "wallet/wallet_palette.h"
#include "wallet/wallet_session.h"
#include "wallet/wallet_ton_connect.h"
#include "wallet/wallet_ton_connect_link.h"
#include "wallet/wallet_ton_connect_request.h"
#include "wallet/wallet_user_addresses.h"
#include "window/window_controller.h"
#include "window/window_session_controller.h"
#include "styles/style_wallet.h"
namespace Wallet {
namespace {
[[nodiscard]] Ui::SeparatePanel *ActivePanel() {
for (const auto &[index, account] : Core::App().domain().accounts()) {
if (!account->sessionExists()) {
continue;
}
const auto panel = account->session().wallet().panel();
if (panel && panel->isActiveWindow()) {
return panel;
}
}
return nullptr;
}
// A link amount counts Grams with a dot; a comma is refused.
[[nodiscard]] std::optional<int64> ParseLinkAmount(const QString &amount) {
if (amount.isEmpty()) {
return 0;
} else if (!qthelp::regex_match(u"^\\d+(\\.\\d+)?$"_q, amount, {})) {
return std::nullopt;
}
return Ui::ParseTonAmountString(amount, u"."_q);
}
} // namespace
not_null<Ui::SeparatePanel*> ShowWallet(not_null<Main::Session*> session) {
auto &wallet = session->wallet();
wallet.tonConnect().refreshSessions();
if (const auto exists = wallet.panel()) {
const auto state = exists->windowState();
if (state & Qt::WindowMinimized) {
exists->setWindowState(state & ~Qt::WindowMinimized);
}
exists->showAndActivate();
return exists;
}
auto owned = std::make_unique<Ui::SeparatePanel>();
const auto panel = owned.get();
UseWindowPalette(panel);
const auto show = Main::MakeSessionShow(panel->uiShow(), session);
panel->setWindowFlag(Qt::WindowStaysOnTopHint, false);
Shortcuts::Listen(panel); // Main window may be hidden to tray.
panel->setInnerSize(st::walletPanelSize);
rpl::single(rpl::empty) | rpl::then(
style::PaletteChanged()
) | rpl::on_next([=] {
const auto scope = WindowPaletteScope(panel);
panel->overrideTitleColor(st::windowBgOver->c);
panel->overrideBottomBarColor(st::windowBgOver->c);
panel->overrideBodyColor(WindowPalette()
? std::make_optional(st::windowBg->c)
: std::nullopt);
}, panel->lifetime());
TransactionsShownValue(
session
) | rpl::on_next([=](bool shown) {
panel->setBottomBarHeight(shown ? st::walletRowsHintHeight : 0);
}, panel->lifetime());
panel->setMenuAllowed([=](const Ui::Menu::MenuCallback &addAction) {
FillMenu(show, addAction);
});
panel->windowActiveValue(
) | rpl::filter(rpl::mappers::_1) | rpl::on_next([=] {
session->wallet().tonConnect().refreshSessions();
}, panel->lifetime());
panel->closeRequests(
) | rpl::on_next([=] {
panel->hideGetDuration();
}, panel->lifetime());
panel->closeEvents(
) | rpl::on_next([=] {
session->wallet().setPanel(nullptr);
}, panel->lifetime());
wallet.setPanel(std::move(owned));
panel->showInner(CreateContent(panel, show));
return panel;
}
void CloseWallet(not_null<Main::Session*> session) {
session->wallet().setPanel(nullptr);
}
bool CloseActiveWindow() {
if (const auto panel = ActivePanel()) {
panel->close();
return true;
}
return false;
}
bool MinimizeActiveWindow() {
if (const auto panel = ActivePanel()) {
panel->setWindowState(panel->windowState() | Qt::WindowMinimized);
return true;
}
return false;
}
void OpenTransferLink(
not_null<Window::SessionController*> controller,
const QString &url) {
if (!TransferLinkValid(url)) {
controller->showToast(tr::lng_wallet_send_invalid_address(tr::now));
return;
}
const auto link = ParseTransferLink(url);
if (link && TransferLinkExpired(link->expiresAt)) {
controller->showToast(tr::lng_wallet_send_link_expired(tr::now));
return;
}
const auto session = &controller->session();
const auto panel = ShowWallet(session);
ShowTransferLink(Main::MakeSessionShow(panel->uiShow(), session), url);
}
void OpenSendGramsLink(
not_null<Window::SessionController*> controller,
const QString &to,
const QString &amount) {
const auto amountNano = ParseLinkAmount(amount);
if (!amountNano || (to.isEmpty() && !amount.isEmpty())) {
controller->showToast(tr::lng_wallet_send_link_invalid(tr::now));
return;
}
const auto session = &controller->session();
const auto panel = ShowWallet(session);
if (to.isEmpty()) {
return;
}
ShowSendToLinkRecipient(
Main::MakeSessionShow(panel->uiShow(), session),
to,
*amountNano);
}
void OpenAddressEntity(
not_null<Window::SessionController*> controller,
const QString &text) {
const auto address = text.trimmed();
if (!ParseAddress(address)) {
controller->showToast(tr::lng_wallet_send_link_invalid(tr::now));
return;
}
OpenSendGramsLink(controller, address, QString());
}
bool CanOfferSendMoney(not_null<UserData*> user) {
const auto session = &user->session();
auto &wallet = session->wallet();
return !session->supportMode()
&& session->appConfig().walletAvailable()
&& (wallet.presenceCurrent() != Presence::Unavailable)
&& wallet.userAddresses().recipientError(
peerToUser(user->id)).isEmpty();
}
void OpenSendMoney(
not_null<Window::SessionController*> controller,
not_null<UserData*> user,
Fn<void()> sent) {
const auto session = &controller->session();
if (&user->session() != session || !CanOfferSendMoney(user)) {
return;
}
const auto weak = base::make_weak(session);
ShowSendToUser(
controller->uiShow(),
user,
std::move(sent),
0,
[=] {
if (const auto strong = weak.get()) {
ShowWallet(strong);
}
});
}
void OpenTonConnectLink(
not_null<Window::SessionController*> controller,
const TonConnectLink &link) {
auto &tonConnect = controller->session().wallet().tonConnect();
if (link.kind == TonConnectLinkKind::OpenPending) {
tonConnect.requests().openPending(controller, link.clientId);
} else if (link.kind == TonConnectLinkKind::Connect) {
tonConnect.connect(controller, link);
} else {
ShowWallet(&controller->session());
}
}
void OpenTonConnectRequest(
not_null<Window::SessionController*> controller,
FullMsgId itemId) {
controller->session().wallet().tonConnect().requests().open(
controller,
itemId);
}
std::shared_ptr<Main::SessionShow> TonConnectBoxShow(
not_null<Window::SessionController*> controller) {
const auto session = &controller->session();
if (session->wallet().panel()) {
ShowWallet(session);
} else {
controller->window().activate();
}
return TonConnectBoxShowNoActivate(controller);
}
std::shared_ptr<Main::SessionShow> TonConnectBoxShowNoActivate(
not_null<Window::SessionController*> controller) {
const auto session = &controller->session();
if (const auto panel = session->wallet().panel()) {
return Main::MakeSessionShow(panel->uiShow(), session);
}
return controller->uiShow();
}
std::shared_ptr<Main::SessionShow> ActiveWindowShow(
not_null<Main::Session*> session) {
const auto panel = session->wallet().panel();
return (panel && panel->isActiveWindow())
? Main::MakeSessionShow(panel->uiShow(), session)
: nullptr;
}
} // namespace Wallet