mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Add channel gifts filter.
This commit is contained in:
parent
addd37fb1f
commit
ec69d557dc
4 changed files with 163 additions and 19 deletions
|
@ -2131,6 +2131,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_peer_gifts_about_mine" = "These gifts were sent to you by other users. Click on a gift to convert it to Stars or change its privacy settings.";
|
||||
"lng_peer_gifts_notify" = "Notify About New Gifts";
|
||||
"lng_peer_gifts_notify_enabled" = "You will receive a message from Telegram when your channel receives a gift.";
|
||||
"lng_peer_gifts_filter_by_value" = "Sort by Value";
|
||||
"lng_peer_gifts_filter_by_date" = "Sort by Date";
|
||||
"lng_peer_gifts_filter_unlimited" = "Unlimited";
|
||||
"lng_peer_gifts_filter_limited" = "Limited";
|
||||
"lng_peer_gifts_filter_unique" = "Unique";
|
||||
"lng_peer_gifts_filter_saved" = "Displayed";
|
||||
"lng_peer_gifts_filter_unsaved" = "Hidden";
|
||||
|
||||
"lng_premium_gift_duration_months#one" = "for {count} month";
|
||||
"lng_premium_gift_duration_months#other" = "for {count} months";
|
||||
|
|
|
@ -442,6 +442,11 @@ void WrapWidget::setupTopBarMenuToggle() {
|
|||
addTopBarMenuButton();
|
||||
}
|
||||
}, _topBar->lifetime());
|
||||
} else if (section.type() == Section::Type::PeerGifts
|
||||
&& key.peer()
|
||||
&& key.peer()->isChannel()
|
||||
&& key.peer()->canManageGifts()) {
|
||||
addTopBarMenuButton();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "info/info_controller.h"
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/menu/menu_add_action_callback.h"
|
||||
#include "ui/widgets/box_content_divider.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/scroll_area.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
@ -28,6 +30,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "settings/settings_credits_graphics.h"
|
||||
#include "styles/style_info.h"
|
||||
#include "styles/style_layers.h" // boxRadius
|
||||
#include "styles/style_media_player.h" // mediaPlayerMenuCheck
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_credits.h" // giftBoxPadding
|
||||
|
||||
namespace Info::PeerGifts {
|
||||
|
@ -57,7 +61,8 @@ public:
|
|||
InnerWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
not_null<PeerData*> peer);
|
||||
not_null<PeerData*> peer,
|
||||
rpl::producer<Filter> filter);
|
||||
|
||||
[[nodiscard]] not_null<PeerData*> peer() const {
|
||||
return _peer;
|
||||
|
@ -65,6 +70,9 @@ public:
|
|||
[[nodiscard]] rpl::producer<bool> notifyEnabled() const {
|
||||
return _notifyEnabled.events();
|
||||
}
|
||||
[[nodiscard]] rpl::producer<> scrollToTop() const {
|
||||
return _scrollToTop.events();
|
||||
}
|
||||
|
||||
void saveState(not_null<Memento*> memento);
|
||||
void restoreState(not_null<Memento*> memento);
|
||||
|
@ -89,21 +97,25 @@ private:
|
|||
void refreshButtons();
|
||||
void validateButtons();
|
||||
void showGift(int index);
|
||||
void refreshAbout();
|
||||
|
||||
int resizeGetHeight(int width) override;
|
||||
|
||||
const not_null<Window::SessionController*> _window;
|
||||
rpl::variable<Filter> _filter;
|
||||
Delegate _delegate;
|
||||
not_null<Controller*> _controller;
|
||||
std::unique_ptr<Ui::FlatLabel> _about;
|
||||
const not_null<PeerData*> _peer;
|
||||
std::vector<Entry> _entries;
|
||||
int _totalCount = 0;
|
||||
rpl::event_stream<> _scrollToTop;
|
||||
|
||||
MTP::Sender _api;
|
||||
mtpRequestId _loadMoreRequestId = 0;
|
||||
QString _offset;
|
||||
bool _allLoaded = false;
|
||||
bool _reloading = false;
|
||||
|
||||
rpl::event_stream<bool> _notifyEnabled;
|
||||
std::vector<View> _views;
|
||||
|
@ -122,22 +134,13 @@ private:
|
|||
InnerWidget::InnerWidget(
|
||||
QWidget *parent,
|
||||
not_null<Controller*> controller,
|
||||
not_null<PeerData*> peer)
|
||||
not_null<PeerData*> peer,
|
||||
rpl::producer<Filter> filter)
|
||||
: BoxContentDivider(parent)
|
||||
, _window(controller->parentController())
|
||||
, _filter(std::move(filter))
|
||||
, _delegate(_window, GiftButtonMode::Minimal)
|
||||
, _controller(controller)
|
||||
, _about((!peer->isSelf() && peer->canManageGifts())
|
||||
? nullptr
|
||||
: std::make_unique<Ui::FlatLabel>(
|
||||
this,
|
||||
(peer->isSelf()
|
||||
? tr::lng_peer_gifts_about_mine(Ui::Text::RichLangValue)
|
||||
: tr::lng_peer_gifts_about(
|
||||
lt_user,
|
||||
rpl::single(Ui::Text::Bold(peer->shortName())),
|
||||
Ui::Text::RichLangValue)),
|
||||
st::giftListAbout))
|
||||
, _peer(peer)
|
||||
, _totalCount(_peer->peerGiftsCount())
|
||||
, _api(&_peer->session().mtp()) {
|
||||
|
@ -146,6 +149,14 @@ InnerWidget::InnerWidget(
|
|||
if (peer->canManageGifts()) {
|
||||
subscribeToUpdates();
|
||||
}
|
||||
|
||||
_filter.value() | rpl::start_with_next([=] {
|
||||
_reloading = true;
|
||||
_api.request(base::take(_loadMoreRequestId)).cancel();
|
||||
_allLoaded = false;
|
||||
refreshAbout();
|
||||
loadMore();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
void InnerWidget::subscribeToUpdates() {
|
||||
|
@ -221,11 +232,16 @@ void InnerWidget::loadMore() {
|
|||
return;
|
||||
}
|
||||
using Flag = MTPpayments_GetSavedStarGifts::Flag;
|
||||
const auto withUnsaved = _peer->canManageGifts();
|
||||
const auto filter = _filter.current();
|
||||
_loadMoreRequestId = _api.request(MTPpayments_GetSavedStarGifts(
|
||||
MTP_flags(withUnsaved ? Flag() : Flag::f_exclude_unsaved),
|
||||
MTP_flags((filter.sortByValue ? Flag::f_sort_by_value : Flag())
|
||||
| (filter.skipLimited ? Flag::f_exclude_limited : Flag())
|
||||
| (filter.skipUnlimited ? Flag::f_exclude_unlimited : Flag())
|
||||
| (filter.skipUnique ? Flag::f_exclude_unique : Flag())
|
||||
| (filter.skipSaved ? Flag::f_exclude_saved : Flag())
|
||||
| (filter.skipUnsaved ? Flag::f_exclude_unsaved : Flag())),
|
||||
_peer->input,
|
||||
MTP_string(_offset),
|
||||
MTP_string(_reloading ? QString() : _offset),
|
||||
MTP_int(kPerPage)
|
||||
)).done([=](const MTPpayments_SavedStarGifts &result) {
|
||||
_loadMoreRequestId = 0;
|
||||
|
@ -244,6 +260,10 @@ void InnerWidget::loadMore() {
|
|||
owner->processUsers(data.vusers());
|
||||
owner->processChats(data.vchats());
|
||||
|
||||
if (base::take(_reloading)) {
|
||||
_entries.clear();
|
||||
_views.clear();
|
||||
}
|
||||
_entries.reserve(_entries.size() + data.vgifts().v.size());
|
||||
for (const auto &gift : data.vgifts().v) {
|
||||
if (auto parsed = Api::FromTL(_peer, gift)) {
|
||||
|
@ -255,6 +275,7 @@ void InnerWidget::loadMore() {
|
|||
}
|
||||
}
|
||||
refreshButtons();
|
||||
refreshAbout();
|
||||
}).fail([=] {
|
||||
_loadMoreRequestId = 0;
|
||||
_allLoaded = true;
|
||||
|
@ -353,6 +374,27 @@ void InnerWidget::showGift(int index) {
|
|||
_entries[index].gift));
|
||||
}
|
||||
|
||||
void InnerWidget::refreshAbout() {
|
||||
if (!_peer->isSelf() && _peer->canManageGifts() && !_entries.empty()) {
|
||||
if (_about) {
|
||||
_about = nullptr;
|
||||
resizeToWidth(width());
|
||||
}
|
||||
} else if (!_about) {
|
||||
_about = std::make_unique<Ui::FlatLabel>(
|
||||
this,
|
||||
(_peer->isSelf()
|
||||
? tr::lng_peer_gifts_about_mine(Ui::Text::RichLangValue)
|
||||
: tr::lng_peer_gifts_about(
|
||||
lt_user,
|
||||
rpl::single(Ui::Text::Bold(_peer->shortName())),
|
||||
Ui::Text::RichLangValue)),
|
||||
st::giftListAbout);
|
||||
_about->show();
|
||||
resizeToWidth(width());
|
||||
}
|
||||
}
|
||||
|
||||
int InnerWidget::resizeGetHeight(int width) {
|
||||
const auto count = int(_entries.size());
|
||||
const auto padding = st::giftBoxPadding;
|
||||
|
@ -360,7 +402,7 @@ int InnerWidget::resizeGetHeight(int width) {
|
|||
const auto skipw = st::giftBoxGiftSkip.x();
|
||||
_perRow = std::min(
|
||||
(available + skipw) / (_singleMin.width() + skipw),
|
||||
count);
|
||||
std::max(count, 1));
|
||||
if (!_perRow) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -374,7 +416,9 @@ int InnerWidget::resizeGetHeight(int width) {
|
|||
const auto rows = (count + _perRow - 1) / _perRow;
|
||||
const auto skiph = st::giftBoxGiftSkip.y();
|
||||
|
||||
auto result = padding.bottom() * 2 + rows * (singleh + skiph) - skiph;
|
||||
auto result = rows
|
||||
? (padding.bottom() * 2 + rows * (singleh + skiph) - skiph)
|
||||
: 0;
|
||||
|
||||
if (const auto about = _about.get()) {
|
||||
const auto margin = st::giftListAboutMargin;
|
||||
|
@ -430,11 +474,14 @@ Widget::Widget(
|
|||
not_null<PeerData*> peer)
|
||||
: ContentWidget(parent, controller) {
|
||||
_inner = setInnerWidget(
|
||||
object_ptr<InnerWidget>(this, controller, peer));
|
||||
object_ptr<InnerWidget>(this, controller, peer, _filter.value()));
|
||||
_inner->notifyEnabled(
|
||||
) | rpl::take(1) | rpl::start_with_next([=](bool enabled) {
|
||||
setupNotifyCheckbox(enabled);
|
||||
}, _inner->lifetime());
|
||||
_inner->scrollToTop() | rpl::start_with_next([=] {
|
||||
scrollTo({ 0, 0 });
|
||||
}, _inner->lifetime());
|
||||
}
|
||||
|
||||
void Widget::showFinished() {
|
||||
|
@ -510,6 +557,77 @@ void Widget::setupNotifyCheckbox(bool enabled) {
|
|||
_hasPinnedToBottom = true;
|
||||
}
|
||||
|
||||
void Widget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) {
|
||||
const auto filter = _filter.current();
|
||||
const auto change = [=](Fn<void(Filter&)> update) {
|
||||
auto now = _filter.current();
|
||||
update(now);
|
||||
_filter = now;
|
||||
};
|
||||
|
||||
if (filter.sortByValue) {
|
||||
addAction(tr::lng_peer_gifts_filter_by_date(tr::now), [=] {
|
||||
change([](Filter &filter) { filter.sortByValue = false; });
|
||||
}, &st::menuIconSchedule);
|
||||
} else {
|
||||
addAction(tr::lng_peer_gifts_filter_by_value(tr::now), [=] {
|
||||
change([](Filter &filter) { filter.sortByValue = true; });
|
||||
}, &st::menuIconEarn);
|
||||
}
|
||||
|
||||
addAction({ .isSeparator = true });
|
||||
|
||||
addAction(tr::lng_peer_gifts_filter_unlimited(tr::now), [=] {
|
||||
change([](Filter &filter) {
|
||||
filter.skipUnlimited = !filter.skipUnlimited;
|
||||
if (filter.skipUnlimited
|
||||
&& filter.skipLimited
|
||||
&& filter.skipUnique) {
|
||||
filter.skipLimited = false;
|
||||
}
|
||||
});
|
||||
}, filter.skipUnlimited ? nullptr : &st::mediaPlayerMenuCheck);
|
||||
addAction(tr::lng_peer_gifts_filter_limited(tr::now), [=] {
|
||||
change([](Filter &filter) {
|
||||
filter.skipLimited = !filter.skipLimited;
|
||||
if (filter.skipUnlimited
|
||||
&& filter.skipLimited
|
||||
&& filter.skipUnique) {
|
||||
filter.skipUnlimited = false;
|
||||
}
|
||||
});
|
||||
}, filter.skipLimited ? nullptr : &st::mediaPlayerMenuCheck);
|
||||
addAction(tr::lng_peer_gifts_filter_unique(tr::now), [=] {
|
||||
change([](Filter &filter) {
|
||||
filter.skipUnique = !filter.skipUnique;
|
||||
if (filter.skipUnlimited
|
||||
&& filter.skipLimited
|
||||
&& filter.skipUnique) {
|
||||
filter.skipUnlimited = false;
|
||||
}
|
||||
});
|
||||
}, filter.skipUnique ? nullptr : &st::mediaPlayerMenuCheck);
|
||||
|
||||
addAction({ .isSeparator = true });
|
||||
|
||||
addAction(tr::lng_peer_gifts_filter_saved(tr::now), [=] {
|
||||
change([](Filter &filter) {
|
||||
filter.skipSaved = !filter.skipSaved;
|
||||
if (filter.skipSaved && filter.skipUnsaved) {
|
||||
filter.skipUnsaved = false;
|
||||
}
|
||||
});
|
||||
}, filter.skipSaved ? nullptr : &st::mediaPlayerMenuCheck);
|
||||
addAction(tr::lng_peer_gifts_filter_unsaved(tr::now), [=] {
|
||||
change([](Filter &filter) {
|
||||
filter.skipUnsaved = !filter.skipUnsaved;
|
||||
if (filter.skipSaved && filter.skipUnsaved) {
|
||||
filter.skipSaved = false;
|
||||
}
|
||||
});
|
||||
}, filter.skipUnsaved ? nullptr : &st::mediaPlayerMenuCheck);
|
||||
}
|
||||
|
||||
rpl::producer<QString> Widget::title() {
|
||||
return tr::lng_peer_gifts_title();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,17 @@ struct ListState {
|
|||
QString offset;
|
||||
};
|
||||
|
||||
struct Filter {
|
||||
bool sortByValue : 1 = false;
|
||||
bool skipUnlimited : 1 = false;
|
||||
bool skipLimited : 1 = false;
|
||||
bool skipUnique : 1 = false;
|
||||
bool skipSaved : 1 = false;
|
||||
bool skipUnsaved : 1 = false;
|
||||
|
||||
friend inline bool operator==(Filter, Filter) = default;
|
||||
};
|
||||
|
||||
class InnerWidget;
|
||||
|
||||
class Memento final : public ContentMemento {
|
||||
|
@ -65,6 +76,8 @@ public:
|
|||
const QRect &geometry,
|
||||
not_null<Memento*> memento);
|
||||
|
||||
void fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) override;
|
||||
|
||||
rpl::producer<QString> title() override;
|
||||
|
||||
rpl::producer<bool> desiredBottomShadowVisibility() override;
|
||||
|
@ -82,6 +95,7 @@ private:
|
|||
InnerWidget *_inner = nullptr;
|
||||
QPointer<Ui::SlideWrap<Ui::RpWidget>> _pinnedToBottom;
|
||||
rpl::variable<bool> _hasPinnedToBottom;
|
||||
rpl::variable<Filter> _filter;
|
||||
bool _shown = false;
|
||||
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue