Suggest global search of cashtags.

This commit is contained in:
John Preston 2024-06-27 16:55:19 +04:00
parent 631d6abb06
commit 09e6077e97
6 changed files with 52 additions and 28 deletions

View file

@ -2655,7 +2655,7 @@ void InnerWidget::applySearchState(SearchState state) {
onHashtagFilterUpdate(QStringView()); onHashtagFilterUpdate(QStringView());
} }
_searchState = std::move(state); _searchState = std::move(state);
_searchingHashtag = IsHashtagSearchQuery(_searchState.query); _searchHashOrCashtag = IsHashOrCashtagSearchQuery(_searchState.query);
updateSearchIn(); updateSearchIn();
moveSearchIn(); moveSearchIn();
@ -3332,7 +3332,8 @@ auto InnerWidget::searchTagsChanges() const
} }
void InnerWidget::updateSearchIn() { void InnerWidget::updateSearchIn() {
if (!_searchState.inChat && !_searchingHashtag) { if (!_searchState.inChat
&& _searchHashOrCashtag == HashOrCashtag::None) {
_searchIn = nullptr; _searchIn = nullptr;
return; return;
} else if (!_searchIn) { } else if (!_searchIn) {
@ -3381,7 +3382,7 @@ void InnerWidget::updateSearchIn() {
? Ui::MakeUserpicThumbnail(sublist->peer()) ? Ui::MakeUserpicThumbnail(sublist->peer())
: nullptr; : nullptr;
const auto myIcon = Ui::MakeIconThumbnail(st::menuIconChats); const auto myIcon = Ui::MakeIconThumbnail(st::menuIconChats);
const auto publicIcon = _searchingHashtag const auto publicIcon = (_searchHashOrCashtag != HashOrCashtag::None)
? Ui::MakeIconThumbnail(st::menuIconChannel) ? Ui::MakeIconThumbnail(st::menuIconChannel)
: nullptr; : nullptr;
const auto peerTabType = (peer && peer->isBroadcast()) const auto peerTabType = (peer && peer->isBroadcast())

View file

@ -62,6 +62,7 @@ class IndexedList;
class SearchTags; class SearchTags;
class SearchEmpty; class SearchEmpty;
class ChatSearchIn; class ChatSearchIn;
enum class HashOrCashtag : uchar;
struct ChosenRow { struct ChosenRow {
Key key; Key key;
@ -514,7 +515,7 @@ private:
Ui::DraggingScrollManager _draggingScroll; Ui::DraggingScrollManager _draggingScroll;
SearchState _searchState; SearchState _searchState;
bool _searchingHashtag = false; HashOrCashtag _searchHashOrCashtag = {};
History *_searchInMigrated = nullptr; History *_searchInMigrated = nullptr;
PeerData *_searchFromShown = nullptr; PeerData *_searchFromShown = nullptr;
Ui::Text::String _searchFromUserText; Ui::Text::String _searchFromUserText;

View file

@ -2125,14 +2125,14 @@ bool Widget::searchForPeersRequired(const QString &query) const {
return _searchState.filterChatsList() return _searchState.filterChatsList()
&& !_openedForum && !_openedForum
&& !query.isEmpty() && !query.isEmpty()
&& !IsHashtagSearchQuery(query); && (IsHashOrCashtagSearchQuery(query) == HashOrCashtag::None);
} }
bool Widget::searchForTopicsRequired(const QString &query) const { bool Widget::searchForTopicsRequired(const QString &query) const {
return _searchState.filterChatsList() return _searchState.filterChatsList()
&& _openedForum && _openedForum
&& !query.isEmpty() && !query.isEmpty()
&& !IsHashtagSearchQuery(query) && (IsHashOrCashtagSearchQuery(query) == HashOrCashtag::None)
&& !_openedForum->topicsList()->loaded(); && !_openedForum->topicsList()->loaded();
} }
@ -2654,16 +2654,19 @@ void Widget::updateCancelSearch() {
QString Widget::validateSearchQuery() { QString Widget::validateSearchQuery() {
const auto query = currentSearchQuery(); const auto query = currentSearchQuery();
if (_searchState.tab == ChatSearchTab::PublicPosts) { if (_searchState.tab == ChatSearchTab::PublicPosts) {
_searchingHashtag = true; if (_searchHashOrCashtag == HashOrCashtag::None) {
_searchHashOrCashtag = HashOrCashtag::Hashtag;
}
const auto fixed = FixHashtagSearchQuery( const auto fixed = FixHashtagSearchQuery(
query, query,
currentSearchQueryCursorPosition()); currentSearchQueryCursorPosition(),
_searchHashOrCashtag);
if (fixed.text != query) { if (fixed.text != query) {
setSearchQuery(fixed.text, fixed.cursorPosition); setSearchQuery(fixed.text, fixed.cursorPosition);
} }
return fixed.text; return fixed.text;
} else { } else {
_searchingHashtag = IsHashtagSearchQuery(query); _searchHashOrCashtag = IsHashOrCashtagSearchQuery(query);
} }
return query; return query;
} }
@ -2860,11 +2863,12 @@ bool Widget::applySearchState(SearchState state) {
state.fromPeer = nullptr; state.fromPeer = nullptr;
} }
if (state.tab == ChatSearchTab::PublicPosts if (state.tab == ChatSearchTab::PublicPosts
&& !IsHashtagSearchQuery(state.query)) { && IsHashOrCashtagSearchQuery(state.query) == HashOrCashtag::None) {
state.tab = (_openedForum && !state.inChat) state.tab = (_openedForum && !state.inChat)
? ChatSearchTab::ThisPeer ? ChatSearchTab::ThisPeer
: ChatSearchTab::MyMessages; : ChatSearchTab::MyMessages;
} else if (!state.inChat && !_searchingHashtag) { } else if (!state.inChat
&& _searchHashOrCashtag == HashOrCashtag::None) {
state.tab = (forum || _openedForum) state.tab = (forum || _openedForum)
? ChatSearchTab::ThisPeer ? ChatSearchTab::ThisPeer
: ChatSearchTab::MyMessages; : ChatSearchTab::MyMessages;
@ -2904,7 +2908,7 @@ bool Widget::applySearchState(SearchState state) {
&& !state.inChat && !state.inChat
&& !_openedForum) && !_openedForum)
|| (state.tab == ChatSearchTab::PublicPosts || (state.tab == ChatSearchTab::PublicPosts
&& !_searchingHashtag)) { && _searchHashOrCashtag == HashOrCashtag::None)) {
state.tab = state.inChat.topic() state.tab = state.inChat.topic()
? ChatSearchTab::ThisTopic ? ChatSearchTab::ThisTopic
: (state.inChat.owningHistory() || state.inChat.sublist()) : (state.inChat.owningHistory() || state.inChat.sublist())

View file

@ -79,6 +79,7 @@ enum class SearchRequestDelay : uchar;
class Suggestions; class Suggestions;
class ChatSearchIn; class ChatSearchIn;
enum class ChatSearchTab : uchar; enum class ChatSearchTab : uchar;
enum class HashOrCashtag : uchar;
class Widget final : public Window::AbstractSectionWidget { class Widget final : public Window::AbstractSectionWidget {
public: public:
@ -314,7 +315,7 @@ private:
object_ptr<Ui::JumpDownButton> _scrollToTop; object_ptr<Ui::JumpDownButton> _scrollToTop;
bool _scrollToTopIsShown = false; bool _scrollToTopIsShown = false;
bool _forumSearchRequested = false; bool _forumSearchRequested = false;
bool _searchingHashtag = false; HashOrCashtag _searchHashOrCashtag = {};
Data::Folder *_openedFolder = nullptr; Data::Folder *_openedFolder = nullptr;
Data::Forum *_openedForum = nullptr; Data::Forum *_openedForum = nullptr;

View file

@ -199,12 +199,14 @@ void Action::handleKeyPress(not_null<QKeyEvent*> e) {
FixedHashtagSearchQuery FixHashtagSearchQuery( FixedHashtagSearchQuery FixHashtagSearchQuery(
const QString &query, const QString &query,
int cursorPosition) { int cursorPosition,
HashOrCashtag tag) {
const auto trimmed = query.trimmed(); const auto trimmed = query.trimmed();
const auto hash = int(trimmed.isEmpty() const auto hash = int(trimmed.isEmpty()
? query.size() ? query.size()
: query.indexOf(trimmed)); : query.indexOf(trimmed));
const auto start = std::min(cursorPosition, hash); const auto start = std::min(cursorPosition, hash);
const auto first = QChar(tag == HashOrCashtag::Cashtag ? '$' : '#');
auto result = query.mid(0, start); auto result = query.mid(0, start);
for (const auto &ch : query.mid(start)) { for (const auto &ch : query.mid(start)) {
if (ch.isSpace()) { if (ch.isSpace()) {
@ -213,33 +215,41 @@ FixedHashtagSearchQuery FixHashtagSearchQuery(
} }
continue; continue;
} else if (result.size() == start) { } else if (result.size() == start) {
result += '#'; result += first;
if (ch != '#') { if (ch != first) {
++cursorPosition; ++cursorPosition;
} }
} }
if (ch != '#') { if (ch != first) {
result += ch; result += ch;
} }
} }
if (result.size() == start) { if (result.size() == start) {
result += '#'; result += first;
++cursorPosition; ++cursorPosition;
} }
return { result, cursorPosition }; return { result, cursorPosition };
} }
bool IsHashtagSearchQuery(const QString &query) { HashOrCashtag IsHashOrCashtagSearchQuery(const QString &query) {
const auto trimmed = query.trimmed(); const auto trimmed = query.trimmed();
if (trimmed.isEmpty() || trimmed[0] != '#') { const auto first = trimmed.isEmpty() ? QChar() : trimmed[0];
return false; if (first == '#') {
} for (const auto &ch : trimmed) {
for (const auto &ch : trimmed) { if (ch.isSpace()) {
if (ch.isSpace()) { return HashOrCashtag::None;
return false; }
} }
return HashOrCashtag::Hashtag;
} else if (first == '$') {
for (const auto &ch : trimmed.midRef(1)) {
if (ch < 'A' || ch > 'Z') {
return HashOrCashtag::None;
}
}
return HashOrCashtag::Cashtag;
} }
return true; return HashOrCashtag::None;
} }
void ChatSearchIn::Section::update() { void ChatSearchIn::Section::update() {

View file

@ -87,14 +87,21 @@ private:
}; };
enum class HashOrCashtag : uchar {
None,
Hashtag,
Cashtag,
};
struct FixedHashtagSearchQuery { struct FixedHashtagSearchQuery {
QString text; QString text;
int cursorPosition = 0; int cursorPosition = 0;
}; };
[[nodiscard]] FixedHashtagSearchQuery FixHashtagSearchQuery( [[nodiscard]] FixedHashtagSearchQuery FixHashtagSearchQuery(
const QString &query, const QString &query,
int cursorPosition); int cursorPosition,
HashOrCashtag tag);
[[nodiscard]] bool IsHashtagSearchQuery(const QString &query); [[nodiscard]] HashOrCashtag IsHashOrCashtagSearchQuery(const QString &query);
} // namespace Dialogs } // namespace Dialogs