From aabf13669025f2eb026bd09df911220f916251db Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 4 Aug 2015 18:01:47 +0300 Subject: [PATCH] search in conversation, clear history and delete conversation for all chats --- Telegram/Resources/lang.strings | 7 ++ Telegram/SourceFiles/app.cpp | 9 -- Telegram/SourceFiles/app.h | 1 - Telegram/SourceFiles/dialogswidget.cpp | 118 +++++++++++++++++++--- Telegram/SourceFiles/dialogswidget.h | 12 +++ Telegram/SourceFiles/gui/flattextarea.cpp | 2 + Telegram/SourceFiles/history.cpp | 10 +- Telegram/SourceFiles/historywidget.cpp | 2 + Telegram/SourceFiles/mainwidget.cpp | 47 +++++---- Telegram/SourceFiles/mainwidget.h | 6 +- Telegram/SourceFiles/profilewidget.cpp | 59 +++++++++-- Telegram/SourceFiles/profilewidget.h | 7 +- 12 files changed, 225 insertions(+), 55 deletions(-) diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings index 115bf77c5..1eb67ca5f 100644 --- a/Telegram/Resources/lang.strings +++ b/Telegram/Resources/lang.strings @@ -158,6 +158,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_no_contacts" = "You have no contacts"; "lng_contacts_loading" = "Loading.."; "lng_contacts_not_found" = "No contacts found"; +"lng_dlg_search_chat" = "Search in this chat"; +"lng_dlg_search_for_messages" = "Search for messages"; "lng_settings_save" = "Save"; "lng_settings_upload" = "Set Profile Photo"; @@ -339,6 +341,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_topbar_info" = "Info"; "lng_profile_about_section" = "About"; "lng_profile_settings_section" = "Settings"; +"lng_profile_actions_section" = "Actions"; "lng_profile_bot_settings" = "Settings"; "lng_profile_bot_help" = "Help"; "lng_profile_participants_section" = "Members"; @@ -348,6 +351,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_profile_edit_contact" = "Edit"; "lng_profile_enable_notifications" = "Notifications"; "lng_profile_clear_history" = "Clear history"; +"lng_profile_delete_conversation" = "Delete conversation"; +"lng_profile_clear_and_exit" = "Delete and exit"; +"lng_profile_search_messages" = "Search for messages"; "lng_profile_send_message" = "Send Message"; "lng_profile_share_contact" = "Share Contact"; "lng_profile_invite_to_group" = "Add to Group"; @@ -382,6 +388,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org "lng_sure_delete_contact" = "Are you sure, you want to delete {contact} from your contact list?"; "lng_sure_delete_history" = "Are you sure, you want to delete all message history with {contact}?\n\nThis action cannot be undone."; +"lng_sure_delete_group_history" = "Are you sure, you want to delete all message history in «{group}»?\n\nThis action cannot be undone."; "lng_sure_delete_and_exit" = "Are you sure, you want to delete all message history and leave «{group}»?\n\nThis action cannot be undone."; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index a5b5659a2..120fae069 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1752,15 +1752,6 @@ namespace App { } } - /* // don't delete history without deleting its' peerdata - void deleteHistory(const PeerId &peer) { - Histories::iterator i = ::histories.find(peer); - if (i != ::histories.end()) { - ::histories.typing.remove(i.value()); - ::histories.erase(i); - } - } -/**/ void historyRegRandom(uint64 randomId, MsgId itemId) { randomData.insert(randomId, itemId); } diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index 5a91cba2a..c1befed22 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -183,7 +183,6 @@ namespace App { void historyClearItems(); void historyRegReply(HistoryReply *reply, HistoryItem *to); void historyUnregReply(HistoryReply *reply, HistoryItem *to); -// void deleteHistory(const PeerId &peer); void historyRegRandom(uint64 randomId, MsgId itemId); void historyUnregRandom(uint64 randomId); diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp index 89ba6f814..427f87d3f 100644 --- a/Telegram/SourceFiles/dialogswidget.cpp +++ b/Telegram/SourceFiles/dialogswidget.cpp @@ -42,12 +42,16 @@ peopleSel(-1), _lastSearchId(0), _state(DefaultState), _addContactLnk(this, lang(lng_add_contact_button)), -_overDelete(false) { +_cancelSearchInPeer(this, st::btnCancelSearch), +_overDelete(false), +_searchInPeer(0) { connect(main, SIGNAL(dialogToTop(const History::DialogLinks&)), this, SLOT(onDialogToTop(const History::DialogLinks&))); connect(main, SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&))); connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*))); connect(main, SIGNAL(dialogRowReplaced(DialogRow*,DialogRow*)), this, SLOT(onDialogRowReplaced(DialogRow*,DialogRow*))); connect(&_addContactLnk, SIGNAL(clicked()), App::wnd(), SLOT(onShowAddContact())); + connect(&_cancelSearchInPeer, SIGNAL(clicked()), this, SIGNAL(cancelSearchInPeer())); + _cancelSearchInPeer.hide(); refresh(false); } @@ -60,7 +64,9 @@ int32 DialogsListWidget::peopleOffset() const { } int32 DialogsListWidget::searchedOffset() const { - return peopleOffset() + (peopleResults.isEmpty() ? 0 : ((peopleResults.size() * st::dlgHeight) + st::searchedBarHeight)); + int32 result = peopleOffset() + (peopleResults.isEmpty() ? 0 : ((peopleResults.size() * st::dlgHeight) + st::searchedBarHeight)); + if (_searchInPeer) result += st::dlgHeight; + return result; } void DialogsListWidget::paintEvent(QPaintEvent *e) { @@ -181,6 +187,18 @@ void DialogsListWidget::paintEvent(QPaintEvent *e) { } } + if (_searchInPeer) { + searchInPeerPaint(p, width()); + p.translate(0, st::dlgHeight); + if (_state == FilteredState && searchResults.isEmpty()) { + p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); + p.setFont(st::searchedBarFont->f); + p.setPen(st::searchedBarColor->p); + p.drawText(QRect(0, 0, width(), st::searchedBarHeight), lang(lng_dlg_search_for_messages), style::al_center); + p.translate(0, st::searchedBarHeight); + } + } + if (_state == SearchedState || !searchResults.isEmpty()) { QString text = lng_search_found_results(lt_count, searchResults.isEmpty() ? 0 : searchedCount); p.fillRect(0, 0, width(), st::searchedBarHeight, st::searchedBarBG->b); @@ -252,6 +270,31 @@ void DialogsListWidget::peopleResultPaint(UserData *user, QPainter &p, int32 w, history->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); } +void DialogsListWidget::searchInPeerPaint(QPainter &p, int32 w) const { + QRect fullRect(0, 0, w, st::dlgHeight); + p.fillRect(fullRect, st::dlgBG->b); + + p.drawPixmap(st::dlgPaddingHor, st::dlgPaddingVer, _searchInPeer->photo->pix(st::dlgPhotoSize)); + + int32 nameleft = st::dlgPaddingHor + st::dlgPhotoSize + st::dlgPhotoPadding; + int32 namewidth = w - nameleft - st::dlgPaddingHor * 2 - st::btnCancelSearch.width; + QRect rectForName(nameleft, st::dlgPaddingVer + st::dlgNameTop, namewidth, st::msgNameFont->height); + + // draw chat icon + if (_searchInPeer->chat) { + p.drawPixmap(QPoint(rectForName.left() + st::dlgChatImgLeft, rectForName.top() + st::dlgChatImgTop), App::sprite(), st::dlgChatImg); + rectForName.setLeft(rectForName.left() + st::dlgChatImgSkip); + } + + QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height); + p.setFont(st::dlgHistFont->f); + p.setPen(st::dlgTextColor->p); + p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->m.elidedText(lang(lng_dlg_search_chat), Qt::ElideRight, tr.width())); + + p.setPen(st::dlgNameColor->p); + App::history(_searchInPeer->id)->nameText.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); +} + void DialogsListWidget::activate() { } @@ -347,6 +390,7 @@ void DialogsListWidget::mousePressEvent(QMouseEvent *e) { void DialogsListWidget::resizeEvent(QResizeEvent *e) { _addContactLnk.move((width() - _addContactLnk.width()) / 2, (st::noContactsHeight + st::noContactsFont->height) / 2); + _cancelSearchInPeer.move(width() - st::dlgPaddingHor - st::btnCancelSearch.width, (st::dlgHeight - st::btnCancelSearch.height) / 2); } void DialogsListWidget::onDialogRowReplaced(DialogRow *oldRow, DialogRow *newRow) { @@ -397,9 +441,6 @@ void DialogsListWidget::removePeer(PeerData *peer) { contactsNoDialogs.addByName(App::history(peer->id)); } } -// contactsNoDialogs.del(peer); -// contacts.del(peer); -// App::deleteHistory(peer->id); emit App::main()->dialogsUpdated(); @@ -539,7 +580,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) { } if (newFilter != filter || force) { filter = newFilter; - if (filter.isEmpty()) { + if (!_searchInPeer && filter.isEmpty()) { _state = DefaultState; hashtagResults.clear(); filterResults.clear(); @@ -551,7 +592,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) { _state = FilteredState; filterResults.clear(); - if (!f.isEmpty()) { + if (!_searchInPeer && !f.isEmpty()) { DialogsList *dialogsToFilter = 0, *contactsNoDialogsToFilter = 0; if (dialogs.list.count) { for (fi = fb; fi != fe; ++fi) { @@ -630,7 +671,7 @@ void DialogsListWidget::onFilterUpdate(QString newFilter, bool force) { } void DialogsListWidget::onHashtagFilterUpdate(QStringRef newFilter) { - if (newFilter.isEmpty() || newFilter.at(0) != '#') { + if (newFilter.isEmpty() || newFilter.at(0) != '#' || _searchInPeer) { _hashtagFilter = QString(); if (!hashtagResults.isEmpty()) { hashtagResults.clear(); @@ -817,7 +858,7 @@ void DialogsListWidget::refresh(bool toTop) { } else { if (!_addContactLnk.isHidden()) _addContactLnk.hide(); if (_state == FilteredState) { - h = searchedOffset() + (searchResults.count() * st::dlgHeight) + (searchResults.isEmpty() ? 0 : st::searchedBarHeight); + h = searchedOffset() + (searchResults.count() * st::dlgHeight) + ((searchResults.isEmpty() && !_searchInPeer) ? 0 : st::searchedBarHeight); } else if (_state == SearchedState) { h = searchedOffset() + (searchResults.count() * st::dlgHeight) + st::searchedBarHeight; } @@ -866,9 +907,23 @@ bool DialogsListWidget::hasFilteredResults() const { return !filterResults.isEmpty() && hashtagResults.isEmpty(); } +void DialogsListWidget::searchInPeer(PeerData *peer) { + _searchInPeer = peer; + if (_searchInPeer) { + onHashtagFilterUpdate(QStringRef()); + _cancelSearchInPeer.show(); + } else { + _cancelSearchInPeer.hide(); + } +} + void DialogsListWidget::clearFilter() { if (_state == FilteredState || _state == SearchedState) { - _state = DefaultState; + if (_searchInPeer) { + _state = FilteredState; + } else { + _state = DefaultState; + } hashtagResults.clear(); filterResults.clear(); peopleResults.clear(); @@ -1390,6 +1445,7 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent) , _cancelSearch(this, st::btnCancelSearch) , scroll(this, st::dlgScroll) , list(&scroll, parent) +, _searchInPeer(0) , _searchFull(false) , _peopleFull(false) { @@ -1401,6 +1457,7 @@ DialogsWidget::DialogsWidget(MainWidget *parent) : QWidget(parent) connect(&list, SIGNAL(searchResultChosen()), this, SLOT(onCancel())); connect(&list, SIGNAL(completeHashtag(QString)), this, SLOT(onCompleteHashtag(QString))); connect(&list, SIGNAL(refreshHashtags()), this, SLOT(onFilterCursorMoved())); + connect(&list, SIGNAL(cancelSearchInPeer()), this, SLOT(onCancelSearchInPeer())); connect(&scroll, SIGNAL(geometryChanged()), &list, SLOT(onParentGeometryChanged())); connect(&scroll, SIGNAL(scrolled()), &list, SLOT(onUpdateSelected())); connect(&scroll, SIGNAL(scrolled()), this, SLOT(onListScroll())); @@ -1496,7 +1553,7 @@ bool DialogsWidget::animStep(float64 ms) { } void DialogsWidget::onCancel() { - if (!onCancelSearch() || !App::main()->selectingPeer()) { + if (!onCancelSearch() || (!_searchInPeer && !App::main()->selectingPeer())) { emit cancelled(); } } @@ -1600,10 +1657,10 @@ bool DialogsWidget::onSearchMessages(bool searchCache) { } else if (_searchQuery != q) { _searchQuery = q; _searchFull = false; - _searchRequest = MTP::send(MTPmessages_Search(MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed)); + _searchRequest = MTP::send(MTPmessages_Search(_searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, true), rpcFail(&DialogsWidget::searchFailed)); _searchQueries.insert(_searchRequest, _searchQuery); } - if (q.size() >= MinUsernameLength) { + if (!_searchInPeer && q.size() >= MinUsernameLength) { if (searchCache) { PeopleCache::const_iterator i = _peopleCache.constFind(q); if (i != _peopleCache.cend()) { @@ -1647,7 +1704,7 @@ void DialogsWidget::searchMessages(const QString &query) { void DialogsWidget::onSearchMore(MsgId minMsgId) { if (!_searchRequest && !_searchFull) { - _searchRequest = MTP::send(MTPmessages_Search(MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed)); + _searchRequest = MTP::send(MTPmessages_Search(_searchInPeer ? _searchInPeer->input : MTP_inputPeerEmpty(), MTP_string(_searchQuery), MTP_inputMessagesFilterEmpty(), MTP_int(0), MTP_int(0), MTP_int(0), MTP_int(minMsgId), MTP_int(SearchPerPage)), rpcDone(&DialogsWidget::searchReceived, !minMsgId), rpcFail(&DialogsWidget::searchFailed)); if (!minMsgId) { _searchQueries.insert(_searchRequest, _searchQuery); } @@ -1877,6 +1934,14 @@ void DialogsWidget::onFilterUpdate(bool force) { } } +void DialogsWidget::searchInPeer(PeerData *peer) { + onCancelSearch(); + _searchInPeer = peer; + list.searchInPeer(peer); + onFilterUpdate(true); + list.onFilterUpdate(_filter.text(), true); +} + void DialogsWidget::onFilterCursorMoved(int from, int to) { if (to < 0) to = _filter.cursorPosition(); QString t = _filter.text(); @@ -2035,6 +2100,14 @@ void DialogsWidget::onNewGroup() { bool DialogsWidget::onCancelSearch() { bool clearing = !_filter.text().isEmpty(); + if (_searchInPeer && !clearing) { + if (!cWideMode()) { + App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId); + } + _searchInPeer = 0; + list.searchInPeer(0); + clearing = true; + } list.clearFilter(); _filter.clear(); _filter.updatePlaceholder(); @@ -2042,6 +2115,23 @@ bool DialogsWidget::onCancelSearch() { return clearing; } +void DialogsWidget::onCancelSearchInPeer() { + if (_searchInPeer) { + if (!cWideMode()) { + App::main()->showPeerHistory(_searchInPeer->id, ShowAtUnreadMsgId); + } + _searchInPeer = 0; + list.searchInPeer(0); + } + list.clearFilter(); + _filter.clear(); + _filter.updatePlaceholder(); + onFilterUpdate(); + if (cWideMode()) { + emit cancelled(); + } +} + void DialogsWidget::onDialogToTopFrom(int movedFrom) { if (scroll.scrollTop() > 0) { if (movedFrom > scroll.scrollTop()) { diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h index 922f2a813..ec7c1fa13 100644 --- a/Telegram/SourceFiles/dialogswidget.h +++ b/Telegram/SourceFiles/dialogswidget.h @@ -48,6 +48,7 @@ public: void leaveEvent(QEvent *e); void peopleResultPaint(UserData *user, QPainter &p, int32 w, bool act, bool sel) const; + void searchInPeerPaint(QPainter &p, int32 w) const; void selectSkip(int32 direction); void selectSkipPage(int32 pixels, int32 direction); @@ -93,6 +94,8 @@ public: State state() const; bool hasFilteredResults() const; + void searchInPeer(PeerData *peer); + void onFilterUpdate(QString newFilter, bool force = false); void onHashtagFilterUpdate(QStringRef newFilter); void itemRemoved(HistoryItem *item); @@ -117,6 +120,7 @@ signals: void dialogToTopFrom(int movedFrom); void searchMessages(); void searchResultChosen(); + void cancelSearchInPeer(); void completeHashtag(QString tag); void refreshHashtags(); @@ -156,9 +160,12 @@ private: void paintDialog(QPainter &p, DialogRow *dialog); LinkButton _addContactLnk; + IconedButton _cancelSearchInPeer; bool _overDelete; + PeerData *_searchInPeer; + }; class DialogsWidget : public QWidget, public Animated, public RPCSender { @@ -183,6 +190,8 @@ public: void keyPressEvent(QKeyEvent *e); void paintEvent(QPaintEvent *e); + void searchInPeer(PeerData *peer); + void loadDialogs(); void createDialogAtTop(History *history, int32 unreadCount); void dlgUpdated(DialogRow *row); @@ -226,6 +235,7 @@ public slots: void onAddContact(); void onNewGroup(); bool onCancelSearch(); + void onCancelSearchInPeer(); void onFilterCursorMoved(int from = -1, int to = -1); void onCompleteHashtag(QString tag); @@ -262,6 +272,8 @@ private: anim::ivalue a_coord, a_bgCoord; anim::fvalue a_alpha, a_bgAlpha; + PeerData *_searchInPeer; + QTimer _searchTimer; QString _searchQuery, _peopleQuery; bool _searchFull, _peopleFull; diff --git a/Telegram/SourceFiles/gui/flattextarea.cpp b/Telegram/SourceFiles/gui/flattextarea.cpp index ca001ec97..741a69901 100644 --- a/Telegram/SourceFiles/gui/flattextarea.cpp +++ b/Telegram/SourceFiles/gui/flattextarea.cpp @@ -774,6 +774,8 @@ void FlatTextarea::keyPressEvent(QKeyEvent *e) { } else { emit tabbed(); } + } else if (e->key() == Qt::Key_Search || e == QKeySequence::Find) { + e->ignore(); } else { QTextCursor tc(textCursor()); if (enter && ctrl) { diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp index 1d9e7a74f..2716d1c4d 100644 --- a/Telegram/SourceFiles/history.cpp +++ b/Telegram/SourceFiles/history.cpp @@ -1481,9 +1481,16 @@ void History::clear(bool leaveItems) { if (showFrom) { showFrom = 0; } + if (!leaveItems) { + lastMsg = 0; + } for (int32 i = 0; i < OverviewCount; ++i) { if (!_overview[i].isEmpty() || !_overviewIds[i].isEmpty()) { - if (_overviewCount[i] == 0) _overviewCount[i] = _overview[i].size(); + if (leaveItems) { + if (_overviewCount[i] == 0) _overviewCount[i] = _overview[i].size(); + } else { + _overviewCount[i] = -1; // not loaded yet + } _overview[i].clear(); _overviewIds[i].clear(); if (App::wnd() && !App::quiting()) App::wnd()->mediaOverviewUpdated(peer, MediaOverviewType(i)); @@ -1501,7 +1508,6 @@ void History::clear(bool leaveItems) { lastKeyboardInited = false; } else { setUnreadCount(0); - lastMsg = 0; } height = 0; oldLoaded = false; diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 32ce0a65d..2648c6e0e 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -4816,6 +4816,8 @@ void HistoryWidget::keyPressEvent(QKeyEvent *e) { App::main()->peerAfter(_peer, msgid, p, m); } if (p) App::main()->showPeerHistory(p->id, m); + } else if (_history && (e->key() == Qt::Key_Search || e == QKeySequence::Find)) { + App::main()->searchInPeer(_history->peer); } else { e->ignore(); } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index b56c882b7..47922db5b 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -122,7 +122,7 @@ void TopBarWidget::onDeleteAndExitSure() { if (c) { App::main()->showDialogs(); App::wnd()->hideLayer(); - MTP::send(MTPmessages_DeleteChatUser(MTP_int(p->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistory, p), App::main()->rpcFail(&MainWidget::leaveChatFailed, p)); + MTP::send(MTPmessages_DeleteChatUser(MTP_int(p->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, p), App::main()->rpcFail(&MainWidget::leaveChatFailed, p)); } } @@ -738,20 +738,20 @@ bool MainWidget::leaveChatFailed(PeerData *peer, const RPCError &error) { showDialogs(); } dialogs.removePeer(peer); - App::histories().remove(peer->id); + App::history(peer->id)->clear(); MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer)); return true; } return false; } -void MainWidget::deleteHistory(PeerData *peer, const MTPUpdates &updates) { +void MainWidget::deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates) { sentUpdatesReceived(updates); if ((profile && profile->peer() == peer) || (overview && overview->peer() == peer) || _stack.contains(peer) || history.peer() == peer) { showDialogs(); } dialogs.removePeer(peer); - App::histories().remove(peer->id); + App::history(peer->id)->clear(); MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer)); } @@ -776,26 +776,23 @@ void MainWidget::deletedContact(UserData *user, const MTPcontacts_Link &result) App::emitPeerUpdated(); } -void MainWidget::deleteHistoryAndContact(UserData *user, const MTPcontacts_Link &result) { - const MTPDcontacts_link &d(result.c_contacts_link()); - App::feedUsers(MTP_vector(1, d.vuser), false); - App::feedUserLink(MTP_int(user->id & 0xFFFFFFFF), d.vmy_link, d.vforeign_link, false); - App::emitPeerUpdated(); - - if ((profile && profile->peer() == user) || (overview && overview->peer() == user) || _stack.contains(user) || history.peer() == user) { - showDialogs(); - } - dialogs.removePeer(user); - MTP::send(MTPmessages_DeleteHistory(user->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, (PeerData*)user)); +void MainWidget::deleteConversation(PeerData *peer) { + dialogs.removePeer(peer); + History *h = App::history(peer->id); + h->clear(); + h->newLoaded = h->oldLoaded = true; + showDialogs(); + MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer)); } void MainWidget::clearHistory(PeerData *peer) { - if (!peer->chat && peer->asUser()->contact <= 0) { - dialogs.removePeer(peer->asUser()); + History *h = App::history(peer->id); + if (h->lastMsg) { +// Local::savePeerPosition(h->peer, h->lastMsg->date); } - dialogsToUp(); - dialogs.update(); - App::history(peer->id)->clear(); + h->clear(); + h->newLoaded = h->oldLoaded = true; + showPeerHistory(peer->id, ShowAtUnreadMsgId); MTP::send(MTPmessages_DeleteHistory(peer->input, MTP_int(0)), rpcDone(&MainWidget::deleteHistoryPart, peer)); } @@ -2530,6 +2527,16 @@ void MainWidget::onPeerShown(PeerData *peer) { if (animating()) _topBar.hide(); } +void MainWidget::searchInPeer(PeerData *peer) { + dialogs.searchInPeer(peer); + if (cWideMode()) { + dialogs.activate(); + } else { + dialogsToUp(); + showDialogs(); + } +} + void MainWidget::onUpdateNotifySettings() { if (this != App::main()) return; while (!updateNotifySettingPeers.isEmpty()) { diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index c0503be5e..9fec76a31 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -281,11 +281,11 @@ public: DragState getDragState(const QMimeData *mime); bool leaveChatFailed(PeerData *peer, const RPCError &e); - void deleteHistory(PeerData *peer, const MTPUpdates &updates); + void deleteHistoryAfterLeave(PeerData *peer, const MTPUpdates &updates); void deleteHistoryPart(PeerData *peer, const MTPmessages_AffectedHistory &result); void deleteMessages(const QVector &ids); void deletedContact(UserData *user, const MTPcontacts_Link &result); - void deleteHistoryAndContact(UserData *user, const MTPcontacts_Link &result); + void deleteConversation(PeerData *peer); void clearHistory(PeerData *peer); void removeContact(UserData *user); @@ -421,6 +421,8 @@ public slots: void onTopBarClick(); void onPeerShown(PeerData *peer); + void searchInPeer(PeerData *peer); + void onUpdateNotifySettings(); void onPhotosSelect(); diff --git a/Telegram/SourceFiles/profilewidget.cpp b/Telegram/SourceFiles/profilewidget.cpp index 08c460c4b..30743e737 100644 --- a/Telegram/SourceFiles/profilewidget.cpp +++ b/Telegram/SourceFiles/profilewidget.cpp @@ -55,7 +55,11 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // settings _enableNotifications(this, lang(lng_profile_enable_notifications)), + + // actions + _searchInPeer(this, lang(lng_profile_search_messages)), _clearHistory(this, lang(lng_profile_clear_history)), + _deleteConversation(this, lang(_peer->chat ? lng_profile_clear_and_exit : lng_profile_delete_conversation)), // shared media _allMediaTypes(false), @@ -96,7 +100,6 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // profile _nameText.setText(st::profileNameFont, _nameCache, _textNameOptions); - connect(&_uploadPhoto, SIGNAL(clicked()), this, SLOT(onUpdatePhoto())); connect(&_addParticipant, SIGNAL(clicked()), this, SLOT(onAddParticipant())); connect(&_sendMessage, SIGNAL(clicked()), this, SLOT(onSendMessage())); @@ -149,7 +152,11 @@ ProfileInner::ProfileInner(ProfileWidget *profile, ScrollArea *scroll, const Pee // settings connect(&_enableNotifications, SIGNAL(clicked()), this, SLOT(onEnableNotifications())); + + // actions + connect(&_searchInPeer, SIGNAL(clicked()), this, SLOT(onSearchInPeer())); connect(&_clearHistory, SIGNAL(clicked()), this, SLOT(onClearHistory())); + connect(&_deleteConversation, SIGNAL(clicked()), this, SLOT(onDeleteConversation())); // shared media connect(&_mediaShowAll, SIGNAL(clicked()), this, SLOT(onMediaShowAll())); @@ -181,6 +188,10 @@ void ProfileInner::onSendMessage() { App::main()->showPeerHistory(_peer->id, ShowAtUnreadMsgId); } +void ProfileInner::onSearchInPeer() { + App::main()->searchInPeer(_peer); +} + void ProfileInner::onEnableNotifications() { App::main()->updateNotifySetting(_peer, _enableNotifications.checked()); } @@ -244,17 +255,32 @@ void ProfileInner::onUpdatePhoto() { } void ProfileInner::onClearHistory() { - ConfirmBox *box = new ConfirmBox(lng_sure_delete_history(lt_contact, _peer->name)); + ConfirmBox *box = new ConfirmBox(_peer->chat ? lng_sure_delete_group_history(lt_group, _peer->name) : lng_sure_delete_history(lt_contact, _peer->name)); connect(box, SIGNAL(confirmed()), this, SLOT(onClearHistorySure())); App::wnd()->showLayer(box); } void ProfileInner::onClearHistorySure() { - App::main()->showDialogs(); App::wnd()->hideLayer(); App::main()->clearHistory(_peer); } +void ProfileInner::onDeleteConversation() { + ConfirmBox *box = new ConfirmBox(_peer->chat ? lng_sure_delete_and_exit(lt_group, _peer->name) : lng_sure_delete_history(lt_contact, _peer->name)); + connect(box, SIGNAL(confirmed()), this, SLOT(onDeleteConversationSure())); + App::wnd()->showLayer(box); +} + +void ProfileInner::onDeleteConversationSure() { + if (_peer->chat) { + App::wnd()->hideLayer(); + App::main()->showDialogs(); + MTP::send(MTPmessages_DeleteChatUser(MTP_int(_peer->id & 0xFFFFFFFF), App::self()->inputUser), App::main()->rpcDone(&MainWidget::deleteHistoryAfterLeave, _peer), App::main()->rpcFail(&MainWidget::leaveChatFailed, _peer)); + } else { + App::main()->deleteConversation(_peer); + } +} + void ProfileInner::onAddParticipant() { App::wnd()->showLayer(new ContactsBox(_peerChat)); } @@ -569,6 +595,14 @@ void ProfileInner::paintEvent(QPaintEvent *e) { top += _enableNotifications.height(); + // actions + p.setFont(st::profileHeaderFont->f); + p.setPen(st::profileHeaderColor->p); + p.drawText(_left + st::profileHeaderLeft, top + st::profileHeaderTop + st::profileHeaderFont->ascent, lang(lng_profile_actions_section)); + top += st::profileHeaderSkip; + + top += _searchInPeer.height() + st::setLittleSkip + _clearHistory.height() + st::setLittleSkip + _deleteConversation.height(); + // shared media p.setFont(st::profileHeaderFont->f); p.setPen(st::profileHeaderColor->p); @@ -855,6 +889,12 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { top += st::profileHeaderSkip; _enableNotifications.move(_left, top); top += _enableNotifications.height(); + // actions + top += st::profileHeaderSkip; + _searchInPeer.move(_left, top); top += _searchInPeer.height() + st::setLittleSkip; + _clearHistory.move(_left, top); top += _clearHistory.height() + st::setLittleSkip; + _deleteConversation.move(_left, top); top += _deleteConversation.height(); + // shared media top += st::profileHeaderSkip; @@ -883,7 +923,6 @@ void ProfileInner::resizeEvent(QResizeEvent *e) { } } top += st::profileHeaderTop + st::profileHeaderFont->ascent - st::linkFont->ascent; - _clearHistory.move(_left, top); } void ProfileInner::contextMenuEvent(QContextMenuEvent *e) { @@ -970,6 +1009,9 @@ void ProfileInner::mediaOverviewUpdated(PeerData *peer, MediaOverviewType type) } void ProfileInner::showAll() { + _searchInPeer.show(); + _clearHistory.show(); + _deleteConversation.show(); if (_peerChat) { _sendMessage.hide(); _shareContact.hide(); @@ -1006,7 +1048,6 @@ void ProfileInner::showAll() { } } _enableNotifications.show(); - _clearHistory.hide(); } else { _uploadPhoto.hide(); _cancelPhoto.hide(); @@ -1070,7 +1111,13 @@ void ProfileInner::showAll() { reorderParticipants(); int32 h; if (_peerUser) { - h = _clearHistory.y() + _clearHistory.height() + st::profileHeaderSkip; + h = _mediaShowAll.y() + _mediaShowAll.height() + st::profileHeaderSkip; + if (_mediaShowAll.isHidden()) { + for (int i = 0; i < OverviewCount; ++i) { + if (i == OverviewAudioDocuments) continue; + if (!_mediaLinks[i]->isHidden()) h += _mediaLinks[i]->height() + st::setLittleSkip; + } + } } else { h = _mediaAudios.y() + _mediaAudios.height() + st::profileHeaderSkip; if (!_participants.isEmpty()) { diff --git a/Telegram/SourceFiles/profilewidget.h b/Telegram/SourceFiles/profilewidget.h index 7acc3dfe3..94765769d 100644 --- a/Telegram/SourceFiles/profilewidget.h +++ b/Telegram/SourceFiles/profilewidget.h @@ -68,10 +68,13 @@ public slots: void onShareContact(); void onInviteToGroup(); void onSendMessage(); + void onSearchInPeer(); void onEnableNotifications(); void onClearHistory(); void onClearHistorySure(); + void onDeleteConversation(); + void onDeleteConversationSure(); void onAddParticipant(); void onUpdatePhoto(); @@ -142,7 +145,9 @@ private: // settings FlatCheckbox _enableNotifications; - LinkButton _clearHistory; + + // actions + LinkButton _searchInPeer, _clearHistory, _deleteConversation; // shared media bool _allMediaTypes;