Restrict shared media selection in noforward chats.

This commit is contained in:
John Preston 2021-11-30 16:26:47 +04:00
parent 1d1fa5f98b
commit 5309af5d56
4 changed files with 92 additions and 20 deletions

View File

@ -341,8 +341,10 @@ void TopBar::updateSelectionControlsGeometry(int newWidth) {
_delete->moveToRight(right, 0, newWidth);
right += _delete->width();
}
_forward->moveToRight(right, 0, newWidth);
right += _forward->width();
if (_canForward) {
_forward->moveToRight(right, 0, newWidth);
right += _forward->width();
}
auto left = 0;
_cancelSelection->moveToLeft(left, 0);
@ -411,6 +413,7 @@ void TopBar::setSelectedItems(SelectedItems &&items) {
SelectedItems TopBar::takeSelectedItems() {
_canDelete = false;
_canForward = false;
return std::move(_selectedItems);
}
@ -419,11 +422,13 @@ rpl::producer<> TopBar::cancelSelectionRequests() const {
}
void TopBar::updateSelectionState() {
Expects(_selectionText && _delete);
Expects(_selectionText && _delete && _forward);
_canDelete = computeCanDelete();
_canForward = computeCanForward();
_selectionText->entity()->setValue(generateSelectedText());
_delete->toggle(_canDelete, anim::type::instant);
_forward->toggle(_canForward, anim::type::instant);
updateSelectionControlsGeometry(width());
}
@ -437,6 +442,7 @@ void TopBar::createSelectionControls() {
return created;
};
_canDelete = computeCanDelete();
_canForward = computeCanForward();
_cancelSelection = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
this,
object_ptr<Ui::IconButton>(this, _st.mediaCancel),
@ -461,8 +467,12 @@ void TopBar::createSelectionControls() {
this,
object_ptr<Ui::IconButton>(this, _st.mediaForward),
st::infoTopBarScale));
registerToggleControlCallback(
_forward.data(),
[this] { return selectionMode() && _canForward; });
_forward->setDuration(st::infoTopBarDuration);
_forward->entity()->addClickHandler([this] { performForward(); });
_forward->entity()->setVisible(_canForward);
_delete = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
this,
object_ptr<Ui::IconButton>(this, _st.mediaDelete),
@ -481,6 +491,10 @@ bool TopBar::computeCanDelete() const {
return ranges::all_of(_selectedItems.list, &SelectedItem::canDelete);
}
bool TopBar::computeCanForward() const {
return ranges::all_of(_selectedItems.list, &SelectedItem::canForward);
}
Ui::StringWithNumbers TopBar::generateSelectedText() const {
using Type = Storage::SharedMediaType;
const auto phrase = [&] {

View File

@ -111,6 +111,7 @@ private:
bool searchMode() const;
Ui::StringWithNumbers generateSelectedText() const;
[[nodiscard]] bool computeCanDelete() const;
[[nodiscard]] bool computeCanForward() const;
void updateSelectionState();
void createSelectionControls();
void clearSelectionControls();
@ -153,6 +154,7 @@ private:
SelectedItems _selectedItems;
bool _canDelete = false;
bool _canForward = false;
QPointer<Ui::FadeWrap<Ui::IconButton>> _cancelSelection;
QPointer<Ui::FadeWrap<Ui::LabelWithNumbers>> _selectionText;
QPointer<Ui::FadeWrap<Ui::IconButton>> _forward;

View File

@ -13,6 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "layout/layout_selection.h"
#include "data/data_media_types.h"
#include "data/data_photo.h"
#include "data/data_chat.h"
#include "data/data_channel.h"
#include "data/data_peer_values.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_file_click_handler.h"
@ -731,9 +734,44 @@ void ListWidget::start() {
}, lifetime());
_controller->mediaSourceQueryValue(
) | rpl::start_with_next([this]{
) | rpl::start_with_next([this] {
restart();
}, lifetime());
setupSelectRestriction();
}
void ListWidget::setupSelectRestriction() {
const auto chat = _peer->asChat();
const auto channel = _peer->asChannel();
auto noForwards = chat
? Data::PeerFlagValue(chat, ChatDataFlag::NoForwards)
: Data::PeerFlagValue(
channel,
ChannelDataFlag::NoForwards
) | rpl::type_erased();
auto rights = chat
? chat->adminRightsValue()
: channel->adminRightsValue();
auto canDelete = std::move(
rights
) | rpl::map([=] {
return chat
? chat->canDeleteMessages()
: channel->canDeleteMessages();
});
rpl::combine(
std::move(noForwards),
std::move(canDelete)
) | rpl::filter([=] {
return hasSelectRestriction() && hasSelectedItems();
}) | rpl::start_with_next([=] {
clearSelected();
if (_mouseAction == MouseAction::PrepareSelect) {
mouseActionCancel();
}
}, lifetime());
}
rpl::producer<int> ListWidget::scrollToRequests() const {
@ -1656,18 +1694,20 @@ void ListWidget::showContextMenu(
[=] { _contextMenu = nullptr; }));
}
}
_contextMenu->addAction(
tr::lng_context_select_msg(tr::now),
crl::guard(this, [this, universalId] {
if (hasSelectedText()) {
clearSelected();
} else if (_selected.size() == MaxSelectedItems) {
return;
} else if (_selected.empty()) {
update();
}
applyItemSelection(universalId, FullSelection);
}));
if (!hasSelectRestriction()) {
_contextMenu->addAction(
tr::lng_context_select_msg(tr::now),
crl::guard(this, [this, universalId] {
if (hasSelectedText()) {
clearSelected();
} else if (_selected.size() == MaxSelectedItems) {
return;
} else if (_selected.empty()) {
update();
}
applyItemSelection(universalId, FullSelection);
}));
}
}
_contextMenu->setDestroyedCallback(crl::guard(
@ -1739,6 +1779,17 @@ DeleteMessagesBox *ListWidget::deleteItems(MessageIdsList &&items) {
return nullptr;
}
bool ListWidget::hasSelectRestriction() const {
if (_peer->allowsForwarding()) {
return false;
} else if (const auto chat = _peer->asChat()) {
return !chat->canDeleteMessages();
} else if (const auto channel = _peer->asChannel()) {
return !channel->canDeleteMessages();
}
return true;
}
void ListWidget::setActionBoxWeak(QPointer<Ui::RpWidget> box) {
if ((_actionBoxWeak = box)) {
_actionBoxWeakLifetime = _actionBoxWeak->alive(
@ -2047,7 +2098,7 @@ void ListWidget::updateDragSelection() {
if (swapStates) {
std::swap(fromState, tillState);
}
if (!fromState.itemId || !tillState.itemId) {
if (!fromState.itemId || !tillState.itemId || hasSelectRestriction()) {
clearDragSelection();
return;
}
@ -2183,12 +2234,12 @@ void ListWidget::mouseActionStart(
applyItemSelection(_pressState.itemId, selStatus);
_mouseAction = MouseAction::Selecting;
repaintItem(pressLayout);
} else {
} else if (!hasSelectRestriction()) {
_mouseAction = MouseAction::PrepareSelect;
}
}
}
} else if (!_pressWasInactive) {
} else if (!_pressWasInactive && !hasSelectRestriction()) {
_mouseAction = MouseAction::PrepareSelect; // start items select
}
}
@ -2365,7 +2416,9 @@ void ListWidget::mouseActionFinish(
}
void ListWidget::applyDragSelection() {
applyDragSelection(_selected);
if (!hasSelectRestriction()) {
applyDragSelection(_selected);
}
clearDragSelection();
pushSelectedItems();
}

View File

@ -176,6 +176,9 @@ private:
int recountHeight();
void refreshHeight();
void setupSelectRestriction();
[[nodiscard]] bool hasSelectRestriction() const;
QMargins padding() const;
bool isMyItem(not_null<const HistoryItem*> item) const;
bool isItemLayout(