diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index c5502085a..5e4afae2a 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -977,6 +977,24 @@ bool ResolveBoost( return true; } +bool ResolveChatLink( + Window::SessionController *controller, + const Match &match, + const QVariant &context) { + if (!controller) { + return false; + } + const auto myContext = context.value(); + const auto slug = match->captured(1); + controller->window().activate(); + controller->showPeerByLink(Window::PeerByLinkInfo{ + .chatLinkSlug = match->captured(1), + .clickFromMessageId = myContext.itemId, + .clickFromAttachBotWebviewUrl = myContext.attachBotWebviewUrl, + }); + return true; +} + } // namespace const std::vector &LocalUrlHandlers() { @@ -1046,11 +1064,11 @@ const std::vector &LocalUrlHandlers() { ResolveTestChatTheme, }, { - u"invoice/?\\?(.+)(#|$)"_q, + u"^invoice/?\\?(.+)(#|$)"_q, ResolveInvoice, }, { - u"premium_offer/?(\\?.+)?(#|$)"_q, + u"^premium_offer/?(\\?.+)?(#|$)"_q, ResolvePremiumOffer, }, { @@ -1065,6 +1083,10 @@ const std::vector &LocalUrlHandlers() { u"^boost/?\\?(.+)(#|$)"_q, ResolveBoost, }, + { + u"^message/?\\?slug=([a-zA-Z0-9\\.\\_]+)(&|$)"_q, + ResolveChatLink + }, { u"^([^\\?]+)(\\?|#|$)"_q, HandleUnknown @@ -1176,6 +1198,9 @@ QString TryConvertUrlToLocal(QString url) { ? "gradient" : "slug"; return u"tg://bg?"_q + type + '=' + bg + (params.isEmpty() ? QString() : '&' + params); + } else if (const auto chatlinkMatch = regex_match(u"^m/([a-zA-Z0-9\\.\\_\\-]+)(\\?|$)"_q, query, matchOptions)) { + const auto slug = chatlinkMatch->captured(1); + return u"tg://message?slug="_q + slug; } else if (const auto privateMatch = regex_match(u"^" "c/(\\-?\\d+)" "(" diff --git a/Telegram/SourceFiles/data/data_drafts.cpp b/Telegram/SourceFiles/data/data_drafts.cpp index 6f386e582..e0ebb7741 100644 --- a/Telegram/SourceFiles/data/data_drafts.cpp +++ b/Telegram/SourceFiles/data/data_drafts.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_widget.h" #include "history/history_item_components.h" #include "main/main_session.h" +#include "data/data_changes.h" #include "data/data_session.h" #include "data/data_web_page.h" #include "mainwidget.h" @@ -128,4 +129,29 @@ void ClearPeerCloudDraft( history->applyCloudDraft(topicRootId); } +void SetChatLinkDraft( + not_null peer, + const TextWithEntities &draft) { + const auto textWithTags = TextWithTags{ + draft.text, + TextUtilities::ConvertEntitiesToTextTags(draft.entities) + }; + const auto cursor = MessageCursor{ + int(textWithTags.text.size()), + int(textWithTags.text.size()), + Ui::kQFixedMax + }; + const auto history = peer->owner().history(peer->id); + const auto topicRootId = MsgId(); + history->setLocalDraft(std::make_unique( + textWithTags, + FullReplyTo{ .topicRootId = topicRootId }, + cursor, + Data::WebPageDraft())); + history->clearLocalEditDraft(topicRootId); + history->session().changes().entryUpdated( + history, + Data::EntryUpdate::Flag::LocalDraftSet); +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_drafts.h b/Telegram/SourceFiles/data/data_drafts.h index 4fdd9159c..581acaeea 100644 --- a/Telegram/SourceFiles/data/data_drafts.h +++ b/Telegram/SourceFiles/data/data_drafts.h @@ -205,4 +205,8 @@ using HistoryDrafts = base::flat_map>; && (a->webpage == b->webpage); } +void SetChatLinkDraft( + not_null peer, + const TextWithEntities &draft); + } // namespace Data diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 031946f0a..44868b6db 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "window/window_session_controller.h" +#include "api/api_text_entities.h" #include "boxes/add_contact_box.h" #include "boxes/peers/add_bot_to_chat_box.h" #include "boxes/peers/edit_peer_info_box.h" @@ -307,6 +308,13 @@ void SessionNavigation::showPeerByLink(const PeerByLinkInfo &info) { resolvePhone(info.phone, [=](not_null peer) { showPeerByLinkResolved(peer, info); }); + } else if (!info.chatLinkSlug.isEmpty()) { + resolveChatLink(info.chatLinkSlug, [=]( + not_null peer, + TextWithEntities draft) { + Data::SetChatLinkDraft(peer, draft); + showPeerByLinkResolved(peer, info); + }); } else if (const auto name = std::get_if(&info.usernameOrId)) { resolveUsername(*name, [=](not_null peer) { if (info.startAutoSubmit) { @@ -352,6 +360,33 @@ void SessionNavigation::resolvePhone( }).send(); } +void SessionNavigation::resolveChatLink( + const QString &slug, + Fn peer, TextWithEntities draft)> done) { + _api.request(base::take(_resolveRequestId)).cancel(); + _resolveRequestId = _api.request(MTPaccount_ResolveBusinessChatLink( + MTP_string(slug) + )).done([=](const MTPaccount_ResolvedBusinessChatLinks &result) { + _resolveRequestId = 0; + parentController()->hideLayer(); + const auto &data = result.data(); + _session->data().processUsers(data.vusers()); + _session->data().processChats(data.vchats()); + + using namespace Api; + const auto peerId = peerFromMTP(data.vpeer()); + done(_session->data().peer(peerId), { + qs(data.vmessage()), + EntitiesFromMTP(_session, data.ventities().value_or_empty()) + }); + }).fail([=](const MTP::Error &error) { + _resolveRequestId = 0; + if (error.code() == 400) { + showToast(tr::lng_confirm_phone_link_invalid(tr::now)); + } + }).send(); +} + void SessionNavigation::resolveUsername( const QString &username, Fn)> done) { diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 57e528579..4504f3b3c 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -260,6 +260,9 @@ private: void resolvePhone( const QString &phone, Fn)> done); + void resolveChatLink( + const QString &slug, + Fn peer, TextWithEntities draft)> done); void resolveUsername( const QString &username, Fn)> done); diff --git a/Telegram/SourceFiles/window/window_session_controller_link_info.h b/Telegram/SourceFiles/window/window_session_controller_link_info.h index 5cf6dce7e..01224a3f0 100644 --- a/Telegram/SourceFiles/window/window_session_controller_link_info.h +++ b/Telegram/SourceFiles/window/window_session_controller_link_info.h @@ -31,6 +31,7 @@ using RepliesByLinkInfo = std::variant; struct PeerByLinkInfo { std::variant usernameOrId; QString phone; + QString chatLinkSlug; MsgId messageId = ShowAtUnreadMsgId; StoryId storyId = 0; RepliesByLinkInfo repliesInfo;