diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 3d03bea739..b3fd28e3f9 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -683,17 +683,57 @@ void ApiWrap::finalizeMessageDataRequest( } } -QString ApiWrap::exportDirectMessageLink(not_null item) { +QString ApiWrap::exportDirectMessageLink( + not_null item, + bool inRepliesContext) { Expects(item->history()->peer->isChannel()); const auto itemId = item->fullId(); const auto channel = item->history()->peer->asChannel(); const auto fallback = [&] { - const auto base = channel->hasUsername() - ? channel->username - : "c/" + QString::number(channel->bareId()); - const auto query = base + '/' + QString::number(item->id); - if (channel->hasUsername() && !channel->isMegagroup()) { + auto linkChannel = channel; + auto linkItemId = item->id; + auto linkCommentId = 0; + auto linkThreadId = 0; + if (inRepliesContext) { + if (const auto rootId = item->replyToTop()) { + const auto root = item->history()->owner().message( + channel->bareId(), + rootId); + const auto sender = root + ? root->discussionPostOriginalSender() + : nullptr; + if (sender && sender->hasUsername()) { + // Comment to a public channel. + const auto forwarded = root->Get(); + linkItemId = forwarded->savedFromMsgId; + if (linkItemId) { + linkChannel = sender; + linkCommentId = item->id; + } else { + linkItemId = item->id; + } + } else { + // Reply in a thread, maybe comment in a private channel. + linkThreadId = rootId; + } + } + } + const auto base = linkChannel->hasUsername() + ? linkChannel->username + : "c/" + QString::number(linkChannel->bareId()); + const auto query = base + + '/' + + QString::number(linkItemId) + + (linkCommentId + ? "?comment=" + QString::number(linkCommentId) + : linkThreadId + ? "?thread=" + QString::number(linkThreadId) + : ""); + if (linkChannel->hasUsername() + && !linkChannel->isMegagroup() + && !linkCommentId + && !linkThreadId) { if (const auto media = item->media()) { if (const auto document = media->document()) { if (document->isVideoMessage()) { @@ -709,7 +749,9 @@ QString ApiWrap::exportDirectMessageLink(not_null item) { ? i->second : fallback(); request(MTPchannels_ExportMessageLink( - MTP_flags(0), + MTP_flags(inRepliesContext + ? MTPchannels_ExportMessageLink::Flag::f_thread + : MTPchannels_ExportMessageLink::Flag(0)), channel->inputChannel, MTP_int(item->id) )).done([=](const MTPExportedMessageLink &result) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 0582916fd1..49d85d5d73 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -172,7 +172,9 @@ public: ChannelData *channel, MsgId msgId, RequestMessageDataCallback callback); - QString exportDirectMessageLink(not_null item); + QString exportDirectMessageLink( + not_null item, + bool inRepliesContext); void requestContacts(); void requestDialogs(Data::Folder *folder = nullptr); diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 2fbd09a117..8f24ca6f47 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1647,7 +1647,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) { _menu->addAction(item->history()->peer->isMegagroup() ? tr::lng_context_copy_link(tr::now) : tr::lng_context_copy_post_link(tr::now), [=] { - HistoryView::CopyPostLink(session, itemId); + HistoryView::CopyPostLink(session, itemId, HistoryView::Context::History); }); } if (isUponSelected > 1) { @@ -1792,7 +1792,7 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { }); } else if (item && item->hasDirectLink() && isUponSelected != 2 && isUponSelected != -2) { _menu->addAction(item->history()->peer->isMegagroup() ? tr::lng_context_copy_link(tr::now) : tr::lng_context_copy_post_link(tr::now), [=] { - HistoryView::CopyPostLink(session, itemId); + HistoryView::CopyPostLink(session, itemId, HistoryView::Context::History); }); } if (isUponSelected > 1) { diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index f656299053..03e7dae436 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -218,7 +218,10 @@ void FastShareMessage(not_null item) { auto copyCallback = [=]() { if (const auto item = owner->message(data->msgIds[0])) { if (item->hasDirectLink()) { - HistoryView::CopyPostLink(session, item->fullId()); + HistoryView::CopyPostLink( + session, + item->fullId(), + HistoryView::Context::History); } else if (const auto bot = item->getMessageBot()) { if (const auto media = item->media()) { if (const auto game = media->game()) { diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 097371b98d..86053fcb4f 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -254,11 +254,14 @@ void AddPostLinkAction( } const auto session = &item->history()->session(); const auto itemId = item->fullId(); + const auto context = request.view + ? request.view->context() + : Context::History; menu->addAction( (item->history()->peer->isMegagroup() ? tr::lng_context_copy_link : tr::lng_context_copy_post_link)(tr::now), - [=] { CopyPostLink(session, itemId); }); + [=] { CopyPostLink(session, itemId, context); }); } MessageIdsList ExtractIdsList(const SelectedItems &items) { @@ -774,18 +777,38 @@ base::unique_qptr FillContextMenu( return result; } -void CopyPostLink(not_null session, FullMsgId itemId) { +void CopyPostLink( + not_null session, + FullMsgId itemId, + Context context) { const auto item = session->data().message(itemId); if (!item || !item->hasDirectLink()) { return; } + const auto inRepliesContext = (context == Context::Replies); QGuiApplication::clipboard()->setText( - item->history()->session().api().exportDirectMessageLink(item)); + item->history()->session().api().exportDirectMessageLink( + item, + inRepliesContext)); - const auto channel = item->history()->peer->asChannel(); - Assert(channel != nullptr); + const auto isPublicLink = [&] { + const auto channel = item->history()->peer->asChannel(); + Assert(channel != nullptr); + if (const auto rootId = item->replyToTop()) { + const auto root = item->history()->owner().message( + channel->bareId(), + rootId); + const auto sender = root + ? root->discussionPostOriginalSender() + : nullptr; + if (sender && sender->hasUsername()) { + return true; + } + } + return channel->hasUsername(); + }(); - Ui::Toast::Show(channel->hasUsername() + Ui::Toast::Show(isPublicLink ? tr::lng_channel_public_link_copied(tr::now) : tr::lng_context_about_private_link(tr::now)); } diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.h b/Telegram/SourceFiles/history/view/history_view_context_menu.h index 945b8f9da8..e33495dbe9 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.h +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.h @@ -19,6 +19,7 @@ class SessionNavigation; namespace HistoryView { +enum class Context : char; enum class PointState : char; class ListWidget; class Element; @@ -43,7 +44,10 @@ base::unique_qptr FillContextMenu( not_null list, const ContextMenuRequest &request); -void CopyPostLink(not_null session, FullMsgId itemId); +void CopyPostLink( + not_null session, + FullMsgId itemId, + Context context); void StopPoll(not_null session, FullMsgId itemId); } // namespace