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 {
// 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)));

View file

@ -205,6 +205,7 @@ rpl::producer<bool> 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<bool> 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)

View file

@ -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();
}
}

View file

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

View file

@ -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<QString>()
: 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<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(
not_null<DocumentData*> document) {
sendExistingDocument(document, {}, std::nullopt);
@ -1430,7 +1498,11 @@ bool RepliesWidget::preventsClose(Fn<void()> &&continueCallback) const {
QPixmap RepliesWidget::grabForShowAnimation(const Window::SectionSlideParams &params) {
_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

View file

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