diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4fb274e6e..c4f39a261 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1966,6 +1966,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_copy_listener_link" = "Copy Listener Link"; "lng_group_call_end" = "End Voice Chat"; "lng_group_call_join" = "Join"; +"lng_group_call_join_confirm" = "Do you want to join the voice chat {chat}?"; "lng_group_call_invite_done_user" = "You invited {user} to the voice chat."; "lng_group_call_invite_done_many#one" = "You invited **{count} member** to the voice chat."; "lng_group_call_invite_done_many#other" = "You invited **{count} members** to the voice chat."; @@ -2011,7 +2012,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_recording_start_button" = "Start"; "lng_group_call_is_recorded" = "Voice chat is being recorded."; "lng_group_call_can_speak_here" = "You can now speak."; -"lng_group_call_can_speak" = "You can now speak in **{chat}**."; +"lng_group_call_can_speak" = "You can now speak in {chat}."; "lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages."; diff --git a/Telegram/SourceFiles/calls/calls_choose_join_as.cpp b/Telegram/SourceFiles/calls/calls_choose_join_as.cpp index cc6227a03..64c84f3b9 100644 --- a/Telegram/SourceFiles/calls/calls_choose_join_as.cpp +++ b/Telegram/SourceFiles/calls/calls_choose_join_as.cpp @@ -12,12 +12,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_channel.h" #include "data/data_session.h" +#include "data/data_group_call.h" #include "main/main_session.h" #include "main/main_account.h" #include "lang/lang_keys.h" #include "apiwrap.h" #include "ui/layers/generic_box.h" +#include "ui/text/text_utilities.h" #include "boxes/peer_list_box.h" +#include "boxes/confirm_box.h" #include "styles/style_boxes.h" #include "styles/style_calls.h" @@ -114,7 +117,8 @@ void ChooseJoinAsBox( box->setTitle([&] { switch (context) { case Context::Create: return tr::lng_group_call_start_as_header(); - case Context::Join: return tr::lng_group_call_join_as_header(); + case Context::Join: + case Context::JoinWithConfirm: return tr::lng_group_call_join_as_header(); case Context::Switch: return tr::lng_group_call_display_as_header(); } Unexpected("Context in ChooseJoinAsBox."); @@ -231,19 +235,43 @@ void ChooseJoinAsProcess::start( } return list; }); + const auto selectedId = peer->groupCallDefaultJoinAs(); if (list.empty()) { _request->showToast(Lang::Hard::ServerError()); return; - } else if (list.size() == 1 + } else if (!changingJoinAsFrom + && list.size() == 1 && list.front() == self && (!peer->isChannel() || !peer->asChannel()->amAnonymous() || (peer->isBroadcast() && !peer->canWrite()))) { info.possibleJoinAs = std::move(list); - finish(info); + if (context != Context::JoinWithConfirm + || (selectedId && self->id == selectedId)) { + finish(info); + return; + } + const auto real = peer->groupCall(); + const auto name = (real && !real->title().isEmpty()) + ? real->title() + : peer->name; + auto box = Box<::ConfirmBox>( + tr::lng_group_call_join_confirm( + tr::now, + lt_chat, + Ui::Text::Bold(name), + Ui::Text::WithEntities), + tr::lng_group_call_join(tr::now), + crl::guard(&_request->guard, [=] { finish(info); })); + box->boxClosing( + ) | rpl::start_with_next([=] { + _request = nullptr; + }, _request->lifetime); + + _request->box = box.data(); + _request->showBox(std::move(box)); return; } - const auto selectedId = peer->groupCallDefaultJoinAs(); info.joinAs = [&]() -> not_null { const auto loaded = selectedId ? session->data().peerLoaded(selectedId) diff --git a/Telegram/SourceFiles/calls/calls_choose_join_as.h b/Telegram/SourceFiles/calls/calls_choose_join_as.h index fe8010da6..aa9b9dcf3 100644 --- a/Telegram/SourceFiles/calls/calls_choose_join_as.h +++ b/Telegram/SourceFiles/calls/calls_choose_join_as.h @@ -28,6 +28,7 @@ public: enum class Context { Create, Join, + JoinWithConfirm, Switch, }; diff --git a/Telegram/SourceFiles/calls/calls_group_panel.cpp b/Telegram/SourceFiles/calls/calls_group_panel.cpp index 4fe9c11a0..6344ba2bd 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_group_panel.cpp @@ -302,8 +302,8 @@ Panel::Panel(not_null call) .text = tr::lng_group_call_can_speak( tr::now, lt_chat, - Ui::Text::WithEntities(name), - Ui::Text::RichLangValue), + Ui::Text::Bold(name), + Ui::Text::WithEntities), .st = &st::defaultToast, }); } diff --git a/Telegram/SourceFiles/calls/calls_group_settings.cpp b/Telegram/SourceFiles/calls/calls_group_settings.cpp index b1c254e2f..b33ba2378 100644 --- a/Telegram/SourceFiles/calls/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/calls_group_settings.cpp @@ -531,8 +531,8 @@ void SettingsBox( && peer->asChannel()->hasUsername() && goodReal) { const auto showBox = crl::guard(box, [=]( - object_ptr box) { - box->getDelegate()->show(std::move(box)); + object_ptr next) { + box->getDelegate()->show(std::move(next)); }); const auto showToast = crl::guard(box, [=](QString text) { Ui::Toast::Show( diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index fc390f974..cd3bbee10 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -65,8 +65,11 @@ void Instance::startOutgoingCall(not_null user, bool video) { void Instance::startOrJoinGroupCall( not_null peer, - const QString &joinHash) { - const auto context = peer->groupCall() + const QString &joinHash, + bool confirmNeeded) { + const auto context = confirmNeeded + ? Group::ChooseJoinAsProcess::Context::JoinWithConfirm + : peer->groupCall() ? Group::ChooseJoinAsProcess::Context::Join : Group::ChooseJoinAsProcess::Context::Create; _chooseJoinAs.start(peer, context, [=](object_ptr box) { diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index 18a217fc4..fa3ff5f18 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -45,7 +45,8 @@ public: void startOutgoingCall(not_null user, bool video); void startOrJoinGroupCall( not_null peer, - const QString &joinHash = QString()); + const QString &joinHash = QString(), + bool confirmNeeded = false); void handleUpdate( not_null session, const MTPUpdate &update); diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index c2bdd8c0b..d72875d48 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -212,6 +212,22 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) { }); } +void GroupCall::processFullCall(const MTPphone_GroupCall &call) { + call.match([&](const MTPDphone_groupCall &data) { + _peer->owner().processUsers(data.vusers()); + _peer->owner().processChats(data.vchats()); + _participants.clear(); + _speakingByActiveFinishes.clear(); + _participantPeerBySsrc.clear(); + applyParticipantsSlice( + data.vparticipants().v, + ApplySliceSource::SliceLoaded); + applyCall(data.vcall(), true); + _allReceived = (_fullCount.current() == _participants.size()); + _participantsSliceAdded.fire({}); + }); +} + void GroupCall::reload() { if (_reloadRequestId) { return; @@ -222,19 +238,7 @@ void GroupCall::reload() { _reloadRequestId = api().request( MTPphone_GetGroupCall(input()) ).done([=](const MTPphone_GroupCall &result) { - result.match([&](const MTPDphone_groupCall &data) { - _peer->owner().processUsers(data.vusers()); - _peer->owner().processChats(data.vchats()); - _participants.clear(); - _speakingByActiveFinishes.clear(); - _participantPeerBySsrc.clear(); - applyParticipantsSlice( - data.vparticipants().v, - ApplySliceSource::SliceLoaded); - applyCall(data.vcall(), true); - _allReceived = (_fullCount.current() == _participants.size()); - _participantsSliceAdded.fire({}); - }); + processFullCall(result); _reloadRequestId = 0; }).fail([=](const MTP::Error &error) { _reloadRequestId = 0; diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 872b7dac3..36e722a3b 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -99,6 +99,7 @@ public: void setInCall(); void reload(); + void processFullCall(const MTPphone_GroupCall &call); void setJoinMutedLocally(bool muted); [[nodiscard]] bool joinMuted() const; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 998be1e8a..d6a2cdd61 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_chat.h" #include "data/data_user.h" #include "data/data_changes.h" +#include "data/data_group_call.h" #include "data/data_chat_filters.h" #include "passport/passport_form_controller.h" #include "chat_helpers/tabbed_selector.h" @@ -178,6 +179,11 @@ void SessionNavigation::showPeerByLinkResolved( not_null peer, const PeerByLinkInfo &info) { if (info.voicechatHash && peer->isChannel()) { + const auto bad = [=] { + Ui::ShowMultilineToast({ + .text = { tr::lng_group_invite_bad_link(tr::now) } + }); + }; const auto hash = *info.voicechatHash; _session->api().request(base::take(_resolveRequestId)).cancel(); _resolveRequestId = _session->api().request( @@ -185,11 +191,25 @@ void SessionNavigation::showPeerByLinkResolved( ).done([=](const MTPmessages_ChatFull &result) { _session->api().processFullPeer(peer, result); if (const auto call = peer->groupCall()) { - parentController()->startOrJoinGroupCall(peer, hash); + const auto id = call->id(); + _resolveRequestId = _session->api().request( + MTPphone_GetGroupCall(call->input()) + ).done([=](const MTPphone_GroupCall &result) { + if (const auto now = peer->groupCall() + ; now && now->id() == id) { + now->processFullCall(result); + parentController()->startOrJoinGroupCall( + peer, + hash, + SessionController::GroupCallJoinConfirm::Always); + } else { + bad(); + } + }).fail([=](const MTP::Error &error) { + bad(); + }).send(); } else { - Ui::ShowMultilineToast({ - .text = { tr::lng_group_invite_bad_link(tr::now) } - }); + bad(); } }).send(); return; @@ -953,30 +973,32 @@ void SessionController::closeThirdSection() { void SessionController::startOrJoinGroupCall( not_null peer, QString joinHash, - bool confirmedLeaveOther) { + GroupCallJoinConfirm confirm) { auto &calls = Core::App().calls(); - const auto confirm = [&](QString text, QString button) { + const auto askConfirmation = [&](QString text, QString button) { Ui::show(Box(text, button, crl::guard(this, [=] { Ui::hideLayer(); - startOrJoinGroupCall(peer, joinHash, true); + startOrJoinGroupCall(peer, joinHash, GroupCallJoinConfirm::None); }))); }; - if (!confirmedLeaveOther && calls.inCall()) { + if (confirm != GroupCallJoinConfirm::None && calls.inCall()) { // Do you want to leave your active voice chat // to join a voice chat in this group? - confirm( + askConfirmation( tr::lng_call_leave_to_other_sure(tr::now), tr::lng_call_bar_hangup(tr::now)); - } else if (!confirmedLeaveOther && calls.inGroupCall()) { + } else if (confirm != GroupCallJoinConfirm::None + && calls.inGroupCall()) { if (calls.currentGroupCall()->peer() == peer) { calls.activateCurrentCall(joinHash); } else { - confirm( + askConfirmation( tr::lng_group_call_leave_to_other_sure(tr::now), tr::lng_group_call_leave(tr::now)); } } else { - calls.startOrJoinGroupCall(peer, joinHash); + const auto confirmNeeded = (confirm == GroupCallJoinConfirm::Always); + calls.startOrJoinGroupCall(peer, joinHash, confirmNeeded); } } diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index 49f2fc46d..201b04c9a 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -298,10 +298,15 @@ public: void resizeForThirdSection(); void closeThirdSection(); + enum class GroupCallJoinConfirm { + None, + IfNowInAnother, + Always, + }; void startOrJoinGroupCall( not_null peer, QString joinHash = QString(), - bool confirmedLeaveOther = false); + GroupCallJoinConfirm confirm = GroupCallJoinConfirm::IfNowInAnother); void showSection( std::shared_ptr memento,