From f4ecfeaddd96963f5c05a15f1a31269c1de750ca Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 15 Mar 2024 19:07:22 +0300 Subject: [PATCH] Added ability to perform bulk selection from menu in HistoryWidget. --- Telegram/Resources/langs/lang.strings | 1 + .../history/history_inner_widget.cpp | 81 +++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 39907f573..190958942 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -3013,6 +3013,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_context_delete_msg" = "Delete Message"; "lng_context_auto_delete_in" = "auto-delete in {duration}"; "lng_context_select_msg" = "Select Message"; +"lng_context_select_msg_bulk" = "Select up to this message"; "lng_context_report_msg" = "Report Message"; "lng_context_pin_msg" = "Pin Message"; "lng_context_unpin_msg" = "Unpin Message"; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index a2188d7d5..79c25f691 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2277,6 +2277,87 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { } } }, &st::menuIconSelect); + const auto collectBetween = [=]( + not_null from, + not_null to, + int max) -> HistoryItemsList { + auto current = from; + auto collected = HistoryItemsList(); + collected.reserve(max); + collected.push_back(from); + collected.push_back(to); + const auto toId = to->fullId(); + while (true) { + if (collected.size() > max) { + return {}; + } + const auto view = viewByItem(current); + const auto nextView = nextItem(view); + if (!nextView) { + return {}; + } + const auto nextItem = nextView->data(); + if (nextItem->fullId() == toId) { + return collected; + } + if (nextItem->isRegular() && !nextItem->isService()) { + collected.push_back(nextItem); + } + current = nextItem; + } + }; + + [&] { // Select up to this message. + if (selectedState.count <= 0) { + return; + } + const auto toItem = groupLeaderOrSelf(item); + auto topToBottom = false; + auto nearestItem = (HistoryItem*)(nullptr); + { + auto minDiff = std::numeric_limits::max(); + for (const auto &[item, _] : _selected) { + const auto diff = item->fullId().msg.bare + - toItem->fullId().msg.bare; + if (std::abs(diff) < minDiff) { + nearestItem = item; + minDiff = std::abs(diff); + topToBottom = (diff < 0); + } + } + } + if (!nearestItem) { + return; + } + const auto start = (topToBottom ? nearestItem : toItem); + const auto end = (topToBottom ? toItem : nearestItem); + const auto left = MaxSelectedItems + - selectedState.count + + (topToBottom ? 0 : 1); + if (collectBetween(start, end, left).empty()) { + return; + } + const auto startId = start->fullId(); + const auto endId = end->fullId(); + const auto callback = [=] { + const auto from = session->data().message(startId); + const auto to = session->data().message(endId); + if (from && to) { + for (const auto &i : collectBetween(from, to, left)) { + changeSelectionAsGroup( + &_selected, + i, + SelectAction::Select); + } + update(); + _widget->updateTopBarSelection(); + } + }; + _menu->addAction( + tr::lng_context_select_msg_bulk(tr::now), + callback, + &st::menuIconSelect); + }(); } };