mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 15:17:07 +02:00
Allow sending paid messages.
This commit is contained in:
parent
45c7829cd8
commit
bbc14ba74f
25 changed files with 497 additions and 143 deletions
Telegram
Resources/langs
SourceFiles
|
@ -2789,6 +2789,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_credits_small_balance_reaction" = "Buy **Stars** and send them to {channel} to support their posts.";
|
||||
"lng_credits_small_balance_subscribe" = "Buy **Stars** and subscribe to **{channel}** and other channels.";
|
||||
"lng_credits_small_balance_star_gift" = "Buy **Stars** to send gifts to {user} and other contacts.";
|
||||
"lng_credits_small_balance_for_message" = "Buy **Stars** to send messages to {user}.";
|
||||
"lng_credits_small_balance_fallback" = "Buy **Stars** to unlock content and services on Telegram.";
|
||||
"lng_credits_purchase_blocked" = "Sorry, you can't purchase this item with Telegram Stars.";
|
||||
"lng_credits_enough" = "You have enough stars at the moment. {link}";
|
||||
|
@ -4821,8 +4822,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_slowmode_seconds#one" = "{count} second";
|
||||
"lng_slowmode_seconds#other" = "{count} seconds";
|
||||
|
||||
"lng_payment_for_message#one" = "Pay {star}{count} for 1 Message";
|
||||
"lng_payment_for_message#other" = "Pay {star}{count} for 1 Message";
|
||||
"lng_payment_for_message" = "Pay {cost} for 1 Message";
|
||||
"lng_payment_confirm_title" = "Confirm payment";
|
||||
"lng_payment_confirm_text#one" = "{name} charges **{count}** Star per message.";
|
||||
"lng_payment_confirm_text#other" = "{name} charges **{count}** Stars per message.";
|
||||
|
@ -4830,8 +4830,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_payment_confirm_sure#other" = "Would you like to pay **{count}** Stars to send one message?";
|
||||
"lng_payment_confirm_dont_ask" = "Don't ask me again";
|
||||
"lng_payment_confirm_button" = "Pay for 1 Message";
|
||||
"lng_payment_bar_text#one" = "{name} must pay {star}{count} for each message to you.";
|
||||
"lng_payment_bar_text#other" = "{name} must pay {star}{count} for each message to you.";
|
||||
"lng_payment_bar_text" = "{name} must pay {cost} for each message to you.";
|
||||
"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?";
|
||||
|
|
|
@ -21,7 +21,6 @@ inline constexpr auto kScheduledUntilOnlineTimestamp = TimeId(0x7FFFFFFE);
|
|||
|
||||
struct SendOptions {
|
||||
uint64 price = 0;
|
||||
int64 paidByStars = 0;
|
||||
PeerData *sendAs = nullptr;
|
||||
TimeId scheduled = 0;
|
||||
BusinessShortcutId shortcutId = 0;
|
||||
|
|
|
@ -59,6 +59,7 @@ void Polls::create(
|
|||
history->startSavingCloudDraft(topicRootId);
|
||||
}
|
||||
const auto silentPost = ShouldSendSilent(peer, action.options);
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
if (silentPost) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ void Polls::create(
|
|||
if (action.options.effectId) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
|
||||
}
|
||||
if (action.options.paidByStars) {
|
||||
if (starsPaid) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
|
||||
}
|
||||
const auto sendAs = action.options.sendAs;
|
||||
|
@ -97,7 +98,7 @@ void Polls::create(
|
|||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
|
||||
MTP_long(action.options.effectId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
if (clearCloudDraft) {
|
||||
history->finishSavingCloudDraft(
|
||||
|
|
|
@ -95,6 +95,7 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
|
|||
const auto messagePostAuthor = peer->isBroadcast()
|
||||
? session->user()->name()
|
||||
: QString();
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
|
||||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
|
@ -111,7 +112,7 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
|
|||
flags |= MessageFlag::InvertMedia;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
||||
}
|
||||
if (action.options.paidByStars) {
|
||||
if (starsPaid) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
|
||||
}
|
||||
|
||||
|
@ -133,7 +134,7 @@ void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
|
|||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(session, action.options.shortcutId),
|
||||
MTP_long(action.options.effectId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
api->sendMessageFail(error, peer, randomId);
|
||||
|
@ -194,6 +195,7 @@ void SendExistingMedia(
|
|||
sendFlags |= MTPmessages_SendMedia::Flag::f_entities;
|
||||
}
|
||||
const auto captionText = caption.text;
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
|
||||
if (action.options.scheduled) {
|
||||
flags |= MessageFlag::IsOrWasScheduled;
|
||||
|
@ -210,7 +212,7 @@ void SendExistingMedia(
|
|||
flags |= MessageFlag::InvertMedia;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
||||
}
|
||||
if (action.options.paidByStars) {
|
||||
if (starsPaid) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
|
||||
}
|
||||
|
||||
|
@ -248,7 +250,7 @@ void SendExistingMedia(
|
|||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(session, action.options.shortcutId),
|
||||
MTP_long(action.options.effectId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
if (error.code() == 400
|
||||
|
@ -388,7 +390,8 @@ bool SendDice(MessageToSend &message) {
|
|||
flags |= MessageFlag::InvertMedia;
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
||||
}
|
||||
if (action.options.paidByStars) {
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
if (starsPaid) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
|
||||
}
|
||||
|
||||
|
@ -423,7 +426,7 @@ bool SendDice(MessageToSend &message) {
|
|||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(session, action.options.shortcutId),
|
||||
MTP_long(action.options.effectId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
}, [=](const MTP::Error &error, const MTP::Response &response) {
|
||||
api->sendMessageFail(error, peer, randomId, newId);
|
||||
|
|
|
@ -3883,7 +3883,8 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
sendFlags |= MTPmessages_SendMessage::Flag::f_effect;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_effect;
|
||||
}
|
||||
if (action.options.paidByStars) {
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
if (starsPaid) {
|
||||
sendFlags |= MTPmessages_SendMessage::Flag::f_allow_paid_stars;
|
||||
mediaFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
|
||||
}
|
||||
|
@ -3943,7 +3944,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
mtpShortcut,
|
||||
MTP_long(action.options.effectId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), done, fail);
|
||||
} else {
|
||||
histories.sendPreparedMessage(
|
||||
|
@ -3962,7 +3963,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
|
|||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
mtpShortcut,
|
||||
MTP_long(action.options.effectId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), done, fail);
|
||||
}
|
||||
isFirst = false;
|
||||
|
@ -4059,7 +4060,8 @@ void ApiWrap::sendInlineResult(
|
|||
if (action.options.hideViaBot) {
|
||||
sendFlags |= SendFlag::f_hide_via;
|
||||
}
|
||||
if (action.options.paidByStars) {
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
if (starsPaid) {
|
||||
sendFlags |= SendFlag::f_allow_paid_stars;
|
||||
}
|
||||
|
||||
|
@ -4100,7 +4102,7 @@ void ApiWrap::sendInlineResult(
|
|||
MTP_int(action.options.scheduled),
|
||||
(sendAs ? sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, action.options.shortcutId),
|
||||
MTP_long(action.options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
history->finishSavingCloudDraft(
|
||||
topicRootId,
|
||||
|
@ -4232,6 +4234,7 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
Fn<void(bool)> done) {
|
||||
const auto history = item->history();
|
||||
const auto replyTo = item->replyTo();
|
||||
const auto peer = history->peer;
|
||||
|
||||
auto caption = item->originalText();
|
||||
TextUtilities::Trim(caption);
|
||||
|
@ -4241,6 +4244,7 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
Api::ConvertOption::SkipLocal);
|
||||
|
||||
const auto updateRecentStickers = Api::HasAttachedStickers(media);
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
|
||||
using Flag = MTPmessages_SendMedia::Flag;
|
||||
const auto flags = Flag(0)
|
||||
|
@ -4254,10 +4258,9 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0))
|
||||
| (options.effectId ? Flag::f_effect : Flag(0))
|
||||
| (options.invertCaption ? Flag::f_invert_media : Flag(0))
|
||||
| (options.paidByStars ? Flag::f_allow_paid_stars : Flag(0));
|
||||
| (starsPaid ? Flag::f_allow_paid_stars : Flag(0));
|
||||
|
||||
auto &histories = history->owner().histories();
|
||||
const auto peer = history->peer;
|
||||
const auto itemId = item->fullId();
|
||||
histories.sendPreparedMessage(
|
||||
history,
|
||||
|
@ -4282,7 +4285,7 @@ void ApiWrap::sendMediaWithRandomId(
|
|||
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, options.shortcutId),
|
||||
MTP_long(options.effectId),
|
||||
MTP_long(options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
if (done) done(true);
|
||||
if (updateRecentStickers) {
|
||||
|
@ -4311,6 +4314,7 @@ void ApiWrap::sendMultiPaidMedia(
|
|||
|
||||
const auto history = item->history();
|
||||
const auto replyTo = item->replyTo();
|
||||
const auto peer = history->peer;
|
||||
|
||||
auto caption = item->originalText();
|
||||
TextUtilities::Trim(caption);
|
||||
|
@ -4318,6 +4322,7 @@ void ApiWrap::sendMultiPaidMedia(
|
|||
_session,
|
||||
caption.entities,
|
||||
Api::ConvertOption::SkipLocal);
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
|
||||
using Flag = MTPmessages_SendMedia::Flag;
|
||||
const auto flags = Flag(0)
|
||||
|
@ -4331,10 +4336,9 @@ void ApiWrap::sendMultiPaidMedia(
|
|||
| (options.shortcutId ? Flag::f_quick_reply_shortcut : Flag(0))
|
||||
| (options.effectId ? Flag::f_effect : Flag(0))
|
||||
| (options.invertCaption ? Flag::f_invert_media : Flag(0))
|
||||
| (options.paidByStars ? Flag::f_allow_paid_stars : Flag(0));
|
||||
| (starsPaid ? Flag::f_allow_paid_stars : Flag(0));
|
||||
|
||||
auto &histories = history->owner().histories();
|
||||
const auto peer = history->peer;
|
||||
const auto itemId = item->fullId();
|
||||
album->sent = true;
|
||||
histories.sendPreparedMessage(
|
||||
|
@ -4358,7 +4362,7 @@ void ApiWrap::sendMultiPaidMedia(
|
|||
(options.sendAs ? options.sendAs->input : MTP_inputPeerEmpty()),
|
||||
Data::ShortcutIdToMTP(_session, options.shortcutId),
|
||||
MTP_long(options.effectId),
|
||||
MTP_long(options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](const MTPUpdates &result, const MTP::Response &response) {
|
||||
if (const auto album = _sendingAlbums.take(groupId)) {
|
||||
const auto copy = (*album)->items;
|
||||
|
|
|
@ -1571,6 +1571,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
|||
: topicRootId;
|
||||
const auto peer = thread->peer();
|
||||
const auto threadHistory = thread->owningHistory();
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
histories.sendRequest(threadHistory, requestType, [=](
|
||||
Fn<void()> finish) {
|
||||
const auto session = &threadHistory->session();
|
||||
|
@ -1583,9 +1584,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
|||
| (options.shortcutId
|
||||
? Flag::f_quick_reply_shortcut
|
||||
: Flag(0))
|
||||
| (options.paidByStars
|
||||
? Flag::f_allow_paid_stars
|
||||
: Flag());
|
||||
| (starsPaid ? Flag::f_allow_paid_stars : Flag());
|
||||
threadHistory->sendRequestId = api.request(
|
||||
MTPmessages_ForwardMessages(
|
||||
MTP_flags(sendFlags),
|
||||
|
@ -1598,7 +1597,7 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
|||
MTP_inputPeerEmpty(), // send_as
|
||||
Data::ShortcutIdToMTP(session, options.shortcutId),
|
||||
MTP_int(videoTimestamp.value_or(0)),
|
||||
MTP_long(options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
)).done([=](const MTPUpdates &updates, mtpRequestId reqId) {
|
||||
threadHistory->session().api().applyUpdates(updates);
|
||||
state->requests.remove(reqId);
|
||||
|
|
|
@ -855,6 +855,10 @@ historyComposeButton: FlatButton {
|
|||
color: historyComposeButtonBgRipple;
|
||||
}
|
||||
}
|
||||
historyComposeButtonText: FlatLabel(defaultFlatLabel) {
|
||||
style: semiboldTextStyle;
|
||||
textFg: windowActiveTextFg;
|
||||
}
|
||||
historyGiftToChannel: IconButton(defaultIconButton) {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
|
|
|
@ -205,13 +205,13 @@ void BotGameUrlClickHandler::onClick(ClickContext context) const {
|
|||
});
|
||||
};
|
||||
if (_bot->isVerified()
|
||||
|| _bot->session().local().isBotTrustedOpenGame(_bot->id)) {
|
||||
|| _bot->session().local().isPeerTrustedOpenGame(_bot->id)) {
|
||||
openGame();
|
||||
} else {
|
||||
if (const auto controller = my.sessionWindow.get()) {
|
||||
const auto callback = [=, bot = _bot](Fn<void()> close) {
|
||||
close();
|
||||
bot->session().local().markBotTrustedOpenGame(bot->id);
|
||||
bot->session().local().markPeerTrustedOpenGame(bot->id);
|
||||
openGame();
|
||||
};
|
||||
controller->show(Ui::MakeConfirmBox({
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_channel.h"
|
||||
|
||||
#include "api/api_global_privacy.h"
|
||||
#include "data/components/credits.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_channel_admins.h"
|
||||
#include "data/data_user.h"
|
||||
|
@ -30,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_chat_invite.h"
|
||||
#include "api/api_invite_links.h"
|
||||
#include "apiwrap.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "ui/unread_badge.h"
|
||||
#include "window/notifications_manager.h"
|
||||
|
||||
|
@ -861,7 +863,7 @@ void ChannelData::growSlowmodeLastMessage(TimeId when) {
|
|||
|
||||
int ChannelData::starsPerMessage() const {
|
||||
if (const auto info = mgInfo.get()) {
|
||||
return info->starsPerMessage;
|
||||
return info->_starsPerMessage;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -870,8 +872,54 @@ void ChannelData::setStarsPerMessage(int stars) {
|
|||
if (!mgInfo || starsPerMessage() == stars) {
|
||||
return;
|
||||
}
|
||||
mgInfo->starsPerMessage = stars;
|
||||
const auto removed = mgInfo->_starsPerMessage && !stars;
|
||||
mgInfo->_starsPerMessage = stars;
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
if (removed) {
|
||||
session().local().clearPeerTrusted(id);
|
||||
}
|
||||
}
|
||||
|
||||
int ChannelData::starsForMessageLocked() const {
|
||||
if (const auto info = mgInfo.get()) {
|
||||
return info->_starsForMessageLocked;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChannelData::lockStarsForMessage() {
|
||||
const auto info = mgInfo.get();
|
||||
if (!info || info->_starsForMessageLocked == info->_starsPerMessage) {
|
||||
return;
|
||||
}
|
||||
cancelStarsForMessage();
|
||||
if (info->_starsPerMessage) {
|
||||
info->_starsForMessageLocked = info->_starsPerMessage;
|
||||
session().credits().lock(StarsAmount(info->_starsPerMessage));
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
int ChannelData::commitStarsForMessage() {
|
||||
const auto info = mgInfo.get();
|
||||
if (!info) {
|
||||
return 0;
|
||||
} else if (const auto stars = base::take(info->_starsForMessageLocked)) {
|
||||
session().credits().withdrawLocked(StarsAmount(stars));
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
return stars;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChannelData::cancelStarsForMessage() {
|
||||
const auto info = mgInfo.get();
|
||||
if (!info) {
|
||||
return;
|
||||
} else if (const auto stars = base::take(info->_starsForMessageLocked)) {
|
||||
session().credits().unlock(StarsAmount(stars));
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
int ChannelData::peerGiftsCount() const {
|
||||
|
|
|
@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_peer_bot_commands.h"
|
||||
#include "data/data_user_names.h"
|
||||
|
||||
class ChannelData;
|
||||
|
||||
struct ChannelLocation {
|
||||
QString address;
|
||||
Data::LocationPoint point;
|
||||
|
@ -145,13 +147,15 @@ public:
|
|||
int slowmodeSeconds = 0;
|
||||
TimeId slowmodeLastMessage = 0;
|
||||
|
||||
int starsPerMessage = 0;
|
||||
|
||||
private:
|
||||
ChatData *_migratedFrom = nullptr;
|
||||
ChannelLocation _location;
|
||||
Data::ChatBotCommands _botCommands;
|
||||
std::unique_ptr<Data::Forum> _forum;
|
||||
int _starsPerMessage = 0;
|
||||
int _starsForMessageLocked = 0;
|
||||
|
||||
friend class ChannelData;
|
||||
|
||||
};
|
||||
|
||||
|
@ -458,8 +462,12 @@ public:
|
|||
[[nodiscard]] TimeId slowmodeLastMessage() const;
|
||||
void growSlowmodeLastMessage(TimeId when);
|
||||
|
||||
[[nodiscard]] int starsPerMessage() const;
|
||||
void setStarsPerMessage(int stars);
|
||||
[[nodiscard]] int starsPerMessage() const;
|
||||
[[nodiscard]] int starsForMessageLocked() const;
|
||||
void lockStarsForMessage();
|
||||
[[nodiscard]] int commitStarsForMessage();
|
||||
void cancelStarsForMessage();
|
||||
|
||||
[[nodiscard]] int peerGiftsCount() const;
|
||||
void setPeerGiftsCount(int count);
|
||||
|
|
|
@ -1450,6 +1450,49 @@ bool PeerData::canManageGroupCall() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
int PeerData::starsPerMessage() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->starsPerMessage();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
return channel->starsPerMessage();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PeerData::starsForMessageLocked() const {
|
||||
if (const auto user = asUser()) {
|
||||
return user->starsForMessageLocked();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
return channel->starsForMessageLocked();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PeerData::lockStarsForMessage() {
|
||||
if (const auto user = asUser()) {
|
||||
user->lockStarsForMessage();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
channel->lockStarsForMessage();
|
||||
}
|
||||
}
|
||||
|
||||
int PeerData::commitStarsForMessage() {
|
||||
if (const auto user = asUser()) {
|
||||
return user->commitStarsForMessage();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
return channel->commitStarsForMessage();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PeerData::cancelStarsForMessage() {
|
||||
if (const auto user = asUser()) {
|
||||
user->cancelStarsForMessage();
|
||||
} else if (const auto channel = asChannel()) {
|
||||
channel->cancelStarsForMessage();
|
||||
}
|
||||
}
|
||||
|
||||
Data::GroupCall *PeerData::groupCall() const {
|
||||
if (const auto chat = asChat()) {
|
||||
return chat->groupCall();
|
||||
|
|
|
@ -268,6 +268,12 @@ public:
|
|||
[[nodiscard]] int slowmodeSecondsLeft() const;
|
||||
[[nodiscard]] bool canManageGroupCall() const;
|
||||
|
||||
[[nodiscard]] int starsPerMessage() const;
|
||||
[[nodiscard]] int starsForMessageLocked() const;
|
||||
void lockStarsForMessage();
|
||||
[[nodiscard]] int commitStarsForMessage();
|
||||
void cancelStarsForMessage();
|
||||
|
||||
[[nodiscard]] UserData *asBot();
|
||||
[[nodiscard]] const UserData *asBot() const;
|
||||
[[nodiscard]] UserData *asUser();
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_sensitive_content.h"
|
||||
#include "api/api_statistics.h"
|
||||
#include "storage/localstorage.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "storage/storage_user_photos.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/business/data_business_common.h"
|
||||
|
@ -538,8 +539,44 @@ int UserData::starsPerMessage() const {
|
|||
|
||||
void UserData::setStarsPerMessage(int stars) {
|
||||
if (_starsPerMessage != stars) {
|
||||
const auto removed = _starsPerMessage && !stars;
|
||||
_starsPerMessage = stars;
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
if (removed) {
|
||||
session().local().clearPeerTrusted(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int UserData::starsForMessageLocked() const {
|
||||
return _starsForMessageLocked;
|
||||
}
|
||||
|
||||
void UserData::lockStarsForMessage() {
|
||||
if (_starsPerMessage == _starsForMessageLocked) {
|
||||
return;
|
||||
}
|
||||
cancelStarsForMessage();
|
||||
if (_starsPerMessage) {
|
||||
_starsForMessageLocked = _starsPerMessage;
|
||||
session().credits().lock(StarsAmount(_starsPerMessage));
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
int UserData::commitStarsForMessage() {
|
||||
if (const auto stars = base::take(_starsForMessageLocked)) {
|
||||
session().credits().withdrawLocked(StarsAmount(stars));
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
return stars;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UserData::cancelStarsForMessage() {
|
||||
if (const auto stars = base::take(_starsForMessageLocked)) {
|
||||
session().credits().unlock(StarsAmount(stars));
|
||||
session().changes().peerUpdated(this, UpdateFlag::StarsPerMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "core/stars_amount.h"
|
||||
#include "data/components/credits.h"
|
||||
#include "data/data_birthday.h"
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_chat_participant_status.h"
|
||||
|
@ -179,8 +180,12 @@ public:
|
|||
[[nodiscard]] bool canSendIgnoreRequirePremium() const;
|
||||
[[nodiscard]] bool readDatesPrivate() const;
|
||||
|
||||
[[nodiscard]] int starsPerMessage() const;
|
||||
void setStarsPerMessage(int stars);
|
||||
[[nodiscard]] int starsPerMessage() const;
|
||||
[[nodiscard]] int starsForMessageLocked() const;
|
||||
void lockStarsForMessage();
|
||||
[[nodiscard]] int commitStarsForMessage();
|
||||
void cancelStarsForMessage();
|
||||
|
||||
[[nodiscard]] bool canShareThisContact() const;
|
||||
[[nodiscard]] bool canAddContact() const;
|
||||
|
@ -272,6 +277,7 @@ private:
|
|||
int _commonChatsCount = 0;
|
||||
int _peerGiftsCount = 0;
|
||||
int _starsPerMessage = 0;
|
||||
int _starsForMessageLocked = 0;
|
||||
ContactStatus _contactStatus = ContactStatus::Unknown;
|
||||
CallsStatus _callsStatus = CallsStatus::Unknown;
|
||||
|
||||
|
|
|
@ -5577,7 +5577,23 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
|
|||
auto preparePaidMessage = [&](
|
||||
const MTPDmessageActionPaidMessage &action) {
|
||||
auto result = PreparedServiceText();
|
||||
result.text.text = u"paid for message"_q; AssertIsDebug();
|
||||
const auto stars = action.vstars().v;
|
||||
if (_from->isSelf()) {
|
||||
result.text = tr::lng_action_paid_message_sent(
|
||||
tr::now,
|
||||
lt_count,
|
||||
stars,
|
||||
Ui::Text::WithEntities);
|
||||
} else {
|
||||
result.links.push_back(_from->createOpenLink());
|
||||
result.text = tr::lng_action_paid_message_got(
|
||||
tr::now,
|
||||
lt_count,
|
||||
stars,
|
||||
lt_name,
|
||||
Ui::Text::Link(_from->shortName(), 1),
|
||||
Ui::Text::WithEntities);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "api/api_unread_things.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "boxes/delete_messages_box.h"
|
||||
#include "boxes/send_credits_box.h"
|
||||
#include "boxes/send_files_box.h"
|
||||
#include "boxes/share_box.h"
|
||||
#include "boxes/edit_caption_box.h"
|
||||
|
@ -129,6 +130,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mtproto/mtproto_config.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "settings/business/settings_quick_replies.h"
|
||||
#include "settings/settings_credits_graphics.h"
|
||||
#include "storage/localimageloader.h"
|
||||
#include "storage/storage_account.h"
|
||||
#include "storage/file_upload.h"
|
||||
|
@ -146,6 +148,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/chat/chat_theme.h"
|
||||
#include "ui/chat/chat_style.h"
|
||||
#include "ui/chat/continuous_scroll.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/elastic_scroll.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/item_text_options.h"
|
||||
|
@ -263,6 +266,7 @@ HistoryWidget::HistoryWidget(
|
|||
tr::lng_channel_mute(tr::now).toUpper(),
|
||||
st::historyComposeButton)
|
||||
, _reportMessages(this, QString(), st::historyComposeButton)
|
||||
, _payForMessage(this, QString(), st::historyComposeButton)
|
||||
, _attachToggle(this, st::historyAttach)
|
||||
, _tabbedSelectorToggle(this, st::historyAttachEmoji)
|
||||
, _botKeyboardShow(this, st::historyBotKeyboardShow)
|
||||
|
@ -380,6 +384,7 @@ HistoryWidget::HistoryWidget(
|
|||
_muteUnmute->addClickHandler([=] { toggleMuteUnmute(); });
|
||||
setupGiftToChannelButton();
|
||||
_reportMessages->addClickHandler([=] { reportSelectedMessages(); });
|
||||
_payForMessage->addClickHandler([=] { payForMessage(); });
|
||||
_field->submits(
|
||||
) | rpl::start_with_next([=](Qt::KeyboardModifiers modifiers) {
|
||||
sendWithModifiers(modifiers);
|
||||
|
@ -520,6 +525,7 @@ HistoryWidget::HistoryWidget(
|
|||
_joinChannel->hide();
|
||||
_muteUnmute->hide();
|
||||
_reportMessages->hide();
|
||||
_payForMessage->hide();
|
||||
|
||||
initVoiceRecordBar();
|
||||
|
||||
|
@ -798,6 +804,7 @@ HistoryWidget::HistoryWidget(
|
|||
| PeerUpdateFlag::MessagesTTL
|
||||
| PeerUpdateFlag::ChatThemeEmoji
|
||||
| PeerUpdateFlag::FullInfo
|
||||
| PeerUpdateFlag::StarsPerMessage
|
||||
) | rpl::filter([=](const Data::PeerUpdate &update) {
|
||||
return (update.peer.get() == _peer);
|
||||
}) | rpl::map([](const Data::PeerUpdate &update) {
|
||||
|
@ -809,7 +816,7 @@ HistoryWidget::HistoryWidget(
|
|||
|
||||
const auto was = (_sendAs != nullptr);
|
||||
refreshSendAsToggle();
|
||||
if (was != (_sendAs != nullptr)) {
|
||||
if (was != (_sendAs != nullptr) || _peer->starsPerMessage()) {
|
||||
updateControlsVisibility();
|
||||
updateControlsGeometry();
|
||||
orderWidgets();
|
||||
|
@ -832,7 +839,8 @@ HistoryWidget::HistoryWidget(
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (flags & PeerUpdateFlag::BotStartToken) {
|
||||
if ((flags & PeerUpdateFlag::BotStartToken)
|
||||
|| (flags & PeerUpdateFlag::StarsPerMessage)) {
|
||||
updateControlsVisibility();
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
@ -1957,6 +1965,7 @@ void HistoryWidget::setInnerFocus() {
|
|||
|| isRecording()
|
||||
|| isJoinChannel()
|
||||
|| isBotStart()
|
||||
|| isPayForMessage()
|
||||
|| isBlocked()
|
||||
|| (!_canSendTexts && !_editMsgId)) {
|
||||
if (_scroll->isHidden()) {
|
||||
|
@ -2379,6 +2388,9 @@ void HistoryWidget::showHistory(
|
|||
|
||||
setHistory(nullptr);
|
||||
_list = nullptr;
|
||||
if (_peer) {
|
||||
_peer->cancelStarsForMessage();
|
||||
}
|
||||
_peer = nullptr;
|
||||
_topicsRequested.clear();
|
||||
_canSendMessages = false;
|
||||
|
@ -3017,16 +3029,14 @@ bool HistoryWidget::contentOverlapped(const QRect &globalRect) {
|
|||
}
|
||||
|
||||
bool HistoryWidget::canWriteMessage() const {
|
||||
if (!_history || !_canSendMessages) {
|
||||
return false;
|
||||
}
|
||||
if (isBlocked() || isJoinChannel() || isMuteUnmute() || isBotStart()) {
|
||||
return false;
|
||||
}
|
||||
if (isSearching()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return _history
|
||||
&& _canSendMessages
|
||||
&& !isBlocked()
|
||||
&& !isJoinChannel()
|
||||
&& !isMuteUnmute()
|
||||
&& !isBotStart()
|
||||
&& !isPayForMessage()
|
||||
&& !isSearching();
|
||||
}
|
||||
|
||||
void HistoryWidget::updateControlsVisibility() {
|
||||
|
@ -3086,6 +3096,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
|| isJoinChannel()
|
||||
|| isMuteUnmute()
|
||||
|| isBotStart()
|
||||
|| isPayForMessage()
|
||||
|| isReportMessages()))) {
|
||||
const auto toggle = [&](Ui::FlatButton *shown) {
|
||||
const auto toggleOne = [&](not_null<Ui::FlatButton*> button) {
|
||||
|
@ -3097,6 +3108,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
}
|
||||
};
|
||||
toggleOne(_reportMessages);
|
||||
toggleOne(_payForMessage);
|
||||
toggleOne(_joinChannel);
|
||||
toggleOne(_muteUnmute);
|
||||
toggleOne(_botStart);
|
||||
|
@ -3110,6 +3122,8 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
toggle(_reportMessages);
|
||||
} else if (isBlocked()) {
|
||||
toggle(_unblock);
|
||||
} else if (isPayForMessage()) {
|
||||
toggle(_payForMessage);
|
||||
} else if (isJoinChannel()) {
|
||||
toggle(_joinChannel);
|
||||
} else if (isMuteUnmute()) {
|
||||
|
@ -3172,6 +3186,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_joinChannel->hide();
|
||||
_muteUnmute->hide();
|
||||
_reportMessages->hide();
|
||||
_payForMessage->hide();
|
||||
_send->show();
|
||||
updateSendButtonType();
|
||||
|
||||
|
@ -3285,6 +3300,7 @@ void HistoryWidget::updateControlsVisibility() {
|
|||
_joinChannel->hide();
|
||||
_muteUnmute->hide();
|
||||
_reportMessages->hide();
|
||||
_payForMessage->hide();
|
||||
_attachToggle->hide();
|
||||
if (_silent) {
|
||||
_silent->hide();
|
||||
|
@ -4525,6 +4541,73 @@ void HistoryWidget::reportSelectedMessages() {
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::payForMessage() {
|
||||
if (!_peer || !session().credits().loaded()) {
|
||||
return;
|
||||
} else if (!_peer->starsPerMessage() || _peer->starsForMessageLocked()) {
|
||||
updateControlsVisibility();
|
||||
} else if (session().local().isPeerTrustedPayForMessage(_peer->id)) {
|
||||
payForMessageSure();
|
||||
} else {
|
||||
const auto peer = _peer;
|
||||
const auto count = peer->starsPerMessage();
|
||||
controller()->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
const auto trust = std::make_shared<QPointer<Ui::Checkbox>>();
|
||||
const auto confirmed = [=](Fn<void()> close) {
|
||||
payForMessageSure((*trust)->checked());
|
||||
close();
|
||||
};
|
||||
Ui::ConfirmBox(box, {
|
||||
.text = tr::lng_payment_confirm_text(
|
||||
tr::now,
|
||||
lt_count,
|
||||
count,
|
||||
lt_name,
|
||||
Ui::Text::Bold(peer->shortName()),
|
||||
Ui::Text::RichLangValue).append(' ').append(
|
||||
tr::lng_payment_confirm_sure(
|
||||
tr::now,
|
||||
lt_count,
|
||||
count,
|
||||
Ui::Text::RichLangValue)),
|
||||
.confirmed = confirmed,
|
||||
.confirmText = tr::lng_payment_confirm_button(),
|
||||
.title = tr::lng_payment_confirm_title(),
|
||||
});
|
||||
const auto skip = st::defaultCheckbox.margin.top();
|
||||
*trust = box->addRow(
|
||||
object_ptr<Ui::Checkbox>(
|
||||
box,
|
||||
tr::lng_payment_confirm_dont_ask(tr::now)),
|
||||
st::boxRowPadding + QMargins(0, skip, 0, skip));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::payForMessageSure(bool trust) {
|
||||
if (trust) {
|
||||
session().local().markPeerTrustedPayForMessage(_peer->id);
|
||||
}
|
||||
const auto required = _peer->starsPerMessage();
|
||||
if (!required) {
|
||||
return;
|
||||
}
|
||||
const auto done = [=](Settings::SmallBalanceResult result) {
|
||||
if (result == Settings::SmallBalanceResult::Success
|
||||
|| result == Settings::SmallBalanceResult::Already) {
|
||||
_peer->lockStarsForMessage();
|
||||
if (canWriteMessage()) {
|
||||
setInnerFocus();
|
||||
}
|
||||
}
|
||||
};
|
||||
Settings::MaybeRequestBalanceIncrease(
|
||||
controller()->uiShow(),
|
||||
required,
|
||||
Settings::SmallBalanceForMessage{ .recipientId = _peer->id },
|
||||
crl::guard(this, done));
|
||||
}
|
||||
|
||||
History *HistoryWidget::history() const {
|
||||
return _history;
|
||||
}
|
||||
|
@ -5071,6 +5154,40 @@ bool HistoryWidget::isSearching() const {
|
|||
return _composeSearch != nullptr;
|
||||
}
|
||||
|
||||
bool HistoryWidget::isPayForMessage() const {
|
||||
const auto stars = _peer ? _peer->starsPerMessage() : 0;
|
||||
const auto locked = _peer ? _peer->starsForMessageLocked() : 0;
|
||||
if (!stars || locked) {
|
||||
return false;
|
||||
} else if (const auto channel = _peer->asChannel()) {
|
||||
if (channel->amCreator() || channel->adminRights()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto creating = !_payForMessageStars.current();
|
||||
_payForMessageStars = stars;
|
||||
if (creating) {
|
||||
session().credits().load();
|
||||
|
||||
auto text = _payForMessageStars.value(
|
||||
) | rpl::map([session = &session()](int stars) {
|
||||
return tr::lng_payment_for_message(
|
||||
tr::now,
|
||||
lt_cost,
|
||||
Ui::CreditsEmojiSmall(session).append(
|
||||
Lang::FormatCountDecimal(stars)),
|
||||
Ui::Text::WithEntities);
|
||||
});
|
||||
Ui::SetButtonMarkedLabel(
|
||||
_payForMessage,
|
||||
std::move(text),
|
||||
&session(),
|
||||
st::historyComposeButtonText);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HistoryWidget::showRecordButton() const {
|
||||
return (_recordAvailability != Webrtc::RecordAvailability::None)
|
||||
&& !_voiceRecordBar->isListenState()
|
||||
|
@ -5128,6 +5245,7 @@ bool HistoryWidget::updateCmdStartShown() {
|
|||
&& _peer->asChannel()->mgInfo->botStatus > 0))) {
|
||||
if (!isBotStart()
|
||||
&& !isBlocked()
|
||||
&& !isPayForMessage()
|
||||
&& !_keyboard->hasMarkup()
|
||||
&& !_keyboard->forceReply()
|
||||
&& !_editMsgId) {
|
||||
|
@ -5541,7 +5659,7 @@ void HistoryWidget::moveFieldControls() {
|
|||
|
||||
// (_botMenu.button) (_attachToggle|_replaceMedia) (_sendAs) ---- _inlineResults ------------------------------ _tabbedPanel ------ _fieldBarCancel
|
||||
// (_attachDocument|_attachPhoto) _field (_ttlInfo) (_scheduled) (_silent|_cmdStart|_kbShow) (_kbHide|_tabbedSelectorToggle) _send
|
||||
// (_botStart|_unblock|_joinChannel|_muteUnmute|_reportMessages)
|
||||
// (_botStart|_unblock|_joinChannel|_muteUnmute|_reportMessages|_payForMessage)
|
||||
|
||||
auto buttonsBottom = bottom - _attachToggle->height();
|
||||
auto left = st::historySendRight;
|
||||
|
@ -5615,6 +5733,7 @@ void HistoryWidget::moveFieldControls() {
|
|||
_joinChannel->setGeometry(fullWidthButtonRect);
|
||||
_muteUnmute->setGeometry(fullWidthButtonRect);
|
||||
_reportMessages->setGeometry(fullWidthButtonRect);
|
||||
_payForMessage->setGeometry(fullWidthButtonRect);
|
||||
if (_sendRestriction) {
|
||||
_sendRestriction->setGeometry(fullWidthButtonRect);
|
||||
}
|
||||
|
@ -6055,18 +6174,25 @@ void HistoryWidget::handleHistoryChange(not_null<const History*> history) {
|
|||
const auto joinChannel = isJoinChannel();
|
||||
const auto muteUnmute = isMuteUnmute();
|
||||
const auto reportMessages = isReportMessages();
|
||||
const auto payForMessage = isPayForMessage();
|
||||
const auto update = false
|
||||
|| (_reportMessages->isHidden() == reportMessages)
|
||||
|| (!reportMessages && _unblock->isHidden() == unblock)
|
||||
|| (!reportMessages
|
||||
&& !unblock
|
||||
&& _payForMessage->isHidden() == payForMessage)
|
||||
|| (!reportMessages
|
||||
&& !unblock
|
||||
&& !payForMessage
|
||||
&& _botStart->isHidden() == botStart)
|
||||
|| (!reportMessages
|
||||
&& !unblock
|
||||
&& !payForMessage
|
||||
&& !botStart
|
||||
&& _joinChannel->isHidden() == joinChannel)
|
||||
|| (!reportMessages
|
||||
&& !unblock
|
||||
&& !payForMessage
|
||||
&& !botStart
|
||||
&& !joinChannel
|
||||
&& _muteUnmute->isHidden() == muteUnmute);
|
||||
|
@ -6430,6 +6556,7 @@ void HistoryWidget::updateHistoryGeometry(
|
|||
} else if (!editingMessage()
|
||||
&& (isSearching()
|
||||
|| isBlocked()
|
||||
|| isPayForMessage()
|
||||
|| isBotStart()
|
||||
|| isJoinChannel()
|
||||
|| isMuteUnmute()
|
||||
|
@ -6739,6 +6866,7 @@ void HistoryWidget::updateBotKeyboard(History *h, bool force) {
|
|||
if (!isSearching()
|
||||
&& !isBotStart()
|
||||
&& !isBlocked()
|
||||
&& !isPayForMessage()
|
||||
&& _canSendMessages
|
||||
&& (wasVisible
|
||||
|| (_replyTo && _replyEditMsg)
|
||||
|
@ -8615,6 +8743,7 @@ void HistoryWidget::updateTopBarSelection() {
|
|||
|| (_list && _list->wasSelectedText())
|
||||
|| isRecording()
|
||||
|| isBotStart()
|
||||
|| isPayForMessage()
|
||||
|| isBlocked()
|
||||
|| (!_canSendTexts && !_editMsgId)) {
|
||||
_list->setFocus();
|
||||
|
|
|
@ -422,6 +422,8 @@ private:
|
|||
[[nodiscard]] int computeMaxFieldHeight() const;
|
||||
void toggleMuteUnmute();
|
||||
void reportSelectedMessages();
|
||||
void payForMessage();
|
||||
void payForMessageSure(bool trust = false);
|
||||
void showKeyboardHideButton();
|
||||
void toggleKeyboard(bool manual = true);
|
||||
void startBotCommand();
|
||||
|
@ -640,6 +642,7 @@ private:
|
|||
[[nodiscard]] bool isJoinChannel() const;
|
||||
[[nodiscard]] bool isMuteUnmute() const;
|
||||
[[nodiscard]] bool isReportMessages() const;
|
||||
[[nodiscard]] bool isPayForMessage() const;
|
||||
bool updateCmdStartShown();
|
||||
void updateSendButtonType();
|
||||
[[nodiscard]] bool showRecordButton() const;
|
||||
|
@ -778,6 +781,8 @@ private:
|
|||
QPointer<Ui::IconButton> _giftToChannelIn;
|
||||
QPointer<Ui::IconButton> _giftToChannelOut;
|
||||
object_ptr<Ui::FlatButton> _reportMessages;
|
||||
object_ptr<Ui::FlatButton> _payForMessage;
|
||||
mutable rpl::variable<int> _payForMessageStars;
|
||||
struct {
|
||||
object_ptr<Ui::RoundButton> button = { nullptr };
|
||||
QString text;
|
||||
|
|
|
@ -348,6 +348,7 @@ private:
|
|||
std::unique_ptr<ComposeControls> _composeControls;
|
||||
std::unique_ptr<ComposeSearch> _composeSearch;
|
||||
std::unique_ptr<Ui::FlatButton> _joinGroup;
|
||||
std::unique_ptr<Ui::FlatButton> _payForMessage;
|
||||
std::unique_ptr<TopicReopenBar> _topicReopenBar;
|
||||
std::unique_ptr<EmptyPainter> _emptyPainter;
|
||||
bool _skipScrollEvent = false;
|
||||
|
|
|
@ -1015,12 +1015,12 @@ void WebViewInstance::resolveApp(
|
|||
|
||||
void WebViewInstance::confirmOpen(Fn<void()> done) {
|
||||
if (_bot->isVerified()
|
||||
|| _session->local().isBotTrustedOpenWebView(_bot->id)) {
|
||||
|| _session->local().isPeerTrustedOpenWebView(_bot->id)) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
const auto callback = [=](Fn<void()> close) {
|
||||
_session->local().markBotTrustedOpenWebView(_bot->id);
|
||||
_session->local().markPeerTrustedOpenWebView(_bot->id);
|
||||
close();
|
||||
done();
|
||||
};
|
||||
|
@ -1052,14 +1052,14 @@ void WebViewInstance::confirmAppOpen(
|
|||
bool forceConfirmation) {
|
||||
if (!forceConfirmation
|
||||
&& (_bot->isVerified()
|
||||
|| _session->local().isBotTrustedOpenWebView(_bot->id))) {
|
||||
|| _session->local().isPeerTrustedOpenWebView(_bot->id))) {
|
||||
done(writeAccess);
|
||||
return;
|
||||
}
|
||||
_parentShow->show(Box([=](not_null<Ui::GenericBox*> box) {
|
||||
const auto allowed = std::make_shared<Ui::Checkbox*>();
|
||||
const auto callback = [=](Fn<void()> close) {
|
||||
_session->local().markBotTrustedOpenWebView(_bot->id);
|
||||
_session->local().markPeerTrustedOpenWebView(_bot->id);
|
||||
done((*allowed) && (*allowed)->checked());
|
||||
close();
|
||||
};
|
||||
|
|
|
@ -131,7 +131,8 @@ namespace Media::Stories {
|
|||
if (options.invertCaption) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
|
||||
}
|
||||
if (options.paidByStars) {
|
||||
const auto starsPaid = peer->commitStarsForMessage();
|
||||
if (starsPaid) {
|
||||
sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
|
||||
}
|
||||
const auto done = [=] {
|
||||
|
@ -159,7 +160,7 @@ namespace Media::Stories {
|
|||
MTP_inputPeerEmpty(),
|
||||
Data::ShortcutIdToMTP(session, options.shortcutId),
|
||||
MTP_long(options.effectId),
|
||||
MTP_long(options.paidByStars)
|
||||
MTP_long(starsPaid)
|
||||
), [=](
|
||||
const MTPUpdates &result,
|
||||
const MTP::Response &response) {
|
||||
|
|
|
@ -904,7 +904,7 @@ void Form::submit() {
|
|||
if (index < list.size() && password.isEmpty()) {
|
||||
_updates.fire(TmpPasswordRequired{});
|
||||
return;
|
||||
} else if (!_session->local().isBotTrustedPayment(_details.botId)) {
|
||||
} else if (!_session->local().isPeerTrustedPayment(_details.botId)) {
|
||||
_updates.fire(BotTrustRequired{
|
||||
.bot = _session->data().user(_details.botId),
|
||||
.provider = _session->data().user(_details.providerId),
|
||||
|
@ -1307,7 +1307,7 @@ void Form::acceptTerms() {
|
|||
}
|
||||
|
||||
void Form::trustBot() {
|
||||
_session->local().markBotTrustedPayment(_details.botId);
|
||||
_session->local().markPeerTrustedPayment(_details.botId);
|
||||
}
|
||||
|
||||
void Form::processShippingOptions(const QVector<MTPShippingOption> &data) {
|
||||
|
|
|
@ -2090,6 +2090,8 @@ void SmallBalanceBox(
|
|||
return QString();
|
||||
}, [&](SmallBalanceStarGift value) {
|
||||
return owner->peer(value.recipientId)->shortName();
|
||||
}, [&](SmallBalanceForMessage value) {
|
||||
return owner->peer(value.recipientId)->shortName();
|
||||
});
|
||||
|
||||
auto needed = show->session().credits().balanceValue(
|
||||
|
@ -2128,6 +2130,11 @@ void SmallBalanceBox(
|
|||
lt_user,
|
||||
rpl::single(Ui::Text::Bold(name)),
|
||||
Ui::Text::RichLangValue)
|
||||
: v::is<SmallBalanceForMessage>(source)
|
||||
? tr::lng_credits_small_balance_for_message(
|
||||
lt_user,
|
||||
rpl::single(Ui::Text::Bold(name)),
|
||||
Ui::Text::RichLangValue)
|
||||
: name.isEmpty()
|
||||
? tr::lng_credits_small_balance_fallback(
|
||||
Ui::Text::RichLangValue)
|
||||
|
|
|
@ -200,12 +200,16 @@ struct SmallBalanceDeepLink {
|
|||
struct SmallBalanceStarGift {
|
||||
PeerId recipientId;
|
||||
};
|
||||
struct SmallBalanceForMessage {
|
||||
PeerId recipientId;
|
||||
};
|
||||
struct SmallBalanceSource : std::variant<
|
||||
SmallBalanceBot,
|
||||
SmallBalanceReaction,
|
||||
SmallBalanceSubscription,
|
||||
SmallBalanceDeepLink,
|
||||
SmallBalanceStarGift> {
|
||||
SmallBalanceStarGift,
|
||||
SmallBalanceForMessage> {
|
||||
using variant::variant;
|
||||
};
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ enum { // Local Storage Keys
|
|||
lskSavedGifsOld = 0x0e, // no data
|
||||
lskSavedGifs = 0x0f, // no data
|
||||
lskStickersKeys = 0x10, // no data
|
||||
lskTrustedBots = 0x11, // no data
|
||||
lskTrustedPeers = 0x11, // no data
|
||||
lskFavedStickers = 0x12, // no data
|
||||
lskExportSettings = 0x13, // no data
|
||||
lskBackgroundOld = 0x14, // no data
|
||||
|
@ -220,7 +220,7 @@ base::flat_set<QString> Account::collectGoodNames() const {
|
|||
_legacyBackgroundKeyDay,
|
||||
_recentHashtagsAndBotsKey,
|
||||
_exportSettingsKey,
|
||||
_trustedBotsKey,
|
||||
_trustedPeersKey,
|
||||
_installedMasksKey,
|
||||
_recentMasksKey,
|
||||
_archivedMasksKey,
|
||||
|
@ -308,7 +308,7 @@ Account::ReadMapResult Account::readMapWith(
|
|||
base::flat_map<PeerId, FileKey> draftsMap;
|
||||
base::flat_map<PeerId, FileKey> draftCursorsMap;
|
||||
base::flat_map<PeerId, bool> draftsNotReadMap;
|
||||
quint64 locationsKey = 0, reportSpamStatusesKey = 0, trustedBotsKey = 0;
|
||||
quint64 locationsKey = 0, reportSpamStatusesKey = 0, trustedPeersKey = 0;
|
||||
quint64 recentStickersKeyOld = 0;
|
||||
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0;
|
||||
quint64 installedMasksKey = 0, recentMasksKey = 0, archivedMasksKey = 0;
|
||||
|
@ -371,8 +371,8 @@ Account::ReadMapResult Account::readMapWith(
|
|||
map.stream >> reportSpamStatusesKey;
|
||||
ClearKey(reportSpamStatusesKey, _basePath);
|
||||
} break;
|
||||
case lskTrustedBots: {
|
||||
map.stream >> trustedBotsKey;
|
||||
case lskTrustedPeers: {
|
||||
map.stream >> trustedPeersKey;
|
||||
} break;
|
||||
case lskRecentStickersOld: {
|
||||
map.stream >> recentStickersKeyOld;
|
||||
|
@ -459,7 +459,7 @@ Account::ReadMapResult Account::readMapWith(
|
|||
_draftsNotReadMap = draftsNotReadMap;
|
||||
|
||||
_locationsKey = locationsKey;
|
||||
_trustedBotsKey = trustedBotsKey;
|
||||
_trustedPeersKey = trustedPeersKey;
|
||||
_recentStickersKeyOld = recentStickersKeyOld;
|
||||
_installedStickersKey = installedStickersKey;
|
||||
_featuredStickersKey = featuredStickersKey;
|
||||
|
@ -573,7 +573,7 @@ void Account::writeMap() {
|
|||
if (!_draftsMap.empty()) mapSize += sizeof(quint32) * 2 + _draftsMap.size() * sizeof(quint64) * 2;
|
||||
if (!_draftCursorsMap.empty()) mapSize += sizeof(quint32) * 2 + _draftCursorsMap.size() * sizeof(quint64) * 2;
|
||||
if (_locationsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_trustedBotsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_trustedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_recentStickersKeyOld) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
|
||||
mapSize += sizeof(quint32) + 4 * sizeof(quint64);
|
||||
|
@ -619,8 +619,8 @@ void Account::writeMap() {
|
|||
if (_locationsKey) {
|
||||
mapData.stream << quint32(lskLocations) << quint64(_locationsKey);
|
||||
}
|
||||
if (_trustedBotsKey) {
|
||||
mapData.stream << quint32(lskTrustedBots) << quint64(_trustedBotsKey);
|
||||
if (_trustedPeersKey) {
|
||||
mapData.stream << quint32(lskTrustedPeers) << quint64(_trustedPeersKey);
|
||||
}
|
||||
if (_recentStickersKeyOld) {
|
||||
mapData.stream << quint32(lskRecentStickersOld) << quint64(_recentStickersKeyOld);
|
||||
|
@ -693,7 +693,7 @@ void Account::reset() {
|
|||
_draftsMap.clear();
|
||||
_draftCursorsMap.clear();
|
||||
_draftsNotReadMap.clear();
|
||||
_locationsKey = _trustedBotsKey = 0;
|
||||
_locationsKey = _trustedPeersKey = 0;
|
||||
_recentStickersKeyOld = 0;
|
||||
_installedStickersKey = 0;
|
||||
_featuredStickersKey = 0;
|
||||
|
@ -3147,47 +3147,47 @@ void Account::readSelf(
|
|||
}
|
||||
}
|
||||
|
||||
void Account::writeTrustedBots() {
|
||||
if (_trustedBots.empty()) {
|
||||
if (_trustedBotsKey) {
|
||||
ClearKey(_trustedBotsKey, _basePath);
|
||||
_trustedBotsKey = 0;
|
||||
void Account::writeTrustedPeers() {
|
||||
if (_trustedPeers.empty()) {
|
||||
if (_trustedPeersKey) {
|
||||
ClearKey(_trustedPeersKey, _basePath);
|
||||
_trustedPeersKey = 0;
|
||||
writeMapDelayed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!_trustedBotsKey) {
|
||||
_trustedBotsKey = GenerateKey(_basePath);
|
||||
if (!_trustedPeersKey) {
|
||||
_trustedPeersKey = GenerateKey(_basePath);
|
||||
writeMapQueued();
|
||||
}
|
||||
quint32 size = sizeof(qint32) + _trustedBots.size() * sizeof(quint64);
|
||||
quint32 size = sizeof(qint32) + _trustedPeers.size() * sizeof(quint64);
|
||||
EncryptedDescriptor data(size);
|
||||
data.stream << qint32(_trustedBots.size());
|
||||
for (const auto &[peerId, mask] : _trustedBots) {
|
||||
// value: 8 bit mask, 56 bit bot peer_id.
|
||||
data.stream << qint32(_trustedPeers.size());
|
||||
for (const auto &[peerId, mask] : _trustedPeers) {
|
||||
// value: 8 bit mask, 56 bit peer_id.
|
||||
auto value = SerializePeerId(peerId);
|
||||
Assert((value >> 56) == 0);
|
||||
value |= (quint64(mask) << 56);
|
||||
data.stream << value;
|
||||
}
|
||||
|
||||
FileWriteDescriptor file(_trustedBotsKey, _basePath);
|
||||
FileWriteDescriptor file(_trustedPeersKey, _basePath);
|
||||
file.writeEncrypted(data, _localKey);
|
||||
}
|
||||
|
||||
void Account::readTrustedBots() {
|
||||
if (_trustedBotsRead) {
|
||||
void Account::readTrustedPeers() {
|
||||
if (_trustedPeersRead) {
|
||||
return;
|
||||
}
|
||||
_trustedBotsRead = true;
|
||||
if (!_trustedBotsKey) {
|
||||
_trustedPeersRead = true;
|
||||
if (!_trustedPeersKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileReadDescriptor trusted;
|
||||
if (!ReadEncryptedFile(trusted, _trustedBotsKey, _basePath, _localKey)) {
|
||||
ClearKey(_trustedBotsKey, _basePath);
|
||||
_trustedBotsKey = 0;
|
||||
if (!ReadEncryptedFile(trusted, _trustedPeersKey, _basePath, _localKey)) {
|
||||
ClearKey(_trustedPeersKey, _basePath);
|
||||
_trustedPeersKey = 0;
|
||||
writeMapDelayed();
|
||||
return;
|
||||
}
|
||||
|
@ -3197,76 +3197,106 @@ void Account::readTrustedBots() {
|
|||
for (int i = 0; i < size; ++i) {
|
||||
auto value = quint64();
|
||||
trusted.stream >> value;
|
||||
const auto mask = base::flags<BotTrustFlag>::from_raw(
|
||||
const auto mask = base::flags<PeerTrustFlag>::from_raw(
|
||||
uchar(value >> 56));
|
||||
const auto peerIdSerialized = value & ~(0xFFULL << 56);
|
||||
const auto peerId = DeserializePeerId(peerIdSerialized);
|
||||
_trustedBots.emplace(peerId, mask);
|
||||
_trustedPeers.emplace(peerId, mask);
|
||||
}
|
||||
}
|
||||
|
||||
void Account::markBotTrustedOpenGame(PeerId botId) {
|
||||
if (isBotTrustedOpenGame(botId)) {
|
||||
void Account::markPeerTrustedOpenGame(PeerId peerId) {
|
||||
if (isPeerTrustedOpenGame(peerId)) {
|
||||
return;
|
||||
}
|
||||
const auto i = _trustedBots.find(botId);
|
||||
if (i == end(_trustedBots)) {
|
||||
_trustedBots.emplace(botId, BotTrustFlag());
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i == end(_trustedPeers)) {
|
||||
_trustedPeers.emplace(peerId, PeerTrustFlag());
|
||||
} else {
|
||||
i->second &= ~BotTrustFlag::NoOpenGame;
|
||||
i->second &= ~PeerTrustFlag::NoOpenGame;
|
||||
}
|
||||
writeTrustedBots();
|
||||
writeTrustedPeers();
|
||||
}
|
||||
|
||||
bool Account::isBotTrustedOpenGame(PeerId botId) {
|
||||
readTrustedBots();
|
||||
const auto i = _trustedBots.find(botId);
|
||||
return (i != end(_trustedBots))
|
||||
&& ((i->second & BotTrustFlag::NoOpenGame) == 0);
|
||||
bool Account::isPeerTrustedOpenGame(PeerId peerId) {
|
||||
readTrustedPeers();
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
return (i != end(_trustedPeers))
|
||||
&& ((i->second & PeerTrustFlag::NoOpenGame) == 0);
|
||||
}
|
||||
|
||||
void Account::markBotTrustedPayment(PeerId botId) {
|
||||
if (isBotTrustedPayment(botId)) {
|
||||
void Account::markPeerTrustedPayment(PeerId peerId) {
|
||||
if (isPeerTrustedPayment(peerId)) {
|
||||
return;
|
||||
}
|
||||
const auto i = _trustedBots.find(botId);
|
||||
if (i == end(_trustedBots)) {
|
||||
_trustedBots.emplace(
|
||||
botId,
|
||||
BotTrustFlag::NoOpenGame | BotTrustFlag::Payment);
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i == end(_trustedPeers)) {
|
||||
_trustedPeers.emplace(
|
||||
peerId,
|
||||
PeerTrustFlag::NoOpenGame | PeerTrustFlag::Payment);
|
||||
} else {
|
||||
i->second |= BotTrustFlag::Payment;
|
||||
i->second |= PeerTrustFlag::Payment;
|
||||
}
|
||||
writeTrustedBots();
|
||||
writeTrustedPeers();
|
||||
}
|
||||
|
||||
bool Account::isBotTrustedPayment(PeerId botId) {
|
||||
readTrustedBots();
|
||||
const auto i = _trustedBots.find(botId);
|
||||
return (i != end(_trustedBots))
|
||||
&& ((i->second & BotTrustFlag::Payment) != 0);
|
||||
bool Account::isPeerTrustedPayment(PeerId peerId) {
|
||||
readTrustedPeers();
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
return (i != end(_trustedPeers))
|
||||
&& ((i->second & PeerTrustFlag::Payment) != 0);
|
||||
}
|
||||
|
||||
void Account::markBotTrustedOpenWebView(PeerId botId) {
|
||||
if (isBotTrustedOpenWebView(botId)) {
|
||||
void Account::markPeerTrustedOpenWebView(PeerId peerId) {
|
||||
if (isPeerTrustedOpenWebView(peerId)) {
|
||||
return;
|
||||
}
|
||||
const auto i = _trustedBots.find(botId);
|
||||
if (i == end(_trustedBots)) {
|
||||
_trustedBots.emplace(
|
||||
botId,
|
||||
BotTrustFlag::NoOpenGame | BotTrustFlag::OpenWebView);
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i == end(_trustedPeers)) {
|
||||
_trustedPeers.emplace(
|
||||
peerId,
|
||||
PeerTrustFlag::NoOpenGame | PeerTrustFlag::OpenWebView);
|
||||
} else {
|
||||
i->second |= BotTrustFlag::OpenWebView;
|
||||
i->second |= PeerTrustFlag::OpenWebView;
|
||||
}
|
||||
writeTrustedBots();
|
||||
writeTrustedPeers();
|
||||
}
|
||||
|
||||
bool Account::isBotTrustedOpenWebView(PeerId botId) {
|
||||
readTrustedBots();
|
||||
const auto i = _trustedBots.find(botId);
|
||||
return (i != end(_trustedBots))
|
||||
&& ((i->second & BotTrustFlag::OpenWebView) != 0);
|
||||
bool Account::isPeerTrustedOpenWebView(PeerId peerId) {
|
||||
readTrustedPeers();
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
return (i != end(_trustedPeers))
|
||||
&& ((i->second & PeerTrustFlag::OpenWebView) != 0);
|
||||
}
|
||||
|
||||
void Account::markPeerTrustedPayForMessage(PeerId peerId) {
|
||||
if (isPeerTrustedPayForMessage(peerId)) {
|
||||
return;
|
||||
}
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i == end(_trustedPeers)) {
|
||||
_trustedPeers.emplace(
|
||||
peerId,
|
||||
PeerTrustFlag::NoOpenGame | PeerTrustFlag::PayForMessage);
|
||||
} else {
|
||||
i->second |= PeerTrustFlag::PayForMessage;
|
||||
}
|
||||
writeTrustedPeers();
|
||||
}
|
||||
|
||||
bool Account::isPeerTrustedPayForMessage(PeerId peerId) {
|
||||
readTrustedPeers();
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
return (i != end(_trustedPeers))
|
||||
&& ((i->second & PeerTrustFlag::PayForMessage) != 0);
|
||||
}
|
||||
|
||||
void Account::clearPeerTrusted(PeerId peerId) {
|
||||
const auto i = _trustedPeers.find(peerId);
|
||||
if (i != end(_trustedPeers)) {
|
||||
_trustedPeers.erase(i);
|
||||
writeTrustedPeers();
|
||||
}
|
||||
}
|
||||
|
||||
void Account::enforceModernStorageIdBots() {
|
||||
|
|
|
@ -167,12 +167,15 @@ public:
|
|||
const QByteArray& serialized,
|
||||
int32 streamVersion);
|
||||
|
||||
void markBotTrustedOpenGame(PeerId botId);
|
||||
[[nodiscard]] bool isBotTrustedOpenGame(PeerId botId);
|
||||
void markBotTrustedPayment(PeerId botId);
|
||||
[[nodiscard]] bool isBotTrustedPayment(PeerId botId);
|
||||
void markBotTrustedOpenWebView(PeerId botId);
|
||||
[[nodiscard]] bool isBotTrustedOpenWebView(PeerId botId);
|
||||
void markPeerTrustedOpenGame(PeerId peerId);
|
||||
[[nodiscard]] bool isPeerTrustedOpenGame(PeerId peerId);
|
||||
void markPeerTrustedPayment(PeerId peerId);
|
||||
[[nodiscard]] bool isPeerTrustedPayment(PeerId peerId);
|
||||
void markPeerTrustedOpenWebView(PeerId peerId);
|
||||
[[nodiscard]] bool isPeerTrustedOpenWebView(PeerId peerId);
|
||||
void markPeerTrustedPayForMessage(PeerId peerId);
|
||||
[[nodiscard]] bool isPeerTrustedPayForMessage(PeerId peerId);
|
||||
void clearPeerTrusted(PeerId peerId);
|
||||
|
||||
void enforceModernStorageIdBots();
|
||||
[[nodiscard]] Webview::StorageId resolveStorageIdBots();
|
||||
|
@ -203,12 +206,13 @@ private:
|
|||
IncorrectPasscode,
|
||||
Failed,
|
||||
};
|
||||
enum class BotTrustFlag : uchar {
|
||||
enum class PeerTrustFlag : uchar {
|
||||
NoOpenGame = (1 << 0),
|
||||
Payment = (1 << 1),
|
||||
OpenWebView = (1 << 2),
|
||||
PayForMessage = (1 << 3),
|
||||
};
|
||||
friend inline constexpr bool is_flag_type(BotTrustFlag) { return true; };
|
||||
friend inline constexpr bool is_flag_type(PeerTrustFlag) { return true; };
|
||||
|
||||
[[nodiscard]] base::flat_set<QString> collectGoodNames() const;
|
||||
[[nodiscard]] auto prepareReadSettingsContext() const
|
||||
|
@ -261,8 +265,8 @@ private:
|
|||
Data::StickersSetFlags readingFlags = 0);
|
||||
void importOldRecentStickers();
|
||||
|
||||
void readTrustedBots();
|
||||
void writeTrustedBots();
|
||||
void readTrustedPeers();
|
||||
void writeTrustedPeers();
|
||||
|
||||
void readMediaLastPlaybackPositions();
|
||||
void writeMediaLastPlaybackPositions();
|
||||
|
@ -295,7 +299,7 @@ private:
|
|||
Fn<std::optional<QByteArray>()> _downloadsSerialize;
|
||||
|
||||
FileKey _locationsKey = 0;
|
||||
FileKey _trustedBotsKey = 0;
|
||||
FileKey _trustedPeersKey = 0;
|
||||
FileKey _installedStickersKey = 0;
|
||||
FileKey _featuredStickersKey = 0;
|
||||
FileKey _recentStickersKey = 0;
|
||||
|
@ -324,8 +328,8 @@ private:
|
|||
qint32 _cacheTotalTimeLimit = 0;
|
||||
qint32 _cacheBigFileTotalTimeLimit = 0;
|
||||
|
||||
base::flat_map<PeerId, base::flags<BotTrustFlag>> _trustedBots;
|
||||
bool _trustedBotsRead = false;
|
||||
base::flat_map<PeerId, base::flags<PeerTrustFlag>> _trustedPeers;
|
||||
bool _trustedPeersRead = false;
|
||||
bool _readingUserSettings = false;
|
||||
bool _recentHashtagsAndBotsWereRead = false;
|
||||
bool _searchSuggestionsRead = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue