From c6d51dfeb91aa0f81393623a780efbbf295bc9cd Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 15 Jun 2026 22:17:26 +0400 Subject: [PATCH] Show community content on the channel info page instead of a box. --- Telegram/CMakeLists.txt | 2 + Telegram/Resources/langs/lang.strings | 1 + .../SourceFiles/boxes/peers/community_box.cpp | 44 +++---- .../SourceFiles/boxes/peers/community_box.h | 11 +- .../info/community/info_community_widget.cpp | 117 ++++++++++++++++++ .../info/community/info_community_widget.h | 62 ++++++++++ Telegram/SourceFiles/info/info_controller.h | 1 + Telegram/SourceFiles/info/info_memento.cpp | 10 +- .../info/profile/info_profile_actions.cpp | 3 +- .../window/window_session_controller.cpp | 4 +- 10 files changed, 226 insertions(+), 29 deletions(-) create mode 100644 Telegram/SourceFiles/info/community/info_community_widget.cpp create mode 100644 Telegram/SourceFiles/info/community/info_community_widget.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 3c88730fd3..94eaa5e0ae 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1142,6 +1142,8 @@ PRIVATE info/common_groups/info_common_groups_inner_widget.h info/common_groups/info_common_groups_widget.cpp info/common_groups/info_common_groups_widget.h + info/community/info_community_widget.cpp + info/community/info_community_widget.h info/downloads/info_downloads_inner_widget.cpp info/downloads/info_downloads_inner_widget.h info/downloads/info_downloads_provider.cpp diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index a07ad6e1ea..908f955c5a 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2199,6 +2199,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_discussion_group_warning" = "\"Chat history for new members\" will be switched to **Visible**."; "lng_community_title" = "Community"; +"lng_community_manage" = "Manage Community"; "lng_community_add_button" = "Add Group to a Community"; "lng_community_add_about" = "Make your group part of a community with multiple related chats."; "lng_community_create" = "Create Community"; diff --git a/Telegram/SourceFiles/boxes/peers/community_box.cpp b/Telegram/SourceFiles/boxes/peers/community_box.cpp index 2916e259d8..6969db46fc 100644 --- a/Telegram/SourceFiles/boxes/peers/community_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/community_box.cpp @@ -129,23 +129,25 @@ void ChatsController::rowClicked(not_null row) { _callback(row->peer()); } -void CommunityBox( - not_null box, - not_null navigation, - not_null community) { - box->setTitle(Info::Profile::NameValue(community)); - box->setWidth(st::boxWideWidth); +} // namespace +void SetupCommunityContent( + not_null container, + not_null navigation, + not_null community, + std::shared_ptr show) { const auto info = community->communityInfo(); if (!info) { - box->addButton(tr::lng_close(), [=] { box->closeBox(); }); return; } - const auto container = box->verticalLayout(); - box->addTopButton(st::boxTitleClose, [=] { box->closeBox(); }); if (community->canEditInformation()) { - box->addTopButton(st::communityBoxManage, [=] { + Settings::AddButtonWithIcon( + container, + tr::lng_community_manage(), + st::settingsButton, + { &st::menuIconEdit } + )->addClickHandler([=] { ShowManageCommunityBox(navigation, community); }); } @@ -199,7 +201,7 @@ void CommunityBox( auto chats = info->linkedPeersValue( ) | rpl::map([=] { return PartitionChats(info); - }) | rpl::start_spawning(box->lifetime()); + }) | rpl::start_spawning(container->lifetime()); const auto openChat = [=](not_null peer) { navigation->showPeerHistory( @@ -233,8 +235,7 @@ void CommunityBox( const std::shared_ptr _show; }; - const auto delegate = inner->lifetime().make_state( - Main::MakeSessionShow(box->uiShow(), &community->session())); + const auto delegate = inner->lifetime().make_state(show); const auto controller = inner->lifetime().make_state< ChatsController >(&community->session(), std::move(list), openChat); @@ -266,16 +267,22 @@ void CommunityBox( return c.requestable; })); - box->addButton(tr::lng_community_add_chat(), [=] { + Settings::AddButtonWithIcon( + container, + tr::lng_community_add_chat(), + st::settingsButton, + { &st::menuIconGroups } + )->addClickHandler([=] { ShowChooseChatToAddBox(navigation, community); }); - box->addButton(tr::lng_close(), [=] { box->closeBox(); }); if (!community->wasFullUpdated()) { community->session().api().requestFullPeer(community); } } +namespace { + class ChooseChatController final : public PeerListController { public: ChooseChatController( @@ -351,13 +358,6 @@ void ChooseChatController::rowClicked(not_null row) { } // namespace -void ShowCommunityBox( - not_null navigation, - not_null community) { - navigation->uiShow()->showBox( - Box(CommunityBox, navigation, community)); -} - void BanFromCommunityWithWarning( std::shared_ptr show, not_null community, diff --git a/Telegram/SourceFiles/boxes/peers/community_box.h b/Telegram/SourceFiles/boxes/peers/community_box.h index c1e5bdec1f..a398b7d3a3 100644 --- a/Telegram/SourceFiles/boxes/peers/community_box.h +++ b/Telegram/SourceFiles/boxes/peers/community_box.h @@ -12,15 +12,22 @@ class PeerData; namespace Ui { class Show; +class VerticalLayout; } // namespace Ui +namespace Main { +class SessionShow; +} // namespace Main + namespace Window { class SessionNavigation; } // namespace Window -void ShowCommunityBox( +void SetupCommunityContent( + not_null container, not_null navigation, - not_null community); + not_null community, + std::shared_ptr show); void ShowChooseChatToAddBox( not_null navigation, diff --git a/Telegram/SourceFiles/info/community/info_community_widget.cpp b/Telegram/SourceFiles/info/community/info_community_widget.cpp new file mode 100644 index 0000000000..4c4ede6a40 --- /dev/null +++ b/Telegram/SourceFiles/info/community/info_community_widget.cpp @@ -0,0 +1,117 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "info/community/info_community_widget.h" + +#include "boxes/peers/community_box.h" +#include "data/data_channel.h" +#include "info/profile/info_profile_values.h" +#include "info/info_controller.h" +#include "ui/wrap/vertical_layout.h" +#include "ui/ui_utility.h" +#include "styles/style_info.h" + +namespace Info::Community { + +class InnerWidget final : public Ui::VerticalLayout { +public: + InnerWidget( + QWidget *parent, + not_null controller, + not_null peer); + + [[nodiscard]] not_null peer() const { + return _peer; + } + +private: + const not_null _peer; + +}; + +InnerWidget::InnerWidget( + QWidget *parent, + not_null controller, + not_null peer) +: Ui::VerticalLayout(parent) +, _peer(peer) { + if (const auto community = peer->asChannel()) { + SetupCommunityContent(this, controller, community, controller->uiShow()); + } +} + +Memento::Memento(not_null peer) +: ContentMemento(peer, nullptr, nullptr, PeerId()) { +} + +Section Memento::section() const { + return Section(Section::Type::Community); +} + +object_ptr Memento::createWidget( + QWidget *parent, + not_null controller, + const QRect &geometry) { + auto result = object_ptr(parent, controller, peer()); + result->setInternalState(geometry, this); + return result; +} + +Memento::~Memento() = default; + +Widget::Widget( + QWidget *parent, + not_null controller, + not_null peer) +: ContentWidget(parent, controller) { + _inner = setInnerWidget(object_ptr(this, controller, peer)); +} + +rpl::producer Widget::title() { + return Info::Profile::NameValue(peer()); +} + +not_null Widget::peer() const { + return _inner->peer(); +} + +bool Widget::showInternal(not_null memento) { + if (!controller()->validateMementoPeer(memento)) { + return false; + } + if (auto communityMemento = dynamic_cast(memento.get())) { + if (communityMemento->peer() == peer()) { + restoreState(communityMemento); + return true; + } + } + return false; +} + +void Widget::setInternalState( + const QRect &geometry, + not_null memento) { + setGeometry(geometry); + Ui::SendPendingMoveResizeEvents(this); + restoreState(memento); +} + +std::shared_ptr Widget::doCreateMemento() { + auto result = std::make_shared(peer()); + saveState(result.get()); + return result; +} + +void Widget::saveState(not_null memento) { + memento->setScrollTop(scrollTopSave()); +} + +void Widget::restoreState(not_null memento) { + scrollTopRestore(memento->scrollTop()); +} + +} // namespace Info::Community diff --git a/Telegram/SourceFiles/info/community/info_community_widget.h b/Telegram/SourceFiles/info/community/info_community_widget.h new file mode 100644 index 0000000000..045ab36dc3 --- /dev/null +++ b/Telegram/SourceFiles/info/community/info_community_widget.h @@ -0,0 +1,62 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "info/info_content_widget.h" + +class PeerData; +class ChannelData; + +namespace Info::Community { + +class InnerWidget; + +class Memento final : public ContentMemento { +public: + explicit Memento(not_null peer); + + object_ptr createWidget( + QWidget *parent, + not_null controller, + const QRect &geometry) override; + + Section section() const override; + + ~Memento(); + +}; + +class Widget final : public ContentWidget { +public: + Widget( + QWidget *parent, + not_null controller, + not_null peer); + + [[nodiscard]] not_null peer() const; + + bool showInternal( + not_null memento) override; + + void setInternalState( + const QRect &geometry, + not_null memento); + + rpl::producer title() override; + +private: + void saveState(not_null memento); + void restoreState(not_null memento); + + std::shared_ptr doCreateMemento() override; + + InnerWidget *_inner = nullptr; + +}; + +} // namespace Info::Community diff --git a/Telegram/SourceFiles/info/info_controller.h b/Telegram/SourceFiles/info/info_controller.h index 14ad24d686..258f05eccb 100644 --- a/Telegram/SourceFiles/info/info_controller.h +++ b/Telegram/SourceFiles/info/info_controller.h @@ -157,6 +157,7 @@ public: CommonGroups, SimilarPeers, RequestsList, + Community, ReactionsList, SavedSublists, PeerGifts, diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 86ec371fe4..dc0985f572 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/similar_peers/info_similar_peers_widget.h" #include "info/reactions_list/info_reactions_list_widget.h" #include "info/requests_list/info_requests_list_widget.h" +#include "info/community/info_community_widget.h" #include "info/peer_gifts/info_peer_gifts_widget.h" #include "info/polls/info_polls_list_widget.h" #include "info/polls/info_polls_results_widget.h" @@ -35,7 +36,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Info { Memento::Memento(not_null peer) -: Memento(peer, Section::Type::Profile) { +: Memento(peer, [&] { + const auto channel = peer->asChannel(); + return (channel && channel->isCommunity()) + ? Section::Type::Community + : Section::Type::Profile; +}()) { } Memento::Memento(not_null peer, Section section) @@ -217,6 +223,8 @@ std::shared_ptr Memento::DefaultContent( return std::make_shared(peer); case Section::Type::RequestsList: return std::make_shared(peer); + case Section::Type::Community: + return std::make_shared(peer); case Section::Type::SavedSublists: return std::make_shared(&peer->session()); case Section::Type::Members: diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index 34e98a067d..9c9332b456 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "boxes/peer_list_box.h" #include "boxes/peers/add_bot_to_chat_box.h" -#include "boxes/peers/community_box.h" #include "boxes/peers/edit_contact_box.h" #include "boxes/peers/edit_participants_box.h" #include "boxes/peers/edit_peer_info_box.h" @@ -2604,7 +2603,7 @@ Section DetailsFiller::makeCommunityLink(not_null channel) { >(); const auto controller = container->lifetime().make_state( community, - [=] { ShowCommunityBox(window, community); }); + [=] { window->showPeerInfo(community); }); const auto content = container->add(object_ptr( container, controller)); diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 18aab18008..0899a03722 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -2757,7 +2757,7 @@ bool SessionController::canShowSeparateWindow(SeparateId id) const { void SessionController::showPeer(not_null peer, MsgId msgId) { if (const auto channel = peer->asChannel()) { if (channel->isCommunity()) { - ShowCommunityBox(this, channel); + showPeerInfo(channel, SectionShow()); return; } } @@ -3089,7 +3089,7 @@ void SessionController::showPeerHistory( if (const auto peer = session().data().peerLoaded(peerId)) { if (const auto channel = peer->asChannel()) { if (channel->isCommunity()) { - ShowCommunityBox(this, channel); + showPeerInfo(channel, SectionShow()); return; } }