Added storage of proper text size with emoji to input field.

This commit is contained in:
23rd 2024-03-06 17:32:20 +03:00 committed by John Preston
parent 3c8cf5f5db
commit 1587f9f1b9
2 changed files with 31 additions and 13 deletions

View file

@ -1927,7 +1927,7 @@ bool InputField::hasText() const {
return (from.next() != till);
}
QString InputField::getTextPart(
InputField::TextPart InputField::getTextPart(
int start,
int end,
TagList &outTagsList,
@ -1938,7 +1938,7 @@ QString InputField::getTextPart(
if (end >= 0 && end <= start) {
outTagsChanged = !outTagsList.isEmpty();
outTagsList.clear();
return QString();
return { QString(), 0 };
}
if (start < 0) {
@ -1967,6 +1967,7 @@ QString InputField::getTextPart(
if (!full && end < 0) {
end = possibleLength;
}
auto textSizeWithoutSurrogatePairsCount = document->characterCount() - 1;
for (auto block = from; block != till;) {
for (auto item = block.begin(); !item.atEnd(); ++item) {
@ -1993,14 +1994,19 @@ QString InputField::getTextPart(
}
}
const auto emojiText = [&] {
struct EmojiEntry final {
QString text;
uint8 surrogatePairs = 0;
};
const auto emojiEntry = [&]() -> EmojiEntry {
if (format.isImageFormat()) {
const auto imageName = format.toImageFormat().name();
if (const auto emoji = Emoji::FromUrl(imageName)) {
return emoji->text();
return { emoji->text(), emoji->surrogatePairs() };
}
}
return format.property(kCustomEmojiText).toString();
return { format.property(kCustomEmojiText).toString(), 0 };
}();
auto text = [&] {
const auto result = fragment.text();
@ -2030,9 +2036,12 @@ QString InputField::getTextPart(
if (ch > begin) {
result.append(begin, ch - begin);
}
adjustedLength += (emojiText.size() - 1);
if (!emojiText.isEmpty()) {
result.append(emojiText);
const auto size = emojiEntry.text.size() - 1;
adjustedLength += size;
if (!emojiEntry.text.isEmpty()) {
result.append(emojiEntry.text);
textSizeWithoutSurrogatePairsCount += size
- emojiEntry.surrogatePairs;
}
begin = ch + 1;
} break;
@ -2063,7 +2072,7 @@ QString InputField::getTextPart(
markdownTagAccumulator.finish();
outTagsChanged = tagAccumulator.changed();
return result;
return { result, textSizeWithoutSurrogatePairsCount };
}
bool InputField::isUndoAvailable() const {
@ -2457,7 +2466,7 @@ void InputField::handleContentsChanged() {
setErrorShown(false);
auto tagsChanged = false;
const auto currentText = getTextPart(
const auto [currentText, currentTextSize] = getTextPart(
0,
-1,
_lastTextWithTags.tags,
@ -2466,6 +2475,7 @@ void InputField::handleContentsChanged() {
//highlightMarkdown();
_lastTextSizeWithoutSurrogatePairsCount = currentTextSize;
if (tagsChanged || (_lastTextWithTags.text != currentText)) {
_lastTextWithTags.text = currentText;
const auto weak = MakeWeak(this);
@ -2640,7 +2650,7 @@ void InputField::setTextWithTags(
TextWithTags InputField::getTextWithTagsPart(int start, int end) const {
auto changed = false;
auto result = TextWithTags();
result.text = getTextPart(start, end, result.tags, changed);
result.text = getTextPart(start, end, result.tags, changed).text;
return result;
}
@ -3988,7 +3998,7 @@ void PrepareFormattingOptimization(not_null<QTextDocument*> document) {
int FieldCharacterCount(not_null<InputField*> field) {
// This method counts emoji properly.
return field->document()->characterCount() - 1;
return field->lastTextSizeWithoutSurrogatePairsCount();
}
} // namespace Ui

View file

@ -241,6 +241,9 @@ public:
const QString &getLastText() const {
return _lastTextWithTags.text;
}
[[nodiscard]] int lastTextSizeWithoutSurrogatePairsCount() const {
return _lastTextSizeWithoutSurrogatePairsCount;
}
void setPlaceholder(
rpl::producer<QString> placeholder,
int afterSymbols = 0);
@ -380,7 +383,11 @@ private:
// "start" and "end" are in coordinates of text where emoji are replaced
// by ObjectReplacementCharacter. If "end" = -1 means get text till the end.
QString getTextPart(
struct TextPart final {
QString text;
int textSizeWithoutSurrogatePairsCount = 0;
};
TextPart getTextPart(
int start,
int end,
TagList &outTagsList,
@ -484,6 +491,7 @@ private:
TextWithTags _lastTextWithTags;
std::vector<MarkdownTag> _lastMarkdownTags;
QString _lastPreEditText;
int _lastTextSizeWithoutSurrogatePairsCount = 0;
std::optional<QString> _inputMethodCommit;
QMargins _additionalMargins;