mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Show toast on forward attempt to premium required.
This commit is contained in:
parent
7c468052e6
commit
eda7118df9
12 changed files with 428 additions and 64 deletions
|
@ -15,6 +15,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_peer.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_user.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
|
@ -334,6 +338,72 @@ const Data::SubscriptionOptions &Premium::subscriptionOptions() const {
|
|||
return _subscriptionOptions;
|
||||
}
|
||||
|
||||
rpl::producer<> Premium::somePremiumRequiredResolved() const {
|
||||
return _somePremiumRequiredResolved.events();
|
||||
}
|
||||
|
||||
void Premium::resolvePremiumRequired(not_null<UserData*> user) {
|
||||
_resolvePremiumRequiredUsers.emplace(user);
|
||||
if (!_premiumRequiredRequestScheduled
|
||||
&& _resolvePremiumRequestedUsers.empty()) {
|
||||
_premiumRequiredRequestScheduled = true;
|
||||
crl::on_main(_session, [=] {
|
||||
requestPremiumRequiredSlice();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Premium::requestPremiumRequiredSlice() {
|
||||
_premiumRequiredRequestScheduled = false;
|
||||
if (!_resolvePremiumRequestedUsers.empty()
|
||||
|| _resolvePremiumRequiredUsers.empty()) {
|
||||
return;
|
||||
}
|
||||
constexpr auto kPerRequest = 100;
|
||||
auto users = MTP_vector_from_range(_resolvePremiumRequiredUsers
|
||||
| ranges::views::transform(&UserData::inputUser));
|
||||
if (users.v.size() > kPerRequest) {
|
||||
auto shortened = users.v;
|
||||
shortened.resize(kPerRequest);
|
||||
users = MTP_vector<MTPInputUser>(std::move(shortened));
|
||||
const auto from = begin(_resolvePremiumRequiredUsers);
|
||||
_resolvePremiumRequestedUsers = { from, from + kPerRequest };
|
||||
_resolvePremiumRequiredUsers.erase(from, from + kPerRequest);
|
||||
} else {
|
||||
_resolvePremiumRequestedUsers
|
||||
= base::take(_resolvePremiumRequiredUsers);
|
||||
}
|
||||
const auto finish = [=](const QVector<MTPBool> &list) {
|
||||
constexpr auto me = UserDataFlag::MeRequiresPremiumToWrite;
|
||||
constexpr auto known = UserDataFlag::RequirePremiumToWriteKnown;
|
||||
constexpr auto mask = me | known;
|
||||
|
||||
auto index = 0;
|
||||
for (const auto &user : base::take(_resolvePremiumRequestedUsers)) {
|
||||
const auto require = (index < list.size())
|
||||
&& mtpIsTrue(list[index++]);
|
||||
user->setFlags((user->flags() & ~mask)
|
||||
| known
|
||||
| (require ? me : UserDataFlag()));
|
||||
}
|
||||
if (!_premiumRequiredRequestScheduled
|
||||
&& !_resolvePremiumRequiredUsers.empty()) {
|
||||
_premiumRequiredRequestScheduled = true;
|
||||
crl::on_main(_session, [=] {
|
||||
requestPremiumRequiredSlice();
|
||||
});
|
||||
}
|
||||
_somePremiumRequiredResolved.fire({});
|
||||
};
|
||||
_session->api().request(
|
||||
MTPusers_GetIsPremiumRequiredToContact(std::move(users))
|
||||
).done([=](const MTPVector<MTPBool> &result) {
|
||||
finish(result.v);
|
||||
}).fail([=] {
|
||||
finish({});
|
||||
}).send();
|
||||
}
|
||||
|
||||
PremiumGiftCodeOptions::PremiumGiftCodeOptions(not_null<PeerData*> peer)
|
||||
: _peer(peer)
|
||||
, _api(&peer->session().api().instance()) {
|
||||
|
@ -494,4 +564,33 @@ bool PremiumGiftCodeOptions::giveawayGiftsPurchaseAvailable() const {
|
|||
false);
|
||||
}
|
||||
|
||||
RequirePremiumState ResolveRequiresPremiumToWrite(
|
||||
not_null<History*> history) {
|
||||
const auto user = history->peer->asUser();
|
||||
if (!user
|
||||
|| !user->someRequirePremiumToWrite()
|
||||
|| user->session().premium()) {
|
||||
return RequirePremiumState::No;
|
||||
} else if (user->requirePremiumToWriteKnown()) {
|
||||
return user->meRequiresPremiumToWrite()
|
||||
? RequirePremiumState::Yes
|
||||
: RequirePremiumState::No;
|
||||
}
|
||||
// We allow this potentially-heavy loop because in case we've opened
|
||||
// the chat and have a lot of messages `requires_premium` will be known.
|
||||
for (const auto &block : history->blocks) {
|
||||
for (const auto &view : block->messages) {
|
||||
const auto item = view->data();
|
||||
if (!item->out() && !item->isService()) {
|
||||
using Flag = UserDataFlag;
|
||||
constexpr auto known = Flag::RequirePremiumToWriteKnown;
|
||||
constexpr auto me = Flag::MeRequiresPremiumToWrite;
|
||||
user->setFlags((user->flags() | known) & ~me);
|
||||
return RequirePremiumState::No;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RequirePremiumState::Unknown;
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_subscription_option.h"
|
||||
#include "mtproto/sender.h"
|
||||
|
||||
class History;
|
||||
class ApiWrap;
|
||||
|
||||
namespace Main {
|
||||
|
@ -103,10 +104,14 @@ public:
|
|||
[[nodiscard]] auto subscriptionOptions() const
|
||||
-> const Data::SubscriptionOptions &;
|
||||
|
||||
[[nodiscard]] rpl::producer<> somePremiumRequiredResolved() const;
|
||||
void resolvePremiumRequired(not_null<UserData*> user);
|
||||
|
||||
private:
|
||||
void reloadPromo();
|
||||
void reloadStickers();
|
||||
void reloadCloudSet();
|
||||
void requestPremiumRequiredSlice();
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
|
@ -143,6 +148,11 @@ private:
|
|||
|
||||
Data::SubscriptionOptions _subscriptionOptions;
|
||||
|
||||
rpl::event_stream<> _somePremiumRequiredResolved;
|
||||
base::flat_set<not_null<UserData*>> _resolvePremiumRequiredUsers;
|
||||
base::flat_set<not_null<UserData*>> _resolvePremiumRequestedUsers;
|
||||
bool _premiumRequiredRequestScheduled = false;
|
||||
|
||||
};
|
||||
|
||||
class PremiumGiftCodeOptions final {
|
||||
|
@ -196,4 +206,12 @@ private:
|
|||
|
||||
};
|
||||
|
||||
enum class RequirePremiumState {
|
||||
Unknown,
|
||||
Yes,
|
||||
No,
|
||||
};
|
||||
[[nodiscard]] RequirePremiumState ResolveRequiresPremiumToWrite(
|
||||
not_null<History*> history);
|
||||
|
||||
} // namespace Api
|
||||
|
|
|
@ -544,6 +544,12 @@ bool PeerListRow::checked() const {
|
|||
return _checkbox && _checkbox->checked();
|
||||
}
|
||||
|
||||
void PeerListRow::preloadUserpic() {
|
||||
if (_peer) {
|
||||
_peer->loadUserpic();
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListRow::setCustomStatus(const QString &status, bool active) {
|
||||
setStatusText(status);
|
||||
_statusType = active ? StatusType::CustomActive : StatusType::Custom;
|
||||
|
@ -1914,10 +1920,7 @@ void PeerListContent::loadProfilePhotos() {
|
|||
if (to > rowsCount) to = rowsCount;
|
||||
|
||||
for (auto index = from; index != to; ++index) {
|
||||
const auto row = getRow(RowIndex(index));
|
||||
if (!row->special()) {
|
||||
row->peer()->loadUserpic();
|
||||
}
|
||||
getRow(RowIndex(index))->preloadUserpic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,8 @@ public:
|
|||
[[nodiscard]] virtual auto generateNameWords() const
|
||||
-> const base::flat_set<QString> &;
|
||||
|
||||
virtual void preloadUserpic();
|
||||
|
||||
void setCustomStatus(const QString &status, bool active = false);
|
||||
void clearCustomStatus();
|
||||
|
||||
|
|
|
@ -8,10 +8,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/peer_list_controllers.h"
|
||||
|
||||
#include "api/api_chat_participants.h"
|
||||
#include "api/api_premium.h"
|
||||
#include "base/random.h"
|
||||
#include "boxes/filters/edit_filter_chats_list.h"
|
||||
#include "settings/settings_premium.h"
|
||||
#include "ui/boxes/confirm_box.h"
|
||||
#include "ui/effects/round_checkbox.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
|
@ -19,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/painter.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_stories.h"
|
||||
#include "data/data_channel.h"
|
||||
|
@ -44,10 +48,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
#include "styles/style_dialogs.h"
|
||||
|
||||
#include "data/data_stories.h"
|
||||
#include "dialogs/ui/dialogs_stories_content.h"
|
||||
#include "dialogs/ui/dialogs_stories_list.h"
|
||||
#include "styles/style_chat_helpers.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -257,9 +258,63 @@ bool PeerListGlobalSearchController::isLoading() {
|
|||
return _timer.isActive() || _requestId;
|
||||
}
|
||||
|
||||
ChatsListBoxController::Row::Row(not_null<History*> history)
|
||||
void ChatsListBoxController::RowDelegate::rowPreloadUserpic(
|
||||
not_null<Row*> row) {
|
||||
row->PeerListRow::preloadUserpic();
|
||||
}
|
||||
|
||||
ChatsListBoxController::Row::Row(
|
||||
not_null<History*> history,
|
||||
RowDelegate *delegate)
|
||||
: PeerListRow(history->peer)
|
||||
, _history(history) {
|
||||
, _history(history)
|
||||
, _delegate(delegate) {
|
||||
}
|
||||
|
||||
void PaintLock(
|
||||
Painter &p,
|
||||
not_null<const style::PeerListItem*> st,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
int size) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto &check = st->checkbox.check;
|
||||
auto pen = check.border->p;
|
||||
pen.setWidthF(check.width);
|
||||
p.setPen(pen);
|
||||
p.setBrush(st::premiumButtonBg2);
|
||||
const auto &icon = st::stickersPremiumLock;
|
||||
const auto width = icon.width();
|
||||
const auto height = icon.height();
|
||||
const auto rect = QRect(
|
||||
QPoint(x + size - width, y + size - height),
|
||||
icon.size());
|
||||
p.drawEllipse(rect);
|
||||
icon.paintInCenter(p, rect);
|
||||
}
|
||||
|
||||
auto ChatsListBoxController::Row::generatePaintUserpicCallback(
|
||||
bool forceRound)
|
||||
-> PaintRoundImageCallback {
|
||||
auto result = PeerListRow::generatePaintUserpicCallback(forceRound);
|
||||
if (_locked) {
|
||||
AssertIsDebug();
|
||||
const auto st = /*_delegate ? _delegate->rowSt() : */&st::defaultPeerListItem;
|
||||
return [=](Painter &p, int x, int y, int outerWidth, int size) {
|
||||
result(p, x, y, outerWidth, size);
|
||||
PaintLock(p, st, x, y, outerWidth, size);
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ChatsListBoxController::Row::preloadUserpic() {
|
||||
if (_delegate) {
|
||||
_delegate->rowPreloadUserpic(this);
|
||||
} else {
|
||||
PeerListRow::preloadUserpic();
|
||||
}
|
||||
}
|
||||
|
||||
ChatsListBoxController::ChatsListBoxController(
|
||||
|
@ -629,14 +684,40 @@ std::unique_ptr<PeerListRow> ContactsBoxController::createRow(
|
|||
return std::make_unique<PeerListRow>(user);
|
||||
}
|
||||
|
||||
ChooseRecipientPremiumRequiredError WritePremiumRequiredError(
|
||||
not_null<UserData*> user) {
|
||||
return {
|
||||
.text = tr::lng_send_non_premium_message_toast(
|
||||
tr::now,
|
||||
lt_user,
|
||||
TextWithEntities{ user->shortName() },
|
||||
lt_link,
|
||||
Ui::Text::Link(
|
||||
Ui::Text::Bold(
|
||||
tr::lng_send_non_premium_message_toast_link(
|
||||
tr::now))),
|
||||
Ui::Text::RichLangValue),
|
||||
};
|
||||
}
|
||||
|
||||
ChooseRecipientBoxController::ChooseRecipientBoxController(
|
||||
not_null<Main::Session*> session,
|
||||
FnMut<void(not_null<Data::Thread*>)> callback,
|
||||
Fn<bool(not_null<Data::Thread*>)> filter)
|
||||
: ChatsListBoxController(session)
|
||||
, _session(session)
|
||||
, _callback(std::move(callback))
|
||||
, _filter(std::move(filter)) {
|
||||
: ChooseRecipientBoxController({
|
||||
.session = session,
|
||||
.callback = std::move(callback),
|
||||
.filter = std::move(filter),
|
||||
}) {
|
||||
}
|
||||
|
||||
ChooseRecipientBoxController::ChooseRecipientBoxController(
|
||||
ChooseRecipientArgs &&args)
|
||||
: ChatsListBoxController(args.session)
|
||||
, _session(args.session)
|
||||
, _callback(std::move(args.callback))
|
||||
, _filter(std::move(args.filter))
|
||||
, _premiumRequiredError(std::move(args.premiumRequiredError)) {
|
||||
}
|
||||
|
||||
Main::Session &ChooseRecipientBoxController::session() const {
|
||||
|
@ -645,9 +726,50 @@ Main::Session &ChooseRecipientBoxController::session() const {
|
|||
|
||||
void ChooseRecipientBoxController::prepareViewHook() {
|
||||
delegate()->peerListSetTitle(tr::lng_forward_choose());
|
||||
|
||||
if (_premiumRequiredError) {
|
||||
rpl::merge(
|
||||
Data::AmPremiumValue(_session) | rpl::to_empty,
|
||||
_session->api().premium().somePremiumRequiredResolved()
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshLockedRows();
|
||||
}, _lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
void ChooseRecipientBoxController::refreshLockedRows() {
|
||||
auto count = delegate()->peerListFullRowsCount();
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
const auto raw = delegate()->peerListRowAt(i);
|
||||
const auto row = static_cast<Row*>(raw.get());
|
||||
if (const auto user = row->peer()->asUser()) {
|
||||
const auto history = row->history();
|
||||
const auto locked = (Api::ResolveRequiresPremiumToWrite(history)
|
||||
== Api::RequirePremiumState::Yes);
|
||||
if (row->locked() != locked) {
|
||||
row->setLocked(locked);
|
||||
delegate()->peerListUpdateRow(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChooseRecipientBoxController::rowPreloadUserpic(not_null<Row*> row) {
|
||||
row->PeerListRow::preloadUserpic();
|
||||
|
||||
if (!_premiumRequiredError) {
|
||||
return;
|
||||
} else if (Api::ResolveRequiresPremiumToWrite(row->history())
|
||||
== Api::RequirePremiumState::Unknown) {
|
||||
const auto user = row->peer()->asUser();
|
||||
session().api().premium().resolvePremiumRequired(user);
|
||||
}
|
||||
}
|
||||
|
||||
void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
|
||||
if (showLockedError(row)) {
|
||||
return;
|
||||
}
|
||||
auto guard = base::make_weak(this);
|
||||
const auto peer = row->peer();
|
||||
if (const auto forum = peer->forum()) {
|
||||
|
@ -698,6 +820,19 @@ void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ChooseRecipientBoxController::showLockedError(
|
||||
not_null<PeerListRow*> row) const {
|
||||
if (!static_cast<Row*>(row.get())->locked()) {
|
||||
return false;
|
||||
}
|
||||
::Settings::ShowPremiumPromoToast(
|
||||
delegate()->peerListUiShow(),
|
||||
ChatHelpers::ResolveWindowDefault(),
|
||||
_premiumRequiredError(row->peer()->asUser()).text,
|
||||
u"require_premium"_q);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString ChooseRecipientBoxController::savedMessagesChatStatus() const {
|
||||
return tr::lng_saved_forward_here(tr::now);
|
||||
}
|
||||
|
@ -708,8 +843,23 @@ auto ChooseRecipientBoxController::createRow(
|
|||
const auto skip = _filter
|
||||
? !_filter(history)
|
||||
: ((peer->isBroadcast() && !Data::CanSendAnything(peer))
|
||||
|| (peer->isUser() && !Data::CanSendAnything(peer)));
|
||||
return skip ? nullptr : std::make_unique<Row>(history);
|
||||
|| peer->isRepliesChat()
|
||||
|| (peer->isUser() && (_premiumRequiredError
|
||||
? peer->asUser()->isInaccessible()
|
||||
: !Data::CanSendAnything(peer))));
|
||||
if (skip) {
|
||||
return nullptr;
|
||||
}
|
||||
auto result = std::make_unique<Row>(
|
||||
history,
|
||||
static_cast<RowDelegate*>(this));
|
||||
if (_premiumRequiredError) {
|
||||
const auto require = Api::ResolveRequiresPremiumToWrite(history);
|
||||
if (require == Api::RequirePremiumState::Yes) {
|
||||
result->setLocked(true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ChooseTopicSearchController::ChooseTopicSearchController(
|
||||
|
|
|
@ -91,16 +91,34 @@ private:
|
|||
|
||||
class ChatsListBoxController : public PeerListController {
|
||||
public:
|
||||
class Row;
|
||||
class RowDelegate {
|
||||
public:
|
||||
virtual void rowPreloadUserpic(not_null<Row*> row);
|
||||
};
|
||||
|
||||
class Row : public PeerListRow {
|
||||
public:
|
||||
Row(not_null<History*> history);
|
||||
Row(not_null<History*> history, RowDelegate *delegate = nullptr);
|
||||
|
||||
not_null<History*> history() const {
|
||||
[[nodiscard]] not_null<History*> history() const {
|
||||
return _history;
|
||||
}
|
||||
[[nodiscard]] bool locked() const {
|
||||
return _locked;
|
||||
}
|
||||
void setLocked(bool locked) {
|
||||
_locked = locked;
|
||||
}
|
||||
PaintRoundImageCallback generatePaintUserpicCallback(
|
||||
bool forceRound) override;
|
||||
|
||||
void preloadUserpic() override;
|
||||
|
||||
private:
|
||||
not_null<History*> _history;
|
||||
const not_null<History*> _history;
|
||||
RowDelegate *_delegate = nullptr;
|
||||
bool _locked = false;
|
||||
|
||||
};
|
||||
|
||||
|
@ -207,14 +225,32 @@ private:
|
|||
|
||||
};
|
||||
|
||||
struct ChooseRecipientPremiumRequiredError {
|
||||
TextWithEntities text;
|
||||
};
|
||||
|
||||
[[nodiscard]] ChooseRecipientPremiumRequiredError WritePremiumRequiredError(
|
||||
not_null<UserData*> user);
|
||||
|
||||
struct ChooseRecipientArgs {
|
||||
not_null<Main::Session*> session;
|
||||
FnMut<void(not_null<Data::Thread*>)> callback;
|
||||
Fn<bool(not_null<Data::Thread*>)> filter;
|
||||
|
||||
using PremiumRequiredError = ChooseRecipientPremiumRequiredError;
|
||||
Fn<PremiumRequiredError(not_null<UserData*>)> premiumRequiredError;
|
||||
};
|
||||
|
||||
class ChooseRecipientBoxController
|
||||
: public ChatsListBoxController
|
||||
, public base::has_weak_ptr {
|
||||
, public base::has_weak_ptr
|
||||
, private ChatsListBoxController::RowDelegate {
|
||||
public:
|
||||
ChooseRecipientBoxController(
|
||||
not_null<Main::Session*> session,
|
||||
FnMut<void(not_null<Data::Thread*>)> callback,
|
||||
Fn<bool(not_null<Data::Thread*>)> filter = nullptr);
|
||||
explicit ChooseRecipientBoxController(ChooseRecipientArgs &&args);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
|
@ -225,10 +261,19 @@ protected:
|
|||
void prepareViewHook() override;
|
||||
std::unique_ptr<Row> createRow(not_null<History*> history) override;
|
||||
|
||||
[[nodiscard]] bool showLockedError(not_null<PeerListRow*> row) const;
|
||||
|
||||
private:
|
||||
void refreshLockedRows();
|
||||
void rowPreloadUserpic(not_null<Row*> row) override;
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
FnMut<void(not_null<Data::Thread*>)> _callback;
|
||||
Fn<bool(not_null<Data::Thread*>)> _filter;
|
||||
Fn<ChooseRecipientPremiumRequiredError(
|
||||
not_null<UserData*>)> _premiumRequiredError;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -18,29 +18,35 @@ rpl::producer<bool> Show::adjustShadowLeft() const {
|
|||
return rpl::single(false);
|
||||
}
|
||||
|
||||
Window::SessionController *Show::resolveWindow(WindowUsage usage) const {
|
||||
const auto session = &this->session();
|
||||
const auto check = [&](Window::Controller *window) {
|
||||
if (const auto controller = window->sessionController()) {
|
||||
if (&controller->session() == session) {
|
||||
return controller;
|
||||
ResolveWindow ResolveWindowDefault() {
|
||||
return [](not_null<Main::Session*> session, WindowUsage usage)
|
||||
-> Window::SessionController* {
|
||||
const auto check = [&](Window::Controller *window) {
|
||||
if (const auto controller = window->sessionController()) {
|
||||
if (&controller->session() == session) {
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
return (Window::SessionController*)nullptr;
|
||||
};
|
||||
auto &app = Core::App();
|
||||
if (const auto a = check(app.activeWindow())) {
|
||||
return a;
|
||||
} else if (const auto b = check(app.activePrimaryWindow())) {
|
||||
return b;
|
||||
} else if (const auto c = check(app.windowFor(&session->account()))) {
|
||||
return c;
|
||||
} else if (const auto d = check(
|
||||
app.ensureSeparateWindowForAccount(
|
||||
&session->account()))) {
|
||||
return d;
|
||||
}
|
||||
return (Window::SessionController*)nullptr;
|
||||
return nullptr;
|
||||
};
|
||||
auto &app = Core::App();
|
||||
if (const auto a = check(app.activeWindow())) {
|
||||
return a;
|
||||
} else if (const auto b = check(app.activePrimaryWindow())) {
|
||||
return b;
|
||||
} else if (const auto c = check(app.windowFor(&session->account()))) {
|
||||
return c;
|
||||
} else if (const auto d = check(
|
||||
app.ensureSeparateWindowForAccount(
|
||||
&session->account()))) {
|
||||
return d;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Window::SessionController *Show::resolveWindow(WindowUsage usage) const {
|
||||
return ResolveWindowDefault()(&session(), usage);
|
||||
}
|
||||
|
||||
} // namespace ChatHelpers
|
||||
|
|
|
@ -44,6 +44,11 @@ enum class WindowUsage {
|
|||
PremiumPromo,
|
||||
};
|
||||
|
||||
using ResolveWindow = Fn<Window::SessionController*(
|
||||
not_null<Main::Session*>,
|
||||
WindowUsage)>;
|
||||
[[nodiscard]] ResolveWindow ResolveWindowDefault();
|
||||
|
||||
class Show : public Main::SessionShow {
|
||||
public:
|
||||
virtual void activate() = 0;
|
||||
|
|
|
@ -892,14 +892,13 @@ void ShowReplyToChatBox(
|
|||
using Chosen = not_null<Data::Thread*>;
|
||||
|
||||
Controller(not_null<Main::Session*> session)
|
||||
: ChooseRecipientBoxController(
|
||||
session,
|
||||
[=](Chosen thread) mutable { _singleChosen.fire_copy(thread); },
|
||||
nullptr) {
|
||||
}
|
||||
|
||||
void rowClicked(not_null<PeerListRow*> row) override final {
|
||||
ChooseRecipientBoxController::rowClicked(row);
|
||||
: ChooseRecipientBoxController({
|
||||
.session = session,
|
||||
.callback = [=](Chosen thread) {
|
||||
_singleChosen.fire_copy(thread);
|
||||
},
|
||||
.premiumRequiredError = WritePremiumRequiredError,
|
||||
}) {
|
||||
}
|
||||
|
||||
[[nodiscard]] rpl::producer<Chosen> singleChosen() const {
|
||||
|
@ -912,6 +911,7 @@ void ShowReplyToChatBox(
|
|||
|
||||
private:
|
||||
void prepareViewHook() override {
|
||||
ChooseRecipientBoxController::prepareViewHook();
|
||||
delegate()->peerListSetTitle(tr::lng_reply_in_another_title());
|
||||
}
|
||||
|
||||
|
|
|
@ -1316,6 +1316,22 @@ void ShowPremiumPromoToast(
|
|||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
TextWithEntities textWithLink,
|
||||
const QString &ref) {
|
||||
ShowPremiumPromoToast(show, [=](
|
||||
not_null<Main::Session*> session,
|
||||
ChatHelpers::WindowUsage usage) {
|
||||
Expects(&show->session() == session);
|
||||
|
||||
return show->resolveWindow(usage);
|
||||
}, std::move(textWithLink), ref);
|
||||
}
|
||||
|
||||
void ShowPremiumPromoToast(
|
||||
std::shared_ptr<Main::SessionShow> show,
|
||||
Fn<Window::SessionController*(
|
||||
not_null<Main::Session*>,
|
||||
ChatHelpers::WindowUsage)> resolveWindow,
|
||||
TextWithEntities textWithLink,
|
||||
const QString &ref) {
|
||||
using WeakToast = base::weak_ptr<Ui::Toast::Instance>;
|
||||
const auto toast = std::make_shared<WeakToast>();
|
||||
(*toast) = show->showToast({
|
||||
|
@ -1331,7 +1347,8 @@ void ShowPremiumPromoToast(
|
|||
if (const auto strong = toast->get()) {
|
||||
strong->hideAnimated();
|
||||
(*toast) = nullptr;
|
||||
if (const auto controller = show->resolveWindow(
|
||||
if (const auto controller = resolveWindow(
|
||||
&show->session(),
|
||||
ChatHelpers::WindowUsage::PremiumPromo)) {
|
||||
Settings::ShowPremium(controller, ref);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ struct RoundButton;
|
|||
|
||||
namespace ChatHelpers {
|
||||
class Show;
|
||||
enum class WindowUsage;
|
||||
} // namespace ChatHelpers
|
||||
|
||||
namespace Ui {
|
||||
|
@ -28,6 +29,7 @@ class VerticalLayout;
|
|||
|
||||
namespace Main {
|
||||
class Session;
|
||||
class SessionShow;
|
||||
} // namespace Main
|
||||
|
||||
namespace Window {
|
||||
|
@ -61,6 +63,13 @@ void ShowPremiumPromoToast(
|
|||
std::shared_ptr<ChatHelpers::Show> show,
|
||||
TextWithEntities textWithLink,
|
||||
const QString &ref);
|
||||
void ShowPremiumPromoToast(
|
||||
std::shared_ptr<::Main::SessionShow> show,
|
||||
Fn<Window::SessionController*(
|
||||
not_null<::Main::Session*>,
|
||||
ChatHelpers::WindowUsage)> resolveWindow,
|
||||
TextWithEntities textWithLink,
|
||||
const QString &ref);
|
||||
|
||||
struct SubscribeButtonArgs final {
|
||||
Window::SessionController *controller = nullptr;
|
||||
|
|
|
@ -1504,8 +1504,11 @@ void PeerMenuShareContactBox(
|
|||
*weak = navigation->parentController()->show(
|
||||
Box<PeerListBox>(
|
||||
std::make_unique<ChooseRecipientBoxController>(
|
||||
&navigation->session(),
|
||||
std::move(callback)),
|
||||
ChooseRecipientArgs{
|
||||
.session = &navigation->session(),
|
||||
.callback = std::move(callback),
|
||||
.premiumRequiredError = WritePremiumRequiredError,
|
||||
}),
|
||||
[](not_null<PeerListBox*> box) {
|
||||
box->addButton(tr::lng_cancel(), [=] {
|
||||
box->closeBox();
|
||||
|
@ -1742,10 +1745,12 @@ QPointer<Ui::BoxContent> ShowChooseRecipientBox(
|
|||
}
|
||||
};
|
||||
*weak = navigation->parentController()->show(Box<PeerListBox>(
|
||||
std::make_unique<ChooseRecipientBoxController>(
|
||||
&navigation->session(),
|
||||
std::move(callback),
|
||||
std::move(filter)),
|
||||
std::make_unique<ChooseRecipientBoxController>(ChooseRecipientArgs{
|
||||
.session = &navigation->session(),
|
||||
.callback = std::move(callback),
|
||||
.filter = std::move(filter),
|
||||
.premiumRequiredError = WritePremiumRequiredError,
|
||||
}),
|
||||
std::move(initBox)));
|
||||
return weak->data();
|
||||
}
|
||||
|
@ -1799,15 +1804,18 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
|
|||
using Chosen = not_null<Data::Thread*>;
|
||||
|
||||
Controller(not_null<Main::Session*> session)
|
||||
: ChooseRecipientBoxController(
|
||||
session,
|
||||
[=](Chosen thread) mutable { _singleChosen.fire_copy(thread); },
|
||||
nullptr) {
|
||||
: ChooseRecipientBoxController({
|
||||
.session = session,
|
||||
.callback = [=](Chosen thread) {
|
||||
_singleChosen.fire_copy(thread);
|
||||
},
|
||||
.premiumRequiredError = WritePremiumRequiredError,
|
||||
}) {
|
||||
}
|
||||
|
||||
void rowClicked(not_null<PeerListRow*> row) override final {
|
||||
const auto count = delegate()->peerListSelectedRowsCount();
|
||||
if (count && row->peer()->isForum()) {
|
||||
if (showLockedError(row) || (count && row->peer()->isForum())) {
|
||||
return;
|
||||
} else if (!count || row->peer()->isForum()) {
|
||||
ChooseRecipientBoxController::rowClicked(row);
|
||||
|
@ -2126,10 +2134,12 @@ QPointer<Ui::BoxContent> ShowShareGameBox(
|
|||
});
|
||||
};
|
||||
*weak = navigation->parentController()->show(Box<PeerListBox>(
|
||||
std::make_unique<ChooseRecipientBoxController>(
|
||||
&navigation->session(),
|
||||
std::move(chosen),
|
||||
std::move(filter)),
|
||||
std::make_unique<ChooseRecipientBoxController>(ChooseRecipientArgs{
|
||||
.session = &navigation->session(),
|
||||
.callback = std::move(chosen),
|
||||
.filter = std::move(filter),
|
||||
.premiumRequiredError = WritePremiumRequiredError,
|
||||
}),
|
||||
std::move(initBox)));
|
||||
return weak->data();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue