Added storage of proper text size with emoji to input field.
This commit is contained in:
parent
3c8cf5f5db
commit
1587f9f1b9
2 changed files with 31 additions and 13 deletions
|
|
@ -1927,7 +1927,7 @@ bool InputField::hasText() const {
|
||||||
return (from.next() != till);
|
return (from.next() != till);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString InputField::getTextPart(
|
InputField::TextPart InputField::getTextPart(
|
||||||
int start,
|
int start,
|
||||||
int end,
|
int end,
|
||||||
TagList &outTagsList,
|
TagList &outTagsList,
|
||||||
|
|
@ -1938,7 +1938,7 @@ QString InputField::getTextPart(
|
||||||
if (end >= 0 && end <= start) {
|
if (end >= 0 && end <= start) {
|
||||||
outTagsChanged = !outTagsList.isEmpty();
|
outTagsChanged = !outTagsList.isEmpty();
|
||||||
outTagsList.clear();
|
outTagsList.clear();
|
||||||
return QString();
|
return { QString(), 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
|
|
@ -1967,6 +1967,7 @@ QString InputField::getTextPart(
|
||||||
if (!full && end < 0) {
|
if (!full && end < 0) {
|
||||||
end = possibleLength;
|
end = possibleLength;
|
||||||
}
|
}
|
||||||
|
auto textSizeWithoutSurrogatePairsCount = document->characterCount() - 1;
|
||||||
|
|
||||||
for (auto block = from; block != till;) {
|
for (auto block = from; block != till;) {
|
||||||
for (auto item = block.begin(); !item.atEnd(); ++item) {
|
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()) {
|
if (format.isImageFormat()) {
|
||||||
const auto imageName = format.toImageFormat().name();
|
const auto imageName = format.toImageFormat().name();
|
||||||
if (const auto emoji = Emoji::FromUrl(imageName)) {
|
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 = [&] {
|
auto text = [&] {
|
||||||
const auto result = fragment.text();
|
const auto result = fragment.text();
|
||||||
|
|
@ -2030,9 +2036,12 @@ QString InputField::getTextPart(
|
||||||
if (ch > begin) {
|
if (ch > begin) {
|
||||||
result.append(begin, ch - begin);
|
result.append(begin, ch - begin);
|
||||||
}
|
}
|
||||||
adjustedLength += (emojiText.size() - 1);
|
const auto size = emojiEntry.text.size() - 1;
|
||||||
if (!emojiText.isEmpty()) {
|
adjustedLength += size;
|
||||||
result.append(emojiText);
|
if (!emojiEntry.text.isEmpty()) {
|
||||||
|
result.append(emojiEntry.text);
|
||||||
|
textSizeWithoutSurrogatePairsCount += size
|
||||||
|
- emojiEntry.surrogatePairs;
|
||||||
}
|
}
|
||||||
begin = ch + 1;
|
begin = ch + 1;
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -2063,7 +2072,7 @@ QString InputField::getTextPart(
|
||||||
markdownTagAccumulator.finish();
|
markdownTagAccumulator.finish();
|
||||||
|
|
||||||
outTagsChanged = tagAccumulator.changed();
|
outTagsChanged = tagAccumulator.changed();
|
||||||
return result;
|
return { result, textSizeWithoutSurrogatePairsCount };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputField::isUndoAvailable() const {
|
bool InputField::isUndoAvailable() const {
|
||||||
|
|
@ -2457,7 +2466,7 @@ void InputField::handleContentsChanged() {
|
||||||
setErrorShown(false);
|
setErrorShown(false);
|
||||||
|
|
||||||
auto tagsChanged = false;
|
auto tagsChanged = false;
|
||||||
const auto currentText = getTextPart(
|
const auto [currentText, currentTextSize] = getTextPart(
|
||||||
0,
|
0,
|
||||||
-1,
|
-1,
|
||||||
_lastTextWithTags.tags,
|
_lastTextWithTags.tags,
|
||||||
|
|
@ -2466,6 +2475,7 @@ void InputField::handleContentsChanged() {
|
||||||
|
|
||||||
//highlightMarkdown();
|
//highlightMarkdown();
|
||||||
|
|
||||||
|
_lastTextSizeWithoutSurrogatePairsCount = currentTextSize;
|
||||||
if (tagsChanged || (_lastTextWithTags.text != currentText)) {
|
if (tagsChanged || (_lastTextWithTags.text != currentText)) {
|
||||||
_lastTextWithTags.text = currentText;
|
_lastTextWithTags.text = currentText;
|
||||||
const auto weak = MakeWeak(this);
|
const auto weak = MakeWeak(this);
|
||||||
|
|
@ -2640,7 +2650,7 @@ void InputField::setTextWithTags(
|
||||||
TextWithTags InputField::getTextWithTagsPart(int start, int end) const {
|
TextWithTags InputField::getTextWithTagsPart(int start, int end) const {
|
||||||
auto changed = false;
|
auto changed = false;
|
||||||
auto result = TextWithTags();
|
auto result = TextWithTags();
|
||||||
result.text = getTextPart(start, end, result.tags, changed);
|
result.text = getTextPart(start, end, result.tags, changed).text;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3988,7 +3998,7 @@ void PrepareFormattingOptimization(not_null<QTextDocument*> document) {
|
||||||
|
|
||||||
int FieldCharacterCount(not_null<InputField*> field) {
|
int FieldCharacterCount(not_null<InputField*> field) {
|
||||||
// This method counts emoji properly.
|
// This method counts emoji properly.
|
||||||
return field->document()->characterCount() - 1;
|
return field->lastTextSizeWithoutSurrogatePairsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,9 @@ public:
|
||||||
const QString &getLastText() const {
|
const QString &getLastText() const {
|
||||||
return _lastTextWithTags.text;
|
return _lastTextWithTags.text;
|
||||||
}
|
}
|
||||||
|
[[nodiscard]] int lastTextSizeWithoutSurrogatePairsCount() const {
|
||||||
|
return _lastTextSizeWithoutSurrogatePairsCount;
|
||||||
|
}
|
||||||
void setPlaceholder(
|
void setPlaceholder(
|
||||||
rpl::producer<QString> placeholder,
|
rpl::producer<QString> placeholder,
|
||||||
int afterSymbols = 0);
|
int afterSymbols = 0);
|
||||||
|
|
@ -380,7 +383,11 @@ private:
|
||||||
|
|
||||||
// "start" and "end" are in coordinates of text where emoji are replaced
|
// "start" and "end" are in coordinates of text where emoji are replaced
|
||||||
// by ObjectReplacementCharacter. If "end" = -1 means get text till the end.
|
// 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 start,
|
||||||
int end,
|
int end,
|
||||||
TagList &outTagsList,
|
TagList &outTagsList,
|
||||||
|
|
@ -484,6 +491,7 @@ private:
|
||||||
TextWithTags _lastTextWithTags;
|
TextWithTags _lastTextWithTags;
|
||||||
std::vector<MarkdownTag> _lastMarkdownTags;
|
std::vector<MarkdownTag> _lastMarkdownTags;
|
||||||
QString _lastPreEditText;
|
QString _lastPreEditText;
|
||||||
|
int _lastTextSizeWithoutSurrogatePairsCount = 0;
|
||||||
std::optional<QString> _inputMethodCommit;
|
std::optional<QString> _inputMethodCommit;
|
||||||
|
|
||||||
QMargins _additionalMargins;
|
QMargins _additionalMargins;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue