From 2f6f4325830caff386867e2c8035881bc65febc5 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 21 Apr 2022 18:29:49 +0400 Subject: [PATCH] Handle join-to-write / request-to-join in comments section. --- Telegram/SourceFiles/data/data_channel.cpp | 3 +- .../SourceFiles/data/data_peer_values.cpp | 3 +- .../history_view_compose_controls.cpp | 25 ++++- .../controls/history_view_compose_controls.h | 4 + .../view/history_view_replies_section.cpp | 105 ++++++++++++++++-- .../view/history_view_replies_section.h | 2 + 6 files changed, 127 insertions(+), 15 deletions(-) diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index df48daf29..ed0436420 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -467,7 +467,8 @@ bool ChannelData::canPublish() const { bool ChannelData::canWrite() const { // Duplicated in Data::CanWriteValue(). - const auto allowed = amIn() || (flags() & Flag::HasLink); + const auto allowed = amIn() + || ((flags() & Flag::HasLink) && !(flags() & Flag::JoinToWrite)); return allowed && (canPublish() || (!isBroadcast() && !amRestricted(Restriction::SendMessages))); diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp index 222c207b0..8b21f0e3f 100644 --- a/Telegram/SourceFiles/data/data_peer_values.cpp +++ b/Telegram/SourceFiles/data/data_peer_values.cpp @@ -205,6 +205,7 @@ rpl::producer CanWriteValue(ChannelData *channel) { using Flag = ChannelDataFlag; const auto mask = 0 | Flag::Left + | Flag::JoinToWrite | Flag::HasLink | Flag::Forbidden | Flag::Creator @@ -227,7 +228,7 @@ rpl::producer CanWriteValue(ChannelData *channel) { bool defaultSendMessagesRestriction) { const auto notAmInFlags = Flag::Left | Flag::Forbidden; const auto allowed = !(flags & notAmInFlags) - || (flags & Flag::HasLink); + || ((flags & Flag::HasLink) && !(flags & Flag::JoinToWrite)); return allowed && (postMessagesRight || (flags & Flag::Creator) || (!(flags & Flag::Broadcast) diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 78479cfa9..aa6513cf2 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -1215,6 +1215,19 @@ void ComposeControls::checkAutocomplete() { autocomplete.fromStart); } +void ComposeControls::hide() { + showStarted(); + _hidden = true; +} + +void ComposeControls::show() { + if (_hidden.current()) { + _hidden = false; + showFinished(); + checkAutocomplete(); + } +} + void ComposeControls::init() { initField(); initTabbedSelector(); @@ -1224,6 +1237,11 @@ void ComposeControls::init() { initVoiceRecordBar(); initKeyHandler(); + _hidden.changes( + ) | rpl::start_with_next([=] { + updateWrappingVisibility(); + }, _wrap->lifetime()); + _botCommandStart->setClickedCallback([=] { setText({ "/" }); }); _wrap->sizeValue( @@ -2021,10 +2039,11 @@ void ComposeControls::initVoiceRecordBar() { } void ComposeControls::updateWrappingVisibility() { + const auto hidden = _hidden.current(); const auto restricted = _writeRestriction.current().has_value(); - _writeRestricted->setVisible(restricted); - _wrap->setVisible(!restricted); - if (!restricted) { + _writeRestricted->setVisible(!hidden && restricted); + _wrap->setVisible(!hidden && !restricted); + if (!hidden && !restricted) { _wrap->raise(); } } diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h index 95d04e241..b3793dc56 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.h @@ -169,6 +169,9 @@ public: void hidePanelsAnimated(); void clearListenState(); + void hide(); + void show(); + [[nodiscard]] rpl::producer lockShowStarts() const; [[nodiscard]] bool isLockPresent() const; [[nodiscard]] bool isRecording() const; @@ -285,6 +288,7 @@ private: rpl::variable _slowmodeSecondsLeft; rpl::variable _sendDisabledBySlowmode; rpl::variable> _writeRestriction; + rpl::variable _hidden; Mode _mode = Mode::Normal; const std::unique_ptr _wrap; diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 1513acdbc..8f29e85cb 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -231,7 +231,9 @@ RepliesWidget::RepliesWidget( }, lifetime()); _inner->editMessageRequested( - ) | rpl::start_with_next([=](auto fullId) { + ) | rpl::filter([=] { + return !_joinGroup; + }) | rpl::start_with_next([=](auto fullId) { if (const auto item = session().data().message(fullId)) { const auto media = item->media(); if (media && !media->webpage()) { @@ -245,7 +247,9 @@ RepliesWidget::RepliesWidget( }, _inner->lifetime()); _inner->replyToMessageRequested( - ) | rpl::start_with_next([=](auto fullId) { + ) | rpl::filter([=] { + return !_joinGroup; + }) | rpl::start_with_next([=](auto fullId) { replyToMessage(fullId); }, _inner->lifetime()); @@ -477,13 +481,20 @@ void RepliesWidget::setupComposeControls() { std::move(hasSendingMessage), _1 && _2); - auto writeRestriction = session().changes().peerFlagsValue( - _history->peer, - Data::PeerUpdate::Flag::Rights + auto writeRestriction = rpl::combine( + session().changes().peerFlagsValue( + _history->peer, + Data::PeerUpdate::Flag::Rights), + Data::CanWriteValue(_history->peer) ) | rpl::map([=] { - return Data::RestrictionError( + const auto restriction = Data::RestrictionError( _history->peer, ChatRestriction::SendMessages); + return restriction + ? restriction + : _history->peer->canWrite() + ? std::optional() + : tr::lng_group_not_accessible(tr::now); }); _composeControls->setHistory({ @@ -495,7 +506,9 @@ void RepliesWidget::setupComposeControls() { }); _composeControls->height( - ) | rpl::start_with_next([=] { + ) | rpl::filter([=] { + return !_joinGroup; + }) | rpl::start_with_next([=] { const auto wasMax = (_scroll->scrollTopMax() == _scroll->scrollTop()); updateControlsGeometry(); if (wasMax) { @@ -617,6 +630,20 @@ void RepliesWidget::setupComposeControls() { }, lifetime()); _composeControls->finishAnimating(); + + if (const auto channel = _history->peer->asChannel()) { + channel->updateFull(); + if (!channel->isBroadcast()) { + rpl::combine( + Data::CanWriteValue(channel), + channel->flagsValue() + ) | rpl::start_with_next([=] { + refreshJoinGroupButton(); + }, lifetime()); + } else { + refreshJoinGroupButton(); + } + } } void RepliesWidget::chooseAttach() { @@ -1066,6 +1093,47 @@ void RepliesWidget::edit( doSetInnerFocus(); } +void RepliesWidget::refreshJoinGroupButton() { + const auto set = [&](std::unique_ptr button) { + if (!button && !_joinGroup) { + return; + } + const auto atMax = (_scroll->scrollTopMax() == _scroll->scrollTop()); + _joinGroup = std::move(button); + if (!animatingShow()) { + if (button) { + button->show(); + _composeControls->hide(); + } else { + _composeControls->show(); + } + } + updateControlsGeometry(); + if (atMax) { + listScrollTo(_scroll->scrollTopMax()); + } + }; + const auto channel = _history->peer->asChannel(); + if (channel->amIn() || !channel->joinToWrite() || channel->amCreator()) { + set(nullptr); + } else { + if (!_joinGroup) { + set(std::make_unique( + this, + QString(), + st::historyComposeButton)); + _joinGroup->setClickedCallback([=] { + session().api().joinChannel(channel); + }); + } + _joinGroup->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 RepliesWidget::sendExistingDocument( not_null document) { sendExistingDocument(document, {}, std::nullopt); @@ -1430,7 +1498,11 @@ bool RepliesWidget::preventsClose(Fn &&continueCallback) const { QPixmap RepliesWidget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) { _topBar->updateControlsVisibility(); if (params.withTopBarShadow) _topBarShadow->hide(); - _composeControls->showForGrab(); + if (_joinGroup) { + _composeControls->hide(); + } else { + _composeControls->showForGrab(); + } auto result = Ui::GrabWidget(this); if (params.withTopBarShadow) _topBarShadow->show(); _rootView->hide(); @@ -1605,7 +1677,9 @@ void RepliesWidget::updateControlsGeometry() { _rootView->resizeToWidth(contentWidth); const auto bottom = height(); - const auto controlsHeight = _composeControls->heightCurrent(); + const auto controlsHeight = _joinGroup + ? _joinGroup->height() + : _composeControls->heightCurrent(); const auto scrollY = _topBar->height() + _rootViewHeight; const auto scrollHeight = bottom - scrollY - controlsHeight; const auto scrollSize = QSize(contentWidth, scrollHeight); @@ -1622,6 +1696,13 @@ void RepliesWidget::updateControlsGeometry() { } updateInnerVisibleArea(); } + if (_joinGroup) { + _joinGroup->setGeometry( + 0, + bottom - _joinGroup->height(), + contentWidth, + _joinGroup->height()); + } _composeControls->move(0, bottom - controlsHeight); _composeControls->setAutocompleteBoundingRect(_scroll->geometry()); @@ -1715,7 +1796,11 @@ void RepliesWidget::showAnimatedHook( void RepliesWidget::showFinishedHook() { _topBar->setAnimatingMode(false); - _composeControls->showFinished(); + if (_joinGroup) { + _composeControls->hide(); + } else { + _composeControls->showFinished(); + } _rootView->show(); // We should setup the drag area only after diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.h b/Telegram/SourceFiles/history/view/history_view_replies_section.h index 43d247665..eccf68a5c 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.h +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.h @@ -260,6 +260,7 @@ private: Api::SendOptions options, std::optional localMessageId); + void refreshJoinGroupButton(); [[nodiscard]] bool showSlowmodeError(); [[nodiscard]] std::optional writeRestriction() const; @@ -274,6 +275,7 @@ private: object_ptr _topBar; object_ptr _topBarShadow; std::unique_ptr _composeControls; + std::unique_ptr _joinGroup; bool _skipScrollEvent = false; std::unique_ptr _rootView;