mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Highlight word from search query.
This commit is contained in:
parent
3957fea5e4
commit
3565215c81
3 changed files with 104 additions and 30 deletions
|
@ -88,6 +88,7 @@ constexpr auto SwitchAtTopMsgId = MsgId(SpecialMsgIdShift + 2);
|
|||
constexpr auto ShowAndStartBotMsgId = MsgId(SpecialMsgIdShift + 4);
|
||||
constexpr auto ShowAndMaybeStartBotMsgId = MsgId(SpecialMsgIdShift + 5);
|
||||
constexpr auto ShowForChooseMessagesMsgId = MsgId(SpecialMsgIdShift + 6);
|
||||
constexpr auto kSearchQueryOffsetHint = -1;
|
||||
|
||||
static_assert(SpecialMsgIdShift + 0xFF < 0);
|
||||
static_assert(-(SpecialMsgIdShift + 0xFF) > ServerMaxMsgId);
|
||||
|
|
|
@ -696,16 +696,19 @@ void Widget::chosenRow(const ChosenRow &row) {
|
|||
}
|
||||
return;
|
||||
} else if (const auto topic = row.key.topic()) {
|
||||
auto params = Window::SectionShow(
|
||||
Window::SectionShow::Way::ClearStack);
|
||||
params.highlightPart.text = _searchState.query;
|
||||
if (!params.highlightPart.empty()) {
|
||||
params.highlightPartOffsetHint = kSearchQueryOffsetHint;
|
||||
}
|
||||
if (row.newWindow) {
|
||||
controller()->showInNewWindow(
|
||||
Window::SeparateId(topic),
|
||||
row.message.fullId.msg);
|
||||
} else {
|
||||
session().data().saveViewAsMessages(topic->forum(), false);
|
||||
controller()->showThread(
|
||||
topic,
|
||||
row.message.fullId.msg,
|
||||
Window::SectionShow::Way::ClearStack);
|
||||
controller()->showThread(topic, row.message.fullId.msg, params);
|
||||
}
|
||||
} else if (history
|
||||
&& row.userpicClick
|
||||
|
@ -742,13 +745,16 @@ void Widget::chosenRow(const ChosenRow &row) {
|
|||
const auto showAtMsgId = controller()->uniqueChatsInSearchResults()
|
||||
? ShowAtUnreadMsgId
|
||||
: row.message.fullId.msg;
|
||||
auto params = Window::SectionShow(
|
||||
Window::SectionShow::Way::ClearStack);
|
||||
params.highlightPart.text = _searchState.query;
|
||||
if (!params.highlightPart.empty()) {
|
||||
params.highlightPartOffsetHint = kSearchQueryOffsetHint;
|
||||
}
|
||||
if (row.newWindow) {
|
||||
controller()->showInNewWindow(peer, showAtMsgId);
|
||||
} else {
|
||||
controller()->showThread(
|
||||
history,
|
||||
showAtMsgId,
|
||||
Window::SectionShow::Way::ClearStack);
|
||||
controller()->showThread(history, showAtMsgId, params);
|
||||
hideChildList();
|
||||
}
|
||||
} else if (const auto folder = row.key.folder()) {
|
||||
|
|
|
@ -94,6 +94,89 @@ Element *MousedElement/* = nullptr*/;
|
|||
return session->tryResolveWindow();
|
||||
}
|
||||
|
||||
[[nodiscard]] TextSelection FindSearchQueryHighlight(
|
||||
const QString &text,
|
||||
const QString &query) {
|
||||
const auto lower = query.toLower();
|
||||
const auto inside = text.toLower();
|
||||
const auto find = [&](QStringView part) {
|
||||
auto skip = 0;
|
||||
if (const auto from = inside.indexOf(part, skip); from >= 0) {
|
||||
if (!from || !inside[from - 1].isLetterOrNumber()) {
|
||||
return from;
|
||||
}
|
||||
skip = from + 1;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
if (const auto from = find(lower); from >= 0) {
|
||||
const auto till = from + query.size();
|
||||
if (till >= inside.size() || !inside[till].isLetterOrNumber()) {
|
||||
return { uint16(from), uint16(till) };
|
||||
}
|
||||
}
|
||||
const auto tillEndOfWord = [&](int from) {
|
||||
for (auto till = from + 1; till != inside.size(); ++till) {
|
||||
if (!inside[till].isLetterOrNumber()) {
|
||||
return TextSelection{ uint16(from), uint16(till) };
|
||||
}
|
||||
}
|
||||
return TextSelection{ uint16(from), uint16(inside.size()) };
|
||||
};
|
||||
const auto words = QStringView(lower).split(
|
||||
QRegularExpression(
|
||||
u"[\\W]"_q,
|
||||
QRegularExpression::UseUnicodePropertiesOption),
|
||||
Qt::SkipEmptyParts);
|
||||
for (const auto &word : words) {
|
||||
const auto length = int(word.size());
|
||||
const auto cut = length / 2;
|
||||
const auto part = word.mid(0, length - cut);
|
||||
const auto offset = find(part);
|
||||
if (offset < 0) {
|
||||
continue;
|
||||
}
|
||||
for (auto i = 0; i != cut; ++i) {
|
||||
const auto part = word.mid(0, length - i);
|
||||
if (const auto from = find(part); from >= 0) {
|
||||
return tillEndOfWord(from);
|
||||
}
|
||||
}
|
||||
return tillEndOfWord(offset);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]] TextSelection ApplyModificationsFrom(
|
||||
TextSelection result,
|
||||
const Ui::Text::String &text) {
|
||||
if (result.empty()) {
|
||||
return result;
|
||||
}
|
||||
for (const auto &modification : text.modifications()) {
|
||||
if (modification.position >= result.to) {
|
||||
break;
|
||||
}
|
||||
if (modification.added) {
|
||||
++result.to;
|
||||
}
|
||||
const auto shiftTo = std::min(
|
||||
int(modification.skipped),
|
||||
result.to - modification.position);
|
||||
result.to -= shiftTo;
|
||||
if (modification.position <= result.from) {
|
||||
if (modification.added) {
|
||||
++result.from;
|
||||
}
|
||||
const auto shiftFrom = std::min(
|
||||
int(modification.skipped),
|
||||
result.from - modification.position);
|
||||
result.from -= shiftFrom;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
|
||||
|
@ -1726,6 +1809,11 @@ TextSelection Element::FindSelectionFromQuote(
|
|||
return {};
|
||||
}
|
||||
const auto &original = quote.item->originalText();
|
||||
if (quote.offset == kSearchQueryOffsetHint) {
|
||||
return ApplyModificationsFrom(
|
||||
FindSearchQueryHighlight(original.text, quote.text.text),
|
||||
text);
|
||||
}
|
||||
const auto length = int(original.text.size());
|
||||
const auto qlength = int(quote.text.text.size());
|
||||
const auto checkAt = [&](int offset) {
|
||||
|
@ -1789,28 +1877,7 @@ TextSelection Element::FindSelectionFromQuote(
|
|||
if (result.empty()) {
|
||||
return {};
|
||||
}
|
||||
for (const auto &modification : text.modifications()) {
|
||||
if (modification.position >= result.to) {
|
||||
break;
|
||||
}
|
||||
if (modification.added) {
|
||||
++result.to;
|
||||
}
|
||||
const auto shiftTo = std::min(
|
||||
int(modification.skipped),
|
||||
result.to - modification.position);
|
||||
result.to -= shiftTo;
|
||||
if (modification.position <= result.from) {
|
||||
if (modification.added) {
|
||||
++result.from;
|
||||
}
|
||||
const auto shiftFrom = std::min(
|
||||
int(modification.skipped),
|
||||
result.from - modification.position);
|
||||
result.from -= shiftFrom;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return ApplyModificationsFrom(result, text);
|
||||
}
|
||||
|
||||
Reactions::ButtonParameters Element::reactionButtonParameters(
|
||||
|
|
Loading…
Add table
Reference in a new issue