Improve Ui::Text::String features.

This commit is contained in:
John Preston 2023-10-03 17:50:33 +04:00
parent 2b3f17e982
commit 396c229a4d
31 changed files with 85 additions and 82 deletions

View File

@ -194,7 +194,7 @@ not_null<Ui::FlatLabel*> CreateWarningLabel(
if (value >= 0) {
result->setText(QString::number(value));
} else {
result->setMarkedText(Ui::Text::PlainLink(
result->setMarkedText(Ui::Text::Colorized(
QString::number(value)));
}
result->setVisible(shown);

View File

@ -75,7 +75,7 @@ constexpr auto kShowChatNamesCount = 8;
.entities = (history->chatListBadgesState().unread
? EntitiesInText{
{ EntityType::Semibold, 0, int(name.size()), QString() },
{ EntityType::PlainLink, 0, int(name.size()), QString() },
{ EntityType::Colorized, 0, int(name.size()), QString() },
}
: EntitiesInText{}),
};

View File

@ -85,7 +85,7 @@ using ItemPreviewImage = HistoryView::ItemPreviewImage;
const TextWithEntities &caption,
bool hasMiniImages = false) {
if (caption.text.isEmpty()) {
return Ui::Text::PlainLink(attachType);
return Ui::Text::Colorized(attachType);
}
return hasMiniImages
@ -96,7 +96,7 @@ using ItemPreviewImage = HistoryView::ItemPreviewImage;
tr::lng_dialogs_text_media_wrapped(
tr::now,
lt_media,
Ui::Text::PlainLink(attachType),
Ui::Text::Colorized(attachType),
Ui::Text::WithEntities),
lt_caption,
caption,
@ -558,7 +558,7 @@ ItemPreview Media::toGroupPreview(
: fileCount
? tr::lng_in_dlg_file_count(tr::now, lt_count, fileCount)
: tr::lng_in_dlg_album(tr::now);
result.text = Ui::Text::PlainLink(genericText);
result.text = Ui::Text::Colorized(genericText);
}
if (!loadingContext.empty()) {
result.loadingContext = std::move(loadingContext);
@ -937,7 +937,7 @@ TextWithEntities MediaFile::notificationText() const {
const auto text = _emoji.isEmpty()
? tr::lng_in_dlg_sticker(tr::now)
: tr::lng_in_dlg_sticker_emoji(tr::now, lt_emoji, _emoji);
return Ui::Text::PlainLink(text);
return Ui::Text::Colorized(text);
}
const auto type = [&] {
if (_document->isVideoMessage()) {
@ -1719,7 +1719,7 @@ PollData *MediaPoll::poll() const {
}
TextWithEntities MediaPoll::notificationText() const {
return Ui::Text::PlainLink(_poll->question);
return Ui::Text::Colorized(_poll->question);
}
QString MediaPoll::pinnedTextSubstring() const {

View File

@ -308,14 +308,14 @@ Image *Story::replyPreview() const {
TextWithEntities Story::inReplyText() const {
const auto type = tr::lng_in_dlg_story(tr::now);
return _caption.text.isEmpty()
? Ui::Text::PlainLink(type)
? Ui::Text::Colorized(type)
: tr::lng_dialogs_text_media(
tr::now,
lt_media_part,
tr::lng_dialogs_text_media_wrapped(
tr::now,
lt_media,
Ui::Text::PlainLink(type),
Ui::Text::Colorized(type),
Ui::Text::WithEntities),
lt_caption,
_caption,

View File

@ -260,7 +260,7 @@ void PaintFolderEntryText(
.now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionLines = rect.height() / st::dialogsTextFont->height,
.elisionHeight = rect.height(),
});
}
@ -420,7 +420,7 @@ void PaintRow(
.now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionLines = 1,
.elisionOneLine = true,
});
} else if (draft
|| (supportMode
@ -462,13 +462,13 @@ void PaintRow(
auto &cache = thread->cloudDraftTextCache();
if (cache.isEmpty()) {
using namespace TextUtilities;
auto draftWrapped = Text::PlainLink(
auto draftWrapped = Text::Colorized(
tr::lng_dialogs_text_from_wrapped(
tr::now,
lt_from,
tr::lng_from_draft(tr::now)));
auto draftText = supportMode
? Text::PlainLink(
? Text::Colorized(
Support::ChatOccupiedString(history))
: tr::lng_dialogs_text_with_from(
tr::now,
@ -514,7 +514,7 @@ void PaintRow(
.now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionLines = 1,
.elisionOneLine = true,
});
}
} else if (!item) {

View File

@ -94,7 +94,7 @@ TextWithEntities DialogsPreviewText(TextWithEntities text) {
EntityType::Underline,
EntityType::Italic,
EntityType::CustomEmoji,
EntityType::PlainLink,
EntityType::Colorized,
});
for (auto &entity : result.entities) {
if (entity.type() == EntityType::Pre) {
@ -102,6 +102,13 @@ TextWithEntities DialogsPreviewText(TextWithEntities text) {
EntityType::Code,
entity.offset(),
entity.length());
} else if (entity.type() == EntityType::Colorized
&& !entity.data().isEmpty()) {
// Drop 'data' so that only link-color colorization takes place.
entity = EntityInText(
EntityType::Colorized,
entity.offset(),
entity.length());
}
}
return result;
@ -188,7 +195,7 @@ void MessageView::prepare(
TextUtilities::Trim(preview.text);
auto textToCache = DialogsPreviewText(std::move(preview.text));
_hasPlainLinkAtBegin = !textToCache.entities.empty()
&& (textToCache.entities.front().type() == EntityType::PlainLink);
&& (textToCache.entities.front().type() == EntityType::Colorized);
_textCache.setMarkedText(
st::dialogsTextStyle,
std::move(textToCache),
@ -305,7 +312,6 @@ void MessageView::paint(
rect.setWidth(rect.width() - st::forumDialogJumpArrowSkip);
finalRight -= st::forumDialogJumpArrowSkip;
}
const auto lines = rect.height() / st::dialogsTextFont->height;
const auto pausedSpoiler = context.paused
|| On(PowerSaving::kChatSpoiler);
if (!_senderCache.isEmpty()) {
@ -313,7 +319,7 @@ void MessageView::paint(
.position = rect.topLeft(),
.availableWidth = rect.width(),
.palette = palette,
.elisionLines = lines,
.elisionHeight = rect.height(),
});
rect.setLeft(rect.x() + _senderCache.maxWidth());
if (!_imagesCache.empty() && !_leftIcon) {
@ -381,7 +387,7 @@ void MessageView::paint(
.now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler,
.elisionLines = lines,
.elisionHeight = rect.height(),
});
rect.setLeft(rect.x() + _textCache.maxWidth());
}
@ -457,7 +463,7 @@ HistoryView::ItemPreview PreviewWithSender(
auto fullWithOffset = tr::lng_dialogs_text_with_from(
tr::now,
lt_from_part,
Ui::Text::PlainLink(std::move(wrappedWithOffset.text)),
Ui::Text::Colorized(std::move(wrappedWithOffset.text)),
lt_message,
std::move(preview.text),
TextWithTagOffset<lt_from_part>::FromString);

View File

@ -75,7 +75,7 @@ void TopicsView::prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint) {
title.title.setMarkedText(
st::dialogsTextStyle,
(unread
? Ui::Text::PlainLink(
? Ui::Text::Colorized(
Ui::Text::Wrapped(
std::move(topicTitle),
EntityType::Bold))
@ -141,7 +141,7 @@ void TopicsView::paint(
.now = context.now,
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.elisionLines = 1,
.elisionOneLine = true,
});
const auto skip = skipBig
? context.st->topicsSkipBig

View File

@ -45,7 +45,7 @@ void TopBar::updateData(Content &&content) {
.append(" \xe2\x80\x93 ")
.append(row.label)
.append(' ')
.append(Ui::Text::PlainLink(row.info)));
.append(Ui::Text::Colorized(row.info)));
_progress->setValue(row.progress);
}

View File

@ -2932,9 +2932,7 @@ ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const {
// Because larger version is shown exactly to the left of the small.
//auto media = _media ? _media->toPreview(options) : ItemPreview();
return {
.text = Ui::Text::Wrapped(
notificationText(),
EntityType::PlainLink),
.text = Ui::Text::Colorized(notificationText()),
//.images = std::move(media.images),
//.loadingContext = std::move(media.loadingContext),
};
@ -3011,7 +3009,7 @@ TextWithEntities HistoryItem::inReplyText() const {
result = Ui::Text::Mid(result, name.size());
TextUtilities::Trim(result);
}
return Ui::Text::Wrapped(result, EntityType::PlainLink);
return Ui::Text::Colorized(result);
}
const std::vector<ClickHandlerPtr> &HistoryItem::customTextLinks() const {

View File

@ -630,7 +630,7 @@ void HistoryMessageReply::paint(
.pausedEmoji = (context.paused
|| On(PowerSaving::kEmojiChat)),
.pausedSpoiler = pausedSpoiler,
.elisionLines = 1,
.elisionOneLine = true,
});
p.setTextPalette(stm->textPalette);
}

View File

@ -7949,7 +7949,7 @@ void HistoryWidget::drawField(Painter &p, const QRect &rect) {
.now = now,
.pausedEmoji = paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler,
.elisionLines = 1,
.elisionOneLine = true,
});
} else {
p.setFont(st::msgDateFont);

View File

@ -902,7 +902,7 @@ void FieldHeader::paintEditOrReplyToMessage(Painter &p) {
.now = crl::now(),
.pausedEmoji = p.inactive() || On(PowerSaving::kEmojiChat),
.pausedSpoiler = p.inactive() || On(PowerSaving::kChatSpoiler),
.elisionLines = 1,
.elisionOneLine = true,
});
}

View File

@ -181,7 +181,7 @@ void ForwardPanel::updateTexts() {
text = DropCustomEmoji(std::move(text));
}
} else {
text = Ui::Text::PlainLink(
text = Ui::Text::Colorized(
tr::lng_forward_messages(tr::now, lt_count, count));
}
}
@ -364,7 +364,7 @@ void ForwardPanel::paint(
.now = now,
.pausedEmoji = paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler,
.elisionLines = 1,
.elisionOneLine = true,
});
}

View File

@ -358,15 +358,15 @@ void ServiceMessagePainter::PaintComplexBubble(
}
}
QVector<int> ServiceMessagePainter::CountLineWidths(
std::vector<int> ServiceMessagePainter::CountLineWidths(
const Ui::Text::String &text,
const QRect &textRect) {
const auto linesCount = qMax(
textRect.height() / st::msgServiceFont->height,
1);
auto result = QVector<int>();
result.reserve(linesCount);
text.countLineWidths(textRect.width(), &result);
auto result = text.countLineWidths(textRect.width(), {
.reserve = linesCount,
});
const auto minDelta = 2 * (Ui::HistoryServiceMsgRadius()
+ Ui::HistoryServiceMsgInvertedRadius()

View File

@ -113,7 +113,7 @@ public:
const QRect &textRect);
private:
static QVector<int> CountLineWidths(
static std::vector<int> CountLineWidths(
const Ui::Text::String &text,
const QRect &textRect);

View File

@ -257,7 +257,7 @@ void Game::draw(Painter &p, const PaintContext &context) const {
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.selection = toDescriptionSelection(context.selection),
.elisionLines = _descriptionLines,
.elisionHeight = _descriptionLines * lineHeight,
.elisionRemoveFromEnd = endskip,
});
tshift += _descriptionLines * lineHeight;

View File

@ -583,7 +583,9 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
.pausedEmoji = context.paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = context.paused || On(PowerSaving::kChatSpoiler),
.selection = toDescriptionSelection(context.selection),
.elisionLines = std::max(_descriptionLines, 0),
.elisionHeight = ((_descriptionLines > 0)
? (_descriptionLines * lineHeight)
: 0),
.elisionRemoveFromEnd = (_descriptionLines > 0) ? endskip : 0,
});
tshift += (_descriptionLines > 0)

View File

@ -524,7 +524,7 @@ void Cover::refreshStatusText() {
_refreshStatusTimer.callOnce(updateIn);
}
return showOnline
? PlainLink(result)
? Ui::Text::Colorized(result)
: TextWithEntities{ .text = result };
} else if (auto chat = _peer->asChat()) {
if (!chat->amIn()) {
@ -543,7 +543,7 @@ void Cover::refreshStatusText() {
onlineCount,
channel->isMegagroup());
return hasMembersLink
? PlainLink(result)
? Ui::Text::Colorized(result)
: TextWithEntities{ .text = result };
}
return tr::lng_chat_status_unaccessible(tr::now, WithEntities);

View File

@ -133,8 +133,8 @@ bool ValueParser::readTag() {
_tagsUsed.insert(_currentTagIndex);
if (_currentTagReplacer.isEmpty()) {
_currentTagReplacer = QString(4, TextCommand);
_currentTagReplacer[1] = kTextCommandLangTag;
_currentTagReplacer = QString(4, QChar(kTextCommand));
_currentTagReplacer[1] = QChar(kTextCommandLangTag);
}
_currentTagReplacer[2] = QChar(0x0020 + _currentTagIndex);
@ -168,8 +168,10 @@ QString PrepareTestValue(const QString &current, QChar filler) {
auto result = QString(size + 1, filler);
auto inCommand = false;
for (auto i = 0; i != size; ++i) {
auto ch = current[i];
auto newInCommand = (ch.unicode() == TextCommand) ? (!inCommand) : inCommand;
const auto ch = current[i];
const auto newInCommand = (ch.unicode() == kTextCommand)
? (!inCommand)
: inCommand;
if (inCommand || newInCommand || ch.isSpace()) {
result[i + 1] = ch;
}

View File

@ -868,8 +868,10 @@ auto ChoosePlural = ChoosePluralDefault;
int FindTagReplacementPosition(const QString &original, ushort tag) {
for (auto s = original.constData(), ch = s, e = ch + original.size(); ch != e;) {
if (*ch == TextCommand) {
if (ch + kTagReplacementSize <= e && (ch + 1)->unicode() == kTextCommandLangTag && *(ch + 3) == TextCommand) {
if (ch->unicode() == kTextCommand) {
if (ch + kTagReplacementSize <= e
&& (ch + 1)->unicode() == kTextCommandLangTag
&& (ch + 3)->unicode() == kTextCommand) {
if ((ch + 2)->unicode() == 0x0020 + tag) {
return ch - s;
} else {

View File

@ -11,11 +11,12 @@ enum lngtag_count : int;
namespace Lang {
inline constexpr auto kTextCommand = 0x10;
inline constexpr auto kTextCommandLangTag = 0x20;
constexpr auto kTagReplacementSize = 4;
[[nodiscard]] int FindTagReplacementPosition(
const QString &original,
const QString &original,
ushort tag);
struct ShortenedCount {

View File

@ -5014,7 +5014,7 @@ void OverlayWidget::paintCaptionContent(
.spoiler = Ui::Text::DefaultSpoilerCache(),
.pausedEmoji = On(PowerSaving::kEmojiChat),
.pausedSpoiler = On(PowerSaving::kChatSpoiler),
.elisionLines = inner.height() / lineHeight,
.elisionHeight = inner.height(),
.elisionRemoveFromEnd = _captionSkipBlockWidth,
});

View File

@ -888,17 +888,13 @@ void Panel::showWebviewError(
rich.append("\n\n");
switch (information.error) {
case Error::NoWebview2: {
const auto command = QString(QChar(TextCommand));
const auto text = tr::lng_payments_webview_install_edge(
rich.append(tr::lng_payments_webview_install_edge(
tr::now,
lt_link,
command);
const auto parts = text.split(command);
rich.append(parts.value(0))
.append(Text::Link(
Text::Link(
"Microsoft Edge WebView2 Runtime",
"https://go.microsoft.com/fwlink/p/?LinkId=2124703"))
.append(parts.value(1));
"https://go.microsoft.com/fwlink/p/?LinkId=2124703"),
Ui::Text::WithEntities));
} break;
case Error::NoWebKitGTK:
rich.append(tr::lng_payments_webview_install_webkit(tr::now));

View File

@ -1265,17 +1265,13 @@ void Panel::showWebviewError(
rich.append("\n\n");
switch (information.error) {
case Error::NoWebview2: {
const auto command = QString(QChar(TextCommand));
const auto text = tr::lng_payments_webview_install_edge(
rich.append(tr::lng_payments_webview_install_edge(
tr::now,
lt_link,
command);
const auto parts = text.split(command);
rich.append(parts.value(0))
.append(Text::Link(
Text::Link(
"Microsoft Edge WebView2 Runtime",
"https://go.microsoft.com/fwlink/p/?LinkId=2124703"))
.append(parts.value(1));
"https://go.microsoft.com/fwlink/p/?LinkId=2124703"),
Ui::Text::WithEntities));
} break;
case Error::NoWebKitGTK:
rich.append(tr::lng_payments_webview_install_webkit(tr::now));

View File

@ -469,9 +469,9 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
}
for (auto &stm : _messageStyles) {
const auto same = (stm.textPalette.linkFg->c == stm.historyTextFg->c);
stm.textPalette.linkAlwaysActive = same ? 1 : 0;
stm.semiboldPalette.linkAlwaysActive = same ? 1 : 0;
stm.textPalette.linkAlwaysActive
= stm.semiboldPalette.linkAlwaysActive
= (stm.textPalette.linkFg->c == stm.historyTextFg->c);
}
_paletteChanged.fire({});

View File

@ -457,7 +457,7 @@ void MessageBar::paint(Painter &p) {
.now = now,
.pausedEmoji = paused || On(PowerSaving::kEmojiChat),
.pausedSpoiler = pausedSpoiler,
.elisionLines = 1,
.elisionOneLine = true,
});
}
} else if (_animation->bodyAnimation == BodyAnimation::Text) {

View File

@ -444,7 +444,7 @@ void EmptyUserpic::fillString(const QString &name) {
}
} else if (!letterFound && ch->isLetterOrNumber()) {
letterFound = true;
if (ch + 1 != end && Ui::Text::IsDiac(*(ch + 1))) {
if (ch + 1 != end && Ui::Text::IsDiacritic(*(ch + 1))) {
letters.push_back(QString(ch, 2));
levels.push_back(level);
++ch;

View File

@ -76,7 +76,7 @@ TextParseOptions TextNameOptions = {
};
TextParseOptions TextDialogOptions = {
TextParsePlainLinks | TextParseMarkdown, // flags
TextParseColorized | TextParseMarkdown, // flags
0, // maxw is style-dependent
1, // maxh
Qt::LayoutDirectionAuto, // lang-dependent

View File

@ -828,7 +828,7 @@ void Notification::paintTitle(Painter &p) {
.spoiler = Ui::Text::DefaultSpoilerCache(),
.pausedEmoji = On(PowerSaving::kEmojiChat),
.pausedSpoiler = On(PowerSaving::kChatSpoiler),
.elisionLines = 1,
.elisionOneLine = true,
});
}
@ -842,7 +842,7 @@ void Notification::paintText(Painter &p) {
.spoiler = Ui::Text::DefaultSpoilerCache(),
.pausedEmoji = On(PowerSaving::kEmojiChat),
.pausedSpoiler = On(PowerSaving::kChatSpoiler),
.elisionLines = _textRect.height() / st::dialogsTextFont->height,
.elisionHeight = _textRect.height(),
});
}
@ -922,7 +922,7 @@ void Notification::updateNotifyDisplay() {
2 * st::dialogsTextFont->height);
const auto text = !_reaction.empty()
? (!_author.isEmpty()
? Ui::Text::PlainLink(_author).append(' ')
? Ui::Text::Colorized(_author).append(' ')
: TextWithEntities()
).append(Manager::ComposeReactionNotification(
_item,
@ -935,7 +935,7 @@ void Notification::updateNotifyDisplay() {
.spoilerLoginCode = options.spoilerLoginCode,
}).text
: ((!_author.isEmpty()
? Ui::Text::PlainLink(_author)
? Ui::Text::Colorized(_author)
: TextWithEntities()
).append(_forwardedCount > 1
? ('\n' + tr::lng_forward_messages(
@ -944,7 +944,7 @@ void Notification::updateNotifyDisplay() {
_forwardedCount))
: QString()));
const auto options = TextParseOptions{
(TextParsePlainLinks
(TextParseColorized
| TextParseMarkdown
| (_forwardedCount > 1 ? TextParseMultiline : 0)),
0,

View File

@ -47,7 +47,7 @@ namespace {
}
} else if (!letterFound && ch->isLetterOrNumber()) {
letterFound = true;
if (ch + 1 != end && Ui::Text::IsDiac(*(ch + 1))) {
if (ch + 1 != end && Ui::Text::IsDiacritic(*(ch + 1))) {
letters.push_back(QString(ch, 2));
levels.push_back(level);
++ch;
@ -353,25 +353,25 @@ void Generator::generateData() {
"Mike Apple",
2,
"9:00",
Ui::Text::PlainLink(QChar(55357)
Ui::Text::Colorized(QChar(55357)
+ QString()
+ QChar(56836)
+ " Sticker"));
_rows.back().unreadCounter = 2;
_rows.back().muted = true;
addRow("Evening Club", 1, "8:00", Ui::Text::PlainLink("Eva: Photo"));
addRow("Evening Club", 1, "8:00", Ui::Text::Colorized("Eva: Photo"));
_rows.back().type = Row::Type::Group;
addRow(
"Old Pirates",
6,
"7:00",
Ui::Text::PlainLink("Max:").append(" Yo-ho-ho!"));
Ui::Text::Colorized("Max:").append(" Yo-ho-ho!"));
_rows.back().type = Row::Type::Group;
addRow("Max Bright", 3, "6:00", { .text = "How about some coffee?" });
_rows.back().status = Status::Received;
addRow("Natalie Parker", 4, "5:00", { .text = "OK, great)" });
_rows.back().status = Status::Received;
addRow("Davy Jones", 5, "4:00", Ui::Text::PlainLink("Keynote.pdf"));
addRow("Davy Jones", 5, "4:00", Ui::Text::Colorized("Keynote.pdf"));
_topBarName.setText(st::msgNameStyle, "Eva Summer", Ui::NameTextOptions());
_topBarStatus = "online";

@ -1 +1 @@
Subproject commit 93458e4cb3845c9743bb0c0a78f1e6ce7ee99363
Subproject commit 02440524eaa2b1bd6d1909ff4aa2ca207a282b2c