mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Count unread correctly in folders.
This commit is contained in:
parent
58519300ea
commit
8fd811517b
23 changed files with 673 additions and 798 deletions
|
@ -433,8 +433,8 @@ void ApiWrap::applyUpdates(
|
|||
App::main()->feedUpdates(updates, sentMessageRandomId);
|
||||
}
|
||||
|
||||
void ApiWrap::savePinnedOrder(FolderId folderId) {
|
||||
const auto &order = _session->data().pinnedChatsOrder(folderId);
|
||||
void ApiWrap::savePinnedOrder(Data::Folder *folder) {
|
||||
const auto &order = _session->data().pinnedChatsOrder(folder);
|
||||
const auto input = [](const Dialogs::Key &key) {
|
||||
if (const auto history = key.history()) {
|
||||
return MTP_inputDialogPeer(history->peer->input);
|
||||
|
@ -451,7 +451,7 @@ void ApiWrap::savePinnedOrder(FolderId folderId) {
|
|||
input);
|
||||
request(MTPmessages_ReorderPinnedDialogs(
|
||||
MTP_flags(MTPmessages_ReorderPinnedDialogs::Flag::f_force),
|
||||
MTP_int(folderId),
|
||||
MTP_int(folder ? folder->id() : 0),
|
||||
MTP_vector(peers)
|
||||
)).send();
|
||||
}
|
||||
|
@ -707,17 +707,17 @@ void ApiWrap::requestContacts() {
|
|||
}).send();
|
||||
}
|
||||
|
||||
void ApiWrap::requestDialogs(FolderId folderId) {
|
||||
if (folderId && !_foldersLoadState.contains(folderId)) {
|
||||
_foldersLoadState.emplace(folderId, DialogsLoadState());
|
||||
void ApiWrap::requestDialogs(Data::Folder *folder) {
|
||||
if (folder && !_foldersLoadState.contains(folder)) {
|
||||
_foldersLoadState.emplace(folder, DialogsLoadState());
|
||||
}
|
||||
requestMoreDialogs(folderId);
|
||||
requestMoreDialogs(folder);
|
||||
}
|
||||
|
||||
void ApiWrap::requestMoreDialogs(FolderId folderId) {
|
||||
const auto state = dialogsLoadState(folderId);
|
||||
void ApiWrap::requestMoreDialogs(Data::Folder *folder) {
|
||||
const auto state = dialogsLoadState(folder);
|
||||
if (!state) {
|
||||
if (!folderId) {
|
||||
if (!folder) {
|
||||
_session->data().addAllSavedPeers();
|
||||
}
|
||||
return;
|
||||
|
@ -734,7 +734,7 @@ void ApiWrap::requestMoreDialogs(FolderId folderId) {
|
|||
const auto hash = 0;
|
||||
state->requestId = request(MTPmessages_GetDialogs(
|
||||
MTP_flags(flags),
|
||||
MTP_int(folderId),
|
||||
MTP_int(folder ? folder->id() : 0),
|
||||
MTP_int(state->offsetDate),
|
||||
MTP_int(state->offsetId),
|
||||
(state->offsetPeer
|
||||
|
@ -743,31 +743,31 @@ void ApiWrap::requestMoreDialogs(FolderId folderId) {
|
|||
MTP_int(loadCount),
|
||||
MTP_int(hash)
|
||||
)).done([=](const MTPmessages_Dialogs &result) {
|
||||
const auto state = dialogsLoadState(folderId);
|
||||
const auto state = dialogsLoadState(folder);
|
||||
result.match([](const MTPDmessages_dialogsNotModified & data) {
|
||||
LOG(("API Error: not-modified received for requested dialogs."));
|
||||
}, [&](const auto &data) {
|
||||
if constexpr (data.Is<MTPDmessages_dialogs>()) {
|
||||
if (state) {
|
||||
state->listReceived = true;
|
||||
dialogsLoadFinish(folderId); // may kill 'state'.
|
||||
dialogsLoadFinish(folder); // may kill 'state'.
|
||||
}
|
||||
} else {
|
||||
updateDialogsOffset(
|
||||
folderId,
|
||||
folder,
|
||||
data.vdialogs.v,
|
||||
data.vmessages.v);
|
||||
}
|
||||
_session->data().processUsers(data.vusers);
|
||||
_session->data().processChats(data.vchats);
|
||||
_session->data().applyDialogs(
|
||||
folderId,
|
||||
folder,
|
||||
data.vmessages.v,
|
||||
data.vdialogs.v);
|
||||
});
|
||||
|
||||
if (!folderId) {
|
||||
requestDialogs(folderId);
|
||||
if (!folder) {
|
||||
requestDialogs(folder);
|
||||
requestContacts();
|
||||
if (!_dialogsLoadState
|
||||
|| (!_dialogsLoadState->listReceived
|
||||
|
@ -775,15 +775,15 @@ void ApiWrap::requestMoreDialogs(FolderId folderId) {
|
|||
refreshDialogsLoadBlocked();
|
||||
}
|
||||
}
|
||||
_session->data().chatsListChanged(folderId);
|
||||
_session->data().chatsListChanged(folder);
|
||||
}).fail([=](const RPCError &error) {
|
||||
dialogsLoadState(folderId)->requestId = 0;
|
||||
dialogsLoadState(folder)->requestId = 0;
|
||||
}).send();
|
||||
|
||||
if (!state->pinnedReceived) {
|
||||
requestPinnedDialogs(folderId);
|
||||
requestPinnedDialogs(folder);
|
||||
}
|
||||
if (!folderId) {
|
||||
if (!folder) {
|
||||
refreshDialogsLoadBlocked();
|
||||
}
|
||||
}
|
||||
|
@ -801,7 +801,7 @@ void ApiWrap::refreshDialogsLoadBlocked() {
|
|||
}
|
||||
|
||||
void ApiWrap::updateDialogsOffset(
|
||||
FolderId folderId,
|
||||
Data::Folder *folder,
|
||||
const QVector<MTPDialog> &dialogs,
|
||||
const QVector<MTPMessage> &messages) {
|
||||
auto lastDate = TimeId(0);
|
||||
|
@ -834,7 +834,7 @@ void ApiWrap::updateDialogsOffset(
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (const auto state = dialogsLoadState(folderId)) {
|
||||
if (const auto state = dialogsLoadState(folder)) {
|
||||
if (lastDate) {
|
||||
state->offsetDate = lastDate;
|
||||
state->offsetId = lastMsgId;
|
||||
|
@ -842,31 +842,31 @@ void ApiWrap::updateDialogsOffset(
|
|||
state->requestId = 0;
|
||||
} else {
|
||||
state->listReceived = true;
|
||||
dialogsLoadFinish(folderId);
|
||||
dialogsLoadFinish(folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto ApiWrap::dialogsLoadState(FolderId folderId) -> DialogsLoadState* {
|
||||
if (!folderId) {
|
||||
auto ApiWrap::dialogsLoadState(Data::Folder *folder) -> DialogsLoadState* {
|
||||
if (!folder) {
|
||||
return _dialogsLoadState.get();
|
||||
}
|
||||
const auto i = _foldersLoadState.find(folderId);
|
||||
const auto i = _foldersLoadState.find(folder);
|
||||
return (i != end(_foldersLoadState)) ? &i->second : nullptr;
|
||||
}
|
||||
|
||||
void ApiWrap::dialogsLoadFinish(FolderId folderId) {
|
||||
void ApiWrap::dialogsLoadFinish(Data::Folder *folder) {
|
||||
const auto notify = [&] {
|
||||
Core::App().postponeCall(crl::guard(_session, [=] {
|
||||
_session->data().chatsListDone(folderId);
|
||||
_session->data().chatsListDone(folder);
|
||||
}));
|
||||
};
|
||||
const auto state = dialogsLoadState(folderId);
|
||||
const auto state = dialogsLoadState(folder);
|
||||
if (!state || !state->listReceived || !state->pinnedReceived) {
|
||||
return;
|
||||
}
|
||||
if (folderId) {
|
||||
_foldersLoadState.remove(folderId);
|
||||
if (folder) {
|
||||
_foldersLoadState.remove(folder);
|
||||
notify();
|
||||
} else {
|
||||
_dialogsLoadState = nullptr;
|
||||
|
@ -874,32 +874,32 @@ void ApiWrap::dialogsLoadFinish(FolderId folderId) {
|
|||
}
|
||||
}
|
||||
|
||||
void ApiWrap::requestPinnedDialogs(FolderId folderId) {
|
||||
const auto state = dialogsLoadState(folderId);
|
||||
void ApiWrap::requestPinnedDialogs(Data::Folder *folder) {
|
||||
const auto state = dialogsLoadState(folder);
|
||||
if (!state || state->pinnedReceived || state->pinnedRequestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto finalize = [=] {
|
||||
if (const auto state = dialogsLoadState(folderId)) {
|
||||
if (const auto state = dialogsLoadState(folder)) {
|
||||
state->pinnedRequestId = 0;
|
||||
state->pinnedReceived = true;
|
||||
dialogsLoadFinish(folderId);
|
||||
dialogsLoadFinish(folder);
|
||||
}
|
||||
};
|
||||
state->pinnedRequestId = request(MTPmessages_GetPinnedDialogs(
|
||||
MTP_int(folderId)
|
||||
MTP_int(folder ? folder->id() : 0)
|
||||
)).done([=](const MTPmessages_PeerDialogs &result) {
|
||||
finalize();
|
||||
result.match([&](const MTPDmessages_peerDialogs &data) {
|
||||
_session->data().processUsers(data.vusers);
|
||||
_session->data().processChats(data.vchats);
|
||||
_session->data().clearPinnedChats(folderId);
|
||||
_session->data().clearPinnedChats(folder);
|
||||
_session->data().applyDialogs(
|
||||
folderId,
|
||||
folder,
|
||||
data.vmessages.v,
|
||||
data.vdialogs.v);
|
||||
_session->data().chatsListChanged(folderId);
|
||||
_session->data().chatsListChanged(folder);
|
||||
});
|
||||
}).fail([=](const RPCError &error) {
|
||||
finalize();
|
||||
|
@ -1258,10 +1258,15 @@ void ApiWrap::gotChatFull(
|
|||
channel->setInviteLink((f.vexported_invite.type() == mtpc_chatInviteExported) ? qs(f.vexported_invite.c_chatInviteExported().vlink) : QString());
|
||||
if (const auto history = _session->data().historyLoaded(channel)) {
|
||||
history->clearUpTill(f.vavailable_min_id.v);
|
||||
history->applyDialogFields(
|
||||
f.vunread_count.v,
|
||||
f.vread_inbox_max_id.v,
|
||||
f.vread_outbox_max_id.v);
|
||||
if (history->folderKnown()) {
|
||||
history->applyDialogFields(
|
||||
history->folder(),
|
||||
f.vunread_count.v,
|
||||
f.vread_inbox_max_id.v,
|
||||
f.vread_outbox_max_id.v);
|
||||
} else {
|
||||
requestDialogEntry(history);
|
||||
}
|
||||
}
|
||||
if (f.has_pinned_msg_id()) {
|
||||
channel->setPinnedMessageId(f.vpinned_msg_id.v);
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
|
||||
|
||||
void savePinnedOrder(FolderId folderId);
|
||||
void savePinnedOrder(Data::Folder *folder);
|
||||
void toggleHistoryArchived(
|
||||
not_null<History*> history,
|
||||
bool archived,
|
||||
|
@ -79,8 +79,8 @@ public:
|
|||
QString exportDirectMessageLink(not_null<HistoryItem*> item);
|
||||
|
||||
void requestContacts();
|
||||
void requestDialogs(FolderId folderId);
|
||||
void requestPinnedDialogs(FolderId folderId);
|
||||
void requestDialogs(Data::Folder *folder = nullptr);
|
||||
void requestPinnedDialogs(Data::Folder *folder = nullptr);
|
||||
void requestMoreBlockedByDateDialogs();
|
||||
rpl::producer<bool> dialogsLoadMayBlockByDate() const;
|
||||
rpl::producer<bool> dialogsLoadBlockedByDate() const;
|
||||
|
@ -467,12 +467,12 @@ private:
|
|||
void setupSupportMode();
|
||||
void refreshDialogsLoadBlocked();
|
||||
void updateDialogsOffset(
|
||||
FolderId folderId,
|
||||
Data::Folder *folder,
|
||||
const QVector<MTPDialog> &dialogs,
|
||||
const QVector<MTPMessage> &messages);
|
||||
void requestMoreDialogs(FolderId folderId);
|
||||
DialogsLoadState *dialogsLoadState(FolderId folderId);
|
||||
void dialogsLoadFinish(FolderId folderId);
|
||||
void requestMoreDialogs(Data::Folder *folder);
|
||||
DialogsLoadState *dialogsLoadState(Data::Folder *folder);
|
||||
void dialogsLoadFinish(Data::Folder *folder);
|
||||
|
||||
void checkQuitPreventFinished();
|
||||
|
||||
|
@ -761,7 +761,9 @@ private:
|
|||
rpl::variable<bool> _dialogsLoadMayBlockByDate = false;
|
||||
rpl::variable<bool> _dialogsLoadBlockedByDate = false;
|
||||
|
||||
base::flat_map<FolderId, DialogsLoadState> _foldersLoadState;
|
||||
base::flat_map<
|
||||
not_null<Data::Folder*>,
|
||||
DialogsLoadState> _foldersLoadState;
|
||||
|
||||
rpl::event_stream<SendOptions> _sendActions;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwidget.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "history/history.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_profile.h"
|
||||
|
||||
|
@ -266,13 +266,13 @@ void ChatsListBoxController::rebuildRows() {
|
|||
++added;
|
||||
}
|
||||
}
|
||||
added += appendList(Auth().data().chatsList(Dialogs::Mode::All));
|
||||
added += appendList(Auth().data().chatsList()->indexed());
|
||||
added += appendList(Auth().data().contactsNoChatsList());
|
||||
if (!wasEmpty && added > 0) {
|
||||
// Place dialogs list before contactsNoDialogs list.
|
||||
delegate()->peerListPartitionRows([](const PeerListRow &a) {
|
||||
const auto history = static_cast<const Row&>(a).history();
|
||||
return history->inChatList(Dialogs::Mode::All);
|
||||
return history->inChatList();
|
||||
});
|
||||
if (respectSavedMessagesChat()) {
|
||||
delegate()->peerListPartitionRows([](const PeerListRow &a) {
|
||||
|
|
|
@ -1080,7 +1080,7 @@ void AddSpecialBoxSearchController::addChatsContacts() {
|
|||
return result;
|
||||
};
|
||||
const auto dialogsIndex = getSmallestIndex(
|
||||
_peer->owner().chatsList(Dialogs::Mode::All));
|
||||
_peer->owner().chatsList()->indexed());
|
||||
const auto contactsIndex = getSmallestIndex(
|
||||
_peer->owner().contactsNoChatsList());
|
||||
|
||||
|
|
|
@ -489,7 +489,7 @@ ShareBox::Inner::Inner(
|
|||
_rowHeight = st::shareRowHeight;
|
||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
|
||||
const auto dialogs = Auth().data().chatsList(Dialogs::Mode::All);
|
||||
const auto dialogs = Auth().data().chatsList()->indexed();
|
||||
const auto self = Auth().user();
|
||||
if (_filterCallback(self)) {
|
||||
_chatsIndexed->addToEnd(self->owner().history(self));
|
||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history_item.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "storage/storage_facade.h"
|
||||
#include "core/application.h"
|
||||
//#include "storage/storage_feed_messages.h" // #feed
|
||||
#include "auth_session.h"
|
||||
#include "apiwrap.h"
|
||||
|
@ -25,6 +26,16 @@ namespace {
|
|||
|
||||
constexpr auto kLoadedChatsMinCount = 20;
|
||||
|
||||
rpl::producer<int> PinnedDialogsInFolderMaxValue() {
|
||||
return rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
Core::App().configUpdates()
|
||||
) | rpl::map([=] {
|
||||
return Global::PinnedDialogsInFolderMax();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// #feed
|
||||
|
@ -40,9 +51,7 @@ constexpr auto kLoadedChatsMinCount = 20;
|
|||
Folder::Folder(not_null<Data::Session*> owner, FolderId id)
|
||||
: Entry(owner, this)
|
||||
, _id(id)
|
||||
, _chatsList(Dialogs::SortMode::Date)
|
||||
, _importantChatsList(Dialogs::SortMode::Date)
|
||||
, _pinnedChatsList(Global::PinnedDialogsInFolderMax())
|
||||
, _chatsList(PinnedDialogsInFolderMaxValue())
|
||||
, _name(lang(lng_archived_chats)) {
|
||||
indexNameParts();
|
||||
}
|
||||
|
@ -78,51 +87,19 @@ void Folder::indexNameParts() {
|
|||
}
|
||||
|
||||
void Folder::registerOne(not_null<History*> history) {
|
||||
//session().storage().invalidate( // #feed
|
||||
// Storage::FeedMessagesInvalidate(_id));
|
||||
|
||||
if (unreadCountKnown()) {
|
||||
if (history->unreadCountKnown()) {
|
||||
// If history unreadCount is known that means that we've
|
||||
// already had the channel information and if it was in the
|
||||
// feed already (not yet known) it wouldn't get here.
|
||||
// That means here we get if we add a new channel to feed.
|
||||
if (const auto count = history->unreadCount()) {
|
||||
unreadCountChanged(count, history->mute() ? count : 0);
|
||||
}
|
||||
} else {
|
||||
session().api().requestDialogEntry(this);
|
||||
}
|
||||
}
|
||||
if (_chatsList.size() == 1) {
|
||||
if (_chatsList.indexed()->size() == 1) {
|
||||
updateChatListSortPosition();
|
||||
}
|
||||
owner().notifyFolderUpdated(this, FolderUpdateFlag::List);
|
||||
}
|
||||
|
||||
void Folder::unregisterOne(not_null<History*> history) {
|
||||
//session().storage().remove( // #feed
|
||||
// Storage::FeedMessagesRemoveAll(_id, channel->bareId()));
|
||||
|
||||
if (unreadCountKnown()) {
|
||||
if (history->unreadCountKnown()) {
|
||||
if (const auto delta = -history->unreadCount()) {
|
||||
unreadCountChanged(delta, history->mute() ? delta : 0);
|
||||
}
|
||||
} else {
|
||||
session().api().requestDialogEntry(this);
|
||||
}
|
||||
}
|
||||
if (_chatsList.empty()) {
|
||||
updateChatListExistence();
|
||||
}
|
||||
owner().notifyFolderUpdated(this, FolderUpdateFlag::List);
|
||||
}
|
||||
|
||||
not_null<Dialogs::IndexedList*> Folder::chatsList(Dialogs::Mode list) {
|
||||
return (list == Dialogs::Mode::All)
|
||||
? &_chatsList
|
||||
: &_importantChatsList;
|
||||
not_null<Dialogs::MainList*> Folder::chatsList() {
|
||||
return &_chatsList;
|
||||
}
|
||||
|
||||
void Folder::loadUserpic() {
|
||||
|
@ -163,71 +140,16 @@ void Folder::paintUserpic(
|
|||
}
|
||||
|
||||
bool Folder::chatsListLoaded() const {
|
||||
return _chatsListLoaded;
|
||||
return _chatsList.loaded();
|
||||
}
|
||||
|
||||
void Folder::setChatsListLoaded(bool loaded) {
|
||||
if (_chatsListLoaded != loaded) {
|
||||
_chatsListLoaded = loaded;
|
||||
owner().notifyFolderUpdated(this, FolderUpdateFlag::List);
|
||||
if (_chatsList.loaded() == loaded) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(true);
|
||||
_chatsList.setLoaded(loaded);
|
||||
}
|
||||
// // #feed
|
||||
//int32 Folder::chatsHash() const {
|
||||
// const auto ordered = ranges::view::all(
|
||||
// _histories
|
||||
// ) | ranges::view::transform([](not_null<History*> history) {
|
||||
// return history->peer->bareId();
|
||||
// }) | ranges::to_vector | ranges::action::sort;
|
||||
// return Api::CountHash(ordered);
|
||||
//}
|
||||
//
|
||||
//void Folder::setChats(std::vector<not_null<PeerData*>> chats) {
|
||||
// const auto remove = ranges::view::all(
|
||||
// _histories
|
||||
// ) | ranges::view::transform([](not_null<History*> history) {
|
||||
// return history->peer;
|
||||
// }) | ranges::view::filter([&](not_null<PeerData*> peer) {
|
||||
// return !base::contains(chats, peer);
|
||||
// }) | ranges::to_vector;
|
||||
//
|
||||
// const auto add = ranges::view::all(
|
||||
// chats
|
||||
// ) | ranges::view::filter([&](not_null<PeerData*> peer) {
|
||||
// return ranges::find(
|
||||
// _histories,
|
||||
// peer,
|
||||
// [](auto history) { return history->peer; }
|
||||
// ) == end(_histories);
|
||||
// }) | ranges::view::transform([](PeerData *peer) {
|
||||
// return not_null<PeerData*>(peer);
|
||||
// }) | ranges::to_vector;
|
||||
//
|
||||
// changeChatsList(add, remove);
|
||||
//
|
||||
// setChatsLoaded(true);
|
||||
//}
|
||||
//
|
||||
//void Folder::changeChatsList(
|
||||
// const std::vector<not_null<PeerData*>> &add,
|
||||
// const std::vector<not_null<PeerData*>> &remove) {
|
||||
// _settingChats = true;
|
||||
// const auto restore = gsl::finally([&] { _settingChats = false; });
|
||||
//
|
||||
// for (const auto channel : remove) {
|
||||
// channel->clearFeed();
|
||||
// }
|
||||
//
|
||||
// //// We assume the last message was correct before requesting the list.
|
||||
// //// So we save it and don't allow channels from the list to change it.
|
||||
// //// After that we restore it.
|
||||
// const auto oldChatListMessage = base::take(_chatListMessage);
|
||||
// for (const auto channel : add) {
|
||||
// _chatListMessage = std::nullopt;
|
||||
// channel->setFeed(this);
|
||||
// }
|
||||
// _chatListMessage = oldChatListMessage;
|
||||
//}
|
||||
|
||||
void Folder::requestChatListMessage() {
|
||||
if (!chatListMessageKnown()) {
|
||||
|
@ -235,66 +157,14 @@ void Folder::requestChatListMessage() {
|
|||
}
|
||||
}
|
||||
|
||||
void Folder::setPinnedChatsLimit(int limit) {
|
||||
_pinnedChatsList.setLimit(limit);
|
||||
}
|
||||
|
||||
void Folder::setChatPinned(const Dialogs::Key &key, bool pinned) {
|
||||
_pinnedChatsList.setPinned(key, pinned);
|
||||
}
|
||||
|
||||
void Folder::addPinnedChat(const Dialogs::Key &key) {
|
||||
_pinnedChatsList.addPinned(key);
|
||||
}
|
||||
|
||||
void Folder::applyPinnedChats(const QVector<MTPDialogPeer> &list) {
|
||||
_pinnedChatsList.applyList(&owner(), list);
|
||||
}
|
||||
|
||||
const std::vector<Dialogs::Key> &Folder::pinnedChatsOrder() const {
|
||||
return _pinnedChatsList.order();
|
||||
}
|
||||
|
||||
void Folder::clearPinnedChats() {
|
||||
_pinnedChatsList.clear();
|
||||
}
|
||||
|
||||
void Folder::reorderTwoPinnedChats(
|
||||
const Dialogs::Key &key1,
|
||||
const Dialogs::Key &key2) {
|
||||
_pinnedChatsList.reorder(key1, key2);
|
||||
}
|
||||
|
||||
TimeId Folder::adjustedChatListTimeId() const {
|
||||
return _chatsList.empty()
|
||||
const auto list = _chatsList.indexed();
|
||||
return list->empty()
|
||||
? TimeId(0)
|
||||
: (*_chatsList.begin())->entry()->adjustedChatListTimeId();
|
||||
}
|
||||
|
||||
int Folder::unreadCount() const {
|
||||
return _unreadCount.value_or(0);
|
||||
}
|
||||
|
||||
rpl::producer<int> Folder::unreadCountValue() const {
|
||||
return rpl::single(
|
||||
unreadCount()
|
||||
) | rpl::then(_unreadCountChanges.events());
|
||||
}
|
||||
|
||||
bool Folder::unreadCountKnown() const {
|
||||
return !!_unreadCount;
|
||||
: (*list->begin())->entry()->adjustedChatListTimeId();
|
||||
}
|
||||
|
||||
void Folder::applyDialog(const MTPDdialogFolder &data) {
|
||||
//const auto addChannel = [&](ChannelId channelId) { // #feed
|
||||
// if (const auto channel = owner().channelLoaded(channelId)) {
|
||||
// channel->setFeed(this);
|
||||
// }
|
||||
//};
|
||||
//for (const auto &channelId : data.vfeed_other_channels.v) {
|
||||
// addChannel(channelId.v);
|
||||
//}
|
||||
|
||||
if (const auto peerId = peerFromMTP(data.vpeer)) {
|
||||
const auto history = owner().history(peerId);
|
||||
const auto fullId = FullMsgId(
|
||||
|
@ -303,24 +173,36 @@ void Folder::applyDialog(const MTPDdialogFolder &data) {
|
|||
history->setFolder(this, App::histItemById(fullId));
|
||||
} else {
|
||||
_chatsList.clear();
|
||||
_importantChatsList.clear();
|
||||
updateChatListExistence();
|
||||
}
|
||||
setUnreadCounts(
|
||||
data.vunread_unmuted_messages_count.v,
|
||||
data.vunread_muted_messages_count.v);
|
||||
//setUnreadMark(data.is_unread_mark());
|
||||
//setUnreadMentionsCount(data.vunread_mentions_count.v);
|
||||
|
||||
//if (data.has_read_max_position()) { // #feed
|
||||
// setUnreadPosition(FeedPositionFromMTP(data.vread_max_position));
|
||||
//}
|
||||
|
||||
if (_chatsList.size() < kLoadedChatsMinCount) {
|
||||
session().api().requestDialogs(_id);
|
||||
updateCloudUnread(data);
|
||||
if (_chatsList.indexed()->size() < kLoadedChatsMinCount) {
|
||||
session().api().requestDialogs(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::updateCloudUnread(const MTPDdialogFolder &data) {
|
||||
const auto notifier = unreadStateChangeNotifier(!_chatsList.loaded());
|
||||
|
||||
_cloudUnread.messagesCountMuted = data.vunread_muted_messages_count.v;
|
||||
_cloudUnread.messagesCount = _cloudUnread.messagesCountMuted
|
||||
+ data.vunread_unmuted_messages_count.v;
|
||||
_cloudUnread.chatsCountMuted = data.vunread_muted_peers_count.v;
|
||||
_cloudUnread.chatsCount = _cloudUnread.chatsCountMuted
|
||||
+ data.vunread_unmuted_peers_count.v;
|
||||
}
|
||||
|
||||
Dialogs::UnreadState Folder::chatListUnreadState() const {
|
||||
const auto state = _chatsList.loaded()
|
||||
? _chatsList.unreadState()
|
||||
: _cloudUnread;
|
||||
auto result = Dialogs::UnreadState();
|
||||
result.messagesCount = state.messagesCount;
|
||||
result.messagesCountMuted = result.messagesCount.value_or(0);
|
||||
result.chatsCount = result.chatsCountMuted = state.chatsCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Folder::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
|
||||
const auto folderId = data.has_folder_id() ? data.vfolder_id.v : 0;
|
||||
if (folderId != 0) {
|
||||
|
@ -329,129 +211,50 @@ void Folder::applyPinnedUpdate(const MTPDupdateDialogPinned &data) {
|
|||
owner().setChatPinned(this, data.is_pinned());
|
||||
}
|
||||
|
||||
void Folder::changedInChatListHook(Dialogs::Mode list, bool added) {
|
||||
if (list != Dialogs::Mode::All) {
|
||||
void Folder::unreadStateChanged(
|
||||
const Dialogs::UnreadState &wasState,
|
||||
const Dialogs::UnreadState &nowState) {
|
||||
const auto updateCloudUnread = _cloudUnread.messagesCount.has_value()
|
||||
&& wasState.messagesCount.has_value();
|
||||
const auto notify = _chatsList.loaded() || updateCloudUnread;
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
|
||||
_chatsList.unreadStateChanged(wasState, nowState);
|
||||
if (!_cloudUnread.messagesCount.has_value()
|
||||
|| !wasState.messagesCount.has_value()) {
|
||||
return;
|
||||
}
|
||||
if (const auto count = unreadCount()) {
|
||||
const auto mutedCount = _unreadMutedCount;
|
||||
const auto nonMutedCount = count - mutedCount;
|
||||
const auto mutedDelta = added ? mutedCount : -mutedCount;
|
||||
const auto nonMutedDelta = added ? nonMutedCount : -nonMutedCount;
|
||||
owner().unreadIncrement(nonMutedDelta, false);
|
||||
owner().unreadIncrement(mutedDelta, true);
|
||||
Assert(nowState.messagesCount.has_value());
|
||||
|
||||
const auto fullMuted = (nonMutedCount == 0);
|
||||
const auto entriesWithUnreadDelta = added ? 1 : -1;
|
||||
const auto mutedEntriesWithUnreadDelta = fullMuted
|
||||
? entriesWithUnreadDelta
|
||||
: 0;
|
||||
owner().unreadEntriesChanged(
|
||||
entriesWithUnreadDelta,
|
||||
mutedEntriesWithUnreadDelta);
|
||||
}
|
||||
*_cloudUnread.messagesCount += *nowState.messagesCount
|
||||
- *wasState.messagesCount;
|
||||
_cloudUnread.messagesCountMuted += nowState.messagesCountMuted
|
||||
- wasState.messagesCountMuted;
|
||||
_cloudUnread.chatsCount += nowState.chatsCount - wasState.chatsCount;
|
||||
_cloudUnread.chatsCountMuted += nowState.chatsCountMuted
|
||||
- wasState.chatsCountMuted;
|
||||
}
|
||||
|
||||
template <typename PerformUpdate>
|
||||
void Folder::updateUnreadCounts(PerformUpdate &&performUpdate) {
|
||||
const auto wasUnreadCount = _unreadCount ? *_unreadCount : 0;
|
||||
const auto wasUnreadMutedCount = _unreadMutedCount;
|
||||
const auto wasFullMuted = (wasUnreadMutedCount > 0)
|
||||
&& (wasUnreadCount == wasUnreadMutedCount);
|
||||
void Folder::unreadEntryChanged(
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added) {
|
||||
const auto updateCloudUnread = _cloudUnread.messagesCount.has_value()
|
||||
&& state.messagesCount.has_value();
|
||||
const auto notify = _chatsList.loaded() || updateCloudUnread;
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
|
||||
performUpdate();
|
||||
Assert(_unreadCount.has_value());
|
||||
|
||||
_unreadCountChanges.fire(unreadCount());
|
||||
updateChatListEntry();
|
||||
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
const auto nowUnreadCount = *_unreadCount;
|
||||
const auto nowUnreadMutedCount = _unreadMutedCount;
|
||||
const auto nowFullMuted = (nowUnreadMutedCount > 0)
|
||||
&& (nowUnreadCount == nowUnreadMutedCount);
|
||||
|
||||
owner().unreadIncrement(
|
||||
(nowUnreadCount - nowUnreadMutedCount)
|
||||
- (wasUnreadCount - wasUnreadMutedCount),
|
||||
false);
|
||||
owner().unreadIncrement(
|
||||
nowUnreadMutedCount - wasUnreadMutedCount,
|
||||
true);
|
||||
|
||||
const auto entriesDelta = (nowUnreadCount && !wasUnreadCount)
|
||||
? 1
|
||||
: (wasUnreadCount && !nowUnreadCount)
|
||||
? -1
|
||||
: 0;
|
||||
const auto mutedEntriesDelta = (!wasFullMuted && nowFullMuted)
|
||||
? 1
|
||||
: (wasFullMuted && !nowFullMuted)
|
||||
? -1
|
||||
: 0;
|
||||
owner().unreadEntriesChanged(
|
||||
entriesDelta,
|
||||
mutedEntriesDelta);
|
||||
}
|
||||
}
|
||||
|
||||
void Folder::setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount) {
|
||||
if (unreadCountKnown()
|
||||
&& (*_unreadCount == unreadNonMutedCount + unreadMutedCount)
|
||||
&& (_unreadMutedCount == unreadMutedCount)) {
|
||||
_chatsList.unreadEntryChanged(state, added);
|
||||
if (!_cloudUnread.messagesCount.has_value()
|
||||
|| !state.messagesCount.has_value()) {
|
||||
return;
|
||||
}
|
||||
updateUnreadCounts([&] {
|
||||
_unreadCount = unreadNonMutedCount + unreadMutedCount;
|
||||
_unreadMutedCount = unreadMutedCount;
|
||||
});
|
||||
const auto delta = (added ? 1 : -1);
|
||||
*_cloudUnread.messagesCount += delta * *state.messagesCount;
|
||||
_cloudUnread.messagesCountMuted += delta * state.messagesCountMuted;
|
||||
_cloudUnread.chatsCount += delta * state.chatsCount;
|
||||
_cloudUnread.chatsCountMuted += delta * state.chatsCountMuted;
|
||||
}
|
||||
// #feed
|
||||
//void Folder::setUnreadPosition(const MessagePosition &position) {
|
||||
// if (_unreadPosition.current() < position) {
|
||||
// _unreadPosition = position;
|
||||
// }
|
||||
//}
|
||||
|
||||
void Folder::unreadCountChanged(int unreadCountDelta, int mutedCountDelta) {
|
||||
if (!unreadCountKnown()) {
|
||||
return;
|
||||
}
|
||||
updateUnreadCounts([&] {
|
||||
accumulate_max(unreadCountDelta, -*_unreadCount);
|
||||
*_unreadCount += unreadCountDelta;
|
||||
|
||||
mutedCountDelta = snap(
|
||||
mutedCountDelta,
|
||||
-_unreadMutedCount,
|
||||
*_unreadCount - _unreadMutedCount);
|
||||
_unreadMutedCount += mutedCountDelta;
|
||||
});
|
||||
}
|
||||
//
|
||||
//void Folder::setUnreadMark(bool unread) {
|
||||
// if (_unreadMark != unread) {
|
||||
// _unreadMark = unread;
|
||||
// if (!_unreadCount || !*_unreadCount) {
|
||||
// if (inChatList(Dialogs::Mode::All)) {
|
||||
// const auto delta = _unreadMark ? 1 : -1;
|
||||
// owner().unreadIncrement(delta, mute());
|
||||
// owner().unreadEntriesChanged(
|
||||
// delta,
|
||||
// mute() ? delta : 0);
|
||||
//
|
||||
// updateChatListEntry();
|
||||
// }
|
||||
// }
|
||||
// Notify::peerUpdatedDelayed(
|
||||
// peer,
|
||||
// Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//bool Folder::unreadMark() const {
|
||||
// return _unreadMark;
|
||||
//}
|
||||
// #feed
|
||||
//MessagePosition Folder::unreadPosition() const {
|
||||
// return _unreadPosition.current();
|
||||
|
@ -462,7 +265,7 @@ void Folder::unreadCountChanged(int unreadCountDelta, int mutedCountDelta) {
|
|||
//}
|
||||
|
||||
bool Folder::toImportant() const {
|
||||
return !_importantChatsList.empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
int Folder::fixedOnTopIndex() const {
|
||||
|
@ -474,7 +277,9 @@ bool Folder::shouldBeInChatList() const {
|
|||
}
|
||||
|
||||
int Folder::chatListUnreadCount() const {
|
||||
return unreadCount();
|
||||
return session().settings().countUnreadMessages()
|
||||
? chatListUnreadState().messagesCount.value_or(0)
|
||||
: chatListUnreadState().chatsCount;
|
||||
}
|
||||
|
||||
bool Folder::chatListUnreadMark() const {
|
||||
|
@ -482,18 +287,20 @@ bool Folder::chatListUnreadMark() const {
|
|||
}
|
||||
|
||||
bool Folder::chatListMutedBadge() const {
|
||||
return _unreadCount ? (*_unreadCount <= _unreadMutedCount) : false;
|
||||
return true;
|
||||
}
|
||||
|
||||
HistoryItem *Folder::chatListMessage() const {
|
||||
return _chatsList.empty()
|
||||
const auto list = _chatsList.indexed();
|
||||
return list->empty()
|
||||
? nullptr
|
||||
: (*_chatsList.begin())->key().entry()->chatListMessage();
|
||||
: (*list->begin())->key().entry()->chatListMessage();
|
||||
}
|
||||
|
||||
bool Folder::chatListMessageKnown() const {
|
||||
return _chatsList.empty()
|
||||
|| (*_chatsList.begin())->key().entry()->chatListMessageKnown();
|
||||
const auto list = _chatsList.indexed();
|
||||
return list->empty()
|
||||
|| (*list->begin())->key().entry()->chatListMessageKnown();
|
||||
}
|
||||
|
||||
const QString &Folder::chatListName() const {
|
||||
|
|
|
@ -8,8 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#pragma once
|
||||
|
||||
#include "dialogs/dialogs_entry.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "dialogs/dialogs_pinned_list.h"
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
#include "data/data_messages.h"
|
||||
|
||||
class ChannelData;
|
||||
|
@ -20,15 +19,6 @@ namespace Data {
|
|||
class Session;
|
||||
class Folder;
|
||||
|
||||
enum class FolderUpdateFlag {
|
||||
List,
|
||||
};
|
||||
|
||||
struct FolderUpdate {
|
||||
not_null<Data::Folder*> folder;
|
||||
FolderUpdateFlag flag;
|
||||
};
|
||||
|
||||
//MessagePosition FeedPositionFromMTP(const MTPFeedPosition &position); // #feed
|
||||
|
||||
class Folder final : public Dialogs::Entry {
|
||||
|
@ -43,43 +33,21 @@ public:
|
|||
void registerOne(not_null<History*> history);
|
||||
void unregisterOne(not_null<History*> history);
|
||||
|
||||
not_null<Dialogs::IndexedList*> chatsList(Dialogs::Mode list);
|
||||
not_null<Dialogs::MainList*> chatsList();
|
||||
|
||||
void applyDialog(const MTPDdialogFolder &data);
|
||||
void applyPinnedUpdate(const MTPDupdateDialogPinned &data);
|
||||
|
||||
void setUnreadCounts(int unreadNonMutedCount, int unreadMutedCount);
|
||||
//void setUnreadPosition(const MessagePosition &position); // #feed
|
||||
void unreadCountChanged(
|
||||
int unreadCountDelta,
|
||||
int mutedCountDelta);
|
||||
rpl::producer<int> unreadCountValue() const;
|
||||
//MessagePosition unreadPosition() const; // #feed
|
||||
//rpl::producer<MessagePosition> unreadPositionChanges() const; // #feed
|
||||
|
||||
//void setUnreadMark(bool unread);
|
||||
//bool unreadMark() const;
|
||||
//int unreadCountForBadge() const; // unreadCount || unreadMark ? 1 : 0.
|
||||
|
||||
void setPinnedChatsLimit(int limit);
|
||||
|
||||
// Places on the last place in the list otherwise.
|
||||
// Does nothing if already pinned.
|
||||
void addPinnedChat(const Dialogs::Key &key);
|
||||
|
||||
// if (pinned) places on the first place in the list.
|
||||
void setChatPinned(const Dialogs::Key &key, bool pinned);
|
||||
|
||||
void applyPinnedChats(const QVector<MTPDialogPeer> &list);
|
||||
const std::vector<Dialogs::Key> &pinnedChatsOrder() const;
|
||||
void clearPinnedChats();
|
||||
void reorderTwoPinnedChats(
|
||||
const Dialogs::Key &key1,
|
||||
const Dialogs::Key &key2);
|
||||
void updateCloudUnread(const MTPDdialogFolder &data);
|
||||
void unreadStateChanged(
|
||||
const Dialogs::UnreadState &wasState,
|
||||
const Dialogs::UnreadState &nowState);
|
||||
void unreadEntryChanged(const Dialogs::UnreadState &state, bool added);
|
||||
|
||||
TimeId adjustedChatListTimeId() const override;
|
||||
int unreadCount() const;
|
||||
bool unreadCountKnown() const;
|
||||
|
||||
int fixedOnTopIndex() const override;
|
||||
bool toImportant() const override;
|
||||
|
@ -87,13 +55,13 @@ public:
|
|||
int chatListUnreadCount() const override;
|
||||
bool chatListUnreadMark() const override;
|
||||
bool chatListMutedBadge() const override;
|
||||
Dialogs::UnreadState chatListUnreadState() const override;
|
||||
HistoryItem *chatListMessage() const override;
|
||||
bool chatListMessageKnown() const override;
|
||||
void requestChatListMessage() override;
|
||||
const QString &chatListName() const override;
|
||||
const base::flat_set<QString> &chatListNameWords() const override;
|
||||
const base::flat_set<QChar> &chatListFirstLetters() const override;
|
||||
void changedInChatListHook(Dialogs::Mode list, bool added) override;
|
||||
|
||||
void loadUserpic() override;
|
||||
void paintUserpic(
|
||||
|
@ -103,34 +71,20 @@ public:
|
|||
int size) const override;
|
||||
|
||||
bool chatsListLoaded() const;
|
||||
void setChatsListLoaded(bool loaded);
|
||||
//int32 chatsHash() const;
|
||||
//void setChats(std::vector<not_null<PeerData*>> chats); // #feed
|
||||
void setChatsListLoaded(bool loaded = true);
|
||||
|
||||
private:
|
||||
void indexNameParts();
|
||||
//void changeChatsList(
|
||||
// const std::vector<not_null<PeerData*>> &add,
|
||||
// const std::vector<not_null<PeerData*>> &remove);
|
||||
|
||||
template <typename PerformUpdate>
|
||||
void updateUnreadCounts(PerformUpdate &&performUpdate);
|
||||
|
||||
FolderId _id = 0;
|
||||
Dialogs::IndexedList _chatsList;
|
||||
Dialogs::IndexedList _importantChatsList;
|
||||
Dialogs::PinnedList _pinnedChatsList;
|
||||
bool _chatsListLoaded = false;
|
||||
Dialogs::MainList _chatsList;
|
||||
|
||||
QString _name;
|
||||
base::flat_set<QString> _nameWords;
|
||||
base::flat_set<QChar> _nameFirstLetters;
|
||||
|
||||
Dialogs::UnreadState _cloudUnread;
|
||||
//rpl::variable<MessagePosition> _unreadPosition;
|
||||
std::optional<int> _unreadCount;
|
||||
rpl::event_stream<int> _unreadCountChanges;
|
||||
int _unreadMutedCount = 0;
|
||||
//bool _unreadMark = false;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -140,6 +140,16 @@ MTPPhotoSize FindDocumentThumbnail(const MTPDdocument &data) {
|
|||
: MTPPhotoSize(MTP_photoSizeEmpty(MTP_string("")));
|
||||
}
|
||||
|
||||
rpl::producer<int> PinnedDialogsCountMaxValue() {
|
||||
return rpl::single(
|
||||
rpl::empty_value()
|
||||
) | rpl::then(
|
||||
Core::App().configUpdates()
|
||||
) | rpl::map([=] {
|
||||
return Global::PinnedDialogsCountMax();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Session::Session(not_null<AuthSession*> session)
|
||||
|
@ -150,11 +160,9 @@ Session::Session(not_null<AuthSession*> session)
|
|||
, _bigFileCache(Core::App().databases().get(
|
||||
Local::cacheBigFilePath(),
|
||||
Local::cacheBigFileSettings()))
|
||||
, _chatsList(Dialogs::SortMode::Date)
|
||||
, _importantChatsList(Dialogs::SortMode::Date)
|
||||
, _chatsList(PinnedDialogsCountMaxValue())
|
||||
, _contactsList(Dialogs::SortMode::Name)
|
||||
, _contactsNoChatsList(Dialogs::SortMode::Name)
|
||||
, _pinnedChatsList(Global::PinnedDialogsCountMax())
|
||||
, _selfDestructTimer([=] { checkSelfDestructItems(); })
|
||||
, _sendActionsAnimation([=](crl::time now) {
|
||||
return sendActionsAnimationCallback(now);
|
||||
|
@ -168,14 +176,6 @@ Session::Session(not_null<AuthSession*> session)
|
|||
setupChannelLeavingViewer();
|
||||
setupPeerNameViewer();
|
||||
setupUserIsContactViewer();
|
||||
|
||||
Core::App().configUpdates(
|
||||
) | rpl::start_with_next([=] {
|
||||
_pinnedChatsList.setLimit(Global::PinnedDialogsCountMax());
|
||||
for (const auto &[folderId, folder] : _folders) {
|
||||
folder->setPinnedChatsLimit(Global::PinnedDialogsInFolderMax());
|
||||
}
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Session::clear() {
|
||||
|
@ -786,7 +786,7 @@ bool Session::sendActionsAnimationCallback(crl::time now) {
|
|||
}
|
||||
|
||||
bool Session::chatsListLoaded(Data::Folder *folder) {
|
||||
return folder ? folder->chatsListLoaded() : _chatsListLoaded;
|
||||
return chatsList(folder)->loaded();
|
||||
}
|
||||
|
||||
void Session::chatsListChanged(FolderId folderId) {
|
||||
|
@ -797,12 +797,11 @@ void Session::chatsListChanged(Data::Folder *folder) {
|
|||
_chatsListChanged.fire_copy(folder);
|
||||
}
|
||||
|
||||
void Session::chatsListDone(FolderId folderId) {
|
||||
const auto folder = folderId ? this->folder(folderId).get() : nullptr;
|
||||
void Session::chatsListDone(Data::Folder *folder) {
|
||||
if (folder) {
|
||||
folder->setChatsListLoaded(true);
|
||||
folder->setChatsListLoaded();
|
||||
} else {
|
||||
_chatsListLoaded = true;
|
||||
_chatsList.setLoaded();
|
||||
}
|
||||
_chatsListLoadedEvents.fire_copy(folder);
|
||||
}
|
||||
|
@ -964,13 +963,6 @@ void Session::setupPeerNameViewer() {
|
|||
) | rpl::start_with_next([=](const Notify::PeerUpdate &update) {
|
||||
const auto peer = update.peer;
|
||||
const auto &oldLetters = update.oldNameFirstLetters;
|
||||
_chatsList.peerNameChanged(Dialogs::Mode::All, peer, oldLetters);
|
||||
if (Global::DialogsModeEnabled()) {
|
||||
_importantChatsList.peerNameChanged(
|
||||
Dialogs::Mode::Important,
|
||||
peer,
|
||||
oldLetters);
|
||||
}
|
||||
_contactsNoChatsList.peerNameChanged(peer, oldLetters);
|
||||
_contactsList.peerNameChanged(peer, oldLetters);
|
||||
}, _lifetime);
|
||||
|
@ -991,7 +983,7 @@ void Session::setupUserIsContactViewer() {
|
|||
if (user->contactStatus() == UserData::ContactStatus::Contact) {
|
||||
const auto history = user->owner().history(user->id);
|
||||
_contactsList.addByName(history);
|
||||
if (!_chatsList.contains(history)) {
|
||||
if (!_chatsList.indexed()->contains(history)) {
|
||||
_contactsNoChatsList.addByName(history);
|
||||
}
|
||||
} else if (const auto history = user->owner().historyLoaded(user)) {
|
||||
|
@ -1288,16 +1280,6 @@ rpl::producer<not_null<UserData*>> Session::megagroupParticipantAdded(
|
|||
});
|
||||
}
|
||||
|
||||
void Session::notifyFolderUpdated(
|
||||
not_null<Folder*> folder,
|
||||
FolderUpdateFlag update) {
|
||||
_folderUpdates.fire({ folder, update });
|
||||
}
|
||||
|
||||
rpl::producer<FolderUpdate> Session::folderUpdated() const {
|
||||
return _folderUpdates.events();
|
||||
}
|
||||
|
||||
void Session::notifyStickersUpdated() {
|
||||
_stickersUpdated.fire({});
|
||||
}
|
||||
|
@ -1355,33 +1337,24 @@ MessageIdsList Session::itemOrItsGroup(not_null<HistoryItem*> item) const {
|
|||
void Session::setChatPinned(const Dialogs::Key &key, bool pinned) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
|
||||
if (const auto folder = key.entry()->folder()) {
|
||||
folder->setChatPinned(key, pinned);
|
||||
} else {
|
||||
_pinnedChatsList.setPinned(key, pinned);
|
||||
}
|
||||
const auto list = chatsList(key.entry()->folder())->pinned();
|
||||
list->setPinned(key, pinned);
|
||||
}
|
||||
|
||||
void Session::setPinnedFromDialog(const Dialogs::Key &key, bool pinned) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
|
||||
if (const auto folder = key.entry()->folder()) {
|
||||
if (pinned) {
|
||||
folder->addPinnedChat(key);
|
||||
} else {
|
||||
folder->setChatPinned(key, false);
|
||||
}
|
||||
} else if (pinned) {
|
||||
_pinnedChatsList.addPinned(key);
|
||||
const auto list = chatsList(key.entry()->folder())->pinned();
|
||||
if (pinned) {
|
||||
list->addPinned(key);
|
||||
} else {
|
||||
_pinnedChatsList.setPinned(key, false);
|
||||
list->setPinned(key, false);
|
||||
}
|
||||
}
|
||||
|
||||
void Session::applyPinnedChats(
|
||||
FolderId folderId,
|
||||
Data::Folder *folder,
|
||||
const QVector<MTPDialogPeer> &list) {
|
||||
const auto folder = folderId ? this->folder(folderId).get() : nullptr;
|
||||
for (const auto &peer : list) {
|
||||
peer.match([&](const MTPDdialogPeer &data) {
|
||||
const auto history = this->history(peerFromMTP(data.vpeer));
|
||||
|
@ -1396,33 +1369,31 @@ void Session::applyPinnedChats(
|
|||
}
|
||||
});
|
||||
}
|
||||
if (folder) {
|
||||
folder->applyPinnedChats(list);
|
||||
} else {
|
||||
_pinnedChatsList.applyList(this, list);
|
||||
}
|
||||
chatsList(folder)->pinned()->applyList(this, list);
|
||||
}
|
||||
|
||||
void Session::applyDialogs(
|
||||
FolderId requestFolderId,
|
||||
Data::Folder *requestFolder,
|
||||
const QVector<MTPMessage> &messages,
|
||||
const QVector<MTPDialog> &dialogs) {
|
||||
App::feedMsgs(messages, NewMessageLast);
|
||||
for (const auto &dialog : dialogs) {
|
||||
dialog.match([&](const auto &data) {
|
||||
applyDialog(requestFolderId, data);
|
||||
applyDialog(requestFolder, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Session::applyDialog(FolderId requestFolderId, const MTPDdialog &data) {
|
||||
void Session::applyDialog(
|
||||
Data::Folder *requestFolder,
|
||||
const MTPDdialog &data) {
|
||||
const auto peerId = peerFromMTP(data.vpeer);
|
||||
if (!peerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto history = session().data().history(peerId);
|
||||
history->applyDialog(requestFolderId, data);
|
||||
history->applyDialog(requestFolder, data);
|
||||
setPinnedFromDialog(history, data.is_pinned());
|
||||
|
||||
if (!history->fixedOnTopIndex() && !history->isPinnedDialog()) {
|
||||
|
@ -1443,10 +1414,10 @@ void Session::applyDialog(FolderId requestFolderId, const MTPDdialog &data) {
|
|||
}
|
||||
|
||||
void Session::applyDialog(
|
||||
FolderId requestFolderId,
|
||||
Data::Folder *requestFolder,
|
||||
const MTPDdialogFolder &data) {
|
||||
if (requestFolderId != 0) {
|
||||
LOG(("API Error: requestFolderId != 0 for dialogFolder."));
|
||||
if (requestFolder) {
|
||||
LOG(("API Error: requestFolder != nullptr for dialogFolder."));
|
||||
}
|
||||
const auto folder = processFolder(data.vfolder);
|
||||
folder->applyDialog(data);
|
||||
|
@ -1478,36 +1449,23 @@ void Session::addAllSavedPeers() {
|
|||
addSavedPeersAfter(QDateTime());
|
||||
}
|
||||
|
||||
int Session::pinnedChatsCount(FolderId folderId) const {
|
||||
return pinnedChatsOrder(folderId).size();
|
||||
int Session::pinnedChatsCount(Data::Folder *folder) const {
|
||||
return pinnedChatsOrder(folder).size();
|
||||
}
|
||||
|
||||
int Session::pinnedChatsLimit(FolderId folderId) const {
|
||||
return folderId
|
||||
int Session::pinnedChatsLimit(Data::Folder *folder) const {
|
||||
return folder
|
||||
? Global::PinnedDialogsInFolderMax()
|
||||
: Global::PinnedDialogsCountMax();
|
||||
}
|
||||
|
||||
const std::vector<Dialogs::Key> &Session::pinnedChatsOrder(
|
||||
FolderId folderId) const {
|
||||
if (folderId) {
|
||||
if (const auto folder = folderLoaded(folderId)) {
|
||||
return folder->pinnedChatsOrder();
|
||||
}
|
||||
static const auto result = std::vector<Dialogs::Key>();
|
||||
return result;
|
||||
}
|
||||
return _pinnedChatsList.order();
|
||||
Data::Folder *folder) const {
|
||||
return chatsList(folder)->pinned()->order();
|
||||
}
|
||||
|
||||
void Session::clearPinnedChats(FolderId folderId) {
|
||||
if (folderId) {
|
||||
if (const auto folder = folderLoaded(folderId)) {
|
||||
folder->clearPinnedChats();
|
||||
}
|
||||
} else {
|
||||
_pinnedChatsList.clear();
|
||||
}
|
||||
void Session::clearPinnedChats(Data::Folder *folder) {
|
||||
chatsList(folder)->pinned()->clear();
|
||||
}
|
||||
|
||||
void Session::reorderTwoPinnedChats(
|
||||
|
@ -1516,12 +1474,7 @@ void Session::reorderTwoPinnedChats(
|
|||
Expects(key1.entry()->folderKnown() && key2.entry()->folderKnown());
|
||||
Expects(key1.entry()->folder() == key2.entry()->folder());
|
||||
|
||||
const auto folder = key1.entry()->folder();
|
||||
if (folder) {
|
||||
folder->reorderTwoPinnedChats(key1, key2);
|
||||
} else {
|
||||
_pinnedChatsList.reorder(key1, key2);
|
||||
}
|
||||
chatsList(key1.entry()->folder())->pinned()->reorder(key1, key2);
|
||||
}
|
||||
|
||||
NotifySettings &Session::defaultNotifySettings(
|
||||
|
@ -1621,57 +1574,61 @@ void Session::updateSendActionAnimation(
|
|||
}
|
||||
|
||||
int Session::unreadBadge() const {
|
||||
const auto state = _chatsList.unreadState();
|
||||
return computeUnreadBadge(
|
||||
_unreadFull,
|
||||
_unreadMuted,
|
||||
_unreadEntriesFull,
|
||||
_unreadEntriesMuted);
|
||||
state.messagesCount.value_or(0),
|
||||
state.messagesCountMuted,
|
||||
state.chatsCount,
|
||||
state.chatsCountMuted);
|
||||
}
|
||||
|
||||
bool Session::unreadBadgeMuted() const {
|
||||
const auto state = _chatsList.unreadState();
|
||||
return computeUnreadBadgeMuted(
|
||||
_unreadFull,
|
||||
_unreadMuted,
|
||||
_unreadEntriesFull,
|
||||
_unreadEntriesMuted);
|
||||
state.messagesCount.value_or(0),
|
||||
state.messagesCountMuted,
|
||||
state.chatsCount,
|
||||
state.chatsCountMuted);
|
||||
}
|
||||
|
||||
int Session::unreadBadgeIgnoreOne(History *history) const {
|
||||
const auto removeCount = (history
|
||||
&& history->inChatList(Dialogs::Mode::All))
|
||||
const auto removeCount = (history && history->inChatList())
|
||||
? history->unreadCount()
|
||||
: 0;
|
||||
if (!removeCount) {
|
||||
return unreadBadge();
|
||||
}
|
||||
const auto removeMuted = history->mute();
|
||||
const auto state = _chatsList.unreadState();
|
||||
const auto removeMuted = history->mute()
|
||||
|| (history->folder() != nullptr);
|
||||
return computeUnreadBadge(
|
||||
_unreadFull - removeCount,
|
||||
_unreadMuted - (removeMuted ? removeCount : 0),
|
||||
_unreadEntriesFull - 1,
|
||||
_unreadEntriesMuted - (removeMuted ? 1 : 0));
|
||||
state.messagesCount.value_or(0) - removeCount,
|
||||
state.messagesCountMuted - (removeMuted ? removeCount : 0),
|
||||
state.chatsCount - 1,
|
||||
state.chatsCountMuted - (removeMuted ? 1 : 0));
|
||||
}
|
||||
|
||||
bool Session::unreadBadgeMutedIgnoreOne(History *history) const {
|
||||
const auto removeCount = (history
|
||||
&& history->inChatList(Dialogs::Mode::All))
|
||||
const auto removeCount = (history && history->inChatList())
|
||||
? history->unreadCount()
|
||||
: 0;
|
||||
if (!removeCount) {
|
||||
return unreadBadgeMuted();
|
||||
}
|
||||
const auto state = _chatsList.unreadState();
|
||||
const auto removeMuted = history->mute();
|
||||
return computeUnreadBadgeMuted(
|
||||
_unreadFull - removeCount,
|
||||
_unreadMuted - (removeMuted ? removeCount : 0),
|
||||
_unreadEntriesFull - 1,
|
||||
_unreadEntriesMuted - (removeMuted ? 1 : 0));
|
||||
state.messagesCount.value_or(0) - removeCount,
|
||||
state.messagesCountMuted - (removeMuted ? removeCount : 0),
|
||||
state.chatsCount - 1,
|
||||
state.chatsCountMuted - (removeMuted ? 1 : 0));
|
||||
}
|
||||
|
||||
int Session::unreadOnlyMutedBadge() const {
|
||||
const auto state = _chatsList.unreadState();
|
||||
return _session->settings().countUnreadMessages()
|
||||
? _unreadMuted
|
||||
: _unreadEntriesMuted;
|
||||
? state.messagesCountMuted
|
||||
: state.chatsCountMuted;
|
||||
}
|
||||
|
||||
int Session::computeUnreadBadge(
|
||||
|
@ -1698,57 +1655,29 @@ bool Session::computeUnreadBadgeMuted(
|
|||
: (entriesMuted >= entriesFull);
|
||||
}
|
||||
|
||||
void Session::unreadIncrement(int count, bool muted) {
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
_unreadFull += count;
|
||||
if (muted) {
|
||||
_unreadMuted += count;
|
||||
}
|
||||
if (_session->settings().countUnreadMessages()) {
|
||||
if (!muted || _session->settings().includeMutedCounter()) {
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
void Session::unreadStateChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &wasState) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
Expects(key.entry()->inChatList());
|
||||
|
||||
void Session::unreadMuteChanged(int count, bool muted) {
|
||||
const auto wasAll = (_unreadMuted == _unreadFull);
|
||||
if (muted) {
|
||||
_unreadMuted += count;
|
||||
const auto nowState = key.entry()->chatListUnreadState();
|
||||
if (const auto folder = key.entry()->folder()) {
|
||||
folder->unreadStateChanged(wasState, nowState);
|
||||
} else {
|
||||
_unreadMuted -= count;
|
||||
}
|
||||
if (_session->settings().countUnreadMessages()) {
|
||||
const auto nowAll = (_unreadMuted == _unreadFull);
|
||||
const auto changed = !_session->settings().includeMutedCounter()
|
||||
|| (wasAll != nowAll);
|
||||
if (changed) {
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
_chatsList.unreadStateChanged(wasState, nowState);
|
||||
}
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
|
||||
void Session::unreadEntriesChanged(
|
||||
int withUnreadDelta,
|
||||
int mutedWithUnreadDelta) {
|
||||
if (!withUnreadDelta && !mutedWithUnreadDelta) {
|
||||
return;
|
||||
}
|
||||
const auto wasAll = (_unreadEntriesMuted == _unreadEntriesFull);
|
||||
_unreadEntriesFull += withUnreadDelta;
|
||||
_unreadEntriesMuted += mutedWithUnreadDelta;
|
||||
if (!_session->settings().countUnreadMessages()) {
|
||||
const auto nowAll = (_unreadEntriesMuted == _unreadEntriesFull);
|
||||
const auto withMuted = _session->settings().includeMutedCounter();
|
||||
const auto withMutedChanged = withMuted
|
||||
&& (withUnreadDelta != 0 || wasAll != nowAll);
|
||||
const auto withoutMutedChanged = !withMuted
|
||||
&& (withUnreadDelta != mutedWithUnreadDelta);
|
||||
if (withMutedChanged || withoutMutedChanged) {
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
void Session::unreadEntryChanged(const Dialogs::Key &key, bool added) {
|
||||
Expects(key.entry()->folderKnown());
|
||||
|
||||
const auto state = key.entry()->chatListUnreadState();
|
||||
if (const auto folder = key.entry()->folder()) {
|
||||
folder->unreadEntryChanged(state, added);
|
||||
} else {
|
||||
_chatsList.unreadEntryChanged(state, added);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2986,10 +2915,13 @@ not_null<Folder*> Session::processFolder(const MTPDfolder &data) {
|
|||
// return _defaultFeedId.value();
|
||||
//}
|
||||
|
||||
not_null<Dialogs::IndexedList*> Session::chatsList(Dialogs::Mode list) {
|
||||
return (list == Dialogs::Mode::All)
|
||||
? &_chatsList
|
||||
: &_importantChatsList;
|
||||
not_null<Dialogs::MainList*> Session::chatsList(Data::Folder *folder) {
|
||||
return folder ? folder->chatsList().get() : &_chatsList;
|
||||
}
|
||||
|
||||
not_null<const Dialogs::MainList*> Session::chatsList(
|
||||
Data::Folder *folder) const {
|
||||
return folder ? folder->chatsList() : &_chatsList;
|
||||
}
|
||||
|
||||
not_null<Dialogs::IndexedList*> Session::contactsList() {
|
||||
|
@ -3006,7 +2938,7 @@ auto Session::refreshChatListEntry(Dialogs::Key key)
|
|||
|
||||
const auto entry = key.entry();
|
||||
auto result = RefreshChatListEntryResult();
|
||||
result.changed = !entry->inChatList(Mode::All);
|
||||
result.changed = !entry->inChatList();
|
||||
if (result.changed) {
|
||||
const auto mainRow = entry->addToChatList(Mode::All);
|
||||
_contactsNoChatsList.del(key, mainRow);
|
||||
|
@ -3241,7 +3173,7 @@ void Session::serviceNotification(
|
|||
MTPstring()));
|
||||
}
|
||||
const auto history = this->history(PeerData::kServiceNotificationsId);
|
||||
if (!history->lastMessageKnown()) {
|
||||
if (!history->folderKnown()) {
|
||||
_session->api().requestDialogEntry(history, [=] {
|
||||
insertCheckedServiceNotification(message, media, date);
|
||||
});
|
||||
|
@ -3263,10 +3195,6 @@ void Session::insertCheckedServiceNotification(
|
|||
const MTPMessageMedia &media,
|
||||
TimeId date) {
|
||||
const auto history = this->history(PeerData::kServiceNotificationsId);
|
||||
if (!history->isReadyFor(ShowAtUnreadMsgId)) {
|
||||
history->setUnreadCount(0);
|
||||
history->getReadyFor(ShowAtTheEndMsgId);
|
||||
}
|
||||
const auto flags = MTPDmessage::Flag::f_entities
|
||||
| MTPDmessage::Flag::f_from_id
|
||||
| MTPDmessage_ClientFlag::f_clientside_unread
|
||||
|
|
|
@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "chat_helpers/stickers.h"
|
||||
#include "dialogs/dialogs_key.h"
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "dialogs/dialogs_pinned_list.h"
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
#include "data/data_groups.h"
|
||||
#include "data/data_notify_settings.h"
|
||||
#include "history/history_location_manager.h"
|
||||
|
@ -51,8 +51,6 @@ struct SavedCredentials;
|
|||
namespace Data {
|
||||
|
||||
class Folder;
|
||||
enum class FolderUpdateFlag;
|
||||
struct FolderUpdate;
|
||||
|
||||
class WallPaper;
|
||||
|
||||
|
@ -148,7 +146,7 @@ public:
|
|||
}
|
||||
void chatsListChanged(FolderId folderId);
|
||||
void chatsListChanged(Data::Folder *folder);
|
||||
void chatsListDone(FolderId folderId);
|
||||
void chatsListDone(Data::Folder *folder);
|
||||
|
||||
struct ItemVisibilityQuery {
|
||||
not_null<HistoryItem*> item;
|
||||
|
@ -209,9 +207,6 @@ public:
|
|||
[[nodiscard]] rpl::producer<not_null<UserData*>> megagroupParticipantAdded(
|
||||
not_null<ChannelData*> channel) const;
|
||||
|
||||
void notifyFolderUpdated(not_null<Folder*> folder, FolderUpdateFlag update);
|
||||
[[nodiscard]] rpl::producer<FolderUpdate> folderUpdated() const;
|
||||
|
||||
void notifyStickersUpdated();
|
||||
[[nodiscard]] rpl::producer<> stickersUpdated() const;
|
||||
void notifySavedGifsUpdated();
|
||||
|
@ -299,20 +294,20 @@ public:
|
|||
void applyUpdate(const MTPDupdateChatDefaultBannedRights &update);
|
||||
|
||||
void applyDialogs(
|
||||
FolderId requestFolderId,
|
||||
Data::Folder *requestFolder,
|
||||
const QVector<MTPMessage> &messages,
|
||||
const QVector<MTPDialog> &dialogs);
|
||||
void addSavedPeersAfter(const QDateTime &date);
|
||||
void addAllSavedPeers();
|
||||
|
||||
int pinnedChatsCount(FolderId folderId) const;
|
||||
int pinnedChatsLimit(FolderId folderId) const;
|
||||
int pinnedChatsCount(Data::Folder *folder) const;
|
||||
int pinnedChatsLimit(Data::Folder *folder) const;
|
||||
const std::vector<Dialogs::Key> &pinnedChatsOrder(
|
||||
FolderId folderId) const;
|
||||
Data::Folder *folder) const;
|
||||
void setChatPinned(const Dialogs::Key &key, bool pinned);
|
||||
void clearPinnedChats(FolderId folderId);
|
||||
void clearPinnedChats(Data::Folder *folder);
|
||||
void applyPinnedChats(
|
||||
FolderId folderId,
|
||||
Data::Folder *folder,
|
||||
const QVector<MTPDialogPeer> &list);
|
||||
void reorderTwoPinnedChats(
|
||||
const Dialogs::Key &key1,
|
||||
|
@ -346,11 +341,10 @@ public:
|
|||
bool unreadBadgeMutedIgnoreOne(History *history) const;
|
||||
int unreadOnlyMutedBadge() const;
|
||||
|
||||
void unreadIncrement(int count, bool muted);
|
||||
void unreadMuteChanged(int count, bool muted);
|
||||
void unreadEntriesChanged(
|
||||
int withUnreadDelta,
|
||||
int mutedWithUnreadDelta);
|
||||
void unreadStateChanged(
|
||||
const Dialogs::Key &key,
|
||||
const Dialogs::UnreadState &wasState);
|
||||
void unreadEntryChanged(const Dialogs::Key &key, bool added);
|
||||
|
||||
void selfDestructIn(not_null<HistoryItem*> item, crl::time delay);
|
||||
|
||||
|
@ -525,7 +519,9 @@ public:
|
|||
//FeedId defaultFeedId() const;
|
||||
//rpl::producer<FeedId> defaultFeedIdValue() const;
|
||||
|
||||
not_null<Dialogs::IndexedList*> chatsList(Dialogs::Mode list);
|
||||
not_null<Dialogs::MainList*> chatsList(Data::Folder *folder = nullptr);
|
||||
not_null<const Dialogs::MainList*> chatsList(
|
||||
Data::Folder *folder = nullptr) const;
|
||||
not_null<Dialogs::IndexedList*> contactsList();
|
||||
not_null<Dialogs::IndexedList*> contactsNoChatsList();
|
||||
|
||||
|
@ -601,6 +597,7 @@ private:
|
|||
void setupUserIsContactViewer();
|
||||
|
||||
void checkSelfDestructItems();
|
||||
|
||||
int computeUnreadBadge(
|
||||
int full,
|
||||
int muted,
|
||||
|
@ -612,8 +609,10 @@ private:
|
|||
int entriesFull,
|
||||
int entriesMuted) const;
|
||||
|
||||
void applyDialog(FolderId requestFolderId, const MTPDdialog &data);
|
||||
void applyDialog(FolderId requestFolderId, const MTPDdialogFolder &data);
|
||||
void applyDialog(Data::Folder *requestFolder, const MTPDdialog &data);
|
||||
void applyDialog(
|
||||
Data::Folder *requestFolder,
|
||||
const MTPDdialogFolder &data);
|
||||
|
||||
void photoApplyFields(
|
||||
not_null<PhotoData*> photo,
|
||||
|
@ -734,7 +733,6 @@ private:
|
|||
QPointer<BoxContent> _exportSuggestion;
|
||||
|
||||
rpl::variable<bool> _contactsLoaded = false;
|
||||
bool _chatsListLoaded = false;
|
||||
rpl::event_stream<Data::Folder*> _chatsListLoadedEvents;
|
||||
rpl::event_stream<Data::Folder*> _chatsListChanged;
|
||||
base::Observable<ItemVisibilityQuery> _queryItemVisibility;
|
||||
|
@ -756,7 +754,6 @@ private:
|
|||
rpl::event_stream<not_null<History*>> _historyChanged;
|
||||
rpl::event_stream<MegagroupParticipant> _megagroupParticipantRemoved;
|
||||
rpl::event_stream<MegagroupParticipant> _megagroupParticipantAdded;
|
||||
rpl::event_stream<FolderUpdate> _folderUpdates;
|
||||
rpl::event_stream<DialogsRowReplacement> _dialogsRowReplacements;
|
||||
|
||||
rpl::event_stream<> _stickersUpdated;
|
||||
|
@ -773,16 +770,9 @@ private:
|
|||
Stickers::Order _archivedStickerSetsOrder;
|
||||
Stickers::SavedGifs _savedGifs;
|
||||
|
||||
int _unreadFull = 0;
|
||||
int _unreadMuted = 0;
|
||||
int _unreadEntriesFull = 0;
|
||||
int _unreadEntriesMuted = 0;
|
||||
|
||||
Dialogs::IndexedList _chatsList;
|
||||
Dialogs::IndexedList _importantChatsList;
|
||||
Dialogs::MainList _chatsList;
|
||||
Dialogs::IndexedList _contactsList;
|
||||
Dialogs::IndexedList _contactsNoChatsList;
|
||||
Dialogs::PinnedList _pinnedChatsList;
|
||||
|
||||
base::Timer _selfDestructTimer;
|
||||
std::vector<FullMsgId> _selfDestructItems;
|
||||
|
|
|
@ -77,7 +77,7 @@ void Entry::cacheProxyPromoted(bool promoted) {
|
|||
}
|
||||
|
||||
bool Entry::needUpdateInChatList() const {
|
||||
return inChatList(Dialogs::Mode::All) || shouldBeInChatList();
|
||||
return inChatList() || shouldBeInChatList();
|
||||
}
|
||||
|
||||
void Entry::updateChatListSortPosition() {
|
||||
|
@ -102,6 +102,10 @@ void Entry::updateChatListExistence() {
|
|||
setChatListExistence(shouldBeInChatList());
|
||||
}
|
||||
|
||||
void Entry::notifyUnreadStateChange(const UnreadState &wasState) {
|
||||
owner().unreadStateChanged(_key, wasState);
|
||||
}
|
||||
|
||||
void Entry::setChatListExistence(bool exists) {
|
||||
if (const auto main = App::main()) {
|
||||
if (exists && _sortKeyInChatList) {
|
||||
|
@ -117,9 +121,6 @@ TimeId Entry::adjustedChatListTimeId() const {
|
|||
return chatListTimeId();
|
||||
}
|
||||
|
||||
void Entry::changedInChatListHook(Dialogs::Mode list, bool added) {
|
||||
}
|
||||
|
||||
void Entry::changedChatListPinHook() {
|
||||
}
|
||||
|
||||
|
@ -160,7 +161,9 @@ int Entry::posInChatList(Dialogs::Mode list) const {
|
|||
not_null<Row*> Entry::addToChatList(Mode list) {
|
||||
if (!inChatList(list)) {
|
||||
chatListLinks(list) = myChatsList(list)->addToEnd(_key);
|
||||
changedInChatListHook(list, true);
|
||||
if (list == Mode::All) {
|
||||
owner().unreadEntryChanged(_key, true);
|
||||
}
|
||||
}
|
||||
return mainChatListLink(list);
|
||||
}
|
||||
|
@ -169,7 +172,9 @@ void Entry::removeFromChatList(Dialogs::Mode list) {
|
|||
if (inChatList(list)) {
|
||||
myChatsList(list)->del(_key);
|
||||
chatListLinks(list).clear();
|
||||
changedInChatListHook(list, false);
|
||||
if (list == Mode::All) {
|
||||
owner().unreadEntryChanged(_key, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +199,7 @@ void Entry::addChatListEntryByLetter(
|
|||
|
||||
void Entry::updateChatListEntry() const {
|
||||
if (const auto main = App::main()) {
|
||||
if (inChatList(Mode::All)) {
|
||||
if (inChatList()) {
|
||||
main->repaintDialogRow(
|
||||
Mode::All,
|
||||
mainChatListLink(Mode::All));
|
||||
|
@ -212,10 +217,7 @@ void Entry::updateChatListEntry() const {
|
|||
}
|
||||
|
||||
not_null<IndexedList*> Entry::myChatsList(Mode list) const {
|
||||
if (const auto current = folder()) {
|
||||
return current->chatsList(list);
|
||||
}
|
||||
return owner().chatsList(list);
|
||||
return owner().chatsList(folder())->indexed(list);
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -40,6 +40,15 @@ struct PositionChange {
|
|||
int to = -1;
|
||||
};
|
||||
|
||||
struct UnreadState {
|
||||
std::optional<int> messagesCount;
|
||||
int messagesCountMuted = 0;
|
||||
int chatsCount = 0;
|
||||
int chatsCountMuted = 0;
|
||||
bool mark = false;
|
||||
bool markMuted = false;
|
||||
};
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
Entry(not_null<Data::Session*> owner, const Key &key);
|
||||
|
@ -51,7 +60,7 @@ public:
|
|||
AuthSession &session() const;
|
||||
|
||||
PositionChange adjustByPosInChatList(Mode list);
|
||||
bool inChatList(Mode list) const {
|
||||
bool inChatList(Mode list = Mode::All) const {
|
||||
return !chatListLinks(list).empty();
|
||||
}
|
||||
int posInChatList(Mode list) const;
|
||||
|
@ -89,6 +98,7 @@ public:
|
|||
virtual int chatListUnreadCount() const = 0;
|
||||
virtual bool chatListUnreadMark() const = 0;
|
||||
virtual bool chatListMutedBadge() const = 0;
|
||||
virtual UnreadState chatListUnreadState() const = 0;
|
||||
virtual HistoryItem *chatListMessage() const = 0;
|
||||
virtual bool chatListMessageKnown() const = 0;
|
||||
virtual void requestChatListMessage() = 0;
|
||||
|
@ -125,10 +135,22 @@ public:
|
|||
mutable const HistoryItem *textCachedFor = nullptr; // cache
|
||||
mutable Text lastItemTextCache;
|
||||
|
||||
protected:
|
||||
auto unreadStateChangeNotifier(bool required) {
|
||||
const auto notify = required && inChatList();
|
||||
const auto wasState = notify ? chatListUnreadState() : UnreadState();
|
||||
return gsl::finally([=] {
|
||||
if (notify) {
|
||||
notifyUnreadStateChange(wasState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void changedInChatListHook(Mode list, bool added);
|
||||
virtual void changedChatListPinHook();
|
||||
|
||||
void notifyUnreadStateChange(const UnreadState &wasState);
|
||||
|
||||
void setChatListExistence(bool exists);
|
||||
RowsByLetter &chatListLinks(Mode list);
|
||||
const RowsByLetter &chatListLinks(Mode list) const;
|
||||
|
|
|
@ -96,6 +96,14 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
|||
|
||||
subscribe(session().downloaderTaskFinished(), [=] { update(); });
|
||||
|
||||
subscribe(session().notifications().settingsChanged(), [=](
|
||||
Window::Notifications::ChangeType change) {
|
||||
if (change == Window::Notifications::ChangeType::CountMessages) {
|
||||
// Folder rows change their unread badge with this setting.
|
||||
update();
|
||||
}
|
||||
});
|
||||
|
||||
session().data().contactsLoaded().changes(
|
||||
) | rpl::start_with_next([=] {
|
||||
refresh();
|
||||
|
@ -143,8 +151,9 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
|||
) | rpl::filter([=](Data::Folder *folder) {
|
||||
return (folder == _openedFolder);
|
||||
}) | rpl::start_with_next([=] {
|
||||
const auto mode = Global::DialogsMode();
|
||||
if (_openedFolder
|
||||
&& _openedFolder->chatsList(Global::DialogsMode())->empty()) {
|
||||
&& _openedFolder->chatsList()->indexed(mode)->empty()) {
|
||||
_openedFolder->updateChatListSortPosition();
|
||||
cancelFolder();
|
||||
} else {
|
||||
|
@ -188,10 +197,6 @@ DialogsInner::DialogsInner(QWidget *parent, not_null<Window::Controller*> contro
|
|||
}
|
||||
}
|
||||
}));
|
||||
session().data().folderUpdated(
|
||||
) | rpl::start_with_next([=](const Data::FolderUpdate &update) {
|
||||
updateDialogRow({ update.folder, FullMsgId() });
|
||||
}, lifetime());
|
||||
|
||||
_controller->activeChatEntryValue(
|
||||
) | rpl::combine_previous(
|
||||
|
@ -218,8 +223,7 @@ void DialogsInner::handleChatMigration(not_null<ChatData*> chat) {
|
|||
|
||||
if (const auto from = chat->owner().historyLoaded(chat)) {
|
||||
if (const auto to = chat->owner().historyLoaded(channel)) {
|
||||
if (to->inChatList(Dialogs::Mode::All)
|
||||
&& from->inChatList(Dialogs::Mode::All)) {
|
||||
if (to->inChatList() && from->inChatList()) {
|
||||
removeDialog(from);
|
||||
}
|
||||
}
|
||||
|
@ -227,8 +231,11 @@ void DialogsInner::handleChatMigration(not_null<ChatData*> chat) {
|
|||
}
|
||||
|
||||
int DialogsInner::dialogsOffset() const {
|
||||
return (_openedFolder ? openedFolderSkip() : 0)
|
||||
+ (_importantSwitch ? st::dialogsImportantBarHeight : 0);
|
||||
return _openedFolder
|
||||
? openedFolderSkip()
|
||||
: _importantSwitch
|
||||
? st::dialogsImportantBarHeight
|
||||
: 0;
|
||||
}
|
||||
|
||||
int DialogsInner::proxyPromotedCount() const {
|
||||
|
@ -298,6 +305,9 @@ bool DialogsInner::changeOpenedFolder(Data::Folder *folder) {
|
|||
Ui::DialogTextOptions());
|
||||
}
|
||||
refresh();
|
||||
if (_loadMoreCallback) {
|
||||
_loadMoreCallback();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -320,7 +330,7 @@ void DialogsInner::paintEvent(QPaintEvent *e) {
|
|||
}
|
||||
if (_state == State::Default) {
|
||||
auto rows = shownDialogs();
|
||||
if (_importantSwitch) {
|
||||
if (!_openedFolder && _importantSwitch) {
|
||||
auto selected = isPressed() ? _importantSwitchPressed : _importantSwitchSelected;
|
||||
Dialogs::Layout::paintImportantSwitch(p, Global::DialogsMode(), fullWidth, selected);
|
||||
dialogsClip.translate(0, -st::dialogsImportantBarHeight);
|
||||
|
@ -807,12 +817,21 @@ void DialogsInner::selectByMouse(QPoint globalPosition) {
|
|||
_mouseSelection = true;
|
||||
_lastMousePosition = globalPosition;
|
||||
|
||||
int w = width(), mouseY = local.y();
|
||||
const auto w = width();
|
||||
const auto mouseY = local.y();
|
||||
clearIrrelevantState();
|
||||
if (_state == State::Default) {
|
||||
auto importantSwitchSelected = (_importantSwitch && mouseY >= 0 && mouseY < dialogsOffset());
|
||||
mouseY -= dialogsOffset();
|
||||
auto selected = importantSwitchSelected ? nullptr : (mouseY >= 0 ? shownDialogs()->rowAtY(mouseY, st::dialogsRowHeight) : nullptr);
|
||||
const auto switchTop = _openedFolder ? openedFolderSkip() : 0;
|
||||
const auto switchBottom = dialogsOffset();
|
||||
const auto importantSwitchSelected = _importantSwitch
|
||||
&& !_openedFolder
|
||||
&& (mouseY >= switchTop)
|
||||
&& (mouseY < switchBottom);
|
||||
const auto selected = importantSwitchSelected
|
||||
? nullptr
|
||||
: (mouseY >= switchBottom)
|
||||
? shownDialogs()->rowAtY(mouseY - switchBottom, st::dialogsRowHeight)
|
||||
: nullptr;
|
||||
if (_selected != selected || _importantSwitchSelected != importantSwitchSelected) {
|
||||
updateSelectedRow();
|
||||
_selected = selected;
|
||||
|
@ -945,8 +964,7 @@ void DialogsInner::checkReorderPinnedStart(QPoint localPosition) {
|
|||
if (updateReorderIndexGetCount() < 2) {
|
||||
_dragging = nullptr;
|
||||
} else {
|
||||
const auto folderId = _openedFolder ? _openedFolder->id() : 0;
|
||||
const auto &order = session().data().pinnedChatsOrder(folderId);
|
||||
const auto &order = session().data().pinnedChatsOrder(_openedFolder);
|
||||
_pinnedOnDragStart = base::flat_set<Dialogs::Key>{
|
||||
order.begin(),
|
||||
order.end()
|
||||
|
@ -989,8 +1007,7 @@ int DialogsInner::countPinnedIndex(Dialogs::Row *ofRow) {
|
|||
}
|
||||
|
||||
void DialogsInner::savePinnedOrder() {
|
||||
const auto folderId = _openedFolder ? _openedFolder->id() : 0;
|
||||
const auto &newOrder = session().data().pinnedChatsOrder(folderId);
|
||||
const auto &newOrder = session().data().pinnedChatsOrder(_openedFolder);
|
||||
if (newOrder.size() != _pinnedOnDragStart.size()) {
|
||||
return; // Something has changed in the set of pinned chats.
|
||||
}
|
||||
|
@ -999,7 +1016,7 @@ void DialogsInner::savePinnedOrder() {
|
|||
return; // Something has changed in the set of pinned chats.
|
||||
}
|
||||
}
|
||||
session().api().savePinnedOrder(folderId);
|
||||
session().api().savePinnedOrder(_openedFolder);
|
||||
}
|
||||
|
||||
void DialogsInner::finishReorderPinned() {
|
||||
|
@ -1513,7 +1530,8 @@ void DialogsInner::updateSelectedRow(Dialogs::Key key) {
|
|||
} else if (_selected) {
|
||||
update(0, dialogsOffset() + _selected->pos() * st::dialogsRowHeight, width(), st::dialogsRowHeight);
|
||||
} else if (_importantSwitchSelected) {
|
||||
update(0, 0, width(), st::dialogsImportantBarHeight);
|
||||
const auto switchTop = _openedFolder ? openedFolderSkip() : 0;
|
||||
update(0, switchTop, width(), st::dialogsImportantBarHeight);
|
||||
}
|
||||
} else if (_state == State::Filtered) {
|
||||
if (key) {
|
||||
|
@ -1536,9 +1554,8 @@ void DialogsInner::updateSelectedRow(Dialogs::Key key) {
|
|||
}
|
||||
|
||||
not_null<Dialogs::IndexedList*> DialogsInner::shownDialogs() const {
|
||||
return _openedFolder
|
||||
? _openedFolder->chatsList(Global::DialogsMode())
|
||||
: session().data().chatsList(Global::DialogsMode());
|
||||
const auto mode = Global::DialogsMode();
|
||||
return session().data().chatsList(_openedFolder)->indexed(mode);
|
||||
}
|
||||
|
||||
void DialogsInner::leaveEventHook(QEvent *e) {
|
||||
|
@ -1676,7 +1693,7 @@ void DialogsInner::applyFilterUpdate(QString newFilter, bool force) {
|
|||
_filterResultsGlobal.clear();
|
||||
if (!_searchInChat && !words.isEmpty()) {
|
||||
const Dialogs::List *toFilter = nullptr;
|
||||
if (const auto list = session().data().chatsList(Dialogs::Mode::All); !list->empty()) {
|
||||
if (const auto list = session().data().chatsList()->indexed(); !list->empty()) {
|
||||
for (fi = fb; fi != fe; ++fi) {
|
||||
const auto found = list->filtered(fi->at(0));
|
||||
if (!found || found->empty()) {
|
||||
|
@ -2001,7 +2018,7 @@ void DialogsInner::peerSearchReceived(
|
|||
for (const auto &mtpPeer : result) {
|
||||
if (const auto peer = session().data().peerLoaded(peerFromMTP(mtpPeer))) {
|
||||
if (const auto history = peer->owner().historyLoaded(peer)) {
|
||||
if (history->inChatList(Dialogs::Mode::All)) {
|
||||
if (history->inChatList()) {
|
||||
continue; // skip existing chats
|
||||
}
|
||||
}
|
||||
|
@ -2017,7 +2034,7 @@ void DialogsInner::peerSearchReceived(
|
|||
}
|
||||
|
||||
void DialogsInner::notify_historyMuteUpdated(History *history) {
|
||||
if (!_importantSwitch || !history->inChatList(Dialogs::Mode::All)) {
|
||||
if (!_importantSwitch || !history->inChatList()) {
|
||||
return;
|
||||
}
|
||||
refreshDialog(history);
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Dialogs {
|
|||
|
||||
enum class SortMode;
|
||||
|
||||
class List {
|
||||
class List final {
|
||||
public:
|
||||
List(SortMode sortMode);
|
||||
List(const List &other) = delete;
|
||||
|
|
130
Telegram/SourceFiles/dialogs/dialogs_main_list.cpp
Normal file
130
Telegram/SourceFiles/dialogs/dialogs_main_list.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
|
||||
#include "observer_peer.h"
|
||||
#include "history/history.h"
|
||||
|
||||
namespace Dialogs {
|
||||
namespace {
|
||||
|
||||
UnreadState ApplyMarkToCounters(const UnreadState &state) {
|
||||
auto result = UnreadState();
|
||||
const auto count = state.messagesCount.value_or(0);
|
||||
result.messagesCount = (count > 0)
|
||||
? count
|
||||
: state.mark
|
||||
? 1
|
||||
: 0;
|
||||
result.messagesCountMuted = (state.messagesCountMuted > 0)
|
||||
? state.messagesCountMuted
|
||||
: state.markMuted
|
||||
? 1
|
||||
: 0;
|
||||
result.chatsCount = (state.chatsCount > 0)
|
||||
? state.chatsCount
|
||||
: state.mark
|
||||
? 1
|
||||
: 0;
|
||||
result.chatsCountMuted = (state.chatsCountMuted > 0)
|
||||
? state.chatsCountMuted
|
||||
: state.markMuted
|
||||
? 1
|
||||
: 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MainList::MainList(rpl::producer<int> pinnedLimit)
|
||||
: _all(SortMode::Date)
|
||||
, _important(SortMode::Date)
|
||||
, _pinned(1) {
|
||||
_unreadState.messagesCount = 0;
|
||||
|
||||
std::move(
|
||||
pinnedLimit
|
||||
) | rpl::start_with_next([=](int limit) {
|
||||
_pinned.setLimit(limit);
|
||||
}, _lifetime);
|
||||
|
||||
Notify::PeerUpdateViewer(
|
||||
Notify::PeerUpdate::Flag::NameChanged
|
||||
) | rpl::start_with_next([=](const Notify::PeerUpdate &update) {
|
||||
const auto peer = update.peer;
|
||||
const auto &oldLetters = update.oldNameFirstLetters;
|
||||
_all.peerNameChanged(Mode::All, peer, oldLetters);
|
||||
_important.peerNameChanged(Mode::Important, peer, oldLetters);
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
bool MainList::empty() const {
|
||||
return _all.empty();
|
||||
}
|
||||
|
||||
bool MainList::loaded() const {
|
||||
return _loaded;
|
||||
}
|
||||
|
||||
void MainList::setLoaded(bool loaded) {
|
||||
_loaded = loaded;
|
||||
}
|
||||
|
||||
void MainList::clear() {
|
||||
_all.clear();
|
||||
_important.clear();
|
||||
_unreadState = UnreadState();
|
||||
}
|
||||
|
||||
void MainList::unreadStateChanged(
|
||||
const UnreadState &wasState,
|
||||
const UnreadState &nowState) {
|
||||
const auto wasWithMark = ApplyMarkToCounters(wasState);
|
||||
const auto nowWithMark = ApplyMarkToCounters(nowState);
|
||||
*_unreadState.messagesCount += *nowWithMark.messagesCount
|
||||
- *wasWithMark.messagesCount;
|
||||
_unreadState.messagesCountMuted += nowWithMark.messagesCountMuted
|
||||
- wasWithMark.messagesCountMuted;
|
||||
_unreadState.chatsCount += nowWithMark.chatsCount
|
||||
- wasWithMark.chatsCount;
|
||||
_unreadState.chatsCountMuted += nowWithMark.chatsCountMuted
|
||||
- wasWithMark.chatsCountMuted;
|
||||
}
|
||||
|
||||
void MainList::unreadEntryChanged(
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added) {
|
||||
const auto withMark = ApplyMarkToCounters(state);
|
||||
const auto delta = (added ? 1 : -1);
|
||||
*_unreadState.messagesCount += delta * *withMark.messagesCount;
|
||||
_unreadState.messagesCountMuted += delta * withMark.messagesCountMuted;
|
||||
_unreadState.chatsCount += delta * withMark.chatsCount;
|
||||
_unreadState.chatsCountMuted += delta * withMark.chatsCountMuted;
|
||||
}
|
||||
|
||||
UnreadState MainList::unreadState() const {
|
||||
return _unreadState;
|
||||
}
|
||||
|
||||
not_null<IndexedList*> MainList::indexed(Mode list) {
|
||||
return (list == Mode::All) ? &_all : &_important;
|
||||
}
|
||||
|
||||
not_null<const IndexedList*> MainList::indexed(Mode list) const {
|
||||
return (list == Mode::All) ? &_all : &_important;
|
||||
}
|
||||
|
||||
not_null<PinnedList*> MainList::pinned() {
|
||||
return &_pinned;
|
||||
}
|
||||
|
||||
not_null<const PinnedList*> MainList::pinned() const {
|
||||
return &_pinned;
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
49
Telegram/SourceFiles/dialogs/dialogs_main_list.h
Normal file
49
Telegram/SourceFiles/dialogs/dialogs_main_list.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "dialogs/dialogs_pinned_list.h"
|
||||
|
||||
namespace Dialogs {
|
||||
|
||||
class MainList final {
|
||||
public:
|
||||
explicit MainList(rpl::producer<int> pinnedLimit);
|
||||
|
||||
bool empty() const;
|
||||
bool loaded() const;
|
||||
void setLoaded(bool loaded = true);
|
||||
void clear();
|
||||
|
||||
void unreadStateChanged(
|
||||
const UnreadState &wasState,
|
||||
const UnreadState &nowState);
|
||||
void unreadEntryChanged(
|
||||
const Dialogs::UnreadState &state,
|
||||
bool added);
|
||||
UnreadState unreadState() const;
|
||||
|
||||
not_null<IndexedList*> indexed(Mode list = Mode::All);
|
||||
not_null<const IndexedList*> indexed(Mode list = Mode::All) const;
|
||||
not_null<PinnedList*> pinned();
|
||||
not_null<const PinnedList*> pinned() const;
|
||||
|
||||
private:
|
||||
IndexedList _all;
|
||||
IndexedList _important;
|
||||
PinnedList _pinned;
|
||||
UnreadState _unreadState;
|
||||
|
||||
bool _loaded = false;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
} // namespace Dialogs
|
|
@ -41,7 +41,7 @@ int PinnedList::addPinnedGetPosition(const Key &key) {
|
|||
applyLimit(_limit - 1);
|
||||
const auto position = int(_data.size());
|
||||
_data.push_back(key);
|
||||
key.entry()->cachePinnedIndex(position);
|
||||
key.entry()->cachePinnedIndex(position + 1);
|
||||
return position;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Dialogs {
|
|||
|
||||
class Key;
|
||||
|
||||
class PinnedList {
|
||||
class PinnedList final {
|
||||
public:
|
||||
explicit PinnedList(int limit);
|
||||
|
||||
|
|
|
@ -248,9 +248,8 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null<Window::Controller*> cont
|
|||
onSearchMore();
|
||||
} else {
|
||||
const auto folder = _inner->shownFolder();
|
||||
const auto folderId = folder ? folder->id() : FolderId(0);
|
||||
if (!folderId || !folder->chatsListLoaded()) {
|
||||
session().api().requestDialogs(folderId);
|
||||
if (!folder || !folder->chatsListLoaded()) {
|
||||
session().api().requestDialogs(folder);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -378,13 +377,13 @@ void DialogsWidget::activate() {
|
|||
}
|
||||
|
||||
void DialogsWidget::refreshDialog(Dialogs::Key key) {
|
||||
const auto creating = !key.entry()->inChatList(Dialogs::Mode::All);
|
||||
const auto creating = !key.entry()->inChatList();
|
||||
_inner->refreshDialog(key);
|
||||
const auto history = key.history();
|
||||
if (creating && history && history->peer->migrateFrom()) {
|
||||
if (const auto migrated = history->owner().historyLoaded(
|
||||
history->peer->migrateFrom())) {
|
||||
if (migrated->inChatList(Dialogs::Mode::All)) {
|
||||
if (migrated->inChatList()) {
|
||||
_inner->removeDialog(migrated);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1610,98 +1610,69 @@ int History::unreadCountForBadge() const {
|
|||
}
|
||||
|
||||
bool History::unreadCountKnown() const {
|
||||
return !!_unreadCount;
|
||||
return _unreadCount.has_value();
|
||||
}
|
||||
|
||||
void History::setUnreadCount(int newUnreadCount) {
|
||||
if (!_unreadCount || *_unreadCount != newUnreadCount) {
|
||||
const auto wasUnread = _unreadMark || unreadCount();
|
||||
const auto unreadCountDelta = _unreadCount | [&](int count) {
|
||||
return newUnreadCount - count;
|
||||
};
|
||||
if (newUnreadCount == 1) {
|
||||
if (loadedAtBottom()) {
|
||||
_firstUnreadView = !isEmpty()
|
||||
? blocks.back()->messages.back().get()
|
||||
: nullptr;
|
||||
}
|
||||
if (const auto last = msgIdForRead()) {
|
||||
setInboxReadTill(last - 1);
|
||||
}
|
||||
} else if (!newUnreadCount) {
|
||||
_firstUnreadView = nullptr;
|
||||
if (const auto last = msgIdForRead()) {
|
||||
setInboxReadTill(last);
|
||||
}
|
||||
} else {
|
||||
if (!_firstUnreadView && !_unreadBarView && loadedAtBottom()) {
|
||||
calculateFirstUnreadMessage();
|
||||
}
|
||||
}
|
||||
const auto unreadMarkDelta = [&] {
|
||||
if (_unreadMark) {
|
||||
const auto was = _unreadCount && (*_unreadCount > 0);
|
||||
const auto now = (newUnreadCount > 0);
|
||||
if (was != now) {
|
||||
return was ? 1 : -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}();
|
||||
_unreadCount = newUnreadCount;
|
||||
Expects(folderKnown());
|
||||
|
||||
if (_unreadBarView) {
|
||||
const auto count = chatListUnreadCount();
|
||||
if (count > 0) {
|
||||
_unreadBarView->setUnreadBarCount(count);
|
||||
} else {
|
||||
_unreadBarView->setUnreadBarFreezed();
|
||||
}
|
||||
}
|
||||
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
const auto delta = unreadMarkDelta + (unreadCountDelta
|
||||
? *unreadCountDelta
|
||||
: newUnreadCount);
|
||||
owner().unreadIncrement(delta, mute());
|
||||
|
||||
const auto nowUnread = (*_unreadCount > 0) || _unreadMark;
|
||||
const auto entriesDelta = (wasUnread && !nowUnread)
|
||||
? -1
|
||||
: (nowUnread && !wasUnread)
|
||||
? 1
|
||||
: 0;
|
||||
owner().unreadEntriesChanged(
|
||||
entriesDelta,
|
||||
mute() ? entriesDelta : 0);
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
if (_unreadCount == newUnreadCount) {
|
||||
return;
|
||||
}
|
||||
const auto notifier = unreadStateChangeNotifier(true);
|
||||
|
||||
_unreadCount = newUnreadCount;
|
||||
|
||||
if (newUnreadCount == 1) {
|
||||
if (loadedAtBottom()) {
|
||||
_firstUnreadView = !isEmpty()
|
||||
? blocks.back()->messages.back().get()
|
||||
: nullptr;
|
||||
}
|
||||
if (const auto last = msgIdForRead()) {
|
||||
setInboxReadTill(last - 1);
|
||||
}
|
||||
} else if (!newUnreadCount) {
|
||||
_firstUnreadView = nullptr;
|
||||
if (const auto last = msgIdForRead()) {
|
||||
setInboxReadTill(last);
|
||||
}
|
||||
} else {
|
||||
if (!_firstUnreadView && !_unreadBarView && loadedAtBottom()) {
|
||||
calculateFirstUnreadMessage();
|
||||
}
|
||||
}
|
||||
if (_unreadBarView) {
|
||||
const auto count = chatListUnreadCount();
|
||||
if (count > 0) {
|
||||
_unreadBarView->setUnreadBarCount(count);
|
||||
} else {
|
||||
_unreadBarView->setUnreadBarFreezed();
|
||||
}
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
}
|
||||
|
||||
void History::setUnreadMark(bool unread) {
|
||||
if (clearUnreadOnClientSide()) {
|
||||
unread = false;
|
||||
}
|
||||
if (_unreadMark != unread) {
|
||||
_unreadMark = unread;
|
||||
if (!_unreadCount || !*_unreadCount) {
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
const auto delta = _unreadMark ? 1 : -1;
|
||||
owner().unreadIncrement(delta, mute());
|
||||
owner().unreadEntriesChanged(
|
||||
delta,
|
||||
mute() ? delta : 0);
|
||||
|
||||
updateChatListEntry();
|
||||
}
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
if (_unreadMark == unread) {
|
||||
return;
|
||||
}
|
||||
const auto noUnreadMessages = !unreadCount();
|
||||
const auto notifier = unreadStateChangeNotifier(noUnreadMessages);
|
||||
|
||||
_unreadMark = unread;
|
||||
|
||||
if (inChatList() && noUnreadMessages) {
|
||||
updateChatListEntry();
|
||||
}
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::UnreadViewChanged);
|
||||
}
|
||||
|
||||
bool History::unreadMark() const {
|
||||
|
@ -1728,38 +1699,15 @@ bool History::changeMute(bool newMute) {
|
|||
if (_mute == newMute) {
|
||||
return false;
|
||||
}
|
||||
const auto notify = (unreadCountForBadge() > 0);
|
||||
const auto notifier = unreadStateChangeNotifier(notify);
|
||||
|
||||
_mute = newMute;
|
||||
|
||||
//const auto feed = peer->isChannel() // #feed
|
||||
// ? peer->asChannel()->feed()
|
||||
// : nullptr;
|
||||
//if (feed) {
|
||||
// if (_unreadCount) {
|
||||
// if (*_unreadCount) {
|
||||
// const auto unreadCountDelta = 0;
|
||||
// const auto mutedCountDelta = _mute ? *_unreadCount : -*_unreadCount;
|
||||
// feed->unreadCountChanged(unreadCountDelta, mutedCountDelta);
|
||||
// }
|
||||
// } else {
|
||||
// session().api().requestDialogEntry(this);
|
||||
// session().api().requestDialogEntry(feed);
|
||||
// }
|
||||
//}
|
||||
if (inChatList(Dialogs::Mode::All)) {
|
||||
if (const auto count = unreadCountForBadge()) {
|
||||
owner().unreadMuteChanged(count, _mute);
|
||||
|
||||
const auto entriesWithUnreadDelta = 0;
|
||||
const auto mutedEntriesWithUnreadDelta = _mute ? 1 : -1;
|
||||
owner().unreadEntriesChanged(
|
||||
entriesWithUnreadDelta,
|
||||
mutedEntriesWithUnreadDelta);
|
||||
|
||||
Notify::unreadCounterUpdated();
|
||||
}
|
||||
if (inChatList()) {
|
||||
Notify::historyMuteUpdated(this);
|
||||
updateChatListEntry();
|
||||
}
|
||||
updateChatListEntry();
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
Notify::PeerUpdate::Flag::NotificationsEnabled);
|
||||
|
@ -1839,9 +1787,9 @@ void History::setFolderPointer(Data::Folder *folder) {
|
|||
owner().setChatPinned(this, false);
|
||||
}
|
||||
const auto wasKnown = folderKnown();
|
||||
const auto wasInAll = inChatList(Mode::All);
|
||||
const auto wasInImportant = wasInAll && inChatList(Mode::Important);
|
||||
if (wasInAll) {
|
||||
const auto wasInList = inChatList();
|
||||
const auto wasInImportant = wasInList && inChatList(Mode::Important);
|
||||
if (wasInList) {
|
||||
removeFromChatList(Mode::All);
|
||||
if (wasInImportant) {
|
||||
removeFromChatList(Mode::Important);
|
||||
|
@ -1852,7 +1800,7 @@ void History::setFolderPointer(Data::Folder *folder) {
|
|||
if (was) {
|
||||
was->unregisterOne(this);
|
||||
}
|
||||
if (wasInAll) {
|
||||
if (wasInList) {
|
||||
addToChatList(Mode::All);
|
||||
if (wasInImportant) {
|
||||
addToChatList(Mode::Important);
|
||||
|
@ -2068,6 +2016,18 @@ bool History::chatListMutedBadge() const {
|
|||
return mute();
|
||||
}
|
||||
|
||||
Dialogs::UnreadState History::chatListUnreadState() const {
|
||||
auto result = Dialogs::UnreadState();
|
||||
const auto count = _unreadCount.value_or(0);
|
||||
result.messagesCount = _unreadCount;
|
||||
result.messagesCountMuted = (_unreadCount && mute()) ? count : 0;
|
||||
result.chatsCount = count ? 1 : 0;
|
||||
result.chatsCountMuted = (count && mute()) ? 1 : 0;
|
||||
result.mark = _unreadMark;
|
||||
result.markMuted = mute() ? _unreadMark : false;
|
||||
return result;
|
||||
}
|
||||
|
||||
HistoryItem *History::chatListMessage() const {
|
||||
return _chatListMessage.value_or(nullptr);
|
||||
}
|
||||
|
@ -2482,8 +2442,16 @@ bool History::isServerSideUnread(not_null<const HistoryItem*> item) const {
|
|||
: (!_inboxReadBefore || (item->id >= *_inboxReadBefore));
|
||||
}
|
||||
|
||||
void History::applyDialog(FolderId requestFolderId, const MTPDdialog &data) {
|
||||
void History::applyDialog(
|
||||
Data::Folder *requestFolder,
|
||||
const MTPDdialog &data) {
|
||||
const auto folder = data.has_folder_id()
|
||||
? (data.vfolder_id.v
|
||||
? owner().folder(data.vfolder_id.v).get()
|
||||
: nullptr)
|
||||
: requestFolder;
|
||||
applyDialogFields(
|
||||
folder,
|
||||
data.vunread_count.v,
|
||||
data.vread_inbox_max_id.v,
|
||||
data.vread_outbox_max_id.v);
|
||||
|
@ -2512,15 +2480,6 @@ void History::applyDialog(FolderId requestFolderId, const MTPDdialog &data) {
|
|||
if (data.has_draft() && data.vdraft.type() == mtpc_draftMessage) {
|
||||
Data::applyPeerCloudDraft(peer->id, data.vdraft.c_draftMessage());
|
||||
}
|
||||
|
||||
const auto folderId = data.has_folder_id()
|
||||
? data.vfolder_id.v
|
||||
: requestFolderId;
|
||||
if (folderId) {
|
||||
setFolder(owner().folder(folderId));
|
||||
} else {
|
||||
clearFolder();
|
||||
}
|
||||
session().api().dialogEntryApplied(this);
|
||||
}
|
||||
|
||||
|
@ -2593,9 +2552,15 @@ bool History::skipUnreadUpdate() const {
|
|||
}
|
||||
|
||||
void History::applyDialogFields(
|
||||
Data::Folder *folder,
|
||||
int unreadCount,
|
||||
MsgId maxInboxRead,
|
||||
MsgId maxOutboxRead) {
|
||||
if (folder) {
|
||||
setFolder(folder);
|
||||
} else {
|
||||
clearFolder();
|
||||
}
|
||||
if (!skipUnreadUpdate()) {
|
||||
setUnreadCount(unreadCount);
|
||||
setInboxReadTill(maxInboxRead);
|
||||
|
@ -3089,19 +3054,6 @@ void History::applyGroupAdminChanges(
|
|||
}
|
||||
}
|
||||
|
||||
void History::changedInChatListHook(Dialogs::Mode list, bool added) {
|
||||
if (list == Dialogs::Mode::All) {
|
||||
if (const auto delta = unreadCountForBadge() * (added ? 1 : -1)) {
|
||||
owner().unreadIncrement(delta, mute());
|
||||
|
||||
const auto entriesDelta = added ? 1 : -1;
|
||||
owner().unreadEntriesChanged(
|
||||
entriesDelta,
|
||||
mute() ? entriesDelta : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void History::changedChatListPinHook() {
|
||||
Notify::peerUpdatedDelayed(
|
||||
peer,
|
||||
|
|
|
@ -191,9 +191,10 @@ public:
|
|||
bool lastMessageKnown() const;
|
||||
void unknownMessageDeleted(MsgId messageId);
|
||||
void applyDialogTopMessage(MsgId topMessageId);
|
||||
void applyDialog(FolderId requestFolderId, const MTPDdialog &data);
|
||||
void applyDialog(Data::Folder *requestFolder, const MTPDdialog &data);
|
||||
void applyPinnedUpdate(const MTPDupdateDialogPinned &data);
|
||||
void applyDialogFields(
|
||||
Data::Folder *folder,
|
||||
int unreadCount,
|
||||
MsgId maxInboxRead,
|
||||
MsgId maxOutboxRead);
|
||||
|
@ -299,6 +300,7 @@ public:
|
|||
int chatListUnreadCount() const override;
|
||||
bool chatListUnreadMark() const override;
|
||||
bool chatListMutedBadge() const override;
|
||||
Dialogs::UnreadState chatListUnreadState() const override;
|
||||
HistoryItem *chatListMessage() const override;
|
||||
bool chatListMessageKnown() const override;
|
||||
void requestChatListMessage() override;
|
||||
|
@ -417,7 +419,6 @@ private:
|
|||
void removeNotification(not_null<HistoryItem*> item);
|
||||
|
||||
TimeId adjustedChatListTimeId() const override;
|
||||
void changedInChatListHook(Dialogs::Mode list, bool added) override;
|
||||
void changedChatListPinHook() override;
|
||||
|
||||
void setInboxReadTill(MsgId upTo);
|
||||
|
|
|
@ -2872,16 +2872,16 @@ void MainWidget::gotChannelDifference(
|
|||
history->setNotLoadedAtBottom();
|
||||
session().api().requestChannelRangeDifference(history);
|
||||
}
|
||||
App::feedMsgs(data.vmessages, NewMessageLast);
|
||||
data.vdialog.match([&](const MTPDdialog &data) {
|
||||
if (data.has_pts()) {
|
||||
channel->ptsInit(data.vpts.v);
|
||||
}
|
||||
if (history) {
|
||||
history->applyDialog(data);
|
||||
}
|
||||
}, [&](const MTPDdialogFolder &) {
|
||||
});
|
||||
session().data().applyDialogs(
|
||||
nullptr,
|
||||
data.vmessages.v,
|
||||
QVector<MTPDialog>(1, data.vdialog));
|
||||
if (_history->peer() == channel) {
|
||||
_history->updateHistoryDownVisibility();
|
||||
_history->preloadHistoryIfNeeded();
|
||||
|
@ -4270,6 +4270,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
case mtpc_updatePinnedDialogs: {
|
||||
const auto &d = update.c_updatePinnedDialogs();
|
||||
const auto folderId = d.has_folder_id() ? d.vfolder_id.v : 0;
|
||||
const auto loaded = !folderId
|
||||
|| (session().data().folderLoaded(folderId) != nullptr);
|
||||
const auto folder = folderId
|
||||
? session().data().folder(folderId).get()
|
||||
: nullptr;
|
||||
const auto done = [&] {
|
||||
if (!d.has_order()) {
|
||||
return false;
|
||||
|
@ -4280,6 +4285,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
return !session().data().historyLoaded(
|
||||
peerFromMTP(data.vpeer));
|
||||
}, [&](const MTPDdialogPeerFolder &data) {
|
||||
if (folderId) {
|
||||
LOG(("API Error: "
|
||||
"updatePinnedDialogs has nested folders."));
|
||||
return true;
|
||||
}
|
||||
return !session().data().folderLoaded(data.vfolder_id.v);
|
||||
});
|
||||
};
|
||||
|
@ -4288,17 +4298,23 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
if (!allLoaded) {
|
||||
return false;
|
||||
}
|
||||
session().data().applyPinnedChats(folderId, order);
|
||||
session().data().applyPinnedChats(folder, order);
|
||||
return true;
|
||||
}();
|
||||
if (!done) {
|
||||
session().api().requestPinnedDialogs(folderId);
|
||||
session().api().requestPinnedDialogs(folder);
|
||||
}
|
||||
if (!loaded) {
|
||||
session().api().requestDialogEntry(folder);
|
||||
}
|
||||
} break;
|
||||
|
||||
case mtpc_updateDialogPinned: {
|
||||
const auto &d = update.c_updateDialogPinned();
|
||||
const auto folderId = d.has_folder_id() ? d.vfolder_id.v : 0;
|
||||
const auto folder = folderId
|
||||
? session().data().folder(folderId).get()
|
||||
: nullptr;
|
||||
const auto done = d.vpeer.match([&](const MTPDdialogPeer &data) {
|
||||
const auto id = peerFromMTP(data.vpeer);
|
||||
if (const auto history = session().data().historyLoaded(id)) {
|
||||
|
@ -4329,7 +4345,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
|
|||
return false;
|
||||
});
|
||||
if (!done) {
|
||||
session().api().requestPinnedDialogs(folderId);
|
||||
session().api().requestPinnedDialogs(folder);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
|
|
@ -94,13 +94,13 @@ private:
|
|||
|
||||
};
|
||||
|
||||
History *FindWastedPin(FolderId folderId) {
|
||||
const auto &order = Auth().data().pinnedChatsOrder(folderId);
|
||||
History *FindWastedPin(Data::Folder *folder) {
|
||||
const auto &order = Auth().data().pinnedChatsOrder(folder);
|
||||
for (const auto &pinned : order) {
|
||||
if (const auto history = pinned.history()) {
|
||||
if (history->peer->isChat()
|
||||
&& history->peer->asChat()->isDeactivated()
|
||||
&& !history->inChatList(Dialogs::Mode::All)) {
|
||||
&& !history->inChatList()) {
|
||||
return history;
|
||||
}
|
||||
}
|
||||
|
@ -116,17 +116,16 @@ bool PinnedLimitReached(Dialogs::Key key) {
|
|||
Expects(key.entry()->folderKnown());
|
||||
|
||||
const auto folder = key.entry()->folder();
|
||||
const auto folderId = folder ? folder->id() : 0;
|
||||
const auto pinnedCount = Auth().data().pinnedChatsCount(folderId);
|
||||
const auto pinnedMax = Auth().data().pinnedChatsLimit(folderId);
|
||||
const auto pinnedCount = Auth().data().pinnedChatsCount(folder);
|
||||
const auto pinnedMax = Auth().data().pinnedChatsLimit(folder);
|
||||
if (pinnedCount < pinnedMax) {
|
||||
return false;
|
||||
}
|
||||
// Some old chat, that was converted, maybe is still pinned.
|
||||
if (const auto wasted = FindWastedPin(folderId)) {
|
||||
if (const auto wasted = FindWastedPin(folder)) {
|
||||
Auth().data().setChatPinned(wasted, false);
|
||||
Auth().data().setChatPinned(key, true);
|
||||
Auth().api().savePinnedOrder(folderId);
|
||||
Auth().api().savePinnedOrder(folder);
|
||||
} else {
|
||||
auto errorText = lng_error_pinned_max(
|
||||
lt_count,
|
||||
|
|
|
@ -228,6 +228,8 @@
|
|||
<(src_loc)/dialogs/dialogs_layout.h
|
||||
<(src_loc)/dialogs/dialogs_list.cpp
|
||||
<(src_loc)/dialogs/dialogs_list.h
|
||||
<(src_loc)/dialogs/dialogs_main_list.cpp
|
||||
<(src_loc)/dialogs/dialogs_main_list.h
|
||||
<(src_loc)/dialogs/dialogs_pinned_list.cpp
|
||||
<(src_loc)/dialogs/dialogs_pinned_list.h
|
||||
<(src_loc)/dialogs/dialogs_row.cpp
|
||||
|
|
Loading…
Add table
Reference in a new issue