mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 07:07:08 +02:00
Add a hint to unmute your microphone.
This commit is contained in:
parent
1cb1f1cbc1
commit
7a588be54f
7 changed files with 166 additions and 35 deletions
Telegram/SourceFiles
|
@ -1251,7 +1251,7 @@ groupCallTooltip: Tooltip(defaultTooltip) {
|
|||
}
|
||||
groupCallNiceTooltip: ImportantTooltip(defaultImportantTooltip) {
|
||||
bg: importantTooltipBg;
|
||||
padding: margins(10px, 1px, 10px, 3px);
|
||||
padding: margins(10px, 3px, 10px, 5px);
|
||||
radius: 4px;
|
||||
arrow: 4px;
|
||||
}
|
||||
|
|
|
@ -68,4 +68,13 @@ enum class Error {
|
|||
DisabledNoScreen,
|
||||
};
|
||||
|
||||
enum class StickedTooltip {
|
||||
Camera = 0x01,
|
||||
Microphone = 0x02,
|
||||
};
|
||||
constexpr inline bool is_flag_type(StickedTooltip) {
|
||||
return true;
|
||||
}
|
||||
using StickedTooltips = base::flags<StickedTooltip>;
|
||||
|
||||
} // namespace Calls::Group
|
||||
|
|
|
@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "apiwrap.h" // api().kickParticipant.
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "webrtc/webrtc_media_devices.h" // UniqueDesktopCaptureSource.
|
||||
#include "webrtc/webrtc_audio_input_tester.h"
|
||||
#include "styles/style_calls.h"
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
|
@ -71,6 +72,10 @@ constexpr auto kRecordingOpacity = 0.6;
|
|||
constexpr auto kStartNoConfirmation = TimeId(10);
|
||||
constexpr auto kControlsBackgroundOpacity = 0.8;
|
||||
constexpr auto kOverrideActiveColorBgAlpha = 172;
|
||||
constexpr auto kMicrophoneTooltipAfterLoudCount = 3;
|
||||
constexpr auto kDropLoudAfterQuietCount = 5;
|
||||
constexpr auto kMicrophoneTooltipLevelThreshold = 0.2;
|
||||
constexpr auto kMicrophoneTooltipCheckInterval = crl::time(500);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -84,6 +89,49 @@ struct Panel::ControlsBackgroundNarrow {
|
|||
Ui::RpWidget blocker;
|
||||
};
|
||||
|
||||
class Panel::MicLevelTester final {
|
||||
public:
|
||||
explicit MicLevelTester(Fn<void()> show);
|
||||
|
||||
[[nodiscard]] bool showTooltip() const;
|
||||
|
||||
private:
|
||||
void check();
|
||||
|
||||
Fn<void()> _show;
|
||||
base::Timer _timer;
|
||||
Webrtc::AudioInputTester _tester;
|
||||
int _loudCount = 0;
|
||||
int _quietCount = 0;
|
||||
|
||||
};
|
||||
|
||||
Panel::MicLevelTester::MicLevelTester(Fn<void()> show)
|
||||
: _show(std::move(show))
|
||||
, _timer([=] { check(); })
|
||||
, _tester(
|
||||
Core::App().settings().callAudioBackend(),
|
||||
Core::App().settings().callInputDeviceId()) {
|
||||
_timer.callEach(kMicrophoneTooltipCheckInterval);
|
||||
}
|
||||
|
||||
bool Panel::MicLevelTester::showTooltip() const {
|
||||
return (_loudCount >= kMicrophoneTooltipAfterLoudCount);
|
||||
}
|
||||
|
||||
void Panel::MicLevelTester::check() {
|
||||
const auto level = _tester.getAndResetLevel();
|
||||
if (level >= kMicrophoneTooltipLevelThreshold) {
|
||||
_quietCount = 0;
|
||||
if (++_loudCount >= kMicrophoneTooltipAfterLoudCount) {
|
||||
_show();
|
||||
}
|
||||
} else if (_loudCount > 0 && ++_quietCount >= kDropLoudAfterQuietCount) {
|
||||
_quietCount = 0;
|
||||
_loudCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Panel::Panel(not_null<GroupCall*> call)
|
||||
: _call(call)
|
||||
, _peer(call->peer())
|
||||
|
@ -112,6 +160,7 @@ Panel::Panel(not_null<GroupCall*> call)
|
|||
: Ui::CallMuteButtonType::ScheduledSilent),
|
||||
}))
|
||||
, _hangup(widget(), st::groupCallHangup)
|
||||
, _stickedTooltipsShown(Core::App().settings().hiddenGroupCallTooltips())
|
||||
, _toasts(std::make_unique<Toasts>(this)) {
|
||||
_layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox);
|
||||
_layerBg->setHideByBackgroundClick(true);
|
||||
|
@ -418,7 +467,9 @@ void Panel::initControls() {
|
|||
}
|
||||
|
||||
_call->stateValue(
|
||||
) | rpl::filter([](State state) {
|
||||
) | rpl::before_next([=] {
|
||||
showStickedTooltip();
|
||||
}) | rpl::filter([](State state) {
|
||||
return (state == State::HangingUp)
|
||||
|| (state == State::Ended)
|
||||
|| (state == State::FailedHangingUp)
|
||||
|
@ -515,11 +566,6 @@ void Panel::refreshVideoButtons(std::optional<bool> overrideWideMode) {
|
|||
}
|
||||
_video->setProgress(sharing ? 1. : 0.);
|
||||
}, _video->lifetime());
|
||||
_call->mutedValue(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateButtonsGeometry();
|
||||
showStickedTooltip();
|
||||
}, _video->lifetime());
|
||||
}
|
||||
if (!_screenShare) {
|
||||
_screenShare.create(widget(), st::groupCallScreenShareSmall);
|
||||
|
@ -562,7 +608,8 @@ void Panel::hideStickedTooltip(
|
|||
if (hide != StickedTooltipHide::Unavailable) {
|
||||
_stickedTooltipsShown |= type;
|
||||
if (hide == StickedTooltipHide::Discarded) {
|
||||
// #TODO calls save to settings.
|
||||
Core::App().settings().setHiddenGroupCallTooltip(type);
|
||||
Core::App().saveSettingsDelayed();
|
||||
}
|
||||
}
|
||||
const auto control = (type == StickedTooltip::Camera)
|
||||
|
@ -886,6 +933,9 @@ void Panel::raiseControls() {
|
|||
}
|
||||
}
|
||||
_mute->raise();
|
||||
if (_niceTooltip) {
|
||||
_niceTooltip->raise();
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::setupVideo(not_null<Viewport*> viewport) {
|
||||
|
@ -1052,6 +1102,18 @@ void Panel::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
|||
refreshTopButton();
|
||||
}, widget()->lifetime());
|
||||
|
||||
_call->mutedValue(
|
||||
) | rpl::skip(1) | rpl::start_with_next([=](MuteState state) {
|
||||
updateButtonsGeometry();
|
||||
if (state == MuteState::Active
|
||||
|| state == MuteState::PushToTalk) {
|
||||
hideStickedTooltip(
|
||||
StickedTooltip::Microphone,
|
||||
StickedTooltipHide::Activated);
|
||||
}
|
||||
showStickedTooltip();
|
||||
}, widget()->lifetime());
|
||||
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
|
@ -1407,7 +1469,10 @@ bool Panel::updateMode() {
|
|||
_call->showVideoEndpointLarge({});
|
||||
}
|
||||
refreshVideoButtons(wide);
|
||||
_niceTooltip.destroy();
|
||||
if (!_stickedTooltipClose
|
||||
|| _niceTooltipControl.data() != _mute->outer().get()) {
|
||||
_niceTooltip.destroy();
|
||||
}
|
||||
_mode = mode;
|
||||
if (_title) {
|
||||
_title->setTextColorOverride(wide
|
||||
|
@ -1631,7 +1696,10 @@ void Panel::trackControlOver(not_null<Ui::RpWidget*> control, bool over) {
|
|||
|
||||
void Panel::showStickedTooltip() {
|
||||
static const auto kHasCamera = !Webrtc::GetVideoInputList().empty();
|
||||
const auto callReady = (_call->state() == State::Joined
|
||||
|| _call->state() == State::Connecting);
|
||||
if (!(_stickedTooltipsShown & StickedTooltip::Camera)
|
||||
&& callReady
|
||||
&& (_mode.current() == PanelMode::Wide)
|
||||
&& _video
|
||||
&& _call->videoIsWorking()
|
||||
|
@ -1645,13 +1713,25 @@ void Panel::showStickedTooltip() {
|
|||
StickedTooltipHide::Unavailable);
|
||||
|
||||
if (!(_stickedTooltipsShown & StickedTooltip::Microphone)
|
||||
&& (_mode.current() == PanelMode::Wide)
|
||||
&& callReady
|
||||
&& _mute
|
||||
&& !_call->mutedByAdmin()
|
||||
&& false) { // Check if there is incoming sound.
|
||||
showNiceTooltip(_mute->outer(), NiceTooltipType::Sticked);
|
||||
&& !_call->mutedByAdmin()) {
|
||||
if (_stickedTooltipClose) {
|
||||
// Showing already.
|
||||
return;
|
||||
} else if (!_micLevelTester) {
|
||||
// Check if there is incoming sound.
|
||||
_micLevelTester = std::make_unique<MicLevelTester>([=] {
|
||||
showStickedTooltip();
|
||||
});
|
||||
}
|
||||
if (_micLevelTester->showTooltip()) {
|
||||
_micLevelTester = nullptr;
|
||||
showNiceTooltip(_mute->outer(), NiceTooltipType::Sticked);
|
||||
}
|
||||
return;
|
||||
}
|
||||
_micLevelTester = nullptr;
|
||||
hideStickedTooltip(
|
||||
StickedTooltip::Microphone,
|
||||
StickedTooltipHide::Unavailable);
|
||||
|
@ -1685,11 +1765,12 @@ void Panel::showNiceTooltip(
|
|||
}
|
||||
return rpl::producer<QString>();
|
||||
}();
|
||||
if (!text
|
||||
|| _wideControlsAnimation.animating()
|
||||
|| !_wideControlsShown
|
||||
|| _stickedTooltipClose) {
|
||||
if (!text || _stickedTooltipClose) {
|
||||
return;
|
||||
} else if (_wideControlsAnimation.animating() || !_wideControlsShown) {
|
||||
if (type == NiceTooltipType::Normal) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const auto inner = [&]() -> Ui::RpWidget* {
|
||||
const auto normal = (type == NiceTooltipType::Normal);
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/timer.h"
|
||||
#include "base/object_ptr.h"
|
||||
#include "calls/group/calls_group_call.h"
|
||||
#include "calls/group/calls_group_common.h"
|
||||
#include "calls/group/calls_choose_join_as.h"
|
||||
#include "calls/group/ui/desktop_capture_choose_source.h"
|
||||
#include "ui/effects/animations.h"
|
||||
|
@ -64,6 +65,7 @@ class Toasts;
|
|||
class Members;
|
||||
class Viewport;
|
||||
enum class PanelMode;
|
||||
enum class StickedTooltip;
|
||||
|
||||
class Panel final : private Ui::DesktopCapture::ChooseSourceDelegate {
|
||||
public:
|
||||
|
@ -88,19 +90,12 @@ private:
|
|||
Normal,
|
||||
Sticked,
|
||||
};
|
||||
enum class StickedTooltip {
|
||||
Camera = 0x01,
|
||||
Microphone = 0x02,
|
||||
};
|
||||
friend constexpr inline bool is_flag_type(StickedTooltip) {
|
||||
return true;
|
||||
};
|
||||
using StickedTooltips = base::flags<StickedTooltip>;
|
||||
enum class StickedTooltipHide {
|
||||
Unavailable,
|
||||
Activated,
|
||||
Discarded,
|
||||
};
|
||||
class MicLevelTester;
|
||||
|
||||
std::unique_ptr<Ui::Window> createWindow();
|
||||
[[nodiscard]] not_null<Ui::RpWidget*> widget() const;
|
||||
|
@ -236,6 +231,8 @@ private:
|
|||
const std::unique_ptr<Toasts> _toasts;
|
||||
base::weak_ptr<Ui::Toast::Instance> _lastToast;
|
||||
|
||||
std::unique_ptr<MicLevelTester> _micLevelTester;
|
||||
|
||||
rpl::lifetime _peerLifetime;
|
||||
|
||||
};
|
||||
|
|
|
@ -493,8 +493,10 @@ void SettingsBox(
|
|||
tr::now,
|
||||
lt_delay,
|
||||
FormatDelay(delay)));
|
||||
Core::App().settings().setGroupCallPushToTalkDelay(delay);
|
||||
applyAndSave();
|
||||
if (Core::App().settings().groupCallPushToTalkDelay() != delay) {
|
||||
Core::App().settings().setGroupCallPushToTalkDelay(delay);
|
||||
applyAndSave();
|
||||
}
|
||||
};
|
||||
callback(value);
|
||||
const auto slider = pushToTalkInner->add(
|
||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/platform/base_platform_info.h"
|
||||
#include "webrtc/webrtc_create_adm.h"
|
||||
#include "ui/gl/gl_detection.h"
|
||||
#include "calls/group/calls_group_common.h"
|
||||
#include "facades.h"
|
||||
|
||||
namespace Core {
|
||||
|
@ -94,23 +95,35 @@ QByteArray Settings::serialize() const {
|
|||
+ sizeof(qint32) * 5
|
||||
+ Serialize::stringSize(_downloadPath.current())
|
||||
+ Serialize::bytearraySize(_downloadPathBookmark)
|
||||
+ sizeof(qint32) * 12
|
||||
+ sizeof(qint32) * 9
|
||||
+ Serialize::stringSize(_callOutputDeviceId)
|
||||
+ Serialize::stringSize(_callInputDeviceId)
|
||||
+ Serialize::stringSize(_callVideoInputDeviceId)
|
||||
+ sizeof(qint32) * 5
|
||||
+ Serialize::bytearraySize(proxy);
|
||||
+ sizeof(qint32) * 5;
|
||||
for (const auto &[key, value] : _soundOverrides) {
|
||||
size += Serialize::stringSize(key) + Serialize::stringSize(value);
|
||||
}
|
||||
size += sizeof(qint32) * 13
|
||||
+ Serialize::bytearraySize(_videoPipGeometry)
|
||||
+ sizeof(qint32)
|
||||
+ (_dictionariesEnabled.current().size() * sizeof(quint64))
|
||||
+ sizeof(qint32) * 12
|
||||
+ Serialize::stringSize(_callVideoInputDeviceId)
|
||||
+ sizeof(qint32) * 2
|
||||
+ Serialize::bytearraySize(_groupCallPushToTalkShortcut)
|
||||
+ sizeof(qint64)
|
||||
+ sizeof(qint32) * 2
|
||||
+ Serialize::bytearraySize(windowPosition)
|
||||
+ sizeof(qint32);
|
||||
for (const auto &[id, rating] : recentEmojiPreloadData) {
|
||||
size += Serialize::stringSize(id) + sizeof(quint16);
|
||||
}
|
||||
size += sizeof(qint32);
|
||||
for (const auto &[id, variant] : _emojiVariants) {
|
||||
size += Serialize::stringSize(id) + sizeof(quint8);
|
||||
}
|
||||
size += Serialize::bytearraySize(_videoPipGeometry);
|
||||
size += Serialize::bytearraySize(windowPosition);
|
||||
size += sizeof(qint32) * 3
|
||||
+ Serialize::bytearraySize(proxy)
|
||||
+ sizeof(qint32);
|
||||
|
||||
auto result = QByteArray();
|
||||
result.reserve(size);
|
||||
|
@ -200,8 +213,9 @@ QByteArray Settings::serialize() const {
|
|||
stream
|
||||
<< qint32(_disableOpenGL ? 1 : 0)
|
||||
<< qint32(_groupCallNoiseSuppression ? 1 : 0)
|
||||
<< _workMode.current()
|
||||
<< proxy;
|
||||
<< qint32(_workMode.current())
|
||||
<< proxy
|
||||
<< qint32(_hiddenGroupCallTooltips.value());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -281,6 +295,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
qint32 groupCallNoiseSuppression = _groupCallNoiseSuppression ? 1 : 0;
|
||||
qint32 workMode = static_cast<qint32>(_workMode.current());
|
||||
QByteArray proxy;
|
||||
qint32 hiddenGroupCallTooltips = qint32(_hiddenGroupCallTooltips.value());
|
||||
|
||||
stream >> themesAccentColors;
|
||||
if (!stream.atEnd()) {
|
||||
|
@ -421,6 +436,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
if (!stream.atEnd()) {
|
||||
stream >> proxy;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
stream >> hiddenGroupCallTooltips;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||
|
@ -540,6 +558,16 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
|||
case WorkMode::TrayOnly:
|
||||
case WorkMode::WindowOnly: _workMode = uncheckedWorkMode; break;
|
||||
}
|
||||
_hiddenGroupCallTooltips = [&] {
|
||||
using Tooltip = Calls::Group::StickedTooltip;
|
||||
return Tooltip(0)
|
||||
| ((hiddenGroupCallTooltips & int(Tooltip::Camera))
|
||||
? Tooltip::Camera
|
||||
: Tooltip(0))
|
||||
| ((hiddenGroupCallTooltips & int(Tooltip::Microphone))
|
||||
? Tooltip::Microphone
|
||||
: Tooltip(0));
|
||||
}();
|
||||
}
|
||||
|
||||
QString Settings::getSoundPath(const QString &key) const {
|
||||
|
@ -795,6 +823,7 @@ void Settings::resetOnLastLogout() {
|
|||
_notifyFromAll = true;
|
||||
_tabbedReplacedWithInfo = false; // per-window
|
||||
_systemDarkModeEnabled = false;
|
||||
_hiddenGroupCallTooltips = 0;
|
||||
|
||||
_recentEmojiPreload.clear();
|
||||
_recentEmoji.clear();
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "window/themes/window_themes_embedded.h"
|
||||
#include "ui/chat/attach/attach_send_files_way.h"
|
||||
#include "platform/platform_notifications_manager.h"
|
||||
#include "base/flags.h"
|
||||
#include "emoji.h"
|
||||
|
||||
enum class RectPart;
|
||||
|
@ -27,6 +28,10 @@ namespace Webrtc {
|
|||
enum class Backend;
|
||||
} // namespace Webrtc
|
||||
|
||||
namespace Calls::Group {
|
||||
enum class StickedTooltip;
|
||||
} // namespace Calls::Group
|
||||
|
||||
namespace Core {
|
||||
|
||||
struct WindowPosition {
|
||||
|
@ -574,6 +579,13 @@ public:
|
|||
_disableOpenGL = value;
|
||||
}
|
||||
|
||||
[[nodiscard]] base::flags<Calls::Group::StickedTooltip> hiddenGroupCallTooltips() const {
|
||||
return _hiddenGroupCallTooltips;
|
||||
}
|
||||
void setHiddenGroupCallTooltip(Calls::Group::StickedTooltip value) {
|
||||
_hiddenGroupCallTooltips |= value;
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool ThirdColumnByDefault();
|
||||
[[nodiscard]] static float64 DefaultDialogsWidthRatio();
|
||||
[[nodiscard]] static qint32 SerializePlaybackSpeed(float64 speed) {
|
||||
|
@ -671,6 +683,7 @@ private:
|
|||
WindowPosition _windowPosition; // per-window
|
||||
bool _disableOpenGL = false;
|
||||
rpl::variable<WorkMode> _workMode = WorkMode::WindowAndTray;
|
||||
base::flags<Calls::Group::StickedTooltip> _hiddenGroupCallTooltips;
|
||||
|
||||
bool _tabbedReplacedWithInfo = false; // per-window
|
||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
||||
|
|
Loading…
Add table
Reference in a new issue