Added initial support of privacy setting for voice messages.

This commit is contained in:
23rd 2022-07-14 22:25:04 +03:00 committed by John Preston
parent b295a9eeb1
commit 67195f3825
12 changed files with 148 additions and 11 deletions

View file

@ -557,6 +557,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_phone_number_privacy" = "Phone number";
"lng_settings_forwards_privacy" = "Forwarded messages";
"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_passcode_disable" = "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_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_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";
@ -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_voices" = "{user} restricted sending of voice messages to them.";
"lng_exceptions_list_title" = "Exceptions";
"lng_removed_list_title" = "Removed users";

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_user.h"
#include "main/main_session.h"
#include "settings/settings_premium.h" // Settings::ShowPremium.
namespace Api {
namespace {
@ -186,6 +187,8 @@ MTPInputPrivacyKey KeyToTL(UserPrivacy::Key key) {
return MTP_inputPrivacyKeyForwards();
case Key::ProfilePhoto:
return MTP_inputPrivacyKeyProfilePhoto();
case Key::Voices:
return MTP_inputPrivacyKeyVoiceMessages();
}
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_privacyKeyProfilePhoto:
case mtpc_inputPrivacyKeyProfilePhoto: return Key::ProfilePhoto;
case mtpc_privacyKeyVoiceMessages:
case mtpc_inputPrivacyKeyVoiceMessages: return Key::Voices;
}
return std::nullopt;
}
@ -241,7 +246,11 @@ void UserPrivacy::save(
_privacySaveRequests.remove(keyTypeId);
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);
}).send();

View file

@ -28,6 +28,7 @@ public:
CallsPeer2Peer,
Forwards,
ProfilePhoto,
Voices,
};
enum class Option {
Everyone,

View file

@ -1125,6 +1125,14 @@ std::optional<QString> RestrictionError(
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) {
if (const auto channel = peer->asChannel()) {
if (messageId <= channel->availableMinId()) {

View file

@ -469,6 +469,8 @@ std::optional<QString> RestrictionError(
not_null<PeerData*> peer,
ChatRestriction restriction);
std::optional<QString> RestrictionVoicesError(not_null<PeerData*> peer);
void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId);
[[nodiscard]] FullMsgId ResolveTopPinnedId(
not_null<PeerData*> peer,

View file

@ -257,6 +257,10 @@ bool UserData::canReceiveGifts() const {
return flags() & UserDataFlag::CanReceiveGifts;
}
bool UserData::canReceiveVoices() const {
return flags() & UserDataFlag::CanReceiveVoices;
}
bool UserData::canShareThisContactFast() const {
return !_phone.isEmpty();
}
@ -327,7 +331,10 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
| (update.is_phone_calls_available() ? Flag::HasPhoneCalls : Flag())
| (canReceiveGifts ? Flag::CanReceiveGifts : 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->setCallsStatus(update.is_phone_calls_private()
? UserData::CallsStatus::Private

View file

@ -52,6 +52,7 @@ enum class UserDataFlag {
Self = (1 << 13),
Premium = (1 << 14),
CanReceiveGifts = (1 << 15),
CanReceiveVoices = (1 << 16),
};
inline constexpr bool is_flag_type(UserDataFlag) { return true; };
using UserDataFlags = base::flags<UserDataFlag>;
@ -108,6 +109,7 @@ public:
[[nodiscard]] bool canAddContact() const;
[[nodiscard]] bool canReceiveGifts() const;
[[nodiscard]] bool canReceiveVoices() const;
// In Data::Session::processUsers() we check only that.
// When actually trying to share contact we perform

View file

@ -929,7 +929,7 @@ void HistoryWidget::initVoiceRecordBar() {
auto scrollHeight = rpl::combine(
_scroll->topValue(),
_scroll->heightValue()
) | rpl::map([=](int top, int height) {
) | rpl::map([](int top, int height) {
return top + height - st::historyRecordLockPosition.y();
});
_voiceRecordBar->setLockBottom(std::move(scrollHeight));
@ -938,9 +938,18 @@ void HistoryWidget::initVoiceRecordBar() {
_voiceRecordBar->setSendButtonGeometryValue(_send->geometryValue());
_voiceRecordBar->setStartRecordingFilter([=] {
const auto error = _peer
? Data::RestrictionError(_peer, ChatRestriction::SendMedia)
: std::nullopt;
const auto error = [&]() -> std::optional<QString> {
if (_peer) {
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) {
controller()->show(Ui::MakeInformBox(*error));
return true;

View file

@ -1962,11 +1962,19 @@ void ComposeControls::initVoiceRecordBar() {
}, _wrap->lifetime());
_voiceRecordBar->setStartRecordingFilter([=] {
const auto error = _history
? Data::RestrictionError(
_history->peer,
ChatRestriction::SendMedia)
: std::nullopt;
const auto error = [&]() -> std::optional<QString> {
const auto peer = _history ? _history->peer : nullptr;
if (!peer) {
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) {
_window->show(Ui::MakeInformBox(*error));
return true;

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_session.h"
#include "data/data_changes.h"
#include "data/data_peer_values.h" // Data::AmPremiumValue.
#include "core/application.h"
#include "core/core_settings.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();
}
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

View file

@ -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

View file

@ -175,6 +175,11 @@ void SetupPrivacy(
{ &st::settingsIconGroup, kIconDarkBlue },
Key::Invites,
[] { 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);