diff --git a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp index 8161553c5..57cfe1b33 100644 --- a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp +++ b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp @@ -12,11 +12,97 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer.h" #include "data/data_session.h" #include "data/data_user.h" +#include "lang/lang_keys.h" #include "main/main_session.h" #include "ui/boxes/confirm_box.h" -#include "lang/lang_keys.h" +#include "ui/effects/ripple_animation.h" +#include "ui/painter.h" +#include "styles/style_statistics.h" namespace Giveaway { +namespace { + +class ChannelRow final : public PeerListRow { +public: + using PeerListRow::PeerListRow; + + QSize rightActionSize() const override; + QMargins rightActionMargins() const override; + void rightActionPaint( + Painter &p, + int x, + int y, + int outerWidth, + bool selected, + bool actionSelected) override; + + void rightActionAddRipple( + QPoint point, + Fn updateCallback) override; + void rightActionStopLastRipple() override; + +private: + std::unique_ptr _actionRipple; + +}; + +QSize ChannelRow::rightActionSize() const { + return QSize( + st::giveawayGiftCodeChannelDeleteIcon.width(), + st::giveawayGiftCodeChannelDeleteIcon.height()) * 2; +} + +QMargins ChannelRow::rightActionMargins() const { + return QMargins( + 0, + (st::defaultPeerListItem.height - rightActionSize().height()) / 2, + st::giveawayRadioPosition.x() / 2, + 0); +} + +void ChannelRow::rightActionPaint( + Painter &p, + int x, + int y, + int outerWidth, + bool selected, + bool actionSelected) { + if (_actionRipple) { + _actionRipple->paint( + p, + x, + y, + outerWidth); + if (_actionRipple->empty()) { + _actionRipple.reset(); + } + } + const auto rect = QRect(QPoint(x, y), ChannelRow::rightActionSize()); + (actionSelected + ? st::giveawayGiftCodeChannelDeleteIconOver + : st::giveawayGiftCodeChannelDeleteIcon).paintInCenter(p, rect); +} + +void ChannelRow::rightActionAddRipple( + QPoint point, + Fn updateCallback) { + if (!_actionRipple) { + auto mask = Ui::RippleAnimation::EllipseMask(rightActionSize()); + _actionRipple = std::make_unique( + st::defaultRippleAnimation, + std::move(mask), + std::move(updateCallback)); + } + _actionRipple->add(point); +} + +void ChannelRow::rightActionStopLastRipple() { + if (_actionRipple) { + _actionRipple->lastStop(); + } +} + +} // namespace AwardMembersListController::AwardMembersListController( not_null navigation, @@ -150,4 +236,72 @@ std::unique_ptr MyChannelsListController::createRow( return row; } +SelectedChannelsListController::SelectedChannelsListController( + not_null peer) +: _peer(peer) { +} + +void SelectedChannelsListController::setTopStatus(rpl::producer s) { + _statusLifetime = std::move( + s + ) | rpl::start_with_next([=](const QString &t) { + if (delegate()->peerListFullRowsCount() > 0) { + delegate()->peerListRowAt(0)->setCustomStatus(t); + } + }); +} + +void SelectedChannelsListController::rebuild( + std::vector> selected) { + while (delegate()->peerListFullRowsCount() > 1) { + delegate()->peerListRemoveRow(delegate()->peerListRowAt(1)); + } + for (const auto &peer : selected) { + delegate()->peerListAppendRow(createRow(peer->asChannel())); + } + delegate()->peerListRefreshRows(); +} + +auto SelectedChannelsListController::channelRemoved() const +-> rpl::producer> { + return _channelRemoved.events(); +} + +void SelectedChannelsListController::rowClicked(not_null row) { +} + +void SelectedChannelsListController::rowRightActionClicked( + not_null row) { + const auto peer = row->peer(); + delegate()->peerListRemoveRow(row); + delegate()->peerListRefreshRows(); + _channelRemoved.fire_copy(peer); +} + +Main::Session &SelectedChannelsListController::session() const { + return _peer->session(); +} + +void SelectedChannelsListController::prepare() { + delegate()->peerListAppendRow(createRow(_peer->asChannel())); +} + +std::unique_ptr SelectedChannelsListController::createRow( + not_null channel) const { + if (channel->isMegagroup()) { + return nullptr; + } + const auto isYourChannel = (_peer->asChannel() == channel); + auto row = isYourChannel + ? std::make_unique(channel) + : std::make_unique(channel); + row->setCustomStatus(isYourChannel + ? QString() + : tr::lng_chat_status_subscribers( + tr::now, + lt_count, + channel->membersCount())); + return row; +} + } // namespace Giveaway diff --git a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h index 46c0a53a3..2c1e589c2 100644 --- a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h +++ b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h @@ -67,4 +67,29 @@ private: }; +class SelectedChannelsListController : public PeerListController { +public: + SelectedChannelsListController(not_null peer); + + void setTopStatus(rpl::producer status); + + void rebuild(std::vector> selected); + [[nodiscard]] rpl::producer> channelRemoved() const; + + Main::Session &session() const override; + void prepare() override; + void rowClicked(not_null row) override; + void rowRightActionClicked(not_null row) override; + +private: + std::unique_ptr createRow( + not_null channel) const; + + const not_null _peer; + + rpl::event_stream> _channelRemoved; + rpl::lifetime _statusLifetime; + +}; + } // namespace Giveaway diff --git a/Telegram/SourceFiles/statistics/statistics.style b/Telegram/SourceFiles/statistics/statistics.style index 449c22293..ba72e5973 100644 --- a/Telegram/SourceFiles/statistics/statistics.style +++ b/Telegram/SourceFiles/statistics/statistics.style @@ -165,3 +165,6 @@ giveawayGiftCodeCountryButton: SettingsButton(reportReasonButton) { } giveawayGiftCodeCountrySelect: MultiSelect(defaultMultiSelect) { } + +giveawayGiftCodeChannelDeleteIcon: icon {{ "dialogs/dialogs_cancel_search", dialogsMenuIconFg }}; +giveawayGiftCodeChannelDeleteIconOver: icon {{ "dialogs/dialogs_cancel_search", dialogsMenuIconFgOver }};