mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-09 00:27:09 +00:00
Support Saved messages in chats list and forwards.
This commit is contained in:
parent
e4ce08e64e
commit
46bafc2dcc
@ -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}:";
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -458,3 +458,5 @@ historyFastShareSize: 31px;
|
||||
historyFastShareLeft: 13px;
|
||||
historyFastShareBottom: 5px;
|
||||
historyFastShareIcon: icon {{ "fast_share", msgServiceFg, point(4px, 3px)}};
|
||||
|
||||
historySavedFont: font(semibold 15px);
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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()) {
|
||||
|
@ -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(
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user