diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index 2e3788eb4..f3d2e2dac 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -1031,7 +1031,7 @@ void TopBarWidget::updateControlsVisibility() { && _activeChat.key.peer()->canSendPolls()) || (topic && topic->canSendPolls()); const auto hasTopicMenu = [&] { - if (!topic) { + if (!topic || section != Section::Replies) { return false; } auto empty = true; diff --git a/Telegram/SourceFiles/mtproto/connection_abstract.h b/Telegram/SourceFiles/mtproto/connection_abstract.h index 71172df45..6a2b48b37 100644 --- a/Telegram/SourceFiles/mtproto/connection_abstract.h +++ b/Telegram/SourceFiles/mtproto/connection_abstract.h @@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +#include + namespace MTP { class Instance; diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp index c6d1e8a12..f3951b34e 100644 --- a/Telegram/SourceFiles/window/notifications_manager.cpp +++ b/Telegram/SourceFiles/window/notifications_manager.cpp @@ -942,8 +942,8 @@ TextWithEntities Manager::ComposeReactionNotification( return text(); } -QString Manager::addTargetAccountName( - const QString &title, +TextWithEntities Manager::addTargetAccountName( + TextWithEntities title, not_null session) { const auto add = [&] { for (const auto &[index, account] : Core::App().domain().accounts()) { @@ -955,13 +955,19 @@ QString Manager::addTargetAccountName( } return false; }(); - return add - ? (title - + accountNameSeparator() - + (session->user()->username().isEmpty() - ? session->user()->name() - : session->user()->username())) - : title; + if (!add) { + return title; + } + return title.append(accountNameSeparator()).append( + (session->user()->username().isEmpty() + ? session->user()->name() + : session->user()->username())); +} + +QString Manager::addTargetAccountName( + const QString &title, + not_null session) { + return addTargetAccountName(TextWithEntities{ title }, session).text; } QString Manager::accountNameSeparator() { @@ -1099,11 +1105,16 @@ void NativeManager::doShowNotification(NotificationFields &&fields) { && !reactionFrom && (item->out() || peer->isSelf()) && item->isFromScheduled(); + const auto topicWithChat = [&] { + const auto name = peer->name(); + const auto topic = item->topic(); + return topic ? (topic->title() + u" ("_q + name + ')') : name; + }; const auto title = options.hideNameAndPhoto ? AppName.utf16() : (scheduled && peer->isSelf()) ? tr::lng_notification_reminder(tr::now) - : peer->name(); + : topicWithChat(); const auto fullTitle = addTargetAccountName(title, &peer->session()); const auto subtitle = reactionFrom ? (reactionFrom != peer ? reactionFrom->name() : QString()) diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h index 517636040..e1bc0ac56 100644 --- a/Telegram/SourceFiles/window/notifications_manager.h +++ b/Telegram/SourceFiles/window/notifications_manager.h @@ -283,6 +283,9 @@ public: const Data::ReactionId &reaction, bool hideContent); + [[nodiscard]] TextWithEntities addTargetAccountName( + TextWithEntities title, + not_null session); [[nodiscard]] QString addTargetAccountName( const QString &title, not_null session); diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 95ac393ef..533bda271 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -636,6 +636,7 @@ Notification::Notification( , _peer(peer) , _started(crl::now()) , _history(history) +, _topic(history->peer->forumTopicFor(topicRootId)) , _topicRootId(topicRootId) , _userpicView(_peer->createUserpicView()) , _author(author) @@ -650,6 +651,13 @@ Notification::Notification( refreshLang(); }, lifetime()); + if (_topic) { + _topic->destroyed( + ) | rpl::start_with_next([=] { + unlinkHistory(); + }, lifetime()); + } + auto position = computePosition(st::notifyMinHeight); updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyMinHeight); @@ -779,18 +787,18 @@ void Notification::actionsOpacityCallback() { } void Notification::customEmojiCallback() { - if (_textRepaintScheduled) { + if (_textsRepaintScheduled) { return; } - _textRepaintScheduled = true; + _textsRepaintScheduled = true; crl::on_main(this, [=] { repaintText(); }); } void Notification::repaintText() { - if (!_textRepaintScheduled) { + if (!_textsRepaintScheduled) { return; } - _textRepaintScheduled = false; + _textsRepaintScheduled = false; if (_cache.isNull()) { return; } @@ -798,11 +806,25 @@ void Notification::repaintText() { const auto adjusted = Ui::Text::AdjustCustomEmojiSize(st::emojiSize); const auto skip = (adjusted - st::emojiSize + 1) / 2; const auto margin = QMargins{ skip, skip, skip, skip }; + p.fillRect(_titleRect.marginsAdded(margin), st::notificationBg); p.fillRect(_textRect.marginsAdded(margin), st::notificationBg); + paintTitle(p); paintText(p); update(); } +void Notification::paintTitle(Painter &p) { + p.setPen(st::dialogsNameFg); + p.setFont(st::semiboldFont); + _titleCache.draw(p, { + .position = _titleRect.topLeft(), + .availableWidth = _titleRect.width(), + .palette = &st::dialogsTextPalette, + .spoiler = Ui::Text::DefaultSpoilerCache(), + .elisionLines = 1, + }); +} + void Notification::paintText(Painter &p) { p.setPen(st::dialogsTextFg); p.setFont(st::dialogsTextFont); @@ -868,7 +890,10 @@ void Notification::updateNotifyDisplay() { Ui::Emoji::Draw(p, emoji, Ui::Emoji::GetSizeNormal(), rectForName.left(), top); rectForName.setLeft(rectForName.left() + size + st::semiboldFont->spacew); } - if (const auto chatTypeIcon = Dialogs::Ui::ChatTypeIcon(_history->peer)) { + const auto chatTypeIcon = _topic + ? nullptr + : Dialogs::Ui::ChatTypeIcon(_history->peer); + if (chatTypeIcon) { chatTypeIcon->paint(p, rectForName.topLeft(), w); rectForName.setLeft(rectForName.left() + chatTypeIcon->width() @@ -941,18 +966,46 @@ void Notification::updateNotifyDisplay() { itemWidth)); } - p.setPen(st::dialogsNameFg); - Ui::Text::String titleText; - const auto title = options.hideNameAndPhoto - ? qsl("Telegram Desktop") + const auto topicWithChat = [&]() -> TextWithEntities { + const auto name = _history->peer->name(); + const auto wrapIcon = [](DocumentId id) { + return TextWithEntities{ + "@", + { EntityInText( + EntityType::CustomEmoji, + 0, + 1, + Data::SerializeCustomEmojiId({.id = id })) + }, + }; + }; + if (!_topic) { + return { name }; + } + auto start = _topic->iconId() + ? wrapIcon(_topic->iconId()) + : TextWithEntities(); + return start.append(_topic->title() + u" ("_q + name + ')'); + }; + auto title = options.hideNameAndPhoto + ? TextWithEntities{ u"Telegram Desktop"_q } : reminder - ? tr::lng_notification_reminder(tr::now) - : _history->peer->name(); + ? tr::lng_notification_reminder(tr::now, Ui::Text::WithEntities) + : topicWithChat(); const auto fullTitle = manager()->addTargetAccountName( - title, + std::move(title), &_history->session()); - titleText.setText(st::semiboldTextStyle, fullTitle, Ui::NameTextOptions()); - titleText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); + const auto context = Core::MarkedTextContext{ + .session = &_history->session(), + .customEmojiRepaint = [=] { customEmojiCallback(); }, + }; + _titleCache.setMarkedText( + st::semiboldTextStyle, + fullTitle, + Ui::NameTextOptions(), + context); + _titleRect = rectForName; + paintTitle(p); } _cache = std::move(img); @@ -1104,6 +1157,7 @@ bool Notification::unlinkHistory(History *history, MsgId topicRootId) { if (unlink) { hideFast(); _history = nullptr; + _topic = nullptr; _item = nullptr; } return unlink; diff --git a/Telegram/SourceFiles/window/notifications_manager_default.h b/Telegram/SourceFiles/window/notifications_manager_default.h index 6637695a8..773694f81 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.h +++ b/Telegram/SourceFiles/window/notifications_manager_default.h @@ -265,6 +265,7 @@ private: void updateGeometry(int x, int y, int width, int height) override; void actionsOpacityCallback(); void repaintText(); + void paintTitle(Painter &p); void paintText(Painter &p); void customEmojiCallback(); @@ -273,18 +274,21 @@ private: const not_null _peer; QImage _cache; + Ui::Text::String _titleCache; Ui::Text::String _textCache; + QRect _titleRect; QRect _textRect; bool _hideReplyButton = false; bool _actionsVisible = false; - bool _textRepaintScheduled = false; + bool _textsRepaintScheduled = false; Ui::Animations::Simple a_actionsOpacity; QPixmap _buttonsCache; crl::time _started; History *_history = nullptr; + Data::ForumTopic *_topic = nullptr; MsgId _topicRootId = 0; std::shared_ptr _userpicView; QString _author;