From 745ce34dd5545737dd7c4dfc3f22a4e3d52d13a9 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 29 Dec 2021 18:27:23 +0300 Subject: [PATCH] Added new entity type for plain non-interactive links. Increased size of the block flags by two bits. Added a text utility to wrap a simple text with plain links. Added a new flag to specify parsing of plain links. --- ui/text/text.cpp | 15 +++++++++++++-- ui/text/text_block.cpp | 32 ++++++++++++++++---------------- ui/text/text_block.h | 17 +++++++++-------- ui/text/text_entity.h | 2 ++ ui/text/text_utilities.cpp | 4 ++++ ui/text/text_utilities.h | 1 + 6 files changed, 45 insertions(+), 26 deletions(-) diff --git a/ui/text/text.cpp b/ui/text/text.cpp index 8b54eb6..e24a385 100644 --- a/ui/text/text.cpp +++ b/ui/text/text.cpp @@ -77,7 +77,9 @@ TextWithEntities PrepareRichFromRich( const TextParseOptions &options) { auto result = text; const auto &preparsed = text.entities; - if ((options.flags & TextParseLinks) && !preparsed.isEmpty()) { + const bool parseLinks = (options.flags & TextParseLinks); + const bool parsePlainLinks = (options.flags & TextParsePlainLinks); + if (!preparsed.isEmpty() && (parseLinks || parsePlainLinks)) { bool parseMentions = (options.flags & TextParseMentions); bool parseHashtags = (options.flags & TextParseHashtags); bool parseBotCommands = (options.flags & TextParseBotCommands); @@ -91,6 +93,12 @@ TextWithEntities PrepareRichFromRich( if (((type == EntityType::Mention || type == EntityType::MentionName) && !parseMentions) || (type == EntityType::Hashtag && !parseHashtags) || (type == EntityType::Cashtag && !parseHashtags) || + (type == EntityType::PlainLink + && !parsePlainLinks + && !parseMarkdown) || + (!parseLinks + && (type == EntityType::Url + || type == EntityType::CustomUrl)) || (type == EntityType::BotCommand && !parseBotCommands) || // #TODO entities (!parseMarkdown && (type == EntityType::Bold || type == EntityType::Semibold @@ -601,6 +609,8 @@ bool Parser::checkEntities() { flags = TextBlockFItalic; } else if (entityType == EntityType::Underline) { flags = TextBlockFUnderline; + } else if (entityType == EntityType::PlainLink) { + flags = TextBlockFPlainLink; } else if (entityType == EntityType::StrikeOut) { flags = TextBlockFStrikeOut; } else if (entityType == EntityType::Code) { // #TODO entities @@ -2880,7 +2890,7 @@ private: } else { _background = {}; } - if (block->lnkIndex()) { + if (block->lnkIndex() || (block->flags() & TextBlockFPlainLink)) { _currentPen = &_textPalette->linkFg->p; _currentPenSelected = &_textPalette->selectLinkFg->p; } else if ((block->flags() & TextBlockFCode) || (block->flags() & TextBlockFPre)) { @@ -3576,6 +3586,7 @@ TextForMimeData String::toText( { TextBlockFBold, EntityType::Bold }, { TextBlockFSemibold, EntityType::Semibold }, { TextBlockFUnderline, EntityType::Underline }, + { TextBlockFPlainLink, EntityType::PlainLink }, { TextBlockFStrikeOut, EntityType::StrikeOut }, { TextBlockFCode, EntityType::Code }, // #TODO entities { TextBlockFPre, EntityType::Pre }, diff --git a/ui/text/text_block.cpp b/ui/text/text_block.cpp index f862dfb..a110c15 100644 --- a/ui/text/text_block.cpp +++ b/ui/text/text_block.cpp @@ -345,11 +345,11 @@ AbstractBlock::AbstractBlock( const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex) : _from(from) -, _flags((flags & 0xFF) | ((lnkIndex & 0xFFFF) << 12)) +, _flags((flags & 0b1111111111) | ((lnkIndex & 0xFFFF) << 14)) , _spoilerIndex(spoilerIndex) { } @@ -374,11 +374,11 @@ QFixed AbstractBlock::f_rpadding() const { } uint16 AbstractBlock::lnkIndex() const { - return (_flags >> 12) & 0xFFFF; + return (_flags >> 14) & 0xFFFF; } void AbstractBlock::setLnkIndex(uint16 lnkIndex) { - _flags = (_flags & ~(0xFFFF << 12)) | (lnkIndex << 12); + _flags = (_flags & ~(0xFFFF << 14)) | (lnkIndex << 14); } uint16 AbstractBlock::spoilerIndex() const { @@ -390,11 +390,11 @@ void AbstractBlock::setSpoilerIndex(uint16 spoilerIndex) { } TextBlockType AbstractBlock::type() const { - return TextBlockType((_flags >> 8) & 0x0F); + return TextBlockType((_flags >> 10) & 0x0F); } int32 AbstractBlock::flags() const { - return (_flags & 0xFFF); + return (_flags & 0b1111111111); } QFixed AbstractBlock::f_rbearing() const { @@ -409,11 +409,11 @@ TextBlock::TextBlock( QFixed minResizeWidth, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex) : AbstractBlock(font, str, from, length, flags, lnkIndex, spoilerIndex) { - _flags |= ((TextBlockTText & 0x0F) << 8); + _flags |= ((TextBlockTText & 0x0F) << 10); if (length) { style::font blockFont = font; if (!flags && lnkIndex) { @@ -455,13 +455,13 @@ EmojiBlock::EmojiBlock( const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex, EmojiPtr emoji) : AbstractBlock(font, str, from, length, flags, lnkIndex, spoilerIndex) , _emoji(emoji) { - _flags |= ((TextBlockTEmoji & 0x0F) << 8); + _flags |= ((TextBlockTEmoji & 0x0F) << 10); _width = int(st::emojiSize + 2 * st::emojiPadding); _rpadding = 0; for (auto i = length; i != 0;) { @@ -479,11 +479,11 @@ NewlineBlock::NewlineBlock( const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex) : AbstractBlock(font, str, from, length, flags, lnkIndex, spoilerIndex) { - _flags |= ((TextBlockTNewline & 0x0F) << 8); + _flags |= ((TextBlockTNewline & 0x0F) << 10); } Qt::LayoutDirection NewlineBlock::nextDirection() const { @@ -500,7 +500,7 @@ SkipBlock::SkipBlock( uint16 spoilerIndex) : AbstractBlock(font, str, from, 1, 0, lnkIndex, spoilerIndex) , _height(h) { - _flags |= ((TextBlockTSkip & 0x0F) << 8); + _flags |= ((TextBlockTSkip & 0x0F) << 10); _width = w; } @@ -641,7 +641,7 @@ Block Block::Newline( const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex) { return New( @@ -660,7 +660,7 @@ Block Block::Text( QFixed minResizeWidth, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex) { return New( @@ -679,7 +679,7 @@ Block Block::Emoji( const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex, EmojiPtr emoji) { diff --git a/ui/text/text_block.h b/ui/text/text_block.h index b57075b..c02d68c 100644 --- a/ui/text/text_block.h +++ b/ui/text/text_block.h @@ -30,6 +30,7 @@ enum TextBlockFlags { TextBlockFSemibold = 0x20, TextBlockFCode = 0x40, TextBlockFPre = 0x80, + TextBlockFPlainLink = 0x100, }; class AbstractBlock { @@ -58,13 +59,13 @@ protected: const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex); uint16 _from = 0; - uint32 _flags = 0; // 4 bits empty, 16 bits lnkIndex, 4 bits type, 8 bits flags + uint32 _flags = 0; // 2 bits empty, 16 bits lnkIndex, 4 bits type, 10 bits flags uint16 _spoilerIndex = 0; @@ -86,7 +87,7 @@ public: const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex); @@ -126,7 +127,7 @@ public: QFixed minResizeWidth, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex); @@ -150,7 +151,7 @@ public: const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex, EmojiPtr emoji); @@ -200,7 +201,7 @@ public: const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex); @@ -210,7 +211,7 @@ public: QFixed minResizeWidth, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex); @@ -219,7 +220,7 @@ public: const QString &str, uint16 from, uint16 length, - uchar flags, + uint16 flags, uint16 lnkIndex, uint16 spoilerIndex, EmojiPtr emoji); diff --git a/ui/text/text_entity.h b/ui/text/text_entity.h index 823932d..cbc1168 100644 --- a/ui/text/text_entity.h +++ b/ui/text/text_entity.h @@ -25,6 +25,7 @@ enum class EntityType : uchar { MentionName, BotCommand, MediaTimestamp, + PlainLink, // Senders in chat list, attachements in chat list, etc. Bold, Semibold, @@ -241,6 +242,7 @@ enum { TextParseHashtags = 0x010, TextParseBotCommands = 0x020, TextParseMarkdown = 0x040, + TextParsePlainLinks = 0x080, }; struct TextWithTags { diff --git a/ui/text/text_utilities.cpp b/ui/text/text_utilities.cpp index 715c8ed..dcc8d4f 100644 --- a/ui/text/text_utilities.cpp +++ b/ui/text/text_utilities.cpp @@ -42,6 +42,10 @@ TextWithEntities Link(const QString &text, const QString &url) { return WithSingleEntity(text, EntityType::CustomUrl, url); } +TextWithEntities PlainLink(const QString &text) { + return WithSingleEntity(text, EntityType::PlainLink); +} + TextWithEntities RichLangValue(const QString &text) { static const auto kStart = QRegularExpression("(\\*\\*|__)"); diff --git a/ui/text/text_utilities.h b/ui/text/text_utilities.h index b07d0e7..3ebe974 100644 --- a/ui/text/text_utilities.h +++ b/ui/text/text_utilities.h @@ -30,6 +30,7 @@ inline constexpr auto Upper = details::ToUpperType{}; [[nodiscard]] TextWithEntities Link( const QString &text, const QString &url = "internal:action"); +[[nodiscard]] TextWithEntities PlainLink(const QString &text); [[nodiscard]] TextWithEntities RichLangValue(const QString &text); [[nodiscard]] inline TextWithEntities WithEntities(const QString &text) { return { text };