mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Ask for boosts to unlock group restrictions.
This commit is contained in:
parent
a7ae7a8cda
commit
5f10c1875c
38 changed files with 587 additions and 389 deletions
|
@ -3267,13 +3267,13 @@ void ApiWrap::finishForwarding(const SendAction &action) {
|
||||||
const auto topicRootId = action.replyTo.topicRootId;
|
const auto topicRootId = action.replyTo.topicRootId;
|
||||||
auto toForward = history->resolveForwardDraft(topicRootId);
|
auto toForward = history->resolveForwardDraft(topicRootId);
|
||||||
if (!toForward.items.empty()) {
|
if (!toForward.items.empty()) {
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
history->peer,
|
history->peer,
|
||||||
{
|
{
|
||||||
.topicRootId = topicRootId,
|
.topicRootId = topicRootId,
|
||||||
.forward = &toForward.items,
|
.forward = &toForward.items,
|
||||||
});
|
});
|
||||||
if (!error.isEmpty()) {
|
if (error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/view/history_view_group_call_bar.h" // GenerateUserpics...
|
#include "history/view/history_view_group_call_bar.h" // GenerateUserpics...
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -1492,27 +1492,14 @@ object_ptr<Ui::BoxContent> ShareInviteLinkBox(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto error = [&] {
|
const auto errorWithThread = GetErrorForSending(
|
||||||
for (const auto thread : result) {
|
result,
|
||||||
const auto error = GetErrorTextForSending(
|
{ .text = &comment });
|
||||||
thread,
|
if (errorWithThread.error) {
|
||||||
{ .text = &comment });
|
|
||||||
if (!error.isEmpty()) {
|
|
||||||
return std::make_pair(error, thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(QString(), result.front());
|
|
||||||
}();
|
|
||||||
if (!error.first.isEmpty()) {
|
|
||||||
auto text = TextWithEntities();
|
|
||||||
if (result.size() > 1) {
|
|
||||||
text.append(
|
|
||||||
Ui::Text::Bold(error.second->chatListName())
|
|
||||||
).append("\n\n");
|
|
||||||
}
|
|
||||||
text.append(error.first);
|
|
||||||
if (*box) {
|
if (*box) {
|
||||||
(*box)->uiShow()->showBox(Ui::MakeInformBox(text));
|
(*box)->uiShow()->showBox(MakeSendErrorBox(
|
||||||
|
errorWithThread,
|
||||||
|
result.size() > 1));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,7 +220,7 @@ SendFilesCheck DefaultCheckForPeer(
|
||||||
}
|
}
|
||||||
|
|
||||||
SendFilesCheck DefaultCheckForPeer(
|
SendFilesCheck DefaultCheckForPeer(
|
||||||
std::shared_ptr<Ui::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
not_null<PeerData*> peer) {
|
not_null<PeerData*> peer) {
|
||||||
return [=](
|
return [=](
|
||||||
const Ui::PreparedFile &file,
|
const Ui::PreparedFile &file,
|
||||||
|
@ -228,7 +228,7 @@ SendFilesCheck DefaultCheckForPeer(
|
||||||
bool silent) {
|
bool silent) {
|
||||||
const auto error = Data::FileRestrictionError(peer, file, compress);
|
const auto error = Data::FileRestrictionError(peer, file, compress);
|
||||||
if (error && !silent) {
|
if (error && !silent) {
|
||||||
show->showToast(*error);
|
Data::ShowSendErrorToast(show, peer, error);
|
||||||
}
|
}
|
||||||
return !error.has_value();
|
return !error.has_value();
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,7 +80,7 @@ using SendFilesCheck = Fn<bool(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
[[nodiscard]] SendFilesCheck DefaultCheckForPeer(
|
[[nodiscard]] SendFilesCheck DefaultCheckForPeer(
|
||||||
std::shared_ptr<Ui::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
not_null<PeerData*> peer);
|
not_null<PeerData*> peer);
|
||||||
|
|
||||||
using SendFilesConfirmed = Fn<void(
|
using SendFilesConfirmed = Fn<void(
|
||||||
|
|
|
@ -1508,26 +1508,11 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto error = [&] {
|
const auto error = GetErrorForSending(
|
||||||
for (const auto thread : result) {
|
result,
|
||||||
const auto error = GetErrorTextForSending(
|
{ .forward = &items, .text = &comment });
|
||||||
thread,
|
if (error.error) {
|
||||||
{ .forward = &items, .text = &comment });
|
show->showBox(MakeSendErrorBox(error, result.size() > 1));
|
||||||
if (!error.isEmpty()) {
|
|
||||||
return std::make_pair(error, thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(QString(), result.front());
|
|
||||||
}();
|
|
||||||
if (!error.first.isEmpty()) {
|
|
||||||
auto text = TextWithEntities();
|
|
||||||
if (result.size() > 1) {
|
|
||||||
text.append(
|
|
||||||
Ui::Text::Bold(error.second->chatListName())
|
|
||||||
).append("\n\n");
|
|
||||||
}
|
|
||||||
text.append(error.first);
|
|
||||||
show->showBox(Ui::MakeInformBox(text));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1737,30 +1722,13 @@ void FastShareLink(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto error = [&] {
|
const auto error = GetErrorForSending(
|
||||||
for (const auto thread : result) {
|
result,
|
||||||
const auto error = GetErrorTextForSending(
|
{ .text = &comment });
|
||||||
thread,
|
if (error.error) {
|
||||||
{ .text = &comment });
|
|
||||||
if (!error.isEmpty()) {
|
|
||||||
return std::make_pair(error, thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(QString(), result.front());
|
|
||||||
}();
|
|
||||||
if (!error.first.isEmpty()) {
|
|
||||||
auto text = TextWithEntities();
|
|
||||||
if (result.size() > 1) {
|
|
||||||
text.append(
|
|
||||||
Ui::Text::Bold(error.second->chatListName())
|
|
||||||
).append("\n\n");
|
|
||||||
}
|
|
||||||
text.append(error.first);
|
|
||||||
if (const auto weak = *box) {
|
if (const auto weak = *box) {
|
||||||
weak->getDelegate()->show(Ui::MakeConfirmBox({
|
weak->getDelegate()->show(
|
||||||
.text = text,
|
MakeSendErrorBox(error, result.size() > 1));
|
||||||
.inform = true,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "boxes/share_box.h"
|
#include "boxes/share_box.h"
|
||||||
#include "history/view/history_view_schedule_box.h"
|
#include "history/view/history_view_schedule_box.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "data/data_histories.h"
|
#include "data/data_histories.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
@ -139,30 +139,13 @@ object_ptr<ShareBox> ShareInviteLinkBox(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto error = [&] {
|
const auto error = GetErrorForSending(
|
||||||
for (const auto thread : result) {
|
result,
|
||||||
const auto error = GetErrorTextForSending(
|
{ .text = &comment });
|
||||||
thread,
|
if (error.error) {
|
||||||
{ .text = &comment });
|
|
||||||
if (!error.isEmpty()) {
|
|
||||||
return std::make_pair(error, thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(QString(), result.front());
|
|
||||||
}();
|
|
||||||
if (!error.first.isEmpty()) {
|
|
||||||
auto text = TextWithEntities();
|
|
||||||
if (result.size() > 1) {
|
|
||||||
text.append(
|
|
||||||
Ui::Text::Bold(error.second->chatListName())
|
|
||||||
).append("\n\n");
|
|
||||||
}
|
|
||||||
text.append(error.first);
|
|
||||||
if (const auto weak = *box) {
|
if (const auto weak = *box) {
|
||||||
weak->getDelegate()->show(ConfirmBox({
|
weak->getDelegate()->show(
|
||||||
.text = text,
|
MakeSendErrorBox(error, result.size() > 1));
|
||||||
.inform = true,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "chat_helpers/gifs_list_widget.h"
|
#include "chat_helpers/gifs_list_widget.h"
|
||||||
#include "menu/menu_send.h"
|
#include "menu/menu_send.h"
|
||||||
#include "ui/controls/tabbed_search.h"
|
#include "ui/controls/tabbed_search.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
|
@ -1042,23 +1043,39 @@ void TabbedSelector::checkRestrictedPeer() {
|
||||||
? Data::RestrictionError(
|
? Data::RestrictionError(
|
||||||
_currentPeer,
|
_currentPeer,
|
||||||
ChatRestriction::SendOther)
|
ChatRestriction::SendOther)
|
||||||
: std::nullopt)
|
: Data::SendError())
|
||||||
: std::nullopt;
|
: Data::SendError();
|
||||||
if (error) {
|
const auto changed = (_restrictedLabelKey != error.text);
|
||||||
if (!_restrictedLabel) {
|
if (!changed) {
|
||||||
_restrictedLabel.create(
|
|
||||||
this,
|
|
||||||
*error,
|
|
||||||
st::stickersRestrictedLabel);
|
|
||||||
_restrictedLabel->show();
|
|
||||||
updateRestrictedLabelGeometry();
|
|
||||||
currentTab()->footer()->hide();
|
|
||||||
_scroll->hide();
|
|
||||||
_bottomShadow->hide();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_restrictedLabelKey = error.text;
|
||||||
|
if (error) {
|
||||||
|
const auto show = _show;
|
||||||
|
const auto peer = _currentPeer;
|
||||||
|
_restrictedLabel.create(
|
||||||
|
this,
|
||||||
|
rpl::single(error.boostsToLift
|
||||||
|
? Ui::Text::Link(error.text)
|
||||||
|
: TextWithEntities{ error.text }),
|
||||||
|
st::stickersRestrictedLabel);
|
||||||
|
const auto lifting = error.boostsToLift;
|
||||||
|
_restrictedLabel->setClickHandlerFilter([=](auto...) {
|
||||||
|
const auto window = show->resolveWindow(
|
||||||
|
ChatHelpers::WindowUsage::PremiumPromo);
|
||||||
|
window->resolveBoostState(peer->asChannel(), lifting);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
_restrictedLabel->show();
|
||||||
|
updateRestrictedLabelGeometry();
|
||||||
|
currentTab()->footer()->hide();
|
||||||
|
_scroll->hide();
|
||||||
|
_bottomShadow->hide();
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_restrictedLabelKey = QString();
|
||||||
}
|
}
|
||||||
if (_restrictedLabel) {
|
if (_restrictedLabel) {
|
||||||
_restrictedLabel.destroy();
|
_restrictedLabel.destroy();
|
||||||
|
|
|
@ -309,6 +309,7 @@ private:
|
||||||
object_ptr<Ui::PlainShadow> _bottomShadow;
|
object_ptr<Ui::PlainShadow> _bottomShadow;
|
||||||
object_ptr<Ui::ScrollArea> _scroll;
|
object_ptr<Ui::ScrollArea> _scroll;
|
||||||
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
||||||
|
QString _restrictedLabelKey;
|
||||||
std::vector<Tab> _tabs;
|
std::vector<Tab> _tabs;
|
||||||
SelectorTab _currentTabType = SelectorTab::Emoji;
|
SelectorTab _currentTabType = SelectorTab::Emoji;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "boxes/peers/edit_peer_permissions_box.h"
|
#include "boxes/peers/edit_peer_permissions_box.h"
|
||||||
|
#include "chat_helpers/compose/compose_show.h"
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_channel.h"
|
#include "data/data_channel.h"
|
||||||
#include "data/data_forum_topic.h"
|
#include "data/data_forum_topic.h"
|
||||||
|
@ -17,6 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "ui/chat/attach/attach_prepare.h"
|
#include "ui/chat/attach/attach_prepare.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
|
#include "window/window_session_controller.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -167,7 +171,7 @@ bool CanSendAnyOf(
|
||||||
Unexpected("Peer type in CanSendAnyOf.");
|
Unexpected("Peer type in CanSendAnyOf.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> RestrictionError(
|
SendError RestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
ChatRestriction restriction) {
|
ChatRestriction restriction) {
|
||||||
using Flag = ChatRestriction;
|
using Flag = ChatRestriction;
|
||||||
|
@ -175,10 +179,13 @@ std::optional<QString> RestrictionError(
|
||||||
if (const auto user = peer->asUser()) {
|
if (const auto user = peer->asUser()) {
|
||||||
if (user->meRequiresPremiumToWrite()
|
if (user->meRequiresPremiumToWrite()
|
||||||
&& !user->session().premium()) {
|
&& !user->session().premium()) {
|
||||||
return tr::lng_restricted_send_non_premium(
|
return SendError({
|
||||||
tr::now,
|
.text = tr::lng_restricted_send_non_premium(
|
||||||
lt_user,
|
tr::now,
|
||||||
user->shortName());
|
lt_user,
|
||||||
|
user->shortName()),
|
||||||
|
.premiumToLift = true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const auto result = (restriction == Flag::SendVoiceMessages)
|
const auto result = (restriction == Flag::SendVoiceMessages)
|
||||||
? tr::lng_restricted_send_voice_messages(
|
? tr::lng_restricted_send_voice_messages(
|
||||||
|
@ -194,7 +201,7 @@ std::optional<QString> RestrictionError(
|
||||||
? u"can't send polls :("_q
|
? u"can't send polls :("_q
|
||||||
: (restriction == Flag::PinMessages)
|
: (restriction == Flag::PinMessages)
|
||||||
? u"can't pin :("_q
|
? u"can't pin :("_q
|
||||||
: std::optional<QString>();
|
: SendError();
|
||||||
|
|
||||||
Ensures(result.has_value());
|
Ensures(result.has_value());
|
||||||
return result;
|
return result;
|
||||||
|
@ -253,6 +260,15 @@ std::optional<QString> RestrictionError(
|
||||||
Unexpected("Restriction in Data::RestrictionErrorKey.");
|
Unexpected("Restriction in Data::RestrictionErrorKey.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (all
|
||||||
|
&& channel->boostsUnrestrict()
|
||||||
|
&& !channel->unrestrictedByBoosts()) {
|
||||||
|
return SendError({
|
||||||
|
.text = tr::lng_restricted_boost_group(tr::now),
|
||||||
|
.boostsToLift = (channel->boostsUnrestrict()
|
||||||
|
- channel->boostsApplied()),
|
||||||
|
});
|
||||||
|
}
|
||||||
switch (restriction) {
|
switch (restriction) {
|
||||||
case Flag::SendPolls:
|
case Flag::SendPolls:
|
||||||
return all
|
return all
|
||||||
|
@ -302,10 +318,10 @@ std::optional<QString> RestrictionError(
|
||||||
}
|
}
|
||||||
Unexpected("Restriction in Data::RestrictionErrorKey.");
|
Unexpected("Restriction in Data::RestrictionErrorKey.");
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return SendError();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> AnyFileRestrictionError(not_null<PeerData*> peer) {
|
SendError AnyFileRestrictionError(not_null<PeerData*> peer) {
|
||||||
using Restriction = ChatRestriction;
|
using Restriction = ChatRestriction;
|
||||||
for (const auto right : FilesSendRestrictionsList()) {
|
for (const auto right : FilesSendRestrictionsList()) {
|
||||||
if (!RestrictionError(peer, right)) {
|
if (!RestrictionError(peer, right)) {
|
||||||
|
@ -315,7 +331,7 @@ std::optional<QString> AnyFileRestrictionError(not_null<PeerData*> peer) {
|
||||||
return RestrictionError(peer, Restriction::SendFiles);
|
return RestrictionError(peer, Restriction::SendFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> FileRestrictionError(
|
SendError FileRestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress) {
|
std::optional<bool> compress) {
|
||||||
|
@ -339,7 +355,7 @@ std::optional<QString> FileRestrictionError(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> FileRestrictionError(
|
SendError FileRestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const Ui::PreparedFile &file,
|
const Ui::PreparedFile &file,
|
||||||
std::optional<bool> compress) {
|
std::optional<bool> compress) {
|
||||||
|
@ -383,4 +399,32 @@ std::optional<QString> FileRestrictionError(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowSendErrorToast(
|
||||||
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Data::SendError error) {
|
||||||
|
return ShowSendErrorToast(navigation->uiShow(), peer, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowSendErrorToast(
|
||||||
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
Data::SendError error) {
|
||||||
|
Expects(peer->isChannel());
|
||||||
|
|
||||||
|
if (!error.boostsToLift) {
|
||||||
|
show->showToast(*error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto boost = [=] {
|
||||||
|
const auto window = show->resolveWindow(
|
||||||
|
ChatHelpers::WindowUsage::PremiumPromo);
|
||||||
|
window->resolveBoostState(peer->asChannel(), error.boostsToLift);
|
||||||
|
};
|
||||||
|
show->showToast({
|
||||||
|
.text = Ui::Text::Link(*error),
|
||||||
|
.filter = [=](const auto &...) { boost(); return false; },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -7,11 +7,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
namespace ChatHelpers {
|
||||||
|
class Show;
|
||||||
|
} // namespace ChatHelpers
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
struct PreparedList;
|
struct PreparedList;
|
||||||
struct PreparedFile;
|
struct PreparedFile;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
|
namespace Window {
|
||||||
|
class SessionNavigation;
|
||||||
|
} // namespace Window
|
||||||
|
|
||||||
enum class ChatAdminRight {
|
enum class ChatAdminRight {
|
||||||
ChangeInfo = (1 << 0),
|
ChangeInfo = (1 << 0),
|
||||||
PostMessages = (1 << 1),
|
PostMessages = (1 << 1),
|
||||||
|
@ -175,18 +183,65 @@ struct RestrictionsSetOptions {
|
||||||
return CanSendAnyOf(peer, AllSendRestrictions(), forbidInForums);
|
return CanSendAnyOf(peer, AllSendRestrictions(), forbidInForums);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::optional<QString> RestrictionError(
|
struct SendError {
|
||||||
|
SendError(QString text = QString()) : text(std::move(text)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Args {
|
||||||
|
QString text;
|
||||||
|
int boostsToLift = 0;
|
||||||
|
bool premiumToLift = false;
|
||||||
|
};
|
||||||
|
SendError(Args &&args)
|
||||||
|
: text(std::move(args.text))
|
||||||
|
, boostsToLift(args.boostsToLift)
|
||||||
|
, premiumToLift(args.premiumToLift) {
|
||||||
|
}
|
||||||
|
|
||||||
|
QString text;
|
||||||
|
int boostsToLift = 0;
|
||||||
|
bool premiumToLift = false;
|
||||||
|
|
||||||
|
[[nodiscard]] SendError value_or(SendError other) const {
|
||||||
|
return *this ? *this : other;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return !text.isEmpty();
|
||||||
|
}
|
||||||
|
[[nodiscard]] bool has_value() const {
|
||||||
|
return !text.isEmpty();
|
||||||
|
}
|
||||||
|
[[nodiscard]] const QString &operator*() const {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SendErrorWithThread {
|
||||||
|
SendError error;
|
||||||
|
Thread *thread = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] SendError RestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
ChatRestriction restriction);
|
ChatRestriction restriction);
|
||||||
[[nodiscard]] std::optional<QString> AnyFileRestrictionError(
|
[[nodiscard]] SendError AnyFileRestrictionError(not_null<PeerData*> peer);
|
||||||
not_null<PeerData*> peer);
|
[[nodiscard]] SendError FileRestrictionError(
|
||||||
[[nodiscard]] std::optional<QString> FileRestrictionError(
|
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress);
|
std::optional<bool> compress);
|
||||||
[[nodiscard]] std::optional<QString> FileRestrictionError(
|
[[nodiscard]] SendError FileRestrictionError(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
const Ui::PreparedFile &file,
|
const Ui::PreparedFile &file,
|
||||||
std::optional<bool> compress);
|
std::optional<bool> compress);
|
||||||
|
|
||||||
|
void ShowSendErrorToast(
|
||||||
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
SendError error);
|
||||||
|
void ShowSendErrorToast(
|
||||||
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
SendError error);
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -423,7 +423,7 @@ bool Story::hasDirectLink() const {
|
||||||
return !_peer->username().isEmpty();
|
return !_peer->username().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> Story::errorTextForForward(
|
Data::SendError Story::errorTextForForward(
|
||||||
not_null<Thread*> to) const {
|
not_null<Thread*> to) const {
|
||||||
const auto peer = to->peer();
|
const auto peer = to->peer();
|
||||||
const auto holdsPhoto = v::is<not_null<PhotoData*>>(_media.data);
|
const auto holdsPhoto = v::is<not_null<PhotoData*>>(_media.data);
|
||||||
|
@ -433,10 +433,10 @@ std::optional<QString> Story::errorTextForForward(
|
||||||
const auto second = holdsPhoto
|
const auto second = holdsPhoto
|
||||||
? ChatRestriction::SendVideos
|
? ChatRestriction::SendVideos
|
||||||
: ChatRestriction::SendPhotos;
|
: ChatRestriction::SendPhotos;
|
||||||
if (const auto error = Data::RestrictionError(peer, first)) {
|
if (const auto one = Data::RestrictionError(peer, first)) {
|
||||||
return *error;
|
return one;
|
||||||
} else if (const auto error = Data::RestrictionError(peer, second)) {
|
} else if (const auto two = Data::RestrictionError(peer, second)) {
|
||||||
return *error;
|
return two;
|
||||||
} else if (!Data::CanSend(to, first, false)
|
} else if (!Data::CanSend(to, first, false)
|
||||||
|| !Data::CanSend(to, second, false)) {
|
|| !Data::CanSend(to, second, false)) {
|
||||||
return tr::lng_forward_cant(tr::now);
|
return tr::lng_forward_cant(tr::now);
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace Data {
|
||||||
class Session;
|
class Session;
|
||||||
class Thread;
|
class Thread;
|
||||||
class MediaPreload;
|
class MediaPreload;
|
||||||
|
struct SendError;
|
||||||
|
|
||||||
enum class StoryPrivacy : uchar {
|
enum class StoryPrivacy : uchar {
|
||||||
Public,
|
Public,
|
||||||
|
@ -191,7 +192,7 @@ public:
|
||||||
[[nodiscard]] bool canReport() const;
|
[[nodiscard]] bool canReport() const;
|
||||||
|
|
||||||
[[nodiscard]] bool hasDirectLink() const;
|
[[nodiscard]] bool hasDirectLink() const;
|
||||||
[[nodiscard]] std::optional<QString> errorTextForForward(
|
[[nodiscard]] Data::SendError errorTextForForward(
|
||||||
not_null<Thread*> to) const;
|
not_null<Thread*> to) const;
|
||||||
|
|
||||||
void setCaption(TextWithEntities &&caption);
|
void setCaption(TextWithEntities &&caption);
|
||||||
|
|
|
@ -2479,17 +2479,17 @@ bool HistoryItem::requiresSendInlineRight() const {
|
||||||
return Has<HistoryMessageVia>();
|
return Has<HistoryMessageVia>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<QString> HistoryItem::errorTextForForward(
|
Data::SendError HistoryItem::errorTextForForward(
|
||||||
not_null<Data::Thread*> to) const {
|
not_null<Data::Thread*> to) const {
|
||||||
const auto requiredRight = requiredSendRight();
|
const auto requiredRight = requiredSendRight();
|
||||||
const auto requiresInline = requiresSendInlineRight();
|
const auto requiresInline = requiresSendInlineRight();
|
||||||
const auto peer = to->peer();
|
const auto peer = to->peer();
|
||||||
constexpr auto kInline = ChatRestriction::SendInline;
|
constexpr auto kInline = ChatRestriction::SendInline;
|
||||||
if (const auto error = Data::RestrictionError(peer, requiredRight)) {
|
if (const auto error = Data::RestrictionError(peer, requiredRight)) {
|
||||||
return *error;
|
return error;
|
||||||
} else if (requiresInline && !Data::CanSend(to, kInline)) {
|
} else if (requiresInline && !Data::CanSend(to, kInline)) {
|
||||||
return Data::RestrictionError(peer, kInline).value_or(
|
const auto forInline = Data::RestrictionError(peer, kInline);
|
||||||
tr::lng_forward_cant(tr::now));
|
return forInline ? forInline : tr::lng_forward_cant(tr::now);
|
||||||
} else if (_media
|
} else if (_media
|
||||||
&& _media->poll()
|
&& _media->poll()
|
||||||
&& _media->poll()->publicVotes()
|
&& _media->poll()->publicVotes()
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct SponsoredFrom;
|
||||||
class Story;
|
class Story;
|
||||||
class SavedSublist;
|
class SavedSublist;
|
||||||
struct PaidReactionSend;
|
struct PaidReactionSend;
|
||||||
|
struct SendError;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
|
@ -442,7 +443,7 @@ public:
|
||||||
[[nodiscard]] bool suggestDeleteAllReport() const;
|
[[nodiscard]] bool suggestDeleteAllReport() const;
|
||||||
[[nodiscard]] ChatRestriction requiredSendRight() const;
|
[[nodiscard]] ChatRestriction requiredSendRight() const;
|
||||||
[[nodiscard]] bool requiresSendInlineRight() const;
|
[[nodiscard]] bool requiresSendInlineRight() const;
|
||||||
[[nodiscard]] std::optional<QString> errorTextForForward(
|
[[nodiscard]] Data::SendError errorTextForForward(
|
||||||
not_null<Data::Thread*> to) const;
|
not_null<Data::Thread*> to) const;
|
||||||
[[nodiscard]] const HistoryMessageTranslation *translation() const;
|
[[nodiscard]] const HistoryMessageTranslation *translation() const;
|
||||||
[[nodiscard]] bool translationShowRequiresCheck(LanguageId to) const;
|
[[nodiscard]] bool translationShowRequiresCheck(LanguageId to) const;
|
||||||
|
|
|
@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
#include "core/click_handler_types.h" // ClickHandlerContext.
|
#include "core/click_handler_types.h" // ClickHandlerContext.
|
||||||
|
#include "ui/boxes/confirm_box.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
|
@ -59,7 +60,7 @@ bool PeerCallKnown(not_null<PeerData*> peer) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
QString GetErrorTextForSending(
|
Data::SendError GetErrorForSending(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
SendingErrorRequest request) {
|
SendingErrorRequest request) {
|
||||||
const auto forum = request.topicRootId ? peer->forum() : nullptr;
|
const auto forum = request.topicRootId ? peer->forum() : nullptr;
|
||||||
|
@ -71,13 +72,13 @@ QString GetErrorTextForSending(
|
||||||
: peer->owner().history(peer);
|
: peer->owner().history(peer);
|
||||||
if (request.story) {
|
if (request.story) {
|
||||||
if (const auto error = request.story->errorTextForForward(thread)) {
|
if (const auto error = request.story->errorTextForForward(thread)) {
|
||||||
return *error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (request.forward) {
|
if (request.forward) {
|
||||||
for (const auto &item : *request.forward) {
|
for (const auto &item : *request.forward) {
|
||||||
if (const auto error = item->errorTextForForward(thread)) {
|
if (const auto error = item->errorTextForForward(thread)) {
|
||||||
return *error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +88,7 @@ QString GetErrorTextForSending(
|
||||||
peer,
|
peer,
|
||||||
ChatRestriction::SendOther);
|
ChatRestriction::SendOther);
|
||||||
if (error) {
|
if (error) {
|
||||||
return *error;
|
return error;
|
||||||
} else if (!Data::CanSendTexts(thread)) {
|
} else if (!Data::CanSendTexts(thread)) {
|
||||||
return tr::lng_forward_cant(tr::now);
|
return tr::lng_forward_cant(tr::now);
|
||||||
}
|
}
|
||||||
|
@ -134,14 +135,58 @@ QString GetErrorTextForSending(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GetErrorTextForSending(
|
Data::SendError GetErrorForSending(
|
||||||
not_null<Data::Thread*> thread,
|
not_null<Data::Thread*> thread,
|
||||||
SendingErrorRequest request) {
|
SendingErrorRequest request) {
|
||||||
request.topicRootId = thread->topicRootId();
|
request.topicRootId = thread->topicRootId();
|
||||||
return GetErrorTextForSending(thread->peer(), std::move(request));
|
return GetErrorForSending(thread->peer(), std::move(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
Data::SendErrorWithThread GetErrorForSending(
|
||||||
|
const std::vector<not_null<Data::Thread*>> &threads,
|
||||||
|
SendingErrorRequest request) {
|
||||||
|
for (const auto thread : threads) {
|
||||||
|
const auto error = GetErrorForSending(thread, request);
|
||||||
|
if (error) {
|
||||||
|
return Data::SendErrorWithThread{ error, thread };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
object_ptr<Ui::BoxContent> MakeSendErrorBox(
|
||||||
|
const Data::SendErrorWithThread &error,
|
||||||
|
bool withTitle) {
|
||||||
|
Expects(error.error.has_value() && error.thread != nullptr);
|
||||||
|
|
||||||
|
auto text = TextWithEntities();
|
||||||
|
if (withTitle) {
|
||||||
|
text.append(
|
||||||
|
Ui::Text::Bold(error.thread->chatListName())
|
||||||
|
).append("\n\n");
|
||||||
|
}
|
||||||
|
if (error.error.boostsToLift) {
|
||||||
|
text.append(Ui::Text::Link(error.error.text));
|
||||||
|
} else {
|
||||||
|
text.append(error.error.text);
|
||||||
|
}
|
||||||
|
const auto peer = error.thread->peer();
|
||||||
|
const auto lifting = error.error.boostsToLift;
|
||||||
|
const auto filter = [=](const auto &...) {
|
||||||
|
Expects(peer->isChannel());
|
||||||
|
|
||||||
|
const auto window = ChatHelpers::ResolveWindowDefault()(
|
||||||
|
&peer->session(),
|
||||||
|
ChatHelpers::WindowUsage::PremiumPromo);
|
||||||
|
window->resolveBoostState(peer->asChannel(), lifting);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
return Ui::MakeInformBox({
|
||||||
|
.text = text,
|
||||||
|
.labelFilter = filter,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestDependentMessageItem(
|
void RequestDependentMessageItem(
|
||||||
|
|
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/object_ptr.h"
|
||||||
|
|
||||||
class History;
|
class History;
|
||||||
|
|
||||||
namespace Api {
|
namespace Api {
|
||||||
|
@ -17,12 +19,18 @@ struct SendAction;
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class Story;
|
class Story;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
struct SendError;
|
||||||
|
struct SendErrorWithThread;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BoxContent;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
struct PreparedServiceText {
|
struct PreparedServiceText {
|
||||||
TextWithEntities text;
|
TextWithEntities text;
|
||||||
std::vector<ClickHandlerPtr> links;
|
std::vector<ClickHandlerPtr> links;
|
||||||
|
@ -108,13 +116,20 @@ struct SendingErrorRequest {
|
||||||
const TextWithTags *text = nullptr;
|
const TextWithTags *text = nullptr;
|
||||||
bool ignoreSlowmodeCountdown = false;
|
bool ignoreSlowmodeCountdown = false;
|
||||||
};
|
};
|
||||||
[[nodiscard]] QString GetErrorTextForSending(
|
[[nodiscard]] Data::SendError GetErrorForSending(
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
SendingErrorRequest request);
|
SendingErrorRequest request);
|
||||||
[[nodiscard]] QString GetErrorTextForSending(
|
[[nodiscard]] Data::SendError GetErrorForSending(
|
||||||
not_null<Data::Thread*> thread,
|
not_null<Data::Thread*> thread,
|
||||||
SendingErrorRequest request);
|
SendingErrorRequest request);
|
||||||
|
|
||||||
|
[[nodiscard]] Data::SendErrorWithThread GetErrorForSending(
|
||||||
|
const std::vector<not_null<Data::Thread*>> &threads,
|
||||||
|
SendingErrorRequest request);
|
||||||
|
[[nodiscard]] object_ptr<Ui::BoxContent> MakeSendErrorBox(
|
||||||
|
const Data::SendErrorWithThread &error,
|
||||||
|
bool withTitle);
|
||||||
|
|
||||||
[[nodiscard]] TextWithEntities DropDisallowedCustomEmoji(
|
[[nodiscard]] TextWithEntities DropDisallowedCustomEmoji(
|
||||||
not_null<PeerData*> to,
|
not_null<PeerData*> to,
|
||||||
TextWithEntities text);
|
TextWithEntities text);
|
||||||
|
|
|
@ -85,7 +85,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/history_drag_area.h"
|
#include "history/history_drag_area.h"
|
||||||
#include "history/history_inner_widget.h"
|
#include "history/history_inner_widget.h"
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
|
@ -1028,7 +1028,7 @@ void HistoryWidget::refreshTabbedPanel() {
|
||||||
|
|
||||||
void HistoryWidget::initVoiceRecordBar() {
|
void HistoryWidget::initVoiceRecordBar() {
|
||||||
_voiceRecordBar->setStartRecordingFilter([=] {
|
_voiceRecordBar->setStartRecordingFilter([=] {
|
||||||
const auto error = [&]() -> std::optional<QString> {
|
const auto error = [&]() -> Data::SendError {
|
||||||
if (_peer) {
|
if (_peer) {
|
||||||
if (const auto error = Data::RestrictionError(
|
if (const auto error = Data::RestrictionError(
|
||||||
_peer,
|
_peer,
|
||||||
|
@ -1036,10 +1036,10 @@ void HistoryWidget::initVoiceRecordBar() {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return {};
|
||||||
}();
|
}();
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
return true;
|
return true;
|
||||||
} else if (showSlowmodeError()) {
|
} else if (showSlowmodeError()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -4672,7 +4672,7 @@ void HistoryWidget::chooseAttach(
|
||||||
if (!_peer || !_canSendMessages) {
|
if (!_peer || !_canSendMessages) {
|
||||||
return;
|
return;
|
||||||
} else if (const auto error = Data::AnyFileRestrictionError(_peer)) {
|
} else if (const auto error = Data::AnyFileRestrictionError(_peer)) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
return;
|
return;
|
||||||
} else if (showSlowmodeError()) {
|
} else if (showSlowmodeError()) {
|
||||||
return;
|
return;
|
||||||
|
@ -5702,12 +5702,12 @@ bool HistoryWidget::showSendingFilesError(
|
||||||
bool HistoryWidget::showSendingFilesError(
|
bool HistoryWidget::showSendingFilesError(
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress) const {
|
std::optional<bool> compress) const {
|
||||||
const auto text = [&] {
|
const auto error = [&]() -> Data::SendError {
|
||||||
const auto error = _peer
|
const auto error = _peer
|
||||||
? Data::FileRestrictionError(_peer, list, compress)
|
? Data::FileRestrictionError(_peer, list, compress)
|
||||||
: std::nullopt;
|
: Data::SendError();
|
||||||
if (error) {
|
if (!_peer || error) {
|
||||||
return *error;
|
return error;
|
||||||
} else if (const auto left = _peer->slowmodeSecondsLeft()) {
|
} else if (const auto left = _peer->slowmodeSecondsLeft()) {
|
||||||
return tr::lng_slowmode_enabled(
|
return tr::lng_slowmode_enabled(
|
||||||
tr::now,
|
tr::now,
|
||||||
|
@ -5727,15 +5727,15 @@ bool HistoryWidget::showSendingFilesError(
|
||||||
}
|
}
|
||||||
return tr::lng_forward_send_files_cant(tr::now);
|
return tr::lng_forward_send_files_cant(tr::now);
|
||||||
}();
|
}();
|
||||||
if (text.isEmpty()) {
|
if (!error) {
|
||||||
return false;
|
return false;
|
||||||
} else if (text == u"(toolarge)"_q) {
|
} else if (error.text == u"(toolarge)"_q) {
|
||||||
const auto fileSize = list.files.back().size;
|
const auto fileSize = list.files.back().size;
|
||||||
controller()->show(
|
controller()->show(
|
||||||
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
|
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
controller()->showToast(text);
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5775,7 +5775,7 @@ bool HistoryWidget::showSendMessageError(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto topicRootId = resolveReplyToTopicRootId();
|
const auto topicRootId = resolveReplyToTopicRootId();
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
_peer,
|
_peer,
|
||||||
{
|
{
|
||||||
.topicRootId = topicRootId,
|
.topicRootId = topicRootId,
|
||||||
|
@ -5783,10 +5783,10 @@ bool HistoryWidget::showSendMessageError(
|
||||||
.text = &textWithTags,
|
.text = &textWithTags,
|
||||||
.ignoreSlowmodeCountdown = ignoreSlowmodeCountdown,
|
.ignoreSlowmodeCountdown = ignoreSlowmodeCountdown,
|
||||||
});
|
});
|
||||||
if (error.isEmpty()) {
|
if (!error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
controller()->showToast(error);
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6286,39 +6286,39 @@ int HistoryWidget::countAutomaticScrollTop() {
|
||||||
return ScrollMax;
|
return ScrollMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HistoryWidget::computeSendRestriction() const {
|
Data::SendError HistoryWidget::computeSendRestriction() const {
|
||||||
if (const auto user = _peer ? _peer->asUser() : nullptr) {
|
|
||||||
if (user->meRequiresPremiumToWrite()
|
|
||||||
&& !user->session().premium()) {
|
|
||||||
return u"premium_required"_q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto allWithoutPolls = Data::AllSendRestrictions()
|
const auto allWithoutPolls = Data::AllSendRestrictions()
|
||||||
& ~ChatRestriction::SendPolls;
|
& ~ChatRestriction::SendPolls;
|
||||||
const auto error = (_peer && !Data::CanSendAnyOf(_peer, allWithoutPolls))
|
return (_peer && !Data::CanSendAnyOf(_peer, allWithoutPolls))
|
||||||
? Data::RestrictionError(_peer, ChatRestriction::SendOther)
|
? Data::RestrictionError(_peer, ChatRestriction::SendOther)
|
||||||
: std::nullopt;
|
: Data::SendError();
|
||||||
return error ? (u"restriction:"_q + *error) : QString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::updateSendRestriction() {
|
void HistoryWidget::updateSendRestriction() {
|
||||||
const auto restriction = computeSendRestriction();
|
const auto restriction = computeSendRestriction();
|
||||||
if (_sendRestrictionKey == restriction) {
|
if (_sendRestrictionKey == restriction.text) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_sendRestrictionKey = restriction;
|
_sendRestrictionKey = restriction.text;
|
||||||
if (restriction.isEmpty()) {
|
if (!restriction) {
|
||||||
_sendRestriction = nullptr;
|
_sendRestriction = nullptr;
|
||||||
} else if (restriction == u"premium_required"_q) {
|
} else if (restriction.premiumToLift) {
|
||||||
_sendRestriction = PremiumRequiredSendRestriction(
|
_sendRestriction = PremiumRequiredSendRestriction(
|
||||||
this,
|
this,
|
||||||
_peer->asUser(),
|
_peer->asUser(),
|
||||||
controller());
|
controller());
|
||||||
} else if (restriction.startsWith(u"restriction:"_q)) {
|
} else if (const auto lifting = restriction.boostsToLift) {
|
||||||
const auto error = restriction.mid(12);
|
auto button = base::make_unique_q<Ui::FlatButton>(
|
||||||
_sendRestriction = TextErrorSendRestriction(this, error);
|
this,
|
||||||
|
restriction.text,
|
||||||
|
st::historyComposeButton);
|
||||||
|
const auto channel = _peer->asChannel();
|
||||||
|
button->setClickedCallback([=] {
|
||||||
|
controller()->resolveBoostState(channel, lifting);
|
||||||
|
});
|
||||||
|
_sendRestriction = std::move(button);
|
||||||
} else {
|
} else {
|
||||||
Unexpected("Restriction type.");
|
_sendRestriction = TextErrorSendRestriction(this, restriction.text);
|
||||||
}
|
}
|
||||||
if (_sendRestriction) {
|
if (_sendRestriction) {
|
||||||
_sendRestriction->show();
|
_sendRestriction->show();
|
||||||
|
@ -7130,9 +7130,8 @@ void HistoryWidget::sendInlineResult(InlineBots::ResultSelected result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto errorText = result.result->getErrorOnSend(_history);
|
if (const auto error = result.result->getErrorOnSend(_history)) {
|
||||||
if (!errorText.isEmpty()) {
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
controller()->showToast(errorText);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7774,9 +7773,9 @@ bool HistoryWidget::sendExistingDocument(
|
||||||
std::optional<MsgId> localId) {
|
std::optional<MsgId> localId) {
|
||||||
const auto error = _peer
|
const auto error = _peer
|
||||||
? Data::RestrictionError(_peer, ChatRestriction::SendStickers)
|
? Data::RestrictionError(_peer, ChatRestriction::SendStickers)
|
||||||
: std::nullopt;
|
: Data::SendError();
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (!_peer
|
} else if (!_peer
|
||||||
|| !_canSendMessages
|
|| !_canSendMessages
|
||||||
|
@ -7811,9 +7810,9 @@ bool HistoryWidget::sendExistingPhoto(
|
||||||
Api::SendOptions options) {
|
Api::SendOptions options) {
|
||||||
const auto error = _peer
|
const auto error = _peer
|
||||||
? Data::RestrictionError(_peer, ChatRestriction::SendPhotos)
|
? Data::RestrictionError(_peer, ChatRestriction::SendPhotos)
|
||||||
: std::nullopt;
|
: Data::SendError();
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (!_peer || !_canSendMessages) {
|
} else if (!_peer || !_canSendMessages) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -29,6 +29,7 @@ class Error;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class PhotoMedia;
|
class PhotoMedia;
|
||||||
|
struct SendError;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace SendMenu {
|
namespace SendMenu {
|
||||||
|
@ -579,7 +580,7 @@ private:
|
||||||
void addMessagesToBack(not_null<PeerData*> peer, const QVector<MTPMessage> &messages);
|
void addMessagesToBack(not_null<PeerData*> peer, const QVector<MTPMessage> &messages);
|
||||||
|
|
||||||
void updateSendRestriction();
|
void updateSendRestriction();
|
||||||
[[nodiscard]] QString computeSendRestriction() const;
|
[[nodiscard]] Data::SendError computeSendRestriction() const;
|
||||||
void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
|
void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
|
||||||
void updateListSize();
|
void updateListSize();
|
||||||
void startItemRevealAnimations();
|
void startItemRevealAnimations();
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct WriteRestriction {
|
||||||
QString text;
|
QString text;
|
||||||
QString button;
|
QString button;
|
||||||
Type type = Type::None;
|
Type type = Type::None;
|
||||||
|
int boostsToLift = false;
|
||||||
|
|
||||||
[[nodiscard]] bool empty() const {
|
[[nodiscard]] bool empty() const {
|
||||||
return (type == Type::None);
|
return (type == Type::None);
|
||||||
|
|
|
@ -2222,7 +2222,7 @@ void SetupRestrictionView(
|
||||||
not_null<Ui::RpWidget*> widget,
|
not_null<Ui::RpWidget*> widget,
|
||||||
not_null<const style::ComposeControls*> st,
|
not_null<const style::ComposeControls*> st,
|
||||||
std::shared_ptr<ChatHelpers::Show> show,
|
std::shared_ptr<ChatHelpers::Show> show,
|
||||||
const QString &name,
|
not_null<PeerData*> peer,
|
||||||
rpl::producer<Controls::WriteRestriction> restriction,
|
rpl::producer<Controls::WriteRestriction> restriction,
|
||||||
Fn<void(QPainter &p, QRect clip)> paintBackground) {
|
Fn<void(QPainter &p, QRect clip)> paintBackground) {
|
||||||
struct State {
|
struct State {
|
||||||
|
@ -2234,7 +2234,9 @@ void SetupRestrictionView(
|
||||||
};
|
};
|
||||||
const auto state = widget->lifetime().make_state<State>();
|
const auto state = widget->lifetime().make_state<State>();
|
||||||
state->updateGeometries = [=] {
|
state->updateGeometries = [=] {
|
||||||
if (!state->label) {
|
if (!state->label && state->button) {
|
||||||
|
state->button->setGeometry(widget->rect());
|
||||||
|
} else if (!state->label) {
|
||||||
return;
|
return;
|
||||||
} else if (state->button) {
|
} else if (state->button) {
|
||||||
const auto available = widget->width()
|
const auto available = widget->width()
|
||||||
|
@ -2307,14 +2309,24 @@ void SetupRestrictionView(
|
||||||
) | rpl::distinct_until_changed(
|
) | rpl::distinct_until_changed(
|
||||||
) | rpl::start_with_next([=](Controls::WriteRestriction value) {
|
) | rpl::start_with_next([=](Controls::WriteRestriction value) {
|
||||||
using Type = Controls::WriteRestriction::Type;
|
using Type = Controls::WriteRestriction::Type;
|
||||||
if (value.type == Type::Rights) {
|
if (const auto lifting = value.boostsToLift) {
|
||||||
|
state->button = std::make_unique<Ui::FlatButton>(
|
||||||
|
widget,
|
||||||
|
tr::lng_restricted_boost_group(tr::now),
|
||||||
|
st::historyComposeButton);
|
||||||
|
state->button->setClickedCallback([=] {
|
||||||
|
const auto window = show->resolveWindow(
|
||||||
|
ChatHelpers::WindowUsage::PremiumPromo);
|
||||||
|
window->resolveBoostState(peer->asChannel(), lifting);
|
||||||
|
});
|
||||||
|
} else if (value.type == Type::Rights) {
|
||||||
state->icon = nullptr;
|
state->icon = nullptr;
|
||||||
state->unlock = nullptr;
|
state->unlock = nullptr;
|
||||||
state->button = nullptr;
|
state->button = nullptr;
|
||||||
state->label = makeLabel(value.text, st->restrictionLabel);
|
state->label = makeLabel(value.text, st->restrictionLabel);
|
||||||
} else if (value.type == Type::PremiumRequired) {
|
} else if (value.type == Type::PremiumRequired) {
|
||||||
state->icon = makeIcon();
|
state->icon = makeIcon();
|
||||||
state->unlock = makeUnlock(value.button, name);
|
state->unlock = makeUnlock(value.button, peer->shortName());
|
||||||
state->button = std::make_unique<Ui::AbstractButton>(widget);
|
state->button = std::make_unique<Ui::AbstractButton>(widget);
|
||||||
state->button->setClickedCallback([=] {
|
state->button->setClickedCallback([=] {
|
||||||
::Settings::ShowPremiumPromoToast(
|
::Settings::ShowPremiumPromoToast(
|
||||||
|
@ -2322,7 +2334,7 @@ void SetupRestrictionView(
|
||||||
tr::lng_send_non_premium_message_toast(
|
tr::lng_send_non_premium_message_toast(
|
||||||
tr::now,
|
tr::now,
|
||||||
lt_user,
|
lt_user,
|
||||||
TextWithEntities{ name },
|
TextWithEntities{ peer->shortName() },
|
||||||
lt_link,
|
lt_link,
|
||||||
Ui::Text::Link(
|
Ui::Text::Link(
|
||||||
Ui::Text::Bold(
|
Ui::Text::Bold(
|
||||||
|
@ -2373,7 +2385,7 @@ void ComposeControls::initWriteRestriction() {
|
||||||
_writeRestricted.get(),
|
_writeRestricted.get(),
|
||||||
&_st,
|
&_st,
|
||||||
_show,
|
_show,
|
||||||
_history->peer->shortName(),
|
_history->peer,
|
||||||
_writeRestriction.value(),
|
_writeRestriction.value(),
|
||||||
background);
|
background);
|
||||||
|
|
||||||
|
@ -2405,7 +2417,7 @@ void ComposeControls::initVoiceRecordBar() {
|
||||||
}, _wrap->lifetime());
|
}, _wrap->lifetime());
|
||||||
|
|
||||||
_voiceRecordBar->setStartRecordingFilter([=] {
|
_voiceRecordBar->setStartRecordingFilter([=] {
|
||||||
const auto error = [&]() -> std::optional<QString> {
|
const auto error = [&]() -> Data::SendError {
|
||||||
const auto peer = _history ? _history->peer.get() : nullptr;
|
const auto peer = _history ? _history->peer.get() : nullptr;
|
||||||
if (peer) {
|
if (peer) {
|
||||||
if (const auto error = Data::RestrictionError(
|
if (const auto error = Data::RestrictionError(
|
||||||
|
@ -2414,10 +2426,10 @@ void ComposeControls::initVoiceRecordBar() {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return {};
|
||||||
}();
|
}();
|
||||||
if (error) {
|
if (error) {
|
||||||
_show->showToast(*error);
|
Data::ShowSendErrorToast(_show, _history->peer, error);
|
||||||
return true;
|
return true;
|
||||||
} else if (_showSlowmodeError && _showSlowmodeError()) {
|
} else if (_showSlowmodeError && _showSlowmodeError()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_drag_area.h"
|
#include "history/history_drag_area.h"
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/history_view_swipe.h"
|
#include "history/history_view_swipe.h"
|
||||||
#include "ui/chat/pinned_bar.h"
|
#include "ui/chat/pinned_bar.h"
|
||||||
#include "ui/chat/chat_style.h"
|
#include "ui/chat/chat_style.h"
|
||||||
|
@ -661,7 +661,7 @@ void RepliesWidget::setupComposeControls() {
|
||||||
? _topic
|
? _topic
|
||||||
: _history->peer->forumTopicFor(_rootId);
|
: _history->peer->forumTopicFor(_rootId);
|
||||||
return (!topic || topic->canToggleClosed() || !topic->closed())
|
return (!topic || topic->canToggleClosed() || !topic->closed())
|
||||||
? std::optional<QString>()
|
? Data::SendError()
|
||||||
: tr::lng_forum_topic_closed(tr::now);
|
: tr::lng_forum_topic_closed(tr::now);
|
||||||
});
|
});
|
||||||
auto writeRestriction = rpl::combine(
|
auto writeRestriction = rpl::combine(
|
||||||
|
@ -670,7 +670,7 @@ void RepliesWidget::setupComposeControls() {
|
||||||
Data::PeerUpdate::Flag::Rights),
|
Data::PeerUpdate::Flag::Rights),
|
||||||
Data::CanSendAnythingValue(_history->peer),
|
Data::CanSendAnythingValue(_history->peer),
|
||||||
std::move(topicWriteRestrictions)
|
std::move(topicWriteRestrictions)
|
||||||
) | rpl::map([=](auto, auto, std::optional<QString> topicRestriction) {
|
) | rpl::map([=](auto, auto, Data::SendError topicRestriction) {
|
||||||
const auto allWithoutPolls = Data::AllSendRestrictions()
|
const auto allWithoutPolls = Data::AllSendRestrictions()
|
||||||
& ~ChatRestriction::SendPolls;
|
& ~ChatRestriction::SendPolls;
|
||||||
const auto canSendAnything = _topic
|
const auto canSendAnything = _topic
|
||||||
|
@ -687,10 +687,11 @@ void RepliesWidget::setupComposeControls() {
|
||||||
: tr::lng_group_not_accessible(tr::now))
|
: tr::lng_group_not_accessible(tr::now))
|
||||||
: topicRestriction
|
: topicRestriction
|
||||||
? std::move(topicRestriction)
|
? std::move(topicRestriction)
|
||||||
: std::optional<QString>();
|
: Data::SendError();
|
||||||
return text ? Controls::WriteRestriction{
|
return text ? Controls::WriteRestriction{
|
||||||
.text = std::move(*text),
|
.text = std::move(*text),
|
||||||
.type = Controls::WriteRestrictionType::Rights,
|
.type = Controls::WriteRestrictionType::Rights,
|
||||||
|
.boostsToLift = text.boostsToLift,
|
||||||
} : Controls::WriteRestriction();
|
} : Controls::WriteRestriction();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -936,7 +937,7 @@ void RepliesWidget::chooseAttach(
|
||||||
std::optional<bool> overrideSendImagesAsPhotos) {
|
std::optional<bool> overrideSendImagesAsPhotos) {
|
||||||
_choosingAttach = false;
|
_choosingAttach = false;
|
||||||
if (const auto error = Data::AnyFileRestrictionError(_history->peer)) {
|
if (const auto error = Data::AnyFileRestrictionError(_history->peer)) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return;
|
return;
|
||||||
} else if (showSlowmodeError()) {
|
} else if (showSlowmodeError()) {
|
||||||
return;
|
return;
|
||||||
|
@ -1168,11 +1169,11 @@ bool RepliesWidget::showSendingFilesError(
|
||||||
bool RepliesWidget::showSendingFilesError(
|
bool RepliesWidget::showSendingFilesError(
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress) const {
|
std::optional<bool> compress) const {
|
||||||
const auto text = [&] {
|
const auto error = [&]() -> Data::SendError {
|
||||||
const auto peer = _history->peer;
|
const auto peer = _history->peer;
|
||||||
const auto error = Data::FileRestrictionError(peer, list, compress);
|
const auto error = Data::FileRestrictionError(peer, list, compress);
|
||||||
if (error) {
|
if (error) {
|
||||||
return *error;
|
return error;
|
||||||
} else if (const auto left = _history->peer->slowmodeSecondsLeft()) {
|
} else if (const auto left = _history->peer->slowmodeSecondsLeft()) {
|
||||||
return tr::lng_slowmode_enabled(
|
return tr::lng_slowmode_enabled(
|
||||||
tr::now,
|
tr::now,
|
||||||
|
@ -1192,16 +1193,16 @@ bool RepliesWidget::showSendingFilesError(
|
||||||
}
|
}
|
||||||
return tr::lng_forward_send_files_cant(tr::now);
|
return tr::lng_forward_send_files_cant(tr::now);
|
||||||
}();
|
}();
|
||||||
if (text.isEmpty()) {
|
if (!error) {
|
||||||
return false;
|
return false;
|
||||||
} else if (text == u"(toolarge)"_q) {
|
} else if (error.text == u"(toolarge)"_q) {
|
||||||
const auto fileSize = list.files.back().size;
|
const auto fileSize = list.files.back().size;
|
||||||
controller()->show(
|
controller()->show(
|
||||||
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
|
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller()->showToast(text);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,7 +1248,7 @@ void RepliesWidget::send(Api::SendOptions options) {
|
||||||
message.textWithTags = _composeControls->getTextWithAppliedMarkdown();
|
message.textWithTags = _composeControls->getTextWithAppliedMarkdown();
|
||||||
message.webPage = _composeControls->webPageDraft();
|
message.webPage = _composeControls->webPageDraft();
|
||||||
|
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
{
|
{
|
||||||
.topicRootId = _topic ? _topic->rootId() : MsgId(0),
|
.topicRootId = _topic ? _topic->rootId() : MsgId(0),
|
||||||
|
@ -1255,8 +1256,8 @@ void RepliesWidget::send(Api::SendOptions options) {
|
||||||
.text = &message.textWithTags,
|
.text = &message.textWithTags,
|
||||||
.ignoreSlowmodeCountdown = (options.scheduled != 0),
|
.ignoreSlowmodeCountdown = (options.scheduled != 0),
|
||||||
});
|
});
|
||||||
if (!error.isEmpty()) {
|
if (error) {
|
||||||
controller()->showToast(error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1407,7 +1408,7 @@ bool RepliesWidget::sendExistingDocument(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendStickers);
|
ChatRestriction::SendStickers);
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (showSlowmodeError()
|
} else if (showSlowmodeError()
|
||||||
|| ShowSendPremiumError(controller(), document)) {
|
|| ShowSendPremiumError(controller(), document)) {
|
||||||
|
@ -1435,7 +1436,7 @@ bool RepliesWidget::sendExistingPhoto(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendPhotos);
|
ChatRestriction::SendPhotos);
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (showSlowmodeError()) {
|
} else if (showSlowmodeError()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1453,9 +1454,8 @@ bool RepliesWidget::sendExistingPhoto(
|
||||||
void RepliesWidget::sendInlineResult(
|
void RepliesWidget::sendInlineResult(
|
||||||
not_null<InlineBots::Result*> result,
|
not_null<InlineBots::Result*> result,
|
||||||
not_null<UserData*> bot) {
|
not_null<UserData*> bot) {
|
||||||
const auto errorText = result->getErrorOnSend(_history);
|
if (const auto error = result->getErrorOnSend(_history)) {
|
||||||
if (!errorText.isEmpty()) {
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
controller()->showToast(errorText);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendInlineResult(result, bot, {}, std::nullopt);
|
sendInlineResult(result, bot, {}, std::nullopt);
|
||||||
|
|
|
@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/history_view_sticker_toast.h"
|
#include "history/view/history_view_sticker_toast.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_drag_area.h"
|
#include "history/history_drag_area.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "menu/menu_send.h" // SendMenu::Type.
|
#include "menu/menu_send.h" // SendMenu::Type.
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
|
@ -252,83 +252,85 @@ ScheduledWidget::~ScheduledWidget() = default;
|
||||||
void ScheduledWidget::setupComposeControls() {
|
void ScheduledWidget::setupComposeControls() {
|
||||||
auto writeRestriction = _forumTopic
|
auto writeRestriction = _forumTopic
|
||||||
? [&] {
|
? [&] {
|
||||||
auto topicWriteRestrictions = rpl::single(
|
auto topicWriteRestrictions = rpl::single(
|
||||||
) | rpl::then(session().changes().topicUpdates(
|
) | rpl::then(session().changes().topicUpdates(
|
||||||
Data::TopicUpdate::Flag::Closed
|
Data::TopicUpdate::Flag::Closed
|
||||||
) | rpl::filter([=](const Data::TopicUpdate &update) {
|
) | rpl::filter([=](const Data::TopicUpdate &update) {
|
||||||
return (update.topic->history() == _history)
|
return (update.topic->history() == _history)
|
||||||
&& (update.topic->rootId() == _forumTopic->rootId());
|
&& (update.topic->rootId() == _forumTopic->rootId());
|
||||||
}) | rpl::to_empty) | rpl::map([=] {
|
}) | rpl::to_empty) | rpl::map([=] {
|
||||||
return (!_forumTopic
|
return (!_forumTopic
|
||||||
|| _forumTopic->canToggleClosed()
|
|| _forumTopic->canToggleClosed()
|
||||||
|| !_forumTopic->closed())
|
|| !_forumTopic->closed())
|
||||||
? std::optional<QString>()
|
? Data::SendError()
|
||||||
: tr::lng_forum_topic_closed(tr::now);
|
: tr::lng_forum_topic_closed(tr::now);
|
||||||
});
|
});
|
||||||
return rpl::combine(
|
return rpl::combine(
|
||||||
session().changes().peerFlagsValue(
|
session().changes().peerFlagsValue(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
Data::PeerUpdate::Flag::Rights),
|
Data::PeerUpdate::Flag::Rights),
|
||||||
Data::CanSendAnythingValue(_history->peer),
|
Data::CanSendAnythingValue(_history->peer),
|
||||||
std::move(topicWriteRestrictions)
|
std::move(topicWriteRestrictions)
|
||||||
) | rpl::map([=](
|
) | rpl::map([=](
|
||||||
auto,
|
auto,
|
||||||
auto,
|
auto,
|
||||||
std::optional<QString> topicRestriction) {
|
Data::SendError topicRestriction) {
|
||||||
const auto allWithoutPolls = Data::AllSendRestrictions()
|
const auto allWithoutPolls = Data::AllSendRestrictions()
|
||||||
& ~ChatRestriction::SendPolls;
|
& ~ChatRestriction::SendPolls;
|
||||||
const auto canSendAnything = Data::CanSendAnyOf(
|
const auto canSendAnything = Data::CanSendAnyOf(
|
||||||
_forumTopic,
|
_forumTopic,
|
||||||
allWithoutPolls);
|
allWithoutPolls);
|
||||||
const auto restriction = Data::RestrictionError(
|
const auto restriction = Data::RestrictionError(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendOther);
|
ChatRestriction::SendOther);
|
||||||
auto text = !canSendAnything
|
auto text = !canSendAnything
|
||||||
? (restriction
|
? (restriction
|
||||||
? restriction
|
? restriction
|
||||||
|
: topicRestriction
|
||||||
|
? std::move(topicRestriction)
|
||||||
|
: tr::lng_group_not_accessible(tr::now))
|
||||||
: topicRestriction
|
: topicRestriction
|
||||||
? std::move(topicRestriction)
|
? std::move(topicRestriction)
|
||||||
: tr::lng_group_not_accessible(tr::now))
|
: Data::SendError();
|
||||||
: topicRestriction
|
return text ? Controls::WriteRestriction{
|
||||||
? std::move(topicRestriction)
|
.text = std::move(*text),
|
||||||
: std::optional<QString>();
|
.type = Controls::WriteRestrictionType::Rights,
|
||||||
return text ? Controls::WriteRestriction{
|
.boostsToLift = text.boostsToLift,
|
||||||
.text = std::move(*text),
|
} : Controls::WriteRestriction();
|
||||||
.type = Controls::WriteRestrictionType::Rights,
|
}) | rpl::type_erased();
|
||||||
} : Controls::WriteRestriction();
|
}()
|
||||||
}) | rpl::type_erased();
|
|
||||||
}()
|
|
||||||
: [&] {
|
: [&] {
|
||||||
return rpl::combine(
|
return rpl::combine(
|
||||||
session().changes().peerFlagsValue(
|
session().changes().peerFlagsValue(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
Data::PeerUpdate::Flag::Rights),
|
Data::PeerUpdate::Flag::Rights),
|
||||||
Data::CanSendAnythingValue(_history->peer)
|
Data::CanSendAnythingValue(_history->peer)
|
||||||
) | rpl::map([=] {
|
) | rpl::map([=] {
|
||||||
const auto allWithoutPolls = Data::AllSendRestrictions()
|
const auto allWithoutPolls = Data::AllSendRestrictions()
|
||||||
& ~ChatRestriction::SendPolls;
|
& ~ChatRestriction::SendPolls;
|
||||||
const auto canSendAnything = Data::CanSendAnyOf(
|
const auto canSendAnything = Data::CanSendAnyOf(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
allWithoutPolls,
|
allWithoutPolls,
|
||||||
false);
|
false);
|
||||||
const auto restriction = Data::RestrictionError(
|
const auto restriction = Data::RestrictionError(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendOther);
|
ChatRestriction::SendOther);
|
||||||
auto text = !canSendAnything
|
auto text = !canSendAnything
|
||||||
? (restriction
|
? (restriction
|
||||||
? restriction
|
? restriction
|
||||||
: tr::lng_group_not_accessible(tr::now))
|
: tr::lng_group_not_accessible(tr::now))
|
||||||
: std::optional<QString>();
|
: Data::SendError();
|
||||||
return text ? Controls::WriteRestriction{
|
return text ? Controls::WriteRestriction{
|
||||||
.text = std::move(*text),
|
.text = std::move(*text),
|
||||||
.type = Controls::WriteRestrictionType::Rights,
|
.type = Controls::WriteRestrictionType::Rights,
|
||||||
} : Controls::WriteRestriction();
|
.boostsToLift = text.boostsToLift,
|
||||||
}) | rpl::type_erased();
|
} : Controls::WriteRestriction();
|
||||||
}();
|
}) | rpl::type_erased();
|
||||||
|
}();
|
||||||
_composeControls->setHistory({
|
_composeControls->setHistory({
|
||||||
.history = _history.get(),
|
.history = _history.get(),
|
||||||
.writeRestriction = std::move(writeRestriction),
|
.writeRestriction = std::move(writeRestriction),
|
||||||
});
|
});
|
||||||
|
|
||||||
_composeControls->height(
|
_composeControls->height(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
|
@ -463,7 +465,7 @@ void ScheduledWidget::setupComposeControls() {
|
||||||
|
|
||||||
void ScheduledWidget::chooseAttach() {
|
void ScheduledWidget::chooseAttach() {
|
||||||
if (const auto error = Data::AnyFileRestrictionError(_history->peer)) {
|
if (const auto error = Data::AnyFileRestrictionError(_history->peer)) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,12 +669,12 @@ bool ScheduledWidget::showSendingFilesError(
|
||||||
bool ScheduledWidget::showSendingFilesError(
|
bool ScheduledWidget::showSendingFilesError(
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress) const {
|
std::optional<bool> compress) const {
|
||||||
const auto text = [&] {
|
const auto error = [&]() -> Data::SendError {
|
||||||
using Error = Ui::PreparedList::Error;
|
using Error = Ui::PreparedList::Error;
|
||||||
const auto peer = _history->peer;
|
const auto peer = _history->peer;
|
||||||
const auto error = Data::FileRestrictionError(peer, list, compress);
|
const auto error = Data::FileRestrictionError(peer, list, compress);
|
||||||
if (error) {
|
if (error) {
|
||||||
return *error;
|
return error;
|
||||||
} else switch (list.error) {
|
} else switch (list.error) {
|
||||||
case Error::None: return QString();
|
case Error::None: return QString();
|
||||||
case Error::EmptyFile:
|
case Error::EmptyFile:
|
||||||
|
@ -685,16 +687,16 @@ bool ScheduledWidget::showSendingFilesError(
|
||||||
}
|
}
|
||||||
return tr::lng_forward_send_files_cant(tr::now);
|
return tr::lng_forward_send_files_cant(tr::now);
|
||||||
}();
|
}();
|
||||||
if (text.isEmpty()) {
|
if (!error) {
|
||||||
return false;
|
return false;
|
||||||
} else if (text == u"(toolarge)"_q) {
|
} else if (error.text == u"(toolarge)"_q) {
|
||||||
const auto fileSize = list.files.back().size;
|
const auto fileSize = list.files.back().size;
|
||||||
controller()->show(
|
controller()->show(
|
||||||
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
|
Box(FileSizeLimitBox, &session(), fileSize, nullptr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller()->showToast(text);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,7 +719,7 @@ void ScheduledWidget::send() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
{
|
{
|
||||||
.topicRootId = _forumTopic
|
.topicRootId = _forumTopic
|
||||||
|
@ -729,8 +731,8 @@ void ScheduledWidget::send() {
|
||||||
.text = &textWithTags,
|
.text = &textWithTags,
|
||||||
.ignoreSlowmodeCountdown = true,
|
.ignoreSlowmodeCountdown = true,
|
||||||
});
|
});
|
||||||
if (!error.isEmpty()) {
|
if (error) {
|
||||||
controller()->showToast(error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto callback = [=](Api::SendOptions options) { send(options); };
|
const auto callback = [=](Api::SendOptions options) { send(options); };
|
||||||
|
@ -865,7 +867,7 @@ bool ScheduledWidget::sendExistingDocument(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendStickers);
|
ChatRestriction::SendStickers);
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (ShowSendPremiumError(controller(), document)) {
|
} else if (ShowSendPremiumError(controller(), document)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -893,7 +895,7 @@ bool ScheduledWidget::sendExistingPhoto(
|
||||||
_history->peer,
|
_history->peer,
|
||||||
ChatRestriction::SendPhotos);
|
ChatRestriction::SendPhotos);
|
||||||
if (error) {
|
if (error) {
|
||||||
controller()->showToast(*error);
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,9 +911,8 @@ bool ScheduledWidget::sendExistingPhoto(
|
||||||
void ScheduledWidget::sendInlineResult(
|
void ScheduledWidget::sendInlineResult(
|
||||||
not_null<InlineBots::Result*> result,
|
not_null<InlineBots::Result*> result,
|
||||||
not_null<UserData*> bot) {
|
not_null<UserData*> bot) {
|
||||||
const auto errorText = result->getErrorOnSend(_history);
|
if (const auto error = result->getErrorOnSend(_history)) {
|
||||||
if (!errorText.isEmpty()) {
|
Data::ShowSendErrorToast(controller(), _history->peer, error);
|
||||||
controller()->showToast(errorText);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto callback = [=](Api::SendOptions options) {
|
const auto callback = [=](Api::SendOptions options) {
|
||||||
|
|
|
@ -394,13 +394,9 @@ not_null<HistoryItem*> Result::makeMessage(
|
||||||
return sendData->makeMessage(this, history, std::move(fields));
|
return sendData->makeMessage(this, history, std::move(fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Result::getErrorOnSend(not_null<History*> history) const {
|
Data::SendError Result::getErrorOnSend(not_null<History*> history) const {
|
||||||
const auto specific = sendData->getErrorOnSend(this, history);
|
return sendData->getErrorOnSend(this, history).value_or(
|
||||||
return !specific.isEmpty()
|
Data::RestrictionError(history->peer, ChatRestriction::SendInline));
|
||||||
? specific
|
|
||||||
: Data::RestrictionError(
|
|
||||||
history->peer,
|
|
||||||
ChatRestriction::SendInline).value_or(QString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Data::LocationPoint> Result::getLocationPoint() const {
|
std::optional<Data::LocationPoint> Result::getLocationPoint() const {
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct HistoryItemCommonFields;
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
class LocationPoint;
|
class LocationPoint;
|
||||||
|
struct SendError;
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
||||||
namespace InlineBots {
|
namespace InlineBots {
|
||||||
|
@ -69,7 +70,8 @@ public:
|
||||||
[[nodiscard]] not_null<HistoryItem*> makeMessage(
|
[[nodiscard]] not_null<HistoryItem*> makeMessage(
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const;
|
HistoryItemCommonFields &&fields) const;
|
||||||
QString getErrorOnSend(not_null<History*> history) const;
|
[[nodiscard]] Data::SendError getErrorOnSend(
|
||||||
|
not_null<History*> history) const;
|
||||||
|
|
||||||
// interface for Layout:: usage
|
// interface for Layout:: usage
|
||||||
std::optional<Data::LocationPoint> getLocationPoint() const;
|
std::optional<Data::LocationPoint> getLocationPoint() const;
|
||||||
|
|
|
@ -42,11 +42,11 @@ not_null<HistoryItem*> SendDataCommon::makeMessage(
|
||||||
std::move(distinct.media));
|
std::move(distinct.media));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendDataCommon::getErrorOnSend(
|
Data::SendError SendDataCommon::getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const {
|
not_null<History*> history) const {
|
||||||
const auto type = ChatRestriction::SendOther;
|
const auto type = ChatRestriction::SendOther;
|
||||||
return Data::RestrictionError(history->peer, type).value_or(QString());
|
return Data::RestrictionError(history->peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendDataCommon::SentMessageFields SendText::getSentMessageFields() const {
|
SendDataCommon::SentMessageFields SendText::getSentMessageFields() const {
|
||||||
|
@ -106,11 +106,11 @@ not_null<HistoryItem*> SendPhoto::makeMessage(
|
||||||
TextWithEntities{ _message, _entities });
|
TextWithEntities{ _message, _entities });
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendPhoto::getErrorOnSend(
|
Data::SendError SendPhoto::getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const {
|
not_null<History*> history) const {
|
||||||
const auto type = ChatRestriction::SendPhotos;
|
const auto type = ChatRestriction::SendPhotos;
|
||||||
return Data::RestrictionError(history->peer, type).value_or(QString());
|
return Data::RestrictionError(history->peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<HistoryItem*> SendFile::makeMessage(
|
not_null<HistoryItem*> SendFile::makeMessage(
|
||||||
|
@ -123,11 +123,11 @@ not_null<HistoryItem*> SendFile::makeMessage(
|
||||||
TextWithEntities{ _message, _entities });
|
TextWithEntities{ _message, _entities });
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendFile::getErrorOnSend(
|
Data::SendError SendFile::getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const {
|
not_null<History*> history) const {
|
||||||
const auto type = _document->requiredSendRight();
|
const auto type = _document->requiredSendRight();
|
||||||
return Data::RestrictionError(history->peer, type).value_or(QString());
|
return Data::RestrictionError(history->peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<HistoryItem*> SendGame::makeMessage(
|
not_null<HistoryItem*> SendGame::makeMessage(
|
||||||
|
@ -137,11 +137,11 @@ not_null<HistoryItem*> SendGame::makeMessage(
|
||||||
return history->makeMessage(std::move(fields), _game);
|
return history->makeMessage(std::move(fields), _game);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SendGame::getErrorOnSend(
|
Data::SendError SendGame::getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const {
|
not_null<History*> history) const {
|
||||||
const auto type = ChatRestriction::SendGames;
|
const auto type = ChatRestriction::SendGames;
|
||||||
return Data::RestrictionError(history->peer, type).value_or(QString());
|
return Data::RestrictionError(history->peer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendDataCommon::SentMessageFields SendInvoice::getSentMessageFields() const {
|
SendDataCommon::SentMessageFields SendInvoice::getSentMessageFields() const {
|
||||||
|
|
|
@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
struct HistoryItemCommonFields;
|
struct HistoryItemCommonFields;
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
struct SendError;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
} // namespace Main
|
} // namespace Main
|
||||||
|
@ -44,7 +48,7 @@ public:
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const = 0;
|
HistoryItemCommonFields &&fields) const = 0;
|
||||||
virtual QString getErrorOnSend(
|
virtual Data::SendError getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const = 0;
|
not_null<History*> history) const = 0;
|
||||||
|
|
||||||
|
@ -80,7 +84,7 @@ public:
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
|
||||||
QString getErrorOnSend(
|
Data::SendError getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const override;
|
not_null<History*> history) const override;
|
||||||
|
|
||||||
|
@ -241,7 +245,7 @@ public:
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
|
||||||
QString getErrorOnSend(
|
Data::SendError getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const override;
|
not_null<History*> history) const override;
|
||||||
|
|
||||||
|
@ -275,7 +279,7 @@ public:
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
|
||||||
QString getErrorOnSend(
|
Data::SendError getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const override;
|
not_null<History*> history) const override;
|
||||||
|
|
||||||
|
@ -303,7 +307,7 @@ public:
|
||||||
not_null<History*> history,
|
not_null<History*> history,
|
||||||
HistoryItemCommonFields &&fields) const override;
|
HistoryItemCommonFields &&fields) const override;
|
||||||
|
|
||||||
QString getErrorOnSend(
|
Data::SendError getErrorOnSend(
|
||||||
const Result *owner,
|
const Result *owner,
|
||||||
not_null<History*> history) const override;
|
not_null<History*> history) const override;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/popup_menu.h"
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
@ -113,19 +114,35 @@ void Inner::checkRestrictedPeer() {
|
||||||
const auto error = Data::RestrictionError(
|
const auto error = Data::RestrictionError(
|
||||||
_inlineQueryPeer,
|
_inlineQueryPeer,
|
||||||
ChatRestriction::SendInline);
|
ChatRestriction::SendInline);
|
||||||
if (error) {
|
const auto changed = (_restrictedLabelKey != error.text);
|
||||||
if (!_restrictedLabel) {
|
if (!changed) {
|
||||||
_restrictedLabel.create(this, *error, st::stickersRestrictedLabel);
|
|
||||||
_restrictedLabel->show();
|
|
||||||
_restrictedLabel->move(st::inlineResultsLeft - st::roundRadiusSmall, st::stickerPanPadding);
|
|
||||||
_restrictedLabel->resizeToNaturalWidth(width() - (st::inlineResultsLeft - st::roundRadiusSmall) * 2);
|
|
||||||
if (_switchPmButton) {
|
|
||||||
_switchPmButton->hide();
|
|
||||||
}
|
|
||||||
repaintItems();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_restrictedLabelKey = error.text;
|
||||||
|
if (error) {
|
||||||
|
const auto window = _controller;
|
||||||
|
const auto peer = _inlineQueryPeer;
|
||||||
|
_restrictedLabel.create(
|
||||||
|
this,
|
||||||
|
rpl::single(error.boostsToLift
|
||||||
|
? Ui::Text::Link(error.text)
|
||||||
|
: TextWithEntities{ error.text }),
|
||||||
|
st::stickersRestrictedLabel);
|
||||||
|
const auto lifting = error.boostsToLift;
|
||||||
|
_restrictedLabel->setClickHandlerFilter([=](auto...) {
|
||||||
|
window->resolveBoostState(peer->asChannel(), lifting);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
_restrictedLabel->show();
|
||||||
|
updateRestrictedLabelGeometry();
|
||||||
|
if (_switchPmButton) {
|
||||||
|
_switchPmButton->hide();
|
||||||
|
}
|
||||||
|
repaintItems();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_restrictedLabelKey = QString();
|
||||||
}
|
}
|
||||||
if (_restrictedLabel) {
|
if (_restrictedLabel) {
|
||||||
_restrictedLabel.destroy();
|
_restrictedLabel.destroy();
|
||||||
|
@ -136,6 +153,18 @@ void Inner::checkRestrictedPeer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inner::updateRestrictedLabelGeometry() {
|
||||||
|
if (!_restrictedLabel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto labelWidth = width() - st::stickerPanPadding * 2;
|
||||||
|
_restrictedLabel->resizeToWidth(labelWidth);
|
||||||
|
_restrictedLabel->moveToLeft(
|
||||||
|
(width() - _restrictedLabel->width()) / 2,
|
||||||
|
st::stickerPanPadding);
|
||||||
|
}
|
||||||
|
|
||||||
bool Inner::isRestrictedView() {
|
bool Inner::isRestrictedView() {
|
||||||
checkRestrictedPeer();
|
checkRestrictedPeer();
|
||||||
return (_restrictedLabel != nullptr);
|
return (_restrictedLabel != nullptr);
|
||||||
|
@ -178,6 +207,10 @@ rpl::producer<> Inner::inlineRowsCleared() const {
|
||||||
|
|
||||||
Inner::~Inner() = default;
|
Inner::~Inner() = default;
|
||||||
|
|
||||||
|
void Inner::resizeEvent(QResizeEvent *e) {
|
||||||
|
updateRestrictedLabelGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
void Inner::paintEvent(QPaintEvent *e) {
|
void Inner::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
QRect r = e ? e->rect() : rect();
|
QRect r = e ? e->rect() : rect();
|
||||||
|
|
|
@ -108,6 +108,7 @@ protected:
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void leaveEventHook(QEvent *e) override;
|
void leaveEventHook(QEvent *e) override;
|
||||||
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
void leaveToChildEvent(QEvent *e, QWidget *child) override;
|
||||||
|
@ -136,6 +137,7 @@ private:
|
||||||
void clearInlineRows(bool resultsDeleted);
|
void clearInlineRows(bool resultsDeleted);
|
||||||
ItemBase *layoutPrepareInlineResult(Result *result);
|
ItemBase *layoutPrepareInlineResult(Result *result);
|
||||||
|
|
||||||
|
void updateRestrictedLabelGeometry();
|
||||||
void deleteUnusedInlineLayouts();
|
void deleteUnusedInlineLayouts();
|
||||||
|
|
||||||
int validateExistingInlineRows(const Results &results);
|
int validateExistingInlineRows(const Results &results);
|
||||||
|
@ -162,6 +164,7 @@ private:
|
||||||
QByteArray _switchPmUrl;
|
QByteArray _switchPmUrl;
|
||||||
|
|
||||||
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
||||||
|
QString _restrictedLabelKey;
|
||||||
|
|
||||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "dialogs/dialogs_widget.h"
|
#include "dialogs/dialogs_widget.h"
|
||||||
#include "history/history_widget.h"
|
#include "history/history_widget.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/view/media/history_view_media.h"
|
#include "history/view/media/history_view_media.h"
|
||||||
#include "history/view/history_view_service_message.h"
|
#include "history/view/history_view_service_message.h"
|
||||||
#include "history/view/history_view_sublist_section.h"
|
#include "history/view/history_view_sublist_section.h"
|
||||||
|
@ -556,15 +556,15 @@ bool MainWidget::setForwardDraft(
|
||||||
const auto history = thread->owningHistory();
|
const auto history = thread->owningHistory();
|
||||||
const auto items = session().data().idsToItems(draft.ids);
|
const auto items = session().data().idsToItems(draft.ids);
|
||||||
const auto topicRootId = thread->topicRootId();
|
const auto topicRootId = thread->topicRootId();
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
history->peer,
|
history->peer,
|
||||||
{
|
{
|
||||||
.topicRootId = topicRootId,
|
.topicRootId = topicRootId,
|
||||||
.forward = &items,
|
.forward = &items,
|
||||||
.ignoreSlowmodeCountdown = true,
|
.ignoreSlowmodeCountdown = true,
|
||||||
});
|
});
|
||||||
if (!error.isEmpty()) {
|
if (error) {
|
||||||
_controller->show(Ui::MakeInformBox(error));
|
Data::ShowSendErrorToast(_controller, history->peer, error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,12 +611,12 @@ bool MainWidget::sendPaths(
|
||||||
not_null<Data::Thread*> thread,
|
not_null<Data::Thread*> thread,
|
||||||
const QStringList &paths) {
|
const QStringList &paths) {
|
||||||
if (!Data::CanSendAnyOf(thread, Data::FilesSendRestrictions())) {
|
if (!Data::CanSendAnyOf(thread, Data::FilesSendRestrictions())) {
|
||||||
_controller->show(Ui::MakeInformBox(
|
_controller->showToast(
|
||||||
tr::lng_forward_send_files_cant()));
|
tr::lng_forward_send_files_cant(tr::now));
|
||||||
return false;
|
return false;
|
||||||
} else if (const auto error = Data::AnyFileRestrictionError(
|
} else if (const auto error = Data::AnyFileRestrictionError(
|
||||||
thread->peer())) {
|
thread->peer())) {
|
||||||
_controller->show(Ui::MakeInformBox(*error));
|
Data::ShowSendErrorToast(controller(), thread->peer(), error);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
_controller->showThread(
|
_controller->showThread(
|
||||||
|
@ -659,12 +659,12 @@ bool MainWidget::filesOrForwardDrop(
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if (!Data::CanSendAnyOf(thread, Data::FilesSendRestrictions())) {
|
} else if (!Data::CanSendAnyOf(thread, Data::FilesSendRestrictions())) {
|
||||||
_controller->show(Ui::MakeInformBox(
|
_controller->showToast(
|
||||||
tr::lng_forward_send_files_cant()));
|
tr::lng_forward_send_files_cant(tr::now));
|
||||||
return false;
|
return false;
|
||||||
} else if (const auto error = Data::AnyFileRestrictionError(
|
} else if (const auto error = Data::AnyFileRestrictionError(
|
||||||
thread->peer())) {
|
thread->peer())) {
|
||||||
_controller->show(Ui::MakeInformBox(*error));
|
Data::ShowSendErrorToast(_controller, thread->peer(), error);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
_controller->showThread(
|
_controller->showThread(
|
||||||
|
|
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "core/file_utilities.h"
|
#include "core/file_utilities.h"
|
||||||
#include "core/mime_type.h"
|
#include "core/mime_type.h"
|
||||||
#include "data/stickers/data_custom_emoji.h"
|
#include "data/stickers/data_custom_emoji.h"
|
||||||
|
#include "data/data_chat_participant_status.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_message_reaction_id.h"
|
#include "data/data_message_reaction_id.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
|
@ -219,15 +220,15 @@ bool ReplyArea::send(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
_data.peer,
|
_data.peer,
|
||||||
{
|
{
|
||||||
.topicRootId = MsgId(0),
|
.topicRootId = MsgId(0),
|
||||||
.text = &message.textWithTags,
|
.text = &message.textWithTags,
|
||||||
.ignoreSlowmodeCountdown = (options.scheduled != 0),
|
.ignoreSlowmodeCountdown = (options.scheduled != 0),
|
||||||
});
|
});
|
||||||
if (!error.isEmpty()) {
|
if (error) {
|
||||||
_controller->uiShow()->showToast(error);
|
Data::ShowSendErrorToast(_controller->uiShow(), _data.peer, error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +263,7 @@ bool ReplyArea::sendExistingDocument(
|
||||||
_data.peer,
|
_data.peer,
|
||||||
ChatRestriction::SendStickers);
|
ChatRestriction::SendStickers);
|
||||||
if (error) {
|
if (error) {
|
||||||
show->showToast(*error);
|
Data::ShowSendErrorToast(show, _data.peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (showSlowmodeError()
|
} else if (showSlowmodeError()
|
||||||
|| Window::ShowSendPremiumError(show, document)) {
|
|| Window::ShowSendPremiumError(show, document)) {
|
||||||
|
@ -290,7 +291,7 @@ bool ReplyArea::sendExistingPhoto(
|
||||||
_data.peer,
|
_data.peer,
|
||||||
ChatRestriction::SendPhotos);
|
ChatRestriction::SendPhotos);
|
||||||
if (error) {
|
if (error) {
|
||||||
show->showToast(*error);
|
Data::ShowSendErrorToast(show, _data.peer, error);
|
||||||
return false;
|
return false;
|
||||||
} else if (showSlowmodeError()) {
|
} else if (showSlowmodeError()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -308,9 +309,9 @@ bool ReplyArea::sendExistingPhoto(
|
||||||
void ReplyArea::sendInlineResult(
|
void ReplyArea::sendInlineResult(
|
||||||
not_null<InlineBots::Result*> result,
|
not_null<InlineBots::Result*> result,
|
||||||
not_null<UserData*> bot) {
|
not_null<UserData*> bot) {
|
||||||
const auto errorText = result->getErrorOnSend(history());
|
if (const auto error = result->getErrorOnSend(history())) {
|
||||||
if (!errorText.isEmpty()) {
|
const auto show = _controller->uiShow();
|
||||||
_controller->uiShow()->showToast(errorText);
|
Data::ShowSendErrorToast(show, history()->peer, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendInlineResult(result, bot, {}, std::nullopt);
|
sendInlineResult(result, bot, {}, std::nullopt);
|
||||||
|
@ -363,11 +364,11 @@ bool ReplyArea::showSendingFilesError(
|
||||||
bool ReplyArea::showSendingFilesError(
|
bool ReplyArea::showSendingFilesError(
|
||||||
const Ui::PreparedList &list,
|
const Ui::PreparedList &list,
|
||||||
std::optional<bool> compress) const {
|
std::optional<bool> compress) const {
|
||||||
const auto text = [&] {
|
const auto error = [&]() -> Data::SendError {
|
||||||
const auto peer = _data.peer;
|
const auto peer = _data.peer;
|
||||||
const auto error = Data::FileRestrictionError(peer, list, compress);
|
const auto error = Data::FileRestrictionError(peer, list, compress);
|
||||||
if (error) {
|
if (error) {
|
||||||
return *error;
|
return error;
|
||||||
}
|
}
|
||||||
using Error = Ui::PreparedList::Error;
|
using Error = Ui::PreparedList::Error;
|
||||||
switch (list.error) {
|
switch (list.error) {
|
||||||
|
@ -382,9 +383,9 @@ bool ReplyArea::showSendingFilesError(
|
||||||
}
|
}
|
||||||
return tr::lng_forward_send_files_cant(tr::now);
|
return tr::lng_forward_send_files_cant(tr::now);
|
||||||
}();
|
}();
|
||||||
if (text.isEmpty()) {
|
if (!error) {
|
||||||
return false;
|
return false;
|
||||||
} else if (text == u"(toolarge)"_q) {
|
} else if (error.text == u"(toolarge)"_q) {
|
||||||
const auto fileSize = list.files.back().size;
|
const auto fileSize = list.files.back().size;
|
||||||
_controller->uiShow()->showBox(Box(
|
_controller->uiShow()->showBox(Box(
|
||||||
FileSizeLimitBox,
|
FileSizeLimitBox,
|
||||||
|
@ -394,7 +395,7 @@ bool ReplyArea::showSendingFilesError(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_controller->uiShow()->showToast(text);
|
Data::ShowSendErrorToast(_controller->uiShow(), _data.peer, error);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +423,7 @@ void ReplyArea::chooseAttach(
|
||||||
}
|
}
|
||||||
const auto peer = not_null(_data.peer);
|
const auto peer = not_null(_data.peer);
|
||||||
if (const auto error = Data::AnyFileRestrictionError(peer)) {
|
if (const auto error = Data::AnyFileRestrictionError(peer)) {
|
||||||
_controller->uiShow()->showToast(*error);
|
Data::ShowSendErrorToast(_controller->uiShow(), peer, error);
|
||||||
return;
|
return;
|
||||||
} else if (showSlowmodeError()) {
|
} else if (showSlowmodeError()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_thread.h"
|
#include "data/data_thread.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/view/history_view_context_menu.h" // CopyStoryLink.
|
#include "history/view/history_view_context_menu.h" // CopyStoryLink.
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -87,26 +87,11 @@ namespace Media::Stories {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto peer = story->peer();
|
const auto peer = story->peer();
|
||||||
const auto error = [&] {
|
const auto error = GetErrorForSending(
|
||||||
for (const auto thread : result) {
|
result,
|
||||||
const auto error = GetErrorTextForSending(
|
{ .story = story, .text = &comment });
|
||||||
thread,
|
if (error.error) {
|
||||||
{ .story = story, .text = &comment });
|
show->showBox(MakeSendErrorBox(error, result.size() > 1));
|
||||||
if (!error.isEmpty()) {
|
|
||||||
return std::make_pair(error, thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::make_pair(QString(), result.front());
|
|
||||||
}();
|
|
||||||
if (!error.first.isEmpty()) {
|
|
||||||
auto text = TextWithEntities();
|
|
||||||
if (result.size() > 1) {
|
|
||||||
text.append(
|
|
||||||
Ui::Text::Bold(error.second->chatListName())
|
|
||||||
).append("\n\n");
|
|
||||||
}
|
|
||||||
text.append(error.first);
|
|
||||||
show->showBox(Ui::MakeInformBox(text));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,7 +185,9 @@ std::optional<QString> RestrictionToSend(
|
||||||
not_null<Window::Controller*> controller,
|
not_null<Window::Controller*> controller,
|
||||||
ChatRestriction right) {
|
ChatRestriction right) {
|
||||||
if (const auto peer = ActiveChat(controller).peer()) {
|
if (const auto peer = ActiveChat(controller).peer()) {
|
||||||
return Data::RestrictionError(peer, right);
|
if (const auto error = Data::RestrictionError(peer, right)) {
|
||||||
|
return *error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1538,10 +1538,8 @@ void ShortcutMessages::sendInlineResult(
|
||||||
not_null<UserData*> bot) {
|
not_null<UserData*> bot) {
|
||||||
if (showPremiumRequired()) {
|
if (showPremiumRequired()) {
|
||||||
return;
|
return;
|
||||||
}
|
} else if (const auto error = result->getErrorOnSend(_history)) {
|
||||||
const auto errorText = result->getErrorOnSend(_history);
|
Data::ShowSendErrorToast(_controller, _history->peer, error);
|
||||||
if (!errorText.isEmpty()) {
|
|
||||||
_controller->showToast(errorText);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendInlineResult(result, bot, {}, std::nullopt);
|
sendInlineResult(result, bot, {}, std::nullopt);
|
||||||
|
|
|
@ -325,8 +325,14 @@ void BoostBox(
|
||||||
return (counters.mine > 1) ? u"x%1"_q.arg(counters.mine) : u""_q;
|
return (counters.mine > 1) ? u"x%1"_q.arg(counters.mine) : u""_q;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const auto wasMine = state->data.current().mine;
|
||||||
|
const auto wasLifting = data.lifting;
|
||||||
auto text = state->data.value(
|
auto text = state->data.value(
|
||||||
) | rpl::map([=](BoostCounters counters) {
|
) | rpl::map([=](BoostCounters counters) {
|
||||||
|
const auto lifting = wasLifting
|
||||||
|
? (wasLifting
|
||||||
|
- std::clamp(counters.mine - wasMine, 0, wasLifting - 1))
|
||||||
|
: 0;
|
||||||
const auto bold = Ui::Text::Bold(name);
|
const auto bold = Ui::Text::Bold(name);
|
||||||
const auto now = counters.boosts;
|
const auto now = counters.boosts;
|
||||||
const auto full = !counters.nextLevelBoosts;
|
const auto full = !counters.nextLevelBoosts;
|
||||||
|
@ -337,7 +343,14 @@ void BoostBox(
|
||||||
lt_count,
|
lt_count,
|
||||||
rpl::single(float64(counters.level + (left ? 1 : 0))),
|
rpl::single(float64(counters.level + (left ? 1 : 0))),
|
||||||
Ui::Text::RichLangValue);
|
Ui::Text::RichLangValue);
|
||||||
return (counters.mine || full)
|
return (lifting > 1)
|
||||||
|
? tr::lng_boost_group_lift_restrictions_many(
|
||||||
|
lt_count,
|
||||||
|
rpl::single(float64(lifting)),
|
||||||
|
Ui::Text::RichLangValue)
|
||||||
|
: lifting
|
||||||
|
? tr::lng_boost_group_lift_restrictions(Ui::Text::RichLangValue)
|
||||||
|
: (counters.mine || full)
|
||||||
? (left
|
? (left
|
||||||
? tr::lng_boost_channel_needs_unlock(
|
? tr::lng_boost_channel_needs_unlock(
|
||||||
lt_count,
|
lt_count,
|
||||||
|
@ -365,6 +378,14 @@ void BoostBox(
|
||||||
rpl::single(bold),
|
rpl::single(bold),
|
||||||
Ui::Text::RichLangValue);
|
Ui::Text::RichLangValue);
|
||||||
}) | rpl::flatten_latest();
|
}) | rpl::flatten_latest();
|
||||||
|
if (wasLifting) {
|
||||||
|
state->data.value(
|
||||||
|
) | rpl::start_with_next([=](BoostCounters counters) {
|
||||||
|
if (counters.mine - wasMine >= wasLifting) {
|
||||||
|
box->closeBox();
|
||||||
|
}
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
auto faded = object_ptr<Ui::FadeWrap<>>(
|
auto faded = object_ptr<Ui::FadeWrap<>>(
|
||||||
close->parentWidget(),
|
close->parentWidget(),
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct BoostBoxData {
|
||||||
QString name;
|
QString name;
|
||||||
BoostCounters boost;
|
BoostCounters boost;
|
||||||
BoostFeatures features;
|
BoostFeatures features;
|
||||||
|
int lifting = 0;
|
||||||
bool allowMulti = false;
|
bool allowMulti = false;
|
||||||
bool group = false;
|
bool group = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,7 +61,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "api/api_updates.h"
|
#include "api/api_updates.h"
|
||||||
#include "mtproto/mtproto_config.h"
|
#include "mtproto/mtproto_config.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
#include "history/history_item_helpers.h" // GetErrorForSending.
|
||||||
#include "history/view/history_view_context_menu.h"
|
#include "history/view/history_view_context_menu.h"
|
||||||
#include "window/window_separate_id.h"
|
#include "window/window_separate_id.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
|
@ -2595,11 +2595,11 @@ QPointer<Ui::BoxContent> ShowSendNowMessagesBox(
|
||||||
: tr::lng_scheduled_send_now(tr::now);
|
: tr::lng_scheduled_send_now(tr::now);
|
||||||
|
|
||||||
const auto list = session->data().idsToItems(items);
|
const auto list = session->data().idsToItems(items);
|
||||||
const auto error = GetErrorTextForSending(
|
const auto error = GetErrorForSending(
|
||||||
history->peer,
|
history->peer,
|
||||||
{ .forward = &list });
|
{ .forward = &list });
|
||||||
if (!error.isEmpty()) {
|
if (error) {
|
||||||
navigation->showToast(error);
|
Data::ShowSendErrorToast(navigation, history->peer, error);
|
||||||
return { nullptr };
|
return { nullptr };
|
||||||
}
|
}
|
||||||
auto done = [
|
auto done = [
|
||||||
|
|
|
@ -764,7 +764,10 @@ void SessionNavigation::showPeerByLinkResolved(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionNavigation::resolveBoostState(not_null<ChannelData*> channel) {
|
void SessionNavigation::resolveBoostState(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
int boostsToLift) {
|
||||||
|
_boostsToLift = boostsToLift;
|
||||||
if (_boostStateResolving == channel) {
|
if (_boostStateResolving == channel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -772,18 +775,33 @@ void SessionNavigation::resolveBoostState(not_null<ChannelData*> channel) {
|
||||||
_api.request(MTPpremium_GetBoostsStatus(
|
_api.request(MTPpremium_GetBoostsStatus(
|
||||||
channel->input
|
channel->input
|
||||||
)).done([=](const MTPpremium_BoostsStatus &result) {
|
)).done([=](const MTPpremium_BoostsStatus &result) {
|
||||||
_boostStateResolving = nullptr;
|
if (base::take(_boostStateResolving) != channel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto boosted = std::make_shared<bool>();
|
||||||
channel->updateLevelHint(result.data().vlevel().v);
|
channel->updateLevelHint(result.data().vlevel().v);
|
||||||
const auto submit = [=](Fn<void(Ui::BoostCounters)> done) {
|
const auto submit = [=](Fn<void(Ui::BoostCounters)> done) {
|
||||||
applyBoost(channel, done);
|
applyBoost(channel, [=](Ui::BoostCounters counters) {
|
||||||
|
*boosted = true;
|
||||||
|
done(counters);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
uiShow()->show(Box(Ui::BoostBox, Ui::BoostBoxData{
|
const auto lifting = base::take(_boostsToLift);
|
||||||
|
const auto box = uiShow()->show(Box(Ui::BoostBox, Ui::BoostBoxData{
|
||||||
.name = channel->name(),
|
.name = channel->name(),
|
||||||
.boost = ParseBoostCounters(result),
|
.boost = ParseBoostCounters(result),
|
||||||
.features = LookupBoostFeatures(channel),
|
.features = LookupBoostFeatures(channel),
|
||||||
|
.lifting = lifting,
|
||||||
.allowMulti = (BoostsForGift(_session) > 0),
|
.allowMulti = (BoostsForGift(_session) > 0),
|
||||||
.group = channel->isMegagroup(),
|
.group = channel->isMegagroup(),
|
||||||
}, submit));
|
}, submit));
|
||||||
|
if (lifting) {
|
||||||
|
box->boxClosing() | rpl::start_with_next([=] {
|
||||||
|
if (*boosted) {
|
||||||
|
channel->updateFullForced();
|
||||||
|
}
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
_boostStateResolving = nullptr;
|
_boostStateResolving = nullptr;
|
||||||
showToast(u"Error: "_q + error.type());
|
showToast(u"Error: "_q + error.type());
|
||||||
|
|
|
@ -253,7 +253,9 @@ public:
|
||||||
Dialogs::Key inChat,
|
Dialogs::Key inChat,
|
||||||
PeerData *searchFrom = nullptr);
|
PeerData *searchFrom = nullptr);
|
||||||
|
|
||||||
void resolveBoostState(not_null<ChannelData*> channel);
|
void resolveBoostState(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
int boostsToLift = 0);
|
||||||
|
|
||||||
void resolveCollectible(
|
void resolveCollectible(
|
||||||
PeerId ownerId,
|
PeerId ownerId,
|
||||||
|
@ -319,6 +321,7 @@ private:
|
||||||
mtpRequestId _showingRepliesRequestId = 0;
|
mtpRequestId _showingRepliesRequestId = 0;
|
||||||
|
|
||||||
ChannelData *_boostStateResolving = nullptr;
|
ChannelData *_boostStateResolving = nullptr;
|
||||||
|
int _boostsToLift = 0;
|
||||||
|
|
||||||
QString _collectibleEntity;
|
QString _collectibleEntity;
|
||||||
mtpRequestId _collectibleRequestId = 0;
|
mtpRequestId _collectibleRequestId = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue