mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-11 11:47:09 +02:00
Fix sending invite links to paid.
This commit is contained in:
parent
0ac88c0cb5
commit
a1e555267e
1 changed files with 223 additions and 10 deletions
|
@ -9,10 +9,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "api/api_invite_links.h"
|
||||
#include "api/api_premium.h"
|
||||
#include "boxes/peers/edit_participant_box.h"
|
||||
#include "boxes/peers/edit_peer_type_box.h"
|
||||
#include "boxes/peers/replace_boost_box.h"
|
||||
#include "boxes/max_invite_box.h"
|
||||
#include "chat_helpers/message_field.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
|
@ -22,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_changes.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item_helpers.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/boxes/show_or_premium_box.h"
|
||||
|
@ -52,16 +55,39 @@ constexpr auto kUserpicsLimit = 3;
|
|||
|
||||
class ForbiddenRow final : public PeerListRow {
|
||||
public:
|
||||
ForbiddenRow(not_null<PeerData*> peer, bool locked);
|
||||
ForbiddenRow(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<const style::PeerListItem*> lockSt,
|
||||
bool locked);
|
||||
|
||||
PaintRoundImageCallback generatePaintUserpicCallback(
|
||||
bool forceRound) override;
|
||||
|
||||
Api::MessageMoneyRestriction restriction() const;
|
||||
void setRestriction(Api::MessageMoneyRestriction restriction);
|
||||
|
||||
void preloadUserpic() override;
|
||||
void paintUserpicOverlay(
|
||||
Painter &p,
|
||||
const style::PeerListItem &st,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth) override;
|
||||
|
||||
bool refreshLock();
|
||||
|
||||
private:
|
||||
struct Restriction {
|
||||
Api::MessageMoneyRestriction value;
|
||||
RestrictionBadgeCache cache;
|
||||
};
|
||||
|
||||
const bool _locked = false;
|
||||
const not_null<const style::PeerListItem*> _lockSt;
|
||||
QImage _disabledFrame;
|
||||
InMemoryKey _userpicKey;
|
||||
int _paletteVersion = 0;
|
||||
std::shared_ptr<Restriction> _restriction;
|
||||
|
||||
};
|
||||
|
||||
|
@ -81,6 +107,9 @@ public:
|
|||
[[nodiscard]] rpl::producer<int> selectedValue() const {
|
||||
return _selected.value();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<int> starsToSend() const {
|
||||
return _starsToSend.value();
|
||||
}
|
||||
|
||||
void send(
|
||||
std::vector<not_null<PeerData*>> list,
|
||||
|
@ -89,10 +118,16 @@ public:
|
|||
|
||||
private:
|
||||
void appendRow(not_null<UserData*> user);
|
||||
[[nodiscard]] std::unique_ptr<PeerListRow> createRow(
|
||||
[[nodiscard]] std::unique_ptr<ForbiddenRow> createRow(
|
||||
not_null<UserData*> user) const;
|
||||
[[nodiscard]] bool canInvite(not_null<PeerData*> peer) const;
|
||||
|
||||
void send(
|
||||
std::vector<not_null<PeerData*>> list,
|
||||
Ui::ShowPtr show,
|
||||
Fn<void()> close,
|
||||
Api::SendOptions options);
|
||||
|
||||
void setSimpleCover();
|
||||
void setComplexCover();
|
||||
|
||||
|
@ -101,8 +136,11 @@ private:
|
|||
const std::vector<not_null<UserData*>> &_users;
|
||||
const bool _can = false;
|
||||
rpl::variable<int> _selected;
|
||||
rpl::variable<int> _starsToSend;
|
||||
bool _sending = false;
|
||||
|
||||
rpl::lifetime _paymentCheckLifetime;
|
||||
|
||||
};
|
||||
|
||||
base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
|
||||
|
@ -256,11 +294,17 @@ Main::Session &InviteForbiddenController::session() const {
|
|||
return _peer->session();
|
||||
}
|
||||
|
||||
ForbiddenRow::ForbiddenRow(not_null<PeerData*> peer, bool locked)
|
||||
ForbiddenRow::ForbiddenRow(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<const style::PeerListItem*> lockSt,
|
||||
bool locked)
|
||||
: PeerListRow(peer)
|
||||
, _locked(locked) {
|
||||
, _locked(locked)
|
||||
, _lockSt(lockSt) {
|
||||
if (_locked) {
|
||||
setCustomStatus(tr::lng_invite_status_disabled(tr::now));
|
||||
} else {
|
||||
setRestriction(Api::ResolveMessageMoneyRestrictions(peer, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,6 +383,76 @@ PaintRoundImageCallback ForbiddenRow::generatePaintUserpicCallback(
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
Api::MessageMoneyRestriction ForbiddenRow::restriction() const {
|
||||
return _restriction
|
||||
? _restriction->value
|
||||
: Api::MessageMoneyRestriction();
|
||||
}
|
||||
|
||||
void ForbiddenRow::setRestriction(Api::MessageMoneyRestriction restriction) {
|
||||
if (!restriction || !restriction.starsPerMessage) {
|
||||
_restriction = nullptr;
|
||||
return;
|
||||
} else if (!_restriction) {
|
||||
_restriction = std::make_unique<Restriction>();
|
||||
}
|
||||
_restriction->value = restriction;
|
||||
}
|
||||
|
||||
void ForbiddenRow::paintUserpicOverlay(
|
||||
Painter &p,
|
||||
const style::PeerListItem &st,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth) {
|
||||
if (const auto &r = _restriction) {
|
||||
PaintRestrictionBadge(
|
||||
p,
|
||||
_lockSt,
|
||||
r->value.starsPerMessage,
|
||||
r->cache,
|
||||
x,
|
||||
y,
|
||||
outerWidth,
|
||||
st.photoSize);
|
||||
}
|
||||
}
|
||||
|
||||
bool ForbiddenRow::refreshLock() {
|
||||
if (_locked) {
|
||||
return false;
|
||||
} else if (const auto user = peer()->asUser()) {
|
||||
using Restriction = Api::MessageMoneyRestriction;
|
||||
auto r = Api::ResolveMessageMoneyRestrictions(user, nullptr);
|
||||
if (!r || !r.starsPerMessage) {
|
||||
r = Restriction();
|
||||
}
|
||||
if ((_restriction ? _restriction->value : Restriction()) != r) {
|
||||
setRestriction(r);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ForbiddenRow::preloadUserpic() {
|
||||
PeerListRow::preloadUserpic();
|
||||
|
||||
const auto peer = this->peer();
|
||||
const auto known = Api::ResolveMessageMoneyRestrictions(
|
||||
peer,
|
||||
nullptr).known;
|
||||
if (known) {
|
||||
return;
|
||||
} else if (const auto user = peer->asUser()) {
|
||||
const auto api = &user->session().api();
|
||||
api->premium().resolveMessageMoneyRestrictions(user);
|
||||
} else if (const auto group = peer->asChannel()) {
|
||||
group->updateFull();
|
||||
}
|
||||
}
|
||||
|
||||
void InviteForbiddenController::setSimpleCover() {
|
||||
delegate()->peerListSetTitle(
|
||||
_can ? tr::lng_profile_add_via_link() : tr::lng_via_link_cant());
|
||||
|
@ -435,6 +549,30 @@ void InviteForbiddenController::setComplexCover() {
|
|||
}
|
||||
|
||||
void InviteForbiddenController::prepare() {
|
||||
session().api().premium().someMessageMoneyRestrictionsResolved(
|
||||
) | rpl::start_with_next([=] {
|
||||
auto stars = 0;
|
||||
const auto process = [&](not_null<PeerListRow*> raw) {
|
||||
const auto row = static_cast<ForbiddenRow*>(raw.get());
|
||||
if (row->refreshLock()) {
|
||||
delegate()->peerListUpdateRow(raw);
|
||||
}
|
||||
if (const auto r = row->restriction()) {
|
||||
stars += r.starsPerMessage;
|
||||
}
|
||||
};
|
||||
auto count = delegate()->peerListFullRowsCount();
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
process(delegate()->peerListRowAt(i));
|
||||
}
|
||||
_starsToSend = stars;
|
||||
|
||||
count = delegate()->peerListSearchRowsCount();
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
process(delegate()->peerListSearchRowAt(i));
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
if (session().premium()
|
||||
|| (_forbidden.premiumAllowsInvite.empty()
|
||||
&& _forbidden.premiumAllowsWrite.empty())) {
|
||||
|
@ -464,6 +602,11 @@ void InviteForbiddenController::rowClicked(not_null<PeerListRow*> row) {
|
|||
const auto checked = row->checked();
|
||||
delegate()->peerListSetRowChecked(row, !checked);
|
||||
_selected = _selected.current() + (checked ? -1 : 1);
|
||||
const auto r = static_cast<ForbiddenRow*>(row.get())->restriction();
|
||||
if (r.starsPerMessage) {
|
||||
_starsToSend = _starsToSend.current()
|
||||
+ (checked ? -r.starsPerMessage : r.starsPerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void InviteForbiddenController::appendRow(not_null<UserData*> user) {
|
||||
|
@ -473,6 +616,9 @@ void InviteForbiddenController::appendRow(not_null<UserData*> user) {
|
|||
delegate()->peerListAppendRow(std::move(row));
|
||||
if (canInvite(user)) {
|
||||
delegate()->peerListSetRowChecked(raw, true);
|
||||
if (const auto r = raw->restriction()) {
|
||||
_starsToSend = _starsToSend.current() + r.starsPerMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +627,64 @@ void InviteForbiddenController::send(
|
|||
std::vector<not_null<PeerData*>> list,
|
||||
Ui::ShowPtr show,
|
||||
Fn<void()> close) {
|
||||
if (_sending || list.empty()) {
|
||||
send(list, show, close, {});
|
||||
}
|
||||
|
||||
void InviteForbiddenController::send(
|
||||
std::vector<not_null<PeerData*>> list,
|
||||
Ui::ShowPtr show,
|
||||
Fn<void()> close,
|
||||
Api::SendOptions options) {
|
||||
if (list.empty()) {
|
||||
return;
|
||||
}
|
||||
_paymentCheckLifetime.destroy();
|
||||
|
||||
const auto withPaymentApproved = [=](int approved) {
|
||||
auto copy = options;
|
||||
copy.starsApproved = approved;
|
||||
send(list, show, close, copy);
|
||||
};
|
||||
const auto messagesCount = 1;
|
||||
const auto alreadyApproved = options.starsApproved;
|
||||
auto paid = std::vector<not_null<PeerData*>>();
|
||||
auto waiting = base::flat_set<not_null<PeerData*>>();
|
||||
auto totalStars = 0;
|
||||
for (const auto &peer : list) {
|
||||
const auto details = ComputePaymentDetails(peer, messagesCount);
|
||||
if (!details) {
|
||||
waiting.emplace(peer);
|
||||
} else if (details->stars > 0) {
|
||||
totalStars += details->stars;
|
||||
paid.push_back(peer);
|
||||
}
|
||||
}
|
||||
if (!waiting.empty()) {
|
||||
session().changes().peerUpdates(
|
||||
Data::PeerUpdate::Flag::FullInfo
|
||||
) | rpl::start_with_next([=](const Data::PeerUpdate &update) {
|
||||
if (waiting.contains(update.peer)) {
|
||||
withPaymentApproved(alreadyApproved);
|
||||
}
|
||||
}, _paymentCheckLifetime);
|
||||
|
||||
if (!session().credits().loaded()) {
|
||||
session().credits().loadedValue(
|
||||
) | rpl::filter(
|
||||
rpl::mappers::_1
|
||||
) | rpl::take(1) | rpl::start_with_next([=] {
|
||||
withPaymentApproved(alreadyApproved);
|
||||
}, _paymentCheckLifetime);
|
||||
}
|
||||
return;
|
||||
} else if (totalStars > alreadyApproved) {
|
||||
const auto sessionShow = Main::MakeSessionShow(show, &session());
|
||||
ShowSendPaidConfirm(sessionShow, paid, SendPaymentDetails{
|
||||
.messages = messagesCount,
|
||||
.stars = totalStars,
|
||||
}, [=] { withPaymentApproved(totalStars); });
|
||||
return;
|
||||
} else if (_sending) {
|
||||
return;
|
||||
}
|
||||
_sending = true;
|
||||
|
@ -492,12 +695,18 @@ void InviteForbiddenController::send(
|
|||
if (link.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
auto full = options;
|
||||
auto &api = _peer->session().api();
|
||||
auto options = Api::SendOptions();
|
||||
for (const auto &to : list) {
|
||||
auto copy = full;
|
||||
copy.starsApproved = std::min(
|
||||
to->starsPerMessageChecked(),
|
||||
full.starsApproved);
|
||||
full.starsApproved -= copy.starsApproved;
|
||||
|
||||
const auto history = to->owner().history(to);
|
||||
auto message = Api::MessageToSend(
|
||||
Api::SendAction(history, options));
|
||||
Api::SendAction(history, copy));
|
||||
message.textWithTags = { link };
|
||||
message.action.clearDraft = false;
|
||||
api.sendMessage(std::move(message));
|
||||
|
@ -542,10 +751,11 @@ void InviteForbiddenController::send(
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PeerListRow> InviteForbiddenController::createRow(
|
||||
std::unique_ptr<ForbiddenRow> InviteForbiddenController::createRow(
|
||||
not_null<UserData*> user) const {
|
||||
const auto locked = _can && !canInvite(user);
|
||||
return std::make_unique<ForbiddenRow>(user, locked);
|
||||
const auto lockSt = &computeListSt().item;
|
||||
return std::make_unique<ForbiddenRow>(user, lockSt, locked);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -929,12 +1139,15 @@ bool ChatInviteForbidden(
|
|||
) | rpl::start_with_next([=](bool has) {
|
||||
box->clearButtons();
|
||||
if (has) {
|
||||
box->addButton(tr::lng_via_link_send(), [=] {
|
||||
const auto send = box->addButton(tr::lng_via_link_send(), [=] {
|
||||
weak->send(
|
||||
box->collectSelectedRows(),
|
||||
box->uiShow(),
|
||||
crl::guard(box, [=] { box->closeBox(); }));
|
||||
});
|
||||
send->setText(PaidSendButtonText(
|
||||
weak->starsToSend(),
|
||||
tr::lng_via_link_send()));
|
||||
}
|
||||
box->addButton(tr::lng_create_group_skip(), [=] {
|
||||
box->closeBox();
|
||||
|
|
Loading…
Add table
Reference in a new issue