mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +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 ShowAndStartBotMsgId = MsgId(SpecialMsgIdShift + 4);
|
||||||
constexpr auto ShowAndMaybeStartBotMsgId = MsgId(SpecialMsgIdShift + 5);
|
constexpr auto ShowAndMaybeStartBotMsgId = MsgId(SpecialMsgIdShift + 5);
|
||||||
constexpr auto ShowForChooseMessagesMsgId = MsgId(SpecialMsgIdShift + 6);
|
constexpr auto ShowForChooseMessagesMsgId = MsgId(SpecialMsgIdShift + 6);
|
||||||
|
constexpr auto kSearchQueryOffsetHint = -1;
|
||||||
|
|
||||||
static_assert(SpecialMsgIdShift + 0xFF < 0);
|
static_assert(SpecialMsgIdShift + 0xFF < 0);
|
||||||
static_assert(-(SpecialMsgIdShift + 0xFF) > ServerMaxMsgId);
|
static_assert(-(SpecialMsgIdShift + 0xFF) > ServerMaxMsgId);
|
||||||
|
|
|
@ -696,16 +696,19 @@ void Widget::chosenRow(const ChosenRow &row) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (const auto topic = row.key.topic()) {
|
} 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) {
|
if (row.newWindow) {
|
||||||
controller()->showInNewWindow(
|
controller()->showInNewWindow(
|
||||||
Window::SeparateId(topic),
|
Window::SeparateId(topic),
|
||||||
row.message.fullId.msg);
|
row.message.fullId.msg);
|
||||||
} else {
|
} else {
|
||||||
session().data().saveViewAsMessages(topic->forum(), false);
|
session().data().saveViewAsMessages(topic->forum(), false);
|
||||||
controller()->showThread(
|
controller()->showThread(topic, row.message.fullId.msg, params);
|
||||||
topic,
|
|
||||||
row.message.fullId.msg,
|
|
||||||
Window::SectionShow::Way::ClearStack);
|
|
||||||
}
|
}
|
||||||
} else if (history
|
} else if (history
|
||||||
&& row.userpicClick
|
&& row.userpicClick
|
||||||
|
@ -742,13 +745,16 @@ void Widget::chosenRow(const ChosenRow &row) {
|
||||||
const auto showAtMsgId = controller()->uniqueChatsInSearchResults()
|
const auto showAtMsgId = controller()->uniqueChatsInSearchResults()
|
||||||
? ShowAtUnreadMsgId
|
? ShowAtUnreadMsgId
|
||||||
: row.message.fullId.msg;
|
: 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) {
|
if (row.newWindow) {
|
||||||
controller()->showInNewWindow(peer, showAtMsgId);
|
controller()->showInNewWindow(peer, showAtMsgId);
|
||||||
} else {
|
} else {
|
||||||
controller()->showThread(
|
controller()->showThread(history, showAtMsgId, params);
|
||||||
history,
|
|
||||||
showAtMsgId,
|
|
||||||
Window::SectionShow::Way::ClearStack);
|
|
||||||
hideChildList();
|
hideChildList();
|
||||||
}
|
}
|
||||||
} else if (const auto folder = row.key.folder()) {
|
} else if (const auto folder = row.key.folder()) {
|
||||||
|
|
|
@ -94,6 +94,89 @@ Element *MousedElement/* = nullptr*/;
|
||||||
return session->tryResolveWindow();
|
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
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
|
std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
|
||||||
|
@ -1726,6 +1809,11 @@ TextSelection Element::FindSelectionFromQuote(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const auto &original = quote.item->originalText();
|
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 length = int(original.text.size());
|
||||||
const auto qlength = int(quote.text.text.size());
|
const auto qlength = int(quote.text.text.size());
|
||||||
const auto checkAt = [&](int offset) {
|
const auto checkAt = [&](int offset) {
|
||||||
|
@ -1789,28 +1877,7 @@ TextSelection Element::FindSelectionFromQuote(
|
||||||
if (result.empty()) {
|
if (result.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
for (const auto &modification : text.modifications()) {
|
return ApplyModificationsFrom(result, text);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Reactions::ButtonParameters Element::reactionButtonParameters(
|
Reactions::ButtonParameters Element::reactionButtonParameters(
|
||||||
|
|
Loading…
Add table
Reference in a new issue