Add ability to Raise Hand in ForceMuted state.

This commit is contained in:
John Preston 2021-03-08 20:08:43 +04:00
parent f66d7088ef
commit fb579f1c10
6 changed files with 60 additions and 22 deletions

View file

@ -1929,6 +1929,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_you_are_live" = "You are Live"; "lng_group_call_you_are_live" = "You are Live";
"lng_group_call_force_muted" = "Muted by admin"; "lng_group_call_force_muted" = "Muted by admin";
"lng_group_call_force_muted_sub" = "You are in Listen Only mode"; "lng_group_call_force_muted_sub" = "You are in Listen Only mode";
"lng_group_call_raise_hand_tip" = "Click if you want to speak";
"lng_group_call_raised_hand" = "You asked to speak";
"lng_group_call_raised_hand_sub" = "We let the speakers know";
"lng_group_call_connecting" = "Connecting..."; "lng_group_call_connecting" = "Connecting...";
"lng_group_call_leave" = "Leave"; "lng_group_call_leave" = "Leave";
"lng_group_call_leave_title" = "Leave voice chat"; "lng_group_call_leave_title" = "Leave voice chat";

View file

@ -173,7 +173,8 @@ GroupCall::GroupCall(
if (_instance) { if (_instance) {
updateInstanceMuteState(); updateInstanceMuteState();
} }
if (_mySsrc) { if (_mySsrc && !_initialMuteStateSent) {
_initialMuteStateSent = true;
maybeSendMutedUpdate(previous); maybeSendMutedUpdate(previous);
} }
}, _lifetime); }, _lifetime);
@ -371,6 +372,7 @@ void GroupCall::rejoin() {
} }
_mySsrc = 0; _mySsrc = 0;
_initialMuteStateSent = false;
setState(State::Joining); setState(State::Joining);
ensureControllerCreated(); ensureControllerCreated();
setInstanceMode(InstanceMode::None); setInstanceMode(InstanceMode::None);
@ -464,7 +466,8 @@ void GroupCall::applyMeInCallLocally() {
const auto volume = (i != end(participants)) const auto volume = (i != end(participants))
? i->volume ? i->volume
: Group::kDefaultVolume; : Group::kDefaultVolume;
const auto canSelfUnmute = (muted() != MuteState::ForceMuted); const auto canSelfUnmute = (muted() != MuteState::ForceMuted)
&& (muted() != MuteState::RaisedHand);
const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0)) const auto flags = (canSelfUnmute ? Flag::f_can_self_unmute : Flag(0))
| (lastActive ? Flag::f_active_date : Flag(0)) | (lastActive ? Flag::f_active_date : Flag(0))
| (_mySsrc ? Flag(0) : Flag::f_left) | (_mySsrc ? Flag(0) : Flag::f_left)
@ -612,10 +615,12 @@ void GroupCall::setMuted(MuteState mute) {
const auto set = [=] { const auto set = [=] {
const auto wasMuted = (muted() == MuteState::Muted) const auto wasMuted = (muted() == MuteState::Muted)
|| (muted() == MuteState::PushToTalk); || (muted() == MuteState::PushToTalk);
const auto wasRaiseHand = (muted() == MuteState::RaisedHand);
_muted = mute; _muted = mute;
const auto nowMuted = (muted() == MuteState::Muted) const auto nowMuted = (muted() == MuteState::Muted)
|| (muted() == MuteState::PushToTalk); || (muted() == MuteState::PushToTalk);
if (wasMuted != nowMuted) { const auto nowRaiseHand = (muted() == MuteState::RaisedHand);
if (wasMuted != nowMuted || wasRaiseHand != nowRaiseHand) {
applyMeInCallLocally(); applyMeInCallLocally();
} }
}; };
@ -626,6 +631,15 @@ void GroupCall::setMuted(MuteState mute) {
} }
} }
void GroupCall::setMutedAndUpdate(MuteState mute) {
const auto was = muted();
const auto send = _initialMuteStateSent;
setMuted(mute);
if (send) {
maybeSendMutedUpdate(was);
}
}
void GroupCall::handleUpdate(const MTPGroupCall &call) { void GroupCall::handleUpdate(const MTPGroupCall &call) {
return call.match([&](const MTPDgroupCall &data) { return call.match([&](const MTPDgroupCall &data) {
if (_acceptFields) { if (_acceptFields) {
@ -814,12 +828,15 @@ void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) {
hangup(); hangup();
} }
if (data.is_muted() && !data.is_can_self_unmute()) { if (data.is_muted() && !data.is_can_self_unmute()) {
setMuted(MuteState::ForceMuted); setMuted(data.vraise_hand_rating().value_or_empty()
? MuteState::RaisedHand
: MuteState::ForceMuted);
} else if (_instanceMode == InstanceMode::Stream) { } else if (_instanceMode == InstanceMode::Stream) {
LOG(("Call Info: Rejoin after unforcemute in stream mode.")); LOG(("Call Info: Rejoin after unforcemute in stream mode."));
setState(State::Joining); setState(State::Joining);
rejoin(); rejoin();
} else if (muted() == MuteState::ForceMuted) { } else if (muted() == MuteState::ForceMuted
|| muted() == MuteState::RaisedHand) {
setMuted(MuteState::Muted); setMuted(MuteState::Muted);
} else if (data.is_muted() && muted() != MuteState::Muted) { } else if (data.is_muted() && muted() != MuteState::Muted) {
setMuted(MuteState::Muted); setMuted(MuteState::Muted);
@ -1176,23 +1193,28 @@ void GroupCall::maybeSendMutedUpdate(MuteState previous) {
const auto now = muted(); const auto now = muted();
const auto wasActive = (previous == MuteState::Active); const auto wasActive = (previous == MuteState::Active);
const auto nowActive = (now == MuteState::Active); const auto nowActive = (now == MuteState::Active);
if (now == MuteState::ForceMuted if ((wasActive && now == MuteState::Muted)
|| previous == MuteState::ForceMuted || (nowActive
|| (nowActive == wasActive)) { && (previous == MuteState::Muted
return; || previous == MuteState::PushToTalk))
|| (now == MuteState::ForceMuted
&& previous == MuteState::RaisedHand)
|| (now == MuteState::RaisedHand
&& previous == MuteState::ForceMuted)) {
sendMutedUpdate();
} }
sendMutedUpdate();
} }
void GroupCall::sendMutedUpdate() { void GroupCall::sendMutedUpdate() {
_api.request(_updateMuteRequestId).cancel(); _api.request(_updateMuteRequestId).cancel();
using Flag = MTPphone_EditGroupCallParticipant::Flag; using Flag = MTPphone_EditGroupCallParticipant::Flag;
_updateMuteRequestId = _api.request(MTPphone_EditGroupCallParticipant( _updateMuteRequestId = _api.request(MTPphone_EditGroupCallParticipant(
MTP_flags((muted() != MuteState::Active) ? Flag::f_muted : Flag(0)), MTP_flags(((muted() != MuteState::Active) ? Flag::f_muted : Flag(0))
| Flag::f_raise_hand),
inputCall(), inputCall(),
_joinAs->input, _joinAs->input,
MTP_int(100000), // volume MTP_int(100000), // volume
MTPBool() // #TODO calls raise_hand MTP_bool(muted() == MuteState::RaisedHand)
)).done([=](const MTPUpdates &result) { )).done([=](const MTPUpdates &result) {
_updateMuteRequestId = 0; _updateMuteRequestId = 0;
_peer->session().api().applyUpdates(result); _peer->session().api().applyUpdates(result);
@ -1364,6 +1386,7 @@ void GroupCall::applyGlobalShortcutChanges() {
void GroupCall::pushToTalk(bool pressed, crl::time delay) { void GroupCall::pushToTalk(bool pressed, crl::time delay) {
if (muted() == MuteState::ForceMuted if (muted() == MuteState::ForceMuted
|| muted() == MuteState::RaisedHand
|| muted() == MuteState::Active) { || muted() == MuteState::Active) {
return; return;
} else if (pressed) { } else if (pressed) {

View file

@ -50,6 +50,7 @@ enum class MuteState {
PushToTalk, PushToTalk,
Muted, Muted,
ForceMuted, ForceMuted,
RaisedHand,
}; };
[[nodiscard]] inline auto MapPushToTalkToActive() { [[nodiscard]] inline auto MapPushToTalkToActive() {
@ -120,6 +121,7 @@ public:
void changeTitle(const QString &title); void changeTitle(const QString &title);
void setMuted(MuteState mute); void setMuted(MuteState mute);
void setMutedAndUpdate(MuteState mute);
[[nodiscard]] MuteState muted() const { [[nodiscard]] MuteState muted() const {
return _muted.current(); return _muted.current();
} }
@ -263,6 +265,7 @@ private:
std::vector<not_null<PeerData*>> _possibleJoinAs; std::vector<not_null<PeerData*>> _possibleJoinAs;
rpl::variable<MuteState> _muted = MuteState::Muted; rpl::variable<MuteState> _muted = MuteState::Muted;
bool _initialMuteStateSent = false;
bool _acceptFields = false; bool _acceptFields = false;
rpl::event_stream<Group::ParticipantState> _otherParticipantStateValue; rpl::event_stream<Group::ParticipantState> _otherParticipantStateValue;

View file

@ -471,13 +471,15 @@ void GroupPanel::initControls() {
) | rpl::filter([=](Qt::MouseButton button) { ) | rpl::filter([=](Qt::MouseButton button) {
return (button == Qt::LeftButton) && (_call != nullptr); return (button == Qt::LeftButton) && (_call != nullptr);
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
if (_call->muted() == MuteState::ForceMuted) { const auto oldState = _call->muted();
_mute->shake(); const auto newState = (oldState == MuteState::ForceMuted)
} else { ? MuteState::RaisedHand
_call->setMuted((_call->muted() == MuteState::Muted) : (oldState == MuteState::RaisedHand)
? MuteState::Active ? MuteState::ForceMuted
: MuteState::Muted); : (oldState == MuteState::Muted)
} ? MuteState::Active
: MuteState::Muted;
_call->setMutedAndUpdate(newState);
}, _mute->lifetime()); }, _mute->lifetime());
_hangup->setClickedCallback([=] { endCall(); }); _hangup->setClickedCallback([=] { endCall(); });
@ -562,13 +564,17 @@ void GroupPanel::initWithCall(GroupCall *call) {
? tr::lng_group_call_connecting(tr::now) ? tr::lng_group_call_connecting(tr::now)
: mute == MuteState::ForceMuted : mute == MuteState::ForceMuted
? tr::lng_group_call_force_muted(tr::now) ? tr::lng_group_call_force_muted(tr::now)
: mute == MuteState::RaisedHand
? tr::lng_group_call_raised_hand(tr::now)
: mute == MuteState::Muted : mute == MuteState::Muted
? tr::lng_group_call_unmute(tr::now) ? tr::lng_group_call_unmute(tr::now)
: tr::lng_group_call_you_are_live(tr::now)), : tr::lng_group_call_you_are_live(tr::now)),
.subtext = (connecting .subtext = (connecting
? QString() ? QString()
: mute == MuteState::ForceMuted : mute == MuteState::ForceMuted
? tr::lng_group_call_force_muted_sub(tr::now) ? tr::lng_group_call_raise_hand_tip(tr::now)
: mute == MuteState::RaisedHand
? tr::lng_group_call_raised_hand_sub(tr::now)
: mute == MuteState::Muted : mute == MuteState::Muted
? tr::lng_group_call_unmute_sub(tr::now) ? tr::lng_group_call_unmute_sub(tr::now)
: QString()), : QString()),
@ -576,6 +582,8 @@ void GroupPanel::initWithCall(GroupCall *call) {
? Ui::CallMuteButtonType::Connecting ? Ui::CallMuteButtonType::Connecting
: mute == MuteState::ForceMuted : mute == MuteState::ForceMuted
? Ui::CallMuteButtonType::ForceMuted ? Ui::CallMuteButtonType::ForceMuted
: mute == MuteState::RaisedHand
? Ui::CallMuteButtonType::RaisedHand
: mute == MuteState::Muted : mute == MuteState::Muted
? Ui::CallMuteButtonType::Muted ? Ui::CallMuteButtonType::Muted
: Ui::CallMuteButtonType::Active), : Ui::CallMuteButtonType::Active),

View file

@ -60,7 +60,7 @@ constexpr auto kBlobUpdateInterval = crl::time(100);
auto BarStateFromMuteState(MuteState state, bool connecting) { auto BarStateFromMuteState(MuteState state, bool connecting) {
return (connecting return (connecting
? BarState::Connecting ? BarState::Connecting
: state == MuteState::ForceMuted : (state == MuteState::ForceMuted || state == MuteState::RaisedHand)
? BarState::ForceMuted ? BarState::ForceMuted
: state == MuteState::Muted : state == MuteState::Muted
? BarState::Muted ? BarState::Muted
@ -274,7 +274,8 @@ void TopBar::initControls() {
if (const auto call = _call.get()) { if (const auto call = _call.get()) {
call->setMuted(!call->muted()); call->setMuted(!call->muted());
} else if (const auto group = _groupCall.get()) { } else if (const auto group = _groupCall.get()) {
if (group->muted() == MuteState::ForceMuted) { if (group->muted() == MuteState::ForceMuted
|| group->muted() == MuteState::RaisedHand) {
Ui::Toast::Show(tr::lng_group_call_force_muted_sub(tr::now)); Ui::Toast::Show(tr::lng_group_call_force_muted_sub(tr::now));
} else { } else {
group->setMuted((group->muted() == MuteState::Muted) group->setMuted((group->muted() == MuteState::Muted)

View file