mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-07-25 23:13:11 +02:00
Support RemoveFee/ChargeFee in monoforums.
This commit is contained in:
parent
d05155a403
commit
35b129287b
14 changed files with 202 additions and 61 deletions
BIN
Telegram/Resources/icons/menu/cancel_fee.png
Normal file
BIN
Telegram/Resources/icons/menu/cancel_fee.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 865 B |
BIN
Telegram/Resources/icons/menu/cancel_fee@2x.png
Normal file
BIN
Telegram/Resources/icons/menu/cancel_fee@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
Telegram/Resources/icons/menu/cancel_fee@3x.png
Normal file
BIN
Telegram/Resources/icons/menu/cancel_fee@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
|
@ -4315,6 +4315,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_context_edit_shortcut" = "Edit Shortcut";
|
||||
"lng_context_delete_shortcut" = "Delete Quick Reply";
|
||||
"lng_context_gift_send" = "Send Another Gift";
|
||||
"lng_context_charge_fee" = "Charge Fee";
|
||||
"lng_context_remove_fee" = "Remove Fee";
|
||||
"lng_context_fee_now" = "{name} pays {amount} per message.";
|
||||
"lng_context_fee_free" = "{name} can send messages for free.";
|
||||
|
||||
"lng_add_tag_about" = "Tag this message with an emoji for quick search.";
|
||||
"lng_subscribe_tag_about" = "Organize your Saved Messages with tags. {link}";
|
||||
|
@ -5317,6 +5321,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_payment_bar_button" = "Remove Fee";
|
||||
"lng_payment_refund_title" = "Remove Fee";
|
||||
"lng_payment_refund_text" = "Are you sure you want to allow {name} to message you for free?";
|
||||
"lng_payment_refund_channel" = "Do you want to allow {name} to message the channel for free?";
|
||||
"lng_payment_refund_also#one" = "Refund already paid {count} Star";
|
||||
"lng_payment_refund_also#other" = "Refund already paid {count} Stars";
|
||||
"lng_payment_refund_confirm" = "Confirm";
|
||||
|
|
|
@ -731,6 +731,24 @@ void SavedSublist::applyMonoforumDialog(
|
|||
unreadReactions().setCount(data.vunread_reactions_count().v);
|
||||
setUnreadMark(data.is_unread_mark());
|
||||
applyMaybeLast(topItem);
|
||||
|
||||
if (data.is_nopaid_messages_exception()) {
|
||||
_flags |= Flag::FeeRemoved;
|
||||
} else {
|
||||
_flags &= ~Flag::FeeRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
bool SavedSublist::isFeeRemoved() const {
|
||||
return (_flags & Flag::FeeRemoved);
|
||||
}
|
||||
|
||||
void SavedSublist::toggleFeeRemoved(bool feeRemoved) {
|
||||
if (feeRemoved) {
|
||||
_flags |= Flag::FeeRemoved;
|
||||
} else {
|
||||
_flags &= ~Flag::FeeRemoved;
|
||||
}
|
||||
}
|
||||
|
||||
TimeId SavedSublist::adjustedChatListTimeId() const {
|
||||
|
|
|
@ -32,6 +32,8 @@ public:
|
|||
~SavedSublist();
|
||||
|
||||
[[nodiscard]] bool inMonoforum() const;
|
||||
[[nodiscard]] bool isFeeRemoved() const;
|
||||
void toggleFeeRemoved(bool feeRemoved);
|
||||
|
||||
void apply(const SublistReadTillUpdate &update);
|
||||
void apply(const MessageUpdate &update);
|
||||
|
@ -125,6 +127,7 @@ private:
|
|||
enum class Flag : uchar {
|
||||
ResolveChatListMessage = (1 << 0),
|
||||
InMonoforum = (1 << 1),
|
||||
FeeRemoved = (1 << 2),
|
||||
};
|
||||
friend inline constexpr bool is_flag_type(Flag) { return true; }
|
||||
using Flags = base::flags<Flag>;
|
||||
|
|
|
@ -1194,6 +1194,7 @@ PaysStatus::PaysStatus(
|
|||
not_null<UserData*> user)
|
||||
: _controller(window)
|
||||
, _user(user)
|
||||
, _paidAlready(std::make_shared<rpl::variable<int>>())
|
||||
, _inner(Ui::CreateChild<Bar>(parent.get(), user))
|
||||
, _bar(parent, object_ptr<Bar>::fromRaw(_inner)) {
|
||||
setupState();
|
||||
|
@ -1220,65 +1221,12 @@ void PaysStatus::setupState() {
|
|||
void PaysStatus::setupHandlers() {
|
||||
_inner->removeClicks(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto user = _user;
|
||||
const auto exception = [=](bool refund) {
|
||||
using Flag = MTPaccount_ToggleNoPaidMessagesException::Flag;
|
||||
const auto api = &user->session().api();
|
||||
const auto require = false;
|
||||
api->request(MTPaccount_ToggleNoPaidMessagesException(
|
||||
MTP_flags((refund ? Flag::f_refund_charged : Flag())
|
||||
| (require ? Flag::f_require_payment : Flag())),
|
||||
MTPInputPeer(), // parent_peer // #TODO monoforum
|
||||
user->inputUser
|
||||
)).done([=] {
|
||||
user->clearPaysPerMessage();
|
||||
}).send();
|
||||
};
|
||||
_controller->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
const auto refund = std::make_shared<QPointer<Ui::Checkbox>>();
|
||||
Ui::ConfirmBox(box, {
|
||||
.text = tr::lng_payment_refund_text(
|
||||
tr::now,
|
||||
lt_name,
|
||||
Ui::Text::Bold(user->shortName()),
|
||||
Ui::Text::WithEntities),
|
||||
.confirmed = [=](Fn<void()> close) {
|
||||
exception(*refund && (*refund)->checked());
|
||||
close();
|
||||
},
|
||||
.confirmText = tr::lng_payment_refund_confirm(tr::now),
|
||||
.title = tr::lng_payment_refund_title(tr::now),
|
||||
});
|
||||
const auto paid = box->lifetime().make_state<
|
||||
rpl::variable<int>
|
||||
>();
|
||||
*paid = _paidAlready.value();
|
||||
paid->value() | rpl::start_with_next([=](int already) {
|
||||
if (!already) {
|
||||
delete base::take(*refund);
|
||||
} else if (!*refund) {
|
||||
const auto skip = st::defaultCheckbox.margin.top();
|
||||
*refund = box->addRow(
|
||||
object_ptr<Ui::Checkbox>(
|
||||
box,
|
||||
tr::lng_payment_refund_also(
|
||||
lt_count,
|
||||
paid->value() | tr::to_count()),
|
||||
false,
|
||||
st::defaultCheckbox),
|
||||
st::boxRowPadding + QMargins(0, skip, 0, skip));
|
||||
}
|
||||
}, box->lifetime());
|
||||
|
||||
user->session().api().request(MTPaccount_GetPaidMessagesRevenue(
|
||||
MTP_flags(0),
|
||||
MTPInputPeer(), // parent_peer // #TODO monoforum
|
||||
user->inputUser
|
||||
)).done(crl::guard(_inner, [=](
|
||||
const MTPaccount_PaidMessagesRevenue &result) {
|
||||
_paidAlready = result.data().vstars_amount().v;
|
||||
})).send();
|
||||
}));
|
||||
Window::PeerMenuConfirmToggleFee(
|
||||
_controller,
|
||||
_paidAlready,
|
||||
_user->session().user(),
|
||||
_user,
|
||||
true);
|
||||
}, _bar.lifetime());
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ private:
|
|||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
const not_null<UserData*> _user;
|
||||
rpl::variable<int> _paidAlready;
|
||||
std::shared_ptr<rpl::variable<int>> _paidAlready;
|
||||
State _state;
|
||||
QPointer<Bar> _inner;
|
||||
SlidingBar _bar;
|
||||
|
|
|
@ -1171,6 +1171,11 @@ void TopBarWidget::updateControlsVisibility() {
|
|||
? (hasPollsMenu || hasTodoListsMenu || hasTopicMenu)
|
||||
: (section == Section::ChatsList)
|
||||
? (_activeChat.key.peer() && _activeChat.key.peer()->isForum())
|
||||
: (section == Section::SavedSublist)
|
||||
? (_activeChat.key.peer()
|
||||
&& _activeChat.key.peer()->isChannel()
|
||||
&& _activeChat.key.peer()->owner().commonStarsPerMessage(
|
||||
_activeChat.key.peer()->asChannel()))
|
||||
: false);
|
||||
const auto hasInfo = !_activeChat.key.folder()
|
||||
&& (section == Section::History
|
||||
|
|
|
@ -56,6 +56,7 @@ menuIconDiscussion: icon {{ "menu/discussion", menuIconColor }};
|
|||
menuIconStats: icon {{ "menu/stats", menuIconColor }};
|
||||
menuIconBoosts: icon {{ "menu/boosts", menuIconColor }};
|
||||
menuIconEarn: icon {{ "menu/earn", menuIconColor }};
|
||||
menuIconCancelFee: icon {{ "menu/cancel_fee", menuIconColor }};
|
||||
menuIconCreatePoll: icon {{ "menu/create_poll", menuIconColor }};
|
||||
menuIconCreateTodoList: icon {{ "menu/select", menuIconColor }};
|
||||
menuIconQrCode: icon {{ "menu/qr_code", menuIconColor }};
|
||||
|
|
|
@ -316,6 +316,14 @@ windowArchiveToast: Toast(defaultToast) {
|
|||
maxWidth: boxWideWidth;
|
||||
}
|
||||
|
||||
windowFeeItem: Menu(defaultMenu) {
|
||||
itemPadding: margins(17px, 3px, 17px, 4px);
|
||||
itemRightSkip: 0px;
|
||||
itemStyle: whenReadStyle;
|
||||
itemFgOver: windowFg;
|
||||
itemFgDisabled: windowFg;
|
||||
}
|
||||
|
||||
ivWidthMin: 380px;
|
||||
ivHeightMin: 480px;
|
||||
ivWidthDefault: 600px;
|
||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "base/random.h"
|
||||
#include "base/options.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "base/unique_qptr.h"
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "boxes/delete_messages_box.h"
|
||||
#include "boxes/max_invite_box.h"
|
||||
|
@ -83,6 +84,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "info/stories/info_stories_widget.h"
|
||||
#include "data/components/scheduled_messages.h"
|
||||
#include "data/notify/data_notify_settings.h"
|
||||
#include "data/stickers/data_custom_emoji.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_folder.h"
|
||||
|
@ -98,10 +100,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_chat_filters.h"
|
||||
#include "dialogs/dialogs_key.h"
|
||||
#include "core/application.h"
|
||||
#include "core/ui_integration.h"
|
||||
#include "export/export_manager.h"
|
||||
#include "boxes/peers/edit_peer_info_box.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "styles/style_chat.h"
|
||||
#include "styles/style_credits.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_window.h" // st::windowMinWidth
|
||||
|
@ -277,6 +281,7 @@ private:
|
|||
void fillArchiveActions();
|
||||
void fillSavedSublistActions();
|
||||
void fillContextMenuActions();
|
||||
void fillMonoforumPeerActions();
|
||||
|
||||
void addHidePromotion();
|
||||
void addTogglePin();
|
||||
|
@ -321,6 +326,7 @@ private:
|
|||
void addVideoChat();
|
||||
void addViewStatistics();
|
||||
void addBoostChat();
|
||||
void addToggleFee();
|
||||
|
||||
[[nodiscard]] bool skipCreateActions() const;
|
||||
|
||||
|
@ -1360,6 +1366,7 @@ void Filler::fill() {
|
|||
case Section::Scheduled: fillScheduledActions(); break;
|
||||
case Section::ContextMenu:
|
||||
case Section::SubsectionTabsMenu: fillContextMenuActions(); break;
|
||||
case Section::SavedSublist: fillMonoforumPeerActions(); break;
|
||||
default: Unexpected("_request.section in Filler::fill.");
|
||||
}
|
||||
}
|
||||
|
@ -1647,6 +1654,68 @@ void Filler::fillSavedSublistActions() {
|
|||
addTogglePin();
|
||||
}
|
||||
|
||||
void Filler::fillMonoforumPeerActions() {
|
||||
Expects(_sublist != nullptr);
|
||||
|
||||
addToggleFee();
|
||||
}
|
||||
|
||||
void Filler::addToggleFee() {
|
||||
const auto feeRemoved = _sublist->isFeeRemoved();
|
||||
const auto text = feeRemoved
|
||||
? tr::lng_context_charge_fee(tr::now)
|
||||
: tr::lng_context_remove_fee(tr::now);
|
||||
const auto navigation = _controller;
|
||||
const auto parent = _sublist->parentChat();
|
||||
const auto user = _sublist->sublistPeer()->asUser();
|
||||
if (!parent || !user) {
|
||||
return;
|
||||
}
|
||||
const auto paidAmount = std::make_shared<rpl::variable<int>>();
|
||||
_addAction(text, [=] {
|
||||
const auto removeFee = !feeRemoved;
|
||||
PeerMenuConfirmToggleFee(
|
||||
navigation,
|
||||
paidAmount,
|
||||
parent,
|
||||
user,
|
||||
removeFee);
|
||||
}, feeRemoved ? &st::menuIconEarn : &st::menuIconCancelFee);
|
||||
_addAction({ .isSeparator = true });
|
||||
_addAction({ .make = [=](not_null<Ui::RpWidget*> actionParent) {
|
||||
const auto text = feeRemoved
|
||||
? tr::lng_context_fee_free(
|
||||
tr::now,
|
||||
lt_name,
|
||||
TextWithEntities{ user->shortName() },
|
||||
Ui::Text::WithEntities)
|
||||
: tr::lng_context_fee_now(
|
||||
tr::now,
|
||||
lt_name,
|
||||
TextWithEntities{ user->shortName() },
|
||||
lt_amount,
|
||||
user->owner().customEmojiManager().ministarEmoji(
|
||||
{ 0, st::giftBoxByStarsStarTop, 0, 0 }
|
||||
).append(Lang::FormatCountDecimal(
|
||||
user->owner().commonStarsPerMessage(parent)
|
||||
)),
|
||||
Ui::Text::WithEntities);
|
||||
const auto action = new QAction(actionParent);
|
||||
action->setDisabled(true);
|
||||
auto result = base::make_unique_q<Ui::Menu::Action>(
|
||||
actionParent,
|
||||
st::windowFeeItem,
|
||||
action,
|
||||
nullptr,
|
||||
nullptr);
|
||||
result->setMarkedText(
|
||||
text,
|
||||
QString(),
|
||||
Core::TextContext({ .session = &user->session() }));
|
||||
return result;
|
||||
} });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void PeerMenuExportChat(
|
||||
|
@ -3726,4 +3795,81 @@ bool CanArchive(History *history, PeerData *peer) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void PeerMenuConfirmToggleFee(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
std::shared_ptr<rpl::variable<int>> paidAmount,
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> user,
|
||||
bool removeFee) {
|
||||
const auto parent = peer->isChannel() ? peer->asChannel() : nullptr;
|
||||
const auto exception = [=](bool refund) {
|
||||
using Flag = MTPaccount_ToggleNoPaidMessagesException::Flag;
|
||||
const auto api = &user->session().api();
|
||||
api->request(MTPaccount_ToggleNoPaidMessagesException(
|
||||
MTP_flags((refund ? Flag::f_refund_charged : Flag())
|
||||
| (removeFee ? Flag() : Flag::f_require_payment)
|
||||
| (parent ? Flag::f_parent_peer : Flag())),
|
||||
parent->input,
|
||||
user->inputUser
|
||||
)).done([=] {
|
||||
if (!parent) {
|
||||
user->clearPaysPerMessage();
|
||||
} else if (const auto monoforum = peer->monoforum()) {
|
||||
if (const auto sublist = monoforum->sublistLoaded(user)) {
|
||||
sublist->toggleFeeRemoved(removeFee);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
if (!removeFee) {
|
||||
exception(false);
|
||||
return;
|
||||
}
|
||||
navigation->uiShow()->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
const auto refund = std::make_shared<QPointer<Ui::Checkbox>>();
|
||||
Ui::ConfirmBox(box, {
|
||||
.text = tr::lng_payment_refund_text(
|
||||
tr::now,
|
||||
lt_name,
|
||||
Ui::Text::Bold(user->shortName()),
|
||||
Ui::Text::WithEntities),
|
||||
.confirmed = [=](Fn<void()> close) {
|
||||
exception(*refund && (*refund)->checked());
|
||||
close();
|
||||
},
|
||||
.confirmText = tr::lng_payment_refund_confirm(tr::now),
|
||||
.title = tr::lng_payment_refund_title(tr::now),
|
||||
});
|
||||
const auto paid = box->lifetime().make_state<
|
||||
rpl::variable<int>
|
||||
>();
|
||||
*paid = paidAmount->value();
|
||||
paid->value() | rpl::start_with_next([=](int already) {
|
||||
if (!already) {
|
||||
delete base::take(*refund);
|
||||
} else if (!*refund) {
|
||||
const auto skip = st::defaultCheckbox.margin.top();
|
||||
*refund = box->addRow(
|
||||
object_ptr<Ui::Checkbox>(
|
||||
box,
|
||||
tr::lng_payment_refund_also(
|
||||
lt_count,
|
||||
paid->value() | tr::to_count()),
|
||||
false,
|
||||
st::defaultCheckbox),
|
||||
st::boxRowPadding + QMargins(0, skip, 0, skip));
|
||||
}
|
||||
}, box->lifetime());
|
||||
|
||||
using Flag = MTPaccount_GetPaidMessagesRevenue::Flag;
|
||||
user->session().api().request(MTPaccount_GetPaidMessagesRevenue(
|
||||
MTP_flags(parent ? Flag::f_parent_peer : Flag()),
|
||||
parent ? parent->input : MTPInputPeer(),
|
||||
user->inputUser
|
||||
)).done([=](const MTPaccount_PaidMessagesRevenue &result) {
|
||||
*paidAmount = result.data().vstars_amount().v;
|
||||
}).send();
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace Window
|
||||
|
|
|
@ -253,4 +253,11 @@ void AddSeparatorAndShiftUp(const PeerMenuCallback &addAction);
|
|||
[[nodiscard]] bool IsArchived(not_null<History*> history);
|
||||
[[nodiscard]] bool CanArchive(History *history, PeerData *peer);
|
||||
|
||||
void PeerMenuConfirmToggleFee(
|
||||
not_null<Window::SessionNavigation*> navigation,
|
||||
std::shared_ptr<rpl::variable<int>> paidAmount,
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> user,
|
||||
bool removeFee);
|
||||
|
||||
} // namespace Window
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 0b7933ad1189076233b69fac0a5a475d2a5deb8b
|
||||
Subproject commit d905dad9c9b0e7e2b6755bb13957f37862888464
|
Loading…
Add table
Reference in a new issue