Implement restrictions on topics enabling.

This commit is contained in:
John Preston 2022-10-25 18:07:05 +04:00
parent aac91a19ca
commit 99564d3d44
7 changed files with 138 additions and 31 deletions

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper #include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/toasts/common_toasts.h"
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -32,6 +33,7 @@ constexpr auto kEnableSearchRowsCount = 10;
class Controller : public PeerListController, public base::has_weak_ptr { class Controller : public PeerListController, public base::has_weak_ptr {
public: public:
Controller( Controller(
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
ChannelData *chat, ChannelData *chat,
const std::vector<not_null<PeerData*>> &chats, const std::vector<not_null<PeerData*>> &chats,
@ -47,6 +49,7 @@ private:
void choose(not_null<ChannelData*> chat); void choose(not_null<ChannelData*> chat);
void choose(not_null<ChatData*> chat); void choose(not_null<ChatData*> chat);
not_null<Window::SessionNavigation*> _navigation;
not_null<ChannelData*> _channel; not_null<ChannelData*> _channel;
ChannelData *_chat = nullptr; ChannelData *_chat = nullptr;
std::vector<not_null<PeerData*>> _chats; std::vector<not_null<PeerData*>> _chats;
@ -59,12 +62,14 @@ private:
}; };
Controller::Controller( Controller::Controller(
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
ChannelData *chat, ChannelData *chat,
const std::vector<not_null<PeerData*>> &chats, const std::vector<not_null<PeerData*>> &chats,
Fn<void(ChannelData*)> callback, Fn<void(ChannelData*)> callback,
Fn<void(not_null<PeerData*>)> showHistoryCallback) Fn<void(not_null<PeerData*>)> showHistoryCallback)
: _channel(channel) : _navigation(navigation)
, _channel(channel)
, _chat(chat) , _chat(chat)
, _chats(std::move(chats)) , _chats(std::move(chats))
, _callback(std::move(callback)) , _callback(std::move(callback))
@ -131,6 +136,10 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
} }
void Controller::choose(not_null<ChannelData*> chat) { void Controller::choose(not_null<ChannelData*> chat) {
if (chat->isForum()) {
ShowForumForDiscussionError(_navigation);
return;
}
auto text = tr::lng_manage_discussion_group_sure( auto text = tr::lng_manage_discussion_group_sure(
tr::now, tr::now,
lt_group, lt_group,
@ -324,6 +333,7 @@ object_ptr<Ui::BoxContent> EditLinkedChatBox(
ShowAtUnreadMsgId); ShowAtUnreadMsgId);
}; };
auto controller = std::make_unique<Controller>( auto controller = std::make_unique<Controller>(
navigation,
channel, channel,
chat, chat,
std::move(chats), std::move(chats),
@ -362,3 +372,13 @@ object_ptr<Ui::BoxContent> EditLinkedChatBox(
canEdit, canEdit,
callback); callback);
} }
void ShowForumForDiscussionError(
not_null<Window::SessionNavigation*> navigation) {
Ui::ShowMultilineToast({
.parentOverride = Window::Show(navigation).toastParent(),
.text = tr::lng_forum_topics_no_discussion(
tr::now,
Ui::Text::RichLangValue),
});
}

View file

@ -29,3 +29,6 @@ object_ptr<Ui::BoxContent> EditLinkedChatBox(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
std::vector<not_null<PeerData*>> &&chats, std::vector<not_null<PeerData*>> &&chats,
Fn<void(ChannelData*)> callback); Fn<void(ChannelData*)> callback);
void ShowForumForDiscussionError(
not_null<Window::SessionNavigation*> navigation);

View file

@ -39,10 +39,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "main/main_session.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
@ -67,6 +72,12 @@ namespace {
}); });
} }
[[nodiscard]] int EnableForumMinMembers(not_null<PeerData*> peer) {
return peer->session().account().appConfig().get<int>(
u"forum_upgrade_participants_min"_q,
200);
}
void AddSkip( void AddSkip(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container,
int top = st::editPeerTopButtonsLayoutSkip, int top = st::editPeerTopButtonsLayoutSkip,
@ -253,6 +264,8 @@ private:
Ui::UserpicButton *photo = nullptr; Ui::UserpicButton *photo = nullptr;
rpl::lifetime initialPhotoImageWaiting; rpl::lifetime initialPhotoImageWaiting;
Ui::VerticalLayout *buttonsLayout = nullptr; Ui::VerticalLayout *buttonsLayout = nullptr;
Ui::SettingsButton *forumToggle = nullptr;
bool forumToggleLocked = false;
Ui::SlideWrap<> *historyVisibilityWrap = nullptr; Ui::SlideWrap<> *historyVisibilityWrap = nullptr;
}; };
struct Saving { struct Saving {
@ -279,6 +292,7 @@ private:
[[nodiscard]] bool canEditInformation() const; [[nodiscard]] bool canEditInformation() const;
[[nodiscard]] bool canEditReactions() const; [[nodiscard]] bool canEditReactions() const;
void refreshHistoryVisibility(); void refreshHistoryVisibility();
void refreshForumToggleLocked();
void showEditPeerTypeBox( void showEditPeerTypeBox(
std::optional<rpl::producer<QString>> error = {}); std::optional<rpl::producer<QString>> error = {});
void showEditLinkedChatBox(); void showEditLinkedChatBox();
@ -614,7 +628,8 @@ void Controller::refreshHistoryVisibility() {
_controls.historyVisibilityWrap->toggle( _controls.historyVisibilityWrap->toggle(
(!withUsername (!withUsername
&& !_channelHasLocationOriginalValue && !_channelHasLocationOriginalValue
&& (!_linkedChatSavedValue || !*_linkedChatSavedValue)), && (!_linkedChatSavedValue || !*_linkedChatSavedValue)
&& (!_forumSavedValue || !*_forumSavedValue)),
anim::type::instant); anim::type::instant);
} }
@ -645,6 +660,11 @@ void Controller::showEditPeerTypeBox(
void Controller::showEditLinkedChatBox() { void Controller::showEditLinkedChatBox() {
Expects(_peer->isChannel()); Expects(_peer->isChannel());
if (_forumSavedValue && *_forumSavedValue) {
ShowForumForDiscussionError(_navigation);
return;
}
const auto box = std::make_shared<QPointer<Ui::BoxContent>>(); const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
const auto callback = [=](ChannelData *result) { const auto callback = [=](ChannelData *result) {
@ -654,6 +674,7 @@ void Controller::showEditLinkedChatBox() {
*_linkedChatSavedValue = result; *_linkedChatSavedValue = result;
_linkedChatUpdates.fire_copy(result); _linkedChatUpdates.fire_copy(result);
refreshHistoryVisibility(); refreshHistoryVisibility();
refreshForumToggleLocked();
}; };
const auto canEdit = channel->isBroadcast() const auto canEdit = channel->isBroadcast()
? channel->canEditInformation() ? channel->canEditInformation()
@ -675,8 +696,14 @@ void Controller::showEditLinkedChatBox() {
} else if (!canEdit || _linkedChatsRequestId) { } else if (!canEdit || _linkedChatsRequestId) {
return; return;
} else if (channel->isMegagroup()) { } else if (channel->isMegagroup()) {
// Restore original linked channel. if (_forumSavedValue
callback(_linkedChatOriginalValue); && *_forumSavedValue
&& _linkedChatOriginalValue) {
ShowForumForDiscussionError(_navigation);
} else {
// Restore original linked channel.
callback(_linkedChatOriginalValue);
}
return; return;
} }
_linkedChatsRequestId = _api.request( _linkedChatsRequestId = _api.request(
@ -817,22 +844,58 @@ void Controller::fillLinkedChatButton() {
void Controller::fillForumButton() { void Controller::fillForumButton() {
Expects(_controls.buttonsLayout != nullptr); Expects(_controls.buttonsLayout != nullptr);
const auto channel = _peer->asChannel(); const auto button = _controls.forumToggle = _controls.buttonsLayout->add(
if (!channel || !channel->amCreator()) { EditPeerInfoBox::CreateButton(
return; _controls.buttonsLayout,
} tr::lng_forum_topics_switch(),
rpl::single(QString()),
AddButtonWithText( [] {},
_controls.buttonsLayout, st::manageGroupTopicsButton,
tr::lng_forum_topics_switch(), { &st::settingsIconGroup, Settings::kIconPurple }));
rpl::single(QString()), const auto unlocks = std::make_shared<rpl::event_stream<bool>>();
[] {}, button->toggleOn(
{ &st::settingsIconGroup, Settings::kIconPurple } rpl::single(_peer->isForum()) | rpl::then(unlocks->events())
)->toggleOn(rpl::single(channel->isForum())
)->toggledValue( )->toggledValue(
) | rpl::start_with_next([=](bool toggled) { ) | rpl::start_with_next([=](bool toggled) {
_forumSavedValue = toggled; if (_controls.forumToggleLocked && toggled) {
unlocks->fire(false);
if (_linkedChatSavedValue && *_linkedChatSavedValue) {
ShowForumForDiscussionError(_navigation);
} else {
Ui::ShowMultilineToast({
.parentOverride = Window::Show(
_navigation).toastParent(),
.text = tr::lng_forum_topics_not_enough(
tr::now,
lt_count,
EnableForumMinMembers(_peer),
Ui::Text::RichLangValue),
});
}
} else {
_forumSavedValue = toggled;
if (toggled) {
_savingData.hiddenPreHistory = false;
}
refreshHistoryVisibility();
}
}, _controls.buttonsLayout->lifetime()); }, _controls.buttonsLayout->lifetime());
refreshForumToggleLocked();
}
void Controller::refreshForumToggleLocked() {
if (!_controls.forumToggle) {
return;
}
const auto limit = EnableForumMinMembers(_peer);
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
const auto notenough = !_peer->isForum()
&& ((chat ? chat->count : channel->membersCount()) < limit);
const auto linked = _linkedChatSavedValue
&& *_linkedChatSavedValue;
const auto locked = _controls.forumToggleLocked = notenough || linked;
_controls.forumToggle->setToggleLocked(locked);
} }
void Controller::fillSignaturesButton() { void Controller::fillSignaturesButton() {
@ -943,8 +1006,8 @@ void Controller::fillManageSection() {
: chat->canEditPreHistoryHidden(); : chat->canEditPreHistoryHidden();
}(); }();
const auto canEditForum = isChannel const auto canEditForum = isChannel
&& channel->isMegagroup() ? (channel->isMegagroup() && channel->amCreator())
&& channel->canEditInformation(); : chat->amCreator();
const auto canEditPermissions = [&] { const auto canEditPermissions = [&] {
return isChannel return isChannel
@ -1703,9 +1766,20 @@ void Controller::togglePreHistoryHidden(
void Controller::saveForum() { void Controller::saveForum() {
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
if (!_savingData.forum if (!_savingData.forum
|| !channel || *_savingData.forum == _peer->isForum()) {
|| *_savingData.forum == channel->isForum()) {
return continueSave(); return continueSave();
} else if (!channel) {
const auto saveForChannel = [=](not_null<ChannelData*> channel) {
if (_peer->asChannel() == channel) {
saveForum();
} else {
cancelSave();
}
};
_peer->session().api().migrateChat(
_peer->asChat(),
crl::guard(this, saveForChannel));
return;
} }
_api.request(MTPchannels_ToggleForum( _api.request(MTPchannels_ToggleForum(
channel->inputChannel, channel->inputChannel,

View file

@ -111,7 +111,7 @@ void Forum::preloadTopics() {
} }
void Forum::reloadTopics() { void Forum::reloadTopics() {
_allLoaded = false; _topicsList.setLoaded(false);
session().api().request(base::take(_requestId)).cancel(); session().api().request(base::take(_requestId)).cancel();
_offsetDate = 0; _offsetDate = 0;
_offsetId = _offsetTopicId = 0; _offsetId = _offsetTopicId = 0;
@ -124,7 +124,7 @@ void Forum::reloadTopics() {
} }
void Forum::requestTopics() { void Forum::requestTopics() {
if (_allLoaded || _requestId) { if (_topicsList.loaded() || _requestId) {
return; return;
} }
const auto firstLoad = !_offsetDate; const auto firstLoad = !_offsetDate;
@ -141,13 +141,13 @@ void Forum::requestTopics() {
applyReceivedTopics(result, true); applyReceivedTopics(result, true);
_requestId = 0; _requestId = 0;
_chatsListChanges.fire({}); _chatsListChanges.fire({});
if (_allLoaded) { if (_topicsList.loaded()) {
_chatsListLoadedEvents.fire({}); _chatsListLoadedEvents.fire({});
} }
requestSomeStale(); requestSomeStale();
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
_allLoaded = true;
_requestId = 0; _requestId = 0;
_topicsList.setLoaded();
if (error.type() == u"CHANNEL_FORUM_MISSING"_q) { if (error.type() == u"CHANNEL_FORUM_MISSING"_q) {
const auto flags = channel()->flags() & ~ChannelDataFlag::Forum; const auto flags = channel()->flags() & ~ChannelDataFlag::Forum;
channel()->setFlags(flags); channel()->setFlags(flags);
@ -215,7 +215,7 @@ void Forum::applyReceivedTopics(
} }
if (updateOffset if (updateOffset
&& (list.isEmpty() || list.size() == data.vcount().v)) { && (list.isEmpty() || list.size() == data.vcount().v)) {
_allLoaded = true; _topicsList.setLoaded();
} }
if (!_staleRootIds.empty()) { if (!_staleRootIds.empty()) {
requestSomeStale(); requestSomeStale();

View file

@ -103,7 +103,6 @@ private:
TimeId _offsetDate = 0; TimeId _offsetDate = 0;
MsgId _offsetId = 0; MsgId _offsetId = 0;
MsgId _offsetTopicId = 0; MsgId _offsetTopicId = 0;
bool _allLoaded = false;
base::flat_set<MsgId> _creatingRootIds; base::flat_set<MsgId> _creatingRootIds;

View file

@ -567,10 +567,11 @@ peerPermissionsButton: SettingsCountButton(managePeerButton) {
iconPosition: point(24px, 5px); iconPosition: point(24px, 5px);
} }
manageGroupButtonInner: SettingsButton(infoProfileButton) {
padding: margins(60px, 10px, 24px, 8px);
}
manageGroupButton: SettingsCountButton(managePeerButton) { manageGroupButton: SettingsCountButton(managePeerButton) {
button: SettingsButton(infoProfileButton) { button: manageGroupButtonInner;
padding: margins(60px, 10px, 24px, 8px);
}
labelPosition: point(22px, 12px); labelPosition: point(22px, 12px);
iconPosition: point(20px, 4px); iconPosition: point(20px, 4px);
} }
@ -579,6 +580,16 @@ manageGroupTopButtonWithText: SettingsCountButton(manageGroupButton) {
labelPosition: point(22px, 10px); labelPosition: point(22px, 10px);
iconPosition: point(0px, 0px); iconPosition: point(0px, 0px);
} }
manageGroupTopicsButton: SettingsCountButton(manageGroupTopButtonWithText) {
button: SettingsButton(manageGroupButtonInner) {
toggle: Toggle(infoProfileToggle) {
lockIcon: icon {{ "info/info_rights_lock", menuIconFg }};
}
toggleOver: Toggle(infoProfileToggleOver) {
lockIcon: icon {{ "info/info_rights_lock", menuIconFgOver }};
}
}
}
manageDeleteGroupButton: SettingsCountButton(manageGroupTopButtonWithText) { manageDeleteGroupButton: SettingsCountButton(manageGroupTopButtonWithText) {
button: SettingsButton(infoProfileButton) { button: SettingsButton(infoProfileButton) {

@ -1 +1 @@
Subproject commit 7f1dd3c351f534d0564c41376176eb0cd1be4184 Subproject commit 865056eec8986bfbdc7f1194ef16ea9db6243742