diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index cad1098f82..7733927a03 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1000,6 +1000,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_profile_view_discussion" = "View discussion"; "lng_profile_join_channel" = "Join Channel"; "lng_profile_join_group" = "Join Group"; +"lng_profile_apply_to_join_group" = "Apply to Join Group"; "lng_profile_delete_and_exit" = "Leave"; "lng_profile_kick" = "Remove"; "lng_profile_delete_removed" = "Delete"; @@ -1128,6 +1129,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_public_group_title" = "Public"; "lng_manage_private_peer_title" = "Private"; "lng_manage_public_peer_title" = "Public"; +"lng_manage_peer_send_title" = "Who can send new messages?"; +"lng_manage_peer_send_only_members" = "Only members"; +"lng_manage_peer_send_only_members_about" = "Turn this on if you expect users to join your group before being able to send messages."; +"lng_manage_peer_send_approve_members" = "Approve new members"; +"lng_manage_peer_send_approve_members_about" = "Turn this on if you want users to join the group only after they are approved by an admin."; "lng_manage_peer_no_forwards_title" = "Saving content"; "lng_manage_peer_no_forwards" = "Restrict saving content"; "lng_manage_peer_no_forwards_about" = "Members won't be able to forward messages from this group or save media files."; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index d9bc84af76..2b3b0ee089 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -269,6 +269,8 @@ private: std::optional hiddenPreHistory; std::optional signatures; std::optional noForwards; + std::optional joinToWrite; + std::optional requestToJoin; std::optional linkedChat; }; @@ -306,6 +308,8 @@ private: [[nodiscard]] bool validateHistoryVisibility(Saving &to) const; [[nodiscard]] bool validateSignatures(Saving &to) const; [[nodiscard]] bool validateForwards(Saving &to) const; + [[nodiscard]] bool validateJoinToWrite(Saving &to) const; + [[nodiscard]] bool validateRequestToJoin(Saving &to) const; void save(); void saveUsername(); @@ -315,6 +319,8 @@ private: void saveHistoryVisibility(); void saveSignatures(); void saveForwards(); + void saveJoinToWrite(); + void saveRequestToJoin(); void savePhoto(); void pushSaveStage(FnMut &&lambda); void continueSave(); @@ -329,14 +335,12 @@ private: void subscribeToMigration(); void migrate(not_null channel); - std::optional _privacySavedValue; std::optional _linkedChatSavedValue; ChannelData *_linkedChatOriginalValue = nullptr; bool _channelHasLocationOriginalValue = false; std::optional _historyVisibilitySavedValue; - std::optional _usernameSavedValue; + std::optional _typeDataSavedValue; std::optional _signaturesSavedValue; - std::optional _noForwardsSavedValue; const not_null _navigation; const not_null _box; @@ -602,8 +606,10 @@ void Controller::refreshHistoryVisibility() { if (!_controls.historyVisibilityWrap) { return; } + const auto withUsername = _typeDataSavedValue + && (_typeDataSavedValue->privacy == Privacy::HasUsername); _controls.historyVisibilityWrap->toggle( - (_privacySavedValue != Privacy::HasUsername + (withUsername && !_channelHasLocationOriginalValue && (!_linkedChatSavedValue || !*_linkedChatSavedValue)), anim::type::instant); @@ -611,22 +617,19 @@ void Controller::refreshHistoryVisibility() { void Controller::showEditPeerTypeBox( std::optional> error) { - const auto boxCallback = crl::guard(this, [=]( - Privacy checked, QString publicLink, bool noForwards) { - _privacyTypeUpdates.fire(std::move(checked)); - _privacySavedValue = checked; - _usernameSavedValue = publicLink; - _noForwardsSavedValue = noForwards; + const auto boxCallback = crl::guard(this, [=](EditPeerTypeData data) { + _privacyTypeUpdates.fire_copy(data.privacy); + _typeDataSavedValue = data; refreshHistoryVisibility(); }); + _typeDataSavedValue->hasLinkedChat + = (_linkedChatSavedValue.value_or(nullptr) != nullptr); _navigation->parentController()->show( Box( _peer, _channelHasLocationOriginalValue, boxCallback, - _privacySavedValue, - _usernameSavedValue, - _noForwardsSavedValue, + _typeDataSavedValue, error), Ui::LayerOption::KeepOther); } @@ -698,12 +701,20 @@ void Controller::fillPrivacyTypeButton() { // Create Privacy Button. const auto hasLocation = _peer->isChannel() && _peer->asChannel()->hasLocation(); - _privacySavedValue = (_peer->isChannel() - && _peer->asChannel()->hasUsername()) - ? Privacy::HasUsername - : Privacy::NoUsername; - _noForwardsSavedValue = !_peer->allowsForwarding(); - + _typeDataSavedValue = EditPeerTypeData{ + .privacy = ((_peer->isChannel() + && _peer->asChannel()->hasUsername()) + ? Privacy::HasUsername + : Privacy::NoUsername), + .username = (_peer->isChannel() + ? _peer->asChannel()->username + : QString()), + .noForwards = !_peer->allowsForwarding(), + .joinToWrite = (_peer->isMegagroup() + && _peer->asChannel()->joinToWrite()), + .requestToJoin = (_peer->isMegagroup() + && _peer->asChannel()->requestToJoin()), + }; const auto isGroup = (_peer->isChat() || _peer->isMegagroup()); const auto icon = isGroup ? &st::settingsIconGroup @@ -732,7 +743,7 @@ void Controller::fillPrivacyTypeButton() { [=] { showEditPeerTypeBox(); }, { icon, Settings::kIconLightBlue }); - _privacyTypeUpdates.fire_copy(*_privacySavedValue); + _privacyTypeUpdates.fire_copy(_typeDataSavedValue->privacy); } void Controller::fillLinkedChatButton() { @@ -1060,9 +1071,9 @@ void Controller::fillManageSection() { }, { &st::infoRoundedIconInviteLinks, Settings::kIconLightOrange }); - if (_privacySavedValue) { + if (_typeDataSavedValue) { _privacyTypeUpdates.events_starting_with_copy( - *_privacySavedValue + _typeDataSavedValue->privacy ) | rpl::start_with_next([=](Privacy flag) { wrap->toggle( flag != Privacy::HasUsername, @@ -1217,24 +1228,22 @@ std::optional Controller::validate() const { && validateDescription(result) && validateHistoryVisibility(result) && validateSignatures(result) - && validateForwards(result)) { + && validateForwards(result) + && validateJoinToWrite(result) + && validateRequestToJoin(result)) { return result; } return {}; } bool Controller::validateUsername(Saving &to) const { - if (!_privacySavedValue) { + if (!_typeDataSavedValue) { return true; - } else if (_privacySavedValue != Privacy::HasUsername) { + } else if (_typeDataSavedValue->privacy != Privacy::HasUsername) { to.username = QString(); return true; } - const auto username = _usernameSavedValue.value_or( - _peer->isChannel() - ? _peer->asChannel()->username - : QString() - ); + const auto username = _typeDataSavedValue->username; if (username.isEmpty()) { return false; } @@ -1276,7 +1285,8 @@ bool Controller::validateHistoryVisibility(Saving &to) const { if (!_controls.historyVisibilityWrap || !_controls.historyVisibilityWrap->toggled() || _channelHasLocationOriginalValue - || (_privacySavedValue == Privacy::HasUsername)) { + || (_typeDataSavedValue + && _typeDataSavedValue->privacy == Privacy::HasUsername)) { return true; } to.hiddenPreHistory @@ -1293,10 +1303,26 @@ bool Controller::validateSignatures(Saving &to) const { } bool Controller::validateForwards(Saving &to) const { - if (!_noForwardsSavedValue.has_value()) { + if (!_typeDataSavedValue) { return true; } - to.noForwards = _noForwardsSavedValue; + to.noForwards = _typeDataSavedValue->noForwards; + return true; +} + +bool Controller::validateJoinToWrite(Saving &to) const { + if (!_typeDataSavedValue) { + return true; + } + to.joinToWrite = _typeDataSavedValue->joinToWrite; + return true; +} + +bool Controller::validateRequestToJoin(Saving &to) const { + if (!_typeDataSavedValue) { + return true; + } + to.requestToJoin = _typeDataSavedValue->requestToJoin; return true; } @@ -1315,6 +1341,8 @@ void Controller::save() { pushSaveStage([=] { saveHistoryVisibility(); }); pushSaveStage([=] { saveSignatures(); }); pushSaveStage([=] { saveForwards(); }); + pushSaveStage([=] { saveJoinToWrite(); }); + pushSaveStage([=] { saveRequestToJoin(); }); pushSaveStage([=] { savePhoto(); }); continueSave(); } @@ -1591,6 +1619,50 @@ void Controller::saveForwards() { }).send(); } +void Controller::saveJoinToWrite() { + const auto joinToWrite = _peer->isMegagroup() + && _peer->asChannel()->joinToWrite(); + if (!_savingData.joinToWrite + || *_savingData.joinToWrite == joinToWrite) { + return continueSave(); + } + _api.request(MTPchannels_ToggleJoinToSend( + _peer->asChannel()->inputChannel, + MTP_bool(*_savingData.joinToWrite) + )).done([=](const MTPUpdates &result) { + _peer->session().api().applyUpdates(result); + continueSave(); + }).fail([=](const MTP::Error &error) { + if (error.type() == qstr("CHAT_NOT_MODIFIED")) { + continueSave(); + } else { + cancelSave(); + } + }).send(); +} + +void Controller::saveRequestToJoin() { + const auto requestToJoin = _peer->isMegagroup() + && _peer->asChannel()->requestToJoin(); + if (!_savingData.requestToJoin + || *_savingData.requestToJoin == requestToJoin) { + return continueSave(); + } + _api.request(MTPchannels_ToggleJoinRequest( + _peer->asChannel()->inputChannel, + MTP_bool(*_savingData.requestToJoin) + )).done([=](const MTPUpdates &result) { + _peer->session().api().applyUpdates(result); + continueSave(); + }).fail([=](const MTP::Error &error) { + if (error.type() == qstr("CHAT_NOT_MODIFIED")) { + continueSave(); + } else { + cancelSave(); + } + }).send(); +} + void Controller::savePhoto() { auto image = _controls.photo ? _controls.photo->takeResultImage() diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp index e6d6ad2e7f..e1894da924 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.cpp @@ -52,16 +52,14 @@ public: not_null container, not_null peer, bool useLocationPhrases, - std::optional privacySavedValue, - std::optional usernameSavedValue, - std::optional noForwardsSavedValue); + std::optional dataSavedValue); void createContent(); [[nodiscard]] QString getUsernameInput() const; void setFocusUsername(); [[nodiscard]] rpl::producer getTitle() const { - return !_privacySavedValue + return !_dataSavedValue ? tr::lng_create_invite_link_title() : _isGroup ? tr::lng_manage_peer_group_type() @@ -79,6 +77,12 @@ public: [[nodiscard]] bool noForwards() const { return _controls.noForwards->toggled(); } + [[nodiscard]] bool joinToWrite() const { + return _controls.joinToWrite && _controls.joinToWrite->toggled(); + } + [[nodiscard]] bool requestToJoin() const { + return _controls.requestToJoin && _controls.requestToJoin->toggled(); + } void showError(rpl::producer text) { _controls.usernameInput->showError(); @@ -93,10 +97,13 @@ private: base::unique_qptr usernameResult; const style::FlatLabel *usernameResultStyle = nullptr; - Ui::SlideWrap *inviteLinkWrap = nullptr; + Ui::SlideWrap<> *inviteLinkWrap = nullptr; Ui::FlatLabel *inviteLink = nullptr; + Ui::SlideWrap *whoSendWrap = nullptr; Ui::SettingsButton *noForwards = nullptr; + Ui::SettingsButton *joinToWrite = nullptr; + Ui::SettingsButton *requestToJoin = nullptr; }; Controls _controls; @@ -130,9 +137,7 @@ private: bool _linkOnly = false; MTP::Sender _api; - std::optional _privacySavedValue; - std::optional _usernameSavedValue; - std::optional _noForwardsSavedValue; + std::optional _dataSavedValue; bool _useLocationPhrases = false; bool _isGroup = false; @@ -153,20 +158,17 @@ Controller::Controller( not_null container, not_null peer, bool useLocationPhrases, - std::optional privacySavedValue, - std::optional usernameSavedValue, - std::optional noForwardsSavedValue) + std::optional dataSavedValue) : _show(show) , _peer(peer) -, _linkOnly(!privacySavedValue.has_value()) +, _linkOnly(!dataSavedValue.has_value()) , _api(&_peer->session().mtp()) -, _privacySavedValue(privacySavedValue) -, _usernameSavedValue(usernameSavedValue) -, _noForwardsSavedValue(noForwardsSavedValue) +, _dataSavedValue(dataSavedValue) , _useLocationPhrases(useLocationPhrases) , _isGroup(_peer->isChat() || _peer->isMegagroup()) -, _goodUsername(!_usernameSavedValue.value_or( - _peer->isChannel() ? _peer->asChannel()->username : QString()).isEmpty()) +, _goodUsername(_dataSavedValue + ? !_dataSavedValue->username.isEmpty() + : (_peer->isChannel() && !_peer->asChannel()->username.isEmpty())) , _wrap(container) , _checkUsernameTimer([=] { checkUsernameAvailability(); }) { _peer->updateFull(); @@ -175,7 +177,12 @@ Controller::Controller( void Controller::createContent() { _controls = Controls(); - fillPrivaciesButtons(_wrap, _privacySavedValue); + fillPrivaciesButtons( + _wrap, + (_dataSavedValue + ? _dataSavedValue->privacy + : std::optional())); + // Skip. if (!_linkOnly) { _wrap->add(object_ptr(_wrap)); @@ -204,6 +211,63 @@ void Controller::createContent() { AddDividerText(_wrap.get(), tr::lng_group_invite_manage_about()); if (!_linkOnly) { + if (_peer->isMegagroup()) { + _controls.whoSendWrap = _wrap->add( + object_ptr>( + _wrap.get(), + object_ptr(_wrap.get()))); + const auto wrap = _controls.whoSendWrap->entity(); + + AddSkip(wrap); + if (_dataSavedValue->hasLinkedChat) { + AddSubsectionTitle(wrap, tr::lng_manage_peer_send_title()); + + _controls.joinToWrite = wrap->add(EditPeerInfoBox::CreateButton( + wrap, + tr::lng_manage_peer_send_only_members(), + rpl::single(QString()), + [=] {}, + st::manageGroupTopButtonWithText, + {} + )); + _controls.joinToWrite->toggleOn( + rpl::single(_dataSavedValue->joinToWrite) + )->toggledValue( + ) | rpl::start_with_next([=](bool toggled) { + _dataSavedValue->joinToWrite = toggled; + }, wrap->lifetime()); + } + auto joinToWrite = _controls.joinToWrite + ? _controls.joinToWrite->toggledValue() + : rpl::single(true); + + const auto requestToJoinWrap = wrap->add( + object_ptr>( + wrap, + EditPeerInfoBox::CreateButton( + wrap, + tr::lng_manage_peer_send_approve_members(), + rpl::single(QString()), + [=] {}, + st::manageGroupTopButtonWithText, + {})))->setDuration(0); + requestToJoinWrap->toggleOn(rpl::duplicate(joinToWrite)); + _controls.requestToJoin = requestToJoinWrap->entity(); + _controls.requestToJoin->toggleOn( + rpl::single(_dataSavedValue->requestToJoin) + )->toggledValue( + ) | rpl::start_with_next([=](bool toggled) { + _dataSavedValue->requestToJoin = toggled; + }, wrap->lifetime()); + + AddSkip(wrap); + AddDividerText( + wrap, + rpl::conditional( + std::move(joinToWrite), + tr::lng_manage_peer_send_approve_members_about(), + tr::lng_manage_peer_send_only_members_about())); + } AddSkip(_wrap.get()); AddSubsectionTitle( _wrap.get(), @@ -216,10 +280,10 @@ void Controller::createContent() { st::peerPermissionsButton, {})); _controls.noForwards->toggleOn( - rpl::single(_noForwardsSavedValue.value_or(false)) + rpl::single(_dataSavedValue->noForwards) )->toggledValue( ) | rpl::start_with_next([=](bool toggled) { - _noForwardsSavedValue = toggled; + _dataSavedValue->noForwards = toggled; }, _wrap->lifetime()); AddSkip(_wrap.get()); AddDividerText( @@ -234,8 +298,9 @@ void Controller::createContent() { if (_controls.privacy->value() == Privacy::NoUsername) { checkUsernameAvailability(); } - const auto forShowing = _privacySavedValue.value_or( - Privacy::NoUsername); + const auto forShowing = _dataSavedValue + ? _dataSavedValue->privacy + : Privacy::NoUsername; _controls.inviteLinkWrap->toggle( (forShowing != Privacy::HasUsername), anim::type::instant); @@ -332,8 +397,9 @@ object_ptr Controller::createUsernameEdit() { Expects(_wrap != nullptr); const auto channel = _peer->asChannel(); - const auto username = _usernameSavedValue.value_or( - channel ? channel->username : QString()); + const auto username = (!_dataSavedValue || !channel) + ? QString() + : channel->username; auto result = object_ptr>( _wrap, @@ -401,6 +467,15 @@ void Controller::privacyChanged(Privacy value) { (value == Privacy::HasUsername), anim::type::instant); }; + const auto toggleWhoSendWrap = [&] { + if (!_controls.whoSendWrap) { + return; + } + _controls.whoSendWrap->toggle( + (value == Privacy::HasUsername + || (_dataSavedValue && _dataSavedValue->hasLinkedChat)), + anim::type::instant); + }; const auto refreshVisibilities = [&] { // Now first we need to hide that was shown. // Otherwise box will change own Y position. @@ -408,10 +483,12 @@ void Controller::privacyChanged(Privacy value) { if (value == Privacy::HasUsername) { toggleInviteLink(); toggleEditUsername(); + toggleWhoSendWrap(); _controls.usernameResult = nullptr; checkUsernameAvailability(); } else { + toggleWhoSendWrap(); toggleEditUsername(); toggleInviteLink(); } @@ -572,7 +649,7 @@ object_ptr Controller::createInviteLinkBlock() { const auto container = result->entity(); using namespace Settings; - if (_privacySavedValue) { + if (_dataSavedValue) { AddSkip(container); AddSubsectionTitle(container, tr::lng_create_permanent_link_title()); @@ -601,24 +678,20 @@ EditPeerTypeBox::EditPeerTypeBox( QWidget*, not_null peer, bool useLocationPhrases, - std::optional> savedCallback, - std::optional privacySaved, - std::optional usernameSaved, - std::optional noForwardsValue, + std::optional> savedCallback, + std::optional dataSaved, std::optional> usernameError) : _peer(peer) , _useLocationPhrases(useLocationPhrases) , _savedCallback(std::move(savedCallback)) -, _privacySavedValue(privacySaved) -, _usernameSavedValue(usernameSaved) -, _noForwardsValue(noForwardsValue) +, _dataSavedValue(dataSaved) , _usernameError(usernameError) { } EditPeerTypeBox::EditPeerTypeBox( QWidget*, not_null peer) -: EditPeerTypeBox(nullptr, peer, {}, {}, {}, {}, {}, {}) { +: EditPeerTypeBox(nullptr, peer, {}, {}, {}) { } void EditPeerTypeBox::setInnerFocus() { @@ -636,9 +709,7 @@ void EditPeerTypeBox::prepare() { content.data(), _peer, _useLocationPhrases, - _privacySavedValue, - _usernameSavedValue, - _noForwardsValue); + _dataSavedValue); _focusRequests.events( ) | rpl::start_with_next( [=] { @@ -662,12 +733,15 @@ void EditPeerTypeBox::prepare() { } auto local = std::move(*_savedCallback); - local( - v, - (v == Privacy::HasUsername + local(EditPeerTypeData{ + .privacy = v, + .username = (v == Privacy::HasUsername ? controller->getUsernameInput() : QString()), - controller->noForwards()); // We don't need username with private type. + .noForwards = controller->noForwards(), + .joinToWrite = controller->joinToWrite(), + .requestToJoin = controller->requestToJoin(), + }); // We don't need username with private type. closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); }); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h index 3f544e1f97..8f182c6b3c 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_type_box.h @@ -29,16 +29,23 @@ enum class UsernameState { NotAvailable, }; +struct EditPeerTypeData { + Privacy privacy = Privacy::NoUsername; + QString username; + bool hasLinkedChat = false; + bool noForwards = false; + bool joinToWrite = false; + bool requestToJoin = false; +}; + class EditPeerTypeBox : public Ui::BoxContent { public: EditPeerTypeBox( QWidget*, not_null peer, bool useLocationPhrases, - std::optional> savedCallback, - std::optional privacySaved, - std::optional usernameSaved, - std::optional noForwardsSaved, + std::optional> savedCallback, + std::optional dataSaved, std::optional> usernameError = {}); // For invite link only. @@ -53,11 +60,9 @@ protected: private: not_null _peer; bool _useLocationPhrases = false; - std::optional> _savedCallback; + std::optional> _savedCallback; - std::optional _privacySavedValue; - std::optional _usernameSavedValue; - std::optional _noForwardsValue; + std::optional _dataSavedValue; std::optional> _usernameError; rpl::event_stream<> _focusRequests; diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 5496dd56c8..11b312123c 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -52,6 +52,8 @@ enum class ChannelDataFlag { HasLink = (1 << 18), SlowmodeEnabled = (1 << 19), NoForwards = (1 << 20), + JoinToWrite = (1 << 21), + RequestToJoin = (1 << 22), }; inline constexpr bool is_flag_type(ChannelDataFlag) { return true; }; using ChannelDataFlags = base::flags; @@ -255,6 +257,12 @@ public: [[nodiscard]] bool amCreator() const { return flags() & Flag::Creator; } + [[nodiscard]] bool joinToWrite() const { + return flags() & Flag::JoinToWrite; + } + [[nodiscard]] bool requestToJoin() const { + return flags() & Flag::RequestToJoin; + } [[nodiscard]] auto adminRights() const { return _adminRights.current(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 7d7bb82cad..98af6caf8e 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -741,7 +741,9 @@ not_null Session::processChat(const MTPChat &data) { | Flag::CallNotEmpty | Flag::Forbidden | (!minimal ? (Flag::Left | Flag::Creator) : Flag()) - | Flag::NoForwards; + | Flag::NoForwards + | Flag::JoinToWrite + | Flag::RequestToJoin; const auto flagsSet = (data.is_broadcast() ? Flag::Broadcast : Flag()) | (data.is_verified() ? Flag::Verified : Flag()) | (data.is_scam() ? Flag::Scam : Flag()) @@ -762,7 +764,9 @@ not_null Session::processChat(const MTPChat &data) { ? (data.is_left() ? Flag::Left : Flag()) | (data.is_creator() ? Flag::Creator : Flag()) : Flag()) - | (data.is_noforwards() ? Flag::NoForwards : Flag()); + | (data.is_noforwards() ? Flag::NoForwards : Flag()) + | (data.is_join_to_send() ? Flag::JoinToWrite : Flag()) + | (data.is_join_request() ? Flag::RequestToJoin : Flag()); channel->setFlags((channel->flags() & ~flagsMask) | flagsSet); channel->setName( diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index ccaaa25c21..fc5d26c864 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -913,6 +913,16 @@ Dialogs::EntryState HistoryWidget::computeDialogsEntryState() const { }; } +void HistoryWidget::refreshJoinChannelText() { + if (const auto channel = _peer ? _peer->asChannel() : nullptr) { + _joinChannel->setText((channel->isBroadcast() + ? tr::lng_profile_join_channel(tr::now) + : (channel->requestToJoin() && !channel->amCreator()) + ? tr::lng_profile_apply_to_join_group(tr::now) + : tr::lng_profile_join_group(tr::now)).toUpper()); + } +} + void HistoryWidget::refreshTopBarActiveChat() { const auto state = computeDialogsEntryState(); _topBar->setActiveChat(state, _history->sendActionPainter()); @@ -2210,12 +2220,6 @@ void HistoryWidget::showHistory( && !_peer->asUser()->isSupport()) ? tr::lng_restart_button(tr::now) : tr::lng_unblock_button(tr::now)).toUpper()); - if (const auto channel = _peer->asChannel()) { - channel->updateFull(); - _joinChannel->setText((channel->isMegagroup() - ? tr::lng_profile_join_group(tr::now) - : tr::lng_profile_join_channel(tr::now)).toUpper()); - } } _nonEmptySelection = false; @@ -2269,6 +2273,18 @@ void HistoryWidget::showHistory( object_ptr(this, _scroll, controller(), _history)); _list->show(); + if (const auto channel = _peer->asChannel()) { + channel->updateFull(); + if (!channel->isBroadcast()) { + channel->flagsValue( + ) | rpl::start_with_next([=] { + refreshJoinChannelText(); + }, _list->lifetime()); + } else { + refreshJoinChannelText(); + } + } + controller()->adaptive().changes( ) | rpl::start_with_next([=] { _history->forceFullResize(); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index abb3f75b52..1f97fe9437 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -375,6 +375,7 @@ private: [[nodiscard]] Dialogs::EntryState computeDialogsEntryState() const; void refreshTopBarActiveChat(); + void refreshJoinChannelText(); void requestMessageData(MsgId msgId); void messageDataReceived(not_null peer, MsgId msgId);