diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 1d70d961f..59bd910cf 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1192,10 +1192,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_channel_mute" = "Mute"; "lng_channel_unmute" = "Unmute"; "lng_saved_messages" = "Saved Messages"; -"lng_archived_chats" = "Archived chats"; "lng_saved_short" = "Save"; "lng_saved_forward_here" = "Forward messages here for quick access"; +"lng_archived_chats" = "Archived chats"; +"lng_archived_add" = "Archive"; +"lng_archived_remove" = "Unarchive"; +"lng_chat_archived" = "Chat archived.\nMuted chats will stay archived after new messages arrive."; +"lng_chat_unarchived" = "Chat restored from your archive."; + "lng_dialogs_text_with_from" = "{from_part} {message}"; "lng_dialogs_text_from_wrapped" = "{from}:"; "lng_dialogs_text_media" = "{media_part} {caption}"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index fdca1a629..c06f3cebd 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -460,29 +460,27 @@ void ApiWrap::toggleHistoryArchived( if (const auto already = _historyArchivedRequests.take(history)) { request(already->first).cancel(); } - // #TODO archive - const auto folderId = Data::Folder::kId; - //const auto flags = group - // ? MTPchannels_ChangeFeedBroadcast::Flag::f_feed_id - // : MTPchannels_ChangeFeedBroadcast::Flag(0); - //const auto requestId = request(MTPchannels_ChangeFeedBroadcast( - // MTP_flags(flags), - // channel->inputChannel, - // MTP_int(feedId) - //)).done([=](const MTPUpdates &result) { - // applyUpdates(result); - // if (group) { - // channel->setFeed(_session->data().feed(feedId)); - // } else { - // channel->clearFeed(); - // } - // if (const auto data = _channelGroupingRequests.take(channel)) { - // data->second(); - // } - //}).fail([=](const RPCError &error) { - // _channelGroupingRequests.remove(channel); - //}).send(); - //_channelGroupingRequests.emplace(channel, requestId, callback); + const auto archiveId = Data::Folder::kId; + const auto requestId = request(MTPfolders_EditPeerFolders( + MTP_vector( + 1, + MTP_inputFolderPeer( + history->peer->input, + MTP_int(archived ? archiveId : 0))) + )).done([=](const MTPUpdates &result) { + applyUpdates(result); + if (archived) { + history->setFolder(_session->data().folder(archiveId)); + } else { + history->clearFolder(); + } + if (const auto data = _historyArchivedRequests.take(history)) { + data->second(); + } + }).fail([=](const RPCError &error) { + _historyArchivedRequests.remove(history); + }).send(); + _historyArchivedRequests.emplace(history, requestId, callback); } // #feed //void ApiWrap::ungroupAllFromFeed(not_null feed) { @@ -678,7 +676,7 @@ QString ApiWrap::exportDirectMessageLink(not_null item) { } void ApiWrap::requestContacts() { - if (_session->data().contactsLoaded().value() || _contactsRequestId) { + if (_session->data().contactsLoaded().current() || _contactsRequestId) { return; } _contactsRequestId = request(MTPcontacts_GetContacts( @@ -700,7 +698,7 @@ void ApiWrap::requestContacts() { UserData::ContactStatus::Contact); } } - _session->data().contactsLoaded().set(true); + _session->data().contactsLoaded() = true; }).fail([=](const RPCError &error) { _contactsRequestId = 0; }).send(); @@ -745,10 +743,10 @@ void ApiWrap::requestMoreDialogs(FolderId folderId) { : MTP_inputPeerEmpty()), MTP_int(loadCount), MTP_int(hash) - )).done([=](const MTPmessages_Dialogs &result) { + )).done([=](const MTPmessages_Dialogs & result) { result.match([](const MTPDmessages_dialogsNotModified & data) { LOG(("API Error: not-modified received for requested dialogs.")); - }, [&](const auto &data) { + }, [&](const auto & data) { if constexpr (data.Is()) { dialogsLoadFinish(folderId); } else { @@ -767,17 +765,12 @@ void ApiWrap::requestMoreDialogs(FolderId folderId) { if (!folderId) { requestDialogs(); + requestContacts(); if (!_dialogsLoadState || !_dialogsLoadState->requestId) { refreshDialogsLoadBlocked(); } } - _session->data().moreChatsLoaded().notify(); - if (!folderId) { - if (!_dialogsLoadState && _pinnedDialogsReceived) { - _session->data().allChatsLoaded().set(true); - } - requestContacts(); - } + _session->data().chatsListChanged(folderId); }).fail([=](const RPCError &error) { dialogsLoadState(folderId)->requestId = 0; }).send(); @@ -852,11 +845,19 @@ auto ApiWrap::dialogsLoadState(FolderId folderId) -> DialogsLoadState* { } void ApiWrap::dialogsLoadFinish(FolderId folderId) { + const auto notify = [&] { + Core::App().postponeCall(crl::guard(_session, [=] { + _session->data().chatsListDone(folderId); + })); + }; if (folderId) { - _session->data().folder(folderId)->setChatsListLoaded(true); _foldersLoadState.remove(folderId); + notify(); } else { _dialogsLoadState = nullptr; + if (_pinnedDialogsReceived) { + notify(); + } } } @@ -865,7 +866,6 @@ void ApiWrap::requestPinnedDialogs() { return; } - _pinnedDialogsReceived = false; const auto folderId = FolderId(0); _pinnedDialogsRequestId = request(MTPmessages_GetPinnedDialogs( MTP_int(folderId) @@ -884,9 +884,9 @@ void ApiWrap::requestPinnedDialogs() { _pinnedDialogsRequestId = 0; _pinnedDialogsReceived = true; - _session->data().moreChatsLoaded().notify(); + _session->data().chatsListChanged(folderId); if (!_dialogsLoadState) { - _session->data().allChatsLoaded().set(true); + _session->data().chatsListDone(folderId); } }); }).fail([=](const RPCError &error) { diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp index e7dd60c69..3535f5e37 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp @@ -225,18 +225,26 @@ void ChatsListBoxController::prepare() { prepareViewHook(); - rebuildRows(); + if (!Auth().data().chatsListLoaded()) { + Auth().data().chatsListLoadedEvents( + ) | rpl::filter([=](Data::Folder *folder) { + return !folder; + }) | rpl::start_with_next([=] { + checkForEmptyRows(); + }, lifetime()); + } - auto &sessionData = Auth().data(); - subscribe(sessionData.contactsLoaded(), [this](bool loaded) { + Auth().data().chatsListChanges( + ) | rpl::filter([=](Data::Folder *folder) { + return !folder; + }) | rpl::start_with_next([=] { rebuildRows(); - }); - subscribe(sessionData.moreChatsLoaded(), [this] { + }, lifetime()); + + Auth().data().contactsLoaded().value( + ) | rpl::start_with_next([=] { rebuildRows(); - }); - subscribe(sessionData.allChatsLoaded(), [this](bool loaded) { - checkForEmptyRows(); - }); + }, lifetime()); } void ChatsListBoxController::rebuildRows() { @@ -280,8 +288,8 @@ void ChatsListBoxController::checkForEmptyRows() { if (delegate()->peerListFullRowsCount()) { setDescriptionText(QString()); } else { - auto &sessionData = Auth().data(); - auto loaded = sessionData.contactsLoaded().value() && sessionData.allChatsLoaded().value(); + const auto loaded = Auth().data().contactsLoaded().current() + && Auth().data().chatsListLoaded(); setDescriptionText(loaded ? emptyBoxText() : lang(lng_contacts_loading)); } } @@ -318,12 +326,10 @@ void ContactsBoxController::prepare() { prepareViewHook(); - rebuildRows(); - - auto &sessionData = Auth().data(); - subscribe(sessionData.contactsLoaded(), [this](bool loaded) { + Auth().data().contactsLoaded().value( + ) | rpl::start_with_next([=] { rebuildRows(); - }); + }, lifetime()); } void ContactsBoxController::rebuildRows() { @@ -349,8 +355,7 @@ void ContactsBoxController::checkForEmptyRows() { if (delegate()->peerListFullRowsCount()) { setDescriptionText(QString()); } else { - auto &sessionData = Auth().data(); - auto loaded = sessionData.contactsLoaded().value(); + const auto loaded = Auth().data().contactsLoaded().current(); setDescriptionText(lang(loaded ? lng_contacts_not_found : lng_contacts_loading)); } } @@ -473,13 +478,13 @@ bool AddBotToGroupBoxController::sharingBotGame() const { } QString AddBotToGroupBoxController::emptyBoxText() const { - return lang(Auth().data().allChatsLoaded().value() + return lang(Auth().data().chatsListLoaded() ? (sharingBotGame() ? lng_bot_no_chats : lng_bot_no_groups) : lng_contacts_loading); } QString AddBotToGroupBoxController::noResultsText() const { - return lang(Auth().data().allChatsLoaded().value() + return lang(Auth().data().chatsListLoaded() ? (sharingBotGame() ? lng_bot_chats_not_found : lng_bot_groups_not_found) : lng_contacts_loading); } @@ -493,7 +498,12 @@ void AddBotToGroupBoxController::prepareViewHook() { ? lng_bot_choose_chat : lng_bot_choose_group)); updateLabels(); - subscribe(Auth().data().allChatsLoaded(), [this](bool) { updateLabels(); }); + Auth().data().chatsListLoadedEvents( + ) | rpl::filter([=](Data::Folder *folder) { + return !folder; + }) | rpl::start_with_next([=] { + updateLabels(); + }, lifetime()); } ChooseRecipientBoxController::ChooseRecipientBoxController( diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.h b/Telegram/SourceFiles/boxes/peer_list_controllers.h index 974a35602..6ed67b08f 100644 --- a/Telegram/SourceFiles/boxes/peer_list_controllers.h +++ b/Telegram/SourceFiles/boxes/peer_list_controllers.h @@ -76,9 +76,7 @@ private: }; -class ChatsListBoxController - : public PeerListController - , protected base::Subscriber { +class ChatsListBoxController : public PeerListController { public: ChatsListBoxController( std::unique_ptr searchController @@ -113,9 +111,7 @@ private: }; -class ContactsBoxController - : public PeerListController - , protected base::Subscriber { +class ContactsBoxController : public PeerListController { public: ContactsBoxController( std::unique_ptr searchController diff --git a/Telegram/SourceFiles/core/changelogs.cpp b/Telegram/SourceFiles/core/changelogs.cpp index e1e8d5c21..467dcb5dc 100644 --- a/Telegram/SourceFiles/core/changelogs.cpp +++ b/Telegram/SourceFiles/core/changelogs.cpp @@ -103,9 +103,12 @@ QString FormatVersionPrecise(int version) { Changelogs::Changelogs(not_null session, int oldVersion) : _session(session) , _oldVersion(oldVersion) { - _chatsSubscription = subscribe( - _session->data().moreChatsLoaded(), - [=] { requestCloudLogs(); }); + _session->data().chatsListChanges( + ) | rpl::filter([](Data::Folder *folder) { + return !folder; + }) | rpl::start_with_next([=] { + requestCloudLogs(); + }, _chatsSubscription); } std::unique_ptr Changelogs::Create( @@ -117,7 +120,7 @@ std::unique_ptr Changelogs::Create( } void Changelogs::requestCloudLogs() { - unsubscribe(base::take(_chatsSubscription)); + _chatsSubscription.destroy(); const auto callback = [this](const MTPUpdates &result) { _session->api().applyUpdates(result); diff --git a/Telegram/SourceFiles/core/changelogs.h b/Telegram/SourceFiles/core/changelogs.h index 36002f23e..3e8007cef 100644 --- a/Telegram/SourceFiles/core/changelogs.h +++ b/Telegram/SourceFiles/core/changelogs.h @@ -29,7 +29,7 @@ private: const not_null _session; const int _oldVersion = 0; - int _chatsSubscription = 0; + rpl::lifetime _chatsSubscription; bool _addedSomeLocal = false; }; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 656cc00de..42910c52b 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -774,6 +774,28 @@ bool Session::sendActionsAnimationCallback(crl::time now) { return !_sendActions.empty(); } +bool Session::chatsListLoaded(Data::Folder *folder) { + return folder ? folder->chatsListLoaded() : _chatsListLoaded; +} + +void Session::chatsListChanged(FolderId folderId) { + chatsListChanged(folderId ? folder(folderId).get() : nullptr); +} + +void Session::chatsListChanged(Data::Folder *folder) { + _chatsListChanged.fire_copy(folder); +} + +void Session::chatsListDone(FolderId folderId) { + const auto folder = folderId ? this->folder(folderId).get() : nullptr; + if (folder) { + folder->setChatsListLoaded(true); + } else { + _chatsListLoaded = true; + } + _chatsListLoadedEvents.fire_copy(folder); +} + Storage::Cache::Database &Session::cache() { return *_cache; } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index fd3235030..3fc480cd9 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -135,15 +135,19 @@ public: const MTPSendMessageAction &action, TimeId when); - [[nodiscard]] base::Variable &contactsLoaded() { + [[nodiscard]] rpl::variable &contactsLoaded() { return _contactsLoaded; } - [[nodiscard]] base::Variable &allChatsLoaded() { - return _allChatsLoaded; + [[nodiscard]] rpl::producer chatsListChanges() const { + return _chatsListChanged.events(); } - [[nodiscard]] base::Observable &moreChatsLoaded() { - return _moreChatsLoaded; + [[nodiscard]] bool chatsListLoaded(Data::Folder *folder = nullptr); + [[nodiscard]] rpl::producer chatsListLoadedEvents() const { + return _chatsListLoadedEvents.events(); } + void chatsListChanged(FolderId folderId); + void chatsListChanged(Data::Folder *folder); + void chatsListDone(FolderId folderId); struct ItemVisibilityQuery { not_null item; @@ -725,9 +729,10 @@ private: TimeId _exportAvailableAt = 0; QPointer _exportSuggestion; - base::Variable _contactsLoaded = { false }; - base::Variable _allChatsLoaded = { false }; - base::Observable _moreChatsLoaded; + rpl::variable _contactsLoaded = false; + bool _chatsListLoaded = false; + rpl::event_stream _chatsListLoadedEvents; + rpl::event_stream _chatsListChanged; base::Observable _queryItemVisibility; rpl::event_stream _itemIdChanges; rpl::event_stream> _itemLayoutChanges; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 81d4583f5..9776b3c68 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -89,8 +89,12 @@ DialogsInner::DialogsInner(QWidget *parent, not_null contro _cancelSearchFromUser->setClickedCallback([this] { searchFromUserChanged.notify(nullptr); }); _cancelSearchFromUser->hide(); - subscribe(session().downloaderTaskFinished(), [this] { update(); }); - subscribe(session().data().contactsLoaded(), [this](bool) { refresh(); }); + subscribe(session().downloaderTaskFinished(), [=] { update(); }); + + session().data().contactsLoaded().changes( + ) | rpl::start_with_next([=] { + refresh(); + }, lifetime()); session().data().itemRemoved( ) | rpl::start_with_next([=](not_null item) { @@ -362,7 +366,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) { p.fillRect(dialogsClip, st::dialogsBg); p.setFont(st::noContactsFont); p.setPen(st::noContactsColor); - p.drawText(QRect(0, 0, fullWidth, st::noContactsHeight - (session().data().contactsLoaded().value() ? st::noContactsFont->height : 0)), lang(session().data().contactsLoaded().value() ? lng_no_chats : lng_contacts_loading), style::al_center); + p.drawText(QRect(0, 0, fullWidth, st::noContactsHeight - (session().data().contactsLoaded().current() ? st::noContactsFont->height : 0)), lang(session().data().contactsLoaded().current() ? lng_no_chats : lng_contacts_loading), style::al_center); } } else if (_state == State::Filtered) { if (!_hashtagResults.empty()) { @@ -1953,12 +1957,16 @@ void DialogsInner::notify_historyMuteUpdated(History *history) { refreshDialog(history); } +Data::Folder *DialogsInner::shownFolder() const { + return _openedFolder; +} + void DialogsInner::refresh(bool toTop) { int32 h = 0; if (_state == State::Default) { if (shownDialogs()->empty()) { h = st::noContactsHeight; - if (session().data().contactsLoaded().value()) { + if (session().data().contactsLoaded().current()) { if (_addContactLnk->isHidden()) _addContactLnk->show(); } else { if (!_addContactLnk->isHidden()) _addContactLnk->hide(); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 03ca7e507..e2e9ba385 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -68,6 +68,7 @@ public: void scrollToEntry(const Dialogs::RowDescriptor &entry); + Data::Folder *shownFolder() const; int32 lastSearchDate() const; PeerData *lastSearchPeer() const; MsgId lastSearchId() const; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 6bc36252b..6b424c35a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -183,10 +183,13 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont }); connect(_scroll, SIGNAL(geometryChanged()), _inner, SLOT(onParentGeometryChanged())); connect(_scroll, SIGNAL(scrolled()), this, SLOT(onListScroll())); - subscribe(session().data().moreChatsLoaded(), [=] { + session().data().chatsListChanges( + ) | rpl::filter([=](Data::Folder *folder) { + return (folder == _inner->shownFolder()); + }) | rpl::start_with_next([=] { _inner->refresh(); onListScroll(); - }); + }, lifetime()); connect(_filter, &Ui::FlatInput::cancelled, [=] { onCancel(); }); diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 4bf29ec37..752adc464 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -1829,12 +1829,12 @@ void History::setFolderPointer(Data::Folder *folder) { } using Mode = Dialogs::Mode; const auto wasAll = inChatList(Mode::All); - const auto wasImportant = inChatList(Mode::Important); + const auto wasImportant = wasAll && inChatList(Mode::Important); if (wasAll) { removeFromChatList(Mode::All); - } - if (wasImportant) { - removeFromChatList(Mode::Important); + if (wasImportant) { + removeFromChatList(Mode::Important); + } } const auto was = std::exchange(_folder, folder); if (was) { @@ -1842,9 +1842,11 @@ void History::setFolderPointer(Data::Folder *folder) { } if (wasAll) { addToChatList(Mode::All); - } - if (wasImportant) { - addToChatList(Mode::Important); + if (wasImportant) { + addToChatList(Mode::Important); + } + owner().chatsListChanged(was); + owner().chatsListChanged(_folder); } if (_folder) { _folder->registerOne(this); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 3a09164c8..1b4f04016 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -361,48 +361,55 @@ HistoryWidget::HistoryWidget( confirmSendingFiles(data, CompressConfirm::No); ActivateWindow(this->controller()); }); - _attachDragPhoto->setDroppedCallback([this](const QMimeData *data) { + _attachDragPhoto->setDroppedCallback([=](const QMimeData *data) { confirmSendingFiles(data, CompressConfirm::Yes); ActivateWindow(this->controller()); }); - subscribe(Adaptive::Changed(), [this] { update(); }); + subscribe(Adaptive::Changed(), [=] { update(); }); Auth().data().itemRemoved( - ) | rpl::start_with_next( - [this](auto item) { itemRemoved(item); }, - lifetime()); + ) | rpl::start_with_next([=](not_null item) { + itemRemoved(item); + }, lifetime()); + Auth().data().historyChanged( - ) | rpl::start_with_next( - [=](auto history) { handleHistoryChange(history); }, - lifetime()); + ) | rpl::start_with_next([=](not_null history) { + handleHistoryChange(history); + }, lifetime()); + Auth().data().viewResizeRequest( - ) | rpl::start_with_next([this](auto view) { + ) | rpl::start_with_next([=](not_null view) { if (view->data()->mainView() == view) { updateHistoryGeometry(); } }, lifetime()); + Auth().data().itemViewRefreshRequest( - ) | rpl::start_with_next([this](auto item) { + ) | rpl::start_with_next([=](not_null item) { // While HistoryInner doesn't own item views we must refresh them // even if the list is not yet created / was destroyed. if (!_list) { item->refreshMainView(); } }, lifetime()); + Auth().data().animationPlayInlineRequest( - ) | rpl::start_with_next([=](auto item) { + ) | rpl::start_with_next([=](not_null item) { if (const auto view = item->mainView()) { if (const auto media = view->media()) { media->playAnimation(); } } }, lifetime()); - subscribe(Auth().data().contactsLoaded(), [this](bool) { + + Auth().data().contactsLoaded().changes( + ) | rpl::start_with_next([=] { if (_peer) { updateReportSpamStatus(); updateControlsVisibility(); } - }); + }, lifetime()); + subscribe(Media::Player::instance()->switchToNextNotifier(), [this](const Media::Player::Instance::Switch &pair) { if (pair.from.type() == AudioMsgId::Type::Voice) { scrollToCurrentVoiceMessage(pair.from.contextId(), pair.to); @@ -1863,7 +1870,7 @@ void HistoryWidget::updateReportSpamStatus() { } } auto status = dbiprsRequesting; - if (!Auth().data().contactsLoaded().value() || _firstLoadRequest) { + if (!Auth().data().contactsLoaded().current() || _firstLoadRequest) { status = dbiprsUnknown; } else if (_peer->isUser() && _peer->asUser()->contactStatus() == UserData::ContactStatus::Contact) { diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index a5cd2d118..922270e2d 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -39,7 +39,9 @@ namespace { constexpr auto kBlockedPerPage = 40; -class BlockUserBoxController : public ChatsListBoxController { +class BlockUserBoxController + : public ChatsListBoxController + , private base::Subscriber { public: void rowClicked(not_null row) override; diff --git a/Telegram/SourceFiles/window/main_window.cpp b/Telegram/SourceFiles/window/main_window.cpp index 8234dbaa2..9d9a4f9a9 100644 --- a/Telegram/SourceFiles/window/main_window.cpp +++ b/Telegram/SourceFiles/window/main_window.cpp @@ -620,6 +620,9 @@ void MainWindow::setInactivePress(bool inactive) { } } -MainWindow::~MainWindow() = default; +MainWindow::~MainWindow() { + // We want to delete all widgets before the _controller. + _body.destroy(); +} } // namespace Window diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index 7b9dda6f3..00810d119 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -20,7 +20,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwidget.h" #include "mainwindow.h" #include "observer_peer.h" -#include "styles/style_boxes.h" #include "history/history.h" #include "window/window_controller.h" #include "support/support_helper.h" @@ -37,6 +36,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "dialogs/dialogs_key.h" #include "boxes/peers/edit_peer_info_box.h" +#include "styles/style_boxes.h" +#include "styles/style_window.h" // st::windowMinWidth namespace Window { namespace { @@ -56,6 +57,7 @@ private: void addInfo(); void addSearch(); void addToggleUnreadMark(); + void addToggleArchive(); void addUserActions(not_null user); void addBlockUser(not_null user); void addChatActions(not_null chat); @@ -94,7 +96,7 @@ private: History *FindWastedPin() { const auto &order = Auth().data().pinnedDialogsOrder(); - for (const auto pinned : order) { + for (const auto &pinned : order) { if (const auto history = pinned.history()) { if (history->peer->isChat() && history->peer->asChat()->isDeactivated() @@ -271,6 +273,22 @@ void Filler::addToggleUnreadMark() { }, *lifetime); } +void Filler::addToggleArchive() { + const auto peer = _peer; + const auto archived = [&] { + const auto history = peer->owner().historyLoaded(peer); + return history && history->folder(); + }(); + const auto toggle = [=] { + ToggleHistoryArchived( + peer->owner().history(peer), + !archived); + }; + _addAction( + lang(archived ? lng_archived_remove : lng_archived_add), + toggle); +} + void Filler::addBlockUser(not_null user) { auto blockText = [](not_null user) { return lang(user->isBlocked() @@ -477,6 +495,9 @@ void Filler::fill() { } else if (const auto channel = _peer->asChannel()) { addChannelActions(channel); } + if (_source == PeerMenuSource::ChatsList) { + addToggleArchive(); + } } FolderFiller::FolderFiller( @@ -767,24 +788,17 @@ void PeerMenuAddMuteAction( // [=] { Ui::hideLayer(); Auth().api().ungroupAllFromFeed(feed); })); //} // -//void ToggleChannelGrouping(not_null channel, bool group) { -// const auto callback = [=] { -// Ui::Toast::Show(lang(group -// ? lng_feed_channel_added -// : lng_feed_channel_removed)); -// }; -// if (group) { -// const auto feed = Auth().data().feed(Data::Feed::kId); -// if (feed->channels().size() < 2) { -// Info::FeedProfile::EditController::Start(feed, channel); -// return; -// } -// } -// Auth().api().toggleChannelGrouping( -// channel, -// group, -// callback); -//} +void ToggleHistoryArchived(not_null history, bool archived) { + const auto callback = [=] { + Ui::Toast::Show(lang(archived + ? lng_chat_archived + : lng_chat_unarchived)); + }; + history->session().api().toggleHistoryArchived( + history, + archived, + callback); +} Fn ClearHistoryHandler(not_null peer) { return [=] { diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h index 707980b2d..dedfdb155 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.h +++ b/Telegram/SourceFiles/window/window_peer_menu.h @@ -52,7 +52,7 @@ void PeerMenuAddChannelMembers(not_null channel); //void PeerMenuUngroupFeed(not_null feed); // #feed void PeerMenuCreatePoll(not_null peer); -//void ToggleChannelGrouping(not_null channel, bool group); // #feed +void ToggleHistoryArchived(not_null history, bool archived); Fn ClearHistoryHandler(not_null peer); Fn DeleteAndLeaveHandler(not_null peer);