Replace SelectedItemSet with MessageIdsList.

Use vector<FullMsgId> everywhere instead QMap<..,HistoryItem*>.
The old way the app crashed in case some messages were deleted.
If the items are needed use HistoryItemsList=vector<HistoryItem*>.
This commit is contained in:
John Preston 2017-12-06 14:13:38 +04:00
parent 3845985a6b
commit 6764a3cc86
25 changed files with 269 additions and 248 deletions

View File

@ -356,6 +356,28 @@ rpl::producer<> AuthSessionData::savedGifsUpdated() const {
return _savedGifsUpdated.events(); return _savedGifsUpdated.events();
} }
HistoryItemsList AuthSessionData::idsToItems(
const MessageIdsList &ids) const {
return ranges::view::all(
ids
) | ranges::view::transform([](const FullMsgId &fullId) {
return App::histItemById(fullId);
}) | ranges::view::filter([](HistoryItem *item) {
return item != nullptr;
}) | ranges::view::transform([](HistoryItem *item) {
return not_null<HistoryItem*>(item);
}) | ranges::to_vector;
}
MessageIdsList AuthSessionData::itemsToIds(
const HistoryItemsList &items) const {
return ranges::view::all(
items
) | ranges::view::transform([](not_null<HistoryItem*> item) {
return item->fullId();
}) | ranges::to_vector;
}
AuthSession &Auth() { AuthSession &Auth() {
auto result = Messenger::Instance().authSession(); auto result = Messenger::Instance().authSession();
Assert(result != nullptr); Assert(result != nullptr);

View File

@ -261,6 +261,9 @@ public:
return _savedGifs; return _savedGifs;
} }
HistoryItemsList idsToItems(const MessageIdsList &ids) const;
MessageIdsList itemsToIds(const HistoryItemsList &items) const;
private: private:
struct Variables { struct Variables {
Variables(); Variables();

View File

@ -450,21 +450,11 @@ DeleteMessagesBox::DeleteMessagesBox(
DeleteMessagesBox::DeleteMessagesBox( DeleteMessagesBox::DeleteMessagesBox(
QWidget*, QWidget*,
const SelectedItemSet &selected) MessageIdsList &&selected)
: _ids(CollectFrom(selected)) { : _ids(std::move(selected)) {
Expects(!_ids.empty()); Expects(!_ids.empty());
} }
std::vector<FullMsgId> DeleteMessagesBox::CollectFrom(
const SelectedItemSet &items) {
return ranges::make_iterator_range(
items.begin(),
items.end()
) | ranges::view::transform([](not_null<HistoryItem*> item) {
return item->fullId();
}) | ranges::to_vector;
}
void DeleteMessagesBox::prepare() { void DeleteMessagesBox::prepare() {
auto text = QString(); auto text = QString();
if (_moderateFrom) { if (_moderateFrom) {

View File

@ -177,7 +177,7 @@ public:
QWidget*, QWidget*,
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
bool suggestModerateActions); bool suggestModerateActions);
DeleteMessagesBox(QWidget*, const SelectedItemSet &selected); DeleteMessagesBox(QWidget*, MessageIdsList &&selected);
protected: protected:
void prepare() override; void prepare() override;
@ -188,9 +188,7 @@ protected:
private: private:
void deleteAndClear(); void deleteAndClear();
static std::vector<FullMsgId> CollectFrom(const SelectedItemSet &items); const MessageIdsList _ids;
const std::vector<FullMsgId> _ids;
const bool _singleItem = false; const bool _singleItem = false;
UserData *_moderateFrom = nullptr; UserData *_moderateFrom = nullptr;
ChannelData *_moderateInChannel = nullptr; ChannelData *_moderateInChannel = nullptr;

View File

@ -892,7 +892,7 @@ void AddBotToGroupBoxController::prepareViewHook() {
} }
ChooseRecipientBoxController::ChooseRecipientBoxController( ChooseRecipientBoxController::ChooseRecipientBoxController(
base::lambda<void(not_null<PeerData*>)> callback) base::lambda_once<void(not_null<PeerData*>)> callback)
: _callback(std::move(callback)) { : _callback(std::move(callback)) {
} }

View File

@ -243,7 +243,7 @@ private:
class ChooseRecipientBoxController : public ChatsListBoxController { class ChooseRecipientBoxController : public ChatsListBoxController {
public: public:
ChooseRecipientBoxController( ChooseRecipientBoxController(
base::lambda<void(not_null<PeerData*>)> callback); base::lambda_once<void(not_null<PeerData*>)> callback);
void rowClicked(not_null<PeerListRow*> row) override; void rowClicked(not_null<PeerListRow*> row) override;
@ -257,6 +257,6 @@ protected:
not_null<History*> history) override; not_null<History*> history) override;
private: private:
base::lambda<void(not_null<PeerData*>)> _callback; base::lambda_once<void(not_null<PeerData*>)> _callback;
}; };

View File

@ -154,6 +154,8 @@ inline bool operator<(const FullMsgId &a, const FullMsgId &b) {
return a.channel < b.channel; return a.channel < b.channel;
} }
using MessageIdsList = std::vector<FullMsgId>;
inline PeerId peerFromMessage(const MTPmessage &msg) { inline PeerId peerFromMessage(const MTPmessage &msg) {
auto compute = [](auto &message) { auto compute = [](auto &message) {
auto from_id = message.has_from_id() ? peerFromUser(message.vfrom_id) : 0; auto from_id = message.has_from_id() ? peerFromUser(message.vfrom_id) : 0;

View File

@ -798,7 +798,7 @@ void DialogsWidget::updateDragInScroll(bool inScroll) {
if (_dragInScroll != inScroll) { if (_dragInScroll != inScroll) {
_dragInScroll = inScroll; _dragInScroll = inScroll;
if (_dragInScroll) { if (_dragInScroll) {
App::main()->showForwardLayer(SelectedItemSet()); App::main()->showForwardLayer({});
} else { } else {
App::main()->dialogsCancelled(); App::main()->dialogsCancelled();
} }

View File

@ -214,26 +214,16 @@ void History::draftSavedToCloud() {
if (App::main()) App::main()->writeDrafts(this); if (App::main()) App::main()->writeDrafts(this);
} }
SelectedItemSet History::validateForwardDraft() { HistoryItemsList History::validateForwardDraft() {
auto result = SelectedItemSet(); auto result = Auth().data().idsToItems(_forwardDraft);
auto count = 0;
for_const (auto &fullMsgId, _forwardDraft) {
if (auto item = App::histItemById(fullMsgId)) {
result.insert(++count, item);
}
}
if (result.size() != _forwardDraft.size()) { if (result.size() != _forwardDraft.size()) {
setForwardDraft(result); setForwardDraft(Auth().data().itemsToIds(result));
} }
return result; return result;
} }
void History::setForwardDraft(const SelectedItemSet &items) { void History::setForwardDraft(MessageIdsList &&items) {
_forwardDraft.clear(); _forwardDraft = std::move(items);
_forwardDraft.reserve(items.size());
for_const (auto item, items) {
_forwardDraft.push_back(item->fullId());
}
} }
bool History::updateSendActionNeedsAnimating(UserData *user, const MTPSendMessageAction &action) { bool History::updateSendActionNeedsAnimating(UserData *user, const MTPSendMessageAction &action) {

View File

@ -33,7 +33,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
void HistoryInit(); void HistoryInit();
class HistoryItem; class HistoryItem;
using SelectedItemSet = QMap<int, not_null<HistoryItem*>>; using HistoryItemsList = std::vector<not_null<HistoryItem*>>;
enum NewMessageType { enum NewMessageType {
NewMessageUnread, NewMessageUnread,
@ -423,11 +423,11 @@ public:
return _editDraft ? editDraft() : localDraft(); return _editDraft ? editDraft() : localDraft();
} }
QVector<FullMsgId> forwardDraft() const { const MessageIdsList &forwardDraft() const {
return _forwardDraft; return _forwardDraft;
} }
SelectedItemSet validateForwardDraft(); HistoryItemsList validateForwardDraft();
void setForwardDraft(const SelectedItemSet &items); void setForwardDraft(MessageIdsList &&items);
// some fields below are a property of a currently displayed instance of this // some fields below are a property of a currently displayed instance of this
// conversation history not a property of the conversation history itself // conversation history not a property of the conversation history itself
@ -603,7 +603,7 @@ private:
std::unique_ptr<Data::Draft> _localDraft, _cloudDraft; std::unique_ptr<Data::Draft> _localDraft, _cloudDraft;
std::unique_ptr<Data::Draft> _editDraft; std::unique_ptr<Data::Draft> _editDraft;
QVector<FullMsgId> _forwardDraft; MessageIdsList _forwardDraft;
using TypingUsers = QMap<UserData*, TimeMs>; using TypingUsers = QMap<UserData*, TimeMs>;
TypingUsers _typing; TypingUsers _typing;

View File

@ -1984,22 +1984,26 @@ void HistoryInner::clearSelectedItems(bool onlyTextSelection) {
} }
} }
SelectedItemSet HistoryInner::getSelectedItems() const { MessageIdsList HistoryInner::getSelectedItems() const {
auto result = SelectedItemSet(); using namespace ranges;
if (_selected.empty() || _selected.cbegin()->second != FullSelection) { if (_selected.empty() || _selected.cbegin()->second != FullSelection) {
return result; return {};
} }
for (auto &selected : _selected) { auto result = make_iterator_range(
auto item = selected.first; _selected.begin(),
if (item && item->toHistoryMessage() && item->id > 0) { _selected.end()
if (item->history() == _migrated) { ) | view::filter([](const auto &selected) {
result.insert(item->id - ServerMaxMsgId, item); const auto item = selected.first;
} else { return item && item->toHistoryMessage() && (item->id > 0);
result.insert(item->id, item); }) | view::transform([](const auto &selected) {
} return selected.first->fullId();
} }) | to_vector;
}
result |= action::sort(ordered_less{}, [](const FullMsgId &msgId) {
return msgId.channel ? msgId.msg : (msgId.msg - ServerMaxMsgId);
});
return result; return result;
} }

View File

@ -65,7 +65,7 @@ public:
HistoryTopBarWidget::SelectedState getSelectionState() const; HistoryTopBarWidget::SelectedState getSelectionState() const;
void clearSelectedItems(bool onlyTextSelection = false); void clearSelectedItems(bool onlyTextSelection = false);
SelectedItemSet getSelectedItems() const; MessageIdsList getSelectedItems() const;
void selectItem(HistoryItem *item); void selectItem(HistoryItem *item);
void updateBotInfo(bool recount = true); void updateBotInfo(bool recount = true);

View File

@ -119,9 +119,9 @@ MTPDmessage::Flags NewForwardedFlags(
return result; return result;
} }
bool HasMediaItems(const SelectedItemSet &items) { bool HasMediaItems(const HistoryItemsList &items) {
for_const (auto item, items) { for (const auto item : items) {
if (auto media = item->getMedia()) { if (const auto media = item->getMedia()) {
switch (media->type()) { switch (media->type()) {
case MediaTypePhoto: case MediaTypePhoto:
case MediaTypeVideo: case MediaTypeVideo:
@ -135,9 +135,9 @@ bool HasMediaItems(const SelectedItemSet &items) {
return false; return false;
} }
bool HasStickerItems(const SelectedItemSet &items) { bool HasStickerItems(const HistoryItemsList &items) {
for_const (auto item, items) { for (const auto item : items) {
if (auto media = item->getMedia()) { if (const auto media = item->getMedia()) {
switch (media->type()) { switch (media->type()) {
case MediaTypeSticker: return true; case MediaTypeSticker: return true;
} }
@ -146,9 +146,9 @@ bool HasStickerItems(const SelectedItemSet &items) {
return false; return false;
} }
bool HasGifItems(const SelectedItemSet &items) { bool HasGifItems(const HistoryItemsList &items) {
for_const (auto item, items) { for (const auto item : items) {
if (auto media = item->getMedia()) { if (const auto media = item->getMedia()) {
switch (media->type()) { switch (media->type()) {
case MediaTypeGif: return !media->getDocument()->isRoundVideo(); case MediaTypeGif: return !media->getDocument()->isRoundVideo();
} }
@ -157,9 +157,9 @@ bool HasGifItems(const SelectedItemSet &items) {
return false; return false;
} }
bool HasGameItems(const SelectedItemSet &items) { bool HasGameItems(const HistoryItemsList &items) {
for_const (auto item, items) { for (const auto item : items) {
if (auto media = item->getMedia()) { if (const auto media = item->getMedia()) {
switch (media->type()) { switch (media->type()) {
case MediaTypeGame: return true; case MediaTypeGame: return true;
} }
@ -168,8 +168,8 @@ bool HasGameItems(const SelectedItemSet &items) {
return false; return false;
} }
bool HasInlineItems(const SelectedItemSet &items) { bool HasInlineItems(const HistoryItemsList &items) {
for_const (auto item, items) { for (const auto item : items) {
if (item->viaBot()) { if (item->viaBot()) {
return true; return true;
} }
@ -229,13 +229,12 @@ void FastShareMessage(not_null<HistoryItem*> item) {
return; return;
} }
auto items = SelectedItemSet(); auto items = HistoryItemsList(1, item);
auto restrictedSomewhere = false; auto restrictedSomewhere = false;
auto restrictedEverywhere = true; auto restrictedEverywhere = true;
auto firstError = QString(); auto firstError = QString();
items.insert(item->id, item); for (const auto peer : result) {
for_const (auto peer, result) { const auto error = GetErrorTextForForward(peer, items);
auto error = GetErrorTextForForward(peer, items);
if (!error.isEmpty()) { if (!error.isEmpty()) {
if (firstError.isEmpty()) { if (firstError.isEmpty()) {
firstError = error; firstError = error;
@ -266,7 +265,7 @@ void FastShareMessage(not_null<HistoryItem*> item) {
auto sendFlags = MTPmessages_ForwardMessages::Flag::f_with_my_score; auto sendFlags = MTPmessages_ForwardMessages::Flag::f_with_my_score;
MTPVector<MTPint> msgIds = MTP_vector<MTPint>(1, MTP_int(data->msgId.msg)); MTPVector<MTPint> msgIds = MTP_vector<MTPint>(1, MTP_int(data->msgId.msg));
if (auto main = App::main()) { if (auto main = App::main()) {
for_const (auto peer, result) { for (const auto peer : result) {
if (!GetErrorTextForForward(peer, items).isEmpty()) { if (!GetErrorTextForForward(peer, items).isEmpty()) {
continue; continue;
} }
@ -320,7 +319,9 @@ MTPDmessage::Flags NewMessageFlags(not_null<PeerData*> peer) {
return result; return result;
} }
QString GetErrorTextForForward(not_null<PeerData*> peer, const SelectedItemSet &items) { QString GetErrorTextForForward(
not_null<PeerData*> peer,
const HistoryItemsList &items) {
if (!peer->canWrite()) { if (!peer->canWrite()) {
return lang(lng_forward_cant); return lang(lng_forward_cant);
} }

View File

@ -23,7 +23,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
void HistoryInitMessages(); void HistoryInitMessages();
base::lambda<void(ChannelData*, MsgId)> HistoryDependentItemCallback(const FullMsgId &msgId); base::lambda<void(ChannelData*, MsgId)> HistoryDependentItemCallback(const FullMsgId &msgId);
MTPDmessage::Flags NewMessageFlags(not_null<PeerData*> peer); MTPDmessage::Flags NewMessageFlags(not_null<PeerData*> peer);
QString GetErrorTextForForward(not_null<PeerData*> peer, const SelectedItemSet &items); QString GetErrorTextForForward(
not_null<PeerData*> peer,
const HistoryItemsList &items);
void FastShareMessage(not_null<HistoryItem*> item); void FastShareMessage(not_null<HistoryItem*> item);
class HistoryMessage : public HistoryItem, private HistoryItemInstantiated<HistoryMessage> { class HistoryMessage : public HistoryItem, private HistoryItemInstantiated<HistoryMessage> {

View File

@ -66,15 +66,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "history/history_top_bar_widget.h" #include "history/history_top_bar_widget.h"
#include "window/themes/window_theme.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "base/qthelp_regex.h" #include "base/qthelp_regex.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "platform/platform_file_utilities.h" #include "platform/platform_file_utilities.h"
#include "auth_session.h" #include "auth_session.h"
#include "window/themes/window_theme.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/window_slide_animation.h" #include "window/window_slide_animation.h"
#include "window/window_peer_menu.h"
#include "inline_bots/inline_results_widget.h" #include "inline_bots/inline_results_widget.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
@ -174,8 +175,11 @@ void ReportSpamPanel::setReported(bool reported, PeerData *onPeer) {
update(); update();
} }
HistoryHider::HistoryHider(MainWidget *parent, const SelectedItemSet &items) : RpWidget(parent) HistoryHider::HistoryHider(
, _forwardItems(items) MainWidget *parent,
MessageIdsList &&items)
: RpWidget(parent)
, _forwardItems(std::move(items))
, _send(this, langFactory(lng_forward_send), st::defaultBoxButton) , _send(this, langFactory(lng_forward_send), st::defaultBoxButton)
, _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) { , _cancel(this, langFactory(lng_cancel), st::defaultBoxButton) {
init(); init();
@ -212,20 +216,6 @@ HistoryHider::HistoryHider(MainWidget *parent, const QString &url, const QString
void HistoryHider::init() { void HistoryHider::init() {
subscribe(Lang::Current().updated(), [this] { refreshLang(); }); subscribe(Lang::Current().updated(), [this] { refreshLang(); });
if (!_forwardItems.empty()) {
Auth().data().itemRemoved()
| rpl::start_with_next([this](auto item) {
for (auto i = _forwardItems.begin(); i != _forwardItems.end(); ++i) {
if (i->get() == item) {
i = _forwardItems.erase(i);
break;
}
}
if (_forwardItems.empty()) {
startHide();
}
}, lifetime());
}
connect(_send, SIGNAL(clicked()), this, SLOT(forward())); connect(_send, SIGNAL(clicked()), this, SLOT(forward()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(startHide())); connect(_cancel, SIGNAL(clicked()), this, SLOT(startHide()));
subscribe(Global::RefPeerChooseCancel(), [this] { startHide(); }); subscribe(Global::RefPeerChooseCancel(), [this] { startHide(); });
@ -336,7 +326,7 @@ void HistoryHider::forward() {
} else if (!_botAndQuery.isEmpty()) { } else if (!_botAndQuery.isEmpty()) {
parent()->onInlineSwitchChosen(_offered->id, _botAndQuery); parent()->onInlineSwitchChosen(_offered->id, _botAndQuery);
} else { } else {
parent()->setForwardDraft(_offered->id, _forwardItems); parent()->setForwardDraft(_offered->id, std::move(_forwardItems));
} }
} }
emit forwarded(); emit forwarded();
@ -418,7 +408,7 @@ bool HistoryHider::offerPeer(PeerId peer) {
} else { } else {
auto toId = _offered->id; auto toId = _offered->id;
_offered = nullptr; _offered = nullptr;
if (parent()->setForwardDraft(toId, _forwardItems)) { if (parent()->setForwardDraft(toId, std::move(_forwardItems))) {
startHide(); startHide();
} }
return false; return false;
@ -3673,7 +3663,7 @@ bool HistoryWidget::canSendMessages(PeerData *peer) const {
} }
bool HistoryWidget::readyToForward() const { bool HistoryWidget::readyToForward() const {
return _canSendMessages && !_toForward.isEmpty(); return _canSendMessages && !_toForward.empty();
} }
bool HistoryWidget::hasSilentToggle() const { bool HistoryWidget::hasSilentToggle() const {
@ -3880,9 +3870,7 @@ void HistoryWidget::forwardMessage() {
auto item = App::contextItem(); auto item = App::contextItem();
if (!item || item->id < 0 || item->serviceMsg()) return; if (!item || item->id < 0 || item->serviceMsg()) return;
auto items = SelectedItemSet(); Window::ShowForwardMessagesBox({ 1, item->fullId() });
items.insert(item->id, item);
App::main()->showForwardBox(std::move(items));
} }
void HistoryWidget::selectMessage() { void HistoryWidget::selectMessage() {
@ -4878,15 +4866,13 @@ void HistoryWidget::itemRemoved(not_null<const HistoryItem*> item) {
onKbToggle(); onKbToggle();
_kbReplyTo = 0; _kbReplyTo = 0;
} }
for (auto i = _toForward.begin(); i != _toForward.end(); ++i) { auto found = ranges::find(_toForward, item);
if (i->get() == item) { if (found != _toForward.end()) {
i = _toForward.erase(i); _toForward.erase(found);
updateForwardingTexts(); updateForwardingTexts();
if (_toForward.empty()) { if (_toForward.empty()) {
updateControlsVisibility(); updateControlsVisibility();
updateControlsGeometry(); updateControlsGeometry();
}
break;
} }
} }
} }
@ -5278,9 +5264,13 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
updateField(); updateField();
} else if (_inReplyEditForward) { } else if (_inReplyEditForward) {
if (readyToForward()) { if (readyToForward()) {
auto items = _toForward; const auto items = std::move(_toForward);
App::main()->cancelForwarding(_history); App::main()->cancelForwarding(_history);
App::main()->showForwardBox(std::move(items)); Window::ShowForwardMessagesBox(ranges::view::all(
items
) | ranges::view::transform([](not_null<HistoryItem*> item) {
return item->fullId();
}) | ranges::to_vector);
} else { } else {
Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId()); Ui::showPeerHistory(_peer, _editMsgId ? _editMsgId : replyToId());
} }
@ -5680,9 +5670,9 @@ void HistoryWidget::onReplyToMessage() {
auto item = App::contextItem(); auto item = App::contextItem();
if (!item || item->id < 0 || item->serviceMsg()) return; if (!item || item->id < 0 || item->serviceMsg()) return;
auto items = SelectedItemSet(); App::main()->setForwardDraft(
items.insert(item->id, item); _peer->id,
App::main()->setForwardDraft(_peer->id, items); { 1, item->fullId() });
}))); })));
} }
} }
@ -6178,7 +6168,7 @@ void HistoryWidget::handlePeerUpdate() {
void HistoryWidget::onForwardSelected() { void HistoryWidget::onForwardSelected() {
if (!_list) return; if (!_list) return;
App::main()->showForwardBox(getSelectedItems()); Window::ShowForwardMessagesBox(getSelectedItems());
} }
void HistoryWidget::confirmDeleteContextItem() { void HistoryWidget::confirmDeleteContextItem() {
@ -6198,9 +6188,9 @@ void HistoryWidget::confirmDeleteSelectedItems() {
if (!_list) return; if (!_list) return;
auto selected = _list->getSelectedItems(); auto selected = _list->getSelectedItems();
if (selected.isEmpty()) return; if (selected.empty()) return;
App::main()->deleteLayer(selected.size()); App::main()->deleteLayer(int(selected.size()));
} }
void HistoryWidget::deleteContextItem(bool forEveryone) { void HistoryWidget::deleteContextItem(bool forEveryone) {
@ -6230,18 +6220,24 @@ void HistoryWidget::deleteSelectedItems(bool forEveryone) {
Ui::hideLayer(); Ui::hideLayer();
if (!_list) return; if (!_list) return;
auto selected = _list->getSelectedItems(); const auto items = _list->getSelectedItems();
if (selected.isEmpty()) return; const auto selected = ranges::view::all(
items
) | ranges::view::transform([](const FullMsgId &fullId) {
return App::histItemById(fullId);
}) | ranges::view::filter([](HistoryItem *item) {
return item != nullptr;
}) | ranges::to_vector;
if (selected.empty()) return;
QMap<PeerData*, QVector<MTPint>> idsByPeer; QMap<PeerData*, QVector<MTPint>> idsByPeer;
for_const (auto item, selected) { for (const auto item : selected) {
if (item->id > 0) { idsByPeer[item->history()->peer].push_back(MTP_int(item->id));
idsByPeer[item->history()->peer].push_back(MTP_int(item->id));
}
} }
onClearSelected(); onClearSelected();
for_const (auto item, selected) { for (const auto item : selected) {
item->destroy(); item->destroy();
} }
@ -6275,8 +6271,8 @@ HistoryItem *HistoryWidget::getItemFromHistoryOrMigrated(MsgId genericMsgId) con
return App::histItemById(_channel, genericMsgId); return App::histItemById(_channel, genericMsgId);
} }
SelectedItemSet HistoryWidget::getSelectedItems() const { MessageIdsList HistoryWidget::getSelectedItems() const {
return _list ? _list->getSelectedItems() : SelectedItemSet(); return _list ? _list->getSelectedItems() : MessageIdsList();
} }
void HistoryWidget::updateTopBarSelection() { void HistoryWidget::updateTopBarSelection() {
@ -6354,12 +6350,12 @@ void HistoryWidget::updateForwarding() {
void HistoryWidget::updateForwardingTexts() { void HistoryWidget::updateForwardingTexts() {
int32 version = 0; int32 version = 0;
QString from, text; QString from, text;
if (!_toForward.isEmpty()) { if (const auto count = int(_toForward.size())) {
QMap<PeerData*, bool> fromUsersMap; QMap<PeerData*, bool> fromUsersMap;
QVector<PeerData*> fromUsers; QVector<PeerData*> fromUsers;
fromUsers.reserve(_toForward.size()); fromUsers.reserve(_toForward.size());
for (auto i = _toForward.cbegin(), e = _toForward.cend(); i != e; ++i) { for (const auto item : _toForward) {
auto from = i.value()->senderOriginal(); const auto from = item->senderOriginal();
if (!fromUsersMap.contains(from)) { if (!fromUsersMap.contains(from)) {
fromUsersMap.insert(from, true); fromUsersMap.insert(from, true);
fromUsers.push_back(from); fromUsers.push_back(from);
@ -6374,10 +6370,10 @@ void HistoryWidget::updateForwardingTexts() {
from = lng_forwarding_from_two(lt_user, fromUsers.at(0)->shortName(), lt_second_user, fromUsers.at(1)->shortName()); from = lng_forwarding_from_two(lt_user, fromUsers.at(0)->shortName(), lt_second_user, fromUsers.at(1)->shortName());
} }
if (_toForward.size() < 2) { if (count < 2) {
text = _toForward.cbegin().value()->inReplyText(); text = _toForward.front()->inReplyText();
} else { } else {
text = lng_forward_messages(lt_count, _toForward.size()); text = lng_forward_messages(lt_count, count);
} }
} }
_toForwardFrom.setText(st::msgNameStyle, from, _textNameOptions); _toForwardFrom.setText(st::msgNameStyle, from, _textNameOptions);
@ -6386,9 +6382,9 @@ void HistoryWidget::updateForwardingTexts() {
} }
void HistoryWidget::checkForwardingInfo() { void HistoryWidget::checkForwardingInfo() {
if (!_toForward.isEmpty()) { if (!_toForward.empty()) {
auto version = 0; auto version = 0;
for_const (auto item, _toForward) { for (const auto item : _toForward) {
version += item->senderOriginal()->nameVersion; version += item->senderOriginal()->nameVersion;
} }
if (version != _toForwardNameVersion) { if (version != _toForwardNameVersion) {
@ -6461,10 +6457,14 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
auto forwardLeft = st::historyReplySkip; auto forwardLeft = st::historyReplySkip;
st::historyForwardIcon.paint(p, st::historyReplyIconPosition + QPoint(0, backy), width()); st::historyForwardIcon.paint(p, st::historyReplyIconPosition + QPoint(0, backy), width());
if (!drawWebPagePreview) { if (!drawWebPagePreview) {
auto firstItem = _toForward.cbegin().value(); const auto firstItem = _toForward.front();
auto firstMedia = firstItem->getMedia(); const auto firstMedia = firstItem->getMedia();
auto serviceColor = (_toForward.size() > 1) || (firstMedia != nullptr) || firstItem->serviceMsg(); const auto serviceColor = (_toForward.size() > 1)
auto preview = (_toForward.size() < 2 && firstMedia && firstMedia->hasReplyPreview()) ? firstMedia->replyPreview() : ImagePtr(); || (firstMedia != nullptr)
|| firstItem->serviceMsg();
const auto preview = (_toForward.size() < 2 && firstMedia && firstMedia->hasReplyPreview())
? firstMedia->replyPreview()
: ImagePtr();
if (!preview->isNull()) { if (!preview->isNull()) {
auto to = QRect(forwardLeft, backy + st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height()); auto to = QRect(forwardLeft, backy + st::msgReplyPadding.top(), st::msgReplyBarSize.height(), st::msgReplyBarSize.height());
if (preview->width() == preview->height()) { if (preview->width() == preview->height()) {

View File

@ -102,7 +102,7 @@ class HistoryHider : public Ui::RpWidget, private base::Subscriber {
Q_OBJECT Q_OBJECT
public: public:
HistoryHider(MainWidget *parent, const SelectedItemSet &items); // forward messages HistoryHider(MainWidget *parent, MessageIdsList &&items); // forward messages
HistoryHider(MainWidget *parent, UserData *sharedContact); // share contact HistoryHider(MainWidget *parent, UserData *sharedContact); // share contact
HistoryHider(MainWidget *parent); // send path from command line argument HistoryHider(MainWidget *parent); // send path from command line argument
HistoryHider(MainWidget *parent, const QString &url, const QString &text); // share url HistoryHider(MainWidget *parent, const QString &url, const QString &text); // share url
@ -143,7 +143,7 @@ private:
MainWidget *parent(); MainWidget *parent();
UserData *_sharedContact = nullptr; UserData *_sharedContact = nullptr;
SelectedItemSet _forwardItems; MessageIdsList _forwardItems;
bool _sendPath = false; bool _sendPath = false;
QString _shareUrl, _shareText; QString _shareUrl, _shareText;
@ -261,7 +261,7 @@ public:
void enqueueMessageHighlight(not_null<HistoryItem*> item); void enqueueMessageHighlight(not_null<HistoryItem*> item);
TimeMs highlightStartTime(not_null<const HistoryItem*> item) const; TimeMs highlightStartTime(not_null<const HistoryItem*> item) const;
SelectedItemSet getSelectedItems() const; MessageIdsList getSelectedItems() const;
void itemEdited(HistoryItem *item); void itemEdited(HistoryItem *item);
void updateScrollColors(); void updateScrollColors();
@ -485,7 +485,7 @@ private:
void showNextUnreadMention(); void showNextUnreadMention();
void handlePeerUpdate(); void handlePeerUpdate();
void setMembersShowAreaActive(bool active); void setMembersShowAreaActive(bool active);
void forwardItems(SelectedItemSet &&items); void forwardItems(MessageIdsList &&items);
void highlightMessage(MsgId universalMessageId); void highlightMessage(MsgId universalMessageId);
void adjustHighlightedMessageToMigrated(); void adjustHighlightedMessageToMigrated();
@ -553,7 +553,7 @@ private:
Text _replyToName; Text _replyToName;
int _replyToNameVersion = 0; int _replyToNameVersion = 0;
SelectedItemSet _toForward; HistoryItemsList _toForward;
Text _toForwardFrom, _toForwardText; Text _toForwardFrom, _toForwardText;
int _toForwardNameVersion = 0; int _toForwardNameVersion = 0;

View File

@ -38,6 +38,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/wrap/fade_wrap.h" #include "ui/wrap/fade_wrap.h"
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/search_field_controller.h" #include "ui/search_field_controller.h"
#include "window/window_peer_menu.h"
namespace Info { namespace Info {
@ -489,14 +490,14 @@ bool TopBar::searchMode() const {
return _searchModeAvailable && _searchModeEnabled; return _searchModeAvailable && _searchModeEnabled;
} }
SelectedItemSet TopBar::collectItems() const { MessageIdsList TopBar::collectItems() const {
auto result = SelectedItemSet(); return ranges::view::all(
for (auto value : _selectedItems.list) { _selectedItems.list
if (auto item = App::histItemById(value.msgId)) { ) | ranges::view::transform([](auto &&item) {
result.insert(result.size(), item); return item.msgId;
} }) | ranges::view::filter([](const FullMsgId &msgId) {
} return App::histItemById(msgId) != nullptr;
return result; }) | ranges::to_vector;
} }
void TopBar::performForward() { void TopBar::performForward() {
@ -505,20 +506,11 @@ void TopBar::performForward() {
_cancelSelectionClicks.fire({}); _cancelSelectionClicks.fire({});
return; return;
} }
auto callback = [items = std::move(items), weak = make_weak(this)]( Window::ShowForwardMessagesBox(std::move(items), [weak = make_weak(this)]{
not_null<PeerData*> peer) {
App::main()->setForwardDraft(peer->id, items);
if (weak) { if (weak) {
weak->_cancelSelectionClicks.fire({}); weak->_cancelSelectionClicks.fire({});
} }
}; });
Ui::show(Box<PeerListBox>(
std::make_unique<ChooseRecipientBoxController>(std::move(callback)),
[](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_cancel), [box] {
box->closeBox();
});
}));
} }
void TopBar::performDelete() { void TopBar::performDelete() {
@ -526,7 +518,7 @@ void TopBar::performDelete() {
if (items.empty()) { if (items.empty()) {
_cancelSelectionClicks.fire({}); _cancelSelectionClicks.fire({});
} else { } else {
Ui::show(Box<DeleteMessagesBox>(items)); Ui::show(Box<DeleteMessagesBox>(std::move(items)));
} }
} }

View File

@ -97,12 +97,11 @@ private:
bool searchMode() const; bool searchMode() const;
Ui::StringWithNumbers generateSelectedText() const; Ui::StringWithNumbers generateSelectedText() const;
[[nodiscard]] bool computeCanDelete() const; [[nodiscard]] bool computeCanDelete() const;
[[nodiscard]] SelectedItemSet collectSelectedItems() const;
void updateSelectionState(); void updateSelectionState();
void createSelectionControls(); void createSelectionControls();
void clearSelectionControls(); void clearSelectionControls();
SelectedItemSet collectItems() const; MessageIdsList collectItems() const;
void performForward(); void performForward();
void performDelete(); void performDelete();

View File

@ -673,17 +673,13 @@ auto ListWidget::collectSelectedItems() const -> SelectedItems {
return items; return items;
} }
SelectedItemSet ListWidget::collectSelectedSet() const { MessageIdsList ListWidget::collectSelectedIds() const {
auto items = SelectedItemSet(); const auto selected = collectSelectedItems();
if (hasSelectedItems()) { return ranges::view::all(
for (auto &data : _selected) { selected.list
auto fullId = computeFullId(data.first); ) | ranges::view::transform([](const SelectedItem &item) {
if (auto item = App::histItemById(fullId)) { return item.msgId;
items.insert(items.size(), item); }) | ranges::to_vector;
}
}
}
return items;
} }
void ListWidget::pushSelectedItems() { void ListWidget::pushSelectedItems() {
@ -1364,29 +1360,29 @@ void ListWidget::contextMenuEvent(QContextMenuEvent *e) {
} }
void ListWidget::forwardSelected() { void ListWidget::forwardSelected() {
forwardItems(collectSelectedSet()); forwardItems(collectSelectedIds());
} }
void ListWidget::forwardItem(UniversalMsgId universalId) { void ListWidget::forwardItem(UniversalMsgId universalId) {
if (auto item = App::histItemById(computeFullId(universalId))) { if (const auto item = App::histItemById(computeFullId(universalId))) {
auto items = SelectedItemSet(); forwardItems({ 1, item->fullId() });
items.insert(0, item);
forwardItems(std::move(items));
} }
} }
void ListWidget::forwardItems(SelectedItemSet items) { void ListWidget::forwardItems(MessageIdsList &&items) {
if (items.empty()) { if (items.empty()) {
return; return;
} }
auto weak = make_weak(this); auto weak = make_weak(this);
auto callback = [weak, items = std::move(items)](
not_null<PeerData*> peer) mutable {
App::main()->setForwardDraft(peer->id, std::move(items));
if (weak) {
weak->clearSelected();
}
};
auto controller = std::make_unique<ChooseRecipientBoxController>( auto controller = std::make_unique<ChooseRecipientBoxController>(
[weak, items = std::move(items)](not_null<PeerData*> peer) { std::move(callback));
App::main()->setForwardDraft(peer->id, items);
if (weak) {
weak->clearSelected();
}
});
Ui::show(Box<PeerListBox>( Ui::show(Box<PeerListBox>(
std::move(controller), std::move(controller),
[](not_null<PeerListBox*> box) { [](not_null<PeerListBox*> box) {
@ -1397,20 +1393,18 @@ void ListWidget::forwardItems(SelectedItemSet items) {
} }
void ListWidget::deleteSelected() { void ListWidget::deleteSelected() {
deleteItems(collectSelectedSet()); deleteItems(collectSelectedIds());
} }
void ListWidget::deleteItem(UniversalMsgId universalId) { void ListWidget::deleteItem(UniversalMsgId universalId) {
if (auto item = App::histItemById(computeFullId(universalId))) { if (const auto item = App::histItemById(computeFullId(universalId))) {
auto items = SelectedItemSet(); deleteItems({ 1, item->fullId() });
items.insert(0, item);
deleteItems(std::move(items));
} }
} }
void ListWidget::deleteItems(SelectedItemSet items) { void ListWidget::deleteItems(MessageIdsList &&items) {
if (!items.empty()) { if (!items.empty()) {
Ui::show(Box<DeleteMessagesBox>(items)); Ui::show(Box<DeleteMessagesBox>(std::move(items)));
} }
} }

View File

@ -174,7 +174,7 @@ private:
Type type); Type type);
SelectedItems collectSelectedItems() const; SelectedItems collectSelectedItems() const;
SelectedItemSet collectSelectedSet() const; MessageIdsList collectSelectedIds() const;
void pushSelectedItems(); void pushSelectedItems();
FullMsgId computeFullId(UniversalMsgId universalId) const; FullMsgId computeFullId(UniversalMsgId universalId) const;
bool hasSelected() const; bool hasSelected() const;
@ -187,10 +187,10 @@ private:
void clearSelected(); void clearSelected();
void forwardSelected(); void forwardSelected();
void forwardItem(UniversalMsgId universalId); void forwardItem(UniversalMsgId universalId);
void forwardItems(SelectedItemSet items); void forwardItems(MessageIdsList &&items);
void deleteSelected(); void deleteSelected();
void deleteItem(UniversalMsgId universalId); void deleteItem(UniversalMsgId universalId);
void deleteItems(SelectedItemSet items); void deleteItems(MessageIdsList &&items);
void applyItemSelection( void applyItemSelection(
UniversalMsgId universalId, UniversalMsgId universalId,
TextSelection selection); TextSelection selection);

View File

@ -39,6 +39,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/dropdown_menu.h" #include "ui/widgets/dropdown_menu.h"
#include "ui/focus_persister.h" #include "ui/focus_persister.h"
#include "ui/resize_area.h" #include "ui/resize_area.h"
#include "ui/toast/toast.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h" #include "chat_helpers/stickers.h"
#include "info/info_memento.h" #include "info/info_memento.h"
@ -616,10 +617,10 @@ void MainWidget::finishFloatPlayerDrag(not_null<Float*> instance, bool closed) {
} }
bool MainWidget::setForwardDraft(PeerId peerId, ForwardWhatMessages what) { bool MainWidget::setForwardDraft(PeerId peerId, ForwardWhatMessages what) {
auto toForward = SelectedItemSet(); const auto collect = [&]() -> MessageIdsList {
if (what == ForwardSelectedMessages) { if (what == ForwardSelectedMessages) {
toForward = _history->getSelectedItems(); return _history->getSelectedItems();
} else { }
auto item = (HistoryItem*)nullptr; auto item = (HistoryItem*)nullptr;
if (what == ForwardContextMessage) { if (what == ForwardContextMessage) {
item = App::contextItem(); item = App::contextItem();
@ -629,10 +630,11 @@ bool MainWidget::setForwardDraft(PeerId peerId, ForwardWhatMessages what) {
item = App::pressedLinkItem(); item = App::pressedLinkItem();
} }
if (item && item->toHistoryMessage() && item->id > 0) { if (item && item->toHistoryMessage() && item->id > 0) {
toForward.insert(item->id, item); return { 1, item->fullId() };
} }
} return {};
auto result = setForwardDraft(peerId, toForward); };
const auto result = setForwardDraft(peerId, collect());
if (!result) { if (!result) {
if (what == ForwardPressedMessage || what == ForwardPressedLinkMessage) { if (what == ForwardPressedMessage || what == ForwardPressedLinkMessage) {
// We've already released the mouse button, so the forwarding is cancelled. // We've already released the mouse button, so the forwarding is cancelled.
@ -645,16 +647,18 @@ bool MainWidget::setForwardDraft(PeerId peerId, ForwardWhatMessages what) {
return result; return result;
} }
bool MainWidget::setForwardDraft(PeerId peerId, const SelectedItemSet &items) { bool MainWidget::setForwardDraft(PeerId peerId, MessageIdsList &&items) {
Expects(peerId != 0); Expects(peerId != 0);
auto peer = App::peer(peerId); const auto peer = App::peer(peerId);
auto error = GetErrorTextForForward(peer, items); const auto error = GetErrorTextForForward(
peer,
Auth().data().idsToItems(items));
if (!error.isEmpty()) { if (!error.isEmpty()) {
Ui::show(Box<InformBox>(error), LayerOption::KeepOther); Ui::show(Box<InformBox>(error), LayerOption::KeepOther);
return false; return false;
} }
App::history(peer)->setForwardDraft(items); App::history(peer)->setForwardDraft(std::move(items));
if (_history->peer() == peer) { if (_history->peer() == peer) {
_history->cancelReply(); _history->cancelReply();
} }
@ -713,16 +717,16 @@ bool MainWidget::onInlineSwitchChosen(const PeerId &peer, const QString &botAndQ
} }
void MainWidget::cancelForwarding(History *history) { void MainWidget::cancelForwarding(History *history) {
history->setForwardDraft(SelectedItemSet()); history->setForwardDraft({});
_history->updateForwarding(); _history->updateForwarding();
} }
void MainWidget::finishForwarding(History *history, bool silent) { void MainWidget::finishForwarding(History *history, bool silent) {
if (!history) return; if (!history) return;
auto toForward = history->validateForwardDraft(); const auto toForward = history->validateForwardDraft();
if (!toForward.isEmpty()) { if (const auto count = int(toForward.size())) {
auto genClientSideMessage = (toForward.size() < 2); auto genClientSideMessage = (count < 2);
PeerData *forwardFrom = 0; PeerData *forwardFrom = 0;
App::main()->readServerHistory(history); App::main()->readServerHistory(history);
@ -745,12 +749,12 @@ void MainWidget::finishForwarding(History *history, bool silent) {
QVector<MTPint> ids; QVector<MTPint> ids;
QVector<MTPlong> randomIds; QVector<MTPlong> randomIds;
ids.reserve(toForward.size()); ids.reserve(count);
randomIds.reserve(toForward.size()); randomIds.reserve(count);
for (auto i = toForward.cbegin(), e = toForward.cend(); i != e; ++i) { for (const auto item : toForward) {
auto randomId = rand_value<uint64>(); auto randomId = rand_value<uint64>();
if (genClientSideMessage) { if (genClientSideMessage) {
if (auto message = i.value()->toHistoryMessage()) { if (auto message = item->toHistoryMessage()) {
auto newId = FullMsgId(peerToChannel(history->peer->id), clientMsgId()); auto newId = FullMsgId(peerToChannel(history->peer->id), clientMsgId());
auto messageFromId = channelPost ? 0 : Auth().userId(); auto messageFromId = channelPost ? 0 : Auth().userId();
auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString(); auto messagePostAuthor = channelPost ? (Auth().user()->firstName + ' ' + Auth().user()->lastName) : QString();
@ -758,15 +762,15 @@ void MainWidget::finishForwarding(History *history, bool silent) {
App::historyRegRandom(randomId, newId); App::historyRegRandom(randomId, newId);
} }
} }
if (forwardFrom != i.value()->history()->peer) { if (forwardFrom != item->history()->peer) {
if (forwardFrom) { if (forwardFrom) {
history->sendRequestId = MTP::send(MTPmessages_ForwardMessages(MTP_flags(sendFlags), forwardFrom->input, MTP_vector<MTPint>(ids), MTP_vector<MTPlong>(randomIds), history->peer->input), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, history->sendRequestId); history->sendRequestId = MTP::send(MTPmessages_ForwardMessages(MTP_flags(sendFlags), forwardFrom->input, MTP_vector<MTPint>(ids), MTP_vector<MTPlong>(randomIds), history->peer->input), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, history->sendRequestId);
ids.resize(0); ids.resize(0);
randomIds.resize(0); randomIds.resize(0);
} }
forwardFrom = i.value()->history()->peer; forwardFrom = item->history()->peer;
} }
ids.push_back(MTP_int(i.value()->id)); ids.push_back(MTP_int(item->id));
randomIds.push_back(MTP_long(randomId)); randomIds.push_back(MTP_long(randomId));
} }
history->sendRequestId = MTP::send(MTPmessages_ForwardMessages(MTP_flags(sendFlags), forwardFrom->input, MTP_vector<MTPint>(ids), MTP_vector<MTPlong>(randomIds), history->peer->input), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, history->sendRequestId); history->sendRequestId = MTP::send(MTPmessages_ForwardMessages(MTP_flags(sendFlags), forwardFrom->input, MTP_vector<MTPint>(ids), MTP_vector<MTPlong>(randomIds), history->peer->input), rpcDone(&MainWidget::sentUpdatesReceived), RPCFailHandlerPtr(), 0, 0, history->sendRequestId);
@ -1005,37 +1009,22 @@ void MainWidget::hiderLayer(object_ptr<HistoryHider> h) {
checkFloatPlayerVisibility(); checkFloatPlayerVisibility();
} }
void MainWidget::showForwardLayer(const SelectedItemSet &items) { void MainWidget::showForwardLayer(MessageIdsList &&items) {
hiderLayer(object_ptr<HistoryHider>(this, items)); hiderLayer(object_ptr<HistoryHider>(this, std::move(items)));
} }
void MainWidget::showSendPathsLayer() { void MainWidget::showSendPathsLayer() {
hiderLayer(object_ptr<HistoryHider>(this)); hiderLayer(object_ptr<HistoryHider>(this));
} }
void MainWidget::showForwardBox(SelectedItemSet &&items) {
auto controller = std::make_unique<ChooseRecipientBoxController>(
[items = std::move(items)](not_null<PeerData*> peer) {
App::main()->setForwardDraft(peer->id, items);
});
Ui::show(Box<PeerListBox>(
std::move(controller),
[](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_cancel), [box] {
box->closeBox();
});
}));
}
void MainWidget::deleteLayer(int selectedCount) { void MainWidget::deleteLayer(int selectedCount) {
if (selectedCount) { if (selectedCount) {
auto forDelete = true;
auto selected = _history->getSelectedItems(); auto selected = _history->getSelectedItems();
if (!selected.isEmpty()) { if (!selected.empty()) {
Ui::show(Box<DeleteMessagesBox>(selected)); Ui::show(Box<DeleteMessagesBox>(std::move(selected)));
} }
} else if (auto item = App::contextItem()) { } else if (const auto item = App::contextItem()) {
auto suggestModerateActions = true; const auto suggestModerateActions = true;
Ui::show(Box<DeleteMessagesBox>(item, suggestModerateActions)); Ui::show(Box<DeleteMessagesBox>(item, suggestModerateActions));
} }
} }
@ -1335,7 +1324,10 @@ bool MainWidget::addParticipantsFail(
} }
void MainWidget::kickParticipant(ChatData *chat, UserData *user) { void MainWidget::kickParticipant(ChatData *chat, UserData *user) {
MTP::send(MTPmessages_DeleteChatUser(chat->inputChat, user->inputUser), rpcDone(&MainWidget::sentUpdatesReceived), rpcFail(&MainWidget::kickParticipantFail, chat)); MTP::send(
MTPmessages_DeleteChatUser(chat->inputChat, user->inputUser),
rpcDone(&MainWidget::sentUpdatesReceived),
rpcFail(&MainWidget::kickParticipantFail, chat));
Ui::showPeerHistory(chat->id, ShowAtTheEndMsgId); Ui::showPeerHistory(chat->id, ShowAtTheEndMsgId);
} }

View File

@ -178,9 +178,8 @@ public:
int32 dlgsWidth() const; int32 dlgsWidth() const;
void showForwardLayer(const SelectedItemSet &items); void showForwardLayer(MessageIdsList &&items);
void showSendPathsLayer(); void showSendPathsLayer();
void showForwardBox(SelectedItemSet &&items);
void deleteLayer(int selectedCount = 0); // 0 - context item void deleteLayer(int selectedCount = 0); // 0 - context item
void cancelUploadLayer(); void cancelUploadLayer();
void shareContactLayer(UserData *contact); void shareContactLayer(UserData *contact);
@ -189,7 +188,7 @@ public:
void hiderLayer(object_ptr<HistoryHider> h); void hiderLayer(object_ptr<HistoryHider> h);
void noHider(HistoryHider *destroyed); void noHider(HistoryHider *destroyed);
bool setForwardDraft(PeerId peer, ForwardWhatMessages what); bool setForwardDraft(PeerId peer, ForwardWhatMessages what);
bool setForwardDraft(PeerId peer, const SelectedItemSet &items); bool setForwardDraft(PeerId peer, MessageIdsList &&items);
bool shareUrl( bool shareUrl(
not_null<PeerData*> peer, not_null<PeerData*> peer,
const QString &url, const QString &url,

View File

@ -35,6 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_message.h" #include "history/history_message.h"
#include "history/history_media_types.h" #include "history/history_media_types.h"
#include "window/themes/window_theme_preview.h" #include "window/themes/window_theme_preview.h"
#include "window/window_peer_menu.h"
#include "base/task_queue.h" #include "base/task_queue.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "auth_session.h" #include "auth_session.h"
@ -936,11 +937,7 @@ void MediaView::onForward() {
} }
close(); close();
if (auto main = App::main()) { Window::ShowForwardMessagesBox({ 1, item->fullId() });
auto items = SelectedItemSet();
items.insert(item->id, item);
main->showForwardBox(std::move(items));
}
} }
void MediaView::onDelete() { void MediaView::onDelete() {

View File

@ -28,6 +28,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/peers/manage_peer_box.h" #include "boxes/peers/manage_peer_box.h"
#include "boxes/peers/edit_peer_info_box.h" #include "boxes/peers/edit_peer_info_box.h"
#include "ui/toast/toast.h"
#include "core/tl_help.h" #include "core/tl_help.h"
#include "auth_session.h" #include "auth_session.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -492,6 +493,37 @@ void PeerMenuShareContactBox(not_null<UserData*> user) {
})); }));
} }
void ShowForwardMessagesBox(
MessageIdsList &&items,
base::lambda_once<void()> &&successCallback) {
auto weak = std::make_shared<QPointer<PeerListBox>>();
auto callback = [
ids = std::move(items),
callback = std::move(successCallback),
weak
](not_null<PeerData*> peer) mutable {
if (peer->isSelf()) {
Ui::Toast::Show(lang(lng_share_done));
} else {
App::main()->setForwardDraft(peer->id, std::move(ids));
}
if (const auto strong = *weak) {
strong->closeBox();
}
if (callback) {
callback();
}
};
auto initBox = [](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_cancel), [box] {
box->closeBox();
});
};
*weak = Ui::show(Box<PeerListBox>(
std::make_unique<ChooseRecipientBoxController>(std::move(callback)),
std::move(initBox)), LayerOption::KeepOther);
}
void PeerMenuAddChannelMembers(not_null<ChannelData*> channel) { void PeerMenuAddChannelMembers(not_null<ChannelData*> channel) {
if (channel->isMegagroup()) { if (channel->isMegagroup()) {
auto &participants = channel->mgInfo->lastParticipants; auto &participants = channel->mgInfo->lastParticipants;

View File

@ -45,4 +45,8 @@ void PeerMenuShareContactBox(not_null<UserData*> user);
void PeerMenuAddContact(not_null<UserData*> user); void PeerMenuAddContact(not_null<UserData*> user);
void PeerMenuAddChannelMembers(not_null<ChannelData*> channel); void PeerMenuAddChannelMembers(not_null<ChannelData*> channel);
void ShowForwardMessagesBox(
MessageIdsList &&items,
base::lambda_once<void()> &&successCallback = nullptr);
} // namespace Window } // namespace Window