mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-26 11:13:18 +02:00
Add global shortcut permissions check on macOS.
This commit is contained in:
parent
25ffdcc919
commit
f11df0519e
5 changed files with 120 additions and 18 deletions
|
@ -1862,6 +1862,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_group_call_duration_minutes#other" = "{count} minutes";
|
"lng_group_call_duration_minutes#other" = "{count} minutes";
|
||||||
"lng_group_call_duration_seconds#one" = "{count} second";
|
"lng_group_call_duration_seconds#one" = "{count} second";
|
||||||
"lng_group_call_duration_seconds#other" = "{count} seconds";
|
"lng_group_call_duration_seconds#other" = "{count} seconds";
|
||||||
|
"lng_group_call_mac_access" = "Telegram Desktop does not have access to system wide keyboard input required for Push to Talk.";
|
||||||
|
"lng_group_call_mac_input" = "Please allow **Input Monitoring** for Telegram in Privacy Settings.";
|
||||||
|
"lng_group_call_mac_accessibility" = "Please allow **Accessibility** for Telegram in Privacy Settings.\n\nApp restart may be required.";
|
||||||
|
"lng_group_call_mac_settings" = "Open Settings";
|
||||||
|
|
||||||
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ GroupCall::GroupCall(
|
||||||
}
|
}
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
|
|
||||||
|
checkGlobalShortcutAvailability();
|
||||||
|
|
||||||
const auto id = inputCall.c_inputGroupCall().vid().v;
|
const auto id = inputCall.c_inputGroupCall().vid().v;
|
||||||
if (id) {
|
if (id) {
|
||||||
if (const auto call = _channel->call(); call && call->id() == id) {
|
if (const auto call = _channel->call(); call && call->id() == id) {
|
||||||
|
@ -83,6 +85,16 @@ GroupCall::~GroupCall() {
|
||||||
destroyController();
|
destroyController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCall::checkGlobalShortcutAvailability() {
|
||||||
|
auto &settings = Core::App().settings();
|
||||||
|
if (!settings.groupCallPushToTalk()) {
|
||||||
|
return;
|
||||||
|
} else if (!base::GlobalShortcutsAllowed()) {
|
||||||
|
settings.setGroupCallPushToTalk(false);
|
||||||
|
Core::App().saveSettingsDelayed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::setState(State state) {
|
void GroupCall::setState(State state) {
|
||||||
if (_state.current() == State::Failed) {
|
if (_state.current() == State::Failed) {
|
||||||
return;
|
return;
|
||||||
|
@ -747,18 +759,14 @@ auto GroupCall::ensureGlobalShortcutManager()
|
||||||
void GroupCall::applyGlobalShortcutChanges() {
|
void GroupCall::applyGlobalShortcutChanges() {
|
||||||
auto &settings = Core::App().settings();
|
auto &settings = Core::App().settings();
|
||||||
if (!settings.groupCallPushToTalk()
|
if (!settings.groupCallPushToTalk()
|
||||||
|| settings.groupCallPushToTalkShortcut().isEmpty()) {
|
|| settings.groupCallPushToTalkShortcut().isEmpty()
|
||||||
|
|| !base::GlobalShortcutsAvailable()
|
||||||
|
|| !base::GlobalShortcutsAllowed()) {
|
||||||
_shortcutManager = nullptr;
|
_shortcutManager = nullptr;
|
||||||
_pushToTalk = nullptr;
|
_pushToTalk = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ensureGlobalShortcutManager();
|
ensureGlobalShortcutManager();
|
||||||
if (!_shortcutManager) {
|
|
||||||
settings.setGroupCallPushToTalk(false);
|
|
||||||
Core::App().saveSettingsDelayed();
|
|
||||||
_pushToTalk = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto shortcut = _shortcutManager->shortcutFromSerialized(
|
const auto shortcut = _shortcutManager->shortcutFromSerialized(
|
||||||
settings.groupCallPushToTalkShortcut());
|
settings.groupCallPushToTalkShortcut());
|
||||||
if (!shortcut) {
|
if (!shortcut) {
|
||||||
|
|
|
@ -154,6 +154,7 @@ private:
|
||||||
void checkLastSpoke();
|
void checkLastSpoke();
|
||||||
void pushToTalkCancel();
|
void pushToTalkCancel();
|
||||||
|
|
||||||
|
void checkGlobalShortcutAvailability();
|
||||||
void checkJoined();
|
void checkJoined();
|
||||||
|
|
||||||
[[nodiscard]] MTPInputGroupCall inputCall() const;
|
[[nodiscard]] MTPInputGroupCall inputCall() const;
|
||||||
|
|
|
@ -14,10 +14,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/continuous_sliders.h"
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
#include "base/timer_rpl.h"
|
||||||
#include "base/event_filter.h"
|
#include "base/event_filter.h"
|
||||||
#include "base/global_shortcuts.h"
|
#include "base/global_shortcuts.h"
|
||||||
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_group_call.h"
|
#include "data/data_group_call.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
@ -38,6 +41,7 @@ namespace Calls {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kDelaysCount = 201;
|
constexpr auto kDelaysCount = 201;
|
||||||
|
constexpr auto kCheckAccessibilityInterval = crl::time(500);
|
||||||
|
|
||||||
void SaveCallJoinMuted(
|
void SaveCallJoinMuted(
|
||||||
not_null<ChannelData*> channel,
|
not_null<ChannelData*> channel,
|
||||||
|
@ -182,24 +186,39 @@ void GroupCallSettingsBox(
|
||||||
struct PushToTalkState {
|
struct PushToTalkState {
|
||||||
rpl::variable<QString> recordText = tr::lng_group_call_ptt_shortcut();
|
rpl::variable<QString> recordText = tr::lng_group_call_ptt_shortcut();
|
||||||
rpl::variable<QString> shortcutText;
|
rpl::variable<QString> shortcutText;
|
||||||
|
rpl::event_stream<bool> pushToTalkToggles;
|
||||||
|
std::shared_ptr<base::GlobalShortcutManager> manager;
|
||||||
GlobalShortcut shortcut;
|
GlobalShortcut shortcut;
|
||||||
crl::time delay = 0;
|
crl::time delay = 0;
|
||||||
bool recording = false;
|
bool recording = false;
|
||||||
};
|
};
|
||||||
const auto manager = call->ensureGlobalShortcutManager();
|
if (base::GlobalShortcutsAvailable()) {
|
||||||
if (manager) {
|
|
||||||
const auto state = box->lifetime().make_state<PushToTalkState>();
|
const auto state = box->lifetime().make_state<PushToTalkState>();
|
||||||
state->shortcut = manager->shortcutFromSerialized(
|
if (!base::GlobalShortcutsAllowed()) {
|
||||||
settings.groupCallPushToTalkShortcut());
|
Core::App().settings().setGroupCallPushToTalk(false);
|
||||||
|
}
|
||||||
|
const auto tryFillFromManager = [=] {
|
||||||
|
state->shortcut = state->manager
|
||||||
|
? state->manager->shortcutFromSerialized(
|
||||||
|
Core::App().settings().groupCallPushToTalkShortcut())
|
||||||
|
: nullptr;
|
||||||
|
state->shortcutText = state->shortcut
|
||||||
|
? state->shortcut->toDisplayString()
|
||||||
|
: QString();
|
||||||
|
};
|
||||||
|
state->manager = settings.groupCallPushToTalk()
|
||||||
|
? call->ensureGlobalShortcutManager()
|
||||||
|
: nullptr;
|
||||||
|
tryFillFromManager();
|
||||||
|
|
||||||
state->delay = settings.groupCallPushToTalkDelay();
|
state->delay = settings.groupCallPushToTalkDelay();
|
||||||
state->shortcutText = state->shortcut
|
|
||||||
? state->shortcut->toDisplayString()
|
|
||||||
: QString();
|
|
||||||
const auto pushToTalk = AddButton(
|
const auto pushToTalk = AddButton(
|
||||||
layout,
|
layout,
|
||||||
tr::lng_group_call_push_to_talk(),
|
tr::lng_group_call_push_to_talk(),
|
||||||
st::groupCallSettingsButton
|
st::groupCallSettingsButton
|
||||||
)->toggleOn(rpl::single(settings.groupCallPushToTalk()));
|
)->toggleOn(rpl::single(
|
||||||
|
settings.groupCallPushToTalk()
|
||||||
|
) | rpl::then(state->pushToTalkToggles.events()));
|
||||||
const auto pushToTalkWrap = layout->add(
|
const auto pushToTalkWrap = layout->add(
|
||||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||||
layout,
|
layout,
|
||||||
|
@ -220,6 +239,65 @@ void GroupCallSettingsBox(
|
||||||
call->applyGlobalShortcutChanges();
|
call->applyGlobalShortcutChanges();
|
||||||
Core::App().saveSettingsDelayed();
|
Core::App().saveSettingsDelayed();
|
||||||
};
|
};
|
||||||
|
const auto showPrivacyRequest = [=] {
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
if (!Platform::IsMac10_14OrGreater()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto requestInputMonitoring = Platform::IsMac10_15OrGreater();
|
||||||
|
box->getDelegate()->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||||
|
box->addRow(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
box.get(),
|
||||||
|
rpl::combine(
|
||||||
|
tr::lng_group_call_mac_access(),
|
||||||
|
(requestInputMonitoring
|
||||||
|
? tr::lng_group_call_mac_input()
|
||||||
|
: tr::lng_group_call_mac_accessibility())
|
||||||
|
) | rpl::map([](QString a, QString b) {
|
||||||
|
auto result = Ui::Text::RichLangValue(a);
|
||||||
|
result.append("\n\n").append(Ui::Text::RichLangValue(b));
|
||||||
|
return result;
|
||||||
|
}),
|
||||||
|
st::groupCallBoxLabel),
|
||||||
|
style::margins(
|
||||||
|
st::boxRowPadding.left(),
|
||||||
|
st::boxPadding.top(),
|
||||||
|
st::boxRowPadding.right(),
|
||||||
|
st::boxPadding.bottom()));
|
||||||
|
box->addButton(tr::lng_group_call_mac_settings(), [=] {
|
||||||
|
if (requestInputMonitoring) {
|
||||||
|
Platform::OpenInputMonitoringPrivacySettings();
|
||||||
|
} else {
|
||||||
|
Platform::OpenAccessibilityPrivacySettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
|
||||||
|
|
||||||
|
if (!requestInputMonitoring) {
|
||||||
|
// Accessibility is enabled without app restart, so short-poll it.
|
||||||
|
base::timer_each(
|
||||||
|
kCheckAccessibilityInterval
|
||||||
|
) | rpl::filter([] {
|
||||||
|
return base::GlobalShortcutsAllowed();
|
||||||
|
}) | rpl::start_with_next([=] {
|
||||||
|
box->closeBox();
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
#endif // Q_OS_MAC
|
||||||
|
};
|
||||||
|
const auto ensureManager = [=] {
|
||||||
|
if (state->manager) {
|
||||||
|
return true;
|
||||||
|
} else if (base::GlobalShortcutsAllowed()) {
|
||||||
|
state->manager = call->ensureGlobalShortcutManager();
|
||||||
|
tryFillFromManager();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
showPrivacyRequest();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
const auto stopRecording = [=] {
|
const auto stopRecording = [=] {
|
||||||
state->recording = false;
|
state->recording = false;
|
||||||
state->recordText = tr::lng_group_call_ptt_shortcut();
|
state->recordText = tr::lng_group_call_ptt_shortcut();
|
||||||
|
@ -227,9 +305,16 @@ void GroupCallSettingsBox(
|
||||||
? state->shortcut->toDisplayString()
|
? state->shortcut->toDisplayString()
|
||||||
: QString();
|
: QString();
|
||||||
recording->setColorOverride(std::nullopt);
|
recording->setColorOverride(std::nullopt);
|
||||||
manager->stopRecording();
|
if (state->manager) {
|
||||||
|
state->manager->stopRecording();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const auto startRecording = [=] {
|
const auto startRecording = [=] {
|
||||||
|
if (!ensureManager()) {
|
||||||
|
state->pushToTalkToggles.fire(false);
|
||||||
|
pushToTalkWrap->hide(anim::type::instant);
|
||||||
|
return;
|
||||||
|
}
|
||||||
state->recording = true;
|
state->recording = true;
|
||||||
state->recordText = tr::lng_group_call_ptt_recording();
|
state->recordText = tr::lng_group_call_ptt_recording();
|
||||||
recording->setColorOverride(
|
recording->setColorOverride(
|
||||||
|
@ -245,7 +330,7 @@ void GroupCallSettingsBox(
|
||||||
applyAndSave();
|
applyAndSave();
|
||||||
stopRecording();
|
stopRecording();
|
||||||
});
|
});
|
||||||
manager->startRecording(std::move(progress), std::move(done));
|
state->manager->startRecording(std::move(progress), std::move(done));
|
||||||
};
|
};
|
||||||
recording->addClickHandler([=] {
|
recording->addClickHandler([=] {
|
||||||
if (state->recording) {
|
if (state->recording) {
|
||||||
|
@ -293,6 +378,10 @@ void GroupCallSettingsBox(
|
||||||
) | rpl::start_with_next([=](bool toggled) {
|
) | rpl::start_with_next([=](bool toggled) {
|
||||||
if (!toggled) {
|
if (!toggled) {
|
||||||
stopRecording();
|
stopRecording();
|
||||||
|
} else if (!ensureManager()) {
|
||||||
|
state->pushToTalkToggles.fire(false);
|
||||||
|
pushToTalkWrap->hide(anim::type::instant);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Core::App().settings().setGroupCallPushToTalk(toggled);
|
Core::App().settings().setGroupCallPushToTalk(toggled);
|
||||||
applyAndSave();
|
applyAndSave();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit aadebb110e2fe3438cf99b64427b604564ea4ade
|
Subproject commit 01a7497eb84abc2353011d7f5dd4a5e6441e6957
|
Loading…
Add table
Reference in a new issue