diff --git a/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.cpp b/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.cpp index 2141c426f7..d131984b9c 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.cpp @@ -7,13 +7,17 @@ #include "per_dialog_filter.h" #include + #include "lang_auto.h" #include "settings_filters_list.h" +#include "ayu/ayu_settings.h" #include "ayu/data/ayu_database.h" +#include "ayu/features/filters/shadow_ban_utils.h" #include "ayu/utils/telegram_helpers.h" #include "data/data_peer.h" #include "data/data_session.h" #include "main/main_session.h" +#include "styles/style_menu_icons.h" #include "ui/painter.h" #include "window/window_session_controller.h" @@ -50,16 +54,35 @@ PaintRoundImageCallback PerDialogFiltersListRow::generatePaintUserpicCallback(bo } PerDialogFiltersListController::PerDialogFiltersListController(not_null session, - not_null controller) + not_null controller, + bool shadowBan) : _session(session) - , _controller(controller) { + , _controller(controller) + , shadowBan(shadowBan) { } Main::Session &PerDialogFiltersListController::session() const { return *_session; } +void PerDialogFiltersListController::prepareShadowBan() { + const auto &settings = AyuSettings::getInstance(); + const auto &shadowBanned = settings.shadowBanIds; + + for (const auto id : shadowBanned) { + auto peerId = PeerId(PeerIdHelper(abs(id))); + + auto row = std::make_unique(peerId); + + delegate()->peerListAppendRow(reinterpret_cast&&>(row)); + } +} + void PerDialogFiltersListController::prepare() { + if (shadowBan) { + prepareShadowBan(); + return; + } const auto filters = AyuDatabase::getAllRegexFilters(); const auto exclusions = AyuDatabase::getAllFiltersExclusions(); @@ -106,7 +129,7 @@ void PerDialogFiltersListController::prepare() { void PerDialogFiltersListController::rowClicked(not_null peer) { ID did; if (peer->special()) { - const ID pred = peer->id() & PeerId::kChatTypeMask; + const ID pred = peer->id() & PeerId::kChatTypeMask; if (countsByDialogIds.contains(pred)) { did = pred; } else { @@ -115,47 +138,28 @@ void PerDialogFiltersListController::rowClicked(not_null peer) { } else { did = getDialogIdFromPeer(peer->peer()); } + if (shadowBan) { + auto _contextMenu = new Ui::PopupMenu(nullptr, st::popupMenuWithIcons); + _contextMenu->setAttribute(Qt::WA_DeleteOnClose); + + _contextMenu->addAction( + tr::lng_theme_delete(tr::now), + [=] + { + if (ShadowBanUtils::isShadowBanned(did)) { + ShadowBanUtils::removeShadowBan(did); + } else { + ShadowBanUtils::addShadowBan(did); + } + }, + &st::menuIconDelete); + + _contextMenu->popup(QCursor::pos()); + return; + } _controller->dialogId = did; _controller->showExclude = true; _controller->showSettings(AyuFiltersList::Id()); } -SelectChatBoxController::SelectChatBoxController( - not_null controller, - Fn)> onSelectedCallback) - : ChatsListBoxController(&controller->session()) - , _controller(controller) - , _onSelectedCallback(std::move(onSelectedCallback)) { -} - -Main::Session &SelectChatBoxController::session() const { - return _controller->session(); -} - -void SelectChatBoxController::rowClicked(not_null row) { - if (_onSelectedCallback) { - _onSelectedCallback(row->peer()); - } -} - -std::unique_ptr SelectChatBoxController::createRow(not_null history) { - const auto peer = history->peer; - - const auto skip = - peer->isUser() || - //peer->forum() || - peer->monoforum(); - - if (skip) { - return nullptr; - } - auto result = std::make_unique( - history, - nullptr); - return result; -} - -void SelectChatBoxController::prepareViewHook() { - delegate()->peerListSetTitle(tr::ayu_FiltersMenuSelectChat()); -} } diff --git a/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.h b/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.h index 4e319fc236..f73ca9d3ad 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.h +++ b/Telegram/SourceFiles/ayu/ui/settings/filters/per_dialog_filter.h @@ -35,7 +35,8 @@ class PerDialogFiltersListController final : public PeerListController { public: explicit PerDialogFiltersListController(not_null session, - not_null controller); + not_null controller, + bool shadowBan = false); [[nodiscard]] Main::Session &session() const override; @@ -44,36 +45,19 @@ public: void rowClicked(not_null row) override; private: + void prepareShadowBan(); + struct FilterCounts { int filters = 0; int exclusions = 0; }; + std::unordered_map countsByDialogIds; const not_null _session; not_null _controller; + bool shadowBan; }; -class SelectChatBoxController - : public ChatsListBoxController - , public base::has_weak_ptr -{ -public: - explicit SelectChatBoxController( - not_null controller, - Fn)> onSelectedCallback - ); - - Main::Session &session() const override; - void rowClicked(not_null row) override; - -protected: - std::unique_ptr createRow(not_null history) override; - void prepareViewHook() override; - -private: - not_null _controller; - Fn)> _onSelectedCallback; -}; -} // namespace Settings \ No newline at end of file +} // namespace Settings diff --git a/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.cpp b/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.cpp index d1ceb29805..d29cb37b60 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.cpp @@ -6,28 +6,25 @@ // Copyright @Radolyn, 2025 #include "settings_filters_list.h" -#include -#include - #include "edit_filter.h" -#include "ayu/ayu_settings.h" - #include "lang_auto.h" - -#include "boxes/connection_box.h" -#include "settings/settings_common.h" -#include "storage/localstorage.h" -#include "styles/style_menu_icons.h" -#include "styles/style_settings.h" -#include "styles/style_widgets.h" - -#include "../../components/icon_picker.h" +#include "per_dialog_filter.h" +#include "ayu/ayu_settings.h" #include "ayu/data/ayu_database.h" #include "ayu/features/filters/filters_cache_controller.h" #include "ayu/features/filters/filters_utils.h" +#include "ayu/ui/components/icon_picker.h" #include "ayu/utils/telegram_helpers.h" +#include "boxes/connection_box.h" #include "data/data_channel.h" #include "info/info_wrap_widget.h" +#include "settings/settings_common.h" +#include "storage/localstorage.h" +#include "styles/style_boxes.h" +#include "styles/style_media_view.h" +#include "styles/style_menu_icons.h" +#include "styles/style_settings.h" +#include "styles/style_widgets.h" #include "ui/qt_object_factory.h" #include "ui/vertical_list.h" #include "ui/widgets/buttons.h" @@ -38,6 +35,9 @@ namespace Settings { rpl::producer AyuFiltersList::title() { + if (shadowBan) { + return tr::ayu_FiltersShadowBan(); + } if (!dialogId.has_value()) { return tr::ayu_RegexFiltersShared(); } @@ -64,7 +64,8 @@ rpl::producer AyuFiltersList::title() { AyuFiltersList::AyuFiltersList( QWidget *parent, not_null controller) - : Section(parent), _controller(controller), _content(Ui::CreateChild(this)) { + : Section(parent), _controller(controller), _content(Ui::CreateChild(this)), + shadowBan(_controller->shadowBan) { if (_controller->dialogId.has_value()) { dialogId = _controller->dialogId.value(); } @@ -74,6 +75,7 @@ AyuFiltersList::AyuFiltersList( void AyuFiltersList::checkBeforeClose(Fn close) { _controller->showExclude = true; + _controller->shadowBan = false; close(); } @@ -260,8 +262,43 @@ void AyuFiltersList::initializeSharedFilters( } } +void AyuFiltersList::initializeShadowBan(not_null container) { + auto ctrl = container->lifetime().make_state( + &_controller->session(), + _controller, + true // shadowBan + ); + + auto list = object_ptr>( + container, + object_ptr( + container, + ctrl), + QMargins(0, -st::peerListBox.padding.top(), 0, -st::peerListBox.padding.bottom())); + + // delegate is not initialized at this moment + if (AyuSettings::getInstance().shadowBanIds.size() > 0) { + AddSkip(container); + + filtersTitle = AddSubsectionTitle(container, tr::ayu_RegexFiltersHeader()); + const auto content = container->add(std::move(list)); + + AddSkip(container); + + auto delegate = container->lifetime().make_state(); + delegate->setContent(content->entity()); + ctrl->setDelegate(delegate); + } else { + Ui::AddDividerText(container, tr::ayu_RegexFiltersListEmpty()); + } +} + void AyuFiltersList::setupContent(not_null controller) { - initializeSharedFilters(_content); + if (shadowBan) { + initializeShadowBan(_content); + } else { + initializeSharedFilters(_content); + } ResizeFitChild(this, _content); } diff --git a/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.h b/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.h index 9e210cbf60..fafc48a4f0 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.h +++ b/Telegram/SourceFiles/ayu/ui/settings/filters/settings_filters_list.h @@ -33,6 +33,7 @@ public: private: void setupContent(not_null controller); void initializeSharedFilters(not_null container); + void initializeShadowBan(not_null container); void addNewFilter(const RegexFilter &filter, bool exclusion = false); @@ -46,6 +47,7 @@ private: Ui::FlatLabel *excludedTitle = nullptr; std::optional dialogId; + bool shadowBan; }; -} // namespace Settings \ No newline at end of file +} // namespace Settings diff --git a/Telegram/SourceFiles/ayu/ui/settings/settings_filters.cpp b/Telegram/SourceFiles/ayu/ui/settings/settings_filters.cpp index f332686d22..21741c67d9 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/settings_filters.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/settings_filters.cpp @@ -212,6 +212,21 @@ void SetupShared(not_null controller, }); } +void SetupShadowBan(not_null controller, + Ui::VerticalLayout *container) { + auto button = container->add(object_ptr( + container, + tr::ayu_FiltersShadowBan() + )); + button->addClickHandler([=] + { + controller->dialogId = std::nullopt; + controller->showExclude = false; + controller->shadowBan = true; + controller->showSettings(AyuFiltersList::Id()); + }); +} + void SetupPerDialog( not_null controller, not_null container @@ -268,6 +283,7 @@ void AyuFilters::setupContent(not_null controller) { AddDivider(content); SetupShared(controller, content); + SetupShadowBan(controller, content); if (AyuDatabase::hasPerDialogFilters()) { AddSkip(content); diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 609a711a16..3bf42c816b 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -55,9 +55,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL // AyuGram includes #include "ayu/ayu_settings.h" +#include "ayu/features/filters/shadow_ban_utils.h" #include "ayu/ui/settings/filters/edit_filter.h" #include "ayu/ui/settings/filters/settings_filters_list.h" +#include "ayu/utils/telegram_helpers.h" +#include "inline_bots/bot_attach_web_view.h" #include "styles/style_ayu_settings.h" +#include "window/window_peer_menu.h" namespace Info { namespace { @@ -431,12 +435,34 @@ void WrapWidget::setupTopBarMenuToggle() { const auto button = _topBar->addButton(base::make_unique_q(_topBar, st)); const auto show = controller->uiShow(); + if (controller->shadowBan) { + auto types = InlineBots::PeerTypes(); + types |= InlineBots::PeerType::Bot; + types |= InlineBots::PeerType::User; - button->addClickHandler( - [=] + button->addClickHandler([=] + { + Window::ShowChooseRecipientBox( + controller, + [=](not_null thread) + { + const auto peer = thread->peer(); + const auto realId = getDialogIdFromPeer(peer); + + ShadowBanUtils::addShadowBan(realId); + return true; + }, + tr::ayu_FiltersMenuSelectChat(), + nullptr, + types + ); + }); + } else { + button->addClickHandler([=] { show->show(::Settings::RegexEditBox(nullptr, nullptr, controller->dialogId)); }); + } if (controller->showExclude.has_value() && controller->showExclude.value()) { diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index d428e87f7e..cf6df03dc6 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -702,6 +702,7 @@ public: std::optional dialogId; std::vector filterId; std::optional showExclude; // whether to show exclude button in the top bar + bool shadowBan = false; private: struct CachedThemeKey; struct CachedTheme;