Show replies dialog correctly.

This commit is contained in:
John Preston 2020-09-11 18:33:26 +03:00
parent 608d8307d9
commit 4a94a0c438
42 changed files with 345 additions and 58 deletions

View file

@ -1357,6 +1357,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_comments_open_count#one" = "{count} comment"; "lng_comments_open_count#one" = "{count} comment";
"lng_comments_open_count#other" = "{count} comments"; "lng_comments_open_count#other" = "{count} comments";
"lng_comments_open_none" = "Leave a comment"; "lng_comments_open_none" = "Leave a comment";
"lng_replies_messages" = "Replies";
"lng_archived_name" = "Archived chats"; "lng_archived_name" = "Archived chats";
"lng_archived_add" = "Archive"; "lng_archived_add" = "Archive";

View file

@ -86,7 +86,7 @@ void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow*> row) {
} }
std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxController::createRow(not_null<History*> history) { std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxController::createRow(not_null<History*> history) {
if (history->peer->isSelf()) { if (history->peer->isSelf() || history->peer->isRepliesChat()) {
return nullptr; return nullptr;
} else if (!history->peer->isUser() } else if (!history->peer->isUser()
&& !history->peer->isChat() && !history->peer->isChat()

View file

@ -241,19 +241,31 @@ void FilterChatsPreview::paintEvent(QPaintEvent *e) {
} }
for (auto &[history, userpic, button] : _removePeer) { for (auto &[history, userpic, button] : _removePeer) {
const auto savedMessages = history->peer->isSelf(); const auto savedMessages = history->peer->isSelf();
if (savedMessages) { const auto repliesMessages = history->peer->isRepliesChat();
Ui::EmptyUserpic::PaintSavedMessages( if (savedMessages || repliesMessages) {
p, if (savedMessages) {
iconLeft, Ui::EmptyUserpic::PaintSavedMessages(
top + iconTop, p,
width(), iconLeft,
st.photoSize); top + iconTop,
width(),
st.photoSize);
} else {
Ui::EmptyUserpic::PaintRepliesMessages(
p,
iconLeft,
top + iconTop,
width(),
st.photoSize);
}
p.setPen(st::contactsNameFg); p.setPen(st::contactsNameFg);
p.drawTextLeft( p.drawTextLeft(
nameLeft, nameLeft,
top + nameTop, top + nameTop,
width(), width(),
tr::lng_saved_messages(tr::now)); (savedMessages
? tr::lng_saved_messages(tr::now)
: tr::lng_replies_messages(tr::now)));
} else { } else {
history->peer->paintUserpicLeft( history->peer->paintUserpicLeft(
p, p,

View file

@ -170,6 +170,8 @@ ExceptionRow::ExceptionRow(not_null<History*> history) : Row(history) {
QString ExceptionRow::generateName() { QString ExceptionRow::generateName() {
return peer()->isSelf() return peer()->isSelf()
? tr::lng_saved_messages(tr::now) ? tr::lng_saved_messages(tr::now)
: peer()->isRepliesChat()
? tr::lng_replies_messages(tr::now)
: Row::generateName(); : Row::generateName();
} }
@ -180,10 +182,13 @@ QString ExceptionRow::generateShortName() {
PaintRoundImageCallback ExceptionRow::generatePaintUserpicCallback() { PaintRoundImageCallback ExceptionRow::generatePaintUserpicCallback() {
const auto peer = this->peer(); const auto peer = this->peer();
const auto saved = peer->isSelf(); const auto saved = peer->isSelf();
const auto replies = peer->isRepliesChat();
auto userpic = saved ? nullptr : ensureUserpicView(); auto userpic = saved ? nullptr : ensureUserpicView();
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
if (saved) { if (saved) {
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
} else if (replies) {
Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size);
} else { } else {
peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size); peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size);
} }

View file

@ -36,10 +36,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
PaintRoundImageCallback PaintUserpicCallback( PaintRoundImageCallback PaintUserpicCallback(
not_null<PeerData*> peer, not_null<PeerData*> peer,
bool respectSavedMessagesChat) { bool respectSavedMessagesChat) {
if (respectSavedMessagesChat && peer->isSelf()) { if (respectSavedMessagesChat) {
return [](Painter &p, int x, int y, int outerWidth, int size) { if (peer->isSelf()) {
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); return [](Painter &p, int x, int y, int outerWidth, int size) {
}; Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
};
} else if (peer->isRepliesChat()) {
return [](Painter &p, int x, int y, int outerWidth, int size) {
Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size);
};
}
} }
auto userpic = std::shared_ptr<Data::CloudImageView>(); auto userpic = std::shared_ptr<Data::CloudImageView>();
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
@ -318,6 +324,8 @@ void PeerListBox::addSelectItem(
const auto respect = _controller->respectSavedMessagesChat(); const auto respect = _controller->respectSavedMessagesChat();
const auto text = (respect && peer->isSelf()) const auto text = (respect && peer->isSelf())
? tr::lng_saved_short(tr::now) ? tr::lng_saved_short(tr::now)
: (respect && peer->isRepliesChat())
? tr::lng_replies_messages(tr::now)
: peer->shortName(); : peer->shortName();
addSelectItem( addSelectItem(
peer->id, peer->id,
@ -400,14 +408,16 @@ PeerListRow::PeerListRow(not_null<PeerData*> peer, PeerListRowId id)
, _peer(peer) , _peer(peer)
, _initialized(false) , _initialized(false)
, _isSearchResult(false) , _isSearchResult(false)
, _isSavedMessagesChat(false) { , _isSavedMessagesChat(false)
, _isRepliesMessagesChat(false) {
} }
PeerListRow::PeerListRow(PeerListRowId id) PeerListRow::PeerListRow(PeerListRowId id)
: _id(id) : _id(id)
, _initialized(false) , _initialized(false)
, _isSearchResult(false) , _isSearchResult(false)
, _isSavedMessagesChat(false) { , _isSavedMessagesChat(false)
, _isRepliesMessagesChat(false) {
} }
PeerListRow::~PeerListRow() = default; PeerListRow::~PeerListRow() = default;
@ -470,6 +480,8 @@ void PeerListRow::refreshName(const style::PeerListItem &st) {
} }
const auto text = _isSavedMessagesChat const auto text = _isSavedMessagesChat
? tr::lng_saved_messages(tr::now) ? tr::lng_saved_messages(tr::now)
: _isRepliesMessagesChat
? tr::lng_replies_messages(tr::now)
: generateName(); : generateName();
_name.setText(st.nameStyle, text, Ui::NameTextOptions()); _name.setText(st.nameStyle, text, Ui::NameTextOptions());
} }
@ -481,6 +493,8 @@ QString PeerListRow::generateName() {
QString PeerListRow::generateShortName() { QString PeerListRow::generateShortName() {
return _isSavedMessagesChat return _isSavedMessagesChat
? tr::lng_saved_short(tr::now) ? tr::lng_saved_short(tr::now)
: _isRepliesMessagesChat
? tr::lng_replies_messages(tr::now)
: peer()->shortName(); : peer()->shortName();
} }
@ -493,11 +507,14 @@ std::shared_ptr<Data::CloudImageView> PeerListRow::ensureUserpicView() {
PaintRoundImageCallback PeerListRow::generatePaintUserpicCallback() { PaintRoundImageCallback PeerListRow::generatePaintUserpicCallback() {
const auto saved = _isSavedMessagesChat; const auto saved = _isSavedMessagesChat;
const auto replies = _isRepliesMessagesChat;
const auto peer = this->peer(); const auto peer = this->peer();
auto userpic = saved ? nullptr : ensureUserpicView(); auto userpic = saved ? nullptr : ensureUserpicView();
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable { return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
if (saved) { if (saved) {
Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size);
} else if (replies) {
Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, outerWidth, size);
} else { } else {
peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size); peer->paintUserpicLeft(p, userpic, x, y, outerWidth, size);
} }
@ -603,6 +620,8 @@ void PeerListRow::paintDisabledCheckUserpic(
if (_isSavedMessagesChat) { if (_isSavedMessagesChat) {
Ui::EmptyUserpic::PaintSavedMessages(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); Ui::EmptyUserpic::PaintSavedMessages(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2);
} else if (_isRepliesMessagesChat) {
Ui::EmptyUserpic::PaintRepliesMessages(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2);
} else { } else {
peer()->paintUserpicLeft(p, _userpic, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); peer()->paintUserpicLeft(p, _userpic, userpicLeft, userpicTop, outerWidth, userpicRadius * 2);
} }
@ -731,10 +750,12 @@ void PeerListContent::changeCheckState(
} }
void PeerListContent::addRowEntry(not_null<PeerListRow*> row) { void PeerListContent::addRowEntry(not_null<PeerListRow*> row) {
if (_controller->respectSavedMessagesChat() if (_controller->respectSavedMessagesChat() && !row->special()) {
&& !row->special() if (row->peer()->isSelf()) {
&& row->peer()->isSelf()) { row->setIsSavedMessagesChat(true);
row->setIsSavedMessagesChat(true); } else if (row->peer()->isRepliesChat()) {
row->setIsRepliesMessagesChat(true);
}
} }
_rowsById.emplace(row->id(), row); _rowsById.emplace(row->id(), row);
if (!row->special()) { if (!row->special()) {

View file

@ -146,12 +146,12 @@ public:
void setIsSearchResult(bool isSearchResult) { void setIsSearchResult(bool isSearchResult) {
_isSearchResult = isSearchResult; _isSearchResult = isSearchResult;
} }
bool isSavedMessagesChat() const {
return _isSavedMessagesChat;
}
void setIsSavedMessagesChat(bool isSavedMessagesChat) { void setIsSavedMessagesChat(bool isSavedMessagesChat) {
_isSavedMessagesChat = isSavedMessagesChat; _isSavedMessagesChat = isSavedMessagesChat;
} }
void setIsRepliesMessagesChat(bool isRepliesMessagesChat) {
_isRepliesMessagesChat = isRepliesMessagesChat;
}
template <typename UpdateCallback> template <typename UpdateCallback>
void setChecked( void setChecked(
@ -234,6 +234,7 @@ private:
bool _initialized : 1; bool _initialized : 1;
bool _isSearchResult : 1; bool _isSearchResult : 1;
bool _isSavedMessagesChat : 1; bool _isSavedMessagesChat : 1;
bool _isRepliesMessagesChat : 1;
}; };

View file

@ -584,8 +584,7 @@ void ChooseRecipientBoxController::rowClicked(not_null<PeerListRow*> row) {
auto ChooseRecipientBoxController::createRow( auto ChooseRecipientBoxController::createRow(
not_null<History*> history) -> std::unique_ptr<Row> { not_null<History*> history) -> std::unique_ptr<Row> {
const auto peer = history->peer; const auto peer = history->peer;
const auto skip = peer->isChannel() const auto skip = (peer->isBroadcast() && !peer->canWrite())
&& !peer->isMegagroup() || peer->isRepliesChat();
&& !peer->canWrite();
return skip ? nullptr : std::make_unique<Row>(history); return skip ? nullptr : std::make_unique<Row>(history);
} }

View file

@ -203,8 +203,7 @@ public:
protected: protected:
void prepareViewHook() override; void prepareViewHook() override;
std::unique_ptr<Row> createRow( std::unique_ptr<Row> createRow(not_null<History*> history) override;
not_null<History*> history) override;
private: private:
const not_null<Window::SessionNavigation*> _navigation; const not_null<Window::SessionNavigation*> _navigation;

View file

@ -635,7 +635,11 @@ void ShareBox::Inner::updateChat(not_null<PeerData*> peer) {
void ShareBox::Inner::updateChatName( void ShareBox::Inner::updateChatName(
not_null<Chat*> chat, not_null<Chat*> chat,
not_null<PeerData*> peer) { not_null<PeerData*> peer) {
const auto text = peer->isSelf() ? tr::lng_saved_messages(tr::now) : peer->name; const auto text = peer->isSelf()
? tr::lng_saved_messages(tr::now)
: peer->isRepliesChat()
? tr::lng_replies_messages(tr::now)
: peer->name;
chat->name.setText(st::shareNameStyle, text, Ui::NameTextOptions()); chat->name.setText(st::shareNameStyle, text, Ui::NameTextOptions());
} }

View file

@ -541,6 +541,13 @@ void PeerData::fillNames() {
if (localized != english) { if (localized != english) {
appendToIndex(localized); appendToIndex(localized);
} }
} else if (isRepliesChat()) {
const auto english = qsl("Replies");
const auto localized = tr::lng_replies_messages(tr::now);
appendToIndex(english);
if (localized != english) {
appendToIndex(localized);
}
} }
} else if (const auto channel = asChannel()) { } else if (const auto channel = asChannel()) {
appendToIndex(channel->username); appendToIndex(channel->username);
@ -743,6 +750,10 @@ bool PeerData::isBroadcast() const {
return isChannel() ? asChannel()->isBroadcast() : false; return isChannel() ? asChannel()->isBroadcast() : false;
} }
bool PeerData::isRepliesChat() const {
return (id == peerFromUser(708513));
}
bool PeerData::canWrite() const { bool PeerData::canWrite() const {
if (const auto user = asUser()) { if (const auto user = asUser()) {
return user->canWrite(); return user->canWrite();

View file

@ -159,6 +159,10 @@ public:
[[nodiscard]] bool isScam() const; [[nodiscard]] bool isScam() const;
[[nodiscard]] bool isMegagroup() const; [[nodiscard]] bool isMegagroup() const;
[[nodiscard]] bool isBroadcast() const; [[nodiscard]] bool isBroadcast() const;
[[nodiscard]] bool isRepliesChat() const;
[[nodiscard]] bool sharedMediaInfo() const {
return isSelf() || isRepliesChat();
}
[[nodiscard]] bool isNotificationsUser() const { [[nodiscard]] bool isNotificationsUser() const {
return (id == peerFromUser(333000)) return (id == peerFromUser(333000))

View file

@ -170,6 +170,10 @@ rpl::producer<bool> PeerFlagValue(
rpl::producer<bool> CanWriteValue(UserData *user) { rpl::producer<bool> CanWriteValue(UserData *user) {
using namespace rpl::mappers; using namespace rpl::mappers;
if (user->isRepliesChat()) {
return rpl::single(false);
}
return PeerFlagValue(user, MTPDuser::Flag::f_deleted) return PeerFlagValue(user, MTPDuser::Flag::f_deleted)
| rpl::map(!_1); | rpl::map(!_1);
} }

View file

@ -140,7 +140,7 @@ public:
} }
bool canWrite() const { bool canWrite() const {
// Duplicated in Data::CanWriteValue(). // Duplicated in Data::CanWriteValue().
return !isInaccessible(); return !isInaccessible() && !isRepliesChat();
} }
bool canShareThisContact() const; bool canShareThisContact() const;

View file

@ -819,6 +819,8 @@ void InnerWidget::paintSearchInChat(Painter &p) const {
if (const auto peer = _searchInChat.peer()) { if (const auto peer = _searchInChat.peer()) {
if (peer->isSelf()) { if (peer->isSelf()) {
paintSearchInSaved(p, top, _searchInChatText); paintSearchInSaved(p, top, _searchInChatText);
} else if (peer->isRepliesChat()) {
paintSearchInReplies(p, top, _searchInChatText);
} else { } else {
paintSearchInPeer(p, peer, _searchInChatUserpic, top, _searchInChatText); paintSearchInPeer(p, peer, _searchInChatUserpic, top, _searchInChatText);
} }
@ -896,6 +898,16 @@ void InnerWidget::paintSearchInSaved(
paintSearchInFilter(p, paintUserpic, top, nullptr, text); paintSearchInFilter(p, paintUserpic, top, nullptr, text);
} }
void InnerWidget::paintSearchInReplies(
Painter &p,
int top,
const Ui::Text::String &text) const {
const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
Ui::EmptyUserpic::PaintRepliesMessages(p, x, y, width(), size);
};
paintSearchInFilter(p, paintUserpic, top, nullptr, text);
}
//void InnerWidget::paintSearchInFeed( // #feed //void InnerWidget::paintSearchInFeed( // #feed
// Painter &p, // Painter &p,
// not_null<Data::Feed*> feed, // not_null<Data::Feed*> feed,
@ -2359,6 +2371,8 @@ void InnerWidget::refreshSearchInChatLabel() {
if (const auto peer = _searchInChat.peer()) { if (const auto peer = _searchInChat.peer()) {
if (peer->isSelf()) { if (peer->isSelf()) {
return tr::lng_saved_messages(tr::now); return tr::lng_saved_messages(tr::now);
} else if (peer->isRepliesChat()) {
return tr::lng_replies_messages(tr::now);
} }
return peer->name; return peer->name;
//} else if (const auto feed = _searchInChat.feed()) { // #feed //} else if (const auto feed = _searchInChat.feed()) { // #feed

View file

@ -287,6 +287,10 @@ private:
Painter &p, Painter &p,
int top, int top,
const Ui::Text::String &text) const; const Ui::Text::String &text) const;
void paintSearchInReplies(
Painter &p,
int top,
const Ui::Text::String &text) const;
//void paintSearchInFeed( // #feed //void paintSearchInFeed( // #feed
// Painter &p, // Painter &p,
// not_null<Data::Feed*> feed, // not_null<Data::Feed*> feed,

View file

@ -39,7 +39,7 @@ constexpr int kRecentlyInSeconds = 20 * 3600;
const auto kPsaBadgePrefix = "cloud_lng_badge_psa_"; const auto kPsaBadgePrefix = "cloud_lng_badge_psa_";
bool ShowUserBotIcon(not_null<UserData*> user) { bool ShowUserBotIcon(not_null<UserData*> user) {
return user->isBot() && !user->isSupport(); return user->isBot() && !user->isSupport() && !user->isRepliesChat();
} }
void PaintRowTopRight(Painter &p, const QString &text, QRect &rectForName, bool active, bool selected) { void PaintRowTopRight(Painter &p, const QString &text, QRect &rectForName, bool active, bool selected) {
@ -209,7 +209,8 @@ enum class Flag {
Selected = 0x02, Selected = 0x02,
SearchResult = 0x04, SearchResult = 0x04,
SavedMessages = 0x08, SavedMessages = 0x08,
AllowUserOnline = 0x10, RepliesMessages = 0x10,
AllowUserOnline = 0x20,
//FeedSearchResult = 0x10, // #feed //FeedSearchResult = 0x10, // #feed
}; };
inline constexpr bool is_flag_type(Flag) { return true; } inline constexpr bool is_flag_type(Flag) { return true; }
@ -257,6 +258,13 @@ void paintRow(
st::dialogsPadding.y(), st::dialogsPadding.y(),
fullWidth, fullWidth,
st::dialogsPhotoSize); st::dialogsPhotoSize);
} else if (flags & Flag::RepliesMessages) {
Ui::EmptyUserpic::PaintRepliesMessages(
p,
st::dialogsPadding.x(),
st::dialogsPadding.y(),
fullWidth,
st::dialogsPhotoSize);
} else if (from) { } else if (from) {
row->paintUserpic( row->paintUserpic(
p, p,
@ -433,8 +441,10 @@ void paintRow(
sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), fullWidth); sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), fullWidth);
} }
if (flags & Flag::SavedMessages) { if (flags & (Flag::SavedMessages | Flag::RepliesMessages)) {
auto text = tr::lng_saved_messages(tr::now); auto text = (flags & Flag::SavedMessages)
? tr::lng_saved_messages(tr::now)
: tr::lng_replies_messages(tr::now);
const auto textWidth = st::msgNameFont->width(text); const auto textWidth = st::msgNameFont->width(text);
if (textWidth > rectForName.width()) { if (textWidth > rectForName.width()) {
text = st::msgNameFont->elided(text, rectForName.width()); text = st::msgNameFont->elided(text, rectForName.width());
@ -701,7 +711,8 @@ void RowPainter::paint(
const auto flags = (active ? Flag::Active : Flag(0)) const auto flags = (active ? Flag::Active : Flag(0))
| (selected ? Flag::Selected : Flag(0)) | (selected ? Flag::Selected : Flag(0))
| (allowUserOnline ? Flag::AllowUserOnline : Flag(0)) | (allowUserOnline ? Flag::AllowUserOnline : Flag(0))
| (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0)); | (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0))
| (peer && peer->isRepliesChat() ? Flag::RepliesMessages : Flag(0));
const auto paintItemCallback = [&](int nameleft, int namewidth) { const auto paintItemCallback = [&](int nameleft, int namewidth) {
const auto texttop = st::dialogsPadding.y() const auto texttop = st::dialogsPadding.y()
+ st::msgNameFont->height + st::msgNameFont->height
@ -881,10 +892,13 @@ void RowPainter::paint(
}; };
const auto showSavedMessages = history->peer->isSelf() const auto showSavedMessages = history->peer->isSelf()
&& !row->searchInChat(); && !row->searchInChat();
const auto showRepliesMessages = history->peer->isRepliesChat()
&& !row->searchInChat();
const auto flags = (active ? Flag::Active : Flag(0)) const auto flags = (active ? Flag::Active : Flag(0))
| (selected ? Flag::Selected : Flag(0)) | (selected ? Flag::Selected : Flag(0))
| Flag::SearchResult | Flag::SearchResult
| (showSavedMessages ? Flag::SavedMessages : Flag(0))/* // #feed | (showSavedMessages ? Flag::SavedMessages : Flag(0))
| (showRepliesMessages ? Flag::RepliesMessages : Flag(0))/* // #feed
| (row->searchInChat().feed() ? Flag::FeedSearchResult : Flag(0))*/; | (row->searchInChat().feed() ? Flag::FeedSearchResult : Flag(0))*/;
paintRow( paintRow(
p, p,

View file

@ -1466,6 +1466,8 @@ DialogInfo::Type DialogTypeFromChat(const Chat &chat) {
DialogInfo::Type DialogTypeFromUser(const User &user) { DialogInfo::Type DialogTypeFromUser(const User &user) {
return user.isSelf return user.isSelf
? DialogInfo::Type::Self ? DialogInfo::Type::Self
: user.isReplies
? DialogInfo::Type::Replies
: user.isBot : user.isBot
? DialogInfo::Type::Bot ? DialogInfo::Type::Bot
: DialogInfo::Type::Personal; : DialogInfo::Type::Personal;

View file

@ -209,6 +209,7 @@ struct User {
int32 id; int32 id;
bool isBot = false; bool isBot = false;
bool isSelf = false; bool isSelf = false;
bool isReplies = false;
MTPInputUser input = MTP_inputUserEmpty(); MTPInputUser input = MTP_inputUserEmpty();
@ -554,6 +555,7 @@ struct DialogInfo {
enum class Type { enum class Type {
Unknown, Unknown,
Self, Self,
Replies,
Personal, Personal,
Bot, Bot,
PrivateGroup, PrivateGroup,

View file

@ -564,6 +564,8 @@ void ControllerObject::fillMessagesState(
result.entityName = dialog->name; result.entityName = dialog->name;
result.entityType = (dialog->type == Data::DialogInfo::Type::Self) result.entityType = (dialog->type == Data::DialogInfo::Type::Self)
? ProcessingState::EntityType::SavedMessages ? ProcessingState::EntityType::SavedMessages
: (dialog->type == Data::DialogInfo::Type::Replies)
? ProcessingState::EntityType::RepliesMessages
: ProcessingState::EntityType::Chat; : ProcessingState::EntityType::Chat;
result.itemIndex = _messagesWritten + progress.itemIndex; result.itemIndex = _messagesWritten + progress.itemIndex;
result.itemCount = std::max(_messagesCount, result.itemIndex); result.itemCount = std::max(_messagesCount, result.itemIndex);

View file

@ -56,6 +56,7 @@ struct ProcessingState {
enum class EntityType { enum class EntityType {
Chat, Chat,
SavedMessages, SavedMessages,
RepliesMessages,
Other, Other,
}; };

View file

@ -2466,6 +2466,7 @@ Result HtmlWriter::writeDialogEnd() {
switch (type) { switch (type) {
case Type::Unknown: return "unknown"; case Type::Unknown: return "unknown";
case Type::Self: case Type::Self:
case Type::Replies:
case Type::Personal: return "private"; case Type::Personal: return "private";
case Type::Bot: return "bot"; case Type::Bot: return "bot";
case Type::PrivateGroup: case Type::PrivateGroup:
@ -2480,6 +2481,7 @@ Result HtmlWriter::writeDialogEnd() {
switch (type) { switch (type) {
case Type::Unknown: case Type::Unknown:
case Type::Self: case Type::Self:
case Type::Replies:
case Type::Personal: case Type::Personal:
case Type::Bot: return "Deleted Account"; case Type::Bot: return "Deleted Account";
case Type::PrivateGroup: case Type::PrivateGroup:
@ -2494,6 +2496,8 @@ Result HtmlWriter::writeDialogEnd() {
const Data::DialogInfo &dialog) -> QByteArray { const Data::DialogInfo &dialog) -> QByteArray {
if (dialog.type == Type::Self) { if (dialog.type == Type::Self) {
return "Saved messages"; return "Saved messages";
} else if (dialog.type == Type::Replies) {
return "Replies";
} }
return dialog.name; return dialog.name;
}; };
@ -2514,7 +2518,7 @@ Result HtmlWriter::writeDialogEnd() {
+ (outgoing ? " outgoing messages" : " messages"); + (outgoing ? " outgoing messages" : " messages");
}; };
auto userpic = UserpicData{ auto userpic = UserpicData{
(_dialog.type == Type::Self ((_dialog.type == Type::Self || _dialog.type == Type::Replies)
? kSavedMessagesColorIndex ? kSavedMessagesColorIndex
: Data::PeerColorIndex(Data::BarePeerId(_dialog.peerId))), : Data::PeerColorIndex(Data::BarePeerId(_dialog.peerId))),
kEntryUserpicSize kEntryUserpicSize

View file

@ -1011,6 +1011,7 @@ Result JsonWriter::writeDialogStart(const Data::DialogInfo &data) {
switch (type) { switch (type) {
case Type::Unknown: return ""; case Type::Unknown: return "";
case Type::Self: return "saved_messages"; case Type::Self: return "saved_messages";
case Type::Replies: return "replies";
case Type::Personal: return "personal_chat"; case Type::Personal: return "personal_chat";
case Type::Bot: return "bot_chat"; case Type::Bot: return "bot_chat";
case Type::PrivateGroup: return "private_group"; case Type::PrivateGroup: return "private_group";
@ -1026,7 +1027,7 @@ Result JsonWriter::writeDialogStart(const Data::DialogInfo &data) {
? QByteArray() ? QByteArray()
: prepareArrayItemStart(); : prepareArrayItemStart();
block.append(pushNesting(Context::kObject)); block.append(pushNesting(Context::kObject));
if (data.type != Type::Self) { if (data.type != Type::Self && data.type != Type::Replies) {
block.append(prepareObjectItemStart("name") block.append(prepareObjectItemStart("name")
+ StringAllowNull(data.name)); + StringAllowNull(data.name));
} }

View file

@ -883,6 +883,7 @@ Result TextWriter::writeDialogEnd() {
switch (type) { switch (type) {
case Type::Unknown: return "(unknown)"; case Type::Unknown: return "(unknown)";
case Type::Self: case Type::Self:
case Type::Replies:
case Type::Personal: return "Personal chat"; case Type::Personal: return "Personal chat";
case Type::Bot: return "Bot chat"; case Type::Bot: return "Bot chat";
case Type::PrivateGroup: return "Private group"; case Type::PrivateGroup: return "Private group";
@ -898,6 +899,8 @@ Result TextWriter::writeDialogEnd() {
Type type) -> QByteArray { Type type) -> QByteArray {
if (dialog.type == Type::Self) { if (dialog.type == Type::Self) {
return "Saved messages"; return "Saved messages";
} else if (dialog.type == Type::Replies) {
return "Replies";
} }
const auto name = dialog.name; const auto name = dialog.name;
if (!name.isEmpty()) { if (!name.isEmpty()) {

View file

@ -101,7 +101,9 @@ Content ContentFromState(
? tr::lng_deleted(tr::now) ? tr::lng_deleted(tr::now)
: (state.entityType == ProcessingState::EntityType::Chat) : (state.entityType == ProcessingState::EntityType::Chat)
? state.entityName ? state.entityName
: tr::lng_saved_messages(tr::now)), : (state.entityType == ProcessingState::EntityType::SavedMessages)
? tr::lng_saved_messages(tr::now)
: tr::lng_replies_messages(tr::now)),
(state.itemCount > 0 (state.itemCount > 0
? (QString::number(state.itemIndex) ? (QString::number(state.itemIndex)
+ " / " + " / "

View file

@ -388,7 +388,10 @@ void HistoryInner::enumerateItemsInHistory(History *history, int historytop, Met
} }
bool HistoryInner::canHaveFromUserpics() const { bool HistoryInner::canHaveFromUserpics() const {
if (_peer->isUser() && !_peer->isSelf() && !Core::App().settings().chatWide()) { if (_peer->isUser()
&& !_peer->isSelf()
&& !_peer->isRepliesChat()
&& !Core::App().settings().chatWide()) {
return false; return false;
} else if (_peer->isChannel() && !_peer->isMegagroup()) { } else if (_peer->isChannel() && !_peer->isMegagroup()) {
return false; return false;

View file

@ -259,7 +259,8 @@ bool HistoryItem::isDiscussionPost() const {
PeerData *HistoryItem::displayFrom() const { PeerData *HistoryItem::displayFrom() const {
if (const auto sender = discussionPostOriginalSender()) { if (const auto sender = discussionPostOriginalSender()) {
return sender; return sender;
} else if (history()->peer->isSelf()) { } else if (history()->peer->isSelf()
|| history()->peer->isRepliesChat()) {
return senderOriginal(); return senderOriginal();
} }
return author().get(); return author().get();

View file

@ -1935,7 +1935,9 @@ void HistoryWidget::updateFieldSubmitSettings() {
} }
void HistoryWidget::updateNotifyControls() { void HistoryWidget::updateNotifyControls() {
if (!_peer || !_peer->isChannel()) return; if (!_peer || (!_peer->isChannel() && !_peer->isRepliesChat())) {
return;
}
_muteUnmute->setText((_history->mute() _muteUnmute->setText((_history->mute()
? tr::lng_channel_unmute(tr::now) ? tr::lng_channel_unmute(tr::now)
@ -3647,7 +3649,10 @@ bool HistoryWidget::isJoinChannel() const {
} }
bool HistoryWidget::isMuteUnmute() const { bool HistoryWidget::isMuteUnmute() const {
return _peer && _peer->isChannel() && _peer->asChannel()->isBroadcast() && !_peer->asChannel()->canPublish(); return _peer
&& ((_peer->isBroadcast()
&& !_peer->asChannel()->canPublish())
|| _peer->isRepliesChat());
} }
bool HistoryWidget::showRecordButton() const { bool HistoryWidget::showRecordButton() const {

View file

@ -429,7 +429,8 @@ bool Element::computeIsAttachToPrevious(not_null<Element*> previous) {
&& mayBeAttached(item) && mayBeAttached(item)
&& mayBeAttached(prev); && mayBeAttached(prev);
if (possible) { if (possible) {
if (item->history()->peer->isSelf()) { if (item->history()->peer->isSelf()
|| item->history()->peer->isRepliesChat()) {
return IsAttachedToPreviousInSavedMessages(prev, item); return IsAttachedToPreviousInSavedMessages(prev, item);
} else { } else {
return prev->from() == item->from(); return prev->from() == item->from();

View file

@ -1018,6 +1018,11 @@ void Message::unloadHeavyPart() {
_comments = nullptr; _comments = nullptr;
} }
bool Message::showForwardsFromSender() const {
const auto peer = message()->history()->peer;
return peer->isSelf() || peer->isRepliesChat();
}
bool Message::hasFromPhoto() const { bool Message::hasFromPhoto() const {
if (isHidden()) { if (isHidden()) {
return false; return false;
@ -1032,7 +1037,7 @@ bool Message::hasFromPhoto() const {
return false; return false;
} else if (Core::App().settings().chatWide()) { } else if (Core::App().settings().chatWide()) {
return true; return true;
} else if (item->history()->peer->isSelf()) { } else if (showForwardsFromSender()) {
return item->Has<HistoryMessageForwarded>(); return item->Has<HistoryMessageForwarded>();
} }
return !item->out() && !item->history()->peer->isUser(); return !item->out() && !item->history()->peer->isUser();
@ -1844,7 +1849,7 @@ bool Message::hasFromName() const {
const auto item = message(); const auto item = message();
return (!hasOutLayout() || item->from()->isMegagroup()) return (!hasOutLayout() || item->from()->isMegagroup())
&& (!item->history()->peer->isUser() && (!item->history()->peer->isUser()
|| item->history()->peer->isSelf()); || showForwardsFromSender());
} break; } break;
case Context::ContactPreview: case Context::ContactPreview:
return false; return false;
@ -1861,7 +1866,7 @@ bool Message::displayFromName() const {
bool Message::displayForwardedFrom() const { bool Message::displayForwardedFrom() const {
const auto item = message(); const auto item = message();
if (item->history()->peer->isSelf()) { if (showForwardsFromSender()) {
return false; return false;
} }
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) { if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
@ -1885,6 +1890,8 @@ bool Message::hasOutLayout() const {
const auto item = message(); const auto item = message();
if (item->history()->peer->isSelf()) { if (item->history()->peer->isSelf()) {
return !item->Has<HistoryMessageForwarded>(); return !item->Has<HistoryMessageForwarded>();
} else if (showForwardsFromSender()) {
return false;
} }
return item->out() && !item->isPost(); return item->out() && !item->isPost();
} }
@ -1934,7 +1941,7 @@ bool Message::displayFastShare() const {
return !peer->isMegagroup(); return !peer->isMegagroup();
} else if (const auto user = peer->asUser()) { } else if (const auto user = peer->asUser()) {
if (const auto forwarded = item->Get<HistoryMessageForwarded>()) { if (const auto forwarded = item->Get<HistoryMessageForwarded>()) {
return !peer->isSelf() return !showForwardsFromSender()
&& !item->out() && !item->out()
&& forwarded->originalSender && forwarded->originalSender
&& forwarded->originalSender->isChannel() && forwarded->originalSender->isChannel()

View file

@ -120,6 +120,7 @@ private:
void refreshEditedBadge(); void refreshEditedBadge();
void fromNameUpdated(int width) const; void fromNameUpdated(int width) const;
[[nodiscard]] bool showForwardsFromSender() const;
[[nodiscard]] TextSelection skipTextSelection( [[nodiscard]] TextSelection skipTextSelection(
TextSelection selection) const; TextSelection selection) const;
[[nodiscard]] TextSelection unskipTextSelection( [[nodiscard]] TextSelection unskipTextSelection(

View file

@ -329,7 +329,7 @@ void TopBarWidget::paintTopBar(Painter &p) {
const auto history = _activeChat.history(); const auto history = _activeChat.history();
const auto folder = _activeChat.folder(); const auto folder = _activeChat.folder();
if (folder if (folder
|| history->peer->isSelf() || history->peer->sharedMediaInfo()
|| (_section == Section::Scheduled) || (_section == Section::Scheduled)
|| !_customTitleText.isEmpty()) { || !_customTitleText.isEmpty()) {
// #TODO feed name emoji. // #TODO feed name emoji.
@ -341,7 +341,9 @@ void TopBarWidget::paintTopBar(Painter &p) {
: tr::lng_scheduled_messages(tr::now)) : tr::lng_scheduled_messages(tr::now))
: folder : folder
? folder->chatListName() ? folder->chatListName()
: tr::lng_saved_messages(tr::now); : history->peer->isSelf()
? tr::lng_saved_messages(tr::now)
: tr::lng_replies_messages(tr::now);
const auto textWidth = st::historySavedFont->width(text); const auto textWidth = st::historySavedFont->width(text);
if (availableWidth < textWidth) { if (availableWidth < textWidth) {
text = st::historySavedFont->elided(text, availableWidth); text = st::historySavedFont->elided(text, availableWidth);
@ -467,6 +469,10 @@ void TopBarWidget::infoClicked() {
_controller->showSection(Info::Memento( _controller->showSection(Info::Memento(
_activeChat.peer(), _activeChat.peer(),
Info::Section(Storage::SharedMediaType::Photo))); Info::Section(Storage::SharedMediaType::Photo)));
} else if (_activeChat.peer()->isRepliesChat()) {
_controller->showSection(Info::Memento(
_activeChat.peer(),
Info::Section(Storage::SharedMediaType::Photo)));
} else { } else {
_controller->showPeerInfo(_activeChat.peer()); _controller->showPeerInfo(_activeChat.peer());
} }

View file

@ -86,7 +86,7 @@ std::vector<std::unique_ptr<ContentMemento>> Memento::DefaultStack(
} }
Section Memento::DefaultSection(not_null<PeerData*> peer) { Section Memento::DefaultSection(not_null<PeerData*> peer) {
if (peer->isSelf()) { if (peer->sharedMediaInfo()) {
return Section(Section::MediaType::Photo); return Section(Section::MediaType::Photo);
} }
return Section(Section::Type::Profile); return Section(Section::Type::Profile);
@ -94,7 +94,7 @@ Section Memento::DefaultSection(not_null<PeerData*> peer) {
// // #feed // // #feed
//Section Memento::DefaultSection(Dialogs::Key key) { //Section Memento::DefaultSection(Dialogs::Key key) {
// if (const auto peer = key.peer()) { // if (const auto peer = key.peer()) {
// if (peer->isSelf()) { // if (peer->sharedMediaInfo()) {
// return Section(Section::MediaType::Photo); // return Section(Section::MediaType::Photo);
// } // }
// } // }

View file

@ -575,7 +575,7 @@ rpl::producer<QString> TitleValue(
Unexpected("Bad peer type in Info::TitleValue()"); Unexpected("Bad peer type in Info::TitleValue()");
case Section::Type::Media: case Section::Type::Media:
if (peer->isSelf() && isStackBottom) { if (peer->sharedMediaInfo() && isStackBottom) {
return tr::lng_profile_shared_media(); return tr::lng_profile_shared_media();
} }
switch (section.mediaType()) { switch (section.mediaType()) {

View file

@ -154,16 +154,16 @@ void WrapWidget::injectActivePeerProfile(not_null<PeerData*> peer) {
? _historyStack.front().section->section().mediaType() ? _historyStack.front().section->section().mediaType()
: _controller->section().mediaType(); : _controller->section().mediaType();
}(); }();
const auto expectedType = peer->isSelf() const auto expectedType = peer->sharedMediaInfo()
? Section::Type::Media ? Section::Type::Media
: Section::Type::Profile; : Section::Type::Profile;
const auto expectedMediaType = peer->isSelf() const auto expectedMediaType = peer->sharedMediaInfo()
? Section::MediaType::Photo ? Section::MediaType::Photo
: Section::MediaType::kCount; : Section::MediaType::kCount;
if (firstSectionType != expectedType if (firstSectionType != expectedType
|| firstSectionMediaType != expectedMediaType || firstSectionMediaType != expectedMediaType
|| firstPeer != peer) { || firstPeer != peer) {
auto section = peer->isSelf() auto section = peer->sharedMediaInfo()
? Section(Section::MediaType::Photo) ? Section(Section::MediaType::Photo)
: Section(Section::Type::Profile); : Section(Section::Type::Profile);
injectActiveProfileMemento(std::move( injectActiveProfileMemento(std::move(
@ -481,7 +481,7 @@ void WrapWidget::addProfileCallsButton() {
const auto peer = key().peer(); const auto peer = key().peer();
const auto user = peer ? peer->asUser() : nullptr; const auto user = peer ? peer->asUser() : nullptr;
if (!user if (!user
|| user->isSelf() || user->sharedMediaInfo()
|| !user->session().serverConfig().phoneCallsEnabled.current()) { || !user->session().serverConfig().phoneCallsEnabled.current()) {
return; return;
} }

View file

@ -264,6 +264,8 @@ void Manager::Private::showNotification(
if (!hideNameAndPhoto && [notification respondsToSelector:@selector(setContentImage:)]) { if (!hideNameAndPhoto && [notification respondsToSelector:@selector(setContentImage:)]) {
auto userpic = peer->isSelf() auto userpic = peer->isSelf()
? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize) ? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize)
: peer->isRepliesChat()
? Ui::EmptyUserpic::GenerateRepliesMessages(st::notifyMacPhotoSize)
: peer->genUserpic(userpicView, st::notifyMacPhotoSize); : peer->genUserpic(userpicView, st::notifyMacPhotoSize);
NSImage *img = [qt_mac_create_nsimage(userpic) autorelease]; NSImage *img = [qt_mac_create_nsimage(userpic) autorelease];
[notification setContentImage:img]; [notification setContentImage:img];

View file

@ -53,6 +53,10 @@ inline bool IsSelfPeer(PeerData *peer) {
return peer && peer->isSelf(); return peer && peer->isSelf();
} }
inline bool IsRepliesPeer(PeerData *peer) {
return peer && peer->isRepliesChat();
}
QImage PrepareImage() { QImage PrepareImage() {
const auto s = kCircleDiameter * cIntRetinaFactor(); const auto s = kCircleDiameter * cIntRetinaFactor();
auto result = QImage(QSize(s, s), QImage::Format_ARGB32_Premultiplied); auto result = QImage(QSize(s, s), QImage::Format_ARGB32_Premultiplied);
@ -69,6 +73,15 @@ QImage SavedMessagesUserpic() {
return result; return result;
} }
QImage RepliesMessagesUserpic() {
auto result = PrepareImage();
Painter paint(&result);
const auto s = result.width();
Ui::EmptyUserpic::PaintRepliesMessages(paint, 0, 0, s, s);
return result;
}
QImage ArchiveUserpic(not_null<Data::Folder*> folder) { QImage ArchiveUserpic(not_null<Data::Folder*> folder) {
auto result = PrepareImage(); auto result = PrepareImage();
Painter paint(&result); Painter paint(&result);
@ -125,7 +138,7 @@ NSRect PeerRectByIndex(int index) {
} }
TimeId CalculateOnlineTill(not_null<PeerData*> peer) { TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
if (peer->isSelf()) { if (peer->isSelf() || peer->isRepliesChat()) {
return 0; return 0;
} }
if (const auto user = peer->asUser()) { if (const auto user = peer->asUser()) {
@ -172,10 +185,12 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
std::vector<std::unique_ptr<Pin>> _pins; std::vector<std::unique_ptr<Pin>> _pins;
QImage _savedMessages; QImage _savedMessages;
QImage _repliesMessages;
QImage _archive; QImage _archive;
bool _hasArchive; bool _hasArchive;
bool _selfUnpinned; bool _selfUnpinned;
bool _repliesUnpinned;
rpl::event_stream<not_null<NSEvent*>> _touches; rpl::event_stream<not_null<NSEvent*>> _touches;
rpl::event_stream<not_null<NSPressGestureRecognizer*>> _gestures; rpl::event_stream<not_null<NSPressGestureRecognizer*>> _gestures;
@ -458,6 +473,7 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
_session = session; _session = session;
_hasArchive = _selfUnpinned = false; _hasArchive = _selfUnpinned = false;
_savedMessages = SavedMessagesUserpic(); _savedMessages = SavedMessagesUserpic();
_repliesMessages = RepliesMessagesUserpic();
auto *gesture = [[[NSPressGestureRecognizer alloc] auto *gesture = [[[NSPressGestureRecognizer alloc]
initWithTarget:self initWithTarget:self
@ -504,6 +520,9 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
if (IsSelfPeer(pin->peer)) { if (IsSelfPeer(pin->peer)) {
pin->userpic = _savedMessages; pin->userpic = _savedMessages;
return; return;
} else if (IsRepliesPeer(pin->peer)) {
pin->userpic = _repliesMessages;
return;
} }
auto userpic = PrepareImage(); auto userpic = PrepareImage();
Painter p(&userpic); Painter p(&userpic);
@ -629,6 +648,7 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
return std::make_unique<Pin>(std::move(pin)); return std::make_unique<Pin>(std::move(pin));
}) | ranges::to_vector; }) | ranges::to_vector;
_selfUnpinned = ranges::none_of(peers, &PeerData::isSelf); _selfUnpinned = ranges::none_of(peers, &PeerData::isSelf);
_repliesUnpinned = ranges::none_of(peers, &PeerData::isRepliesChat);
peerChangedLifetime->destroy(); peerChangedLifetime->destroy();
for (const auto &pin : _pins) { for (const auto &pin : _pins) {
@ -705,6 +725,7 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
_archive = ArchiveUserpic(f); _archive = ArchiveUserpic(f);
} }
_savedMessages = SavedMessagesUserpic(); _savedMessages = SavedMessagesUserpic();
_repliesMessages = RepliesMessagesUserpic();
updateUserpics(); updateUserpics();
}); });
}, _lifetime); }, _lifetime);
@ -771,6 +792,8 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
return _archive; return _archive;
} else if (_selfUnpinned) { } else if (_selfUnpinned) {
return _savedMessages; return _savedMessages;
} else if (_repliesUnpinned) {
return _repliesMessages;
} }
} }
return _pins[i]->userpic; return _pins[i]->userpic;

View file

@ -116,7 +116,8 @@ auto BlockPeerBoxController::createRow(not_null<History*> history)
-> std::unique_ptr<BlockPeerBoxController::Row> { -> std::unique_ptr<BlockPeerBoxController::Row> {
if (!history->peer->isUser() if (!history->peer->isUser()
|| history->peer->isServiceUser() || history->peer->isServiceUser()
|| history->peer->isSelf()) { || history->peer->isSelf()
|| history->peer->isRepliesChat()) {
return nullptr; return nullptr;
} }
auto row = std::make_unique<Row>(history); auto row = std::make_unique<Row>(history);

View file

@ -91,6 +91,15 @@ void PaintSavedMessagesInner(
} }
} }
void PaintRepliesMessagesInner(
Painter &p,
int x,
int y,
int size,
const style::color &bg,
const style::color &fg) {
}
template <typename Callback> template <typename Callback>
[[nodiscard]] QPixmap Generate(int size, Callback callback) { [[nodiscard]] QPixmap Generate(int size, Callback callback) {
auto result = QImage( auto result = QImage(
@ -230,6 +239,76 @@ QPixmap EmptyUserpic::GenerateSavedMessagesRounded(int size) {
}); });
} }
void EmptyUserpic::PaintRepliesMessages(
Painter &p,
int x,
int y,
int outerWidth,
int size) {
const auto &bg = st::historyPeerSavedMessagesBg;
const auto &fg = st::historyPeerUserpicFg;
PaintRepliesMessages(p, x, y, outerWidth, size, bg, fg);
}
void EmptyUserpic::PaintRepliesMessagesRounded(
Painter &p,
int x,
int y,
int outerWidth,
int size) {
const auto &bg = st::historyPeerSavedMessagesBg;
const auto &fg = st::historyPeerUserpicFg;
PaintRepliesMessagesRounded(p, x, y, outerWidth, size, bg, fg);
}
void EmptyUserpic::PaintRepliesMessages(
Painter &p,
int x,
int y,
int outerWidth,
int size,
const style::color &bg,
const style::color &fg) {
x = rtl() ? (outerWidth - x - size) : x;
PainterHighQualityEnabler hq(p);
p.setBrush(bg);
p.setPen(Qt::NoPen);
p.drawEllipse(x, y, size, size);
PaintRepliesMessagesInner(p, x, y, size, bg, fg);
}
void EmptyUserpic::PaintRepliesMessagesRounded(
Painter &p,
int x,
int y,
int outerWidth,
int size,
const style::color &bg,
const style::color &fg) {
x = rtl() ? (outerWidth - x - size) : x;
PainterHighQualityEnabler hq(p);
p.setBrush(bg);
p.setPen(Qt::NoPen);
p.drawRoundedRect(x, y, size, size, st::buttonRadius, st::buttonRadius);
PaintRepliesMessagesInner(p, x, y, size, bg, fg);
}
QPixmap EmptyUserpic::GenerateRepliesMessages(int size) {
return Generate(size, [&](Painter &p) {
PaintRepliesMessages(p, 0, 0, size, size);
});
}
QPixmap EmptyUserpic::GenerateRepliesMessagesRounded(int size) {
return Generate(size, [&](Painter &p) {
PaintRepliesMessagesRounded(p, 0, 0, size, size);
});
}
InMemoryKey EmptyUserpic::uniqueKey() const { InMemoryKey EmptyUserpic::uniqueKey() const {
const auto first = (uint64(0xFFFFFFFFU) << 32) const auto first = (uint64(0xFFFFFFFFU) << 32)
| anim::getPremultiplied(_color->c); | anim::getPremultiplied(_color->c);

View file

@ -65,6 +65,37 @@ public:
static QPixmap GenerateSavedMessages(int size); static QPixmap GenerateSavedMessages(int size);
static QPixmap GenerateSavedMessagesRounded(int size); static QPixmap GenerateSavedMessagesRounded(int size);
static void PaintRepliesMessages(
Painter &p,
int x,
int y,
int outerWidth,
int size);
static void PaintRepliesMessagesRounded(
Painter &p,
int x,
int y,
int outerWidth,
int size);
static void PaintRepliesMessages(
Painter &p,
int x,
int y,
int outerWidth,
int size,
const style::color &bg,
const style::color &fg);
static void PaintRepliesMessagesRounded(
Painter &p,
int x,
int y,
int outerWidth,
int size,
const style::color &bg,
const style::color &fg);
static QPixmap GenerateRepliesMessages(int size);
static QPixmap GenerateRepliesMessagesRounded(int size);
~EmptyUserpic(); ~EmptyUserpic();
private: private:

View file

@ -675,6 +675,13 @@ void UserpicButton::paintEvent(QPaintEvent *e) {
photoPosition.y(), photoPosition.y(),
width(), width(),
_st.photoSize); _st.photoSize);
} else if (showRepliesMessages()) {
Ui::EmptyUserpic::PaintRepliesMessages(
p,
photoPosition.x(),
photoPosition.y(),
width(),
_st.photoSize);
} else { } else {
if (_a_appearance.animating()) { if (_a_appearance.animating()) {
p.drawPixmapLeft(photoPosition, width(), _oldUserpic); p.drawPixmapLeft(photoPosition, width(), _oldUserpic);
@ -1032,6 +1039,10 @@ bool UserpicButton::showSavedMessages() const {
return _showSavedMessagesOnSelf && _peer && _peer->isSelf(); return _showSavedMessagesOnSelf && _peer && _peer->isSelf();
} }
bool UserpicButton::showRepliesMessages() const {
return _showSavedMessagesOnSelf && _peer && _peer->isRepliesChat();
}
void UserpicButton::startChangeOverlayAnimation() { void UserpicButton::startChangeOverlayAnimation() {
auto over = isOver() || isDown(); auto over = isOver() || isDown();
_changeOverlayShown.start( _changeOverlayShown.start(

View file

@ -222,6 +222,7 @@ private:
void updateCursor(); void updateCursor();
void updateVideo(); void updateVideo();
bool showSavedMessages() const; bool showSavedMessages() const;
bool showRepliesMessages() const;
void checkStreamedIsStarted(); void checkStreamedIsStarted();
bool createStreamingObjects(not_null<PhotoData*> photo); bool createStreamingObjects(not_null<PhotoData*> photo);
void clearStreaming(); void clearStreaming();

View file

@ -66,6 +66,11 @@ QString CachedUserpics::get(
? Ui::EmptyUserpic::GenerateSavedMessagesRounded ? Ui::EmptyUserpic::GenerateSavedMessagesRounded
: Ui::EmptyUserpic::GenerateSavedMessages; : Ui::EmptyUserpic::GenerateSavedMessages;
method(st::notifyMacPhotoSize).save(v.path, "PNG"); method(st::notifyMacPhotoSize).save(v.path, "PNG");
} else if (peer->isRepliesChat()) {
const auto method = (_type == Type::Rounded)
? Ui::EmptyUserpic::GenerateRepliesMessagesRounded
: Ui::EmptyUserpic::GenerateRepliesMessages;
method(st::notifyMacPhotoSize).save(v.path, "PNG");
} else if (_type == Type::Rounded) { } else if (_type == Type::Rounded) {
peer->saveUserpicRounded(view, v.path, st::notifyMacPhotoSize); peer->saveUserpicRounded(view, v.path, st::notifyMacPhotoSize);
} else { } else {