Update API scheme, track stars-per-message.

This commit is contained in:
John Preston 2025-02-18 12:54:24 +04:00
parent 2e45d9fc6b
commit 852ab19760
27 changed files with 256 additions and 190 deletions

View file

@ -377,15 +377,15 @@ const Data::PremiumSubscriptionOptions &Premium::subscriptionOptions() const {
return _subscriptionOptions;
}
rpl::producer<> Premium::somePremiumRequiredResolved() const {
return _somePremiumRequiredResolved.events();
rpl::producer<> Premium::someMessageMoneyRestrictionsResolved() const {
return _someMessageMoneyRestrictionsResolved.events();
}
void Premium::resolvePremiumRequired(not_null<UserData*> user) {
_resolvePremiumRequiredUsers.emplace(user);
if (!_premiumRequiredRequestScheduled
&& _resolvePremiumRequestedUsers.empty()) {
_premiumRequiredRequestScheduled = true;
void Premium::resolveMessageMoneyRestrictions(not_null<UserData*> user) {
_resolveMessageMoneyRequiredUsers.emplace(user);
if (!_messageMoneyRequestScheduled
&& _resolveMessageMoneyRequestedUsers.empty()) {
_messageMoneyRequestScheduled = true;
crl::on_main(_session, [=] {
requestPremiumRequiredSlice();
});
@ -393,50 +393,65 @@ void Premium::resolvePremiumRequired(not_null<UserData*> user) {
}
void Premium::requestPremiumRequiredSlice() {
_premiumRequiredRequestScheduled = false;
if (!_resolvePremiumRequestedUsers.empty()
|| _resolvePremiumRequiredUsers.empty()) {
_messageMoneyRequestScheduled = false;
if (!_resolveMessageMoneyRequestedUsers.empty()
|| _resolveMessageMoneyRequiredUsers.empty()) {
return;
}
constexpr auto kPerRequest = 100;
auto users = MTP_vector_from_range(_resolvePremiumRequiredUsers
auto users = MTP_vector_from_range(_resolveMessageMoneyRequiredUsers
| ranges::views::transform(&UserData::inputUser));
if (users.v.size() > kPerRequest) {
auto shortened = users.v;
shortened.resize(kPerRequest);
users = MTP_vector<MTPInputUser>(std::move(shortened));
const auto from = begin(_resolvePremiumRequiredUsers);
_resolvePremiumRequestedUsers = { from, from + kPerRequest };
_resolvePremiumRequiredUsers.erase(from, from + kPerRequest);
const auto from = begin(_resolveMessageMoneyRequiredUsers);
_resolveMessageMoneyRequestedUsers = { from, from + kPerRequest };
_resolveMessageMoneyRequiredUsers.erase(from, from + kPerRequest);
} else {
_resolvePremiumRequestedUsers
= base::take(_resolvePremiumRequiredUsers);
_resolveMessageMoneyRequestedUsers
= base::take(_resolveMessageMoneyRequiredUsers);
}
const auto finish = [=](const QVector<MTPBool> &list) {
constexpr auto me = UserDataFlag::MeRequiresPremiumToWrite;
constexpr auto known = UserDataFlag::RequirePremiumToWriteKnown;
constexpr auto mask = me | known;
const auto finish = [=](const QVector<MTPRequirementToContact> &list) {
auto index = 0;
for (const auto &user : base::take(_resolvePremiumRequestedUsers)) {
const auto require = (index < list.size())
&& mtpIsTrue(list[index++]);
user->setFlags((user->flags() & ~mask)
| known
| (require ? me : UserDataFlag()));
for (const auto &user : base::take(_resolveMessageMoneyRequestedUsers)) {
const auto set = [&](bool requirePremium, int stars) {
using Flag = UserDataFlag;
constexpr auto me = Flag::RequiresPremiumToWrite;
constexpr auto known = Flag::MessageMoneyRestrictionsKnown;
constexpr auto hasPrem = Flag::HasRequirePremiumToWrite;
constexpr auto hasStars = Flag::HasStarsPerMessage;
user->setStarsPerMessage(stars);
user->setFlags((user->flags() & ~(me | hasPrem | hasStars))
| known
| (requirePremium ? (me | hasPrem) : Flag())
| (stars ? hasStars : Flag()));
};
if (index >= list.size()) {
set(false, 0);
continue;
}
list[index++].match([&](const MTPDrequirementToContactEmpty &) {
set(false, 0);
}, [&](const MTPDrequirementToContactPremium &) {
set(true, 0);
}, [&](const MTPDrequirementToContactPaidMessages &data) {
set(false, data.vstars_amount().v);
});
}
if (!_premiumRequiredRequestScheduled
&& !_resolvePremiumRequiredUsers.empty()) {
_premiumRequiredRequestScheduled = true;
if (!_messageMoneyRequestScheduled
&& !_resolveMessageMoneyRequiredUsers.empty()) {
_messageMoneyRequestScheduled = true;
crl::on_main(_session, [=] {
requestPremiumRequiredSlice();
});
}
_somePremiumRequiredResolved.fire({});
_someMessageMoneyRestrictionsResolved.fire({});
};
_session->api().request(
MTPusers_GetIsPremiumRequiredToContact(std::move(users))
).done([=](const MTPVector<MTPBool> &result) {
MTPusers_GetRequirementsToContact(std::move(users))
).done([=](const MTPVector<MTPRequirementToContact> &result) {
finish(result.v);
}).fail([=] {
finish({});
@ -694,28 +709,32 @@ rpl::producer<rpl::no_value, QString> SponsoredToggle::setToggled(bool v) {
};
}
RequirePremiumState ResolveRequiresPremiumToWrite(
MessageMoneyRestriction ResolveMessageMoneyRestrictions(
not_null<PeerData*> peer,
History *maybeHistory) {
const auto user = peer->asUser();
if (!user
|| !user->someRequirePremiumToWrite()
|| user->session().premium()) {
return RequirePremiumState::No;
} else if (user->requirePremiumToWriteKnown()) {
return user->meRequiresPremiumToWrite()
? RequirePremiumState::Yes
: RequirePremiumState::No;
if (!user) {
return { .known = true };
} else if (user->messageMoneyRestrictionsKnown()) {
return {
.starsPerMessage = user->starsPerMessage(),
.premiumRequired = (user->requiresPremiumToWrite()
&& !user->session().premium()),
.known = true,
};
} else if (user->hasStarsPerMessage()) {
return {};
} else if (!user->hasRequirePremiumToWrite()) {
return { .known = true };
} else if (user->flags() & UserDataFlag::MutualContact) {
return RequirePremiumState::No;
return { .known = true };
} else if (!maybeHistory) {
return RequirePremiumState::Unknown;
return {};
}
const auto update = [&](bool require) {
using Flag = UserDataFlag;
constexpr auto known = Flag::RequirePremiumToWriteKnown;
constexpr auto me = Flag::MeRequiresPremiumToWrite;
constexpr auto known = Flag::MessageMoneyRestrictionsKnown;
constexpr auto me = Flag::RequiresPremiumToWrite;
user->setFlags((user->flags() & ~me)
| known
| (require ? me : Flag()));
@ -727,16 +746,19 @@ RequirePremiumState ResolveRequiresPremiumToWrite(
const auto item = view->data();
if (!item->out() && !item->isService()) {
update(false);
return RequirePremiumState::No;
return { .known = true };
}
}
}
if (user->isContact() // Here we know, that we're not in his contacts.
&& maybeHistory->loadedAtTop() // And no incoming messages.
&& maybeHistory->loadedAtBottom()) {
update(true);
return {
.premiumRequired = !user->session().premium(),
.known = true,
};
}
return RequirePremiumState::Unknown;
return {};
}
rpl::producer<DocumentData*> RandomHelloStickerValue(

View file

@ -116,8 +116,9 @@ public:
[[nodiscard]] auto subscriptionOptions() const
-> const Data::PremiumSubscriptionOptions &;
[[nodiscard]] rpl::producer<> somePremiumRequiredResolved() const;
void resolvePremiumRequired(not_null<UserData*> user);
[[nodiscard]] auto someMessageMoneyRestrictionsResolved() const
-> rpl::producer<>;
void resolveMessageMoneyRestrictions(not_null<UserData*> user);
private:
void reloadPromo();
@ -166,10 +167,10 @@ private:
Data::PremiumSubscriptionOptions _subscriptionOptions;
rpl::event_stream<> _somePremiumRequiredResolved;
base::flat_set<not_null<UserData*>> _resolvePremiumRequiredUsers;
base::flat_set<not_null<UserData*>> _resolvePremiumRequestedUsers;
bool _premiumRequiredRequestScheduled = false;
rpl::event_stream<> _someMessageMoneyRestrictionsResolved;
base::flat_set<not_null<UserData*>> _resolveMessageMoneyRequiredUsers;
base::flat_set<not_null<UserData*>> _resolveMessageMoneyRequestedUsers;
bool _messageMoneyRequestScheduled = false;
};
@ -244,12 +245,12 @@ private:
};
enum class RequirePremiumState {
Unknown,
Yes,
No,
struct MessageMoneyRestriction {
int starsPerMessage = 0;
bool premiumRequired = false;
bool known = false;
};
[[nodiscard]] RequirePremiumState ResolveRequiresPremiumToWrite(
[[nodiscard]] MessageMoneyRestriction ResolveMessageMoneyRestrictions(
not_null<PeerData*> peer,
History *maybeHistory);

View file

@ -283,8 +283,9 @@ RecipientRow::RecipientRow(
, _maybeHistory(maybeHistory)
, _resolvePremiumRequired(maybeLockedSt != nullptr) {
if (maybeLockedSt
&& (Api::ResolveRequiresPremiumToWrite(peer, maybeHistory)
== Api::RequirePremiumState::Yes)) {
&& Api::ResolveMessageMoneyRestrictions(
peer,
maybeHistory).premiumRequired) {
_lockedSt = maybeLockedSt;
}
}
@ -305,8 +306,9 @@ bool RecipientRow::refreshLock(
not_null<const style::PeerListItem*> maybeLockedSt) {
if (const auto user = peer()->asUser()) {
const auto locked = _resolvePremiumRequired
&& (Api::ResolveRequiresPremiumToWrite(user, _maybeHistory)
== Api::RequirePremiumState::Yes);
&& Api::ResolveMessageMoneyRestrictions(
user,
_maybeHistory).premiumRequired;
if (this->locked() != locked) {
setLocked(locked ? maybeLockedSt.get() : nullptr);
return true;
@ -320,20 +322,22 @@ void RecipientRow::preloadUserpic() {
if (!_resolvePremiumRequired) {
return;
} else if (Api::ResolveRequiresPremiumToWrite(peer(), _maybeHistory)
== Api::RequirePremiumState::Unknown) {
} else if (!Api::ResolveMessageMoneyRestrictions(
peer(),
_maybeHistory).known) {
const auto user = peer()->asUser();
user->session().api().premium().resolvePremiumRequired(user);
user->session().api().premium().resolveMessageMoneyRestrictions(
user);
}
}
void TrackPremiumRequiredChanges(
void TrackMessageMoneyRestrictionsChanges(
not_null<PeerListController*> controller,
rpl::lifetime &lifetime) {
const auto session = &controller->session();
rpl::merge(
Data::AmPremiumValue(session) | rpl::to_empty,
session->api().premium().somePremiumRequiredResolved()
session->api().premium().someMessageMoneyRestrictionsResolved()
) | rpl::start_with_next([=] {
const auto st = &controller->computeListSt().item;
const auto delegate = controller->delegate();
@ -726,7 +730,7 @@ std::unique_ptr<PeerListRow> ContactsBoxController::createRow(
return std::make_unique<PeerListRow>(user);
}
RecipientPremiumRequiredError WritePremiumRequiredError(
RecipientMoneyRestrictionError WriteMoneyRestrictionError(
not_null<UserData*> user) {
return {
.text = tr::lng_send_non_premium_message_toast(
@ -759,7 +763,7 @@ ChooseRecipientBoxController::ChooseRecipientBoxController(
, _session(args.session)
, _callback(std::move(args.callback))
, _filter(std::move(args.filter))
, _premiumRequiredError(std::move(args.premiumRequiredError)) {
, _moneyRestrictionError(std::move(args.moneyRestrictionError)) {
}
Main::Session &ChooseRecipientBoxController::session() const {
@ -769,14 +773,17 @@ Main::Session &ChooseRecipientBoxController::session() const {
void ChooseRecipientBoxController::prepareViewHook() {
delegate()->peerListSetTitle(tr::lng_forward_choose());
if (_premiumRequiredError) {
TrackPremiumRequiredChanges(this, lifetime());
if (_moneyRestrictionError) {
TrackMessageMoneyRestrictionsChanges(this, lifetime());
}
}
bool ChooseRecipientBoxController::showLockedError(
not_null<PeerListRow*> row) {
return RecipientRow::ShowLockedError(this, row, _premiumRequiredError);
return RecipientRow::ShowLockedError(
this,
row,
_moneyRestrictionError);
}
void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
@ -836,7 +843,7 @@ void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
bool RecipientRow::ShowLockedError(
not_null<PeerListController*> controller,
not_null<PeerListRow*> row,
Fn<RecipientPremiumRequiredError(not_null<UserData*>)> error) {
Fn<RecipientMoneyRestrictionError(not_null<UserData*>)> error) {
if (!static_cast<RecipientRow*>(row.get())->locked()) {
return false;
}
@ -860,15 +867,15 @@ auto ChooseRecipientBoxController::createRow(
: ((peer->isBroadcast() && !Data::CanSendAnything(peer))
|| peer->isRepliesChat()
|| peer->isVerifyCodes()
|| (peer->isUser() && (_premiumRequiredError
? !peer->asUser()->canSendIgnoreRequirePremium()
|| (peer->isUser() && (_moneyRestrictionError
? !peer->asUser()->canSendIgnoreMoneyRestrictions()
: !Data::CanSendAnything(peer))));
if (skip) {
return nullptr;
}
auto result = std::make_unique<Row>(
history,
_premiumRequiredError ? &computeListSt().item : nullptr);
_moneyRestrictionError ? &computeListSt().item : nullptr);
return result;
}

View file

@ -93,11 +93,11 @@ private:
};
struct RecipientPremiumRequiredError {
struct RecipientMoneyRestrictionError {
TextWithEntities text;
};
[[nodiscard]] RecipientPremiumRequiredError WritePremiumRequiredError(
[[nodiscard]] RecipientMoneyRestrictionError WriteMoneyRestrictionError(
not_null<UserData*> user);
class RecipientRow : public PeerListRow {
@ -112,7 +112,7 @@ public:
[[nodiscard]] static bool ShowLockedError(
not_null<PeerListController*> controller,
not_null<PeerListRow*> row,
Fn<RecipientPremiumRequiredError(not_null<UserData*>)> error);
Fn<RecipientMoneyRestrictionError(not_null<UserData*>)> error);
[[nodiscard]] History *maybeHistory() const {
return _maybeHistory;
@ -135,7 +135,7 @@ private:
};
void TrackPremiumRequiredChanges(
void TrackMessageMoneyRestrictionsChanges(
not_null<PeerListController*> controller,
rpl::lifetime &lifetime);
@ -261,8 +261,8 @@ struct ChooseRecipientArgs {
FnMut<void(not_null<Data::Thread*>)> callback;
Fn<bool(not_null<Data::Thread*>)> filter;
using PremiumRequiredError = RecipientPremiumRequiredError;
Fn<PremiumRequiredError(not_null<UserData*>)> premiumRequiredError;
using MoneyRestrictionError = RecipientMoneyRestrictionError;
Fn<MoneyRestrictionError(not_null<UserData*>)> moneyRestrictionError;
};
class ChooseRecipientBoxController
@ -290,8 +290,8 @@ private:
const not_null<Main::Session*> _session;
FnMut<void(not_null<Data::Thread*>)> _callback;
Fn<bool(not_null<Data::Thread*>)> _filter;
Fn<RecipientPremiumRequiredError(
not_null<UserData*>)> _premiumRequiredError;
Fn<RecipientMoneyRestrictionError(
not_null<UserData*>)> _moneyRestrictionError;
};

View file

@ -584,8 +584,8 @@ void AddParticipantsBoxController::subscribeToMigration() {
}
void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
const auto premiumRequiredError = WritePremiumRequiredError;
if (RecipientRow::ShowLockedError(this, row, premiumRequiredError)) {
const auto moneyRestrictionError = WriteMoneyRestrictionError;
if (RecipientRow::ShowLockedError(this, row, moneyRestrictionError)) {
return;
}
const auto &serverConfig = session().serverConfig();
@ -614,7 +614,7 @@ void AddParticipantsBoxController::itemDeselectedHook(
void AddParticipantsBoxController::prepareViewHook() {
updateTitle();
TrackPremiumRequiredChanges(this, lifetime());
TrackMessageMoneyRestrictionsChanges(this, lifetime());
}
int AddParticipantsBoxController::alreadyInCount() const {

View file

@ -1530,7 +1530,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
};
auto filterCallback = [](not_null<Data::Thread*> thread) {
if (const auto user = thread->peer()->asUser()) {
if (user->canSendIgnoreRequirePremium()) {
if (user->canSendIgnoreMoneyRestrictions()) {
return true;
}
}
@ -1541,7 +1541,7 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
.copyCallback = std::move(copyCallback),
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.premiumRequiredError = SharePremiumRequiredError(),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),
});
*box = Ui::MakeWeak(object.data());
return object;

View file

@ -721,11 +721,11 @@ ShareBox::Inner::Inner(
_rowHeight = st::shareRowHeight;
setAttribute(Qt::WA_OpaquePaintEvent);
if (_descriptor.premiumRequiredError) {
if (_descriptor.moneyRestrictionError) {
const auto session = _descriptor.session;
rpl::merge(
Data::AmPremiumValue(session) | rpl::to_empty,
session->api().premium().somePremiumRequiredResolved()
session->api().premium().someMessageMoneyRestrictionsResolved()
) | rpl::start_with_next([=] {
refreshLockedRows();
}, lifetime());
@ -794,7 +794,7 @@ bool ShareBox::Inner::showLockedError(not_null<Chat*> chat) {
::Settings::ShowPremiumPromoToast(
Main::MakeSessionShow(_show, _descriptor.session),
ChatHelpers::ResolveWindowDefault(),
_descriptor.premiumRequiredError(chat->peer->asUser()).text,
_descriptor.moneyRestrictionError(chat->peer->asUser()).text,
u"require_premium"_q);
return true;
}
@ -803,10 +803,9 @@ void ShareBox::Inner::refreshLockedRows() {
auto changed = false;
for (const auto &[peer, data] : _dataMap) {
const auto history = data->history;
const auto locked = (Api::ResolveRequiresPremiumToWrite(
const auto locked = Api::ResolveMessageMoneyRestrictions(
history->peer,
history
) == Api::RequirePremiumState::Yes);
history).premiumRequired;
if (data->locked != locked) {
data->locked = locked;
changed = true;
@ -814,10 +813,9 @@ void ShareBox::Inner::refreshLockedRows() {
}
for (const auto &data : d_byUsernameFiltered) {
const auto history = data->history;
const auto locked = (Api::ResolveRequiresPremiumToWrite(
const auto locked = Api::ResolveMessageMoneyRestrictions(
history->peer,
history
) == Api::RequirePremiumState::Yes);
history).premiumRequired;
if (data->locked != locked) {
data->locked = locked;
changed = true;
@ -887,12 +885,11 @@ void ShareBox::Inner::updateChatName(not_null<Chat*> chat) {
}
void ShareBox::Inner::initChatLocked(not_null<Chat*> chat) {
if (_descriptor.premiumRequiredError) {
if (_descriptor.moneyRestrictionError) {
const auto history = chat->history;
if (Api::ResolveRequiresPremiumToWrite(
history->peer,
history
) == Api::RequirePremiumState::Yes) {
if (Api::ResolveMessageMoneyRestrictions(
history->peer,
history).premiumRequired) {
chat->locked = true;
}
}
@ -1019,14 +1016,14 @@ void ShareBox::Inner::loadProfilePhotos() {
void ShareBox::Inner::preloadUserpic(not_null<Dialogs::Entry*> entry) {
entry->chatListPreloadData();
const auto history = entry->asHistory();
if (!_descriptor.premiumRequiredError || !history) {
if (!_descriptor.moneyRestrictionError || !history) {
return;
} else if (Api::ResolveRequiresPremiumToWrite(
history->peer,
history
) == Api::RequirePremiumState::Unknown) {
} else if (!Api::ResolveMessageMoneyRestrictions(
history->peer,
history).known) {
const auto user = history->peer->asUser();
_descriptor.session->api().premium().resolvePremiumRequired(user);
_descriptor.session->api().premium().resolveMessageMoneyRestrictions(
user);
}
}
@ -1707,7 +1704,7 @@ void FastShareMessage(
const auto requiresInline = item->requiresSendInlineRight();
auto filterCallback = [=](not_null<Data::Thread*> thread) {
if (const auto user = thread->peer()->asUser()) {
if (user->canSendIgnoreRequirePremium()) {
if (user->canSendIgnoreMoneyRestrictions()) {
return true;
}
}
@ -1733,7 +1730,7 @@ void FastShareMessage(
.captionsCount = ItemsForwardCaptionsCount(items),
.show = !hasOnlyForcedForwardedInfo,
},
.premiumRequiredError = SharePremiumRequiredError(),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),
}), Ui::LayerOption::CloseOther);
}
@ -1806,7 +1803,7 @@ void FastShareLink(
};
auto filterCallback = [](not_null<::Data::Thread*> thread) {
if (const auto user = thread->peer()->asUser()) {
if (user->canSendIgnoreRequirePremium()) {
if (user->canSendIgnoreMoneyRestrictions()) {
return true;
}
}
@ -1819,13 +1816,13 @@ void FastShareLink(
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.st = st,
.premiumRequiredError = SharePremiumRequiredError(),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),
}),
Ui::LayerOption::KeepOther,
anim::type::normal);
}
auto SharePremiumRequiredError()
-> Fn<RecipientPremiumRequiredError(not_null<UserData*>)> {
return WritePremiumRequiredError;
auto ShareMessageMoneyRestrictionError()
-> Fn<RecipientMoneyRestrictionError(not_null<UserData*>)> {
return WriteMoneyRestrictionError;
}

View file

@ -87,9 +87,9 @@ void FastShareLink(
const QString &url,
ShareBoxStyleOverrides st = {});
struct RecipientPremiumRequiredError;
[[nodiscard]] auto SharePremiumRequiredError()
-> Fn<RecipientPremiumRequiredError(not_null<UserData*>)>;
struct RecipientMoneyRestrictionError;
[[nodiscard]] auto ShareMessageMoneyRestrictionError()
-> Fn<RecipientMoneyRestrictionError(not_null<UserData*>)>;
class ShareBox final : public Ui::BoxContent {
public:
@ -123,8 +123,9 @@ public:
bool show = false;
} forwardOptions;
using PremiumRequiredError = RecipientPremiumRequiredError;
Fn<PremiumRequiredError(not_null<UserData*>)> premiumRequiredError;
using MoneyRestrictionError = RecipientMoneyRestrictionError;
Fn<MoneyRestrictionError(
not_null<UserData*>)> moneyRestrictionError;
};
ShareBox(QWidget*, Descriptor &&descriptor);

View file

@ -178,7 +178,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
};
auto filterCallback = [](not_null<Data::Thread*> thread) {
if (const auto user = thread->peer()->asUser()) {
if (user->canSendIgnoreRequirePremium()) {
if (user->canSendIgnoreMoneyRestrictions()) {
return true;
}
}
@ -199,7 +199,7 @@ object_ptr<ShareBox> ShareInviteLinkBox(
tr::lng_group_call_copy_speaker_link(),
tr::lng_group_call_copy_listener_link()),
.st = st.shareBox ? *st.shareBox : ShareBoxStyleOverrides(),
.premiumRequiredError = SharePremiumRequiredError(),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),
});
*box = result.data();
return result;

View file

@ -1272,8 +1272,6 @@ void ApplyChannelUpdate(
} else {
channel->setLinkedChat(nullptr);
}
channel->setStarsPerMessage(
update.vsend_paid_messages_stars().value_or_empty());
if (const auto history = channel->owner().historyLoaded(channel)) {
if (const auto available = update.vavailable_min_id()) {
history->clearUpTill(available->v);

View file

@ -120,7 +120,7 @@ bool CanSendAnyOf(
|| user->isRepliesChat()
|| user->isVerifyCodes()) {
return false;
} else if (user->meRequiresPremiumToWrite()
} else if (user->requiresPremiumToWrite()
&& !user->session().premium()) {
return false;
} else if (rights
@ -177,7 +177,7 @@ SendError RestrictionError(
using Flag = ChatRestriction;
if (const auto restricted = peer->amRestricted(restriction)) {
if (const auto user = peer->asUser()) {
if (user->meRequiresPremiumToWrite()
if (user->requiresPremiumToWrite()
&& !user->session().premium()) {
return SendError({
.text = tr::lng_restricted_send_non_premium(

View file

@ -1331,7 +1331,7 @@ Data::RestrictionCheckResult PeerData::amRestricted(
}
};
if (const auto user = asUser()) {
if (user->meRequiresPremiumToWrite() && !user->session().premium()) {
if (user->requiresPremiumToWrite() && !user->session().premium()) {
return Result::Explicit();
}
return (right == ChatRestriction::SendVoiceMessages

View file

@ -224,11 +224,11 @@ inline auto DefaultRestrictionValue(
| ChatRestriction::SendVideoMessages);
auto allowedAny = PeerFlagsValue(
user,
(UserDataFlag::Deleted | UserDataFlag::MeRequiresPremiumToWrite)
(UserDataFlag::Deleted | UserDataFlag::RequiresPremiumToWrite)
) | rpl::map([=](UserDataFlags flags) {
return (flags & UserDataFlag::Deleted)
? rpl::single(false)
: !(flags & UserDataFlag::MeRequiresPremiumToWrite)
: !(flags & UserDataFlag::RequiresPremiumToWrite)
? rpl::single(true)
: AmPremiumValue(&user->session());
}) | rpl::flatten_latest();

View file

@ -532,14 +532,22 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
| Flag::BotInlineGeo
| Flag::Premium
| Flag::Support
| Flag::SomeRequirePremiumToWrite
| Flag::RequirePremiumToWriteKnown
| Flag::HasRequirePremiumToWrite
| Flag::HasStarsPerMessage
| Flag::MessageMoneyRestrictionsKnown
| (!minimal
? Flag::Contact
| Flag::MutualContact
| Flag::DiscardMinPhoto
| Flag::StoriesHidden
: Flag());
const auto hasRequirePremiumToWrite
= data.is_contact_require_premium();
const auto hasStarsPerMessage
= data.vsend_paid_messages_stars().has_value();
if (!hasStarsPerMessage) {
result->setStarsPerMessage(0);
}
const auto storiesState = minimal
? std::optional<Data::Stories::PeerSourceState>()
: data.is_stories_unavailable()
@ -554,14 +562,25 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
| (data.is_bot_inline_geo() ? Flag::BotInlineGeo : Flag())
| (data.is_premium() ? Flag::Premium : Flag())
| (data.is_support() ? Flag::Support : Flag())
| (data.is_contact_require_premium()
? (Flag::SomeRequirePremiumToWrite
| (result->someRequirePremiumToWrite()
? (result->requirePremiumToWriteKnown()
? Flag::RequirePremiumToWriteKnown
| (hasRequirePremiumToWrite
? (Flag::HasRequirePremiumToWrite
| (result->hasRequirePremiumToWrite()
? (result->messageMoneyRestrictionsKnown()
? Flag::MessageMoneyRestrictionsKnown
: Flag())
: Flag()))
: Flag())
| (hasStarsPerMessage
? (Flag::HasStarsPerMessage
| (result->hasStarsPerMessage()
? (result->messageMoneyRestrictionsKnown()
? Flag::MessageMoneyRestrictionsKnown
: Flag())
: Flag()))
: Flag())
| ((!hasRequirePremiumToWrite && !hasStarsPerMessage)
? Flag::MessageMoneyRestrictionsKnown
: Flag())
| (!minimal
? (data.is_contact() ? Flag::Contact : Flag())
| (data.is_mutual_contact() ? Flag::MutualContact : Flag())
@ -999,6 +1018,8 @@ not_null<PeerData*> Session::processChat(const MTPChat &data) {
}
channel->setPhoto(data.vphoto());
channel->setStarsPerMessage(
data.vsend_paid_messages_stars().value_or_empty());
if (wasInChannel != channel->amIn()) {
flags |= UpdateFlag::ChannelAmIn;
@ -4631,7 +4652,8 @@ void Session::serviceNotification(
MTPPeerColor(), // color
MTPPeerColor(), // profile_color
MTPint(), // bot_active_users
MTPlong())); // bot_verification_icon
MTPlong(), // bot_verification_icon
MTPlong())); // send_paid_messages_stars
}
const auto history = this->history(PeerData::kServiceNotificationsId);
const auto insert = [=] {

View file

@ -513,19 +513,23 @@ bool UserData::hasStoriesHidden() const {
return (flags() & UserDataFlag::StoriesHidden);
}
bool UserData::someRequirePremiumToWrite() const {
return (flags() & UserDataFlag::SomeRequirePremiumToWrite);
bool UserData::hasRequirePremiumToWrite() const {
return (flags() & UserDataFlag::HasRequirePremiumToWrite);
}
bool UserData::meRequiresPremiumToWrite() const {
return !isSelf() && (flags() & UserDataFlag::MeRequiresPremiumToWrite);
bool UserData::hasStarsPerMessage() const {
return (flags() & UserDataFlag::HasStarsPerMessage);
}
bool UserData::requirePremiumToWriteKnown() const {
return (flags() & UserDataFlag::RequirePremiumToWriteKnown);
bool UserData::requiresPremiumToWrite() const {
return !isSelf() && (flags() & UserDataFlag::RequiresPremiumToWrite);
}
bool UserData::canSendIgnoreRequirePremium() const {
bool UserData::messageMoneyRestrictionsKnown() const {
return (flags() & UserDataFlag::MessageMoneyRestrictionsKnown);
}
bool UserData::canSendIgnoreMoneyRestrictions() const {
return !isInaccessible() && !isRepliesChat() && !isVerifyCodes();
}
@ -732,6 +736,8 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
if (const auto pinned = update.vpinned_msg_id()) {
SetTopPinnedMessageId(user, pinned->v);
}
user->setStarsPerMessage(
update.vsend_paid_messages_stars().value_or_empty());
using Flag = UserDataFlag;
const auto mask = Flag::Blocked
| Flag::HasPhoneCalls
@ -739,8 +745,8 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
| Flag::CanPinMessages
| Flag::VoiceMessagesForbidden
| Flag::ReadDatesPrivate
| Flag::RequirePremiumToWriteKnown
| Flag::MeRequiresPremiumToWrite;
| Flag::MessageMoneyRestrictionsKnown
| Flag::RequiresPremiumToWrite;
user->setFlags((user->flags() & ~mask)
| (update.is_phone_calls_private()
? Flag::PhoneCallsPrivate
@ -752,9 +758,9 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
? Flag::VoiceMessagesForbidden
: Flag())
| (update.is_read_dates_private() ? Flag::ReadDatesPrivate : Flag())
| Flag::RequirePremiumToWriteKnown
| Flag::MessageMoneyRestrictionsKnown
| (update.is_contact_require_premium()
? Flag::MeRequiresPremiumToWrite
? Flag::RequiresPremiumToWrite
: Flag()));
user->setIsBlocked(update.is_blocked());
user->setCallsStatus(update.is_phone_calls_private()
@ -770,8 +776,6 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
user->setTranslationDisabled(update.is_translations_disabled());
user->setPrivateForwardName(
update.vprivate_forward_name().value_or_empty());
user->setStarsPerMessage(
update.vsend_paid_messages_stars().value_or_empty());
if (const auto info = user->botInfo.get()) {
const auto group = update.vbot_group_admin_rights()

View file

@ -110,10 +110,11 @@ enum class UserDataFlag : uint32 {
StoriesHidden = (1 << 18),
HasActiveStories = (1 << 19),
HasUnreadStories = (1 << 20),
MeRequiresPremiumToWrite = (1 << 21),
SomeRequirePremiumToWrite = (1 << 22),
RequirePremiumToWriteKnown = (1 << 23),
ReadDatesPrivate = (1 << 24),
RequiresPremiumToWrite = (1 << 21),
HasRequirePremiumToWrite = (1 << 22),
HasStarsPerMessage = (1 << 23),
MessageMoneyRestrictionsKnown = (1 << 24),
ReadDatesPrivate = (1 << 25),
};
inline constexpr bool is_flag_type(UserDataFlag) { return true; };
using UserDataFlags = base::flags<UserDataFlag>;
@ -174,10 +175,11 @@ public:
[[nodiscard]] bool applyMinPhoto() const;
[[nodiscard]] bool hasPersonalPhoto() const;
[[nodiscard]] bool hasStoriesHidden() const;
[[nodiscard]] bool someRequirePremiumToWrite() const;
[[nodiscard]] bool meRequiresPremiumToWrite() const;
[[nodiscard]] bool requirePremiumToWriteKnown() const;
[[nodiscard]] bool canSendIgnoreRequirePremium() const;
[[nodiscard]] bool hasRequirePremiumToWrite() const;
[[nodiscard]] bool hasStarsPerMessage() const;
[[nodiscard]] bool requiresPremiumToWrite() const;
[[nodiscard]] bool messageMoneyRestrictionsKnown() const;
[[nodiscard]] bool canSendIgnoreMoneyRestrictions() const;
[[nodiscard]] bool readDatesPrivate() const;
void setStarsPerMessage(int stars);

View file

@ -4350,15 +4350,14 @@ void HistoryInner::refreshAboutView(bool force) {
if (!info->inited) {
session().api().requestFullPeer(user);
}
} else if (user->meRequiresPremiumToWrite()
&& !user->session().premium()
&& !historyHeight()) {
refresh();
} else if (!historyHeight()) {
if (!user->isFullLoaded()) {
session().api().requestFullPeer(user);
} else {
if (user->starsPerMessage() > 0
|| (user->requiresPremiumToWrite()
&& !user->session().premium())
|| user->isFullLoaded()) {
refresh();
} else {
session().api().requestFullPeer(user);
}
}
}

View file

@ -780,7 +780,7 @@ HistoryWidget::HistoryWidget(
) | rpl::start_with_next([=](UserData::Flags::Change change) {
if (change.diff & UserData::Flag::Premium) {
if (const auto user = _peer ? _peer->asUser() : nullptr) {
if (user->meRequiresPremiumToWrite()) {
if (user->requiresPremiumToWrite()) {
handlePeerUpdate();
}
}

View file

@ -1199,12 +1199,15 @@ struct AuthorSelector {
_peer->owner().history(_peer),
&computeListSt().item));
delegate()->peerListRefreshRows();
TrackPremiumRequiredChanges(this, _lifetime);
TrackMessageMoneyRestrictionsChanges(this, _lifetime);
}
void loadMoreRows() override {
}
void rowClicked(not_null<PeerListRow*> row) override {
if (RecipientRow::ShowLockedError(this, row, WritePremiumRequiredError)) {
if (RecipientRow::ShowLockedError(
this,
row,
WriteMoneyRestrictionError)) {
return;
} else if (const auto onstack = _click) {
onstack();
@ -1298,7 +1301,7 @@ void ShowReplyToChatBox(
.callback = [=](Chosen thread) {
_singleChosen.fire_copy(thread);
},
.premiumRequiredError = WritePremiumRequiredError,
.moneyRestrictionError = WriteMoneyRestrictionError,
}) {
_authorRow = AuthorRowSelector(
session,

View file

@ -259,7 +259,9 @@ bool AboutView::refresh() {
if (user && !user->isSelf() && _history->isDisplayedEmpty()) {
if (_item) {
return false;
} else if (user->meRequiresPremiumToWrite()
//} else if (user->starsPerMessage() > 0) {
// setItem(makeStarsPerMessage(), nullptr);
} else if (user->requiresPremiumToWrite()
&& !user->session().premium()) {
setItem(makePremiumRequired(), nullptr);
} else if (user->isBlocked()) {

View file

@ -61,7 +61,8 @@ PeerId GenerateUser(not_null<History*> history, const QString &name) {
MTPPeerColor(), // color
MTPPeerColor(), // profile_color
MTPint(), // bot_active_users
MTPlong())); // bot_verification_icon
MTPlong(), // bot_verification_icon
MTPlong())); // send_paid_messages_stars
return peerId;
}

View file

@ -174,7 +174,8 @@ void Account::createSession(
MTPPeerColor(), // color
MTPPeerColor(), // profile_color
MTPint(), // bot_active_users
MTPlong()), // bot_verification_icon
MTPlong(), // bot_verification_icon
MTPlong()), // send_paid_messages_stars
serialized,
streamVersion,
std::move(settings));

View file

@ -705,7 +705,7 @@ void ReplyArea::show(
using namespace HistoryView::Controls;
return (can
|| !user
|| !user->meRequiresPremiumToWrite()
|| !user->requiresPremiumToWrite()
|| user->session().premium())
? WriteRestriction()
: WriteRestriction{

View file

@ -66,7 +66,7 @@ namespace Media::Stories {
const auto state = std::make_shared<State>();
auto filterCallback = [=](not_null<Data::Thread*> thread) {
if (const auto user = thread->peer()->asUser()) {
if (user->canSendIgnoreRequirePremium()) {
if (user->canSendIgnoreMoneyRestrictions()) {
return true;
}
}
@ -183,7 +183,7 @@ namespace Media::Stories {
.submitCallback = std::move(submitCallback),
.filterCallback = std::move(filterCallback),
.st = st.shareBox ? *st.shareBox : ShareBoxStyleOverrides(),
.premiumRequiredError = SharePremiumRequiredError(),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),
});
}
@ -232,7 +232,7 @@ object_ptr<Ui::BoxContent> PrepareShareAtTimeBox(
const auto requiresInline = item->requiresSendInlineRight();
auto filterCallback = [=](not_null<Data::Thread*> thread) {
if (const auto user = thread->peer()->asUser()) {
if (user->canSendIgnoreRequirePremium()) {
if (user->canSendIgnoreMoneyRestrictions()) {
return true;
}
}
@ -262,7 +262,7 @@ object_ptr<Ui::BoxContent> PrepareShareAtTimeBox(
.captionsCount = ItemsForwardCaptionsCount({ item }),
.show = !hasOnlyForcedForwardedInfo,
},
.premiumRequiredError = SharePremiumRequiredError(),
.moneyRestrictionError = ShareMessageMoneyRestrictionError(),
});
}

View file

@ -113,7 +113,8 @@ bool TTLValidator::can() const {
&& !_peer->isSelf()
&& !_peer->isNotificationsUser()
&& !_peer->asUser()->isInaccessible()
&& (!_peer->asUser()->meRequiresPremiumToWrite()
&& !_peer->asUser()->starsPerMessage()
&& (!_peer->asUser()->requiresPremiumToWrite()
|| _peer->session().premium()))
|| (_peer->isChat()
&& _peer->asChat()->canEditInformation()

View file

@ -84,7 +84,7 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
userEmpty#d3bc4b7a id:long = User;
user#4b46c37e flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long = User;
user#20b1422 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector<Username> stories_max_id:flags2.5?int color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
@ -99,11 +99,11 @@ userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat;
channel#e00998b7 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long = Chat;
channel#7482147e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector<Username> stories_max_id:flags2.4?int color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
channelFull#67d2e29d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int send_paid_messages_stars:flags2.20?long = ChatFull;
channelFull#52d6806b flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -1942,6 +1942,10 @@ paidReactionPrivacyPeer#dc6cfcf0 peer:InputPeer = PaidReactionPrivacy;
account.paidMessagesRevenue#1e109708 stars_amount:long = account.PaidMessagesRevenue;
requirementToContactEmpty#50a9839 = RequirementToContact;
requirementToContactPremium#e581e4e9 = RequirementToContact;
requirementToContactPaidMessages#b4f67e93 stars_amount:long = RequirementToContact;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -2099,7 +2103,7 @@ account.getPaidMessagesRevenue#f1266f38 user_id:InputUser = account.PaidMessages
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
users.getIsPremiumRequiredToContact#a622aa10 id:Vector<InputUser> = Vector<Bool>;
users.getRequirementsToContact#d89a83a3 id:Vector<InputUser> = Vector<RequirementToContact>;
contacts.getContactIDs#7adc669d hash:long = Vector<int>;
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;

View file

@ -1201,7 +1201,8 @@ void Filler::addThemeEdit() {
if (!user || user->isInaccessible()) {
return;
}
if (user->meRequiresPremiumToWrite() && !user->session().premium()) {
if ((user->requiresPremiumToWrite() && !user->session().premium())
|| user->starsPerMessage() > 0) {
return;
}
const auto controller = _controller;
@ -1709,7 +1710,7 @@ void PeerMenuShareContactBox(
ChooseRecipientArgs{
.session = &navigation->session(),
.callback = std::move(callback),
.premiumRequiredError = WritePremiumRequiredError,
.moneyRestrictionError = WriteMoneyRestrictionError,
}),
[](not_null<PeerListBox*> box) {
box->addButton(tr::lng_cancel(), [=] {
@ -1924,7 +1925,7 @@ object_ptr<Ui::BoxContent> PrepareChooseRecipientBox(
.session = session,
.callback = std::move(callback),
.filter = filter,
.premiumRequiredError = WritePremiumRequiredError,
.moneyRestrictionError = WriteMoneyRestrictionError,
})
, _selectable(selectable) {
}
@ -2145,7 +2146,7 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
.callback = [=](Chosen thread) {
_singleChosen.fire_copy(thread);
},
.premiumRequiredError = WritePremiumRequiredError,
.moneyRestrictionError = WriteMoneyRestrictionError,
}) {
}
@ -2555,7 +2556,7 @@ QPointer<Ui::BoxContent> ShowShareGameBox(
.session = &navigation->session(),
.callback = std::move(chosen),
.filter = std::move(filter),
.premiumRequiredError = WritePremiumRequiredError,
.moneyRestrictionError = WriteMoneyRestrictionError,
}),
std::move(initBox)));
return weak->data();