mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 06:35:14 +00:00
Show toast on forward attempt to premium required.
This commit is contained in:
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user