Support Saved messages in chats list and forwards.

This commit is contained in:
John Preston 2017-12-05 18:07:01 +04:00
parent e4ce08e64e
commit 46bafc2dcc
21 changed files with 532 additions and 176 deletions

View File

@ -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}:";

View File

@ -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<PeerData*> 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<PeerData*> 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<void()> updateCallback) {
_checkbox = std::make_unique<Ui::RoundImageCheckbox>(
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<PeerListRow*> row) {
}
void PeerListContent::changeCheckState(not_null<PeerListRow*> 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<PeerListRow*> 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();

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include <rpl/event_stream.h>
#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<PeerData*> peer,
bool respectSavedMessagesChat)
->base::lambda<void(Painter &p, int x, int y, int outerWidth, int size)> {
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 <typename UpdateCallback>
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<PeerData*> peer) override;
void peerListSearchRefreshRows() override;
virtual bool respectSavedMessagesChat() const {
return false;
}
virtual rpl::producer<int> onlineCountValue() const;
rpl::lifetime &lifetime() {

View File

@ -220,7 +220,9 @@ bool PeerListGlobalSearchController::isLoading() {
return _timer.isActive() || _requestId;
}
ChatsListBoxController::ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController) : PeerListController(std::move(searchController)) {
ChatsListBoxController::ChatsListBoxController(
std::unique_ptr<PeerListSearchController> 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<const Row&>(a).history();
return history->inChatList(Dialogs::Mode::All);
});
if (respectSavedMessagesChat()) {
delegate()->peerListPartitionRows([](const PeerListRow &a) {
return a.peer()->isSelf();
});
}
}
checkForEmptyRows();
delegate()->peerListRefreshRows();

View File

@ -90,9 +90,13 @@ private:
};
class ChatsListBoxController : public PeerListController, protected base::Subscriber {
class ChatsListBoxController
: public PeerListController
, protected base::Subscriber {
public:
ChatsListBoxController(std::unique_ptr<PeerListSearchController> searchController = std::make_unique<PeerListGlobalSearchController>());
ChatsListBoxController(
std::unique_ptr<PeerListSearchController> searchController
= std::make_unique<PeerListGlobalSearchController>());
void prepare() override final;
std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData*> peer) override final;
@ -243,11 +247,16 @@ public:
void rowClicked(not_null<PeerListRow*> row) override;
bool respectSavedMessagesChat() const override {
return true;
}
protected:
void prepareViewHook() override;
std::unique_ptr<Row> createRow(
not_null<History*> history) override;
private:
base::lambda<void(not_null<PeerData*>)> _callback;
};

View File

@ -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<PeerData*> 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*> chat,
not_null<PeerData*> 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<PeerData*> peer) {
repaintChatAtIndex(chatIndex(peer));
}
int ShareBox::Inner::chatIndex(PeerData *peer) const {
int ShareBox::Inner::chatIndex(not_null<PeerData*> 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*> 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<void()> 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<PeerData*> peer) {
if (auto chat = _dataMap.value(peer, nullptr)) {
changePeerCheckState(chat, false, ChangeStateWay::SkipCallback);
}
}
void ShareBox::Inner::setPeerSelectedChangedCallback(base::lambda<void(PeerData *peer, bool selected)> 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*> 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);
}
}

View File

@ -115,7 +115,7 @@ public:
Inner(QWidget *parent, ShareBox::FilterCallback &&filterCallback);
void setPeerSelectedChangedCallback(base::lambda<void(PeerData *peer, bool selected)> callback);
void peerUnselected(PeerData *peer);
void peerUnselected(not_null<PeerData*> peer);
QVector<PeerData*> 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*> chat, int index);
void updateChat(not_null<PeerData*> peer);
void updateChatName(not_null<Chat*> chat, not_null<PeerData*> peer);
void repaintChat(not_null<PeerData*> peer);
int chatIndex(not_null<PeerData*> 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*> chat,
bool checked,
ChangeStateWay useCallback = ChangeStateWay::Default);
Chat *getChat(Dialogs::Row *row);
void setActive(int active);

View File

@ -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]);
}

View File

@ -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<PeerData*> 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();

View File

@ -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<PeerData*> 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<void()> _loadMoreCallback;

View File

@ -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 <typename PaintItemCallback, typename PaintCounterCallback>
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<Flag> 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);

View File

@ -458,3 +458,5 @@ historyFastShareSize: 31px;
historyFastShareLeft: 13px;
historyFastShareBottom: 5px;
historyFastShareIcon: icon {{ "fast_share", msgServiceFg, point(4px, 3px)}};
historySavedFont: font(semibold 15px);

View File

@ -186,7 +186,9 @@ void FastShareMessage(not_null<HistoryItem*> item) {
OrderedSet<mtpRequestId> requests;
};
auto data = MakeShared<ShareData>(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<HistoryItem*> item) {
}
return false;
};
auto copyLinkCallback = canCopyLink ? base::lambda<void()>(std::move(copyCallback)) : base::lambda<void()>();
Ui::show(Box<ShareBox>(std::move(copyLinkCallback), std::move(submitCallback), std::move(filterCallback)));
auto copyLinkCallback = canCopyLink
? base::lambda<void()>(std::move(copyCallback))
: base::lambda<void()>();
Ui::show(Box<ShareBox>(
std::move(copyLinkCallback),
std::move(submitCallback),
std::move(filterCallback)));
}
void HistoryInitMessages() {

View File

@ -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();

View File

@ -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() {

View File

@ -48,11 +48,21 @@ std::vector<std::unique_ptr<ContentMemento>> Memento::DefaultStack(
PeerId peerId,
Section section) {
auto result = std::vector<std::unique_ptr<ContentMemento>>();
result.push_back(Default(peerId, section));
result.push_back(DefaultContent(peerId, section));
return result;
}
std::unique_ptr<ContentMemento> Memento::Default(
Section Memento::DefaultSection(not_null<PeerData*> peer) {
return peer->isSelf()
? Section(Section::MediaType::Photo)
: Section(Section::Type::Profile);
}
Memento Memento::Default(not_null<PeerData*> peer) {
return Memento(peer->id, DefaultSection(peer));
}
std::unique_ptr<ContentMemento> Memento::DefaultContent(
PeerId peerId,
Section section) {
Expects(peerId != 0);
@ -84,7 +94,7 @@ std::unique_ptr<ContentMemento> Memento::Default(
peerId,
migratedPeerId);
}
Unexpected("Wrong section type in Info::Memento::Default()");
Unexpected("Wrong section type in Info::Memento::DefaultContent()");
}
object_ptr<Window::SectionWidget> Memento::createWidget(

View File

@ -64,13 +64,16 @@ public:
return _stack.back().get();
}
static Section DefaultSection(not_null<PeerData*> peer);
static Memento Default(not_null<PeerData*> peer);
~Memento();
private:
static std::vector<std::unique_ptr<ContentMemento>> DefaultStack(
PeerId peerId,
Section section);
static std::unique_ptr<ContentMemento> Default(
static std::unique_ptr<ContentMemento> DefaultContent(
PeerId peerId,
Section section);

View File

@ -124,17 +124,35 @@ void WrapWidget::startInjectingActivePeerProfiles() {
}
void WrapWidget::injectActivePeerProfile(not_null<PeerData*> 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));

View File

@ -261,15 +261,18 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
});
addInfoLine(lng_info_about_label, AboutValue(_peer));
}
result->add(object_ptr<Ui::SlideWrap<>>(
result,
object_ptr<Ui::PlainShadow>(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<Ui::SlideWrap<>>(
result,
object_ptr<Ui::PlainShadow>(result),
st::infoProfileSeparatorPadding)
)->setDuration(
st::infoSlideDuration
)->toggleOn(
std::move(tracker).atLeastOneShownValue()
);
}
object_ptr<FloatingIcon>(
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<Ui::SlideWrap<>>(
_wrap,
object_ptr<Ui::PlainShadow>(_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<Ui::RpWidget> DetailsFiller::fill() {
add(object_ptr<BoxContentDivider>(_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<UserData*> user) {
addInviteToGroupAction(user);
}
addShareContactAction(user);
addEditContactAction(user);
addDeleteContactAction(user);
if (!user->isSelf()) {
addEditContactAction(user);
addDeleteContactAction(user);
}
addClearHistoryAction(user);
addDeleteConversationAction(user);
if (!user->isSelf()) {

View File

@ -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<Info::Memento>(peer->id);
return std::make_unique<Info::Memento>(
peer->id,
Info::Memento::DefaultSection(peer));
}
void MainWidget::updateThirdColumnToCurrentPeer(

View File

@ -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<UserData*> user) {
_addAction(
lang(lng_info_share_contact),
[user] { PeerMenuShareContactBox(user); });
_addAction(
lang(lng_info_edit_contact),
[user] { Ui::show(Box<AddContactBox>(user)); });
_addAction(
lang(lng_info_delete_contact),
[user] { PeerMenuDeleteContact(user); });
if (!user->isSelf()) {
_addAction(
lang(lng_info_edit_contact),
[user] { Ui::show(Box<AddContactBox>(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) {