mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-13 04:37:11 +02:00
Support tags search in sublists.
This commit is contained in:
parent
0163938e00
commit
30548c2859
9 changed files with 195 additions and 68 deletions
|
@ -1930,7 +1930,9 @@ void Widget::searchMessages(QString query, Key inChat) {
|
|||
|
||||
auto tags = Data::SearchTagsFromQuery(query);
|
||||
if (!tags.empty()) {
|
||||
inChat = session().data().history(session().user());
|
||||
if (!inChat.sublist()) {
|
||||
inChat = session().data().history(session().user());
|
||||
}
|
||||
query = QString();
|
||||
}
|
||||
const auto inChatChanged = [&] {
|
||||
|
|
|
@ -4797,18 +4797,31 @@ void HistoryWidget::searchInChat() {
|
|||
}
|
||||
}
|
||||
|
||||
void HistoryWidget::searchInChatEmbedded(std::optional<QString> query) {
|
||||
if (!_history) {
|
||||
return;
|
||||
} else if (_composeSearch) {
|
||||
if (query) {
|
||||
_composeSearch->setQuery(*query);
|
||||
bool HistoryWidget::searchInChatEmbedded(Dialogs::Key chat, QString query) {
|
||||
const auto peer = chat.peer();
|
||||
if (!peer || peer != controller()->singlePeer()) {
|
||||
return false;
|
||||
} else if (_peer != peer) {
|
||||
const auto weak = Ui::MakeWeak(this);
|
||||
controller()->showPeerHistory(peer);
|
||||
if (!weak) {
|
||||
return false;
|
||||
}
|
||||
_composeSearch->setInnerFocus();
|
||||
return;
|
||||
}
|
||||
if (_peer != peer) {
|
||||
return false;
|
||||
} else if (_composeSearch) {
|
||||
_composeSearch->setQuery(query);
|
||||
_composeSearch->setInnerFocus();
|
||||
return true;
|
||||
}
|
||||
switchToSearch(query);
|
||||
return true;
|
||||
}
|
||||
|
||||
void HistoryWidget::switchToSearch(QString query) {
|
||||
const auto search = crl::guard(_list, [=] {
|
||||
if (!_history) {
|
||||
if (!_peer) {
|
||||
return;
|
||||
}
|
||||
const auto update = [=] {
|
||||
|
@ -4824,18 +4837,27 @@ void HistoryWidget::searchInChatEmbedded(std::optional<QString> query) {
|
|||
controller(),
|
||||
_history,
|
||||
from,
|
||||
query.value_or(QString()));
|
||||
query);
|
||||
|
||||
update();
|
||||
setInnerFocus();
|
||||
|
||||
_composeSearch->activations(
|
||||
) | rpl::start_with_next([=](not_null<HistoryItem*> item) {
|
||||
controller()->showPeerHistory(
|
||||
item->history()->peer->id,
|
||||
::Window::SectionShow::Way::ClearStack,
|
||||
item->fullId().msg);
|
||||
}, _composeSearch->lifetime());
|
||||
|
||||
_composeSearch->destroyRequests(
|
||||
) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=] {
|
||||
_composeSearch = nullptr;
|
||||
|
||||
update();
|
||||
setInnerFocus();
|
||||
update();
|
||||
setInnerFocus();
|
||||
}, _composeSearch->lifetime());
|
||||
});
|
||||
if (!preventsClose(search)) {
|
||||
|
|
|
@ -251,7 +251,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<> cancelRequests() const {
|
||||
return _cancelRequests.events();
|
||||
}
|
||||
void searchInChatEmbedded(std::optional<QString> query = {});
|
||||
bool searchInChatEmbedded(Dialogs::Key chat, QString query);
|
||||
|
||||
void updateNotifyControls();
|
||||
|
||||
|
@ -642,6 +642,7 @@ private:
|
|||
bool kbWasHidden() const;
|
||||
|
||||
void searchInChat();
|
||||
void switchToSearch(QString query);
|
||||
|
||||
MTP::Sender _api;
|
||||
FullReplyTo _replyTo;
|
||||
|
|
|
@ -329,6 +329,9 @@ TopBar::TopBar(
|
|||
, _window(window)
|
||||
, _history(history)
|
||||
, _searchTimer([=] { requestSearch(); }) {
|
||||
if (from) {
|
||||
setFrom(from);
|
||||
}
|
||||
refreshTags();
|
||||
|
||||
moveToLeft(0, 0);
|
||||
|
@ -367,10 +370,6 @@ TopBar::TopBar(
|
|||
_select->setCancelledCallback([=] {
|
||||
_cancelRequests.fire({});
|
||||
});
|
||||
|
||||
if (from) {
|
||||
setFrom(from);
|
||||
}
|
||||
}
|
||||
|
||||
void TopBar::keyPressEvent(QKeyEvent *e) {
|
||||
|
@ -425,14 +424,15 @@ void TopBar::refreshTags() {
|
|||
_searchTags = nullptr;
|
||||
return;
|
||||
}
|
||||
const auto from = _from.current();
|
||||
const auto reactions = &_history->owner().reactions();
|
||||
const auto sublist = from
|
||||
? _history->owner().savedMessages().sublist(from).get()
|
||||
: nullptr;
|
||||
auto fullTagsList = _from.value() | rpl::map([=](PeerData *from) {
|
||||
const auto sublist = from
|
||||
? _history->owner().savedMessages().sublist(from).get()
|
||||
: nullptr;
|
||||
return _history->owner().reactions().myTagsValue(sublist);
|
||||
}) | rpl::flatten_latest();
|
||||
_searchTags = std::make_unique<Dialogs::SearchTags>(
|
||||
&_history->owner(),
|
||||
reactions->myTagsValue(sublist),
|
||||
std::move(fullTagsList),
|
||||
_searchTagsSelected);
|
||||
|
||||
const auto parent = _searchTags->lifetime().make_state<Ui::RpWidget>(
|
||||
|
@ -822,6 +822,7 @@ public:
|
|||
void setInnerFocus();
|
||||
void setQuery(const QString &query);
|
||||
|
||||
[[nodiscard]] rpl::producer<not_null<HistoryItem*>> activations() const;
|
||||
[[nodiscard]] rpl::producer<> destroyRequests() const;
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
|
@ -845,6 +846,7 @@ private:
|
|||
rpl::event_stream<BottomBar::Index> jumps;
|
||||
} _pendingJump;
|
||||
|
||||
rpl::event_stream<not_null<HistoryItem*>> _activations;
|
||||
rpl::event_stream<> _destroyRequests;
|
||||
|
||||
};
|
||||
|
@ -881,8 +883,10 @@ ComposeSearch::Inner::Inner(
|
|||
|
||||
_topBar->searchRequests(
|
||||
) | rpl::start_with_next([=](const SearchRequest &search) {
|
||||
if (search.query.isEmpty() && !search.from && search.tags.empty()) {
|
||||
return;
|
||||
if (search.query.isEmpty() && search.tags.empty()) {
|
||||
if (!search.from || _history->peer->isSelf()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_apiSearch.clear();
|
||||
_apiSearch.search(search);
|
||||
|
@ -910,8 +914,12 @@ ComposeSearch::Inner::Inner(
|
|||
_apiSearch.newFounds(
|
||||
) | rpl::start_with_next([=] {
|
||||
const auto &apiData = _apiSearch.messages();
|
||||
const auto weak = Ui::MakeWeak(_bottomBar.get());
|
||||
_bottomBar->setTotal(apiData.total);
|
||||
_list.controller->addItems(apiData.messages, true);
|
||||
if (weak) {
|
||||
// Activating the first search result may switch the chat.
|
||||
_list.controller->addItems(apiData.messages, true);
|
||||
}
|
||||
}, _topBar->lifetime());
|
||||
|
||||
_apiSearch.nextFounds(
|
||||
|
@ -922,16 +930,6 @@ ComposeSearch::Inner::Inner(
|
|||
_list.controller->addItems(_apiSearch.messages().messages, false);
|
||||
}, _topBar->lifetime());
|
||||
|
||||
const auto goToMessage = [=](const FullMsgId &itemId) {
|
||||
const auto item = _history->owner().message(itemId);
|
||||
if (item) {
|
||||
_window->showPeerHistory(
|
||||
item->history()->peer->id,
|
||||
::Window::SectionShow::Way::ClearStack,
|
||||
item->fullId().msg);
|
||||
}
|
||||
};
|
||||
|
||||
rpl::merge(
|
||||
_pendingJump.jumps.events() | rpl::filter(rpl::mappers::_1 >= 0),
|
||||
_bottomBar->showItemRequests()
|
||||
|
@ -947,8 +945,14 @@ ComposeSearch::Inner::Inner(
|
|||
return;
|
||||
}
|
||||
_pendingJump.data = {};
|
||||
goToMessage(messages[index]);
|
||||
hideList();
|
||||
const auto item = _history->owner().message(messages[index]);
|
||||
if (item) {
|
||||
const auto weak = Ui::MakeWeak(_topBar.get());
|
||||
_activations.fire_copy(item);
|
||||
if (weak) {
|
||||
hideList();
|
||||
}
|
||||
}
|
||||
}, _bottomBar->lifetime());
|
||||
|
||||
_list.controller->showItemRequests(
|
||||
|
@ -1039,6 +1043,11 @@ void ComposeSearch::Inner::hideList() {
|
|||
}
|
||||
}
|
||||
|
||||
auto ComposeSearch::Inner::activations() const
|
||||
-> rpl::producer<not_null<HistoryItem*>> {
|
||||
return _activations.events();
|
||||
}
|
||||
|
||||
rpl::producer<> ComposeSearch::Inner::destroyRequests() const {
|
||||
return _destroyRequests.events();
|
||||
}
|
||||
|
@ -1074,6 +1083,10 @@ void ComposeSearch::setQuery(const QString &query) {
|
|||
_inner->setQuery(query);
|
||||
}
|
||||
|
||||
rpl::producer<not_null<HistoryItem*>> ComposeSearch::activations() const {
|
||||
return _inner->activations();
|
||||
}
|
||||
|
||||
rpl::producer<> ComposeSearch::destroyRequests() const {
|
||||
return _inner->destroyRequests();
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
void setInnerFocus();
|
||||
void setQuery(const QString &query);
|
||||
|
||||
[[nodiscard]] rpl::producer<not_null<HistoryItem*>> activations() const;
|
||||
[[nodiscard]] rpl::producer<> destroyRequests() const;
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_user.h"
|
||||
#include "history/view/controls/history_view_compose_search.h"
|
||||
#include "history/view/history_view_top_bar_widget.h"
|
||||
#include "history/view/history_view_translate_bar.h"
|
||||
#include "history/view/history_view_list_widget.h"
|
||||
|
@ -221,7 +222,7 @@ Data::Thread *SublistWidget::cornerButtonsThread() {
|
|||
}
|
||||
|
||||
FullMsgId SublistWidget::cornerButtonsCurrentId() {
|
||||
return {};
|
||||
return _lastShownAt;
|
||||
}
|
||||
|
||||
bool SublistWidget::cornerButtonsIgnoreVisibility() {
|
||||
|
@ -249,12 +250,20 @@ bool SublistWidget::cornerButtonsHas(CornerButtonType type) {
|
|||
void SublistWidget::showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
FullMsgId originId) {
|
||||
_inner->showAtPosition(
|
||||
position,
|
||||
{},
|
||||
_cornerButtons.doneJumpFrom(position.fullId, originId));
|
||||
showAtPosition(position, originId, {});
|
||||
}
|
||||
|
||||
void SublistWidget::showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
FullMsgId originItemId,
|
||||
const Window::SectionShow ¶ms) {
|
||||
_lastShownAt = position.fullId;
|
||||
controller()->setActiveChatEntry(activeChat());
|
||||
_inner->showAtPosition(
|
||||
position,
|
||||
params,
|
||||
_cornerButtons.doneJumpFrom(position.fullId, originItemId));
|
||||
}
|
||||
void SublistWidget::updateAdaptiveLayout() {
|
||||
_topBarShadow->moveToLeft(
|
||||
controller()->adaptive().isOneColumn() ? 0 : st::lineWidth,
|
||||
|
@ -266,13 +275,14 @@ not_null<Data::SavedSublist*> SublistWidget::sublist() const {
|
|||
}
|
||||
|
||||
Dialogs::RowDescriptor SublistWidget::activeChat() const {
|
||||
return {
|
||||
_sublist,
|
||||
FullMsgId(_history->peer->id, ShowAtUnreadMsgId)
|
||||
};
|
||||
const auto messageId = _lastShownAt
|
||||
? _lastShownAt
|
||||
: FullMsgId(_history->peer->id, ShowAtUnreadMsgId);
|
||||
return { _sublist, messageId };
|
||||
}
|
||||
|
||||
QPixmap SublistWidget::grabForShowAnimation(const Window::SectionSlideParams ¶ms) {
|
||||
QPixmap SublistWidget::grabForShowAnimation(
|
||||
const Window::SectionSlideParams ¶ms) {
|
||||
_topBar->updateControlsVisibility();
|
||||
if (params.withTopBarShadow) _topBarShadow->hide();
|
||||
auto result = Ui::GrabWidget(this);
|
||||
|
@ -286,7 +296,11 @@ void SublistWidget::checkActivation() {
|
|||
}
|
||||
|
||||
void SublistWidget::doSetInnerFocus() {
|
||||
_inner->setFocus();
|
||||
if (_composeSearch) {
|
||||
_composeSearch->setInnerFocus();
|
||||
} else {
|
||||
_inner->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
bool SublistWidget::showInternal(
|
||||
|
@ -313,6 +327,46 @@ void SublistWidget::setInternalState(
|
|||
restoreState(memento);
|
||||
}
|
||||
|
||||
bool SublistWidget::searchInChatEmbedded(Dialogs::Key chat, QString query) {
|
||||
const auto sublist = chat.sublist();
|
||||
if (!sublist || sublist != _sublist) {
|
||||
return false;
|
||||
} else if (_composeSearch) {
|
||||
_composeSearch->setQuery(query);
|
||||
_composeSearch->setInnerFocus();
|
||||
return true;
|
||||
}
|
||||
_composeSearch = std::make_unique<HistoryView::ComposeSearch>(
|
||||
this,
|
||||
controller(),
|
||||
_history,
|
||||
sublist->peer(),
|
||||
query);
|
||||
|
||||
updateControlsGeometry();
|
||||
setInnerFocus();
|
||||
|
||||
_composeSearch->activations(
|
||||
) | rpl::start_with_next([=](not_null<HistoryItem*> item) {
|
||||
controller()->showPeerHistory(
|
||||
item->history()->peer->id,
|
||||
::Window::SectionShow::Way::ClearStack,
|
||||
item->fullId().msg);
|
||||
}, _composeSearch->lifetime());
|
||||
|
||||
_composeSearch->destroyRequests(
|
||||
) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=] {
|
||||
_composeSearch = nullptr;
|
||||
|
||||
updateControlsGeometry();
|
||||
setInnerFocus();
|
||||
}, _composeSearch->lifetime());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<Window::SectionMemento> SublistWidget::createMemento() {
|
||||
auto result = std::make_shared<SublistMemento>(sublist());
|
||||
saveState(result.get());
|
||||
|
@ -323,7 +377,30 @@ bool SublistWidget::showMessage(
|
|||
PeerId peerId,
|
||||
const Window::SectionShow ¶ms,
|
||||
MsgId messageId) {
|
||||
return false; // We want 'Go to original' to work.
|
||||
const auto id = FullMsgId(_history->peer->id, messageId);
|
||||
const auto message = _history->owner().message(id);
|
||||
if (!message || message->savedSublist() != _sublist) {
|
||||
return false;
|
||||
}
|
||||
const auto originMessage = [&]() -> HistoryItem* {
|
||||
using OriginMessage = Window::SectionShow::OriginMessage;
|
||||
if (const auto origin = std::get_if<OriginMessage>(¶ms.origin)) {
|
||||
if (const auto returnTo = session().data().message(origin->id)) {
|
||||
if (returnTo->savedSublist() == _sublist) {
|
||||
return returnTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}();
|
||||
const auto currentReplyReturn = _cornerButtons.replyReturn();
|
||||
const auto originItemId = !originMessage
|
||||
? FullMsgId()
|
||||
: (currentReplyReturn != originMessage)
|
||||
? originMessage->fullId()
|
||||
: FullMsgId();
|
||||
showAtPosition(message->position(), originItemId, params);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SublistWidget::saveState(not_null<SublistMemento*> memento) {
|
||||
|
@ -555,6 +632,9 @@ void SublistWidget::listSelectionChanged(SelectedItems &&items) {
|
|||
}
|
||||
}
|
||||
_topBar->showSelected(state);
|
||||
if ((state.count > 0) && _composeSearch) {
|
||||
_composeSearch->hideAnimated();
|
||||
}
|
||||
}
|
||||
|
||||
void SublistWidget::listMarkReadTill(not_null<HistoryItem*> item) {
|
||||
|
|
|
@ -33,6 +33,7 @@ class Element;
|
|||
class TopBarWidget;
|
||||
class SublistMemento;
|
||||
class TranslateBar;
|
||||
class ComposeSearch;
|
||||
|
||||
class SublistWidget final
|
||||
: public Window::SectionWidget
|
||||
|
@ -75,6 +76,8 @@ public:
|
|||
return Window::SectionActionResult::Fallback;
|
||||
}
|
||||
|
||||
bool searchInChatEmbedded(Dialogs::Key chat, QString query) override;
|
||||
|
||||
// Float player interface.
|
||||
bool floatPlayerHandleWheelEvent(QEvent *e) override;
|
||||
QRect floatPlayerAvailableRect() override;
|
||||
|
@ -163,6 +166,10 @@ private:
|
|||
void showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
FullMsgId originId = {});
|
||||
void showAtPosition(
|
||||
Data::MessagePosition position,
|
||||
FullMsgId originItemId,
|
||||
const Window::SectionShow ¶ms);
|
||||
|
||||
void setupOpenChatButton();
|
||||
void setupAboutHiddenAuthor();
|
||||
|
@ -189,7 +196,9 @@ private:
|
|||
std::unique_ptr<Ui::ScrollArea> _scroll;
|
||||
std::unique_ptr<Ui::FlatButton> _openChatButton;
|
||||
std::unique_ptr<Ui::RpWidget> _aboutHiddenAuthor;
|
||||
std::unique_ptr<ComposeSearch> _composeSearch;
|
||||
|
||||
FullMsgId _lastShownAt;
|
||||
CornerButtons _cornerButtons;
|
||||
|
||||
};
|
||||
|
|
|
@ -49,6 +49,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item_helpers.h" // GetErrorTextForSending.
|
||||
#include "history/view/media/history_view_media.h"
|
||||
#include "history/view/history_view_service_message.h"
|
||||
#include "history/view/history_view_sublist_section.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "lang/lang_cloud_manager.h"
|
||||
#include "inline_bots/inline_bot_layout_item.h"
|
||||
|
@ -727,28 +728,23 @@ void MainWidget::searchMessages(const QString &query, Dialogs::Key inChat) {
|
|||
_dialogs->setInnerFocus();
|
||||
}
|
||||
} else {
|
||||
if (!Data::SearchTagsFromQuery(query).empty()) {
|
||||
if (const auto sublist = inChat.sublist()) {
|
||||
controller()->showSection(
|
||||
std::make_shared<HistoryView::SublistMemento>(sublist));
|
||||
} else if (!Data::SearchTagsFromQuery(query).empty()) {
|
||||
inChat = controller()->session().data().history(
|
||||
controller()->session().user());
|
||||
}
|
||||
const auto searchIn = [&](not_null<Window::Controller*> window) {
|
||||
if (const auto controller = window->sessionController()) {
|
||||
controller->content()->searchMessages(query, inChat);
|
||||
controller->widget()->activate();
|
||||
}
|
||||
};
|
||||
const auto account = &session().account();
|
||||
if (const auto peer = inChat.peer()) {
|
||||
if (peer == controller()->singlePeer()) {
|
||||
if (_history->peer() != peer) {
|
||||
controller()->showPeerHistory(peer);
|
||||
if ((!_mainSection
|
||||
|| !_mainSection->searchInChatEmbedded(inChat, query))
|
||||
&& !_history->searchInChatEmbedded(inChat, query)) {
|
||||
const auto account = &session().account();
|
||||
if (const auto window = Core::App().windowFor(account)) {
|
||||
if (const auto controller = window->sessionController()) {
|
||||
controller->content()->searchMessages(query, inChat);
|
||||
controller->widget()->activate();
|
||||
}
|
||||
_history->searchInChatEmbedded(query);
|
||||
} else if (const auto window = Core::App().windowFor(peer)) {
|
||||
searchIn(window);
|
||||
}
|
||||
} else if (const auto window = Core::App().windowFor(account)) {
|
||||
searchIn(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,6 +148,9 @@ public:
|
|||
MsgId messageId) {
|
||||
return false;
|
||||
}
|
||||
virtual bool searchInChatEmbedded(Dialogs::Key chat, QString query) {
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual bool preventsClose(
|
||||
Fn<void()> &&continueCallback) const {
|
||||
|
|
Loading…
Add table
Reference in a new issue