From 72a8b92827f2820ac7331f7b5af88397c2090306 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 6 Dec 2020 16:44:20 +0400 Subject: [PATCH] Add push-to-talk release delay. --- Telegram/Resources/langs/lang.strings | 3 ++ Telegram/SourceFiles/calls/calls.style | 17 ++++++ .../SourceFiles/calls/calls_group_call.cpp | 25 +++++++-- Telegram/SourceFiles/calls/calls_group_call.h | 2 + .../calls/calls_group_settings.cpp | 53 +++++++++++++++++-- Telegram/SourceFiles/core/core_settings.cpp | 15 ++++-- Telegram/SourceFiles/core/core_settings.h | 7 +++ 7 files changed, 111 insertions(+), 11 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 69f04bae18..290aa3ed47 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1839,6 +1839,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_call_push_to_talk" = "Push to Talk"; "lng_group_call_ptt_shortcut" = "Edit Shortcut"; "lng_group_call_ptt_recording" = "Stop Recording"; +"lng_group_call_ptt_delay_ms" = "{amount} ms"; +"lng_group_call_ptt_delay_s" = "{amount}s"; +"lng_group_call_ptt_delay" = "Push to Talk release delay: {delay}"; "lng_group_call_share" = "Share Invite Link"; "lng_group_call_end" = "End Voice Chat"; "lng_group_call_join" = "Join"; diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index 5849c02540..abc37b8829 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -670,6 +670,23 @@ groupCallBoxLabel: FlatLabel(boxLabel) { groupCallRowBlobMinRadius: 27px; groupCallRowBlobMaxRadius: 29px; +groupCallDelayLabel: LabelSimple(defaultLabelSimple) { + textFg: groupCallMembersFg; + font: boxTextFont; +} +groupCallDelayLabelMargin: margins(22px, 10px, 20px, 5px); +groupCallDelaySlider: MediaSlider(defaultContinuousSlider) { + seekSize: size(15px, 15px); + activeFg: groupCallActiveFg; + inactiveFg: groupCallMemberNotJoinedStatus; + activeFgOver: groupCallActiveFg; + inactiveFgOver: groupCallMemberNotJoinedStatus; + activeFgDisabled: groupCallActiveFg; + inactiveFgDisabled: groupCallMemberNotJoinedStatus; + receivedTillFg: groupCallMemberNotJoinedStatus; +} +groupCallDelayMargin: margins(22px, 5px, 20px, 10px); + callTopBarMuteCrossLine: CrossLineAnimation { fg: callBarFg; icon: icon {{ "calls/call_record_active", callBarFg }}; diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index 933bcb5e67..b90eef418b 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -52,7 +52,8 @@ GroupCall::GroupCall( , _history(channel->owner().history(channel)) , _api(&_channel->session().mtp()) , _lastSpokeCheckTimer([=] { checkLastSpoke(); }) -, _checkJoinedTimer([=] { checkJoined(); }) { +, _checkJoinedTimer([=] { checkJoined(); }) +, _pushToTalkCancelTimer([=] { pushToTalkCancel(); }) { _muted.value( ) | rpl::combine_previous( ) | rpl::start_with_next([=](MuteState previous, MuteState state) { @@ -781,12 +782,28 @@ void GroupCall::applyGlobalShortcutChanges() { } _pushToTalk = shortcut; _shortcutManager->startWatching(_pushToTalk, [=](bool pressed) { - if (muted() != MuteState::ForceMuted - && muted() != MuteState::Active) { - setMuted(pressed ? MuteState::PushToTalk : MuteState::Muted); + const auto delay = Core::App().settings().groupCallPushToTalkDelay(); + if (muted() == MuteState::ForceMuted + || muted() == MuteState::Active) { + return; + } else if (pressed) { + _pushToTalkCancelTimer.cancel(); + setMuted(MuteState::PushToTalk); + } else if (delay) { + _pushToTalkCancelTimer.callOnce(delay); + } else { + pushToTalkCancel(); } }); } + +void GroupCall::pushToTalkCancel() { + _pushToTalkCancelTimer.cancel(); + if (muted() == MuteState::PushToTalk) { + setMuted(MuteState::Muted); + } +} + //void GroupCall::setAudioVolume(bool input, float level) { // if (_instance) { // if (input) { diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index eab1f503a2..0c6cc9fbde 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -152,6 +152,7 @@ private: gsl::span> data); void setInstanceConnected(bool connected); void checkLastSpoke(); + void pushToTalkCancel(); void checkJoined(); @@ -183,6 +184,7 @@ private: std::shared_ptr _shortcutManager; std::shared_ptr _pushToTalk; + base::Timer _pushToTalkCancelTimer; bool _pushToTalkStarted = false; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/calls/calls_group_settings.cpp b/Telegram/SourceFiles/calls/calls_group_settings.cpp index fffb45f7c7..4b993c0091 100644 --- a/Telegram/SourceFiles/calls/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/calls_group_settings.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "calls/calls_group_panel.h" // LeaveGroupCallBox. #include "calls/calls_instance.h" #include "ui/widgets/level_meter.h" +#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/buttons.h" #include "ui/wrap/slide_wrap.h" #include "ui/toast/toast.h" @@ -36,6 +37,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Calls { namespace { +constexpr auto kDelaysCount = 201; + void SaveCallJoinMuted( not_null channel, uint64 callId, @@ -56,6 +59,22 @@ void SaveCallJoinMuted( )).send(); } +[[nodiscard]] crl::time DelayByIndex(int index) { + return index * crl::time(10); +} + +[[nodiscard]] QString FormatDelay(crl::time delay) { + return (delay < crl::time(1000)) + ? tr::lng_group_call_ptt_delay_ms( + tr::now, + lt_amount, + QString::number(delay)) + : tr::lng_group_call_ptt_delay_s( + tr::now, + lt_amount, + QString::number(delay / 1000., 'f', 2)); +} + } // namespace void GroupCallSettingsBox( @@ -164,6 +183,7 @@ void GroupCallSettingsBox( rpl::variable recordText = tr::lng_group_call_ptt_shortcut(); rpl::variable shortcutText; GlobalShortcut shortcut; + crl::time delay = 0; bool recording = false; }; const auto manager = call->ensureGlobalShortcutManager(); @@ -171,6 +191,7 @@ void GroupCallSettingsBox( const auto state = box->lifetime().make_state(); state->shortcut = manager->shortcutFromSerialized( settings.groupCallPushToTalkShortcut()); + state->delay = settings.groupCallPushToTalkDelay(); state->shortcutText = state->shortcut ? state->shortcut->toDisplayString() : QString(); @@ -240,16 +261,40 @@ void GroupCallSettingsBox( recordingWrap->toggle(toggled, anim::type::normal); }, pushToTalk->lifetime()); + const auto label = layout->add( + object_ptr(layout, st::groupCallDelayLabel), + st::groupCallDelayLabelMargin); + const auto value = std::clamp( + state->delay, + crl::time(0), + DelayByIndex(kDelaysCount - 1)); + const auto callback = [=](crl::time delay) { + state->delay = delay; + label->setText(tr::lng_group_call_ptt_delay( + tr::now, + lt_delay, + FormatDelay(delay))); + Core::App().settings().setGroupCallPushToTalkDelay(delay); + Core::App().saveSettingsDelayed(); + }; + callback(value); + const auto slider = layout->add( + object_ptr(layout, st::groupCallDelaySlider), + st::groupCallDelayMargin); + slider->resize(st::groupCallDelaySlider.seekSize); + slider->setPseudoDiscrete( + kDelaysCount, + DelayByIndex, + value, + callback); + box->boxClosing( ) | rpl::start_with_next([=] { call->applyGlobalShortcutChanges(); }, box->lifetime()); auto boxKeyFilter = [=](not_null e) { - if (e->type() != QEvent::KeyPress) { - return base::EventFilterResult::Continue; - } - return (state->recording) + return (e->type() == QEvent::KeyPress && state->recording) ? base::EventFilterResult::Cancel : base::EventFilterResult::Continue; }; diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 4dd8852ea6..332b20c590 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -111,7 +111,8 @@ QByteArray Settings::serialize() const { << _callVideoInputDeviceId << qint32(_ipRevealWarning ? 1 : 0) << qint32(_groupCallPushToTalk ? 1 : 0) - << _groupCallPushToTalkShortcut; + << _groupCallPushToTalkShortcut + << qint64(_groupCallPushToTalkDelay); } return result; } @@ -181,6 +182,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { qint32 ipRevealWarning = _ipRevealWarning ? 1 : 0; qint32 groupCallPushToTalk = _groupCallPushToTalk ? 1 : 0; QByteArray groupCallPushToTalkShortcut = _groupCallPushToTalkShortcut; + qint64 groupCallPushToTalkDelay = _groupCallPushToTalkDelay; stream >> themesAccentColors; if (!stream.atEnd()) { @@ -270,9 +272,11 @@ void Settings::addFromSerialized(const QByteArray &serialized) { if (!stream.atEnd()) { stream >> groupCallPushToTalk - >> groupCallPushToTalkShortcut; + >> groupCallPushToTalkShortcut + >> groupCallPushToTalkDelay; } - if (stream.status() != QDataStream::Ok) { + if (false && stream.status() != QDataStream::Ok) { + AssertIsDebug(); LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); return; @@ -365,6 +369,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { _systemDarkModeEnabled = (systemDarkModeEnabled == 1); _groupCallPushToTalk = (groupCallPushToTalk == 1); _groupCallPushToTalkShortcut = groupCallPushToTalkShortcut; + _groupCallPushToTalkDelay = groupCallPushToTalkDelay; } bool Settings::chatWide() const { @@ -471,6 +476,10 @@ void Settings::resetOnLastLogout() { //_callInputVolume = 100; //_callAudioDuckingEnabled = true; + _groupCallPushToTalk = false; + _groupCallPushToTalkShortcut = QByteArray(); + _groupCallPushToTalkDelay = 20; + //_themesAccentColors = Window::Theme::AccentColors(); _lastSeenWarningSeen = false; diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index c193ed64cf..c6333ba829 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -229,6 +229,12 @@ public: void setGroupCallPushToTalkShortcut(const QByteArray &serialized) { _groupCallPushToTalkShortcut = serialized; } + [[nodiscard]] crl::time groupCallPushToTalkDelay() const { + return _groupCallPushToTalkDelay; + } + void setGroupCallPushToTalkDelay(crl::time delay) { + _groupCallPushToTalkDelay = delay; + } [[nodiscard]] Window::Theme::AccentColors &themesAccentColors() { return _themesAccentColors; } @@ -527,6 +533,7 @@ private: bool _callAudioDuckingEnabled = true; bool _groupCallPushToTalk = false; QByteArray _groupCallPushToTalkShortcut; + crl::time _groupCallPushToTalkDelay = 20; Window::Theme::AccentColors _themesAccentColors; bool _lastSeenWarningSeen = false; Ui::SendFilesWay _sendFilesWay;