diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 78cbfcbe8f..53bdb4bcb1 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2579,6 +2579,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_bot_allow_write_title" = "Allow messaging"; "lng_bot_allow_write" = "Do you want to allow this bot to send you messages?"; "lng_bot_allow_write_confirm" = "Allow"; +"lng_bot_new_chat" = "New Chat"; +"lng_bot_new_thread_title" = "New Thread"; +"lng_bot_new_thread_about" = "Type any message to create a new thread."; "lng_attach_failed" = "Failed"; "lng_attach_file" = "File"; diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 2b65484848..ea9999fb33 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -1956,7 +1956,7 @@ void Updates::feedUpdate(const MTPUpdate &update) { auto &d = update.c_updateUserTyping(); handleSendActionUpdate( peerFromUser(d.vuser_id()), - 0, + d.vtop_msg_id().value_or_empty(), peerFromUser(d.vuser_id()), d.vaction()); } break; diff --git a/Telegram/SourceFiles/data/data_histories.cpp b/Telegram/SourceFiles/data/data_histories.cpp index bc5587c631..aaf4b3bc36 100644 --- a/Telegram/SourceFiles/data/data_histories.cpp +++ b/Telegram/SourceFiles/data/data_histories.cpp @@ -1044,8 +1044,6 @@ int Histories::sendRequest( void Histories::sendCreateTopicRequest( not_null history, MsgId rootId) { - Expects(history->peer->isChannel()); - const auto forum = history->asForum(); Assert(forum != nullptr); const auto topic = forum->topicFor(rootId); @@ -1058,7 +1056,8 @@ void Histories::sendCreateTopicRequest( using Flag = MTPmessages_CreateForumTopic::Flag; api->request(MTPmessages_CreateForumTopic( MTP_flags(Flag::f_icon_color - | (topic->iconId() ? Flag::f_icon_emoji_id : Flag(0))), + | (topic->iconId() ? Flag::f_icon_emoji_id : Flag()) + | (history->peer->isBot() ? Flag::f_title_missing : Flag())), history->peer->input, MTP_string(topic->title()), MTP_int(topic->colorId()), diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 64f8c6026a..3e7954b97e 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -852,7 +852,7 @@ void HistoryInner::enumerateUserpics(Method method) { lowestAttachedItemTop = itemtop + view->marginTop(); } // Attach userpic to the bottom of the visible area with the same margin as the last message. - auto userpicMinBottomSkip = st::historyPaddingBottom + st::msgMargin.bottom(); + auto userpicMinBottomSkip = _historyMarginBottom + st::msgMargin.bottom(); auto userpicBottom = qMin(itembottom - view->marginBottom(), _visibleAreaBottom - userpicMinBottomSkip); // Do not let the userpic go above the attached messages pack top line. @@ -3510,13 +3510,13 @@ void HistoryInner::recountHistoryGeometry(bool initial) { || (_migrated && _migrated->hasPendingResizedItems())) { _recountedAfterPendingResizedItems = true; } - + const auto aboutAboveHistory = _aboutView && _aboutView->aboveHistory(); const auto visibleHeight = _scroll->height(); - auto oldHistoryPaddingTop = qMax( - visibleHeight - historyHeight() - st::historyPaddingBottom, + auto oldHistoryMarginTop = qMax( + visibleHeight - historyHeight() - _historyMarginBottom, 0); - if (_aboutView) { - accumulate_max(oldHistoryPaddingTop, _aboutView->height); + if (aboutAboveHistory) { + accumulate_max(oldHistoryMarginTop, _aboutView->height); } updateBotInfo(false); @@ -3546,26 +3546,32 @@ void HistoryInner::recountHistoryGeometry(bool initial) { if (const auto view = _aboutView ? _aboutView->view() : nullptr) { _aboutView->height = view->resizeGetHeight(_contentWidth); - _aboutView->top = qMin( - _historyPaddingTop - _aboutView->height, - qMax(0, (_scroll->height() - _aboutView->height) / 2)); + if (aboutAboveHistory) { + _aboutView->top = qMin( + _historyMarginTop - _aboutView->height, + qMax(0, (_scroll->height() - _aboutView->height) / 2)); + } else { + _aboutView->top = qMax( + qMax(0, (_scroll->height() - _aboutView->height) / 2), + _historyMarginTop + historyHeight() - _historyMarginBottom); + } } else if (_aboutView) { _aboutView->top = _aboutView->height = 0; } - auto newHistoryPaddingTop = qMax( - visibleHeight - historyHeight() - st::historyPaddingBottom, + auto newHistoryMarginTop = qMax( + visibleHeight - historyHeight() - _historyMarginBottom, 0); - if (_aboutView) { - accumulate_max(newHistoryPaddingTop, _aboutView->height); + if (aboutAboveHistory) { + accumulate_max(newHistoryMarginTop, _aboutView->height); } - auto historyPaddingTopDelta = (newHistoryPaddingTop - oldHistoryPaddingTop); - if (!initial && historyPaddingTopDelta != 0) { + const auto marginDelta = newHistoryMarginTop - oldHistoryMarginTop; + if (!initial && marginDelta) { if (_history->scrollTopItem) { - _history->scrollTopOffset += historyPaddingTopDelta; + _history->scrollTopOffset += marginDelta; } else if (_migrated && _migrated->scrollTopItem) { - _migrated->scrollTopOffset += historyPaddingTopDelta; + _migrated->scrollTopOffset += marginDelta; } } } @@ -3598,7 +3604,7 @@ void HistoryInner::visibleAreaUpdated(int top, int bottom) { return; } - if (bottom >= _historyPaddingTop + historyHeight() + st::historyPaddingBottom) { + if (bottom >= _historyMarginTop + historyHeight() + _historyMarginBottom) { _history->forgetScrollState(); if (_migrated) { _migrated->forgetScrollState(); @@ -3727,22 +3733,44 @@ void HistoryInner::changeItemsRevealHeight(int revealHeight) { void HistoryInner::updateSize() { const auto visibleHeight = _scroll->height(); const auto itemsHeight = historyHeight() - _revealHeight; - auto newHistoryPaddingTop = qMax(visibleHeight - itemsHeight - st::historyPaddingBottom, 0); - if (_aboutView) { - accumulate_max(newHistoryPaddingTop, _aboutView->height); + const auto aboutAboveHistory = _aboutView && _aboutView->aboveHistory(); + const auto aboutBelowHistory = _aboutView && !aboutAboveHistory; + auto newHistoryMarginBottom = st::historyPaddingBottom; + if (aboutBelowHistory) { + accumulate_max(newHistoryMarginBottom, _aboutView->height); + } + auto newHistoryMarginTop = qMax( + visibleHeight - itemsHeight - newHistoryMarginBottom, + 0); + if (aboutAboveHistory) { + accumulate_max(newHistoryMarginTop, _aboutView->height); } if (_aboutView && _aboutView->height > 0) { - _aboutView->top = qMin( - newHistoryPaddingTop - _aboutView->height, - qMax(0, (_scroll->height() - _aboutView->height) / 2)); + if (aboutAboveHistory) { + _aboutView->top = qMin( + newHistoryMarginTop - _aboutView->height, + qMax(0, (_scroll->height() - _aboutView->height) / 2)); + } else { + _aboutView->top = qMax( + qMax(0, (_scroll->height() - _aboutView->height) / 2), + (newHistoryMarginTop + + itemsHeight + + newHistoryMarginBottom + - _aboutView->height)); + } } - if (_historyPaddingTop != newHistoryPaddingTop) { - _historyPaddingTop = newHistoryPaddingTop; + if (_historyMarginTop != newHistoryMarginTop) { + _historyMarginTop = newHistoryMarginTop; + } + if (_historyMarginBottom != newHistoryMarginBottom) { + _historyMarginBottom = newHistoryMarginBottom; } - int newHeight = _historyPaddingTop + itemsHeight + st::historyPaddingBottom; + const auto newHeight = _historyMarginTop + + itemsHeight + + _historyMarginBottom; if (width() != _scroll->width() || height() != newHeight) { resize(_scroll->width(), newHeight); @@ -4536,7 +4564,7 @@ int HistoryInner::historyScrollTop() const { } int HistoryInner::migratedTop() const { - return (_migrated && !_migrated->isEmpty()) ? _historyPaddingTop : -1; + return (_migrated && !_migrated->isEmpty()) ? _historyMarginTop : -1; } int HistoryInner::historyTop() const { @@ -4544,7 +4572,7 @@ int HistoryInner::historyTop() const { return !_history->isEmpty() ? (mig >= 0 ? (mig + _migrated->height() - _historySkipHeight) - : _historyPaddingTop) + : _historyMarginTop) : -1; } diff --git a/Telegram/SourceFiles/history/history_inner_widget.h b/Telegram/SourceFiles/history/history_inner_widget.h index 4e30c5d168..61cc55f2c5 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.h +++ b/Telegram/SourceFiles/history/history_inner_widget.h @@ -468,7 +468,8 @@ private: History *_migrated = nullptr; HistoryView::ElementDelegate *_migratedElementDelegate = nullptr; int _contentWidth = 0; - int _historyPaddingTop = 0; + int _historyMarginTop = 0; + int _historyMarginBottom = 0; int _revealHeight = 0; int _forumThreadBarWidth = 0; Ui::PeerUserpicView _forumThreadBarUserpicView; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 9f726f5919..070947ccf1 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_sending.h" #include "api/api_send_progress.h" #include "api/api_unread_things.h" +#include "base/random.h" #include "ui/boxes/confirm_box.h" #include "boxes/delete_messages_box.h" #include "boxes/send_credits_box.h" @@ -104,6 +105,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/controls/history_view_voice_record_bar.h" #include "history/view/controls/history_view_webpage_processor.h" #include "history/view/reactions/history_view_reactions_button.h" +#include "history/view/history_view_chat_section.h" #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_service_message.h" #include "history/view/history_view_element.h" @@ -977,6 +979,21 @@ HistoryWidget::HistoryWidget( session().api().sendActions( ) | rpl::filter([=](const Api::SendAction &action) { + if (_creatingBotTopic + && action.history == _creatingBotTopic->owningHistory() + && action.replyTo.topicRootId == _creatingBotTopic->rootId()) { + Ui::PostponeCall(_creatingBotTopic, [=] { + using namespace HistoryView; + const auto topic = base::take(_creatingBotTopic); + controller->showSection( + std::make_shared(ChatViewId{ + .history = topic->owningHistory(), + .repliesRootId = topic->rootId(), + }), + Window::SectionShow::Way::ClearStack); + }); + return false; + } return (action.history == _history); }) | rpl::start_with_next([=](const Api::SendAction &action) { const auto lastKeyboardUsed = lastForceReplyReplied( @@ -1787,6 +1804,9 @@ void HistoryWidget::orderWidgets() { if (_emojiSuggestions) { _emojiSuggestions->raise(); } + if (_attachBotsMenu) { + _attachBotsMenu->raise(); + } _attachDragAreas.document->raise(); _attachDragAreas.photo->raise(); } @@ -2863,6 +2883,10 @@ void HistoryWidget::setHistory(History *history) { const auto wasMigrated = base::take(_migrated); unloadHeavyViewParts(wasHistory); unloadHeavyViewParts(wasMigrated); + if (const auto wasCreatingBotTopic = base::take(_creatingBotTopic)) { + wasCreatingBotTopic->forum()->discardCreatingId( + wasCreatingBotTopic->rootId()); + } } if (history) { _history = history; @@ -4633,6 +4657,22 @@ Api::SendAction HistoryWidget::prepareSendAction( Api::SendOptions options) const { auto result = Api::SendAction(_history, options); result.replyTo = replyTo(); + + if (const auto forum = _history->asForum()) { + if (_history->peer->isBot()) { + if (!_creatingBotTopic) { + const auto &colors = Data::ForumTopicColorIds(); + const auto colorId = colors[base::RandomIndex(colors.size())]; + _creatingBotTopic = forum->topicFor(forum->reserveCreatingId( + tr::lng_bot_new_chat(tr::now), + colorId, + DocumentId())); + } + result = Api::SendAction(_creatingBotTopic, options); + result.replyTo.topicRootId = _creatingBotTopic->rootId(); + } + } + result.options.suggest = suggestOptions(); result.options.sendAs = _sendAs ? _history->session().sendAsPeers().resolveChosen( @@ -6723,7 +6763,7 @@ FullReplyTo HistoryWidget::replyTo() const { ? _replyTo : _kbReplyTo ? FullReplyTo{ _kbReplyTo->fullId() } - : (_peer && _peer->forum()) + : (_peer && _peer->forum() && !_peer->isBot()) ? FullReplyTo{ .topicRootId = Data::ForumTopic::kGeneralId } : FullReplyTo(); } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index d2606c9fc5..fc46753cae 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -30,6 +30,7 @@ class Error; } // namespace MTP namespace Data { +class ForumTopic; class PhotoMedia; struct SendError; } // namespace Data @@ -779,6 +780,7 @@ private: QPointer _list; History *_migrated = nullptr; History *_history = nullptr; + mutable Data::ForumTopic *_creatingBotTopic = nullptr; rpl::lifetime _historySponsoredPreloading; // Initial updateHistoryGeometry() was called. diff --git a/Telegram/SourceFiles/history/view/history_view_about_view.cpp b/Telegram/SourceFiles/history/view/history_view_about_view.cpp index e09fc425d5..2b49f16a43 100644 --- a/Telegram/SourceFiles/history/view/history_view_about_view.cpp +++ b/Telegram/SourceFiles/history/view/history_view_about_view.cpp @@ -138,6 +138,19 @@ private: }; +class NewBotThreadDownIcon final : public MediaGenericPart { +public: + void draw( + Painter &p, + not_null owner, + const PaintContext &context, + int outerWidth) const override; + + QSize countOptimalSize() override; + QSize countCurrentSize(int newWidth) override; + +}; + UserpicsList::UserpicsList( std::vector> peers, const style::GroupCallUserpics &st, @@ -198,6 +211,27 @@ int UserpicsList::width() const { return _st.size + (shifted * (_st.size - _st.shift)); } +void NewBotThreadDownIcon::draw( + Painter &p, + not_null owner, + const PaintContext &context, + int outerWidth) const { + auto color = context.st->msgServiceFg()->c; + color.setAlphaF(color.alphaF() * kLabelOpacity); + st::newBotThreadDown.paintInCenter( + p, + QRect(0, 0, outerWidth, st::newBotThreadDown.height()), + color); +} + +QSize NewBotThreadDownIcon::countOptimalSize() { + return st::newBotThreadDown.size(); +} + +QSize NewBotThreadDownIcon::countCurrentSize(int newWidth) { + return st::newBotThreadDown.size(); +} + auto GenerateChatIntro( not_null parent, Element *replacing, @@ -264,6 +298,40 @@ auto GenerateChatIntro( }; } +auto GenerateNewBotThread( + not_null parent, + Element *replacing) +-> Fn, + Fn)>)> { + return [=]( + not_null media, + Fn)> push) { + auto pushText = [&]( + TextWithEntities text, + QMargins margins = {}, + const base::flat_map &links = {}) { + if (text.empty()) { + return; + } + push(std::make_unique( + std::move(text), + margins, + st::defaultTextStyle, + links)); + }; + const auto title = tr::lng_bot_new_thread_title(tr::now); + const auto description = tr::lng_bot_new_thread_about(tr::now); + pushText(Ui::Text::Bold(title), st::chatIntroTitleMargin); + pushText({ description }, st::chatIntroMargin); + push(std::make_unique()); + + parent->addVerticalMargins( + st::msgServiceMargin.bottom(), + st::msgServiceMargin.top()); + }; +} + auto GenerateNewPeerInfo( not_null parent, Element *replacing, @@ -513,6 +581,10 @@ HistoryItem *AboutView::item() const { return nullptr; } +bool AboutView::aboveHistory() const { + return !_history->peer->isBot() || !_history->isForum(); +} + bool AboutView::refresh() { if (_history->peer->isVerifyCodes()) { if (_item) { @@ -567,6 +639,12 @@ bool AboutView::refresh() { } _version = 0; return false; + } else if (_history->peer->isForum()) { + if (_item) { + return false; + } + setItem(makeNewBotThread(), nullptr); + return true; } const auto version = info->descriptionVersion; if (_version == version) { @@ -891,4 +969,26 @@ AdminLog::OwnedItem AboutView::makeBlocked() { return AdminLog::OwnedItem(_delegate, item); } +AdminLog::OwnedItem AboutView::makeNewBotThread() { + const auto item = _history->makeMessage({ + .id = _history->nextNonHistoryEntryId(), + .flags = (MessageFlag::FakeAboutView + | MessageFlag::FakeHistoryItem + | MessageFlag::Local), + .from = _history->peer->id, + }, PreparedServiceText{ + tr::lng_bot_new_thread_about(tr::now, Ui::Text::RichLangValue) + }); + auto result = AdminLog::OwnedItem(_delegate, item); + result->overrideMedia(std::make_unique( + result.get(), + GenerateNewBotThread(result.get(), _item.get()), + HistoryView::MediaGenericDescriptor{ + .maxWidth = st::chatIntroWidth, + .service = true, + .hideServiceText = true, + })); + return result; +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_about_view.h b/Telegram/SourceFiles/history/view/history_view_about_view.h index b2c8d3cbb8..35f5bd85f5 100644 --- a/Telegram/SourceFiles/history/view/history_view_about_view.h +++ b/Telegram/SourceFiles/history/view/history_view_about_view.h @@ -25,6 +25,7 @@ public: [[nodiscard]] not_null history() const; [[nodiscard]] Element *view() const; [[nodiscard]] HistoryItem *item() const; + [[nodiscard]] bool aboveHistory() const; bool refresh(); @@ -50,6 +51,7 @@ private: [[nodiscard]] AdminLog::OwnedItem makeNewPeerInfo( not_null user); [[nodiscard]] AdminLog::OwnedItem makeBlocked(); + [[nodiscard]] AdminLog::OwnedItem makeNewBotThread(); void makeIntro(not_null user); void setItem(AdminLog::OwnedItem item, DocumentData *sticker); void setHelloChosen(not_null sticker); diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 1df54340f8..2c84640e28 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -965,6 +965,17 @@ bool Element::isLastAndSelfMessage() const { return false; } +void Element::addVerticalMargins(int top, int bottom) { + if (top || bottom) { + AddComponents(ViewAddedMargins::Bit()); + const auto margins = Get(); + margins->top = top; + margins->bottom = bottom; + } else { + RemoveComponents(ViewAddedMargins::Bit()); + } +} + void Element::setPendingResize() { _flags |= Flag::NeedsResize; if (_context == Context::History) { diff --git a/Telegram/SourceFiles/history/view/history_view_element.h b/Telegram/SourceFiles/history/view/history_view_element.h index 14453f3324..12344db790 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.h +++ b/Telegram/SourceFiles/history/view/history_view_element.h @@ -349,6 +349,11 @@ struct PurchasedTag : RuntimeComponent { Ui::Text::String text; }; +struct ViewAddedMargins : RuntimeComponent { + int top = 0; + int bottom = 0; +}; + struct TopicButton { std::unique_ptr ripple; ClickHandlerPtr link; @@ -417,6 +422,8 @@ public: [[nodiscard]] virtual int marginTop() const = 0; [[nodiscard]] virtual int marginBottom() const = 0; + void addVerticalMargins(int top, int bottom); + void setPendingResize(); [[nodiscard]] bool pendingResize() const; [[nodiscard]] bool isUnderCursor() const; diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 1b58ecd65c..b48fec1bf9 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1142,11 +1142,21 @@ int Message::marginTop() const { if (const auto service = Get()) { result += service->height; } + if (const auto margins = Get()) { + result += margins->top; + } return result; } int Message::marginBottom() const { - return isHidden() ? 0 : st::msgMargin.bottom(); + if (isHidden()) { + return 0; + } + auto result = st::msgMargin.bottom(); + if (const auto margins = Get()) { + result += margins->bottom; + } + return result; } void Message::draw(Painter &p, const PaintContext &context) const { diff --git a/Telegram/SourceFiles/history/view/history_view_service_message.cpp b/Telegram/SourceFiles/history/view/history_view_service_message.cpp index 5c96ee4980..d2ceacc08f 100644 --- a/Telegram/SourceFiles/history/view/history_view_service_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_service_message.cpp @@ -533,11 +533,18 @@ int Service::marginTop() const { if (const auto service = Get()) { result += service->height; } + if (const auto margins = Get()) { + result += margins->top; + } return result; } int Service::marginBottom() const { - return st::msgServiceMargin.bottom(); + auto result = st::msgServiceMargin.bottom(); + if (const auto margins = Get()) { + result += margins->bottom; + } + return result; } void Service::draw(Painter &p, const PaintContext &context) const { diff --git a/Telegram/SourceFiles/history/view/history_view_subsection_tabs.cpp b/Telegram/SourceFiles/history/view/history_view_subsection_tabs.cpp index 836b677779..1382980b5a 100644 --- a/Telegram/SourceFiles/history/view/history_view_subsection_tabs.cpp +++ b/Telegram/SourceFiles/history/view/history_view_subsection_tabs.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qt/qt_key_modifiers.h" #include "core/ui_integration.h" #include "data/stickers/data_custom_emoji.h" +#include "data/data_changes.h" #include "data/data_channel.h" #include "data/data_forum.h" #include "data/data_forum_topic.h" @@ -397,6 +398,11 @@ void SubsectionTabs::startFillingSlider( ).append(' ').append(peer->shortName()), }); } + } else if (item.thread->peer()->isBot()) { + sections.push_back({ + .text = { tr::lng_bot_new_chat(tr::now) }, + .userpic = Ui::MakeNewChatSubsectionsThumbnail(textFg), + }); } else { sections.push_back({ .text = { tr::lng_filters_all_short(tr::now) }, @@ -658,6 +664,16 @@ void SubsectionTabs::track() { }) | rpl::start_with_next([=] { scheduleRefresh(); }, _lifetime); + + forum->session().changes().topicUpdates( + Data::TopicUpdate::Flag::Title + | Data::TopicUpdate::Flag::IconId + | Data::TopicUpdate::Flag::ColorId + ) | rpl::filter([=](const Data::TopicUpdate &update) { + return update.topic->forum() == forum; + }) | rpl::start_with_next([=] { + scheduleRefresh(); + }, _lifetime); } else if (const auto monoforum = _history->peer->monoforum()) { monoforum->sublistDestroyed( ) | rpl::start_with_next([=](not_null sublist) { diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_generic.h b/Telegram/SourceFiles/history/view/media/history_view_media_generic.h index 27cce6de31..7753e120e1 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_generic.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_generic.h @@ -130,6 +130,8 @@ private: not_null)> _paintBg; ClickHandlerPtr _fullAreaLink; int _maxWidthCap = 0; + int _marginTop = 0; + int _marginBottom = 0; bool _service : 1 = false; bool _hideServiceText : 1 = false; diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 9f66a65035..40ff9c11a4 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -1461,3 +1461,5 @@ saveMusicInfoMenu: Menu(defaultMenu) { itemFgOver: windowFg; itemPadding: margins(17px, 4px, 17px, 3px); } + +newBotThreadDown: icon {{ "history_down_arrow", msgServiceFg }}; diff --git a/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp b/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp index a792df0522..50a9b1d4c8 100644 --- a/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp +++ b/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.cpp @@ -544,19 +544,22 @@ std::unique_ptr HorizontalSlider::makeButton( std::move(data)); } -std::shared_ptr MakeAllSubsectionsThumbnail( +std::shared_ptr MakeIconSubsectionsThumbnail( + const style::icon &icon, Fn textColor) { class Image final : public DynamicImage { public: - Image(Fn textColor) : _textColor(std::move(textColor)) { + Image(const style::icon &icon, Fn textColor) + : _icon(icon) + , _textColor(std::move(textColor)) { Expects(_textColor != nullptr); } - std::shared_ptr clone() { - return std::make_shared(_textColor); + std::shared_ptr clone() override { + return std::make_shared(_icon, _textColor); } - QImage image(int size) { + QImage image(int size) override { const auto ratio = style::DevicePixelRatio(); const auto full = size * ratio; const auto color = _textColor(); @@ -570,7 +573,7 @@ std::shared_ptr MakeAllSubsectionsThumbnail( } _color = color; if (_mask.isNull()) { - _mask = st::foldersAll.instance(QColor(255, 255, 255)); + _mask = _icon.instance(QColor(255, 255, 255)); } const auto position = ratio * QPoint( (size - (_mask.width() / ratio)) / 2, @@ -587,7 +590,7 @@ std::shared_ptr MakeAllSubsectionsThumbnail( } return _cache; } - void subscribeToUpdates(Fn callback) { + void subscribeToUpdates(Fn callback) override { if (!callback) { _cache = QImage(); _mask = QImage(); @@ -595,13 +598,28 @@ std::shared_ptr MakeAllSubsectionsThumbnail( } private: + const style::icon &_icon; Fn _textColor; QImage _mask; QImage _cache; QColor _color; }; - return std::make_shared(std::move(textColor)); + return std::make_shared(icon, std::move(textColor)); +} + +std::shared_ptr MakeAllSubsectionsThumbnail( + Fn textColor) { + return MakeIconSubsectionsThumbnail( + st::foldersAll, + std::move(textColor)); +} + +std::shared_ptr MakeNewChatSubsectionsThumbnail( + Fn textColor) { + return MakeIconSubsectionsThumbnail( + st::foldersUnread, + std::move(textColor)); } } // namespace Ui diff --git a/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.h b/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.h index 704169b92f..ab029dabb9 100644 --- a/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.h +++ b/Telegram/SourceFiles/ui/controls/subsection_tabs_slider.h @@ -170,5 +170,7 @@ private: [[nodiscard]] std::shared_ptr MakeAllSubsectionsThumbnail( Fn textColor); +[[nodiscard]] std::shared_ptr MakeNewChatSubsectionsThumbnail( + Fn textColor); } // namespace Ui