Support getting OnlyCustomEmoji from Ui::Text::String.
This commit is contained in:
parent
a7117df837
commit
f27d756bcd
3 changed files with 94 additions and 8 deletions
|
|
@ -836,10 +836,28 @@ void Parser::finalize(const TextParseOptions &options) {
|
||||||
currentIndex++;
|
currentIndex++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
auto isolatedEmojiCount = 0;
|
||||||
_t->_hasCustomEmoji = false;
|
_t->_hasCustomEmoji = false;
|
||||||
|
_t->_isIsolatedEmoji = true;
|
||||||
|
_t->_isOnlyCustomEmoji = true;
|
||||||
for (auto &block : _t->_blocks) {
|
for (auto &block : _t->_blocks) {
|
||||||
if (block->type() == TextBlockTCustomEmoji) {
|
if (block->type() == TextBlockTCustomEmoji) {
|
||||||
_t->_hasCustomEmoji = true;
|
_t->_hasCustomEmoji = true;
|
||||||
|
} else if (block->type() != TextBlockTNewline
|
||||||
|
&& block->type() != TextBlockTSkip) {
|
||||||
|
_t->_isOnlyCustomEmoji = false;
|
||||||
|
} else if (block->lnkIndex()) {
|
||||||
|
_t->_isOnlyCustomEmoji = _t->_isIsolatedEmoji = false;
|
||||||
|
}
|
||||||
|
if (_t->_isIsolatedEmoji) {
|
||||||
|
if (block->type() == TextBlockTCustomEmoji
|
||||||
|
|| block->type() == TextBlockTEmoji) {
|
||||||
|
if (++isolatedEmojiCount > kIsolatedEmojiLimit) {
|
||||||
|
_t->_isIsolatedEmoji = false;
|
||||||
|
}
|
||||||
|
} else if (block->type() != TextBlockTSkip) {
|
||||||
|
_t->_isIsolatedEmoji = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const auto spoilerIndex = block->spoilerIndex();
|
const auto spoilerIndex = block->spoilerIndex();
|
||||||
if (spoilerIndex && (_t->_spoilers.size() < spoilerIndex)) {
|
if (spoilerIndex && (_t->_spoilers.size() < spoilerIndex)) {
|
||||||
|
|
@ -906,6 +924,12 @@ void Parser::finalize(const TextParseOptions &options) {
|
||||||
}
|
}
|
||||||
lastHandlerIndex.lnk = realIndex;
|
lastHandlerIndex.lnk = realIndex;
|
||||||
}
|
}
|
||||||
|
if (!_t->_hasCustomEmoji || !_t->_spoilers.empty()) {
|
||||||
|
_t->_isOnlyCustomEmoji = false;
|
||||||
|
}
|
||||||
|
if (_t->_blocks.empty() || !_t->_spoilers.empty()) {
|
||||||
|
_t->_isIsolatedEmoji = false;
|
||||||
|
}
|
||||||
_t->_links.squeeze();
|
_t->_links.squeeze();
|
||||||
_t->_spoilers.squeeze();
|
_t->_spoilers.squeeze();
|
||||||
_t->_blocks.shrink_to_fit();
|
_t->_blocks.shrink_to_fit();
|
||||||
|
|
@ -2916,11 +2940,20 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
String::String(int32 minResizeWidth) : _minResizeWidth(minResizeWidth) {
|
String::String(int32 minResizeWidth)
|
||||||
|
: _minResizeWidth(minResizeWidth)
|
||||||
|
, _hasCustomEmoji(false)
|
||||||
|
, _isOnlyCustomEmoji(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
String::String(const style::TextStyle &st, const QString &text, const TextParseOptions &options, int32 minResizeWidth)
|
String::String(
|
||||||
: _minResizeWidth(minResizeWidth) {
|
const style::TextStyle &st,
|
||||||
|
const QString &text,
|
||||||
|
const TextParseOptions &options,
|
||||||
|
int32 minResizeWidth)
|
||||||
|
: _minResizeWidth(minResizeWidth)
|
||||||
|
, _hasCustomEmoji(false)
|
||||||
|
, _isOnlyCustomEmoji(false) {
|
||||||
setText(st, text, options);
|
setText(st, text, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3552,6 +3585,31 @@ void String::unloadCustomEmoji() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool String::isOnlyCustomEmoji() const {
|
||||||
|
return _isOnlyCustomEmoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnlyCustomEmoji String::toOnlyCustomEmoji() const {
|
||||||
|
if (!_isOnlyCustomEmoji) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto result = OnlyCustomEmoji();
|
||||||
|
auto spaces = 0;
|
||||||
|
result.lines.emplace_back();
|
||||||
|
for (const auto &block : _blocks) {
|
||||||
|
const auto raw = block.get();
|
||||||
|
if (raw->type() == TextBlockTCustomEmoji) {
|
||||||
|
const auto custom = static_cast<const CustomEmojiBlock*>(raw);
|
||||||
|
result.lines.back().push_back({
|
||||||
|
.entityData = custom->_custom->entityData(),
|
||||||
|
});
|
||||||
|
} else if (raw->type() == TextBlockTNewline) {
|
||||||
|
result.lines.emplace_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
QString String::toString(TextSelection selection) const {
|
QString String::toString(TextSelection selection) const {
|
||||||
return toText(selection, false, false).rich.text;
|
return toText(selection, false, false).rich.text;
|
||||||
}
|
}
|
||||||
|
|
@ -3715,7 +3773,14 @@ TextForMimeData String::toText(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool String::isIsolatedEmoji() const {
|
||||||
|
return _isIsolatedEmoji;
|
||||||
|
}
|
||||||
|
|
||||||
IsolatedEmoji String::toIsolatedEmoji() const {
|
IsolatedEmoji String::toIsolatedEmoji() const {
|
||||||
|
if (!_isIsolatedEmoji) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
auto result = IsolatedEmoji();
|
auto result = IsolatedEmoji();
|
||||||
const auto skip = (_blocks.empty()
|
const auto skip = (_blocks.empty()
|
||||||
|| _blocks.back()->type() != TextBlockTSkip) ? 0 : 1;
|
|| _blocks.back()->type() != TextBlockTSkip) ? 0 : 1;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ static constexpr TextSelection AllTextSelection = { 0, 0xFFFF };
|
||||||
namespace Ui::Text {
|
namespace Ui::Text {
|
||||||
|
|
||||||
struct IsolatedEmoji;
|
struct IsolatedEmoji;
|
||||||
|
struct OnlyCustomEmoji;
|
||||||
|
|
||||||
struct StateRequest {
|
struct StateRequest {
|
||||||
enum class Flag {
|
enum class Flag {
|
||||||
|
|
@ -160,17 +161,22 @@ public:
|
||||||
return _text.size();
|
return _text.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool hasCustomEmoji() const;
|
|
||||||
void unloadCustomEmoji();
|
|
||||||
|
|
||||||
[[nodiscard]] QString toString(
|
[[nodiscard]] QString toString(
|
||||||
TextSelection selection = AllTextSelection) const;
|
TextSelection selection = AllTextSelection) const;
|
||||||
[[nodiscard]] TextWithEntities toTextWithEntities(
|
[[nodiscard]] TextWithEntities toTextWithEntities(
|
||||||
TextSelection selection = AllTextSelection) const;
|
TextSelection selection = AllTextSelection) const;
|
||||||
[[nodiscard]] TextForMimeData toTextForMimeData(
|
[[nodiscard]] TextForMimeData toTextForMimeData(
|
||||||
TextSelection selection = AllTextSelection) const;
|
TextSelection selection = AllTextSelection) const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasCustomEmoji() const;
|
||||||
|
void unloadCustomEmoji();
|
||||||
|
|
||||||
|
[[nodiscard]] bool isIsolatedEmoji() const;
|
||||||
[[nodiscard]] IsolatedEmoji toIsolatedEmoji() const;
|
[[nodiscard]] IsolatedEmoji toIsolatedEmoji() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool isOnlyCustomEmoji() const;
|
||||||
|
[[nodiscard]] OnlyCustomEmoji toOnlyCustomEmoji() const;
|
||||||
|
|
||||||
[[nodiscard]] const style::TextStyle *style() const {
|
[[nodiscard]] const style::TextStyle *style() const {
|
||||||
return _st;
|
return _st;
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +216,9 @@ private:
|
||||||
QFixed _minResizeWidth;
|
QFixed _minResizeWidth;
|
||||||
QFixed _maxWidth = 0;
|
QFixed _maxWidth = 0;
|
||||||
int32 _minHeight = 0;
|
int32 _minHeight = 0;
|
||||||
bool _hasCustomEmoji = false;
|
bool _hasCustomEmoji : 1;
|
||||||
|
bool _isIsolatedEmoji : 1;
|
||||||
|
bool _isOnlyCustomEmoji : 1;
|
||||||
|
|
||||||
QString _text;
|
QString _text;
|
||||||
const style::TextStyle *_st = nullptr;
|
const style::TextStyle *_st = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,19 @@ struct IsolatedEmoji {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto t = sizeof(IsolatedEmoji);
|
struct OnlyCustomEmoji {
|
||||||
|
struct Item {
|
||||||
|
QString entityData;
|
||||||
|
int spacesBefore = 0;
|
||||||
|
};
|
||||||
|
std::vector<std::vector<Item>> lines;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {
|
||||||
|
return lines.empty();
|
||||||
|
}
|
||||||
|
[[nodiscard]] explicit operator bool() const {
|
||||||
|
return !empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Ui::Text
|
} // namespace Ui::Text
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue