From 3b40bc6297d9ba2104767007c777a1a41c839080 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 2 Nov 2023 13:33:55 +0400 Subject: [PATCH] Show full reply names with icons. --- .../icons/chat/reply_type_channel.png | Bin 0 -> 277 bytes .../icons/chat/reply_type_channel@2x.png | Bin 0 -> 474 bytes .../icons/chat/reply_type_channel@3x.png | Bin 0 -> 619 bytes .../Resources/icons/chat/reply_type_group.png | Bin 0 -> 324 bytes .../icons/chat/reply_type_group@2x.png | Bin 0 -> 610 bytes .../icons/chat/reply_type_group@3x.png | Bin 0 -> 890 bytes .../Resources/icons/chat/reply_type_user.png | Bin 0 -> 239 bytes .../icons/chat/reply_type_user@2x.png | Bin 0 -> 416 bytes .../icons/chat/reply_type_user@3x.png | Bin 0 -> 554 bytes .../data/stickers/data_custom_emoji.cpp | 47 ++++ .../data/stickers/data_custom_emoji.h | 16 ++ .../history/history_item_components.cpp | 230 +++++++++++------- .../history/history_item_components.h | 16 +- .../history/view/history_view_message.cpp | 6 +- Telegram/SourceFiles/ui/chat/chat.style | 6 + 15 files changed, 226 insertions(+), 95 deletions(-) create mode 100644 Telegram/Resources/icons/chat/reply_type_channel.png create mode 100644 Telegram/Resources/icons/chat/reply_type_channel@2x.png create mode 100644 Telegram/Resources/icons/chat/reply_type_channel@3x.png create mode 100644 Telegram/Resources/icons/chat/reply_type_group.png create mode 100644 Telegram/Resources/icons/chat/reply_type_group@2x.png create mode 100644 Telegram/Resources/icons/chat/reply_type_group@3x.png create mode 100644 Telegram/Resources/icons/chat/reply_type_user.png create mode 100644 Telegram/Resources/icons/chat/reply_type_user@2x.png create mode 100644 Telegram/Resources/icons/chat/reply_type_user@3x.png diff --git a/Telegram/Resources/icons/chat/reply_type_channel.png b/Telegram/Resources/icons/chat/reply_type_channel.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa9e90f8a9f511de6e5823d112727aae6d6b9f6 GIT binary patch literal 277 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1SD^YpWXnZI14-?iy0WWg+Z8+Vb&Z8px|*& z7sn8ZsjdCCe69{6Zu=$mwJv*vL~V_7X^LoYO6RUCTey*-N_t{MyNhvaTUOM}a1R@y zdBJyg{(N_*Sk&f##OhV23g;wByc3@H-1oA|(mUID85k#|MhdV@31V>S*ra3meAcqJ z%q;>t)@iT5v8}d_X~D8gyG+>&sgZHc^Y^`fz01zJ@Z9y%tEGQACNA!Jd}EUiL+o|Q zwu>gc?|(aS9J}%U{34CA%Qok~`%O{_6p0mEy~?U@@sv%ux9gh{CC+`Gv+U(-P4gPY YmG6^!4cndt1HHuH>FVdQ&MBb@0C*j43IG5A literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/reply_type_channel@2x.png b/Telegram/Resources/icons/chat/reply_type_channel@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8bb8c2bfca050e092ade54bf5e45490a6a1fa8 GIT binary patch literal 474 zcmV<00VV#4P)TlE1IPP!z|%+)9&fHIYWbfRv3O{sV)-#vt(@_!o3E z^bcqxMt_IF!XhaWi9}*Rtr9;H$~AbeuTN=S`}!I0Ip=fEz4rhfLEM#b9M@ zKG${KW%GPKzgR3NrIgZMujfX=Fifk}x?ZpJo73s!*bI31nHm-|yCLlu}*S1wlxqQg5TiL;z5!R6Zp=DHeIe`$;Y&Mt6<#xL*m&4ma*^YP!xb~OIU;i5mJ#F1&J_-O(YC97K12*$zo*@ z|AEm=VnkR(jFnWRvw=i9*d&sY22t%B`qGH1UwQQ9y>Dr9bI$$Fxoz*g0Q?7dyN4Zrb3~x-|wX+ zfsbj-W^=FClhfSEAZb1f!&mO+m1R0G+O17WF z;ox*S0RSk9zO-H4@5e5eD-;TuOr|G2;W#cXL%ZG1<#Ny4c)aVsfkvY#m&-Iwzth<* zFbt>DY2h@vg=N{nU~oE}#1V(X(P%U>nT&Lj%jKfe>3*)-&1M3l->sg#^7kx0m8*=)9aK3^)8gpXD! z5Cn-g&O55r>I)MoBo>Q3ly$q^&&vP+{eE96Td&t&k)bFmzH^byX7lPiiq12NqMFU7 zbnsP~Qmj_%YPGuU?7Md)1VK8T&UU-q?RNEg{fnl5k6+r|qW@c4yHfxF002ovPDHLk FV1g_XB@6%n literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/reply_type_group.png b/Telegram/Resources/icons/chat/reply_type_group.png new file mode 100644 index 0000000000000000000000000000000000000000..b40ba4b8140488abcc9a57be4ee43489d69ce6d3 GIT binary patch literal 324 zcmV-K0lWT*P)PbKDXUZIp@3c{ch*%0Q@Vy?=QKlFiF8Q5eQ&##26~DPv(_VZp}78f8J)C@KB{E7|(` z6C|ZjVrQk4GAm`pLdk+iv6=`|cE;x<<)e8Q^EM6UeHu>|&*Hr{=X9?7T)%U79{~8T zUn>ZL!r^eg-=`>QJRT>LNvTx&v2+jw8;u72sL5m^lgT~<2!%p4pE8*Yx6JK!7mLM8 zr4o%sVHkb`P_Nf{0XUAcHTis=Yt83#rBW#r(ChVh0sH-)DX?0tuWqSSdX0j30mI?& z`*VxM^6Hw+W}zKuG#ZMco*sC=-|cogQ{eGV0GG=}5CnU9x7!5*0oH{e zsM&0C(@&?9(P(_l0l#6uFl@8gbUNK~x$Ja0BuR2zu~;07#k^jxTrM9B28l#sI-S1J z!KcLEfm*G0I-PpGUZqk=Bod0E2!a@mM(uX{cs#OY5CkCza=Bd2=d&Q1R;$fsvpA0P z{!yByuh(n0+l@pb2!a3r0K+hbVKhx|Hk($f6_3Xa1_OVzNF++7Qn%afU(rumuh%}G zk7=S-t8uMPr(-gio&o7}T3|G*+wJCXH~;`ZQIsS}u64Owyk74EV7uME3!rJbTrM-$ ztJUh0HJi=;&WTx26cse3M=2BvX0uwYUdQPLgCUmt*#7wfZSN7!3a4#lKR20DKN8A~ilfw*UYD07*qoM6N<$g3cxgxBvhE literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/reply_type_group@3x.png b/Telegram/Resources/icons/chat/reply_type_group@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..11dd58c192309892ab77312c0e7a00e1f2f0db9f GIT binary patch literal 890 zcmV-=1BLvFP)wKYOvTkwIv6rA2s=bUikIjQc}VD#M1);C z1=%sWBxE86ftTnI)FF^UBIpn(Ds&5qZV?q)SYlH4N79OIIiC)}9J)<=x9UCkIXz?F z=l6Wr^X%C(iKIr28vhMet2Gb^q|<4FAQFj$&*$sx?ED)QjYhMxvjfT?NpfLfp{}m( zS8b$H>A}H4xeblm?fzAvxw$zW8vsB)pYQ4EDenkDP+wo4-EMceT;t>8EiEk~*vMqE zOeVuG1OV9G-7V>8G#ZbNj!NctX=w>T5J5r)gQ21g03e-CGkdkQwPmwe*5vl~wjd$1 z*<6hfNs`Q7{A*7bg~rna$?%yjrcky1HT&ayp$tZD=qIo0*yM`~AUSaARX* zVq!w6RC0yYYW2#>NbRT7EB=;&z0Q6SNL*-$E#9UUFb&CO?LXV=%)0DvDI?nkKV z2_Xp5-rla)>oE*NQ51rpTrQVNr7kZo&(F_aUtfPi2!>&k$uu}PXt7v&dwb<_Icx0W zn6}J@}$GKw6b8S)R{{CKcAyD17f*=SMA&0{uuFdW3Z7!FiFB=;hxssck zn{>PQkGHuo#*Q{ByVRb=q@o#=+^Za`*(~_Dtx3siu*c8aX&VGDj z^6`KF|NsB}{r#3LCUf$Vl9Dc6zC3x#l$HWXNl8T>F^;7R7Ya&AW##7TDk^?_d3m{Z z_`00CyGn0w%jIB}l9vAe=jUg6W*Pgs7zYQ2RWH83zdu7uLBYgCBgTe~DWM4faz$S! literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/reply_type_user@2x.png b/Telegram/Resources/icons/chat/reply_type_user@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef54da954090e36d0c4c93727f71a01ffd9b261 GIT binary patch literal 416 zcmV;R0bl-!P)F0pLHs353wHtmE;B zF%H9UwOVz%U1o*jxZQ3?zUOke2!g-{nWjnFve|6dAm8^}A%swCKcqo}!GNhwg-)jv zQ=OX8XoN9t+^a0h$z;L?0RU#RSrkRJa=+gfiv_Kj``HpjQPVV4Rd2W3e!owWgn1m+ zP$wD=hq|th$75NRJDm>3IEte4`5Xkn>jQ0pTigyeaCI2@MC zWv|x*0EnX4BzT^;ZM!H68qr7`$MgBTWtR1N{UTAPD2nNH+Jw?HWrYYKp67jitQzX~ z`}BW8jU-7;=z6`r0cBbCx%j9{hGDp_E6eihN|Geo?e>l1|0GXvJYv0%C5}G;0000< KMNUMnLSTYX9=Kfq literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/chat/reply_type_user@3x.png b/Telegram/Resources/icons/chat/reply_type_user@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..67a947f36d87a651e119f5bd42f9f0dd0d3ececa GIT binary patch literal 554 zcmV+_0@eMAP)Kl|75XKoCF^V;aE^ECgAwvJosS6vWD3pp}KamG**& z7(uW~Z((O+Ay^24O+dllpr{~-1QW%85i~*ED}+1sh`S-%+~KQI4D)7ob~6<9;ltk~ zolXx116h_eOOdaYKo+wH_m48u$&li#Lq>h(G?S-D(( zV}cM~uh&E(LBPbatfDCIWe~z%uSY-@iA0bl2%#*?$W%6DgvaB-sR<_xEfYl%M}`xI zmd)q$)oO(d8xDs!HK9qRQtt zu~;ONN!%o+lmLKiHXDsb-EOxeNu$xI)9IYgXVbO+H*k;9;c$dPpc9f*r*J{^!t4)nnwgdU|H5sR;^Y^neOmBZz!A1 zW@KeAtKjMCLkO`3YX+CgrK;-v8@*yILeoF}Jjopg9^TaM$b=lSr$7yZvKCDqe*xc~qF07*qoM6N<$g1RR1%m4rY literal 0 HcmV?d00001 diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp index 54b16fec6..88f6a0785 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.cpp @@ -89,6 +89,10 @@ private: : FrameSizeFromTag(tag); } +[[nodiscard]] QString InternalPrefix() { + return u"internal:"_q; +} + } // namespace class CustomEmojiLoader final @@ -514,6 +518,9 @@ std::unique_ptr CustomEmojiManager::create( Fn update, SizeTag tag, int sizeOverride) { + if (data.startsWith(InternalPrefix())) { + return internal(data); + } const auto parsed = ParseCustomEmojiData(data); return parsed ? create(parsed, std::move(update), tag, sizeOverride) @@ -540,6 +547,18 @@ std::unique_ptr CustomEmojiManager::create( }); } +std::unique_ptr CustomEmojiManager::internal( + QStringView data) { + const auto index = data.mid(InternalPrefix().size()).toInt(); + Assert(index >= 0 && index < _internalEmoji.size()); + + auto &info = _internalEmoji[index]; + return std::make_unique( + data.toString(), + info.image, + info.textColor); +} + void CustomEmojiManager::resolve( QStringView data, not_null listener) { @@ -885,6 +904,34 @@ uint64 CustomEmojiManager::coloredSetId() const { return _coloredSetId; } +QString CustomEmojiManager::registerInternalEmoji( + QImage emoji, + bool textColor) { + _internalEmoji.push_back({ std::move(emoji), textColor }); + return InternalPrefix() + QString::number(_internalEmoji.size() - 1); +} + +QString CustomEmojiManager::registerInternalEmoji( + const style::icon &icon, + bool textColor) { + const auto i = _iconEmoji.find(&icon); + if (i != end(_iconEmoji)) { + return i->second; + } + auto image = QImage( + icon.size() * style::DevicePixelRatio(), + QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::transparent); + image.setDevicePixelRatio(style::DevicePixelRatio()); + auto p = QPainter(&image); + icon.paint(p, 0, 0, icon.width()); + p.end(); + + const auto result = registerInternalEmoji(std::move(image), textColor); + _iconEmoji.emplace(&icon, result); + return result; +} + int FrameSizeFromTag(SizeTag tag) { const auto emoji = EmojiSizeFromTag(tag); const auto factor = style::DevicePixelRatio(); diff --git a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h index 4c79f8870..01eb1fd79 100644 --- a/Telegram/SourceFiles/data/stickers/data_custom_emoji.h +++ b/Telegram/SourceFiles/data/stickers/data_custom_emoji.h @@ -83,11 +83,22 @@ public: [[nodiscard]] Main::Session &session() const; [[nodiscard]] Session &owner() const; + [[nodiscard]] QString registerInternalEmoji( + QImage emoji, + bool textColor = true); + [[nodiscard]] QString registerInternalEmoji( + const style::icon &icon, + bool textColor = true); + [[nodiscard]] uint64 coloredSetId() const; private: static constexpr auto kSizeCount = int(SizeTag::kCount); + struct InternalEmojiData { + QImage image; + bool textColor = true; + }; struct RepaintBunch { crl::time when = 0; std::vector> instances; @@ -131,6 +142,8 @@ private: SizeTag tag, int sizeOverride, LoaderFactory factory); + [[nodiscard]] std::unique_ptr internal( + QStringView data); [[nodiscard]] static int SizeIndex(SizeTag tag); const not_null _owner; @@ -163,6 +176,9 @@ private: bool _repaintTimerScheduled = false; bool _requestSetsScheduled = false; + std::vector _internalEmoji; + base::flat_map, QString> _iconEmoji; + #if 0 // inject-to-on_main crl::time _repaintsLastAdded = 0; rpl::lifetime _repaintsLifetime; diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index 5dfadd9f6..e331703ae 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -477,7 +477,6 @@ HistoryMessageReply &HistoryMessageReply::operator=( HistoryMessageReply::~HistoryMessageReply() { // clearData() should be called by holder. Expects(resolvedMessage.empty()); - Expects(originalVia == nullptr); } bool HistoryMessageReply::updateData( @@ -523,44 +522,42 @@ bool HistoryMessageReply::updateData( } } + const auto repaint = [=] { holder->customEmojiRepaint(); }; + const auto context = Core::MarkedTextContext{ + .session = &holder->history()->session(), + .customEmojiRepaint = repaint, + }; const auto external = this->external(); - if (resolvedMessage + _multiline = 0; + // #TODO !_fields.storyId && (external || !_fields.quote.empty()); + + const auto displaying = resolvedMessage || resolvedStory - || (external && (!_fields.messageId || force))) { - const auto repaint = [=] { holder->customEmojiRepaint(); }; - const auto context = Core::MarkedTextContext{ - .session = &holder->history()->session(), - .customEmojiRepaint = repaint, - }; - const auto text = !_fields.quote.empty() - ? _fields.quote - : resolvedMessage - ? resolvedMessage->inReplyText() - : resolvedStory - ? resolvedStory->inReplyText() - : TextWithEntities{ u"..."_q }; - _text.setMarkedText( - st::defaultTextStyle, - text, - Ui::DialogTextOptions(), - context); + || (external && (!_fields.messageId || force)); + _displaying = displaying ? 1 : 0; - updateName(holder); + const auto unavailable = !resolvedMessage + && !resolvedStory + && ((!_fields.storyId && !_fields.messageId) || force); + _unavailable = unavailable ? 1 : 0; + + const auto text = !_fields.quote.empty() + ? _fields.quote + : resolvedMessage + ? resolvedMessage->inReplyText() + : resolvedStory + ? resolvedStory->inReplyText() + : TextWithEntities{ u"..."_q }; + _text.setMarkedText( + st::defaultTextStyle, + text, + Ui::DialogTextOptions(), + context); + + updateName(holder); + + if (_displaying) { setLinkFrom(holder); - if (resolvedMessage - && !resolvedMessage->Has()) { - if (const auto bot = resolvedMessage->viaBot()) { - originalVia = std::make_unique(); - originalVia->create( - &holder->history()->owner(), - peerToUser(bot->id)); - } - } - - if (!resolvedMessage && !resolvedStory) { - _unavailable = 1; - } - const auto media = resolvedMessage ? resolvedMessage->media() : nullptr; @@ -642,7 +639,6 @@ void HistoryMessageReply::setTopMessageId(MsgId topMessageId) { } void HistoryMessageReply::clearData(not_null holder) { - originalVia = nullptr; if (resolvedMessage) { holder->history()->owner().unregisterDependentMessage( holder, @@ -658,6 +654,12 @@ void HistoryMessageReply::clearData(not_null holder) { _name.clear(); _text.clear(); _unavailable = 1; + _displaying = 0; + _expandable = 0; + if (_multiline) { + holder->history()->owner().requestItemResize(holder); + _multiline = 0; + } refreshReplyToMedia(); } @@ -691,9 +693,10 @@ PeerData *HistoryMessageReply::sender(not_null holder) const { } QString HistoryMessageReply::senderName( - not_null holder) const { + not_null holder, + bool shorten) const { if (const auto peer = sender(holder)) { - return senderName(peer); + return senderName(peer, shorten); } else if (!resolvedMessage) { return _fields.externalSenderName; } else if (holder->Has()) { @@ -708,11 +711,11 @@ QString HistoryMessageReply::senderName( return QString(); } -QString HistoryMessageReply::senderName(not_null peer) const { - if (const auto user = originalVia ? peer->asUser() : nullptr) { - return user->firstName; - } - return peer->name(); +QString HistoryMessageReply::senderName( + not_null peer, + bool shorten) const { + const auto user = shorten ? peer->asUser() : nullptr; + return user ? user->firstName : peer->name(); } bool HistoryMessageReply::isNameUpdated( @@ -729,47 +732,101 @@ bool HistoryMessageReply::isNameUpdated( void HistoryMessageReply::updateName( not_null holder, std::optional resolvedSender) const { - const auto peer = resolvedSender.value_or(sender(holder)); - const auto name = peer ? senderName(peer) : senderName(holder); + auto viaBotUsername = QString(); + if (resolvedMessage + && !resolvedMessage->Has()) { + if (const auto bot = resolvedMessage->viaBot()) { + viaBotUsername = bot->username(); + } + } + const auto sender = resolvedSender.value_or(this->sender(holder)); + const auto externalPeer = _fields.externalPeerId + ? holder->history()->owner().peer(_fields.externalPeerId).get() + : nullptr; + const auto groupNameAdded = (externalPeer && externalPeer != sender); + const auto shorten = !viaBotUsername.isEmpty() || groupNameAdded; + const auto name = sender + ? senderName(sender, shorten) + : senderName(holder, shorten); const auto hasPreview = (resolvedStory && resolvedStory->hasReplyPreview()) || (resolvedMessage && resolvedMessage->media() && resolvedMessage->media()->hasReplyPreview()); - const auto textLeft = hasPreview - ? (st::messageQuoteStyle.outline - + st::historyReplyPreviewMargin.left() - + st::historyReplyPreview - + st::historyReplyPreviewMargin.right()) - : st::historyReplyPadding.left(); - if (!name.isEmpty()) { - _name.setText(st::fwdTextStyle, name, Ui::NameTextOptions()); - if (peer) { - _nameVersion = peer->nameVersion(); - } - const auto w = _name.maxWidth() - + (originalVia - ? (st::msgServiceFont->spacew + originalVia->maxWidth) - : 0) - + (_fields.quote.empty() - ? 0 - : st::messageTextStyle.blockquote.icon.width()); - _maxWidth = std::max( - w, - std::min(_text.maxWidth(), st::maxSignatureSize)) - + (_fields.storyId - ? (st::dialogsMiniReplyStory.skipText - + st::dialogsMiniReplyStory.icon.icon.width()) - : 0); - } else { - _maxWidth = st::msgDateFont->width(statePhrase()); + const auto previewSkip = st::messageQuoteStyle.outline + + st::historyReplyPreviewMargin.left() + + st::historyReplyPreview + + st::historyReplyPreviewMargin.right() + - st::historyReplyPadding.left(); + const auto peerIcon = [](PeerData *peer) { + return !peer + ? &st::historyReplyUser + : peer->isBroadcast() + ? &st::historyReplyChannel + : (peer->isChannel() || peer->isChat()) + ? &st::historyReplyGroup + : &st::historyReplyUser; + }; + const auto peerEmoji = [&](PeerData *peer) { + const auto owner = &holder->history()->owner(); + return Ui::Text::SingleCustomEmoji( + owner->customEmojiManager().registerInternalEmoji( + *peerIcon(peer))); + }; + auto nameFull = TextWithEntities(); + if (!groupNameAdded && !_fields.storyId) { + nameFull.append(peerEmoji(sender)); } - _maxWidth = textLeft + nameFull.append(name); + if (groupNameAdded) { + nameFull.append(peerEmoji(externalPeer)); + nameFull.append(externalPeer->name()); + } + if (!viaBotUsername.isEmpty()) { + nameFull.append(u" @"_q).append(viaBotUsername); + } + const auto context = Core::MarkedTextContext{ + .session = &holder->history()->session(), + .customEmojiRepaint = [] {}, + .customEmojiLoopLimit = 1, + }; + _name.setMarkedText( + st::fwdTextStyle, + nameFull, + Ui::NameTextOptions(), + context); + if (sender) { + _nameVersion = sender->nameVersion(); + } + const auto nameMaxWidth = previewSkip + + _name.maxWidth() + + (hasQuoteIcon() + ? st::messageTextStyle.blockquote.icon.width() + : 0); + const auto storySkip = _fields.storyId + ? (st::dialogsMiniReplyStory.skipText + + st::dialogsMiniReplyStory.icon.icon.width()) + : 0; + const auto optimalTextSize = _multiline + ? countMultilineOptimalSize(previewSkip) + : QSize( + (previewSkip + + storySkip + + std::min(_text.maxWidth(), st::maxSignatureSize)), + st::normalFont->height); + _maxWidth = std::max(nameMaxWidth, optimalTextSize.width()); + if (!_displaying) { + const auto phraseWidth = st::msgDateFont->width(statePhrase()); + _maxWidth = _unavailable + ? phraseWidth + : std::max(_maxWidth, phraseWidth); + } + _maxWidth = st::historyReplyPadding.left() + _maxWidth + st::historyReplyPadding.right(); _minHeight = st::historyReplyPadding.top() + st::msgServiceNameFont->height - + st::normalFont->height + + optimalTextSize.height() + st::historyReplyPadding.bottom(); } @@ -785,17 +842,11 @@ int HistoryMessageReply::resizeToWidth(int width) const { + st::historyReplyPreview + st::historyReplyPreviewMargin.right()) : st::historyReplyPadding.left(); - if (originalVia) { - originalVia->resize(width - - textLeft - - st::historyReplyPadding.right() - - _name.maxWidth() - - st::msgServiceFont->spacew); - } - if (width >= _maxWidth) { + if (width >= _maxWidth || !_multiline) { _height = _minHeight; return height(); } + // #TODO _height = _minHeight; return height(); } @@ -826,6 +877,15 @@ void HistoryMessageReply::storyRemoved( } } +bool HistoryMessageReply::hasQuoteIcon() const { + return _fields.manualQuote && !_fields.quote.empty(); +} + +QSize HistoryMessageReply::countMultilineOptimalSize( + int firstLineSkip) const { + return QSize(); // #TODO +} + void HistoryMessageReply::paint( Painter &p, not_null holder, @@ -839,7 +899,7 @@ void HistoryMessageReply::paint( y += st::historyReplyTop; const auto rect = QRect(x, y, w, _height); - const auto hasQuote = _fields.manualQuote && !_fields.quote.empty(); + const auto hasQuote = hasQuoteIcon(); const auto selected = context.selected(); const auto colorPeer = resolvedMessage ? resolvedMessage->displayFrom() @@ -969,10 +1029,6 @@ void HistoryMessageReply::paint( ? FromNameFg(context, colorIndexPlusOne - 1) : stm->msgServiceFg->c); _name.drawLeftElided(p, x + textLeft, y + st::historyReplyPadding.top(), w, w + 2 * x + 2 * textLeft); - if (originalVia && w > _name.maxWidth() + st::msgServiceFont->spacew) { - p.setFont(st::msgServiceFont); - p.drawText(x + textLeft + _name.maxWidth() + st::msgServiceFont->spacew, y + st::historyReplyPadding.top() + st::msgServiceFont->ascent, originalVia->text); - } p.setPen(inBubble ? stm->historyTextFg diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index c250e91fb..55c4e149b 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -276,8 +276,12 @@ struct HistoryMessageReply [[nodiscard]] bool external() const; [[nodiscard]] PeerData *sender(not_null holder) const; - [[nodiscard]] QString senderName(not_null holder) const; - [[nodiscard]] QString senderName(not_null peer) const; + [[nodiscard]] QString senderName( + not_null holder, + bool shorten) const; + [[nodiscard]] QString senderName( + not_null peer, + bool shorten) const; [[nodiscard]] bool isNameUpdated(not_null holder) const; void updateName( not_null holder, @@ -340,7 +344,6 @@ struct HistoryMessageReply WebPageId replyToWebPageId = 0; ReplyToMessagePointer resolvedMessage; ReplyToStoryPointer resolvedStory; - std::unique_ptr originalVia; std::unique_ptr spoiler; struct { @@ -349,6 +352,10 @@ struct HistoryMessageReply } ripple; private: + [[nodiscard]] bool hasQuoteIcon() const; + [[nodiscard]] QSize countMultilineOptimalSize( + int firstLineSkip) const; + ReplyFields _fields; ClickHandlerPtr _link; mutable Ui::Text::String _name; @@ -359,6 +366,9 @@ private: mutable int _height = 0; mutable int _nameVersion = 0; uint8 _unavailable : 1 = 0; + uint8 _displaying : 1 = 0; + uint8 _multiline : 1 = 0; + uint8 _expandable : 1 = 0; }; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index f5a6d655d..833702101 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -771,13 +771,9 @@ QSize Message::performCountOptimalSize() { accumulate_max(maxWidth, namew); } if (reply) { - auto replyw = st::msgPadding.left() + const auto replyw = st::msgPadding.left() + reply->maxWidth() + st::msgPadding.right(); - if (reply->originalVia) { - replyw += st::msgServiceFont->spacew - + reply->originalVia->maxWidth; - } accumulate_max(maxWidth, replyw); } if (entry) { diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 70018cad1..d4f189ac0 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -32,6 +32,12 @@ historyReplyBottom: 2px; historyReplyPreview: 32px; historyReplyPreviewMargin: margins(7px, 4px, 4px, 4px); historyReplyPadding: margins(11px, 2px, 6px, 2px); +historyReplyUser: icon {{ "chat/reply_type_user", windowFg }}; +historyReplyUserPadding: margins(0px, 4px, 4px, 0px); +historyReplyGroup: icon {{ "chat/reply_type_group", windowFg }}; +historyReplyGroupPadding: margins(0px, 4px, 4px, 0px); +historyReplyChannel: icon {{ "chat/reply_type_channel", windowFg }}; +historyReplyChannelPadding: margins(0px, 5px, 4px, 0px); msgReplyPadding: margins(6px, 6px, 11px, 6px); msgReplyBarPos: point(1px, 0px);