From 2a5bcd3eec44c455f3d64d9e7f0800aba65ec24b Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 15 Jan 2019 18:13:20 +0400 Subject: [PATCH] Support empty group placeholder for creators. --- Telegram/Resources/langs/lang.strings | 7 ++ .../boxes/peers/add_participants_box.h | 2 - .../boxes/peers/edit_participants_box.h | 2 - Telegram/SourceFiles/history/history.cpp | 14 ++- Telegram/SourceFiles/history/history.style | 7 ++ .../history/history_inner_widget.cpp | 4 +- .../SourceFiles/history/history_widget.cpp | 4 +- .../view/history_view_service_message.cpp | 96 ++++++++++++++++++- .../view/history_view_service_message.h | 6 +- 9 files changed, 131 insertions(+), 11 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 846f0f6abf..67ad7d7f52 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1045,6 +1045,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_group_stickers_description" = "You can choose a sticker set which will be available for every member while in the group chat."; "lng_group_stickers_add" = "Choose sticker set"; +"lng_group_about_header" = "You have created a group."; +"lng_group_about_text" = "Groups can have:"; +"lng_group_about1" = "Up to 100,000 members"; +"lng_group_about2" = "Persistent chat history"; +"lng_group_about3" = "Public links such as t.me/title"; +"lng_group_about4" = "Admins with different rights"; + "lng_switch_stickers" = "Stickers"; "lng_switch_emoji" = "Emoji"; "lng_switch_gifs" = "GIFs"; diff --git a/Telegram/SourceFiles/boxes/peers/add_participants_box.h b/Telegram/SourceFiles/boxes/peers/add_participants_box.h index dd4c1294f9..9da139a677 100644 --- a/Telegram/SourceFiles/boxes/peers/add_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/add_participants_box.h @@ -24,8 +24,6 @@ public: not_null peer, base::flat_set> &&alreadyIn); - using ContactsBoxController::ContactsBoxController; - void rowClicked(not_null row) override; void itemDeselectedHook(not_null peer) override; diff --git a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h index aeb7f848b5..3f1d520525 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_participants_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_participants_box.h @@ -14,8 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/weak_ptr.h" #include "info/profile/info_profile_members_controllers.h" -struct MegagroupInfo; - namespace Window { class Navigation; } // namespace Window diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 75b0b37d45..3c51c2069d 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -2727,7 +2727,19 @@ bool History::isEmpty() const { } bool History::isDisplayedEmpty() const { - return findFirstNonEmpty() == nullptr; + const auto first = findFirstNonEmpty(); + if (!first) { + return true; + } else if (!first->data()->isGroupEssential()) { + return false; + } else if (const auto chat = peer->asChat()) { + // For legacy chats we want to show the chat with only first + // message about you creating the group as an empty chat with + // a nice information about the group features. + return chat->amCreator() && (findLastNonEmpty() == first); + } else { + return false; + } } auto History::findFirstNonEmpty() const -> Element* { diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index c563d781c8..13712ea7e8 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -543,3 +543,10 @@ boxAttachEmoji: IconButton(historyAttachEmoji) { rippleAreaSize: 0px; } boxAttachEmojiTop: 20px; + +historyGroupAboutMargin: 16px; +historyGroupAboutPadding: margins(24px, 16px, 24px, 16px); +historyGroupAboutBulletSkip: 16px; +historyGroupAboutHeaderSkip: 10px; +historyGroupAboutTextSkip: 10px; +historyGroupAboutSkip: 8px; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index c5e852cf52..25473430cf 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -551,8 +551,8 @@ void HistoryInner::paintEvent(QPaintEvent *e) { p.restoreTextPalette(); } - } else if (noHistoryDisplayed) { - HistoryView::paintEmpty(p, width(), height()); + } else if (historyDisplayedEmpty) { + HistoryView::paintEmpty(p, _history, width(), height()); } if (!noHistoryDisplayed) { auto readMentions = base::flat_set>(); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index f79e4e2578..3421355d15 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -6555,9 +6555,9 @@ void HistoryWidget::paintEvent(QPaintEvent *e) { if (_pinnedBar && !_pinnedBar->cancel->isHidden()) { drawPinnedBar(p); } - if (_scroll->isHidden()) { + if (_scroll->isHidden() && _history) { p.setClipRect(_scroll->geometry()); - HistoryView::paintEmpty(p, width(), height() - _field->height() - 2 * st::historySendPadding); + HistoryView::paintEmpty(p, _history, width(), height() - _field->height() - 2 * st::historySendPadding); } } else { const auto w = st::msgServiceFont->width(lang(lng_willbe_history)) diff --git a/Telegram/SourceFiles/history/view/history_view_service_message.cpp b/Telegram/SourceFiles/history/view/history_view_service_message.cpp index 4605cf3eb1..a1023a7aed 100644 --- a/Telegram/SourceFiles/history/view/history_view_service_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_service_message.cpp @@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_components.h" #include "history/view/history_view_cursor_state.h" #include "data/data_abstract_structure.h" +#include "data/data_chat.h" +#include "data/data_channel.h" #include "styles/style_history.h" #include "mainwidget.h" #include "layout.h" @@ -173,6 +175,83 @@ void paintPreparedDate(Painter &p, const QString &dateText, int dateTextWidth, i p.drawText(left + st::msgServicePadding.left(), y + st::msgServiceMargin.top() + st::msgServicePadding.top() + st::msgServiceFont->ascent, dateText); } +void PaintAboutGroup(Painter &p, int width, int height) { + constexpr auto kPhrasesCount = 4; + const auto header = lang(lng_group_about_header); + const auto text = lang(lng_group_about_text); + const auto phrases = std::array{ + lang(lng_group_about1), + lang(lng_group_about2), + lang(lng_group_about3), + lang(lng_group_about4), + }; + + const auto &font = st::msgServiceFont; + const auto headerWidth = font->width(header); + const auto textWidth = font->width(text); + const auto phraseWidths = ranges::view::all( + phrases + ) | ranges::view::transform([&](const QString &text) { + return font->width(text); + }) | ranges::to_vector; + + const auto maxPhraseWidth = *ranges::max_element(phraseWidths); + + const auto margin = st::msgMargin.left(); + const auto maxBubbleWidth = width - 2 * st::historyGroupAboutMargin; + const auto padding = st::historyGroupAboutPadding; + const auto bubbleWidth = std::min( + maxBubbleWidth, + std::max({ + maxPhraseWidth + st::historyGroupAboutBulletSkip, + headerWidth, + textWidth }) + padding.left() + padding.right()); + const auto bubbleHeight = padding.top() + + font->height + + st::historyGroupAboutHeaderSkip + + font->height + + st::historyGroupAboutTextSkip + + font->height * kPhrasesCount + + st::historyGroupAboutSkip * (kPhrasesCount - 1) + + padding.bottom(); + const auto bubbleLeft = (width - bubbleWidth) / 2; + const auto bubbleTop = (height - bubbleHeight) / 3; + + ServiceMessagePainter::paintBubble( + p, + bubbleLeft, + bubbleTop, + bubbleWidth, + bubbleHeight); + + p.setFont(font); + p.setPen(st::msgServiceFg); + const auto left = bubbleLeft + padding.left(); + auto top = bubbleTop + padding.top(); + + p.drawTextLeft(bubbleLeft + (bubbleWidth - headerWidth) / 2, top, width, header); + top += font->height + st::historyGroupAboutHeaderSkip; + + p.drawTextLeft(left, top, width, text); + top += font->height + st::historyGroupAboutTextSkip; + + p.setBrush(st::msgServiceFg); + for (const auto &text : phrases) { + p.setPen(st::msgServiceFg); + p.drawTextLeft(left + st::historyGroupAboutBulletSkip, top, width, text); + { + PainterHighQualityEnabler hq(p); + p.setPen(Qt::NoPen); + p.drawEllipse( + left, + top + (font->height - st::mediaUnreadSize) / 2, + st::mediaUnreadSize, + st::mediaUnreadSize); + } + top += font->height + st::historyGroupAboutSkip; + } +} + } // namepsace int WideChatWidth() { @@ -281,7 +360,22 @@ QVector ServiceMessagePainter::countLineWidths(const Text &text, const QRec return lineWidths; } -void paintEmpty(Painter &p, int width, int height) { +void paintEmpty( + Painter &p, + not_null history, + int width, + int height) { + const auto needAboutGroup = [&] { + if (const auto chat = history->peer->asChat()) { + return chat->amCreator(); + } else if (const auto channel = history->peer->asMegagroup()) { + return channel->amCreator(); + } + return false; + }(); + if (needAboutGroup) { + PaintAboutGroup(p, width, height); + } } void serviceColorsUpdated() { diff --git a/Telegram/SourceFiles/history/view/history_view_service_message.h b/Telegram/SourceFiles/history/view/history_view_service_message.h index 74776ed43a..1854e21457 100644 --- a/Telegram/SourceFiles/history/view/history_view_service_message.h +++ b/Telegram/SourceFiles/history/view/history_view_service_message.h @@ -74,7 +74,11 @@ private: }; -void paintEmpty(Painter &p, int width, int height); +void paintEmpty( + Painter &p, + not_null history, + int width, + int height); void serviceColorsUpdated();