diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index a09b89c507..41830e0fd0 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -177,6 +177,7 @@ GroupCall::GroupCall( , _api(&_peer->session().mtp()) , _joinAs(info.joinAs) , _possibleJoinAs(std::move(info.possibleJoinAs)) +, _joinHash(info.joinHash) , _lastSpokeCheckTimer([=] { checkLastSpoke(); }) , _checkJoinedTimer([=] { checkJoined(); }) , _pushToTalkCancelTimer([=] { pushToTalkCancel(); }) @@ -390,6 +391,15 @@ void GroupCall::rejoin() { rejoin(_joinAs); } +void GroupCall::rejoinWithHash(const QString &hash) { + if (!hash.isEmpty() + && (muted() == MuteState::ForceMuted + || muted() == MuteState::RaisedHand)) { + _joinHash = hash; + rejoin(); + } +} + void GroupCall::rejoin(not_null as) { if (state() != State::Joining && state() != State::Joined @@ -436,12 +446,14 @@ void GroupCall::rejoin(not_null as) { const auto wasMuteState = muted(); using Flag = MTPphone_JoinGroupCall::Flag; _api.request(MTPphone_JoinGroupCall( - MTP_flags((wasMuteState != MuteState::Active) + MTP_flags((wasMuteState != MuteState::Active ? Flag::f_muted - : Flag(0)), + : Flag(0)) | (_joinHash.isEmpty() + ? Flag(0) + : Flag::f_invite_hash)), inputCall(), _joinAs->input, - MTPstring(), // #TODO calls invite_hash + MTP_string(_joinHash), MTP_dataJSON(MTP_bytes(json)) )).done([=](const MTPUpdates &updates) { _mySsrc = ssrc; diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index e48f988a36..79227c8655 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -113,6 +113,7 @@ public: void hangup(); void discard(); void rejoinAs(Group::JoinInfo info); + void rejoinWithHash(const QString &hash); void join(const MTPInputGroupCall &inputCall); void handleUpdate(const MTPGroupCall &call); void handleUpdate(const MTPDupdateGroupCallParticipants &data); @@ -271,6 +272,7 @@ private: not_null _joinAs; std::vector> _possibleJoinAs; + QString _joinHash; rpl::variable _muted = MuteState::Muted; bool _initialMuteStateSent = false; diff --git a/Telegram/SourceFiles/calls/calls_group_common.h b/Telegram/SourceFiles/calls/calls_group_common.h index 67faaf5c3b..371f290b03 100644 --- a/Telegram/SourceFiles/calls/calls_group_common.h +++ b/Telegram/SourceFiles/calls/calls_group_common.h @@ -43,6 +43,7 @@ struct JoinInfo { not_null peer; not_null joinAs; std::vector> possibleJoinAs; + QString joinHash; }; } // namespace Calls::Group diff --git a/Telegram/SourceFiles/calls/calls_group_settings.cpp b/Telegram/SourceFiles/calls/calls_group_settings.cpp index c45fecec97..b5b34dff10 100644 --- a/Telegram/SourceFiles/calls/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/calls_group_settings.cpp @@ -190,7 +190,7 @@ object_ptr ShareInviteLinkBox( .bottomWidget = std::move(bottom), .stMultiSelect = &st::groupCallMultiSelect, .stComment = &st::groupCallShareBoxComment, - .stItem = &st::groupCallShareBoxList }); + .st = &st::groupCallShareBoxList }); *box = result.data(); return result; } diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index ac8036c1f0..ea875c671d 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -61,7 +61,9 @@ void Instance::startOutgoingCall(not_null user, bool video) { }), video); } -void Instance::startOrJoinGroupCall(not_null peer) { +void Instance::startOrJoinGroupCall( + not_null peer, + const QString &joinHash) { const auto context = peer->groupCall() ? Group::ChooseJoinAsProcess::Context::Join : Group::ChooseJoinAsProcess::Context::Create; @@ -71,6 +73,7 @@ void Instance::startOrJoinGroupCall(not_null peer) { Ui::Toast::Show(text); }, [=](Group::JoinInfo info) { const auto call = info.peer->groupCall(); + info.joinHash = joinHash; createGroupCall( std::move(info), call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong())); @@ -486,11 +489,14 @@ bool Instance::hasActivePanel(not_null session) const { return false; } -bool Instance::activateCurrentCall() { +bool Instance::activateCurrentCall(const QString &joinHash) { if (inCall()) { _currentCallPanel->showAndActivate(); return true; } else if (inGroupCall()) { + if (!joinHash.isEmpty()) { + _currentGroupCall->rejoinWithHash(joinHash); + } _currentGroupCallPanel->showAndActivate(); return true; } diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index a02b6ebc99..891b1c49e6 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -43,7 +43,9 @@ public: ~Instance(); void startOutgoingCall(not_null user, bool video); - void startOrJoinGroupCall(not_null peer); + void startOrJoinGroupCall( + not_null peer, + const QString &joinHash = QString()); void handleUpdate( not_null session, const MTPUpdate &update); @@ -57,7 +59,7 @@ public: [[nodiscard]] bool inGroupCall() const; [[nodiscard]] bool hasActivePanel( not_null session) const; - bool activateCurrentCall(); + bool activateCurrentCall(const QString &joinHash = QString()); bool minimizeCurrentActiveCall(); bool closeCurrentActiveCall(); auto getVideoCapture() diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 93912d0da5..98a2f45e94 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -299,6 +299,9 @@ bool ResolveUsername( } : Navigation::RepliesByLinkInfo{ v::null }, .startToken = startToken, + .voicechatHash = (params.contains(u"voicechat"_q) + ? std::make_optional(params.value(u"voicechat"_q)) + : std::nullopt), .clickFromMessageId = fromMessageId, }); return true; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index c048c659ad..fe9b2a8f49 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -151,7 +151,7 @@ void SessionNavigation::resolveChannelById( return; } const auto fail = [=] { - Ui::show(Box(tr::lng_error_post_link_invalid(tr::now))); + Ui::Toast::Show(tr::lng_error_post_link_invalid(tr::now)); }; _session->api().request(base::take(_resolveRequestId)).cancel(); _resolveRequestId = _session->api().request(MTPchannels_GetChannels( @@ -175,6 +175,21 @@ void SessionNavigation::resolveChannelById( void SessionNavigation::showPeerByLinkResolved( not_null peer, const PeerByLinkInfo &info) { + if (info.voicechatHash && peer->isChannel()) { + const auto hash = *info.voicechatHash; + _session->api().request(base::take(_resolveRequestId)).cancel(); + _resolveRequestId = _session->api().request( + MTPchannels_GetFullChannel(peer->asChannel()->inputChannel) + ).done([=](const MTPmessages_ChatFull &result) { + _session->api().processFullPeer(peer, result); + if (const auto call = peer->groupCall()) { + parentController()->startOrJoinGroupCall(peer, hash); + } else { + Ui::Toast::Show(tr::lng_error_post_link_invalid(tr::now)); + } + }).send(); + return; + } auto params = SectionShow{ SectionShow::Way::Forward }; @@ -933,6 +948,7 @@ void SessionController::closeThirdSection() { void SessionController::startOrJoinGroupCall( not_null peer, + QString joinHash, bool confirmedLeaveOther) { //const auto channel = peer->asChannel(); // #TODO calls //if (channel && channel->amAnonymous()) { @@ -945,7 +961,7 @@ void SessionController::startOrJoinGroupCall( const auto confirm = [&](QString text, QString button) { Ui::show(Box(text, button, crl::guard(this, [=] { Ui::hideLayer(); - startOrJoinGroupCall(peer, true); + startOrJoinGroupCall(peer, joinHash, true); }))); }; if (!confirmedLeaveOther && calls.inCall()) { @@ -956,14 +972,14 @@ void SessionController::startOrJoinGroupCall( tr::lng_call_bar_hangup(tr::now)); } else if (!confirmedLeaveOther && calls.inGroupCall()) { if (calls.currentGroupCall()->peer() == peer) { - calls.activateCurrentCall(); + calls.activateCurrentCall(joinHash); } else { confirm( tr::lng_group_call_leave_to_other_sure(tr::now), tr::lng_group_call_leave(tr::now)); } } else { - calls.startOrJoinGroupCall(peer); + calls.startOrJoinGroupCall(peer, joinHash); } } diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 282106b15c..49f2fc46df 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -151,6 +151,7 @@ public: MsgId messageId = ShowAtUnreadMsgId; RepliesByLinkInfo repliesInfo; QString startToken; + std::optional voicechatHash; FullMsgId clickFromMessageId; }; void showPeerByLink(const PeerByLinkInfo &info); @@ -299,6 +300,7 @@ public: void startOrJoinGroupCall( not_null peer, + QString joinHash = QString(), bool confirmedLeaveOther = false); void showSection(