From 8c21fad64265cd157f17cbebd2bce95520ff16dc Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 Oct 2021 16:42:44 +0400 Subject: [PATCH] Move preview paint to Dialogs::Ui::MessageView. --- Telegram/CMakeLists.txt | 2 + Telegram/SourceFiles/data/data_changes.h | 2 +- .../SourceFiles/data/data_media_types.cpp | 42 +++++++---- Telegram/SourceFiles/data/data_media_types.h | 16 ++-- Telegram/SourceFiles/data/data_session.cpp | 4 + Telegram/SourceFiles/dialogs/dialogs.style | 3 + .../SourceFiles/dialogs/dialogs_entry.cpp | 3 +- Telegram/SourceFiles/dialogs/dialogs_entry.h | 5 +- .../dialogs/dialogs_inner_widget.cpp | 21 +----- Telegram/SourceFiles/dialogs/dialogs_row.cpp | 3 +- Telegram/SourceFiles/dialogs/dialogs_row.h | 10 +-- .../SourceFiles/dialogs/ui/dialogs_layout.cpp | 20 +++-- .../dialogs/ui/dialogs_message_view.cpp | 69 +++++++++++++++++ .../dialogs/ui/dialogs_message_view.h | 51 +++++++++++++ Telegram/SourceFiles/history/history.h | 2 + Telegram/SourceFiles/history/history_item.cpp | 75 ++++++++----------- Telegram/SourceFiles/history/history_item.h | 36 +++++---- .../SourceFiles/history/history_service.cpp | 28 +++---- .../SourceFiles/history/history_service.h | 2 +- .../SourceFiles/history/history_widget.cpp | 13 +++- .../window/notifications_manager_default.cpp | 9 ++- 21 files changed, 265 insertions(+), 151 deletions(-) create mode 100644 Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp create mode 100644 Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index e9819919c..a3ca3af67 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -484,6 +484,8 @@ PRIVATE dialogs/dialogs_widget.h dialogs/ui/dialogs_layout.cpp dialogs/ui/dialogs_layout.h + dialogs/ui/dialogs_message_view.cpp + dialogs/ui/dialogs_message_view.h editor/color_picker.cpp editor/color_picker.h editor/controllers/controllers.h diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 6694507c0..0284dc8df 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -148,7 +148,7 @@ struct MessageUpdate { NewMaybeAdded = (1U << 7), RepliesUnreadCount = (1U << 8), - LastUsedBit = (1U << 7), + LastUsedBit = (1U << 8), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; } diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index d76c8601a..942dc6b26 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -55,6 +55,8 @@ namespace { constexpr auto kFastRevokeRestriction = 24 * 60 * TimeId(60); +using ItemPreview = HistoryView::ItemPreview; + [[nodiscard]] Call ComputeCallData(const MTPDmessageActionPhoneCall &call) { auto result = Call(); result.finishReason = [&] { @@ -201,11 +203,12 @@ bool Media::canBeGrouped() const { return false; } -QString Media::chatListText(DrawInDialog way) const { +ItemPreview Media::toPreview(ToPreviewOptions options) const { auto result = notificationText(); - return result.isEmpty() + auto text = result.isEmpty() ? QString() : textcmdLink(1, TextUtilities::Clean(std::move(result))); + return { .text = std::move(text) }; } bool Media::hasReplyPreview() const { @@ -341,11 +344,16 @@ QString MediaPhoto::notificationText() const { parent()->originalText().text); } -QString MediaPhoto::chatListText(DrawInDialog way) const { - const auto caption = (way == DrawInDialog::WithoutSenderAndCaption) +ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const { + const auto caption = options.hideCaption ? QString() : parent()->originalText().text; - return WithCaptionDialogsText(tr::lng_in_dlg_photo(tr::now), caption); + // #TODO minis generate images and support albums + return { + .text = WithCaptionDialogsText( + tr::lng_in_dlg_photo(tr::now), + caption) + }; } QString MediaPhoto::pinnedTextSubstring() const { @@ -511,16 +519,16 @@ bool MediaFile::replyPreviewLoaded() const { return _document->replyPreviewLoaded(); } -QString MediaFile::chatListText(DrawInDialog way) const { +ItemPreview MediaFile::toPreview(ToPreviewOptions options) const { if (const auto sticker = _document->sticker()) { - return Media::chatListText(way); + return Media::toPreview(options); } const auto type = [&] { using namespace Ui::Text; if (_document->isVideoMessage()) { return tr::lng_in_dlg_video_message(tr::now); } else if (_document->isAnimation()) { - return qsl("GIF"); + return u"GIF"_q; } else if (_document->isVideoFile()) { return tr::lng_in_dlg_video(tr::now); } else if (_document->isVoiceMessage()) { @@ -533,10 +541,13 @@ QString MediaFile::chatListText(DrawInDialog way) const { } return tr::lng_in_dlg_file(tr::now); }(); - const auto caption = (way == DrawInDialog::WithoutSenderAndCaption) + const auto caption = options.hideCaption ? QString() : parent()->originalText().text; - return WithCaptionDialogsText(type, caption); + // #TODO minis generate images and support albums + return { + .text = WithCaptionDialogsText(type, caption), + }; } QString MediaFile::notificationText() const { @@ -855,8 +866,11 @@ Data::CloudImage *MediaLocation::location() const { return _location; } -QString MediaLocation::chatListText(DrawInDialog way) const { - return WithCaptionDialogsText(tr::lng_maps_point(tr::now), _title); +ItemPreview MediaLocation::toPreview(ToPreviewOptions options) const { + // #TODO minis generate images + return { + .text = WithCaptionDialogsText(tr::lng_maps_point(tr::now), _title), + }; } QString MediaLocation::notificationText() const { @@ -1049,8 +1063,8 @@ bool MediaWebPage::replyPreviewLoaded() const { return true; } -QString MediaWebPage::chatListText(DrawInDialog way) const { - return notificationText(); +ItemPreview MediaWebPage::toPreview(ToPreviewOptions options) const { + return { .text = notificationText() }; } QString MediaWebPage::notificationText() const { diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index 49cbfffa4..da7a212f6 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -27,7 +27,8 @@ namespace HistoryView { enum class Context : char; class Element; class Media; -enum class DrawInDialog; +struct ItemPreview; +struct ToPreviewOptions; } // namespace HistoryView namespace Data { @@ -73,7 +74,8 @@ public: not_null parent() const; - using DrawInDialog = HistoryView::DrawInDialog; + using ToPreviewOptions = HistoryView::ToPreviewOptions; + using ItemPreview = HistoryView::ItemPreview; virtual std::unique_ptr clone(not_null parent) = 0; @@ -95,7 +97,7 @@ public: virtual bool replyPreviewLoaded() const; // Returns text with link-start and link-end commands for service-color highlighting. // Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text" - virtual QString chatListText(DrawInDialog way) const; + virtual ItemPreview toPreview(ToPreviewOptions way) const; virtual QString notificationText() const = 0; virtual QString pinnedTextSubstring() const = 0; virtual TextForMimeData clipboardText() const = 0; @@ -151,7 +153,7 @@ public: bool hasReplyPreview() const override; Image *replyPreview() const override; bool replyPreviewLoaded() const override; - QString chatListText(DrawInDialog way) const override; + ItemPreview toPreview(ToPreviewOptions options) const override; QString notificationText() const override; QString pinnedTextSubstring() const override; TextForMimeData clipboardText() const override; @@ -189,7 +191,7 @@ public: bool hasReplyPreview() const override; Image *replyPreview() const override; bool replyPreviewLoaded() const override; - QString chatListText(DrawInDialog way) const override; + ItemPreview toPreview(ToPreviewOptions options) const override; QString notificationText() const override; QString pinnedTextSubstring() const override; TextForMimeData clipboardText() const override; @@ -255,7 +257,7 @@ public: std::unique_ptr clone(not_null parent) override; Data::CloudImage *location() const override; - QString chatListText(DrawInDialog way) const override; + ItemPreview toPreview(ToPreviewOptions options) const override; QString notificationText() const override; QString pinnedTextSubstring() const override; TextForMimeData clipboardText() const override; @@ -323,7 +325,7 @@ public: bool hasReplyPreview() const override; Image *replyPreview() const override; bool replyPreviewLoaded() const override; - QString chatListText(DrawInDialog way) const override; + ItemPreview toPreview(ToPreviewOptions options) const override; QString notificationText() const override; QString pinnedTextSubstring() const override; TextForMimeData clipboardText() const override; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 5a709b7b8..27ab05f30 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -1382,6 +1382,10 @@ void Session::requestItemRepaint(not_null item) { } } } + const auto history = item->history(); + if (history->lastItemDialogsView.dependsOn(item)) { + history->updateChatListEntry(); + } } rpl::producer> Session::itemRepaintRequest() const { diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index e71c779a4..1312cb3ca 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -296,3 +296,6 @@ dialogsScamFont: font(9px semibold); dialogsScamSkip: 4px; dialogsScamRadius: 2px; +dialogsMiniPreview: 32px; +dialogsMiniPreviewSkip: 4px; +dialogsMiniPreviewRight: 6px; diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp index dff0aa1ac..1cf2615f3 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.cpp @@ -43,8 +43,7 @@ uint64 PinnedDialogPos(int pinnedIndex) { } // namespace Entry::Entry(not_null owner, Type type) -: lastItemTextCache(st::dialogsTextWidthMin) -, _owner(owner) +: _owner(owner) , _isFolder(type == Type::Folder) { } diff --git a/Telegram/SourceFiles/dialogs/dialogs_entry.h b/Telegram/SourceFiles/dialogs/dialogs_entry.h index 672d7d505..bb4bba3db 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_entry.h +++ b/Telegram/SourceFiles/dialogs/dialogs_entry.h @@ -183,13 +183,10 @@ public: paintUserpic(p, view, rtl() ? (w - x - size) : x, y, size); } - TimeId chatListTimeId() const { + [[nodiscard]] TimeId chatListTimeId() const { return _timeId; } - mutable const HistoryItem *textCachedFor = nullptr; // cache - mutable Ui::Text::String lastItemTextCache; - protected: void notifyUnreadStateChange(const UnreadState &wasState); auto unreadStateChangeNotifier(bool required) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 5a6ab3543..e786a7a59 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -154,14 +154,6 @@ InnerWidget::InnerWidget( dialogRowReplaced(r.old, r.now); }, lifetime()); - session().data().itemRepaintRequest( - ) | rpl::start_with_next([=](auto item) { - const auto history = item->history(); - if (history->textCachedFor == item) { - history->updateChatListEntry(); - } - }, lifetime()); - session().data().sendActionManager().animationUpdated( ) | rpl::start_with_next([=]( const Data::SendActionManager::AnimationUpdate &update) { @@ -235,16 +227,9 @@ InnerWidget::InnerWidget( }, lifetime()); session().changes().messageUpdates( - Data::MessageUpdate::Flag::DialogRowRepaint - | Data::MessageUpdate::Flag::DialogRowRefresh + Data::MessageUpdate::Flag::DialogRowRefresh ) | rpl::start_with_next([=](const Data::MessageUpdate &update) { - const auto item = update.item; - if (update.flags & Data::MessageUpdate::Flag::DialogRowRefresh) { - refreshDialogRow({ item->history(), item->fullId() }); - } - if (update.flags & Data::MessageUpdate::Flag::DialogRowRepaint) { - repaintDialogRow({ item->history(), item->fullId() }); - } + refreshDialogRow({ update.item->history(), update.item->fullId() }); }, lifetime()); session().changes().entryUpdates( @@ -1530,7 +1515,7 @@ void InnerWidget::refreshDialogRow(RowDescriptor row) { if (row.fullId) { for (const auto &result : _searchResults) { if (result->item()->fullId() == row.fullId) { - result->invalidateCache(); + result->itemView().itemInvalidated(result->item()); } } } diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.cpp b/Telegram/SourceFiles/dialogs/dialogs_row.cpp index 372f2e619..2e7412044 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_row.cpp @@ -285,8 +285,7 @@ void Row::validateListEntryCache() const { FakeRow::FakeRow(Key searchInChat, not_null item) : _searchInChat(searchInChat) -, _item(item) -, _cache(st::dialogsTextWidthMin) { +, _item(item) { } } // namespace Dialogs \ No newline at end of file diff --git a/Telegram/SourceFiles/dialogs/dialogs_row.h b/Telegram/SourceFiles/dialogs/dialogs_row.h index 1fe7a0ef0..21e45a14c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_row.h +++ b/Telegram/SourceFiles/dialogs/dialogs_row.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text.h" #include "ui/effects/animations.h" #include "dialogs/dialogs_key.h" +#include "dialogs/ui/dialogs_message_view.h" class History; class HistoryItem; @@ -138,10 +139,8 @@ public: [[nodiscard]] not_null item() const { return _item; } - - void invalidateCache() { - _cacheFor = nullptr; - _cache = Ui::Text::String(); + [[nodiscard]] Ui::MessageView &itemView() const { + return _itemView; } private: @@ -149,8 +148,7 @@ private: Key _searchInChat; not_null _item; - mutable const HistoryItem *_cacheFor = nullptr; - mutable Ui::Text::String _cache; + mutable Ui::MessageView _itemView; }; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index 6182cf0a5..759492bc1 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -775,14 +775,13 @@ void RowPainter::paint( if (const auto folder = row->folder()) { PaintListEntryText(p, itemRect, active, selected, row); } else if (history && !actionWasPainted) { - item->drawInDialog( + history->lastItemDialogsView.paint( p, + item, itemRect, active, selected, - HistoryItem::DrawInDialog::Normal, - history->textCachedFor, - history->lastItemTextCache); + {}); } }; const auto paintCounterCallback = [&] { @@ -845,15 +844,15 @@ void RowPainter::paint( } return nullptr; }(); - const auto drawInDialogWay = [&] { + const auto previewOptions = [&]() -> HistoryView::ToPreviewOptions { if (const auto searchChat = row->searchInChat()) { if (const auto peer = searchChat.peer()) { if (!peer->isChannel() || peer->isMegagroup()) { - return HistoryItem::DrawInDialog::WithoutSender; + return { .hideSender = true }; } } } - return HistoryItem::DrawInDialog::Normal; + return {}; }(); const auto unreadCount = displayUnreadInfo @@ -895,14 +894,13 @@ void RowPainter::paint( texttop, availableWidth, st::dialogsTextFont->height); - item->drawInDialog( + row->itemView().paint( p, + item, itemRect, active, selected, - drawInDialogWay, - row->_cacheFor, - row->_cache); + previewOptions); }; const auto paintCounterCallback = [&] { PaintNarrowCounter( diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp new file mode 100644 index 000000000..176f83d87 --- /dev/null +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp @@ -0,0 +1,69 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "dialogs/ui/dialogs_message_view.h" + +#include "history/history_item.h" +#include "ui/text/text_options.h" +#include "styles/style_dialogs.h" + +namespace Dialogs::Ui { +namespace { + +} // namespace + +MessageView::MessageView() +: _textCache(st::dialogsTextWidthMin) { +} + +MessageView::~MessageView() = default; + +void MessageView::itemInvalidated(not_null item) { + if (_textCachedFor == item.get()) { + _textCachedFor = nullptr; + } +} + +bool MessageView::dependsOn(not_null item) const { + return (_textCachedFor == item.get()); +} + +void MessageView::paint( + Painter &p, + not_null item, + const QRect &geometry, + bool active, + bool selected, + ToPreviewOptions options) const { + if (geometry.isEmpty()) { + return; + } + if (_textCachedFor != item.get()) { + const auto preview = item->toPreview(options); + _textCache.setText( + st::dialogsTextStyle, + preview.text, + DialogTextOptions()); + _textCachedFor = item; + } + p.setTextPalette(active + ? st::dialogsTextPaletteActive + : selected + ? st::dialogsTextPaletteOver + : st::dialogsTextPalette); + p.setFont(st::dialogsTextFont); + p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg)); + _textCache.drawElided( + p, + geometry.left(), + geometry.top(), + geometry.width(), + geometry.height() / st::dialogsTextFont->height); + p.restoreTextPalette(); +} + +} // namespace Dialogs::Ui diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h new file mode 100644 index 000000000..a365cea1b --- /dev/null +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h @@ -0,0 +1,51 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +class HistoryItem; + +namespace Ui { + +} // namespace Ui + +namespace HistoryView { +struct ToPreviewOptions; +struct ItemPreview; +} // namespace HistoryView + +namespace Dialogs::Ui { + +using namespace ::Ui; + +class MessageView final { +public: + MessageView(); + ~MessageView(); + + using ToPreviewOptions = HistoryView::ToPreviewOptions; + using ItemPreview = HistoryView::ItemPreview; + + void itemInvalidated(not_null item); + [[nodiscard]] bool dependsOn(not_null item) const; + + void paint( + Painter &p, + not_null item, + const QRect &geometry, + bool active, + bool selected, + ToPreviewOptions options) const; + +private: + mutable const HistoryItem *_textCachedFor = nullptr; + mutable Ui::Text::String _textCache; + mutable std::vector _imagesCache; + +}; + +} // namespace Dialogs::Ui diff --git a/Telegram/SourceFiles/history/history.h b/Telegram/SourceFiles/history/history.h index 77f054504..033608c75 100644 --- a/Telegram/SourceFiles/history/history.h +++ b/Telegram/SourceFiles/history/history.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_peer.h" #include "data/data_drafts.h" #include "dialogs/dialogs_entry.h" +#include "dialogs/ui/dialogs_message_view.h" #include "history/view/history_view_send_action.h" #include "base/observer.h" #include "base/timer.h" @@ -457,6 +458,7 @@ public: mtpRequestId sendRequestId = 0; Ui::Text::String cloudDraftTextCache; + Dialogs::Ui::MessageView lastItemDialogsView; private: friend class HistoryBlock; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 553b1ae09..f3a6a3be0 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -49,6 +49,8 @@ namespace { constexpr auto kNotificationTextLimit = 255; +using ItemPreview = HistoryView::ItemPreview; + enum class MediaCheckResult { Good, Unsupported, @@ -292,17 +294,7 @@ void HistoryItem::invalidateChatListEntry() { history()->session().changes().messageUpdated( this, Data::MessageUpdate::Flag::DialogRowRefresh); - - // invalidate cache for drawInDialog - if (history()->textCachedFor == this) { - history()->textCachedFor = nullptr; - } - //if (const auto feed = history()->peer->feed()) { // #TODO archive - // if (feed->textCachedFor == this) { - // feed->textCachedFor = nullptr; - // feed->updateChatListEntry(); - // } - //} + history()->lastItemDialogsView.itemInvalidated(this); } void HistoryItem::finishEditionToEmpty() { @@ -946,20 +938,25 @@ QString HistoryItem::notificationText() const { : result.mid(0, kNotificationTextLimit) + qsl("..."); } -QString HistoryItem::inDialogsText(DrawInDialog way) const { - const auto plainText = [&] { +ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const { + auto result = [&]() -> ItemPreview { if (_media) { if (_groupId) { - return textcmdLink(1, TextUtilities::Clean(tr::lng_in_dlg_album(tr::now))); + // #TODO minis generate albums correctly + return { + .text = textcmdLink( + 1, + TextUtilities::Clean(tr::lng_in_dlg_album(tr::now))), + }; } - return _media->chatListText(way); + return _media->toPreview(options); } else if (!emptyText()) { - return TextUtilities::Clean(_text.toString()); + return { .text = TextUtilities::Clean(_text.toString()) }; } - return QString(); + return {}; }(); const auto sender = [&]() -> PeerData* { - if (isPost() || isEmpty() || (way != DrawInDialog::Normal)) { + if (options.hideSender || isPost() || isEmpty()) { return nullptr; } else if (!_history->peer->isUser() || out()) { return displayFrom(); @@ -969,39 +966,29 @@ QString HistoryItem::inDialogsText(DrawInDialog way) const { return nullptr; }(); if (sender) { - auto fromText = sender->isSelf() ? tr::lng_from_you(tr::now) : sender->shortName(); - auto fromWrapped = textcmdLink(1, tr::lng_dialogs_text_from_wrapped(tr::now, lt_from, TextUtilities::Clean(fromText))); - return tr::lng_dialogs_text_with_from(tr::now, lt_from_part, fromWrapped, lt_message, plainText); + const auto fromText = sender->isSelf() + ? tr::lng_from_you(tr::now) + : sender->shortName(); + const auto fromWrapped = textcmdLink( + 1, + tr::lng_dialogs_text_from_wrapped( + tr::now, + lt_from, + TextUtilities::Clean(fromText))); + result.text = tr::lng_dialogs_text_with_from( + tr::now, + lt_from_part, + fromWrapped, + lt_message, + std::move(result.text)); } - return plainText; + return result; } Ui::Text::IsolatedEmoji HistoryItem::isolatedEmoji() const { return Ui::Text::IsolatedEmoji(); } -void HistoryItem::drawInDialog( - Painter &p, - const QRect &r, - bool active, - bool selected, - DrawInDialog way, - const HistoryItem *&cacheFor, - Ui::Text::String &cache) const { - if (r.isEmpty()) { - return; - } - if (cacheFor != this) { - cacheFor = this; - cache.setText(st::dialogsTextStyle, inDialogsText(way), Ui::DialogTextOptions()); - } - p.setTextPalette(active ? st::dialogsTextPaletteActive : (selected ? st::dialogsTextPaletteOver : st::dialogsTextPalette)); - p.setFont(st::dialogsTextFont); - p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg)); - cache.drawElided(p, r.left(), r.top(), r.width(), r.height() / st::dialogsTextFont->height); - p.restoreTextPalette(); -} - HistoryItem::~HistoryItem() { applyTTL(0); } diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index a15beb394..2568c1ad3 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -46,17 +46,25 @@ class SessionController; } // namespace Window namespace HistoryView { + struct TextState; struct StateRequest; enum class CursorState : char; enum class PointState : char; enum class Context : char; class ElementDelegate; -enum class DrawInDialog { - Normal, - WithoutSender, - WithoutSenderAndCaption, + +struct ToPreviewOptions { + bool hideSender = false; + bool hideCaption = false; + bool generateImages = true; }; + +struct ItemPreview { + QString text; + std::vector images; +}; + } // namespace HistoryView struct HiddenSenderInfo; @@ -298,13 +306,18 @@ public: } [[nodiscard]] virtual QString notificationText() const; - using DrawInDialog = HistoryView::DrawInDialog; + using ToPreviewOptions = HistoryView::ToPreviewOptions; + using ItemPreview = HistoryView::ItemPreview; // Returns text with link-start and link-end commands for service-color highlighting. // Example: "[link1-start]You:[link1-end] [link1-start]Photo,[link1-end] caption text" - [[nodiscard]] virtual QString inDialogsText(DrawInDialog way) const; + [[nodiscard]] virtual ItemPreview toPreview( + ToPreviewOptions options) const; [[nodiscard]] virtual QString inReplyText() const { - return inDialogsText(DrawInDialog::WithoutSender); + return toPreview({ + .hideSender = true, + .generateImages = false, + }).text; } [[nodiscard]] virtual Ui::Text::IsolatedEmoji isolatedEmoji() const; [[nodiscard]] virtual TextWithEntities originalText() const { @@ -335,15 +348,6 @@ public: virtual void incrementReplyToTopCounter() { } - void drawInDialog( - Painter &p, - const QRect &r, - bool active, - bool selected, - DrawInDialog way, - const HistoryItem *&cacheFor, - Ui::Text::String &cache) const; - [[nodiscard]] bool emptyText() const { return _text.isEmpty(); } diff --git a/Telegram/SourceFiles/history/history_service.cpp b/Telegram/SourceFiles/history/history_service.cpp index cf1a304d6..96e10eca7 100644 --- a/Telegram/SourceFiles/history/history_service.cpp +++ b/Telegram/SourceFiles/history/history_service.cpp @@ -43,6 +43,8 @@ namespace { constexpr auto kPinnedMessageTextLimit = 16; +using ItemPreview = HistoryView::ItemPreview; + [[nodiscard]] bool PeerCallKnown(not_null peer) { if (peer->groupCall() != nullptr) { return true; @@ -923,14 +925,18 @@ bool HistoryService::needCheck() const { return out() && !isEmpty(); } -QString HistoryService::inDialogsText(DrawInDialog way) const { - return textcmdLink(1, TextUtilities::Clean(notificationText())); +ItemPreview HistoryService::toPreview(ToPreviewOptions options) const { + // #TODO minis generate images + return { + .text = textcmdLink(1, TextUtilities::Clean(notificationText())), + }; } QString HistoryService::inReplyText() const { const auto result = HistoryService::notificationText(); - const auto text = result.trimmed().startsWith(author()->name) - ? result.trimmed().mid(author()->name.size()).trimmed() + const auto &name = author()->name; + const auto text = result.trimmed().startsWith(name) + ? result.trimmed().mid(name.size()).trimmed() : result; return textcmdLink(1, text); } @@ -1190,19 +1196,7 @@ void HistoryService::updateDependentText() { void HistoryService::updateText(PreparedText &&text) { setServiceText(text); history()->owner().requestItemResize(this); - const auto inDialogsHistory = history()->migrateToOrMe(); - if (inDialogsHistory->textCachedFor == this) { - inDialogsHistory->textCachedFor = nullptr; - } - //if (const auto feed = history()->peer->feed()) { // #TODO archive - // if (feed->textCachedFor == this) { - // feed->textCachedFor = nullptr; - // feed->updateChatListEntry(); - // } - //} - history()->session().changes().messageUpdated( - this, - Data::MessageUpdate::Flag::DialogRowRepaint); + invalidateChatListEntry(); history()->owner().updateDependentMessages(this); } diff --git a/Telegram/SourceFiles/history/history_service.h b/Telegram/SourceFiles/history/history_service.h index b8725535c..87749d9da 100644 --- a/Telegram/SourceFiles/history/history_service.h +++ b/Telegram/SourceFiles/history/history_service.h @@ -111,7 +111,7 @@ public: bool serviceMsg() const override { return true; } - QString inDialogsText(DrawInDialog way) const override; + ItemPreview toPreview(ToPreviewOptions options) const override; QString inReplyText() const override; std::unique_ptr createView( diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 6319dc79a..49fbb5bf2 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6853,11 +6853,16 @@ void HistoryWidget::updateForwardingTexts() { } if (count < 2) { - text = _toForward.items.front()->inDialogsText(keepCaptions - ? HistoryItem::DrawInDialog::WithoutSender - : HistoryItem::DrawInDialog::WithoutSenderAndCaption); + // #TODO minis use images + text = _toForward.items.front()->toPreview({ + .hideSender = true, + .hideCaption = !keepCaptions, + .generateImages = false, + }).text; } else { - text = textcmdLink(1, tr::lng_forward_messages(tr::now, lt_count, count)); + text = textcmdLink( + 1, + tr::lng_forward_messages(tr::now, lt_count, count)); } } _toForwardFrom.setText(st::msgNameStyle, from, Ui::NameTextOptions()); diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 5cbc7df1b..d58c46df1 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -804,10 +804,11 @@ void Notification::updateNotifyDisplay() { p.setTextPalette(st::dialogsTextPalette); p.setPen(st::dialogsTextFg); p.setFont(st::dialogsTextFont); - const auto text = _item - ? _item->inDialogsText(reminder - ? HistoryItem::DrawInDialog::WithoutSender - : HistoryItem::DrawInDialog::Normal) + const auto text = _item // #TODO minis use images + ? _item->toPreview({ + .hideSender = reminder, + .generateImages = false, + }).text : ((!_author.isEmpty() ? textcmdLink(1, _author) : QString())