Always join voice chats by link with confirmation.

This commit is contained in:
John Preston 2021-03-16 17:16:01 +04:00
parent 199434c7a2
commit 2c806b11d7
11 changed files with 104 additions and 38 deletions

View File

@ -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.";

View File

@ -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<PeerData*> {
const auto loaded = selectedId
? session->data().peerLoaded(selectedId)

View File

@ -28,6 +28,7 @@ public:
enum class Context {
Create,
Join,
JoinWithConfirm,
Switch,
};

View File

@ -302,8 +302,8 @@ Panel::Panel(not_null<GroupCall*> 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,
});
}

View File

@ -531,8 +531,8 @@ void SettingsBox(
&& peer->asChannel()->hasUsername()
&& goodReal) {
const auto showBox = crl::guard(box, [=](
object_ptr<Ui::BoxContent> box) {
box->getDelegate()->show(std::move(box));
object_ptr<Ui::BoxContent> next) {
box->getDelegate()->show(std::move(next));
});
const auto showToast = crl::guard(box, [=](QString text) {
Ui::Toast::Show(

View File

@ -65,8 +65,11 @@ void Instance::startOutgoingCall(not_null<UserData*> user, bool video) {
void Instance::startOrJoinGroupCall(
not_null<PeerData*> 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<Ui::BoxContent> box) {

View File

@ -45,7 +45,8 @@ public:
void startOutgoingCall(not_null<UserData*> user, bool video);
void startOrJoinGroupCall(
not_null<PeerData*> peer,
const QString &joinHash = QString());
const QString &joinHash = QString(),
bool confirmNeeded = false);
void handleUpdate(
not_null<Main::Session*> session,
const MTPUpdate &update);

View File

@ -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;

View File

@ -99,6 +99,7 @@ public:
void setInCall();
void reload();
void processFullCall(const MTPphone_GroupCall &call);
void setJoinMutedLocally(bool muted);
[[nodiscard]] bool joinMuted() const;

View File

@ -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<PeerData*> 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<PeerData*> 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<ConfirmBox>(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);
}
}

View File

@ -298,10 +298,15 @@ public:
void resizeForThirdSection();
void closeThirdSection();
enum class GroupCallJoinConfirm {
None,
IfNowInAnother,
Always,
};
void startOrJoinGroupCall(
not_null<PeerData*> peer,
QString joinHash = QString(),
bool confirmedLeaveOther = false);
GroupCallJoinConfirm confirm = GroupCallJoinConfirm::IfNowInAnother);
void showSection(
std::shared_ptr<SectionMemento> memento,