diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 39f2c42302..9a0def1ca5 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -976,6 +976,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org "lng_channel_mute" = "Mute"; "lng_channel_unmute" = "Unmute"; "lng_saved_messages" = "Saved messages"; +"lng_saved_short" = "Saved"; +"lng_saved_forward_here" = "Forward messages here for quick access"; "lng_dialogs_text_with_from" = "{from_part} {message}"; "lng_dialogs_text_from_wrapped" = "{from}:"; diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index f0d864e718..88a4b3c28f 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -32,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/widgets/popup_menu.h" #include "ui/effects/round_checkbox.h" #include "ui/effects/ripple_animation.h" +#include "ui/empty_userpic.h" #include "ui/wrap/slide_wrap.h" #include "lang/lang_keys.h" #include "observer_peer.h" @@ -274,10 +275,23 @@ void PeerListBox::addSelectItem(not_null peer, PeerListRow::SetStyle createMultiSelect(); _select->hide(anim::type::instant); } + const auto respect = _controller->respectSavedMessagesChat(); + const auto text = (respect && peer->isSelf()) + ? lang(lng_saved_short) + : peer->shortName(); + const auto callback = PaintUserpicCallback(peer, respect); if (style == PeerListRow::SetStyle::Fast) { - _select->entity()->addItemInBunch(peer->id, peer->shortName(), st::activeButtonBg, PaintUserpicCallback(peer)); + _select->entity()->addItemInBunch( + peer->id, + text, + st::activeButtonBg, + std::move(callback)); } else { - _select->entity()->addItem(peer->id, peer->shortName(), st::activeButtonBg, PaintUserpicCallback(peer), Ui::MultiSelect::AddItemWay::Default); + _select->entity()->addItem( + peer->id, + text, + st::activeButtonBg, + std::move(callback)); } } @@ -313,7 +327,8 @@ PeerListRow::PeerListRow(not_null peer, PeerListRowId id) : _id(id) , _peer(peer) , _initialized(false) -, _isSearchResult(false) { +, _isSearchResult(false) +, _isSavedMessagesChat(false) { } bool PeerListRow::checked() const { @@ -338,13 +353,17 @@ void PeerListRow::refreshStatus() { _statusType = StatusType::LastSeen; _statusValidTill = 0; if (auto user = peer()->asUser()) { - auto time = unixtime(); - setStatusText(App::onlineText(user, time)); - if (App::onlineColorUse(user, time)) { - _statusType = StatusType::Online; + if (_isSavedMessagesChat) { + setStatusText(lang(lng_saved_forward_here)); + } else { + auto time = unixtime(); + setStatusText(App::onlineText(user, time)); + if (App::onlineColorUse(user, time)) { + _statusType = StatusType::Online; + } + _statusValidTill = getms() + + App::onlineWillChangeIn(user, time) * 1000LL; } - _statusValidTill = getms() - + App::onlineWillChangeIn(user, time) * 1000LL; } else if (auto chat = peer()->asChat()) { if (!chat->amIn()) { setStatusText(lang(lng_chat_status_unaccessible)); @@ -368,7 +387,10 @@ void PeerListRow::refreshName(const style::PeerListItem &st) { if (!_initialized) { return; } - _name.setText(st.nameStyle, peer()->name, _textNameOptions); + const auto text = _isSavedMessagesChat + ? lang(lng_saved_messages) + : peer()->name; + _name.setText(st.nameStyle, text, _textNameOptions); } PeerListRow::~PeerListRow() = default; @@ -441,6 +463,8 @@ void PeerListRow::paintUserpic( paintDisabledCheckUserpic(p, st, x, y, outerWidth); } else if (_checkbox) { _checkbox->paint(p, ms, x, y, outerWidth); + } else if (_isSavedMessagesChat) { + Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, st.photoSize); } else { peer()->paintUserpicLeft(p, x, y, outerWidth, st.photoSize); } @@ -469,7 +493,11 @@ void PeerListRow::paintDisabledCheckUserpic( auto iconBorderPen = st::contactsPhotoCheckbox.check.border->p; iconBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth); - peer()->paintUserpicLeft(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); + if (_isSavedMessagesChat) { + Ui::EmptyUserpic::PaintSavedMessages(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); + } else { + peer()->paintUserpicLeft(p, userpicLeft, userpicTop, outerWidth, userpicRadius * 2); + } { PainterHighQualityEnabler hq(p); @@ -507,7 +535,7 @@ void PeerListRow::createCheckbox(base::lambda updateCallback) { _checkbox = std::make_unique( st::contactsPhotoCheckbox, std::move(updateCallback), - PaintUserpicCallback(_peer)); + PaintUserpicCallback(_peer, _isSavedMessagesChat)); } void PeerListRow::setCheckedInternal(bool checked, SetStyle style) { @@ -574,12 +602,16 @@ void PeerListContent::appendFoundRow(not_null row) { } void PeerListContent::changeCheckState(not_null row, bool checked, PeerListRow::SetStyle style) { - row->setChecked(checked, style, [this, row] { - updateRow(row); - }); + row->setChecked( + checked, + style, + [this, row] { updateRow(row); }); } void PeerListContent::addRowEntry(not_null row) { + if (_controller->respectSavedMessagesChat() && row->peer()->isSelf()) { + row->setIsSavedMessagesChat(true); + } _rowsById.emplace(row->id(), row); _rowsByPeer[row->peer()].push_back(row); if (addingToSearchIndex()) { @@ -1013,6 +1045,7 @@ void PeerListContent::setPressed(Selected pressed) { TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) { auto row = getRow(index); Assert(row != nullptr); + row->lazyInitialize(_st.item); auto refreshStatusAt = row->refreshStatusTime(); diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index a708601aed..09fb6913d3 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include #include "ui/rp_widget.h" +#include "ui/empty_userpic.h" #include "boxes/abstract_box.h" #include "mtproto/sender.h" #include "base/timer.h" @@ -46,7 +47,15 @@ namespace Notify { struct PeerUpdate; } // namespace Notify -inline auto PaintUserpicCallback(PeerData *peer) { +inline auto PaintUserpicCallback( + not_null peer, + bool respectSavedMessagesChat) +->base::lambda { + if (respectSavedMessagesChat && peer->isSelf()) { + return [](Painter &p, int x, int y, int outerWidth, int size) { + Ui::EmptyUserpic::PaintSavedMessages(p, x, y, outerWidth, size); + }; + } return [peer](Painter &p, int x, int y, int outerWidth, int size) { peer->paintUserpicLeft(p, x, y, outerWidth, size); }; @@ -141,13 +150,22 @@ public: void setIsSearchResult(bool isSearchResult) { _isSearchResult = isSearchResult; } + bool isSavedMessagesChat() const { + return _isSavedMessagesChat; + } + void setIsSavedMessagesChat(bool isSavedMessagesChat) { + _isSavedMessagesChat = isSavedMessagesChat; + } enum class SetStyle { Animated, Fast, }; template - void setChecked(bool checked, SetStyle style, UpdateCallback callback) { + void setChecked( + bool checked, + SetStyle style, + UpdateCallback callback) { if (checked && !_checkbox) { createCheckbox(std::move(callback)); } @@ -218,6 +236,7 @@ private: State _disabledState = State::Active; bool _initialized : 1; bool _isSearchResult : 1; + bool _isSavedMessagesChat : 1; }; @@ -371,6 +390,10 @@ public: void peerListSearchAddRow(not_null peer) override; void peerListSearchRefreshRows() override; + virtual bool respectSavedMessagesChat() const { + return false; + } + virtual rpl::producer onlineCountValue() const; rpl::lifetime &lifetime() { diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index 247833bcbb..8283fcb60c 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -220,7 +220,9 @@ bool PeerListGlobalSearchController::isLoading() { return _timer.isActive() || _requestId; } -ChatsListBoxController::ChatsListBoxController(std::unique_ptr searchController) : PeerListController(std::move(searchController)) { +ChatsListBoxController::ChatsListBoxController( + std::unique_ptr searchController) +: PeerListController(std::move(searchController)) { } void ChatsListBoxController::prepare() { @@ -254,7 +256,15 @@ void ChatsListBoxController::rebuildRows() { } return count; }; - auto added = appendList(App::main()->dialogsList()); + auto added = 0; + if (respectSavedMessagesChat()) { + if (auto self = App::self()) { + if (appendRow(App::history(self))) { + ++added; + } + } + } + added += appendList(App::main()->dialogsList()); added += appendList(App::main()->contactsNoDialogsList()); if (!wasEmpty && added > 0) { // Place dialogs list before contactsNoDialogs list. @@ -262,6 +272,11 @@ void ChatsListBoxController::rebuildRows() { auto history = static_cast(a).history(); return history->inChatList(Dialogs::Mode::All); }); + if (respectSavedMessagesChat()) { + delegate()->peerListPartitionRows([](const PeerListRow &a) { + return a.peer()->isSelf(); + }); + } } checkForEmptyRows(); delegate()->peerListRefreshRows(); diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h index ab42e7848c..5c92cdc680 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.h +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h @@ -90,9 +90,13 @@ private: }; -class ChatsListBoxController : public PeerListController, protected base::Subscriber { +class ChatsListBoxController + : public PeerListController + , protected base::Subscriber { public: - ChatsListBoxController(std::unique_ptr searchController = std::make_unique()); + ChatsListBoxController( + std::unique_ptr searchController + = std::make_unique()); void prepare() override final; std::unique_ptr createSearchRow(not_null peer) override final; @@ -243,11 +247,16 @@ public: void rowClicked(not_null row) override; + bool respectSavedMessagesChat() const override { + return true; + } + protected: void prepareViewHook() override; std::unique_ptr createRow( not_null history) override; +private: base::lambda)> _callback; }; diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 8fe664cf80..2ab1cb3a25 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -223,7 +223,12 @@ void ShareBox::onFilterUpdate(const QString &query) { void ShareBox::addPeerToMultiSelect(PeerData *peer, bool skipAnimation) { using AddItemWay = Ui::MultiSelect::AddItemWay; auto addItemWay = skipAnimation ? AddItemWay::SkipAnimation : AddItemWay::Default; - _select->addItem(peer->id, peer->shortName(), st::activeButtonBg, PaintUserpicCallback(peer), addItemWay); + _select->addItem( + peer->id, + peer->isSelf() ? lang(lng_saved_short) : peer->shortName(), + st::activeButtonBg, + PaintUserpicCallback(peer, true), + addItemWay); } void ShareBox::onPeerSelectedChanged(PeerData *peer, bool checked) { @@ -281,9 +286,14 @@ ShareBox::Inner::Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallbac setAttribute(Qt::WA_OpaquePaintEvent); auto dialogs = App::main()->dialogsList(); + if (auto self = App::self()) { + if (_filterCallback(App::self())) { + _chatsIndexed->addToEnd(App::history(self)); + } + } for_const (auto row, dialogs->all()) { auto history = row->history(); - if (_filterCallback(history->peer)) { + if (!history->peer->isSelf() && _filterCallback(history->peer)) { _chatsIndexed->addToEnd(history); } } @@ -355,7 +365,7 @@ void ShareBox::Inner::notifyPeerUpdated(const Notify::PeerUpdate &update) { updateChat(update.peer); } -void ShareBox::Inner::updateChat(PeerData *peer) { +void ShareBox::Inner::updateChat(not_null peer) { auto i = _dataMap.find(peer); if (i != _dataMap.cend()) { updateChatName(i.value(), peer); @@ -363,8 +373,11 @@ void ShareBox::Inner::updateChat(PeerData *peer) { } } -void ShareBox::Inner::updateChatName(Chat *chat, PeerData *peer) { - chat->name.setText(st::shareNameStyle, peer->name, _textNameOptions); +void ShareBox::Inner::updateChatName( + not_null chat, + not_null peer) { + const auto text = peer->isSelf() ? lang(lng_saved_messages) : peer->name; + chat->name.setText(st::shareNameStyle, text, _textNameOptions); } void ShareBox::Inner::repaintChatAtIndex(int index) { @@ -394,11 +407,11 @@ ShareBox::Inner::Chat *ShareBox::Inner::getChatAtIndex(int index) { return nullptr; } -void ShareBox::Inner::repaintChat(PeerData *peer) { +void ShareBox::Inner::repaintChat(not_null peer) { repaintChatAtIndex(chatIndex(peer)); } -int ShareBox::Inner::chatIndex(PeerData *peer) const { +int ShareBox::Inner::chatIndex(not_null peer) const { int index = 0; if (_filter.isEmpty()) { for_const (auto row, _chatsIndexed->all()) { @@ -498,7 +511,11 @@ void ShareBox::Inner::setActive(int active) { emit mustScrollTo(y, y + _rowHeight); } -void ShareBox::Inner::paintChat(Painter &p, TimeMs ms, Chat *chat, int index) { +void ShareBox::Inner::paintChat( + Painter &p, + TimeMs ms, + not_null chat, + int index) { auto x = _rowsLeft + qFloor((index % _columnCount) * _rowWidthReal); auto y = _rowsTop + (index / _columnCount) * _rowHeight; @@ -518,7 +535,7 @@ void ShareBox::Inner::paintChat(Painter &p, TimeMs ms, Chat *chat, int index) { ShareBox::Inner::Chat::Chat(PeerData *peer, base::lambda updateCallback) : peer(peer) -, checkbox(st::sharePhotoCheckbox, updateCallback, PaintUserpicCallback(peer)) +, checkbox(st::sharePhotoCheckbox, updateCallback, PaintUserpicCallback(peer, true)) , name(st::sharePhotoCheckbox.imageRadius * 2) { } @@ -649,27 +666,29 @@ void ShareBox::Inner::changeCheckState(Chat *chat) { changePeerCheckState(chat, !chat->checkbox.checked()); } -void ShareBox::Inner::peerUnselected(PeerData *peer) { - // If data is nullptr we simply won't do anything. - auto chat = _dataMap.value(peer, nullptr); - changePeerCheckState(chat, false, ChangeStateWay::SkipCallback); +void ShareBox::Inner::peerUnselected(not_null peer) { + if (auto chat = _dataMap.value(peer, nullptr)) { + changePeerCheckState(chat, false, ChangeStateWay::SkipCallback); + } } void ShareBox::Inner::setPeerSelectedChangedCallback(base::lambda callback) { _peerSelectedChangedCallback = std::move(callback); } -void ShareBox::Inner::changePeerCheckState(Chat *chat, bool checked, ChangeStateWay useCallback) { - if (chat) { - chat->checkbox.setChecked(checked); - } +void ShareBox::Inner::changePeerCheckState( + not_null chat, + bool checked, + ChangeStateWay useCallback) { + chat->checkbox.setChecked(checked); if (checked) { _selected.insert(chat->peer); setActive(chatIndex(chat->peer)); } else { _selected.remove(chat->peer); } - if (useCallback != ChangeStateWay::SkipCallback && _peerSelectedChangedCallback) { + if (useCallback != ChangeStateWay::SkipCallback + && _peerSelectedChangedCallback) { _peerSelectedChangedCallback(chat->peer, checked); } } diff --git a/Telegram/SourceFiles/boxes/share_box.h b/Telegram/SourceFiles/boxes/share_box.h index ba0183d60d..aa817c8c89 100644 --- a/Telegram/SourceFiles/boxes/share_box.h +++ b/Telegram/SourceFiles/boxes/share_box.h @@ -115,7 +115,7 @@ public: Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback); void setPeerSelectedChangedCallback(base::lambda callback); - void peerUnselected(PeerData *peer); + void peerUnselected(not_null peer); QVector selected() const; bool hasSelected() const; @@ -163,11 +163,11 @@ private: Text name; Animation nameActive; }; - void paintChat(Painter &p, TimeMs ms, Chat *chat, int index); - void updateChat(PeerData *peer); - void updateChatName(Chat *chat, PeerData *peer); - void repaintChat(PeerData *peer); - int chatIndex(PeerData *peer) const; + void paintChat(Painter &p, TimeMs ms, not_null chat, int index); + void updateChat(not_null peer); + void updateChatName(not_null chat, not_null peer); + void repaintChat(not_null peer); + int chatIndex(not_null peer) const; void repaintChatAtIndex(int index); Chat *getChatAtIndex(int index); @@ -177,7 +177,10 @@ private: Default, SkipCallback, }; - void changePeerCheckState(Chat *chat, bool checked, ChangeStateWay useCallback = ChangeStateWay::Default); + void changePeerCheckState( + not_null chat, + bool checked, + ChangeStateWay useCallback = ChangeStateWay::Default); Chat *getChat(Dialogs::Row *row); void setActive(int active); diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 14fe3e9854..3c92392dad 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -305,20 +305,35 @@ void PeerData::clearUserpic() { void PeerData::fillNames() { _nameWords.clear(); _nameFirstChars.clear(); - auto toIndex = TextUtilities::RemoveAccents(name); - if (cRussianLetters().match(toIndex).hasMatch()) { - toIndex += ' ' + translitRusEng(toIndex); + auto toIndexList = QStringList(); + auto appendToIndex = [&](const QString &value) { + if (!value.isEmpty()) { + toIndexList.push_back(TextUtilities::RemoveAccents(value)); + } + }; + + appendToIndex(name); + const auto appendTranslit = !toIndexList.isEmpty() + && cRussianLetters().match(toIndexList.front()).hasMatch(); + if (appendTranslit) { + appendToIndex(translitRusEng(toIndexList.front())); } - if (isUser()) { - if (!asUser()->nameOrPhone.isEmpty() && asUser()->nameOrPhone != name) toIndex += ' ' + TextUtilities::RemoveAccents(asUser()->nameOrPhone); - if (!asUser()->username.isEmpty()) toIndex += ' ' + TextUtilities::RemoveAccents(asUser()->username); - } else if (isChannel()) { - if (!asChannel()->username.isEmpty()) toIndex += ' ' + TextUtilities::RemoveAccents(asChannel()->username); + if (auto user = asUser()) { + if (user->nameOrPhone != name) { + appendToIndex(user->nameOrPhone); + } + appendToIndex(user->username); + if (isSelf()) { + appendToIndex(lang(lng_saved_messages)); + } + } else if (auto channel = asChannel()) { + appendToIndex(channel->username); } + auto toIndex = toIndexList.join(' '); toIndex += ' ' + rusKeyboardLayoutSwitch(toIndex); - auto namesList = TextUtilities::PrepareSearchWords(toIndex); - for (auto &name : namesList) { + const auto namesList = TextUtilities::PrepareSearchWords(toIndex); + for (const auto &name : namesList) { _nameWords.insert(name); _nameFirstChars.insert(name[0]); } diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 485c1ab032..a94fb7efc2 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -41,6 +41,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "window/window_controller.h" #include "window/window_peer_menu.h" #include "ui/widgets/multi_select.h" +#include "ui/empty_userpic.h" namespace { @@ -463,7 +464,11 @@ void DialogsInner::paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackgro if (onlyBackground) return; p.setPen(st::dialogsNameFg); - paintSearchInFilter(p, _searchInPeer, top, fullWidth, _searchInPeer->nameText); + if (_searchInPeer->isSelf()) { + paintSearchInFilter(p, nullptr, top, fullWidth, _searchInSavedText); + } else { + paintSearchInFilter(p, _searchInPeer, top, fullWidth, _searchInPeer->nameText); + } if (_searchFromUser) { top += st::dialogsSearchInHeight + st::lineWidth; p.setPen(st::dialogsTextFg); @@ -473,19 +478,53 @@ void DialogsInner::paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackgro } } -void DialogsInner::paintSearchInFilter(Painter &p, not_null peer, int top, int fullWidth, const Text &text) const { - auto pen = p.pen(); - peer->paintUserpicLeft(p, st::dialogsPadding.x(), top + (st::dialogsSearchInHeight - st::dialogsSearchInPhotoSize) / 2, getFullWidth(), st::dialogsSearchInPhotoSize); - - auto nameleft = st::dialogsPadding.x() + st::dialogsSearchInPhotoSize + st::dialogsSearchInPhotoPadding; - auto namewidth = fullWidth - nameleft - st::dialogsPadding.x() * 2 - st::dialogsCancelSearch.width; - auto rectForName = QRect(nameleft, top + (st::dialogsSearchInHeight - st::msgNameFont->height) / 2, namewidth, st::msgNameFont->height); - if (auto chatTypeIcon = Dialogs::Layout::ChatTypeIcon(peer, false, false)) { - chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); +void DialogsInner::paintSearchInFilter( + Painter &p, + PeerData *peer, + int top, + int fullWidth, + const Text &text) const { + const auto savedPen = p.pen(); + const auto userpicTop = top + + (st::dialogsSearchInHeight - st::dialogsSearchInPhotoSize) / 2; + if (peer) { + peer->paintUserpicLeft( + p, + st::dialogsPadding.x(), + userpicTop, + getFullWidth(), + st::dialogsSearchInPhotoSize); + } else { + Ui::EmptyUserpic::PaintSavedMessages( + p, + st::dialogsPadding.x(), + userpicTop, + getFullWidth(), + st::dialogsSearchInPhotoSize); + } + const auto nameleft = st::dialogsPadding.x() + + st::dialogsSearchInPhotoSize + + st::dialogsSearchInPhotoPadding; + const auto namewidth = fullWidth + - nameleft + - st::dialogsPadding.x() * 2 + - st::dialogsCancelSearch.width; + auto rectForName = QRect( + nameleft, + top + (st::dialogsSearchInHeight - st::msgNameFont->height) / 2, + namewidth, + st::msgNameFont->height); + if (auto icon = Dialogs::Layout::ChatTypeIcon(peer, false, false)) { + icon->paint(p, rectForName.topLeft(), fullWidth); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); } - p.setPen(pen); - text.drawLeftElided(p, rectForName.left(), rectForName.top(), rectForName.width(), width()); + p.setPen(savedPen); + text.drawLeftElided( + p, + rectForName.left(), + rectForName.top(), + rectForName.width(), + getFullWidth()); } void DialogsInner::activate() { @@ -1752,11 +1791,23 @@ void DialogsInner::searchInPeer(PeerData *peer, UserData *from) { if (_searchInPeer) { onHashtagFilterUpdate(QStringRef()); _cancelSearchInPeer->show(); + if (_searchInPeer->isSelf()) { + _searchInSavedText.setText( + st::dialogsSearchFromStyle, + lang(lng_saved_messages), + _textDlgOptions); + } } else { _cancelSearchInPeer->hide(); } if (_searchFromUser) { - _searchFromUserText.setText(st::dialogsSearchFromStyle, lng_dlg_search_from(lt_user, textcmdLink(1, App::peerName(_searchFromUser))), _textDlgOptions); + auto fromUserText = lng_dlg_search_from( + lt_user, + textcmdLink(1, App::peerName(_searchFromUser))); + _searchFromUserText.setText( + st::dialogsSearchFromStyle, + fromUserText, + _textDlgOptions); _cancelSearchFromUser->show(); } else { _cancelSearchFromUser->hide(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index eddb3fcb2d..97fbb8c85a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -196,7 +196,12 @@ private: void paintDialog(Painter &p, Dialogs::Row *row, int fullWidth, PeerData *active, PeerData *selected, bool onlyBackground, TimeMs ms); void paintPeerSearchResult(Painter &p, const PeerSearchResult *result, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) const; void paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackground, TimeMs ms) const; - void paintSearchInFilter(Painter &p, not_null peer, int top, int fullWidth, const Text &text) const; + void paintSearchInFilter( + Painter &p, + PeerData *peer, + int top, + int fullWidth, + const Text &text) const; void clearSelection(); void clearSearchResults(bool clearPeerSearchResults = true); @@ -289,6 +294,7 @@ private: PeerData *_searchInMigrated = nullptr; UserData *_searchFromUser = nullptr; Text _searchFromUserText; + Text _searchInSavedText; PeerData *_menuPeer = nullptr; base::lambda _loadMoreCallback; diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index d21343bc28..6cc55727f1 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "dialogs/dialogs_list.h" #include "styles/style_dialogs.h" #include "storage/localstorage.h" +#include "ui/empty_userpic.h" #include "lang/lang_keys.h" namespace Dialogs { @@ -57,6 +58,15 @@ void paintRowDate(Painter &p, const QDateTime &date, QRect &rectForName, bool ac p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent, dt); } +enum class Flag { + Active = 0x01, + Selected = 0x02, + OnlyBackground = 0x04, + SearchResult = 0x08, + SavedMessages = 0x10, +}; +inline constexpr bool is_flag_type(Flag) { return true; } + template void paintRow( Painter &p, @@ -67,20 +77,47 @@ void paintRow( Data::Draft *draft, QDateTime date, int fullWidth, - bool active, - bool selected, - bool onlyBackground, + base::flags flags, TimeMs ms, PaintItemCallback &&paintItemCallback, PaintCounterCallback &&paintCounterCallback) { - QRect fullRect(0, 0, fullWidth, st::dialogsRowHeight); - p.fillRect(fullRect, active ? st::dialogsBgActive : (selected ? st::dialogsBgOver : st::dialogsBg)); - row->paintRipple(p, 0, 0, fullWidth, ms, &(active ? st::dialogsRippleBgActive : st::dialogsRippleBg)->c); - if (onlyBackground) return; + auto active = (flags & Flag::Active); + auto selected = (flags & Flag::Selected); + auto fullRect = QRect(0, 0, fullWidth, st::dialogsRowHeight); + auto bg = active + ? st::dialogsBgActive + : (selected + ? st::dialogsBgOver + : st::dialogsBg); + auto ripple = active + ? st::dialogsRippleBgActive + : st::dialogsRippleBg; + p.fillRect(fullRect, bg); + row->paintRipple(p, 0, 0, fullWidth, ms, &ripple->c); - from->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), fullWidth, st::dialogsPhotoSize); + if (flags & Flag::OnlyBackground) { + return; + } - auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding; + if (flags & Flag::SavedMessages) { + Ui::EmptyUserpic::PaintSavedMessages( + p, + st::dialogsPadding.x(), + st::dialogsPadding.y(), + fullWidth, + st::dialogsPhotoSize); + } else { + from->paintUserpicLeft( + p, + st::dialogsPadding.x(), + st::dialogsPadding.y(), + fullWidth, + st::dialogsPhotoSize); + } + + auto nameleft = st::dialogsPadding.x() + + st::dialogsPhotoSize + + st::dialogsPhotoPadding; if (fullWidth <= nameleft) { if (!draft && item && !item->isEmpty()) { paintCounterCallback(); @@ -89,14 +126,20 @@ void paintRow( } auto namewidth = fullWidth - nameleft - st::dialogsPadding.x(); - QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height); + auto rectForName = QRect( + nameleft, + st::dialogsPadding.y() + st::dialogsNameTop, + namewidth, + st::msgNameFont->height); if (auto chatTypeIcon = ChatTypeIcon(from, active, selected)) { chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); } - int texttop = st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip; + auto texttop = st::dialogsPadding.y() + + st::msgNameFont->height + + st::dialogsSkip; if (draft) { paintRowDate(p, date, rectForName, active, selected); @@ -164,14 +207,28 @@ void paintRow( sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), fullWidth); } - if (from == history->peer && from->isVerified()) { - auto icon = &(active ? st::dialogsVerifiedIconActive : (selected ? st::dialogsVerifiedIconOver : st::dialogsVerifiedIcon)); - rectForName.setWidth(rectForName.width() - icon->width()); - icon->paint(p, rectForName.topLeft() + QPoint(qMin(from->dialogName().maxWidth(), rectForName.width()), 0), fullWidth); + const auto nameFg = active + ? st::dialogsNameFgActive + : (selected + ? st::dialogsNameFgOver + : st::dialogsNameFg); + p.setPen(nameFg); + if (flags & Flag::SavedMessages) { + p.setFont(st::msgNameFont); + auto text = lang(lng_saved_messages); + auto textWidth = st::msgNameFont->width(text); + if (textWidth > rectForName.width()) { + text = st::msgNameFont->elided(text, rectForName.width()); + } + p.drawTextLeft(rectForName.left(), rectForName.top(), fullWidth, text); + } else { + if (!(flags & Flag::SearchResult) && from->isVerified()) { + auto icon = &(active ? st::dialogsVerifiedIconActive : (selected ? st::dialogsVerifiedIconOver : st::dialogsVerifiedIcon)); + rectForName.setWidth(rectForName.width() - icon->width()); + icon->paint(p, rectForName.topLeft() + QPoint(qMin(from->dialogName().maxWidth(), rectForName.width()), 0), fullWidth); + } + from->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); } - - p.setPen(active ? st::dialogsNameFgActive : (selected ? st::dialogsNameFgOver : st::dialogsNameFg)); - from->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); } struct UnreadBadgeSizeData { @@ -207,7 +264,9 @@ QImage colorizeCircleHalf(UnreadBadgeSizeData *data, int size, int half, int xof } // namepsace const style::icon *ChatTypeIcon(PeerData *peer, bool active, bool selected) { - if (peer->isChat() || peer->isMegagroup()) { + if (!peer) { + return nullptr; + } else if (peer->isChat() || peer->isMegagroup()) { return &(active ? st::dialogsChatIconActive : (selected ? st::dialogsChatIconOver : st::dialogsChatIcon)); } else if (peer->isChannel()) { return &(active ? st::dialogsChannelIconActive : (selected ? st::dialogsChannelIconOver : st::dialogsChannelIcon)); @@ -279,7 +338,14 @@ void paintUnreadCount(Painter &p, const QString &text, int x, int y, const Unrea p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + textTop + st.font->ascent, text); } -void RowPainter::paint(Painter &p, const Row *row, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) { +void RowPainter::paint( + Painter &p, + const Row *row, + int fullWidth, + bool active, + bool selected, + bool onlyBackground, + TimeMs ms) { auto history = row->history(); auto item = history->lastMsg; auto cloudDraft = history->cloudDraft(); @@ -403,6 +469,10 @@ void RowPainter::paint(Painter &p, const Row *row, int fullWidth, bool active, b paintUnreadCount(p, counter, unreadRight, unreadTop, st, &unreadWidth); } }; + const auto flags = (active ? Flag::Active : Flag(0)) + | (selected ? Flag::Selected : Flag(0)) + | (onlyBackground ? Flag::OnlyBackground : Flag(0)) + | (history->peer->isSelf() ? Flag::SavedMessages : Flag(0)); paintRow( p, row, @@ -412,17 +482,23 @@ void RowPainter::paint(Painter &p, const Row *row, int fullWidth, bool active, b cloudDraft, displayDate(), fullWidth, - active, - selected, - onlyBackground, + flags, ms, paintItemCallback, paintCounterCallback); } -void RowPainter::paint(Painter &p, const FakeRow *row, int fullWidth, bool active, bool selected, bool onlyBackground, TimeMs ms) { +void RowPainter::paint( + Painter &p, + const FakeRow *row, + int fullWidth, + bool active, + bool selected, + bool onlyBackground, + TimeMs ms) { auto item = row->item(); auto history = item->history(); + auto cloudDraft = nullptr; auto from = [&] { if (auto searchPeer = row->searchInPeer()) { if (!searchPeer->isChannel() || searchPeer->isMegagroup()) { @@ -452,18 +528,20 @@ void RowPainter::paint(Painter &p, const FakeRow *row, int fullWidth, bool activ row->_cache); }; auto paintCounterCallback = [] {}; + const auto flags = (active ? Flag::Active : Flag(0)) + | (selected ? Flag::Selected : Flag(0)) + | (onlyBackground ? Flag::OnlyBackground : Flag(0)) + | Flag::SearchResult; paintRow( p, row, history, from, item, - nullptr, + cloudDraft, item->date, fullWidth, - active, - selected, - onlyBackground, + flags, ms, paintItemCallback, paintCounterCallback); diff --git a/Telegram/SourceFiles/history/history.style b/Telegram/SourceFiles/history/history.style index e4a21bec8d..1523bcbd20 100644 --- a/Telegram/SourceFiles/history/history.style +++ b/Telegram/SourceFiles/history/history.style @@ -458,3 +458,5 @@ historyFastShareSize: 31px; historyFastShareLeft: 13px; historyFastShareBottom: 5px; historyFastShareIcon: icon {{ "fast_share", msgServiceFg, point(4px, 3px)}}; + +historySavedFont: font(semibold 15px); diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 6d4f956509..984f970566 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -186,7 +186,9 @@ void FastShareMessage(not_null item) { OrderedSet requests; }; auto data = MakeShared(item->fullId()); - auto isGame = item->getMessageBot() && item->getMedia() && (item->getMedia()->type() == MediaTypeGame); + auto isGame = item->getMessageBot() + && item->getMedia() + && (item->getMedia()->type() == MediaTypeGame); auto canCopyLink = item->hasDirectLink(); if (!canCopyLink) { @@ -285,8 +287,13 @@ void FastShareMessage(not_null item) { } return false; }; - auto copyLinkCallback = canCopyLink ? base::lambda(std::move(copyCallback)) : base::lambda(); - Ui::show(Box(std::move(copyLinkCallback), std::move(submitCallback), std::move(filterCallback))); + auto copyLinkCallback = canCopyLink + ? base::lambda(std::move(copyCallback)) + : base::lambda(); + Ui::show(Box( + std::move(copyLinkCallback), + std::move(submitCallback), + std::move(filterCallback))); } void HistoryInitMessages() { diff --git a/Telegram/SourceFiles/history/history_top_bar_widget.cpp b/Telegram/SourceFiles/history/history_top_bar_widget.cpp index a88cadbc8a..2ea80a1d35 100644 --- a/Telegram/SourceFiles/history/history_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/history_top_bar_widget.cpp @@ -29,6 +29,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "boxes/add_contact_box.h" #include "boxes/confirm_box.h" #include "info/info_memento.h" +#include "info/info_controller.h" +#include "storage/storage_shared_media.h" #include "mainwidget.h" #include "mainwindow.h" #include "shortcuts.h" @@ -243,7 +245,7 @@ void HistoryTopBarWidget::toggleInfoSection() { Auth().saveDataDelayed(); if (Adaptive::ThreeColumn()) { _controller->showSection( - Info::Memento(_historyPeer->id), + Info::Memento::Default(_historyPeer), Window::SectionShow().withThirdColumn()); } else { _controller->resizeForThirdSection(); @@ -303,25 +305,40 @@ void HistoryTopBarWidget::paintTopBar(Painter &p, TimeMs ms) { auto nametop = st::topBarArrowPadding.top(); auto statustop = st::topBarHeight - st::topBarArrowPadding.bottom() - st::dialogsTextFont->height; auto namewidth = width() - _rightTaken - nameleft; - p.setFont(st::dialogsTextFont); - if (!history->paintSendAction(p, nameleft, statustop, namewidth, width(), st::historyStatusFgTyping, ms)) { - auto statustext = _titlePeerText; - auto statuswidth = _titlePeerTextWidth; - if (statuswidth > namewidth) { - statustext = st::dialogsTextFont->elided( - statustext, - namewidth, - Qt::ElideLeft); - statuswidth = st::dialogsTextFont->width(statustext); - } - p.setPen(_titlePeerTextOnline - ? st::historyStatusFgActive - : st::historyStatusFg); - p.drawTextLeft(nameleft, statustop, width(), statustext, statuswidth); - } p.setPen(st::dialogsNameFg); - _historyPeer->dialogName().drawElided(p, nameleft, nametop, namewidth); + if (_historyPeer->isSelf()) { + auto text = lang(lng_saved_messages); + auto textWidth = st::historySavedFont->width(text); + if (namewidth < textWidth) { + text = st::historySavedFont->elided(text, namewidth); + } + p.setFont(st::historySavedFont); + p.drawTextLeft( + nameleft, + (height() - st::historySavedFont->height) / 2, + width(), + text); + } else { + _historyPeer->dialogName().drawElided(p, nameleft, nametop, namewidth); + + p.setFont(st::dialogsTextFont); + if (!history->paintSendAction(p, nameleft, statustop, namewidth, width(), st::historyStatusFgTyping, ms)) { + auto statustext = _titlePeerText; + auto statuswidth = _titlePeerTextWidth; + if (statuswidth > namewidth) { + statustext = st::dialogsTextFont->elided( + statustext, + namewidth, + Qt::ElideLeft); + statuswidth = st::dialogsTextFont->width(statustext); + } + p.setPen(_titlePeerTextOnline + ? st::historyStatusFgActive + : st::historyStatusFg); + p.drawTextLeft(nameleft, statustop, width(), statustext, statuswidth); + } + } } QRect HistoryTopBarWidget::getMembersShowAreaGeometry() const { @@ -347,7 +364,13 @@ void HistoryTopBarWidget::mousePressEvent(QMouseEvent *e) { } void HistoryTopBarWidget::infoClicked() { - _controller->showPeerInfo(_historyPeer); + if (_historyPeer && _historyPeer->isSelf()) { + _controller->showSection(Info::Memento( + _historyPeer->id, + Info::Section(Storage::SharedMediaType::Photo))); + } else { + _controller->showPeerInfo(_historyPeer); + } } void HistoryTopBarWidget::backClicked() { @@ -367,6 +390,7 @@ void HistoryTopBarWidget::setHistoryPeer(PeerData *historyPeer) { _historyPeer, Ui::UserpicButton::Role::Custom, st::topBarInfoButton); + _info->showSavedMessagesOnSelf(true); _info->setAttribute(Qt::WA_TransparentForMouseEvents); } if (_menu) { @@ -421,7 +445,7 @@ void HistoryTopBarWidget::updateControlsGeometry() { _leftTaken = 0; _back->moveToLeft(_leftTaken, otherButtonsTop); _leftTaken += _back->width(); - if (_info) { + if (_info && !_info->isHidden()) { _info->moveToLeft(_leftTaken, otherButtonsTop); _leftTaken += _info->width(); } @@ -469,7 +493,7 @@ void HistoryTopBarWidget::updateControlsVisibility() { || (App::main() && !App::main()->stackIsEmpty()); _back->setVisible(backVisible); if (_info) { - _info->setVisible(backVisible); + _info->setVisible(Adaptive::OneColumn()); } if (_unreadBadge) { _unreadBadge->show(); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 128d70be16..0c2a72d4ad 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -46,6 +46,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "history/history_drag_area.h" #include "history/history_inner_widget.h" #include "profile/profile_block_group_members.h" +#include "info/info_memento.h" #include "core/click_handler_types.h" #include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_selector.h" @@ -3954,7 +3955,9 @@ void HistoryWidget::pushInfoToThirdSection( if (!_peer) { return; } - controller()->showPeerInfo(_peer, params.withThirdColumn()); + controller()->showSection( + Info::Memento::Default(_peer), + params.withThirdColumn()); } void HistoryWidget::toggleTabbedSelectorMode() { diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 8f6fc7e2fa..21c13c78d3 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -48,11 +48,21 @@ std::vector> Memento::DefaultStack( PeerId peerId, Section section) { auto result = std::vector>(); - result.push_back(Default(peerId, section)); + result.push_back(DefaultContent(peerId, section)); return result; } -std::unique_ptr Memento::Default( +Section Memento::DefaultSection(not_null peer) { + return peer->isSelf() + ? Section(Section::MediaType::Photo) + : Section(Section::Type::Profile); +} + +Memento Memento::Default(not_null peer) { + return Memento(peer->id, DefaultSection(peer)); +} + +std::unique_ptr Memento::DefaultContent( PeerId peerId, Section section) { Expects(peerId != 0); @@ -84,7 +94,7 @@ std::unique_ptr Memento::Default( peerId, migratedPeerId); } - Unexpected("Wrong section type in Info::Memento::Default()"); + Unexpected("Wrong section type in Info::Memento::DefaultContent()"); } object_ptr Memento::createWidget( diff --git a/Telegram/SourceFiles/info/info_memento.h b/Telegram/SourceFiles/info/info_memento.h index 34782db8fc..0a2270481a 100644 --- a/Telegram/SourceFiles/info/info_memento.h +++ b/Telegram/SourceFiles/info/info_memento.h @@ -64,13 +64,16 @@ public: return _stack.back().get(); } + static Section DefaultSection(not_null peer); + static Memento Default(not_null peer); + ~Memento(); private: static std::vector> DefaultStack( PeerId peerId, Section section); - static std::unique_ptr Default( + static std::unique_ptr DefaultContent( PeerId peerId, Section section); diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 98854f4ea0..85c4e2ed59 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -124,17 +124,35 @@ void WrapWidget::startInjectingActivePeerProfiles() { } void WrapWidget::injectActivePeerProfile(not_null peer) { - auto firstPeerId = hasStackHistory() + const auto firstPeerId = hasStackHistory() ? _historyStack.front().section->peerId() : _controller->peerId(); - auto firstSectionType = hasStackHistory() + const auto firstSectionType = hasStackHistory() ? _historyStack.front().section->section().type() : _controller->section().type(); - if (firstSectionType != Section::Type::Profile + const auto firstSectionMediaType = [&] { + if (firstSectionType == Section::Type::Profile) { + return Section::MediaType::kCount; + } + return hasStackHistory() + ? _historyStack.front().section->section().mediaType() + : _controller->section().mediaType(); + }(); + const auto expectedType = peer->isSelf() + ? Section::Type::Media + : Section::Type::Profile; + const auto expectedMediaType = peer->isSelf() + ? Section::MediaType::Photo + : Section::MediaType::kCount; + if (firstSectionType != expectedType + || firstSectionMediaType != expectedMediaType || firstPeerId != peer->id) { auto injected = StackItem(); + auto section = peer->isSelf() + ? Section(Section::MediaType::Photo) + : Section(Section::Type::Profile); injected.section = std::move( - Memento(peer->id).takeStack().front()); + Memento(peer->id, section).takeStack().front()); _historyStack.insert( _historyStack.begin(), std::move(injected)); diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp index c214b66d97..cf8c71b2c0 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp @@ -261,15 +261,18 @@ object_ptr DetailsFiller::setupInfo() { }); addInfoLine(lng_info_about_label, AboutValue(_peer)); } - result->add(object_ptr>( - result, - object_ptr(result), - st::infoProfileSeparatorPadding) - )->setDuration( - st::infoSlideDuration - )->toggleOn( - std::move(tracker).atLeastOneShownValue() - ); + if (!_peer->isSelf()) { + // No notifications toggle for Self => no separator. + result->add(object_ptr>( + result, + object_ptr(result), + st::infoProfileSeparatorPadding) + )->setDuration( + st::infoSlideDuration + )->toggleOn( + std::move(tracker).atLeastOneShownValue() + ); + } object_ptr( result, st::infoIconInformation, @@ -323,28 +326,49 @@ Ui::MultiSlideTracker DetailsFiller::fillUserButtons( Ui::MultiSlideTracker tracker; auto window = _controller->window(); - auto sendMessageVisible = rpl::combine( - _controller->wrapValue(), - window->historyPeer.value(), - (_1 != Wrap::Side) || (_2 != user)); - auto sendMessage = [window, user] { - window->showPeerHistory( - user, - Window::SectionShow::Way::Forward); - }; - AddMainButton( - _wrap, - Lang::Viewer(lng_profile_send_message), - std::move(sendMessageVisible), - std::move(sendMessage), - tracker); - AddMainButton( - _wrap, - Lang::Viewer(lng_info_add_as_contact), - CanAddContactValue(user), - [user] { Window::PeerMenuAddContact(user); }, - tracker); + auto addSendMessageButton = [&] { + auto sendMessageVisible = rpl::combine( + _controller->wrapValue(), + window->historyPeer.value(), + (_1 != Wrap::Side) || (_2 != user)); + auto sendMessage = [window, user] { + window->showPeerHistory( + user, + Window::SectionShow::Way::Forward); + }; + AddMainButton( + _wrap, + Lang::Viewer(lng_profile_send_message), + std::move(sendMessageVisible), + std::move(sendMessage), + tracker); + }; + + if (user->isSelf()) { + auto separator = _wrap->add(object_ptr>( + _wrap, + object_ptr(_wrap), + st::infoProfileSeparatorPadding) + )->setDuration( + st::infoSlideDuration + ); + + addSendMessageButton(); + + separator->toggleOn( + std::move(tracker).atLeastOneShownValue() + ); + } else { + addSendMessageButton(); + + AddMainButton( + _wrap, + Lang::Viewer(lng_info_add_as_contact), + CanAddContactValue(user), + [user] { Window::PeerMenuAddContact(user); }, + tracker); + } return tracker; } @@ -377,7 +401,9 @@ object_ptr DetailsFiller::fill() { add(object_ptr(_wrap)); add(CreateSkipWidget(_wrap)); add(setupInfo()); - add(setupMuteToggle()); + if (!_peer->isSelf()) { + add(setupMuteToggle()); + } setupMainButtons(); add(CreateSkipWidget(_wrap)); return std::move(_wrap); @@ -611,8 +637,10 @@ void ActionsFiller::fillUserActions(not_null user) { addInviteToGroupAction(user); } addShareContactAction(user); - addEditContactAction(user); - addDeleteContactAction(user); + if (!user->isSelf()) { + addEditContactAction(user); + addDeleteContactAction(user); + } addClearHistoryAction(user); addDeleteConversationAction(user); if (!user->isSelf()) { diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index bd92d78239..6f332e0dc8 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -42,6 +42,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "chat_helpers/message_field.h" #include "chat_helpers/stickers.h" #include "info/info_memento.h" +#include "info/info_controller.h" #include "observer_peer.h" #include "apiwrap.h" #include "dialogs/dialogs_widget.h" @@ -3531,7 +3532,9 @@ auto MainWidget::thirdSectionForCurrentMainSection( if (_thirdSectionFromStack) { return std::move(_thirdSectionFromStack); } - return std::make_unique(peer->id); + return std::make_unique( + peer->id, + Info::Memento::DefaultSection(peer)); } void MainWidget::updateThirdColumnToCurrentPeer( diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 39d5e9e781..d62eb61bb0 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -144,7 +144,7 @@ Filler::Filler( } bool Filler::showInfo() { - if (_source == PeerMenuSource::Profile) { + if (_source == PeerMenuSource::Profile || _peer->isSelf()) { return false; } else if (_controller->activePeer.current() != _peer) { return true; @@ -310,16 +310,20 @@ void Filler::addUserActions(not_null user) { _addAction( lang(lng_info_share_contact), [user] { PeerMenuShareContactBox(user); }); - _addAction( - lang(lng_info_edit_contact), - [user] { Ui::show(Box(user)); }); - _addAction( - lang(lng_info_delete_contact), - [user] { PeerMenuDeleteContact(user); }); + if (!user->isSelf()) { + _addAction( + lang(lng_info_edit_contact), + [user] { Ui::show(Box(user)); }); + _addAction( + lang(lng_info_delete_contact), + [user] { PeerMenuDeleteContact(user); }); + } } else if (user->canShareThisContact()) { - _addAction( - lang(lng_info_add_as_contact), - [user] { PeerMenuAddContact(user); }); + if (!user->isSelf()) { + _addAction( + lang(lng_info_add_as_contact), + [user] { PeerMenuAddContact(user); }); + } _addAction( lang(lng_info_share_contact), [user] { PeerMenuShareContactBox(user); }); @@ -412,7 +416,7 @@ void Filler::fill() { if (showInfo()) { addInfo(); } - if (_source != PeerMenuSource::Profile) { + if (_source != PeerMenuSource::Profile && !_peer->isSelf()) { addNotifications(); } if (_source == PeerMenuSource::ChatsList) {