mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Added initial support of privacy setting for voice messages.
This commit is contained in:
parent
b295a9eeb1
commit
67195f3825
12 changed files with 148 additions and 11 deletions
|
@ -557,6 +557,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_settings_phone_number_privacy" = "Phone number";
|
"lng_settings_phone_number_privacy" = "Phone number";
|
||||||
"lng_settings_forwards_privacy" = "Forwarded messages";
|
"lng_settings_forwards_privacy" = "Forwarded messages";
|
||||||
"lng_settings_profile_photo_privacy" = "Profile photo";
|
"lng_settings_profile_photo_privacy" = "Profile photo";
|
||||||
|
"lng_settings_voices_privacy" = "Voice messages";
|
||||||
"lng_settings_sessions_about" = "Control your sessions on other devices.";
|
"lng_settings_sessions_about" = "Control your sessions on other devices.";
|
||||||
"lng_settings_passcode_disable" = "Disable Passcode";
|
"lng_settings_passcode_disable" = "Disable Passcode";
|
||||||
"lng_settings_passcode_disable_sure" = "Are you sure you want to disable passcode?";
|
"lng_settings_passcode_disable_sure" = "Are you sure you want to disable passcode?";
|
||||||
|
@ -987,6 +988,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_edit_privacy_profile_photo_always_title" = "Always allow";
|
"lng_edit_privacy_profile_photo_always_title" = "Always allow";
|
||||||
"lng_edit_privacy_profile_photo_never_title" = "Never allow";
|
"lng_edit_privacy_profile_photo_never_title" = "Never allow";
|
||||||
|
|
||||||
|
"lng_edit_privacy_voices_title" = "Voice messages settings";
|
||||||
|
"lng_edit_privacy_voices_header" = "Who can send me voice messages";
|
||||||
|
"lng_edit_privacy_voices_always_empty" = "Always allow";
|
||||||
|
"lng_edit_privacy_voices_never_empty" = "Never allow";
|
||||||
|
"lng_edit_privacy_voices_exceptions" = "These users will or will not be able to send voice and video messages to you regardless of the settings above.";
|
||||||
|
"lng_edit_privacy_voices_always_title" = "Always allow";
|
||||||
|
"lng_edit_privacy_voices_never_title" = "Never allow";
|
||||||
|
|
||||||
"lng_self_destruct_title" = "Account self-destruction";
|
"lng_self_destruct_title" = "Account self-destruction";
|
||||||
"lng_self_destruct_description" = "If you don't come online at least once within this period, your account will be deleted along with all groups, messages and contacts.";
|
"lng_self_destruct_description" = "If you don't come online at least once within this period, your account will be deleted along with all groups, messages and contacts.";
|
||||||
"lng_self_destruct_sessions_title" = "Session termination";
|
"lng_self_destruct_sessions_title" = "Session termination";
|
||||||
|
@ -2837,6 +2846,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
"lng_restricted_send_public_polls" = "Sorry, public polls can't be forwarded to channels.";
|
"lng_restricted_send_public_polls" = "Sorry, public polls can't be forwarded to channels.";
|
||||||
|
|
||||||
|
"lng_restricted_send_voices" = "{user} restricted sending of voice messages to them.";
|
||||||
|
|
||||||
"lng_exceptions_list_title" = "Exceptions";
|
"lng_exceptions_list_title" = "Exceptions";
|
||||||
"lng_removed_list_title" = "Removed users";
|
"lng_removed_list_title" = "Removed users";
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
#include "settings/settings_premium.h" // Settings::ShowPremium.
|
||||||
|
|
||||||
namespace Api {
|
namespace Api {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -186,6 +187,8 @@ MTPInputPrivacyKey KeyToTL(UserPrivacy::Key key) {
|
||||||
return MTP_inputPrivacyKeyForwards();
|
return MTP_inputPrivacyKeyForwards();
|
||||||
case Key::ProfilePhoto:
|
case Key::ProfilePhoto:
|
||||||
return MTP_inputPrivacyKeyProfilePhoto();
|
return MTP_inputPrivacyKeyProfilePhoto();
|
||||||
|
case Key::Voices:
|
||||||
|
return MTP_inputPrivacyKeyVoiceMessages();
|
||||||
}
|
}
|
||||||
Unexpected("Key in Api::UserPrivacy::KetToTL.");
|
Unexpected("Key in Api::UserPrivacy::KetToTL.");
|
||||||
}
|
}
|
||||||
|
@ -209,6 +212,8 @@ std::optional<UserPrivacy::Key> TLToKey(mtpTypeId type) {
|
||||||
case mtpc_inputPrivacyKeyForwards: return Key::Forwards;
|
case mtpc_inputPrivacyKeyForwards: return Key::Forwards;
|
||||||
case mtpc_privacyKeyProfilePhoto:
|
case mtpc_privacyKeyProfilePhoto:
|
||||||
case mtpc_inputPrivacyKeyProfilePhoto: return Key::ProfilePhoto;
|
case mtpc_inputPrivacyKeyProfilePhoto: return Key::ProfilePhoto;
|
||||||
|
case mtpc_privacyKeyVoiceMessages:
|
||||||
|
case mtpc_inputPrivacyKeyVoiceMessages: return Key::Voices;
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +246,11 @@ void UserPrivacy::save(
|
||||||
_privacySaveRequests.remove(keyTypeId);
|
_privacySaveRequests.remove(keyTypeId);
|
||||||
apply(keyTypeId, data.vrules(), true);
|
apply(keyTypeId, data.vrules(), true);
|
||||||
});
|
});
|
||||||
}).fail([=] {
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
const auto message = error.type();
|
||||||
|
if (message == u"PREMIUM_ACCOUNT_REQUIRED"_q) {
|
||||||
|
Settings::ShowPremium(_session, QString());
|
||||||
|
}
|
||||||
_privacySaveRequests.remove(keyTypeId);
|
_privacySaveRequests.remove(keyTypeId);
|
||||||
}).send();
|
}).send();
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
CallsPeer2Peer,
|
CallsPeer2Peer,
|
||||||
Forwards,
|
Forwards,
|
||||||
ProfilePhoto,
|
ProfilePhoto,
|
||||||
|
Voices,
|
||||||
};
|
};
|
||||||
enum class Option {
|
enum class Option {
|
||||||
Everyone,
|
Everyone,
|
||||||
|
|
|
@ -1125,6 +1125,14 @@ std::optional<QString> RestrictionError(
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<QString> RestrictionVoicesError(not_null<PeerData*> peer) {
|
||||||
|
const auto user = peer->asUser();
|
||||||
|
if (user && !user->canReceiveVoices()) {
|
||||||
|
return tr::lng_restricted_send_voices(tr::now, lt_user, user->name);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId) {
|
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId) {
|
||||||
if (const auto channel = peer->asChannel()) {
|
if (const auto channel = peer->asChannel()) {
|
||||||
if (messageId <= channel->availableMinId()) {
|
if (messageId <= channel->availableMinId()) {
|
||||||
|
|
|
@ -469,6 +469,8 @@ std::optional<QString> RestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
ChatRestriction restriction);
|
ChatRestriction restriction);
|
||||||
|
|
||||||
|
std::optional<QString> RestrictionVoicesError(not_null<PeerData*> peer);
|
||||||
|
|
||||||
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId);
|
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId);
|
||||||
[[nodiscard]] FullMsgId ResolveTopPinnedId(
|
[[nodiscard]] FullMsgId ResolveTopPinnedId(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
|
|
|
@ -257,6 +257,10 @@ bool UserData::canReceiveGifts() const {
|
||||||
return flags() & UserDataFlag::CanReceiveGifts;
|
return flags() & UserDataFlag::CanReceiveGifts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UserData::canReceiveVoices() const {
|
||||||
|
return flags() & UserDataFlag::CanReceiveVoices;
|
||||||
|
}
|
||||||
|
|
||||||
bool UserData::canShareThisContactFast() const {
|
bool UserData::canShareThisContactFast() const {
|
||||||
return !_phone.isEmpty();
|
return !_phone.isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -327,7 +331,10 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
||||||
| (update.is_phone_calls_available() ? Flag::HasPhoneCalls : Flag())
|
| (update.is_phone_calls_available() ? Flag::HasPhoneCalls : Flag())
|
||||||
| (canReceiveGifts ? Flag::CanReceiveGifts : Flag())
|
| (canReceiveGifts ? Flag::CanReceiveGifts : Flag())
|
||||||
| (update.is_can_pin_message() ? Flag::CanPinMessages : Flag())
|
| (update.is_can_pin_message() ? Flag::CanPinMessages : Flag())
|
||||||
| (update.is_blocked() ? Flag::Blocked : Flag()));
|
| (update.is_blocked() ? Flag::Blocked : Flag())
|
||||||
|
| (!update.is_voice_messages_forbidden()
|
||||||
|
? Flag::CanReceiveVoices
|
||||||
|
: Flag()));
|
||||||
user->setIsBlocked(update.is_blocked());
|
user->setIsBlocked(update.is_blocked());
|
||||||
user->setCallsStatus(update.is_phone_calls_private()
|
user->setCallsStatus(update.is_phone_calls_private()
|
||||||
? UserData::CallsStatus::Private
|
? UserData::CallsStatus::Private
|
||||||
|
|
|
@ -52,6 +52,7 @@ enum class UserDataFlag {
|
||||||
Self = (1 << 13),
|
Self = (1 << 13),
|
||||||
Premium = (1 << 14),
|
Premium = (1 << 14),
|
||||||
CanReceiveGifts = (1 << 15),
|
CanReceiveGifts = (1 << 15),
|
||||||
|
CanReceiveVoices = (1 << 16),
|
||||||
};
|
};
|
||||||
inline constexpr bool is_flag_type(UserDataFlag) { return true; };
|
inline constexpr bool is_flag_type(UserDataFlag) { return true; };
|
||||||
using UserDataFlags = base::flags<UserDataFlag>;
|
using UserDataFlags = base::flags<UserDataFlag>;
|
||||||
|
@ -108,6 +109,7 @@ public:
|
||||||
[[nodiscard]] bool canAddContact() const;
|
[[nodiscard]] bool canAddContact() const;
|
||||||
|
|
||||||
[[nodiscard]] bool canReceiveGifts() const;
|
[[nodiscard]] bool canReceiveGifts() const;
|
||||||
|
[[nodiscard]] bool canReceiveVoices() const;
|
||||||
|
|
||||||
// In Data::Session::processUsers() we check only that.
|
// In Data::Session::processUsers() we check only that.
|
||||||
// When actually trying to share contact we perform
|
// When actually trying to share contact we perform
|
||||||
|
|
|
@ -929,7 +929,7 @@ void HistoryWidget::initVoiceRecordBar() {
|
||||||
auto scrollHeight = rpl::combine(
|
auto scrollHeight = rpl::combine(
|
||||||
_scroll->topValue(),
|
_scroll->topValue(),
|
||||||
_scroll->heightValue()
|
_scroll->heightValue()
|
||||||
) | rpl::map([=](int top, int height) {
|
) | rpl::map([](int top, int height) {
|
||||||
return top + height - st::historyRecordLockPosition.y();
|
return top + height - st::historyRecordLockPosition.y();
|
||||||
});
|
});
|
||||||
_voiceRecordBar->setLockBottom(std::move(scrollHeight));
|
_voiceRecordBar->setLockBottom(std::move(scrollHeight));
|
||||||
|
@ -938,9 +938,18 @@ void HistoryWidget::initVoiceRecordBar() {
|
||||||
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
|
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
|
||||||
|
|
||||||
_voiceRecordBar->setStartRecordingFilter([=] {
|
_voiceRecordBar->setStartRecordingFilter([=] {
|
||||||
const auto error = _peer
|
const auto error = [&]() -> std::optional<QString> {
|
||||||
? Data::RestrictionError(_peer, ChatRestriction::SendMedia)
|
if (_peer) {
|
||||||
: std::nullopt;
|
const auto type = ChatRestriction::SendMedia;
|
||||||
|
if (const auto error = Data::RestrictionError(_peer, type)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (const auto error = Data::RestrictionVoicesError(_peer)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}();
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->show(Ui::MakeInformBox(*error));
|
controller()->show(Ui::MakeInformBox(*error));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1962,11 +1962,19 @@ void ComposeControls::initVoiceRecordBar() {
|
||||||
}, _wrap->lifetime());
|
}, _wrap->lifetime());
|
||||||
|
|
||||||
_voiceRecordBar->setStartRecordingFilter([=] {
|
_voiceRecordBar->setStartRecordingFilter([=] {
|
||||||
const auto error = _history
|
const auto error = [&]() -> std::optional<QString> {
|
||||||
? Data::RestrictionError(
|
const auto peer = _history ? _history->peer : nullptr;
|
||||||
_history->peer,
|
if (!peer) {
|
||||||
ChatRestriction::SendMedia)
|
const auto type = ChatRestriction::SendMedia;
|
||||||
: std::nullopt;
|
if (const auto error = Data::RestrictionError(peer, type)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (const auto error = Data::RestrictionVoicesError(peer)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}();
|
||||||
if (error) {
|
if (error) {
|
||||||
_window->show(Ui::MakeInformBox(*error));
|
_window->show(Ui::MakeInformBox(*error));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "data/data_peer_values.h" // Data::AmPremiumValue.
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/core_settings.h"
|
#include "core/core_settings.h"
|
||||||
#include "history/admin_log/history_admin_log_item.h"
|
#include "history/admin_log/history_admin_log_item.h"
|
||||||
|
@ -1007,4 +1008,56 @@ auto ProfilePhotoPrivacyController::exceptionsDescription()
|
||||||
return tr::lng_edit_privacy_profile_photo_exceptions();
|
return tr::lng_edit_privacy_profile_photo_exceptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VoicesPrivacyController::VoicesPrivacyController(
|
||||||
|
not_null<::Main::Session*> session) {
|
||||||
|
Data::AmPremiumValue(
|
||||||
|
session
|
||||||
|
) | rpl::start_with_next([=](bool premium) {
|
||||||
|
if (!premium) {
|
||||||
|
if (const auto box = view()) {
|
||||||
|
box->closeBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, _lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserPrivacy::Key VoicesPrivacyController::key() {
|
||||||
|
return Key::Voices;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<QString> VoicesPrivacyController::title() {
|
||||||
|
return tr::lng_edit_privacy_voices_title();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoicesPrivacyController::hasOption(Option option) {
|
||||||
|
return (option != Option::Nobody);
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<QString> VoicesPrivacyController::optionsTitleKey() {
|
||||||
|
return tr::lng_edit_privacy_voices_header();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<QString> VoicesPrivacyController::exceptionButtonTextKey(
|
||||||
|
Exception exception) {
|
||||||
|
switch (exception) {
|
||||||
|
case Exception::Always: return tr::lng_edit_privacy_voices_always_empty();
|
||||||
|
case Exception::Never: return tr::lng_edit_privacy_voices_never_empty();
|
||||||
|
}
|
||||||
|
Unexpected("Invalid exception value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<QString> VoicesPrivacyController::exceptionBoxTitle(
|
||||||
|
Exception exception) {
|
||||||
|
switch (exception) {
|
||||||
|
case Exception::Always: return tr::lng_edit_privacy_voices_always_title();
|
||||||
|
case Exception::Never: return tr::lng_edit_privacy_voices_never_title();
|
||||||
|
}
|
||||||
|
Unexpected("Invalid exception value.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto VoicesPrivacyController::exceptionsDescription()
|
||||||
|
-> rpl::producer<QString> {
|
||||||
|
return tr::lng_edit_privacy_voices_exceptions();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
|
|
@ -223,4 +223,26 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class VoicesPrivacyController : public EditPrivacyController {
|
||||||
|
public:
|
||||||
|
using Option = EditPrivacyBox::Option;
|
||||||
|
using Exception = EditPrivacyBox::Exception;
|
||||||
|
|
||||||
|
explicit VoicesPrivacyController(not_null<::Main::Session*> session);
|
||||||
|
|
||||||
|
Key key() override;
|
||||||
|
|
||||||
|
rpl::producer<QString> title() override;
|
||||||
|
bool hasOption(Option option) override;
|
||||||
|
rpl::producer<QString> optionsTitleKey() override;
|
||||||
|
rpl::producer<QString> exceptionButtonTextKey(
|
||||||
|
Exception exception) override;
|
||||||
|
rpl::producer<QString> exceptionBoxTitle(Exception exception) override;
|
||||||
|
rpl::producer<QString> exceptionsDescription() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
rpl::lifetime _lifetime;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Settings
|
} // namespace Settings
|
||||||
|
|
|
@ -175,6 +175,11 @@ void SetupPrivacy(
|
||||||
{ &st::settingsIconGroup, kIconDarkBlue },
|
{ &st::settingsIconGroup, kIconDarkBlue },
|
||||||
Key::Invites,
|
Key::Invites,
|
||||||
[] { return std::make_unique<GroupsInvitePrivacyController>(); });
|
[] { return std::make_unique<GroupsInvitePrivacyController>(); });
|
||||||
|
add(
|
||||||
|
tr::lng_settings_voices_privacy(),
|
||||||
|
{ &st::settingsPremiumIconVoice, kIconRed },
|
||||||
|
Key::Voices,
|
||||||
|
[=] { return std::make_unique<VoicesPrivacyController>(session); });
|
||||||
|
|
||||||
session->api().userPrivacy().reload(Api::UserPrivacy::Key::AddedByPhone);
|
session->api().userPrivacy().reload(Api::UserPrivacy::Key::AddedByPhone);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue