diff --git a/Telegram/Resources/icons/history_pin.png b/Telegram/Resources/icons/history_pin.png new file mode 100644 index 000000000..55066f98b Binary files /dev/null and b/Telegram/Resources/icons/history_pin.png differ diff --git a/Telegram/Resources/icons/history_pin@2x.png b/Telegram/Resources/icons/history_pin@2x.png new file mode 100644 index 000000000..285b91659 Binary files /dev/null and b/Telegram/Resources/icons/history_pin@2x.png differ diff --git a/Telegram/Resources/icons/history_pin@3x.png b/Telegram/Resources/icons/history_pin@3x.png new file mode 100644 index 000000000..7ef2fce37 Binary files /dev/null and b/Telegram/Resources/icons/history_pin@3x.png differ diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 7bb00c86e..a30aa9275 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -348,6 +348,7 @@ void HistoryItem::markMediaRead() { } void HistoryItem::setIsPinned(bool pinned) { + const auto changed = (isPinned() != pinned); if (pinned) { _flags |= MTPDmessage::Flag::f_pinned; history()->session().storage().add(Storage::SharedMediaAddExisting( @@ -363,6 +364,9 @@ void HistoryItem::setIsPinned(bool pinned) { Storage::SharedMediaType::Pinned, id)); } + if (changed) { + history()->owner().requestItemResize(this); + } } bool HistoryItem::definesReplyKeyboard() const { diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index d909a839d..b1c2bfb3e 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1816,9 +1816,28 @@ void Message::drawInfo( p.drawText(dateX, dateY + st::msgDateFont->ascent, item->_timeText); } + const auto viewIconTop = infoBottom + st::historyViewsTop; + const auto pinIconTop = infoBottom + st::historyPinTop; + auto left = infoRight - infoW; + if (displayPinIcon()) { + const auto icon = [&] { + if (outbg) { + return &(invertedsprites + ? st::historyPinInvertedIcon + : selected + ? st::historyPinOutSelectedIcon + : st::historyPinOutIcon); + } + return &(invertedsprites + ? st::historyPinInvertedIcon + : selected + ? st::historyPinInSelectedIcon + : st::historyPinInIcon); + }(); + icon->paint(p, left, pinIconTop, width); + left += st::historyViewsWidth; + } if (auto views = item->Get()) { - auto left = infoRight - infoW; - const auto iconTop = infoBottom + st::historyViewsTop; const auto textTop = infoBottom - st::msgDateFont->descent; if (views->replies.count > 0 && !views->commentsMegagroupId @@ -1843,11 +1862,11 @@ void Message::drawInfo( : st::historyViewsSendingIcon); }(); if (item->id > 0) { - icon->paint(p, left, iconTop, width); + icon->paint(p, left, viewIconTop, width); p.drawText(left + st::historyViewsWidth, textTop, views->replies.text); } else if (!outbg && views->views.count < 0) { // sending outbg icon will be painted below auto iconSkip = st::historyViewsSpace + views->replies.textWidth; - icon->paint(p, left + iconSkip, iconTop, width); + icon->paint(p, left + iconSkip, viewIconTop, width); } left += st::historyViewsSpace + views->replies.textWidth @@ -1874,16 +1893,16 @@ void Message::drawInfo( : st::historyViewsSendingIcon); }(); if (item->id > 0) { - icon->paint(p, left, iconTop, width); + icon->paint(p, left, viewIconTop, width); p.drawText(left + st::historyViewsWidth, textTop, views->views.text); } else if (!outbg) { // sending outbg icon will be painted below auto iconSkip = st::historyViewsSpace + views->views.textWidth; - icon->paint(p, left + iconSkip, iconTop, width); + icon->paint(p, left + iconSkip, viewIconTop, width); } } } else if (item->id < 0 && item->history()->peer->isSelf() && !outbg) { auto icon = &(invertedsprites ? st::historyViewsSendingInvertedIcon : st::historyViewsSendingIcon); - icon->paint(p, infoRight - infoW, infoBottom + st::historyViewsTop, width); + icon->paint(p, left, viewIconTop, width); } if (outbg) { auto icon = [&] { @@ -1951,6 +1970,9 @@ int Message::infoWidth() const { result += st::historySendStateSpace; } } + if (displayPinIcon()) { + result += st::historyViewsWidth; + } // When message is scheduled until online, time is not displayed, // so message should have less space. @@ -2000,6 +2022,9 @@ int Message::timeLeft() const { result += st::historySendStateSpace; } } + if (displayPinIcon()) { + result += st::historyViewsWidth; + } return result; } @@ -2046,6 +2071,10 @@ HistoryMessageReply *Message::displayedReply() const { return nullptr; } +bool Message::displayPinIcon() const { + return data()->isPinned() && context() != Context::Pinned; +} + bool Message::hasFromName() const { switch (context()) { case Context::AdminLog: diff --git a/Telegram/SourceFiles/history/view/history_view_message.h b/Telegram/SourceFiles/history/view/history_view_message.h index 3ffa3cff1..e8a3fb229 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.h +++ b/Telegram/SourceFiles/history/view/history_view_message.h @@ -176,11 +176,13 @@ private: QSize performCountCurrentSize(int newWidth) override; bool hasVisibleText() const override; - bool displayFastShare() const; - bool displayGoToOriginal() const; - ClickHandlerPtr fastReplyLink() const; - const HistoryMessageEdited *displayedEditBadge() const; - HistoryMessageEdited *displayedEditBadge(); + [[nodiscard]] bool displayFastShare() const; + [[nodiscard]] bool displayGoToOriginal() const; + [[nodiscard]] ClickHandlerPtr fastReplyLink() const; + [[nodiscard]] const HistoryMessageEdited *displayedEditBadge() const; + [[nodiscard]] HistoryMessageEdited *displayedEditBadge(); + [[nodiscard]] bool displayPinIcon() const; + void initTime(); [[nodiscard]] int timeLeft() const; [[nodiscard]] int plainMaxWidth() const; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp index 15339973a..be79c4dd6 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_prepare.cpp @@ -214,9 +214,12 @@ std::vector DivideByGroups( auto result = std::vector(); auto pushGroup = [&] { + const auto type = (group.files.size() > 1) + ? groupType + : AlbumType::None; result.push_back(PreparedGroup{ .list = base::take(group), - .type = groupType, + .type = type, }); }; for (auto i = 0; i != list.files.size(); ++i) { diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 62472aeb6..4631d5f93 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -182,6 +182,12 @@ historyRepliesInSelectedIcon: icon {{ "history_replies", msgInDateFgSelected }}; historyRepliesOutIcon: icon {{ "history_replies", historyOutIconFg }}; historyRepliesOutSelectedIcon: icon {{ "history_replies", historyOutIconFgSelected }}; historyRepliesInvertedIcon: icon {{ "history_replies", historySendingInvertedIconFg }}; +historyPinTop: -18px; +historyPinInIcon: icon {{ "history_pin", msgInDateFg }}; +historyPinInSelectedIcon: icon {{ "history_pin", msgInDateFgSelected }}; +historyPinOutIcon: icon {{ "history_pin", historyOutIconFg }}; +historyPinOutSelectedIcon: icon {{ "history_pin", historyOutIconFgSelected }}; +historyPinInvertedIcon: icon {{ "history_pin", historySendingInvertedIconFg }}; historyComposeField: InputField(defaultInputField) { font: msgFont;