Restrict shared media selection in noforward chats.
This commit is contained in:
parent
1d1fa5f98b
commit
5309af5d56
|
@ -341,8 +341,10 @@ void TopBar::updateSelectionControlsGeometry(int newWidth) {
|
||||||
_delete->moveToRight(right, 0, newWidth);
|
_delete->moveToRight(right, 0, newWidth);
|
||||||
right += _delete->width();
|
right += _delete->width();
|
||||||
}
|
}
|
||||||
_forward->moveToRight(right, 0, newWidth);
|
if (_canForward) {
|
||||||
right += _forward->width();
|
_forward->moveToRight(right, 0, newWidth);
|
||||||
|
right += _forward->width();
|
||||||
|
}
|
||||||
|
|
||||||
auto left = 0;
|
auto left = 0;
|
||||||
_cancelSelection->moveToLeft(left, 0);
|
_cancelSelection->moveToLeft(left, 0);
|
||||||
|
@ -411,6 +413,7 @@ void TopBar::setSelectedItems(SelectedItems &&items) {
|
||||||
|
|
||||||
SelectedItems TopBar::takeSelectedItems() {
|
SelectedItems TopBar::takeSelectedItems() {
|
||||||
_canDelete = false;
|
_canDelete = false;
|
||||||
|
_canForward = false;
|
||||||
return std::move(_selectedItems);
|
return std::move(_selectedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,11 +422,13 @@ rpl::producer<> TopBar::cancelSelectionRequests() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopBar::updateSelectionState() {
|
void TopBar::updateSelectionState() {
|
||||||
Expects(_selectionText && _delete);
|
Expects(_selectionText && _delete && _forward);
|
||||||
|
|
||||||
_canDelete = computeCanDelete();
|
_canDelete = computeCanDelete();
|
||||||
|
_canForward = computeCanForward();
|
||||||
_selectionText->entity()->setValue(generateSelectedText());
|
_selectionText->entity()->setValue(generateSelectedText());
|
||||||
_delete->toggle(_canDelete, anim::type::instant);
|
_delete->toggle(_canDelete, anim::type::instant);
|
||||||
|
_forward->toggle(_canForward, anim::type::instant);
|
||||||
|
|
||||||
updateSelectionControlsGeometry(width());
|
updateSelectionControlsGeometry(width());
|
||||||
}
|
}
|
||||||
|
@ -437,6 +442,7 @@ void TopBar::createSelectionControls() {
|
||||||
return created;
|
return created;
|
||||||
};
|
};
|
||||||
_canDelete = computeCanDelete();
|
_canDelete = computeCanDelete();
|
||||||
|
_canForward = computeCanForward();
|
||||||
_cancelSelection = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
_cancelSelection = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
||||||
this,
|
this,
|
||||||
object_ptr<Ui::IconButton>(this, _st.mediaCancel),
|
object_ptr<Ui::IconButton>(this, _st.mediaCancel),
|
||||||
|
@ -461,8 +467,12 @@ void TopBar::createSelectionControls() {
|
||||||
this,
|
this,
|
||||||
object_ptr<Ui::IconButton>(this, _st.mediaForward),
|
object_ptr<Ui::IconButton>(this, _st.mediaForward),
|
||||||
st::infoTopBarScale));
|
st::infoTopBarScale));
|
||||||
|
registerToggleControlCallback(
|
||||||
|
_forward.data(),
|
||||||
|
[this] { return selectionMode() && _canForward; });
|
||||||
_forward->setDuration(st::infoTopBarDuration);
|
_forward->setDuration(st::infoTopBarDuration);
|
||||||
_forward->entity()->addClickHandler([this] { performForward(); });
|
_forward->entity()->addClickHandler([this] { performForward(); });
|
||||||
|
_forward->entity()->setVisible(_canForward);
|
||||||
_delete = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
_delete = wrap(Ui::CreateChild<Ui::FadeWrap<Ui::IconButton>>(
|
||||||
this,
|
this,
|
||||||
object_ptr<Ui::IconButton>(this, _st.mediaDelete),
|
object_ptr<Ui::IconButton>(this, _st.mediaDelete),
|
||||||
|
@ -481,6 +491,10 @@ bool TopBar::computeCanDelete() const {
|
||||||
return ranges::all_of(_selectedItems.list, &SelectedItem::canDelete);
|
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 {
|
Ui::StringWithNumbers TopBar::generateSelectedText() const {
|
||||||
using Type = Storage::SharedMediaType;
|
using Type = Storage::SharedMediaType;
|
||||||
const auto phrase = [&] {
|
const auto phrase = [&] {
|
||||||
|
|
|
@ -111,6 +111,7 @@ private:
|
||||||
bool searchMode() const;
|
bool searchMode() const;
|
||||||
Ui::StringWithNumbers generateSelectedText() const;
|
Ui::StringWithNumbers generateSelectedText() const;
|
||||||
[[nodiscard]] bool computeCanDelete() const;
|
[[nodiscard]] bool computeCanDelete() const;
|
||||||
|
[[nodiscard]] bool computeCanForward() const;
|
||||||
void updateSelectionState();
|
void updateSelectionState();
|
||||||
void createSelectionControls();
|
void createSelectionControls();
|
||||||
void clearSelectionControls();
|
void clearSelectionControls();
|
||||||
|
@ -153,6 +154,7 @@ private:
|
||||||
|
|
||||||
SelectedItems _selectedItems;
|
SelectedItems _selectedItems;
|
||||||
bool _canDelete = false;
|
bool _canDelete = false;
|
||||||
|
bool _canForward = false;
|
||||||
QPointer<Ui::FadeWrap<Ui::IconButton>> _cancelSelection;
|
QPointer<Ui::FadeWrap<Ui::IconButton>> _cancelSelection;
|
||||||
QPointer<Ui::FadeWrap<Ui::LabelWithNumbers>> _selectionText;
|
QPointer<Ui::FadeWrap<Ui::LabelWithNumbers>> _selectionText;
|
||||||
QPointer<Ui::FadeWrap<Ui::IconButton>> _forward;
|
QPointer<Ui::FadeWrap<Ui::IconButton>> _forward;
|
||||||
|
|
|
@ -13,6 +13,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "layout/layout_selection.h"
|
#include "layout/layout_selection.h"
|
||||||
#include "data/data_media_types.h"
|
#include "data/data_media_types.h"
|
||||||
#include "data/data_photo.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_document.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_file_click_handler.h"
|
#include "data/data_file_click_handler.h"
|
||||||
|
@ -731,9 +734,44 @@ void ListWidget::start() {
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
_controller->mediaSourceQueryValue(
|
_controller->mediaSourceQueryValue(
|
||||||
) | rpl::start_with_next([this]{
|
) | rpl::start_with_next([this] {
|
||||||
restart();
|
restart();
|
||||||
}, lifetime());
|
}, 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 {
|
rpl::producer<int> ListWidget::scrollToRequests() const {
|
||||||
|
@ -1656,18 +1694,20 @@ void ListWidget::showContextMenu(
|
||||||
[=] { _contextMenu = nullptr; }));
|
[=] { _contextMenu = nullptr; }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_contextMenu->addAction(
|
if (!hasSelectRestriction()) {
|
||||||
tr::lng_context_select_msg(tr::now),
|
_contextMenu->addAction(
|
||||||
crl::guard(this, [this, universalId] {
|
tr::lng_context_select_msg(tr::now),
|
||||||
if (hasSelectedText()) {
|
crl::guard(this, [this, universalId] {
|
||||||
clearSelected();
|
if (hasSelectedText()) {
|
||||||
} else if (_selected.size() == MaxSelectedItems) {
|
clearSelected();
|
||||||
return;
|
} else if (_selected.size() == MaxSelectedItems) {
|
||||||
} else if (_selected.empty()) {
|
return;
|
||||||
update();
|
} else if (_selected.empty()) {
|
||||||
}
|
update();
|
||||||
applyItemSelection(universalId, FullSelection);
|
}
|
||||||
}));
|
applyItemSelection(universalId, FullSelection);
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_contextMenu->setDestroyedCallback(crl::guard(
|
_contextMenu->setDestroyedCallback(crl::guard(
|
||||||
|
@ -1739,6 +1779,17 @@ DeleteMessagesBox *ListWidget::deleteItems(MessageIdsList &&items) {
|
||||||
return nullptr;
|
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) {
|
void ListWidget::setActionBoxWeak(QPointer<Ui::RpWidget> box) {
|
||||||
if ((_actionBoxWeak = box)) {
|
if ((_actionBoxWeak = box)) {
|
||||||
_actionBoxWeakLifetime = _actionBoxWeak->alive(
|
_actionBoxWeakLifetime = _actionBoxWeak->alive(
|
||||||
|
@ -2047,7 +2098,7 @@ void ListWidget::updateDragSelection() {
|
||||||
if (swapStates) {
|
if (swapStates) {
|
||||||
std::swap(fromState, tillState);
|
std::swap(fromState, tillState);
|
||||||
}
|
}
|
||||||
if (!fromState.itemId || !tillState.itemId) {
|
if (!fromState.itemId || !tillState.itemId || hasSelectRestriction()) {
|
||||||
clearDragSelection();
|
clearDragSelection();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2183,12 +2234,12 @@ void ListWidget::mouseActionStart(
|
||||||
applyItemSelection(_pressState.itemId, selStatus);
|
applyItemSelection(_pressState.itemId, selStatus);
|
||||||
_mouseAction = MouseAction::Selecting;
|
_mouseAction = MouseAction::Selecting;
|
||||||
repaintItem(pressLayout);
|
repaintItem(pressLayout);
|
||||||
} else {
|
} else if (!hasSelectRestriction()) {
|
||||||
_mouseAction = MouseAction::PrepareSelect;
|
_mouseAction = MouseAction::PrepareSelect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!_pressWasInactive) {
|
} else if (!_pressWasInactive && !hasSelectRestriction()) {
|
||||||
_mouseAction = MouseAction::PrepareSelect; // start items select
|
_mouseAction = MouseAction::PrepareSelect; // start items select
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2365,7 +2416,9 @@ void ListWidget::mouseActionFinish(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListWidget::applyDragSelection() {
|
void ListWidget::applyDragSelection() {
|
||||||
applyDragSelection(_selected);
|
if (!hasSelectRestriction()) {
|
||||||
|
applyDragSelection(_selected);
|
||||||
|
}
|
||||||
clearDragSelection();
|
clearDragSelection();
|
||||||
pushSelectedItems();
|
pushSelectedItems();
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,6 +176,9 @@ private:
|
||||||
int recountHeight();
|
int recountHeight();
|
||||||
void refreshHeight();
|
void refreshHeight();
|
||||||
|
|
||||||
|
void setupSelectRestriction();
|
||||||
|
[[nodiscard]] bool hasSelectRestriction() const;
|
||||||
|
|
||||||
QMargins padding() const;
|
QMargins padding() const;
|
||||||
bool isMyItem(not_null<const HistoryItem*> item) const;
|
bool isMyItem(not_null<const HistoryItem*> item) const;
|
||||||
bool isItemLayout(
|
bool isItemLayout(
|
||||||
|
|
Loading…
Reference in New Issue