Handle join-to-write / request-to-join in comments section.

This commit is contained in:
John Preston 2022-04-21 18:29:49 +04:00
parent 5874ae7c51
commit 2f6f432583
6 changed files with 127 additions and 15 deletions

View file

@ -467,7 +467,8 @@ bool ChannelData::canPublish() const {
bool ChannelData::canWrite() const { bool ChannelData::canWrite() const {
// Duplicated in Data::CanWriteValue(). // Duplicated in Data::CanWriteValue().
const auto allowed = amIn() || (flags() & Flag::HasLink); const auto allowed = amIn()
|| ((flags() & Flag::HasLink) && !(flags() & Flag::JoinToWrite));
return allowed && (canPublish() return allowed && (canPublish()
|| (!isBroadcast() || (!isBroadcast()
&& !amRestricted(Restriction::SendMessages))); && !amRestricted(Restriction::SendMessages)));

View file

@ -205,6 +205,7 @@ rpl::producer<bool> CanWriteValue(ChannelData *channel) {
using Flag = ChannelDataFlag; using Flag = ChannelDataFlag;
const auto mask = 0 const auto mask = 0
| Flag::Left | Flag::Left
| Flag::JoinToWrite
| Flag::HasLink | Flag::HasLink
| Flag::Forbidden | Flag::Forbidden
| Flag::Creator | Flag::Creator
@ -227,7 +228,7 @@ rpl::producer<bool> CanWriteValue(ChannelData *channel) {
bool defaultSendMessagesRestriction) { bool defaultSendMessagesRestriction) {
const auto notAmInFlags = Flag::Left | Flag::Forbidden; const auto notAmInFlags = Flag::Left | Flag::Forbidden;
const auto allowed = !(flags & notAmInFlags) const auto allowed = !(flags & notAmInFlags)
|| (flags & Flag::HasLink); || ((flags & Flag::HasLink) && !(flags & Flag::JoinToWrite));
return allowed && (postMessagesRight return allowed && (postMessagesRight
|| (flags & Flag::Creator) || (flags & Flag::Creator)
|| (!(flags & Flag::Broadcast) || (!(flags & Flag::Broadcast)

View file

@ -1215,6 +1215,19 @@ void ComposeControls::checkAutocomplete() {
autocomplete.fromStart); autocomplete.fromStart);
} }
void ComposeControls::hide() {
showStarted();
_hidden = true;
}
void ComposeControls::show() {
if (_hidden.current()) {
_hidden = false;
showFinished();
checkAutocomplete();
}
}
void ComposeControls::init() { void ComposeControls::init() {
initField(); initField();
initTabbedSelector(); initTabbedSelector();
@ -1224,6 +1237,11 @@ void ComposeControls::init() {
initVoiceRecordBar(); initVoiceRecordBar();
initKeyHandler(); initKeyHandler();
_hidden.changes(
) | rpl::start_with_next([=] {
updateWrappingVisibility();
}, _wrap->lifetime());
_botCommandStart->setClickedCallback([=] { setText({ "/" }); }); _botCommandStart->setClickedCallback([=] { setText({ "/" }); });
_wrap->sizeValue( _wrap->sizeValue(
@ -2021,10 +2039,11 @@ void ComposeControls::initVoiceRecordBar() {
} }
void ComposeControls::updateWrappingVisibility() { void ComposeControls::updateWrappingVisibility() {
const auto hidden = _hidden.current();
const auto restricted = _writeRestriction.current().has_value(); const auto restricted = _writeRestriction.current().has_value();
_writeRestricted->setVisible(restricted); _writeRestricted->setVisible(!hidden && restricted);
_wrap->setVisible(!restricted); _wrap->setVisible(!hidden && !restricted);
if (!restricted) { if (!hidden && !restricted) {
_wrap->raise(); _wrap->raise();
} }
} }

View file

@ -169,6 +169,9 @@ public:
void hidePanelsAnimated(); void hidePanelsAnimated();
void clearListenState(); void clearListenState();
void hide();
void show();
[[nodiscard]] rpl::producer<bool> lockShowStarts() const; [[nodiscard]] rpl::producer<bool> lockShowStarts() const;
[[nodiscard]] bool isLockPresent() const; [[nodiscard]] bool isLockPresent() const;
[[nodiscard]] bool isRecording() const; [[nodiscard]] bool isRecording() const;
@ -285,6 +288,7 @@ private:
rpl::variable<int> _slowmodeSecondsLeft; rpl::variable<int> _slowmodeSecondsLeft;
rpl::variable<bool> _sendDisabledBySlowmode; rpl::variable<bool> _sendDisabledBySlowmode;
rpl::variable<std::optional<QString>> _writeRestriction; rpl::variable<std::optional<QString>> _writeRestriction;
rpl::variable<bool> _hidden;
Mode _mode = Mode::Normal; Mode _mode = Mode::Normal;
const std::unique_ptr<Ui::RpWidget> _wrap; const std::unique_ptr<Ui::RpWidget> _wrap;

View file

@ -231,7 +231,9 @@ RepliesWidget::RepliesWidget(
}, lifetime()); }, lifetime());
_inner->editMessageRequested( _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)) { if (const auto item = session().data().message(fullId)) {
const auto media = item->media(); const auto media = item->media();
if (media && !media->webpage()) { if (media && !media->webpage()) {
@ -245,7 +247,9 @@ RepliesWidget::RepliesWidget(
}, _inner->lifetime()); }, _inner->lifetime());
_inner->replyToMessageRequested( _inner->replyToMessageRequested(
) | rpl::start_with_next([=](auto fullId) { ) | rpl::filter([=] {
return !_joinGroup;
}) | rpl::start_with_next([=](auto fullId) {
replyToMessage(fullId); replyToMessage(fullId);
}, _inner->lifetime()); }, _inner->lifetime());
@ -477,13 +481,20 @@ void RepliesWidget::setupComposeControls() {
std::move(hasSendingMessage), std::move(hasSendingMessage),
_1 && _2); _1 && _2);
auto writeRestriction = session().changes().peerFlagsValue( auto writeRestriction = rpl::combine(
_history->peer, session().changes().peerFlagsValue(
Data::PeerUpdate::Flag::Rights _history->peer,
Data::PeerUpdate::Flag::Rights),
Data::CanWriteValue(_history->peer)
) | rpl::map([=] { ) | rpl::map([=] {
return Data::RestrictionError( const auto restriction = Data::RestrictionError(
_history->peer, _history->peer,
ChatRestriction::SendMessages); ChatRestriction::SendMessages);
return restriction
? restriction
: _history->peer->canWrite()
? std::optional<QString>()
: tr::lng_group_not_accessible(tr::now);
}); });
_composeControls->setHistory({ _composeControls->setHistory({
@ -495,7 +506,9 @@ void RepliesWidget::setupComposeControls() {
}); });
_composeControls->height( _composeControls->height(
) | rpl::start_with_next([=] { ) | rpl::filter([=] {
return !_joinGroup;
}) | rpl::start_with_next([=] {
const auto wasMax = (_scroll->scrollTopMax() == _scroll->scrollTop()); const auto wasMax = (_scroll->scrollTopMax() == _scroll->scrollTop());
updateControlsGeometry(); updateControlsGeometry();
if (wasMax) { if (wasMax) {
@ -617,6 +630,20 @@ void RepliesWidget::setupComposeControls() {
}, lifetime()); }, lifetime());
_composeControls->finishAnimating(); _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() { void RepliesWidget::chooseAttach() {
@ -1066,6 +1093,47 @@ void RepliesWidget::edit(
doSetInnerFocus(); doSetInnerFocus();
} }
void RepliesWidget::refreshJoinGroupButton() {
const auto set = [&](std::unique_ptr<Ui::FlatButton> 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<Ui::FlatButton>(
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( void RepliesWidget::sendExistingDocument(
not_null<DocumentData*> document) { not_null<DocumentData*> document) {
sendExistingDocument(document, {}, std::nullopt); sendExistingDocument(document, {}, std::nullopt);
@ -1430,7 +1498,11 @@ bool RepliesWidget::preventsClose(Fn<void()> &&continueCallback) const {
QPixmap RepliesWidget::grabForShowAnimation(const Window::SectionSlideParams &params) { QPixmap RepliesWidget::grabForShowAnimation(const Window::SectionSlideParams &params) {
_topBar->updateControlsVisibility(); _topBar->updateControlsVisibility();
if (params.withTopBarShadow) _topBarShadow->hide(); if (params.withTopBarShadow) _topBarShadow->hide();
_composeControls->showForGrab(); if (_joinGroup) {
_composeControls->hide();
} else {
_composeControls->showForGrab();
}
auto result = Ui::GrabWidget(this); auto result = Ui::GrabWidget(this);
if (params.withTopBarShadow) _topBarShadow->show(); if (params.withTopBarShadow) _topBarShadow->show();
_rootView->hide(); _rootView->hide();
@ -1605,7 +1677,9 @@ void RepliesWidget::updateControlsGeometry() {
_rootView->resizeToWidth(contentWidth); _rootView->resizeToWidth(contentWidth);
const auto bottom = height(); 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 scrollY = _topBar->height() + _rootViewHeight;
const auto scrollHeight = bottom - scrollY - controlsHeight; const auto scrollHeight = bottom - scrollY - controlsHeight;
const auto scrollSize = QSize(contentWidth, scrollHeight); const auto scrollSize = QSize(contentWidth, scrollHeight);
@ -1622,6 +1696,13 @@ void RepliesWidget::updateControlsGeometry() {
} }
updateInnerVisibleArea(); updateInnerVisibleArea();
} }
if (_joinGroup) {
_joinGroup->setGeometry(
0,
bottom - _joinGroup->height(),
contentWidth,
_joinGroup->height());
}
_composeControls->move(0, bottom - controlsHeight); _composeControls->move(0, bottom - controlsHeight);
_composeControls->setAutocompleteBoundingRect(_scroll->geometry()); _composeControls->setAutocompleteBoundingRect(_scroll->geometry());
@ -1715,7 +1796,11 @@ void RepliesWidget::showAnimatedHook(
void RepliesWidget::showFinishedHook() { void RepliesWidget::showFinishedHook() {
_topBar->setAnimatingMode(false); _topBar->setAnimatingMode(false);
_composeControls->showFinished(); if (_joinGroup) {
_composeControls->hide();
} else {
_composeControls->showFinished();
}
_rootView->show(); _rootView->show();
// We should setup the drag area only after // We should setup the drag area only after

View file

@ -260,6 +260,7 @@ private:
Api::SendOptions options, Api::SendOptions options,
std::optional<MsgId> localMessageId); std::optional<MsgId> localMessageId);
void refreshJoinGroupButton();
[[nodiscard]] bool showSlowmodeError(); [[nodiscard]] bool showSlowmodeError();
[[nodiscard]] std::optional<QString> writeRestriction() const; [[nodiscard]] std::optional<QString> writeRestriction() const;
@ -274,6 +275,7 @@ private:
object_ptr<TopBarWidget> _topBar; object_ptr<TopBarWidget> _topBar;
object_ptr<Ui::PlainShadow> _topBarShadow; object_ptr<Ui::PlainShadow> _topBarShadow;
std::unique_ptr<ComposeControls> _composeControls; std::unique_ptr<ComposeControls> _composeControls;
std::unique_ptr<Ui::FlatButton> _joinGroup;
bool _skipScrollEvent = false; bool _skipScrollEvent = false;
std::unique_ptr<Ui::PinnedBar> _rootView; std::unique_ptr<Ui::PinnedBar> _rootView;