mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Support "premiums and ..." privacy editing.
This commit is contained in:
parent
1e6fb202f0
commit
5741bd9cca
14 changed files with 328 additions and 55 deletions
|
@ -1107,9 +1107,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_edit_privacy_nobody" = "Nobody";
|
||||
"lng_edit_privacy_premium" = "Premium users";
|
||||
"lng_edit_privacy_exceptions" = "Add exceptions";
|
||||
"lng_edit_privacy_user_types" = "User types";
|
||||
"lng_edit_privacy_users_and_groups" = "Users and groups";
|
||||
"lng_edit_privacy_premium_status" = "all Telegram Premium subscribers";
|
||||
|
||||
"lng_edit_privacy_exceptions_count#one" = "{count} user";
|
||||
"lng_edit_privacy_exceptions_count#other" = "{count} users";
|
||||
"lng_edit_privacy_exceptions_premium_and" = "Premium & {users}";
|
||||
"lng_edit_privacy_exceptions_add" = "Add users or groups";
|
||||
|
||||
"lng_edit_privacy_phone_number_title" = "Phone number privacy";
|
||||
|
|
|
@ -26,7 +26,9 @@ using TLInputRules = MTPVector<MTPInputPrivacyRule>;
|
|||
using TLRules = MTPVector<MTPPrivacyRule>;
|
||||
|
||||
TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
|
||||
const auto collectInputUsers = [](const auto &peers) {
|
||||
using Exceptions = UserPrivacy::Exceptions;
|
||||
const auto collectInputUsers = [](const Exceptions &exceptions) {
|
||||
const auto &peers = exceptions.peers;
|
||||
auto result = QVector<MTPInputUser>();
|
||||
result.reserve(peers.size());
|
||||
for (const auto &peer : peers) {
|
||||
|
@ -36,7 +38,8 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
|
|||
}
|
||||
return result;
|
||||
};
|
||||
const auto collectInputChats = [](const auto &peers) {
|
||||
const auto collectInputChats = [](const Exceptions &exceptions) {
|
||||
const auto &peers = exceptions.peers;
|
||||
auto result = QVector<MTPlong>();
|
||||
result.reserve(peers.size());
|
||||
for (const auto &peer : peers) {
|
||||
|
@ -47,6 +50,7 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
|
|||
return result;
|
||||
};
|
||||
|
||||
using Option = UserPrivacy::Option;
|
||||
auto result = QVector<MTPInputPrivacyRule>();
|
||||
result.reserve(kMaxRules);
|
||||
if (!rule.ignoreAlways) {
|
||||
|
@ -62,6 +66,9 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
|
|||
MTP_inputPrivacyValueAllowChatParticipants(
|
||||
MTP_vector<MTPlong>(chats)));
|
||||
}
|
||||
if (rule.always.premiums && (rule.option != Option::Everyone)) {
|
||||
result.push_back(MTP_inputPrivacyValueAllowPremium());
|
||||
}
|
||||
}
|
||||
if (!rule.ignoreNever) {
|
||||
const auto users = collectInputUsers(rule.never);
|
||||
|
@ -78,14 +85,11 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
|
|||
}
|
||||
}
|
||||
result.push_back([&] {
|
||||
using Option = UserPrivacy::Option;
|
||||
switch (rule.option) {
|
||||
case Option::Everyone: return MTP_inputPrivacyValueAllowAll();
|
||||
case Option::Contacts: return MTP_inputPrivacyValueAllowContacts();
|
||||
case Option::CloseFriends:
|
||||
return MTP_inputPrivacyValueAllowCloseFriends();
|
||||
case Option::ContactsAndPremium:
|
||||
return MTP_inputPrivacyValueAllowPremium();
|
||||
case Option::Nobody: return MTP_inputPrivacyValueDisallowAll();
|
||||
}
|
||||
Unexpected("Option value in Api::UserPrivacy::RulesToTL.");
|
||||
|
@ -102,6 +106,7 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) {
|
|||
using Option = UserPrivacy::Option;
|
||||
auto result = UserPrivacy::Rule();
|
||||
auto optionSet = false;
|
||||
auto allowPremium = false;
|
||||
const auto setOption = [&](Option option) {
|
||||
if (optionSet) {
|
||||
return;
|
||||
|
@ -109,8 +114,8 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) {
|
|||
optionSet = true;
|
||||
result.option = option;
|
||||
};
|
||||
auto &always = result.always;
|
||||
auto &never = result.never;
|
||||
auto &always = result.always.peers;
|
||||
auto &never = result.never.peers;
|
||||
const auto feed = [&](const MTPPrivacyRule &rule) {
|
||||
rule.match([&](const MTPDprivacyValueAllowAll &) {
|
||||
setOption(Option::Everyone);
|
||||
|
@ -119,7 +124,7 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) {
|
|||
}, [&](const MTPDprivacyValueAllowCloseFriends &) {
|
||||
setOption(Option::CloseFriends);
|
||||
}, [&](const MTPDprivacyValueAllowPremium &) {
|
||||
setOption(Option::ContactsAndPremium);
|
||||
result.always.premiums = true;
|
||||
}, [&](const MTPDprivacyValueAllowUsers &data) {
|
||||
const auto &users = data.vusers().v;
|
||||
always.reserve(always.size() + users.size());
|
||||
|
|
|
@ -36,13 +36,16 @@ public:
|
|||
Everyone,
|
||||
Contacts,
|
||||
CloseFriends,
|
||||
ContactsAndPremium,
|
||||
Nobody,
|
||||
};
|
||||
struct Exceptions {
|
||||
std::vector<not_null<PeerData*>> peers;
|
||||
bool premiums = false;
|
||||
};
|
||||
struct Rule {
|
||||
Option option = Option::Everyone;
|
||||
std::vector<not_null<PeerData*>> always;
|
||||
std::vector<not_null<PeerData*>> never;
|
||||
Exceptions always;
|
||||
Exceptions never;
|
||||
bool ignoreAlways = false;
|
||||
bool ignoreNever = false;
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/edit_privacy_box.h"
|
||||
|
||||
#include "api/api_global_privacy.h"
|
||||
#include "boxes/filters/edit_filter_chats_list.h"
|
||||
#include "ui/effects/premium_graphics.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/shadow.h"
|
||||
|
@ -30,12 +32,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
|
||||
namespace {
|
||||
namespace {
|
||||
|
||||
constexpr auto kPremiumsRowId = PeerId(FakeChatId(BareId(1))).value;
|
||||
|
||||
using Exceptions = Api::UserPrivacy::Exceptions;
|
||||
|
||||
void CreateRadiobuttonLock(
|
||||
not_null<Ui::RpWidget*> widget,
|
||||
|
@ -90,37 +96,167 @@ void AddPremiumRequiredRow(
|
|||
}, row->lifetime());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class PrivacyExceptionsBoxController : public ChatsListBoxController {
|
||||
public:
|
||||
PrivacyExceptionsBoxController(
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<QString> title,
|
||||
const std::vector<not_null<PeerData*>> &selected);
|
||||
const Exceptions &selected,
|
||||
bool allowChoosePremiums);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
bool isForeignRow(PeerListRowId itemId) override;
|
||||
bool handleDeselectForeignRow(PeerListRowId itemId) override;
|
||||
|
||||
[[nodiscard]] bool premiumsSelected() const;
|
||||
|
||||
protected:
|
||||
void prepareViewHook() override;
|
||||
std::unique_ptr<Row> createRow(not_null<History*> history) override;
|
||||
|
||||
private:
|
||||
[[nodiscard]] object_ptr<Ui::RpWidget> preparePremiumsRowList();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
rpl::producer<QString> _title;
|
||||
std::vector<not_null<PeerData*>> _selected;
|
||||
Exceptions _selected;
|
||||
bool _allowChoosePremiums = false;
|
||||
|
||||
PeerListContentDelegate *_typesDelegate = nullptr;
|
||||
Fn<void(PeerListRowId)> _deselectOption;
|
||||
|
||||
};
|
||||
|
||||
struct RowSelectionChange {
|
||||
not_null<PeerListRow*> row;
|
||||
bool checked = false;
|
||||
};
|
||||
|
||||
class PremiumsRow final : public PeerListRow {
|
||||
public:
|
||||
PremiumsRow();
|
||||
|
||||
QString generateName() override;
|
||||
QString generateShortName() override;
|
||||
PaintRoundImageCallback generatePaintUserpicCallback(
|
||||
bool forceRound) override;
|
||||
bool useForumLikeUserpic() const override;
|
||||
|
||||
};
|
||||
|
||||
class TypesController final : public PeerListController {
|
||||
public:
|
||||
TypesController(not_null<Main::Session*> session, bool premiums);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void prepare() override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
|
||||
[[nodiscard]] bool premiumsSelected() const;
|
||||
[[nodiscard]] rpl::producer<bool> premiumsChanges() const;
|
||||
[[nodiscard]] auto rowSelectionChanges() const
|
||||
-> rpl::producer<RowSelectionChange>;
|
||||
|
||||
private:
|
||||
[[nodiscard]] std::unique_ptr<PeerListRow> createRow() const;
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
bool _premiums = false;
|
||||
|
||||
rpl::event_stream<> _selectionChanged;
|
||||
rpl::event_stream<RowSelectionChange> _rowSelectionChanges;
|
||||
|
||||
};
|
||||
|
||||
PremiumsRow::PremiumsRow() : PeerListRow(kPremiumsRowId) {
|
||||
setCustomStatus(tr::lng_edit_privacy_premium_status(tr::now));
|
||||
}
|
||||
|
||||
QString PremiumsRow::generateName() {
|
||||
return tr::lng_edit_privacy_premium(tr::now);
|
||||
}
|
||||
|
||||
QString PremiumsRow::generateShortName() {
|
||||
return generateName();
|
||||
}
|
||||
|
||||
PaintRoundImageCallback PremiumsRow::generatePaintUserpicCallback(
|
||||
bool forceRound) {
|
||||
return [=](QPainter &p, int x, int y, int outerWidth, int size) {
|
||||
auto gradient = QLinearGradient(
|
||||
QPointF(x, y),
|
||||
QPointF(x + size, y + size));
|
||||
gradient.setStops(Ui::Premium::ButtonGradientStops());
|
||||
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(gradient);
|
||||
if (forceRound) {
|
||||
p.drawEllipse(x, y, size, size);
|
||||
} else {
|
||||
const auto radius = size * Ui::ForumUserpicRadiusMultiplier();
|
||||
p.drawRoundedRect(x, y, size, size, radius, radius);
|
||||
}
|
||||
st::settingsPrivacyPremium.paintInCenter(p, { x, y, size, size });
|
||||
};
|
||||
}
|
||||
|
||||
bool PremiumsRow::useForumLikeUserpic() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
TypesController::TypesController(
|
||||
not_null<Main::Session*> session,
|
||||
bool premiums)
|
||||
: _session(session)
|
||||
, _premiums(premiums) {
|
||||
}
|
||||
|
||||
Main::Session &TypesController::session() const {
|
||||
return *_session;
|
||||
}
|
||||
|
||||
void TypesController::prepare() {
|
||||
delegate()->peerListAppendRow(std::make_unique<PremiumsRow>());
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
||||
bool TypesController::premiumsSelected() const {
|
||||
const auto row = delegate()->peerListFindRow(kPremiumsRowId);
|
||||
Assert(row != nullptr);
|
||||
|
||||
return row->checked();
|
||||
}
|
||||
|
||||
void TypesController::rowClicked(not_null<PeerListRow*> row) {
|
||||
const auto checked = !row->checked();
|
||||
delegate()->peerListSetRowChecked(row, checked);
|
||||
_rowSelectionChanges.fire({ row, checked });
|
||||
}
|
||||
|
||||
rpl::producer<bool> TypesController::premiumsChanges() const {
|
||||
return _rowSelectionChanges.events(
|
||||
) | rpl::map([=] {
|
||||
return premiumsSelected();
|
||||
});
|
||||
}
|
||||
|
||||
auto TypesController::rowSelectionChanges() const
|
||||
-> rpl::producer<RowSelectionChange> {
|
||||
return _rowSelectionChanges.events();
|
||||
}
|
||||
|
||||
PrivacyExceptionsBoxController::PrivacyExceptionsBoxController(
|
||||
not_null<Main::Session*> session,
|
||||
rpl::producer<QString> title,
|
||||
const std::vector<not_null<PeerData*>> &selected)
|
||||
const Exceptions &selected,
|
||||
bool allowChoosePremiums)
|
||||
: ChatsListBoxController(session)
|
||||
, _session(session)
|
||||
, _title(std::move(title))
|
||||
, _selected(selected) {
|
||||
, _selected(selected)
|
||||
, _allowChoosePremiums(allowChoosePremiums) {
|
||||
}
|
||||
|
||||
Main::Session &PrivacyExceptionsBoxController::session() const {
|
||||
|
@ -129,7 +265,81 @@ Main::Session &PrivacyExceptionsBoxController::session() const {
|
|||
|
||||
void PrivacyExceptionsBoxController::prepareViewHook() {
|
||||
delegate()->peerListSetTitle(std::move(_title));
|
||||
delegate()->peerListAddSelectedPeers(_selected);
|
||||
if (_allowChoosePremiums || _selected.premiums) {
|
||||
delegate()->peerListSetAboveWidget(preparePremiumsRowList());
|
||||
}
|
||||
delegate()->peerListAddSelectedPeers(_selected.peers);
|
||||
}
|
||||
|
||||
bool PrivacyExceptionsBoxController::isForeignRow(PeerListRowId itemId) {
|
||||
return (itemId == kPremiumsRowId);
|
||||
}
|
||||
|
||||
bool PrivacyExceptionsBoxController::handleDeselectForeignRow(
|
||||
PeerListRowId itemId) {
|
||||
if (isForeignRow(itemId)) {
|
||||
_deselectOption(itemId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto PrivacyExceptionsBoxController::preparePremiumsRowList()
|
||||
-> object_ptr<Ui::RpWidget> {
|
||||
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
|
||||
const auto container = result.data();
|
||||
container->add(CreatePeerListSectionSubtitle(
|
||||
container,
|
||||
tr::lng_edit_privacy_user_types()));
|
||||
auto &lifetime = container->lifetime();
|
||||
_typesDelegate = lifetime.make_state<PeerListContentDelegateSimple>();
|
||||
const auto controller = lifetime.make_state<TypesController>(
|
||||
&session(),
|
||||
_selected.premiums);
|
||||
const auto content = result->add(object_ptr<PeerListContent>(
|
||||
container,
|
||||
controller));
|
||||
_typesDelegate->setContent(content);
|
||||
controller->setDelegate(_typesDelegate);
|
||||
|
||||
if (_selected.premiums) {
|
||||
const auto row = _typesDelegate->peerListFindRow(kPremiumsRowId);
|
||||
Assert(row != nullptr);
|
||||
|
||||
content->changeCheckState(row, true, anim::type::instant);
|
||||
this->delegate()->peerListSetForeignRowChecked(
|
||||
row,
|
||||
true,
|
||||
anim::type::instant);
|
||||
}
|
||||
container->add(CreatePeerListSectionSubtitle(
|
||||
container,
|
||||
tr::lng_edit_privacy_users_and_groups()));
|
||||
|
||||
controller->premiumsChanges(
|
||||
) | rpl::start_with_next([=](bool premiums) {
|
||||
_selected.premiums = premiums;
|
||||
}, lifetime);
|
||||
|
||||
controller->rowSelectionChanges(
|
||||
) | rpl::start_with_next([=](RowSelectionChange update) {
|
||||
this->delegate()->peerListSetForeignRowChecked(
|
||||
update.row,
|
||||
update.checked,
|
||||
anim::type::normal);
|
||||
}, lifetime);
|
||||
|
||||
_deselectOption = [=](PeerListRowId itemId) {
|
||||
if (const auto row = _typesDelegate->peerListFindRow(itemId)) {
|
||||
_typesDelegate->peerListSetRowChecked(row, false);
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool PrivacyExceptionsBoxController::premiumsSelected() const {
|
||||
return _selected.premiums;
|
||||
}
|
||||
|
||||
void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
|
@ -145,7 +355,8 @@ void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow*> row) {
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxController::createRow(not_null<History*> history) {
|
||||
auto PrivacyExceptionsBoxController::createRow(not_null<History*> history)
|
||||
-> std::unique_ptr<Row> {
|
||||
if (history->peer->isSelf() || history->peer->isRepliesChat()) {
|
||||
return nullptr;
|
||||
} else if (!history->peer->isUser()
|
||||
|
@ -210,11 +421,13 @@ void EditPrivacyBox::editExceptions(
|
|||
auto controller = std::make_unique<PrivacyExceptionsBoxController>(
|
||||
&_window->session(),
|
||||
_controller->exceptionBoxTitle(exception),
|
||||
exceptions(exception));
|
||||
exceptions(exception),
|
||||
_controller->allowPremiumsToggle(exception));
|
||||
auto initBox = [=, controller = controller.get()](
|
||||
not_null<PeerListBox*> box) {
|
||||
box->addButton(tr::lng_settings_save(), crl::guard(this, [=] {
|
||||
exceptions(exception) = box->collectSelectedRows();
|
||||
exceptions(exception).peers = box->collectSelectedRows();
|
||||
exceptions(exception).premiums = controller->premiumsSelected();
|
||||
const auto type = [&] {
|
||||
switch (exception) {
|
||||
case Exception::Always: return Exception::Never;
|
||||
|
@ -222,8 +435,8 @@ void EditPrivacyBox::editExceptions(
|
|||
}
|
||||
Unexpected("Invalid exception value.");
|
||||
}();
|
||||
auto &removeFrom = exceptions(type);
|
||||
for (const auto peer : exceptions(exception)) {
|
||||
auto &removeFrom = exceptions(type).peers;
|
||||
for (const auto peer : exceptions(exception).peers) {
|
||||
removeFrom.erase(
|
||||
ranges::remove(removeFrom, peer),
|
||||
end(removeFrom));
|
||||
|
@ -237,7 +450,7 @@ void EditPrivacyBox::editExceptions(
|
|||
Box<PeerListBox>(std::move(controller), std::move(initBox)));
|
||||
}
|
||||
|
||||
std::vector<not_null<PeerData*>> &EditPrivacyBox::exceptions(Exception exception) {
|
||||
EditPrivacyBox::Exceptions &EditPrivacyBox::exceptions(Exception exception) {
|
||||
switch (exception) {
|
||||
case Exception::Always: return _value.always;
|
||||
case Exception::Never: return _value.never;
|
||||
|
@ -340,16 +553,28 @@ void EditPrivacyBox::setupContent() {
|
|||
const auto addExceptionLink = [=](Exception exception) {
|
||||
const auto update = Ui::CreateChild<rpl::event_stream<>>(content);
|
||||
auto label = update->events_starting_with({}) | rpl::map([=] {
|
||||
return Settings::ExceptionUsersCount(exceptions(exception));
|
||||
}) | rpl::map([](int count) {
|
||||
return count
|
||||
? tr::lng_edit_privacy_exceptions_count(tr::now, lt_count, count)
|
||||
const auto &value = exceptions(exception);
|
||||
const auto count = Settings::ExceptionUsersCount(value.peers);
|
||||
const auto users = count
|
||||
? tr::lng_edit_privacy_exceptions_count(
|
||||
tr::now,
|
||||
lt_count,
|
||||
count)
|
||||
: tr::lng_edit_privacy_exceptions_add(tr::now);
|
||||
return !value.premiums
|
||||
? users
|
||||
: !count
|
||||
? tr::lng_edit_privacy_premium(tr::now)
|
||||
: tr::lng_edit_privacy_exceptions_premium_and(
|
||||
tr::now,
|
||||
lt_users,
|
||||
users);
|
||||
});
|
||||
_controller->handleExceptionsChange(
|
||||
exception,
|
||||
update->events_starting_with({}) | rpl::map([=] {
|
||||
return Settings::ExceptionUsersCount(exceptions(exception));
|
||||
return Settings::ExceptionUsersCount(
|
||||
exceptions(exception).peers);
|
||||
}));
|
||||
auto text = _controller->exceptionButtonTextKey(exception);
|
||||
const auto button = content->add(
|
||||
|
@ -448,7 +673,7 @@ void EditPrivacyBox::setupContent() {
|
|||
|
||||
addButton(tr::lng_settings_save(), [=] {
|
||||
const auto someAreDisallowed = (_value.option != Option::Everyone)
|
||||
|| !_value.never.empty();
|
||||
|| !_value.never.peers.empty();
|
||||
_controller->confirmSave(someAreDisallowed, crl::guard(this, [=] {
|
||||
_value.ignoreAlways = !showExceptionLink(Exception::Always);
|
||||
_value.ignoreNever = !showExceptionLink(Exception::Never);
|
||||
|
|
|
@ -48,7 +48,8 @@ public:
|
|||
[[nodiscard]] virtual rpl::producer<TextWithEntities> warning() const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual void prepareWarningLabel(not_null<Ui::FlatLabel*> warning) const {
|
||||
virtual void prepareWarningLabel(
|
||||
not_null<Ui::FlatLabel*> warning) const {
|
||||
}
|
||||
[[nodiscard]] virtual rpl::producer<QString> exceptionButtonTextKey(
|
||||
Exception exception) const = 0;
|
||||
|
@ -56,6 +57,10 @@ public:
|
|||
Exception exception) const = 0;
|
||||
[[nodiscard]] virtual auto exceptionsDescription()
|
||||
const -> rpl::producer<QString> = 0;
|
||||
[[nodiscard]] virtual bool allowPremiumsToggle(
|
||||
Exception exception) const {
|
||||
return false;
|
||||
}
|
||||
virtual void handleExceptionsChange(
|
||||
Exception exception,
|
||||
rpl::producer<int> value) {
|
||||
|
@ -117,6 +122,7 @@ class EditPrivacyBox final : public Ui::BoxContent {
|
|||
public:
|
||||
using Value = Api::UserPrivacy::Rule;
|
||||
using Option = Api::UserPrivacy::Option;
|
||||
using Exceptions = Api::UserPrivacy::Exceptions;
|
||||
using Exception = EditPrivacyController::Exception;
|
||||
|
||||
EditPrivacyBox(
|
||||
|
@ -148,7 +154,7 @@ private:
|
|||
int topSkip);
|
||||
|
||||
void editExceptions(Exception exception, Fn<void()> done);
|
||||
std::vector<not_null<PeerData*>> &exceptions(Exception exception);
|
||||
Exceptions &exceptions(Exception exception);
|
||||
|
||||
const not_null<Window::SessionController*> _window;
|
||||
std::unique_ptr<EditPrivacyController> _controller;
|
||||
|
|
|
@ -506,6 +506,22 @@ int PeerListBox::peerListSelectedRowsCount() {
|
|||
return _select ? _select->entity()->getItemsCount() : 0;
|
||||
}
|
||||
|
||||
std::vector<PeerListRowId> PeerListBox::collectSelectedIds() {
|
||||
auto result = std::vector<PeerListRowId>();
|
||||
auto items = _select
|
||||
? _select->entity()->getItems()
|
||||
: QVector<uint64>();
|
||||
if (!items.empty()) {
|
||||
result.reserve(items.size());
|
||||
for (const auto itemId : items) {
|
||||
if (!_controller->isForeignRow(itemId)) {
|
||||
result.push_back(itemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto PeerListBox::collectSelectedRows()
|
||||
-> std::vector<not_null<PeerData*>> {
|
||||
auto result = std::vector<not_null<PeerData*>>();
|
||||
|
@ -887,11 +903,15 @@ void PeerListRow::lazyInitialize(const style::PeerListItem &st) {
|
|||
refreshStatus();
|
||||
}
|
||||
|
||||
bool PeerListRow::useForumLikeUserpic() const {
|
||||
return !special() && peer()->isForum();
|
||||
}
|
||||
|
||||
void PeerListRow::createCheckbox(
|
||||
const style::RoundImageCheckbox &st,
|
||||
Fn<void()> updateCallback) {
|
||||
const auto generateRadius = [=](int size) {
|
||||
return (!special() && peer()->isForum())
|
||||
return useForumLikeUserpic()
|
||||
? int(size * Ui::ForumUserpicRadiusMultiplier())
|
||||
: std::optional<int>();
|
||||
};
|
||||
|
|
|
@ -166,6 +166,8 @@ public:
|
|||
return _name;
|
||||
}
|
||||
|
||||
virtual bool useForumLikeUserpic() const;
|
||||
|
||||
enum class StatusType {
|
||||
Online,
|
||||
LastSeen,
|
||||
|
@ -1042,6 +1044,7 @@ public:
|
|||
std::unique_ptr<PeerListController> controller,
|
||||
Fn<void(not_null<PeerListBox*>)> init);
|
||||
|
||||
[[nodiscard]] std::vector<PeerListRowId> collectSelectedIds();
|
||||
[[nodiscard]] std::vector<not_null<PeerData*>> collectSelectedRows();
|
||||
|
||||
void peerListSetTitle(rpl::producer<QString> title) override {
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
friend inline constexpr auto operator<=>(Birthday, Birthday) = default;
|
||||
friend inline constexpr bool operator==(Birthday, Birthday) = default;
|
||||
|
||||
static constexpr auto kYearMin = 1900;
|
||||
static constexpr auto kYearMin = 1875;
|
||||
static constexpr auto kYearMax = 2100;
|
||||
|
||||
private:
|
||||
|
|
|
@ -161,6 +161,7 @@ settingsPrivacyOption: Checkbox(settingsCheckbox) {
|
|||
settingsPrivacySecurityPadding: 12px;
|
||||
settingsPrivacySkip: 14px;
|
||||
settingsPrivacySkipTop: 4px;
|
||||
settingsPrivacyPremium: icon{{ "profile_premium", premiumButtonFg }};
|
||||
|
||||
settingsPrivacyAddBirthday: FlatLabel(defaultFlatLabel) {
|
||||
minWidth: 256px;
|
||||
|
|
|
@ -392,8 +392,9 @@ void SetupBirthday(
|
|||
key
|
||||
) | rpl::map([=](const Api::UserPrivacy::Rule &value) {
|
||||
return (value.option == Api::UserPrivacy::Option::Contacts)
|
||||
&& value.always.empty()
|
||||
&& value.never.empty();
|
||||
&& value.always.peers.empty()
|
||||
&& !value.always.premiums
|
||||
&& value.never.peers.empty();
|
||||
}) | rpl::distinct_until_changed();
|
||||
|
||||
Ui::AddSkip(container);
|
||||
|
|
|
@ -440,10 +440,7 @@ void SetupPremium(
|
|||
button->addClickHandler([=] {
|
||||
showOther(BusinessId());
|
||||
});
|
||||
constexpr auto kNewExpiresAt = int(1711958400);
|
||||
if (base::unixtime::now() < kNewExpiresAt) {
|
||||
Ui::NewBadge::AddToRight(button);
|
||||
}
|
||||
Ui::NewBadge::AddToRight(button);
|
||||
|
||||
if (controller->session().premiumCanBuy()) {
|
||||
const auto button = AddButtonWithIcon(
|
||||
|
|
|
@ -795,6 +795,11 @@ auto GroupsInvitePrivacyController::exceptionsDescription() const
|
|||
return tr::lng_edit_privacy_groups_exceptions();
|
||||
}
|
||||
|
||||
bool GroupsInvitePrivacyController::allowPremiumsToggle(
|
||||
Exception exception) const {
|
||||
return (exception == Exception::Always);
|
||||
}
|
||||
|
||||
UserPrivacy::Key CallsPrivacyController::key() const {
|
||||
return Key::Calls;
|
||||
}
|
||||
|
|
|
@ -149,6 +149,7 @@ public:
|
|||
rpl::producer<QString> exceptionBoxTitle(
|
||||
Exception exception) const override;
|
||||
rpl::producer<QString> exceptionsDescription() const override;
|
||||
bool allowPremiumsToggle(Exception exception) const override;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -114,31 +114,33 @@ void AddPremiumStar(
|
|||
}, badge->lifetime());
|
||||
}
|
||||
|
||||
QString PrivacyBase(Privacy::Key key, Privacy::Option option) {
|
||||
QString PrivacyBase(Privacy::Key key, const Privacy::Rule &rule) {
|
||||
using Key = Privacy::Key;
|
||||
using Option = Privacy::Option;
|
||||
switch (key) {
|
||||
case Key::CallsPeer2Peer:
|
||||
switch (option) {
|
||||
switch (rule.option) {
|
||||
case Option::Everyone:
|
||||
return tr::lng_edit_privacy_calls_p2p_everyone(tr::now);
|
||||
case Option::Contacts:
|
||||
return tr::lng_edit_privacy_calls_p2p_contacts(tr::now);
|
||||
case Option::CloseFriends:
|
||||
return tr::lng_edit_privacy_close_friends(tr::now); // unused
|
||||
case Option::Nobody:
|
||||
return tr::lng_edit_privacy_calls_p2p_nobody(tr::now);
|
||||
}
|
||||
Unexpected("Value in Privacy::Option.");
|
||||
[[fallthrough]];
|
||||
default:
|
||||
switch (option) {
|
||||
switch (rule.option) {
|
||||
case Option::Everyone: return tr::lng_edit_privacy_everyone(tr::now);
|
||||
case Option::Contacts: return tr::lng_edit_privacy_contacts(tr::now);
|
||||
case Option::Contacts:
|
||||
return rule.always.premiums
|
||||
? tr::lng_edit_privacy_contacts_and_premium(tr::now)
|
||||
: tr::lng_edit_privacy_contacts(tr::now);
|
||||
case Option::CloseFriends:
|
||||
return tr::lng_edit_privacy_close_friends(tr::now);
|
||||
case Option::ContactsAndPremium:
|
||||
return tr::lng_edit_privacy_contacts_and_premium(tr::now);
|
||||
case Option::Nobody: return tr::lng_edit_privacy_nobody(tr::now);
|
||||
case Option::Nobody:
|
||||
return rule.always.premiums
|
||||
? tr::lng_edit_privacy_premium(tr::now)
|
||||
: tr::lng_edit_privacy_nobody(tr::now);
|
||||
}
|
||||
Unexpected("Value in Privacy::Option.");
|
||||
}
|
||||
|
@ -152,17 +154,17 @@ rpl::producer<QString> PrivacyString(
|
|||
key
|
||||
) | rpl::map([=](const Privacy::Rule &value) {
|
||||
auto add = QStringList();
|
||||
if (const auto never = ExceptionUsersCount(value.never)) {
|
||||
if (const auto never = ExceptionUsersCount(value.never.peers)) {
|
||||
add.push_back("-" + QString::number(never));
|
||||
}
|
||||
if (const auto always = ExceptionUsersCount(value.always)) {
|
||||
if (const auto always = ExceptionUsersCount(value.always.peers)) {
|
||||
add.push_back("+" + QString::number(always));
|
||||
}
|
||||
if (!add.isEmpty()) {
|
||||
return PrivacyBase(key, value.option)
|
||||
return PrivacyBase(key, value)
|
||||
+ " (" + add.join(", ") + ")";
|
||||
} else {
|
||||
return PrivacyBase(key, value.option);
|
||||
return PrivacyBase(key, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue