mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-11 09:19:35 +00:00
Improve search in peer / search from user design.
This commit is contained in:
parent
0a6535ea94
commit
99afa1196c
@ -246,10 +246,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_no_chats" = "Your chats will be here";
|
||||
"lng_contacts_loading" = "Loading...";
|
||||
"lng_contacts_not_found" = "No contacts found";
|
||||
"lng_dlg_search_chat" = "Search in this chat";
|
||||
"lng_dlg_search_channel" = "Search in this channel";
|
||||
"lng_dlg_search_for_messages" = "Search for messages";
|
||||
"lng_update_telegram" = "Update Telegram";
|
||||
"lng_dlg_search_in" = "Search messages in";
|
||||
"lng_dlg_search_from" = "From: {user}";
|
||||
|
||||
"lng_settings_save" = "Save";
|
||||
"lng_settings_upload" = "Set Profile Photo";
|
||||
@ -1427,6 +1427,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
"lng_profile_group_info" = "Group info";
|
||||
"lng_profile_channel_info" = "Channel info";
|
||||
"lng_channel_add_admins" = "New administrator";
|
||||
"lng_dlg_search_chat" = "Search in this chat";
|
||||
"lng_dlg_search_channel" = "Search in this channel";
|
||||
|
||||
// Wnd specific
|
||||
|
||||
|
@ -113,9 +113,6 @@ dialogsSearchFrom: IconButton(dialogsCalendar) {
|
||||
iconOver: icon {{ "dialogs_search_from", dialogsMenuIconFgOver }};
|
||||
}
|
||||
dialogsSearchFromPadding: margins(10px, 10px, 10px, 10px);
|
||||
dialogsSearchFromBubble: MultiSelectItem(defaultMultiSelectItem) {
|
||||
maxWidth: 240px;
|
||||
}
|
||||
|
||||
dialogsFilter: FlatInput(defaultFlatInput) {
|
||||
font: font(fsize);
|
||||
@ -223,3 +220,16 @@ dialogsForwardCancel: IconButton {
|
||||
iconPosition: point(12px, 11px);
|
||||
}
|
||||
dialogsForwardFont: semiboldFont;
|
||||
|
||||
dialogsSearchInHeight: 52px;
|
||||
dialogsSearchInPhotoSize: 36px;
|
||||
dialogsSearchInPhotoPadding: 10px;
|
||||
dialogsSearchInSkip: 6px;
|
||||
dialogsSearchFromStyle: TextStyle(defaultTextStyle) {
|
||||
font: normalFont;
|
||||
linkFont: semiboldFont;
|
||||
linkFontOver: semiboldFont;
|
||||
}
|
||||
dialogsSearchFromPalette: TextPalette(defaultTextPalette) {
|
||||
linkFg: dialogsNameFg;
|
||||
}
|
||||
|
@ -48,11 +48,6 @@ constexpr auto kStartReorderThreshold = 30;
|
||||
|
||||
} // namespace
|
||||
|
||||
class DialogsInner::SearchFromBubble : public Ui::MultiSelect::Item {
|
||||
public:
|
||||
using Item::Item;
|
||||
};
|
||||
|
||||
struct DialogsInner::ImportantSwitch {
|
||||
Dialogs::RippleRow row;
|
||||
};
|
||||
@ -78,7 +73,8 @@ DialogsInner::DialogsInner(QWidget *parent, gsl::not_null<Window::Controller*> c
|
||||
, _contacts(std::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
|
||||
, _a_pinnedShifting(animation(this, &DialogsInner::step_pinnedShifting))
|
||||
, _addContactLnk(this, lang(lng_add_contact_button))
|
||||
, _cancelSearchInPeer(this, st::dialogsCancelSearchInPeer) {
|
||||
, _cancelSearchInPeer(this, st::dialogsCancelSearchInPeer)
|
||||
, _cancelSearchFromUser(this, st::dialogsCancelSearchInPeer) {
|
||||
|
||||
#ifdef OS_MAC_OLD
|
||||
// Qt 5.3.2 build is working with glitches otherwise.
|
||||
@ -93,8 +89,10 @@ DialogsInner::DialogsInner(QWidget *parent, gsl::not_null<Window::Controller*> c
|
||||
connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*)));
|
||||
connect(main, SIGNAL(dialogRowReplaced(Dialogs::Row*, Dialogs::Row*)), this, SLOT(onDialogRowReplaced(Dialogs::Row*, Dialogs::Row*)));
|
||||
connect(_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact()));
|
||||
connect(_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer()));
|
||||
_cancelSearchInPeer->setClickedCallback([this] { cancelSearchInPeer(); });
|
||||
_cancelSearchInPeer->hide();
|
||||
_cancelSearchFromUser->setClickedCallback([this] { searchFromUserChanged.notify(nullptr); });
|
||||
_cancelSearchFromUser->hide();
|
||||
|
||||
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });
|
||||
subscribe(Global::RefItemRemoved(), [this](HistoryItem *item) {
|
||||
@ -139,9 +137,9 @@ int DialogsInner::searchedOffset() const {
|
||||
}
|
||||
|
||||
int DialogsInner::searchInPeerSkip() const {
|
||||
auto result = st::dialogsRowHeight;
|
||||
if (_searchFromUserBubble) {
|
||||
result += st::lineWidth + st::dialogsSearchFromPadding.top() + _searchFromUserBubble->rect().height() + st::dialogsSearchFromPadding.bottom();
|
||||
auto result = st::searchedBarHeight + st::dialogsSearchInHeight;
|
||||
if (_searchFromUser) {
|
||||
result += st::lineWidth + st::dialogsSearchInHeight;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -295,7 +293,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
||||
if (!paintingOther) {
|
||||
p.setFont(st::searchedBarFont);
|
||||
p.setPen(st::searchedBarFg);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), lang(lng_search_global_results), style::al_center);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), lang(lng_search_global_results));
|
||||
}
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
@ -325,7 +323,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
||||
if (!paintingOther) {
|
||||
p.setFont(st::searchedBarFont);
|
||||
p.setPen(st::searchedBarFg);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), lang(lng_dlg_search_for_messages), style::al_center);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), lang(lng_dlg_search_for_messages));
|
||||
}
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
}
|
||||
@ -337,7 +335,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
||||
if (!paintingOther) {
|
||||
p.setFont(st::searchedBarFont);
|
||||
p.setPen(st::searchedBarFg);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), text, style::al_center);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), text);
|
||||
}
|
||||
p.translate(0, st::searchedBarHeight);
|
||||
|
||||
@ -429,35 +427,46 @@ void DialogsInner::paintPeerSearchResult(Painter &p, const PeerSearchResult *res
|
||||
|
||||
void DialogsInner::paintSearchInPeer(Painter &p, int fullWidth, bool onlyBackground, TimeMs ms) const {
|
||||
auto height = searchInPeerSkip();
|
||||
auto fullRect = QRect(0, 0, fullWidth, height);
|
||||
|
||||
auto top = st::searchedBarHeight;
|
||||
p.fillRect(0, 0, fullWidth, top, st::searchedBarBg);
|
||||
if (!onlyBackground) {
|
||||
p.setFont(st::searchedBarFont);
|
||||
p.setPen(st::searchedBarFg);
|
||||
p.drawTextLeft(st::searchedBarPosition.x(), st::searchedBarPosition.y(), width(), lang(lng_dlg_search_in));
|
||||
}
|
||||
|
||||
auto fullRect = QRect(0, top, fullWidth, height - top);
|
||||
p.fillRect(fullRect, st::dialogsBg);
|
||||
if (_searchFromUserBubble) {
|
||||
p.fillRect(QRect(0, st::dialogsRowHeight, width(), st::lineWidth), st::shadowFg);
|
||||
if (_searchFromUser) {
|
||||
p.fillRect(QRect(0, top + st::dialogsSearchInHeight, fullWidth, st::lineWidth), st::shadowFg);
|
||||
}
|
||||
if (onlyBackground) return;
|
||||
|
||||
_searchInPeer->paintUserpicLeft(p, st::dialogsPadding.x(), st::dialogsPadding.y(), getFullWidth(), st::dialogsPhotoSize);
|
||||
p.setPen(st::dialogsNameFg);
|
||||
paintSearchInFilter(p, _searchInPeer, top, fullWidth, _searchInPeer->nameText);
|
||||
if (_searchFromUser) {
|
||||
top += st::dialogsSearchInHeight + st::lineWidth;
|
||||
p.setPen(st::dialogsTextFg);
|
||||
p.setTextPalette(st::dialogsSearchFromPalette);
|
||||
paintSearchInFilter(p, _searchFromUser, top, fullWidth, _searchFromUserText);
|
||||
p.restoreTextPalette();
|
||||
}
|
||||
}
|
||||
|
||||
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
|
||||
void DialogsInner::paintSearchInFilter(Painter &p, gsl::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;
|
||||
QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height);
|
||||
|
||||
if (auto chatTypeIcon = Dialogs::Layout::ChatTypeIcon(_searchInPeer, false, false)) {
|
||||
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);
|
||||
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
|
||||
}
|
||||
|
||||
QRect tr(nameleft, st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip, namewidth, st::dialogsTextFont->height);
|
||||
p.setFont(st::dialogsTextFont);
|
||||
p.setPen(st::dialogsTextFg);
|
||||
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(lang((_searchInPeer->isChannel() && !_searchInPeer->isMegagroup()) ? lng_dlg_search_channel : lng_dlg_search_chat), tr.width()));
|
||||
|
||||
p.setPen(st::dialogsNameFg);
|
||||
_searchInPeer->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
|
||||
|
||||
if (_searchFromUserBubble) {
|
||||
_searchFromUserBubble->paint(p, width(), ms);
|
||||
}
|
||||
p.setPen(pen);
|
||||
text.drawLeftElided(p, rectForName.left(), rectForName.top(), rectForName.width(), width());
|
||||
}
|
||||
|
||||
void DialogsInner::activate() {
|
||||
@ -493,14 +502,6 @@ void DialogsInner::updateSelected(QPoint localPos) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_searchFromUserBubble) {
|
||||
if (_searchFromUserBubble->rect().contains(localPos)) {
|
||||
_searchFromUserBubble->mouseMoveEvent(localPos - _searchFromUserBubble->rect().topLeft());
|
||||
} else {
|
||||
_searchFromUserBubble->leaveEvent();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_mouseSelection) {
|
||||
return;
|
||||
}
|
||||
@ -578,26 +579,10 @@ void DialogsInner::updateSelected(QPoint localPos) {
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::handleSearchFromUserClick() {
|
||||
Expects(_searchFromUserBubble != nullptr);
|
||||
if (_searchFromUserBubble->isOverDelete()) {
|
||||
searchFromUserChanged.notify(nullptr);
|
||||
} else {
|
||||
Dialogs::ShowSearchFromBox(_searchInPeer, base::lambda_guarded(this, [this](gsl::not_null<UserData*> user) {
|
||||
Ui::hideLayer();
|
||||
searchFromUserChanged.notify(user);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::mousePressEvent(QMouseEvent *e) {
|
||||
_mouseSelection = true;
|
||||
updateSelected(e->pos());
|
||||
|
||||
if (_searchFromUserBubble && _searchFromUserBubble->rect().contains(e->pos())) {
|
||||
return handleSearchFromUserClick();
|
||||
}
|
||||
|
||||
_pressButton = e->button();
|
||||
setPressed(_selected);
|
||||
setImportantSwitchPressed(_importantSwitchSelected);
|
||||
@ -955,14 +940,8 @@ void DialogsInner::setSearchedPressed(int pressed) {
|
||||
void DialogsInner::resizeEvent(QResizeEvent *e) {
|
||||
_addContactLnk->move((width() - _addContactLnk->width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2);
|
||||
auto widthForCancelButton = qMax(width() + otherWidth(), st::dialogsWidthMin);
|
||||
_cancelSearchInPeer->moveToLeft(widthForCancelButton - st::dialogsFilterSkip - st::dialogsFilterPadding.x() - _cancelSearchInPeer->width(), (st::dialogsRowHeight - st::dialogsCancelSearchInPeer.height) / 2);
|
||||
updateSearchFromBubble();
|
||||
}
|
||||
|
||||
void DialogsInner::updateSearchFromBubble() {
|
||||
if (_searchFromUserBubble) {
|
||||
_searchFromUserBubble->setPosition(st::dialogsSearchFromPadding.left(), st::dialogsRowHeight + st::lineWidth + st::dialogsSearchFromPadding.top(), width(), st::dialogsSearchFromPadding.left());
|
||||
}
|
||||
_cancelSearchInPeer->moveToLeft(widthForCancelButton - st::dialogsSearchInSkip - _cancelSearchInPeer->width(), st::searchedBarHeight + (st::dialogsSearchInHeight - st::dialogsCancelSearchInPeer.height) / 2);
|
||||
_cancelSearchFromUser->moveToLeft(widthForCancelButton - st::dialogsSearchInSkip - _cancelSearchFromUser->width(), st::searchedBarHeight + st::dialogsSearchInHeight + st::lineWidth + (st::dialogsSearchInHeight - st::dialogsCancelSearchInPeer.height) / 2);
|
||||
}
|
||||
|
||||
void DialogsInner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRow) {
|
||||
@ -1193,9 +1172,6 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
|
||||
void DialogsInner::leaveEventHook(QEvent *e) {
|
||||
setMouseTracking(false);
|
||||
clearSelection();
|
||||
if (_searchFromUserBubble) {
|
||||
_searchFromUserBubble->leaveEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogsInner::dragLeft() {
|
||||
@ -1754,19 +1730,18 @@ void DialogsInner::searchInPeer(PeerData *peer, UserData *from) {
|
||||
_searchInPeer = peer ? (peer->migrateTo() ? peer->migrateTo() : peer) : nullptr;
|
||||
_searchInMigrated = _searchInPeer ? _searchInPeer->migrateFrom() : nullptr;
|
||||
_searchFromUser = from;
|
||||
if (_searchFromUser) {
|
||||
_searchFromUserBubble = std::make_unique<SearchFromBubble>(st::dialogsSearchFromBubble, _searchFromUser->id, App::peerName(_searchFromUser), st::activeButtonBg, PaintUserpicCallback(_searchFromUser));
|
||||
_searchFromUserBubble->setUpdateCallback([this] { update(0, st::dialogsRowHeight + st::lineWidth, width(), searchInPeerSkip() - st::dialogsRowHeight - st::lineWidth); });
|
||||
updateSearchFromBubble();
|
||||
} else {
|
||||
_searchFromUserBubble.reset();
|
||||
}
|
||||
if (_searchInPeer) {
|
||||
onHashtagFilterUpdate(QStringRef());
|
||||
_cancelSearchInPeer->show();
|
||||
} else {
|
||||
_cancelSearchInPeer->hide();
|
||||
}
|
||||
if (_searchFromUser) {
|
||||
_searchFromUserText.setText(st::dialogsSearchFromStyle, lng_dlg_search_from(lt_user, textcmdLink(1, App::peerName(_searchFromUser))), _textDlgOptions);
|
||||
_cancelSearchFromUser->show();
|
||||
} else {
|
||||
_cancelSearchFromUser->hide();
|
||||
}
|
||||
_controller->dialogsListDisplayForced().set(_searchInPeer || !_filter.isEmpty(), true);
|
||||
}
|
||||
|
||||
|
@ -194,12 +194,11 @@ 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, gsl::not_null<PeerData*> peer, int top, int fullWidth, const Text &text) const;
|
||||
|
||||
void clearSelection();
|
||||
void clearSearchResults(bool clearPeerSearchResults = true);
|
||||
void updateSelectedRow(PeerData *peer = 0);
|
||||
void updateSearchFromBubble();
|
||||
void handleSearchFromUserClick();
|
||||
|
||||
Dialogs::IndexedList *shownDialogs() const {
|
||||
return (Global::DialogsMode() == Dialogs::Mode::Important) ? _dialogsImportant.get() : _dialogs.get();
|
||||
@ -281,12 +280,12 @@ private:
|
||||
|
||||
object_ptr<Ui::LinkButton> _addContactLnk;
|
||||
object_ptr<Ui::IconButton> _cancelSearchInPeer;
|
||||
object_ptr<Ui::IconButton> _cancelSearchFromUser;
|
||||
|
||||
PeerData *_searchInPeer = nullptr;
|
||||
PeerData *_searchInMigrated = nullptr;
|
||||
UserData *_searchFromUser = nullptr;
|
||||
class SearchFromBubble; // Just a wrap for Ui::MultiSelect::Item.
|
||||
std::unique_ptr<SearchFromBubble> _searchFromUserBubble;
|
||||
Text _searchFromUserText;
|
||||
PeerData *_menuPeer = nullptr;
|
||||
|
||||
Ui::PopupMenu *_menu = nullptr;
|
||||
|
@ -27,8 +27,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
namespace Dialogs {
|
||||
|
||||
void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*>)> callback) {
|
||||
auto createController = [peer, callback = std::move(callback)]()->std::unique_ptr<PeerListController> {
|
||||
void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*>)> callback, base::lambda<void()> closedCallback) {
|
||||
auto createController = [peer, callback = std::move(callback)]() -> std::unique_ptr<PeerListController> {
|
||||
if (peer) {
|
||||
if (auto chat = peer->asChat()) {
|
||||
return std::make_unique<Dialogs::ChatSearchFromController>(chat, std::move(callback));
|
||||
@ -39,9 +39,10 @@ void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*
|
||||
return nullptr;
|
||||
};
|
||||
if (auto controller = createController()) {
|
||||
Ui::show(Box<PeerListBox>(std::move(controller), [](PeerListBox *box) {
|
||||
auto box = Ui::show(Box<SearchFromBox>(std::move(controller), [](PeerListBox *box) {
|
||||
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
|
||||
}), KeepOtherLayers);
|
||||
box->setClosedCallback(std::move(closedCallback));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,27 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||
|
||||
namespace Dialogs {
|
||||
|
||||
void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*>)> callback);
|
||||
void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*>)> callback, base::lambda<void()> closedCallback);
|
||||
|
||||
class SearchFromBox : public PeerListBox {
|
||||
public:
|
||||
using PeerListBox::PeerListBox;
|
||||
|
||||
void setClosedCallback(base::lambda<void()> callback) {
|
||||
_closedCallback = std::move(callback);
|
||||
}
|
||||
|
||||
protected:
|
||||
void closeHook() override {
|
||||
if (_closedCallback) {
|
||||
_closedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
base::lambda<void()> _closedCallback;
|
||||
|
||||
};
|
||||
|
||||
class ChatSearchFromController : public PeerListController, protected base::Subscriber {
|
||||
public:
|
||||
|
@ -874,7 +874,7 @@ void DialogsWidget::showSearchFrom() {
|
||||
Ui::hideLayer();
|
||||
setSearchInPeer(peer, user);
|
||||
onFilterUpdate(true);
|
||||
}));
|
||||
}), base::lambda_guarded(this, [this] { _filter->setFocus(); }));
|
||||
}
|
||||
|
||||
void DialogsWidget::onFilterCursorMoved(int from, int to) {
|
||||
|
Loading…
Reference in New Issue
Block a user