Replace dialogs mode with filters.

This commit is contained in:
John Preston 2020-02-07 13:43:12 +04:00
parent 98b947fbdf
commit 71f7aae948
28 changed files with 330 additions and 236 deletions

View File

@ -320,6 +320,8 @@ PRIVATE
data/data_auto_download.h
data/data_chat.cpp
data/data_chat.h
data/data_chat_filters.cpp
data/data_chat_filters.h
data/data_channel.cpp
data/data_channel.h
data/data_channel_admins.cpp

View File

@ -937,10 +937,7 @@ void ShareBox::Inner::changeCheckState(Chat *chat) {
const auto history = chat->peer->owner().history(chat->peer);
auto row = _chatsIndexed->getRow(history);
if (!row) {
const auto rowsByLetter = _chatsIndexed->addToEnd(history);
const auto it = rowsByLetter.find(0);
Assert(it != rowsByLetter.cend());
row = it->second;
row = _chatsIndexed->addToEnd(history).main;
}
chat = getChat(row);
if (!chat->checkbox.checked()) {

View File

@ -503,8 +503,8 @@ void Application::switchDebugMode() {
}
void Application::switchWorkMode() {
Global::SetDialogsModeEnabled(!Global::DialogsModeEnabled());
Global::SetDialogsMode(Dialogs::Mode::All);
Global::SetDialogsFiltersEnabled(!Global::DialogsFiltersEnabled());
Global::SetDialogsFilterId(0);
Local::writeUserSettings();
App::restart();
}

View File

@ -0,0 +1,53 @@
/*
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 "data/data_chat_filters.h"
#include "history/history.h"
#include "data/data_peer.h"
#include "data/data_user.h"
#include "data/data_chat.h"
#include "data/data_channel.h"
namespace Data {
ChatFilter::ChatFilter(
const QString &title,
Flags flags,
base::flat_set<not_null<History*>> always)
: _title(title)
, _always(std::move(always))
, _flags(flags) {
}
bool ChatFilter::contains(not_null<History*> history) const {
const auto flag = [&] {
const auto peer = history->peer;
if (const auto user = peer->asUser()) {
return user->isBot() ? Flag::Bots : Flag::Users;
} else if (const auto chat = peer->asChat()) {
return Flag::PrivateGroups;
} else if (const auto channel = peer->asChannel()) {
if (channel->isBroadcast()) {
return Flag::Broadcasts;
} else if (channel->isPublic()) {
return Flag::PublicGroups;
} else {
return Flag::PrivateGroups;
}
} else {
Unexpected("Peer type in ChatFilter::contains.");
}
}();
return false
|| ((_flags & flag)
&& (!(_flags & Flag::NoMuted) || !history->mute())
&& (!(_flags & Flag::NoRead) || history->unreadCountForBadge()))
|| _always.contains(history);
}
} // namespace Data

View File

@ -0,0 +1,45 @@
/*
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 "base/flags.h"
class History;
namespace Data {
class ChatFilter final {
public:
enum class Flag : uchar {
Users = 0x01,
PrivateGroups = 0x02,
PublicGroups = 0x04,
Broadcasts = 0x08,
Bots = 0x10,
NoMuted = 0x20,
NoRead = 0x40,
};
friend constexpr inline bool is_flag_type(Flag) { return true; };
using Flags = base::flags<Flag>;
ChatFilter() = default;
ChatFilter(
const QString &title,
Flags flags,
base::flat_set<not_null<History*>> always);
[[nodiscard]] bool contains(not_null<History*> history) const;
private:
QString _title;
base::flat_set<not_null<History*>> _always;
Flags _flags;
};
} // namespace Data

View File

@ -441,10 +441,6 @@ void Folder::unreadEntryChanged(
// return _unreadPosition.changes();
//}
bool Folder::toImportant() const {
return false;
}
int Folder::fixedOnTopIndex() const {
return kArchiveFixOnTopIndex;
}

View File

@ -58,7 +58,6 @@ public:
TimeId adjustedChatListTimeId() const override;
int fixedOnTopIndex() const override;
bool toImportant() const override;
bool shouldBeInChatList() const override;
int chatListUnreadCount() const override;
bool chatListUnreadMark() const override;

View File

@ -3363,25 +3363,25 @@ auto Session::refreshChatListEntry(Dialogs::Key key)
auto result = RefreshChatListEntryResult();
result.changed = !entry->inChatList();
if (result.changed) {
const auto mainRow = entry->addToChatList(Mode::All);
const auto mainRow = entry->addToChatList(0);
_contactsNoChatsList.del(key, mainRow);
} else {
result.moved = entry->adjustByPosInChatList(Mode::All);
}
if (Global::DialogsModeEnabled()) {
if (entry->toImportant()) {
result.importantChanged = !entry->inChatList(Mode::Important);
if (result.importantChanged) {
entry->addToChatList(Mode::Important);
} else {
result.importantMoved = entry->adjustByPosInChatList(
Mode::Important);
}
} else if (entry->inChatList(Mode::Important)) {
entry->removeFromChatList(Mode::Important);
result.importantChanged = true;
}
result.moved = entry->adjustByPosInChatList(0);
}
//if (Global::DialogsFiltersEnabled()) { // #TODO filters
// if (entry->toImportant()) {
// result.importantChanged = !entry->inChatList(Mode::Important);
// if (result.importantChanged) {
// entry->addToChatList(Mode::Important);
// } else {
// result.importantMoved = entry->adjustByPosInChatList(
// Mode::Important);
// }
// } else if (entry->inChatList(Mode::Important)) {
// entry->removeFromChatList(Mode::Important);
// result.importantChanged = true;
// }
//}
return result;
}
@ -3389,10 +3389,10 @@ void Session::removeChatListEntry(Dialogs::Key key) {
using namespace Dialogs;
const auto entry = key.entry();
entry->removeFromChatList(Mode::All);
if (Global::DialogsModeEnabled()) {
entry->removeFromChatList(Mode::Important);
}
entry->removeFromChatList(0);
//if (Global::DialogsFiltersEnabled()) { // #TODO filters
// entry->removeFromChatList(Mode::Important);
//}
if (_contactsList.contains(key)) {
if (!_contactsNoChatsList.contains(key)) {
_contactsNoChatsList.addByName(key);

View File

@ -128,6 +128,7 @@ using UserId = int32;
using ChatId = int32;
using ChannelId = int32;
using FolderId = int32;
using FilterId = int32;
constexpr auto NoChannel = ChannelId(0);

View File

@ -131,25 +131,33 @@ TimeId Entry::adjustedChatListTimeId() const {
void Entry::changedChatListPinHook() {
}
RowsByLetter &Entry::chatListLinks(Mode list) {
return _chatListLinks[static_cast<int>(list)];
RowsByLetter *Entry::chatListLinks(FilterId filterId) {
const auto i = _chatListLinks.find(filterId);
return (i != end(_chatListLinks)) ? &i->second : nullptr;
}
const RowsByLetter &Entry::chatListLinks(Mode list) const {
return _chatListLinks[static_cast<int>(list)];
const RowsByLetter *Entry::chatListLinks(FilterId filterId) const {
const auto i = _chatListLinks.find(filterId);
return (i != end(_chatListLinks)) ? &i->second : nullptr;
}
Row *Entry::mainChatListLink(Mode list) const {
auto it = chatListLinks(list).find(0);
Assert(it != chatListLinks(list).cend());
return it->second;
not_null<Row*> Entry::mainChatListLink(FilterId filterId) const {
const auto links = chatListLinks(filterId);
Assert(links != nullptr);
return links->main;
}
PositionChange Entry::adjustByPosInChatList(Mode list) {
const auto lnk = mainChatListLink(list);
const auto from = lnk->pos();
myChatsList(list)->adjustByDate(chatListLinks(list));
const auto to = lnk->pos();
Row *Entry::maybeMainChatListLink(FilterId filterId) const {
const auto links = chatListLinks(filterId);
return links ? links->main.get() : nullptr;
}
PositionChange Entry::adjustByPosInChatList(FilterId filterId) {
const auto links = chatListLinks(filterId);
Assert(links != nullptr);
const auto from = links->main->pos();
myChatsList(filterId)->adjustByDate(*links);
const auto to = links->main->pos();
return { from, to };
}
@ -161,60 +169,57 @@ void Entry::setChatListTimeId(TimeId date) {
}
}
int Entry::posInChatList(Dialogs::Mode list) const {
return mainChatListLink(list)->pos();
int Entry::posInChatList(FilterId filterId) const {
return mainChatListLink(filterId)->pos();
}
not_null<Row*> Entry::addToChatList(Mode list) {
if (!inChatList(list)) {
chatListLinks(list) = myChatsList(list)->addToEnd(_key);
if (list == Mode::All) {
owner().unreadEntryChanged(_key, true);
}
not_null<Row*> Entry::addToChatList(FilterId filterId) {
if (const auto main = maybeMainChatListLink(filterId)) {
return main;
}
return mainChatListLink(list);
const auto result = _chatListLinks.emplace(
filterId,
myChatsList(filterId)->addToEnd(_key)
).first->second.main;
if (!filterId) {
owner().unreadEntryChanged(_key, true);
}
return result;
}
void Entry::removeFromChatList(Dialogs::Mode list) {
if (inChatList(list)) {
myChatsList(list)->del(_key);
chatListLinks(list).clear();
if (list == Mode::All) {
owner().unreadEntryChanged(_key, false);
}
void Entry::removeFromChatList(FilterId filterId) {
const auto i = _chatListLinks.find(filterId);
if (i == end(_chatListLinks)) {
return;
}
myChatsList(filterId)->del(_key);
_chatListLinks.erase(i);
if (!filterId) {
owner().unreadEntryChanged(_key, false);
}
}
void Entry::removeChatListEntryByLetter(Mode list, QChar letter) {
Expects(letter != 0);
if (inChatList(list)) {
chatListLinks(list).remove(letter);
void Entry::removeChatListEntryByLetter(FilterId filterId, QChar letter) {
const auto i = _chatListLinks.find(filterId);
if (i != end(_chatListLinks)) {
i->second.letters.remove(letter);
}
}
void Entry::addChatListEntryByLetter(
Mode list,
FilterId filterId,
QChar letter,
not_null<Row*> row) {
Expects(letter != 0);
if (inChatList(list)) {
chatListLinks(list).emplace(letter, row);
const auto i = _chatListLinks.find(filterId);
if (i != end(_chatListLinks)) {
i->second.letters.emplace(letter, row);
}
}
void Entry::updateChatListEntry() const {
if (const auto main = App::main()) {
if (inChatList()) {
main->repaintDialogRow(
Mode::All,
mainChatListLink(Mode::All));
if (inChatList(Mode::Important)) {
main->repaintDialogRow(
Mode::Important,
mainChatListLink(Mode::Important));
}
for (const auto &[filterId, links] : _chatListLinks) {
main->repaintDialogRow(filterId, links.main);
}
if (session().supportMode()
&& !session().settings().supportAllSearchResults()) {
@ -223,8 +228,8 @@ void Entry::updateChatListEntry() const {
}
}
not_null<IndexedList*> Entry::myChatsList(Mode list) const {
return owner().chatsList(folder())->indexed(list);
not_null<IndexedList*> Entry::myChatsList(FilterId filterId) const {
return owner().chatsList(folder())->indexed(filterId);
}
} // namespace Dialogs

View File

@ -24,7 +24,11 @@ namespace Dialogs {
class Row;
class IndexedList;
using RowsByLetter = base::flat_map<QChar, not_null<Row*>>;
struct RowsByLetter {
not_null<Row*> main;
base::flat_map<QChar, not_null<Row*>> letters;
};
enum class SortMode {
Date = 0x00,
@ -32,11 +36,6 @@ enum class SortMode {
Add = 0x02,
};
enum class Mode {
All = 0x00,
Important = 0x01,
};
struct PositionChange {
int from = -1;
int to = -1;
@ -94,19 +93,19 @@ public:
Entry &operator=(const Entry &other) = delete;
virtual ~Entry() = default;
Data::Session &owner() const;
Main::Session &session() const;
[[nodiscard]] Data::Session &owner() const;
[[nodiscard]] Main::Session &session() const;
PositionChange adjustByPosInChatList(Mode list);
bool inChatList(Mode list = Mode::All) const {
return !chatListLinks(list).empty();
PositionChange adjustByPosInChatList(FilterId filterId);
[[nodiscard]] bool inChatList(FilterId filterId = 0) const {
return _chatListLinks.contains(filterId);
}
int posInChatList(Mode list) const;
not_null<Row*> addToChatList(Mode list);
void removeFromChatList(Mode list);
void removeChatListEntryByLetter(Mode list, QChar letter);
[[nodiscard]] int posInChatList(FilterId filterId) const;
not_null<Row*> addToChatList(FilterId filterId);
void removeFromChatList(FilterId filterId);
void removeChatListEntryByLetter(FilterId filterId, QChar letter);
void addChatListEntryByLetter(
Mode list,
FilterId filterId,
QChar letter,
not_null<Row*> row);
void updateChatListEntry() const;
@ -131,7 +130,6 @@ public:
static constexpr auto kArchiveFixOnTopIndex = 1;
static constexpr auto kProxyPromotionFixOnTopIndex = 2;
virtual bool toImportant() const = 0;
virtual bool shouldBeInChatList() const = 0;
virtual int chatListUnreadCount() const = 0;
virtual bool chatListUnreadMark() const = 0;
@ -190,15 +188,16 @@ private:
void notifyUnreadStateChange(const UnreadState &wasState);
void setChatListExistence(bool exists);
RowsByLetter &chatListLinks(Mode list);
const RowsByLetter &chatListLinks(Mode list) const;
Row *mainChatListLink(Mode list) const;
RowsByLetter *chatListLinks(FilterId filterId);
const RowsByLetter *chatListLinks(FilterId filterId) const;
not_null<Row*> mainChatListLink(FilterId filterId) const;
Row *maybeMainChatListLink(FilterId filterId) const;
not_null<IndexedList*> myChatsList(Mode list) const;
not_null<IndexedList*> myChatsList(FilterId filterId) const;
not_null<Data::Session*> _owner;
Dialogs::Key _key;
RowsByLetter _chatListLinks[2];
base::flat_map<FilterId, RowsByLetter> _chatListLinks;
uint64 _sortKeyInChatList = 0;
int _pinnedIndex = 0;
bool _isProxyPromoted = false;

View File

@ -20,16 +20,17 @@ IndexedList::IndexedList(SortMode sortMode)
}
RowsByLetter IndexedList::addToEnd(Key key) {
RowsByLetter result;
if (!_list.contains(key)) {
result.emplace(0, _list.addToEnd(key));
for (const auto ch : key.entry()->chatListFirstLetters()) {
auto j = _index.find(ch);
if (j == _index.cend()) {
j = _index.emplace(ch, _sortMode).first;
}
result.emplace(ch, j->second.addToEnd(key));
if (const auto row = _list.getRow(key)) {
return { row };
}
auto result = RowsByLetter{ _list.addToEnd(key) };
for (const auto ch : key.entry()->chatListFirstLetters()) {
auto j = _index.find(ch);
if (j == _index.cend()) {
j = _index.emplace(ch, _sortMode).first;
}
result.letters.emplace(ch, j->second.addToEnd(key));
}
return result;
}
@ -51,13 +52,10 @@ Row *IndexedList::addByName(Key key) {
}
void IndexedList::adjustByDate(const RowsByLetter &links) {
for (const auto [ch, row] : links) {
if (ch == QChar(0)) {
_list.adjustByDate(row);
} else {
if (auto it = _index.find(ch); it != _index.cend()) {
it->second.adjustByDate(row);
}
_list.adjustByDate(links.main);
for (const auto [ch, row] : links.letters) {
if (auto it = _index.find(ch); it != _index.cend()) {
it->second.adjustByDate(row);
}
}
}
@ -95,19 +93,19 @@ void IndexedList::peerNameChanged(
if (_sortMode == SortMode::Name) {
adjustByName(history, oldLetters);
} else {
adjustNames(Dialogs::Mode::All, history, oldLetters);
adjustNames(FilterId(), history, oldLetters);
}
}
}
void IndexedList::peerNameChanged(
Mode list,
FilterId filterId,
not_null<PeerData*> peer,
const base::flat_set<QChar> &oldLetters) {
Expects(_sortMode == SortMode::Date);
if (const auto history = peer->owner().historyLoaded(peer)) {
adjustNames(list, history, oldLetters);
adjustNames(filterId, history, oldLetters);
}
}
@ -149,7 +147,7 @@ void IndexedList::adjustByName(
}
void IndexedList::adjustNames(
Mode list,
FilterId filterId,
not_null<History*> history,
const base::flat_set<QChar> &oldLetters) {
const auto key = Dialogs::Key(history);
@ -168,7 +166,7 @@ void IndexedList::adjustNames(
}
for (auto ch : toRemove) {
if (_sortMode == SortMode::Date) {
history->removeChatListEntryByLetter(list, ch);
history->removeChatListEntryByLetter(filterId, ch);
}
if (auto it = _index.find(ch); it != _index.cend()) {
it->second.del(key, mainRow);
@ -181,7 +179,7 @@ void IndexedList::adjustNames(
}
auto row = j->second.addToEnd(key);
if (_sortMode == SortMode::Date) {
history->addChatListEntryByLetter(list, ch, row);
history->addChatListEntryByLetter(filterId, ch, row);
}
}
}
@ -250,8 +248,4 @@ std::vector<not_null<Row*>> IndexedList::filtered(
return result;
}
IndexedList::~IndexedList() {
clear();
}
} // namespace Dialogs

View File

@ -33,7 +33,7 @@ public:
//For sortMode == SortMode::Date
void peerNameChanged(
Mode list,
FilterId filterId,
not_null<PeerData*> peer,
const base::flat_set<QChar> &oldChars);
@ -49,8 +49,6 @@ public:
}
std::vector<not_null<Row*>> filtered(const QStringList &words) const;
~IndexedList();
// Part of List interface is duplicated here for all() list.
int size() const { return all().size(); }
bool empty() const { return all().empty(); }
@ -78,7 +76,7 @@ private:
Key key,
const base::flat_set<QChar> &oldChars);
void adjustNames(
Mode list,
FilterId filterId,
not_null<History*> history,
const base::flat_set<QChar> &oldChars);

View File

@ -118,9 +118,9 @@ InnerWidget::InnerWidget(
setAttribute(Qt::WA_OpaquePaintEvent, true);
#endif // OS_MAC_OLD
_mode = Global::DialogsModeEnabled()
? Global::DialogsMode()
: Dialogs::Mode::All;
_filterId = Global::DialogsFiltersEnabled()
? Global::DialogsFilterId()
: 0;
_addContactLnk->addClickHandler([] { App::wnd()->onShowAddContact(); });
_cancelSearchInChat->setClickedCallback([=] { cancelSearchInChat(); });
@ -280,7 +280,7 @@ void InnerWidget::refreshWithCollapsedRows(bool toTop) {
_collapsedSelected = -1;
_collapsedRows.clear();
if (!_openedFolder && Global::DialogsModeEnabled()) {
if (!_openedFolder && Global::DialogsFiltersEnabled()) {
_collapsedRows.push_back(std::make_unique<CollapsedRow>());
}
const auto list = shownDialogs();
@ -368,7 +368,7 @@ void InnerWidget::changeOpenedFolder(Data::Folder *folder) {
//const auto lastMousePosition = _lastMousePosition;
clearSelection();
_openedFolder = folder;
_mode = _openedFolder ? Mode::All : Global::DialogsMode();
_filterId = _openedFolder ? 0 : Global::DialogsFilterId();
refreshWithCollapsedRows(true);
// This doesn't work, because we clear selection in leaveEvent on hide.
//if (mouseSelection && lastMousePosition) {
@ -686,12 +686,12 @@ void InnerWidget::paintCollapsedRow(
const auto narrow = (width() <= smallWidth);
const auto text = row->folder
? row->folder->chatListName()
: (_mode == Dialogs::Mode::Important)
: _filterId // #TODO filters
? (narrow ? "Show" : tr::lng_dialogs_show_all_chats(tr::now))
: (narrow ? "Hide" : tr::lng_dialogs_hide_muted_chats(tr::now));
const auto unread = row->folder
? row->folder->chatListUnreadCount()
: (_mode == Dialogs::Mode::Important)
: _filterId // #TODO filters
? session().data().unreadOnlyMutedBadge()
: 0;
Layout::PaintCollapsedRow(
@ -1049,11 +1049,11 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
});
} else if (base::in_range(_filteredPressed, 0, _filterResults.size())) {
const auto row = _filterResults[_filteredPressed];
const auto list = _mode;
const auto filterId = _filterId;
row->addRipple(
e->pos() - QPoint(0, filteredOffset() + _filteredPressed * st::dialogsRowHeight),
QSize(width(), st::dialogsRowHeight),
[=] { repaintDialogRow(list, row); });
[=] { repaintDialogRow(filterId, row); });
} else if (base::in_range(_peerSearchPressed, 0, _peerSearchResults.size())) {
auto &result = _peerSearchResults[_peerSearchPressed];
auto row = &result->row;
@ -1435,10 +1435,10 @@ void InnerWidget::refreshDialog(Key key) {
}
const auto result = session().data().refreshChatListEntry(key);
const auto changed = (_mode == Mode::Important)
const auto changed = _filterId // #TODO filters
? result.importantChanged
: result.changed;
const auto moved = (_mode == Mode::Important)
const auto moved = _filterId // #TODO filters
? result.importantMoved
: result.moved;
@ -1511,17 +1511,17 @@ int InnerWidget::defaultRowTop(not_null<Row*> row) const {
}
void InnerWidget::repaintDialogRow(
Mode list,
FilterId filterId,
not_null<Row*> row) {
if (_state == WidgetState::Default) {
if (_mode == list) {
if (_filterId == filterId) {
if (const auto folder = row->folder()) {
repaintCollapsedFolderRow(folder);
}
update(0, defaultRowTop(row), width(), st::dialogsRowHeight);
}
} else if (_state == WidgetState::Filtered) {
if (list == Mode::All) {
if (!filterId) {
for (auto i = 0, l = int(_filterResults.size()); i != l; ++i) {
if (_filterResults[i]->key() == row->key()) {
update(
@ -1645,10 +1645,10 @@ void InnerWidget::updateSelectedRow(Key key) {
if (_state == WidgetState::Default) {
if (key) {
const auto entry = key.entry();
if (!entry->inChatList(_mode)) {
if (!entry->inChatList(_filterId)) {
return;
}
auto position = entry->posInChatList(_mode);
auto position = entry->posInChatList(_filterId);
auto top = dialogsOffset();
if (base::in_range(position, 0, _pinnedRows.size())) {
top += qRound(_pinnedRows[position].yadd.current());
@ -1680,7 +1680,7 @@ void InnerWidget::updateSelectedRow(Key key) {
}
not_null<IndexedList*> InnerWidget::shownDialogs() const {
return session().data().chatsList(_openedFolder)->indexed(_mode);
return session().data().chatsList(_openedFolder)->indexed(_filterId);
}
void InnerWidget::leaveEventHook(QEvent *e) {
@ -2137,7 +2137,8 @@ void InnerWidget::peerSearchReceived(
}
void InnerWidget::notify_historyMuteUpdated(History *history) {
if (!Global::DialogsModeEnabled() || !history->inChatList()) {
// #TODO filters
if (!Global::DialogsFiltersEnabled() || !history->inChatList()) {
return;
}
refreshDialog(history);
@ -2425,22 +2426,23 @@ void InnerWidget::scrollToEntry(const RowDescriptor &entry) {
void InnerWidget::selectSkipPage(int32 pixels, int32 direction) {
clearMouseSelection();
const auto list = shownDialogs();
int toSkip = pixels / int(st::dialogsRowHeight);
if (_state == WidgetState::Default) {
if (!_selected) {
if (direction > 0 && shownDialogs()->size() > _skipTopDialogs) {
_selected = *(shownDialogs()->cbegin() + _skipTopDialogs);
if (direction > 0 && list->size() > _skipTopDialogs) {
_selected = *(list->cbegin() + _skipTopDialogs);
_collapsedSelected = -1;
} else {
return;
}
}
if (direction > 0) {
for (auto i = shownDialogs()->cfind(_selected), end = shownDialogs()->cend(); i != end && (toSkip--); ++i) {
for (auto i = list->cfind(_selected), end = list->cend(); i != end && (toSkip--); ++i) {
_selected = *i;
}
} else {
for (auto i = shownDialogs()->cfind(_selected), b = shownDialogs()->cbegin(); i != b && (*i)->pos() > _skipTopDialogs && (toSkip--);) {
for (auto i = list->cfind(_selected), b = list->cbegin(); i != b && (*i)->pos() > _skipTopDialogs && (toSkip--);) {
_selected = *(--i);
}
if (toSkip && !_collapsedRows.empty()) {
@ -2463,12 +2465,13 @@ void InnerWidget::selectSkipPage(int32 pixels, int32 direction) {
void InnerWidget::loadPeerPhotos() {
if (!parentWidget()) return;
const auto list = shownDialogs();
auto yFrom = _visibleTop;
auto yTo = _visibleTop + (_visibleBottom - _visibleTop) * (PreloadHeightsCount + 1);
if (_state == WidgetState::Default) {
auto otherStart = shownDialogs()->size() * st::dialogsRowHeight;
auto otherStart = list->size() * st::dialogsRowHeight;
if (yFrom < otherStart) {
for (auto i = shownDialogs()->cfind(yFrom, st::dialogsRowHeight), end = shownDialogs()->cend(); i != end; ++i) {
for (auto i = list->cfind(yFrom, st::dialogsRowHeight), end = list->cend(); i != end; ++i) {
if (((*i)->pos() * st::dialogsRowHeight) >= yTo) {
break;
}
@ -2532,12 +2535,13 @@ bool InnerWidget::chooseCollapsedRow() {
void InnerWidget::switchImportantChats() {
clearSelection();
if (Global::DialogsMode() == Mode::All) {
Global::SetDialogsMode(Mode::Important);
} else {
Global::SetDialogsMode(Mode::All);
}
_mode = Global::DialogsMode();
// #TODO filters
//if (Global::DialogsFilterId() == 0) {
// Global::SetDialogsMode(Mode::Important);
//} else {
// Global::SetDialogsMode(Mode::All);
//}
_filterId = Global::DialogsFilterId();
Local::writeUserSettings();
refreshWithCollapsedRows(true);
_collapsedSelected = 0;
@ -2633,9 +2637,10 @@ RowDescriptor InnerWidget::chatListEntryBefore(
return RowDescriptor();
}
if (_state == WidgetState::Default) {
if (const auto row = shownDialogs()->getRow(which.key)) {
const auto i = shownDialogs()->cfind(row);
if (i != shownDialogs()->cbegin()) {
const auto list = shownDialogs();
if (const auto row = list->getRow(which.key)) {
const auto i = list->cfind(row);
if (i != list->cbegin()) {
return RowDescriptor(
(*(i - 1))->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
@ -2710,9 +2715,10 @@ RowDescriptor InnerWidget::chatListEntryAfter(
return RowDescriptor();
}
if (_state == WidgetState::Default) {
if (const auto row = shownDialogs()->getRow(which.key)) {
const auto i = shownDialogs()->cfind(row) + 1;
if (i != shownDialogs()->cend()) {
const auto list = shownDialogs();
if (const auto row = list->getRow(which.key)) {
const auto i = list->cfind(row) + 1;
if (i != list->cend()) {
return RowDescriptor(
(*i)->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
@ -2775,8 +2781,9 @@ RowDescriptor InnerWidget::chatListEntryAfter(
RowDescriptor InnerWidget::chatListEntryFirst() const {
if (_state == WidgetState::Default) {
const auto i = shownDialogs()->cbegin();
if (i != shownDialogs()->cend()) {
const auto list = shownDialogs();
const auto i = list->cbegin();
if (i != list->cend()) {
return RowDescriptor(
(*i)->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));
@ -2800,8 +2807,9 @@ RowDescriptor InnerWidget::chatListEntryFirst() const {
RowDescriptor InnerWidget::chatListEntryLast() const {
if (_state == WidgetState::Default) {
const auto i = shownDialogs()->cend();
if (i != shownDialogs()->cbegin()) {
const auto list = shownDialogs();
const auto i = list->cend();
if (i != list->cbegin()) {
return RowDescriptor(
(*(i - 1))->key(),
FullMsgId(NoChannel, ShowAtUnreadMsgId));

View File

@ -38,7 +38,6 @@ namespace Dialogs {
class Row;
class FakeRow;
class IndexedList;
enum class Mode;
struct ChosenRow {
Key key;
@ -89,7 +88,7 @@ public:
void refreshDialog(Key key);
void removeDialog(Key key);
void repaintDialogRow(Mode list, not_null<Row*> row);
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row);
void dragLeft();
@ -310,7 +309,7 @@ private:
not_null<Window::SessionController*> _controller;
Mode _mode = Mode();
FilterId _filterId = 0;
bool _mouseSelection = false;
std::optional<QPoint> _lastMousePosition;
Qt::MouseButton _pressButton = Qt::LeftButton;

View File

@ -14,7 +14,6 @@ namespace Dialogs {
MainList::MainList(rpl::producer<int> pinnedLimit)
: _all(SortMode::Date)
, _important(SortMode::Date)
, _pinned(1) {
_unreadState.known = true;
@ -29,8 +28,10 @@ MainList::MainList(rpl::producer<int> pinnedLimit)
) | 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);
_all.peerNameChanged(FilterId(), peer, oldLetters);
for (auto &[filterId, list] : _other) {
list.peerNameChanged(filterId, peer, oldLetters);
}
}, _lifetime);
}
@ -48,7 +49,9 @@ void MainList::setLoaded(bool loaded) {
void MainList::clear() {
_all.clear();
_important.clear();
for (auto &[filterId, list] : _other) { // #TODO filters _other.clear?..
list.clear();
}
_unreadState = UnreadState();
}
@ -72,12 +75,19 @@ UnreadState MainList::unreadState() const {
return _unreadState;
}
not_null<IndexedList*> MainList::indexed(Mode list) {
return (list == Mode::All) ? &_all : &_important;
not_null<IndexedList*> MainList::indexed(FilterId filterId) {
if (!filterId) {
return &_all;
}
const auto i = _other.find(filterId);
if (i != end(_other)) {
return &i->second;
}
return &_other.emplace(filterId, SortMode::Date).first->second;
}
not_null<const IndexedList*> MainList::indexed(Mode list) const {
return (list == Mode::All) ? &_all : &_important;
not_null<const IndexedList*> MainList::indexed() const {
return &_all;
}
not_null<PinnedList*> MainList::pinned() {

View File

@ -27,16 +27,16 @@ public:
void unreadEntryChanged(
const Dialogs::UnreadState &state,
bool added);
UnreadState unreadState() const;
[[nodiscard]] UnreadState unreadState() const;
not_null<IndexedList*> indexed(Mode list = Mode::All);
not_null<const IndexedList*> indexed(Mode list = Mode::All) const;
not_null<IndexedList*> indexed(FilterId filterId = 0);
not_null<const IndexedList*> indexed() const;
not_null<PinnedList*> pinned();
not_null<const PinnedList*> pinned() const;
private:
IndexedList _all;
IndexedList _important;
base::flat_map<FilterId, IndexedList> _other;
PinnedList _pinned;
UnreadState _unreadState;

View File

@ -528,9 +528,9 @@ void Widget::refreshDialog(Key key) {
}
void Widget::repaintDialogRow(
Mode list,
FilterId filterId,
not_null<Row*> row) {
_inner->repaintDialogRow(list, row);
_inner->repaintDialogRow(filterId, row);
}
void Widget::repaintDialogRow(RowDescriptor row) {

View File

@ -41,7 +41,6 @@ class ConnectionState;
namespace Dialogs {
enum class Mode;
struct RowDescriptor;
class Row;
class FakeRow;
@ -63,7 +62,7 @@ public:
void refreshDialog(Key key);
void removeDialog(Key key);
void repaintDialogRow(Mode list, not_null<Row*> row);
void repaintDialogRow(FilterId filterId, not_null<Row*> row);
void repaintDialogRow(RowDescriptor row);
void jumpToTop();

View File

@ -314,8 +314,8 @@ struct Data {
bool AdaptiveForWide = true;
base::Observable<void> AdaptiveChanged;
bool DialogsModeEnabled = false;
Dialogs::Mode DialogsMode = Dialogs::Mode::All;
bool DialogsFiltersEnabled = false;
FilterId DialogsFilterId = 0;
bool ModerateModeEnabled = false;
bool ScreenIsLocked = false;
@ -444,8 +444,8 @@ DefineVar(Global, Adaptive::ChatLayout, AdaptiveChatLayout);
DefineVar(Global, bool, AdaptiveForWide);
DefineRefVar(Global, base::Observable<void>, AdaptiveChanged);
DefineVar(Global, bool, DialogsModeEnabled);
DefineVar(Global, Dialogs::Mode, DialogsMode);
DefineVar(Global, bool, DialogsFiltersEnabled);
DefineVar(Global, FilterId, DialogsFilterId);
DefineVar(Global, bool, ModerateModeEnabled);
DefineVar(Global, bool, ScreenIsLocked);

View File

@ -18,10 +18,6 @@ namespace Data {
struct FileOrigin;
} // namespace Data
namespace Dialogs {
enum class Mode;
} // namespace Dialogs
namespace InlineBots {
namespace Layout {
class ItemBase;
@ -154,8 +150,8 @@ DeclareVar(Adaptive::ChatLayout, AdaptiveChatLayout);
DeclareVar(bool, AdaptiveForWide);
DeclareRefVar(base::Observable<void>, AdaptiveChanged);
DeclareVar(bool, DialogsModeEnabled);
DeclareVar(Dialogs::Mode, DialogsMode);
DeclareVar(bool, DialogsFiltersEnabled);
DeclareVar(FilterId, DialogsFilterId);
DeclareVar(bool, ModerateModeEnabled);
DeclareVar(bool, ScreenIsLocked);

View File

@ -838,7 +838,7 @@ void History::setUnreadMentionsCount(int count) {
}
_unreadMentionsCount = count;
const auto has = (count > 0);
if (has != had && Global::DialogsModeEnabled()) {
if (has != had && Global::DialogsFiltersEnabled()) { // #TODO filters
Notify::historyMuteUpdated(this);
updateChatListEntry();
}
@ -1912,8 +1912,6 @@ void History::clearFolder() {
}
void History::setFolderPointer(Data::Folder *folder) {
using Mode = Dialogs::Mode;
if (_folder == folder) {
return;
}
@ -1922,23 +1920,24 @@ void History::setFolderPointer(Data::Folder *folder) {
}
const auto wasKnown = folderKnown();
const auto wasInList = inChatList();
const auto wasInImportant = wasInList && inChatList(Mode::Important);
if (wasInList) {
removeFromChatList(Mode::All);
if (wasInImportant) {
removeFromChatList(Mode::Important);
}
}
// #TODO filters
//const auto wasInImportant = wasInList && inChatList(Mode::Important);
//if (wasInList) {
// removeFromChatList(Mode::All);
// if (wasInImportant) {
// removeFromChatList(Mode::Important);
// }
//}
const auto was = _folder.value_or(nullptr);
_folder = folder;
if (was) {
was->unregisterOne(this);
}
if (wasInList) {
addToChatList(Mode::All);
if (wasInImportant) {
addToChatList(Mode::Important);
}
addToChatList(0);
//if (wasInImportant) { // #TODO filters
// addToChatList(Mode::Important);
//}
owner().chatsListChanged(was);
owner().chatsListChanged(folder);
} else if (!wasKnown) {
@ -2602,10 +2601,6 @@ bool History::shouldBeInChatList() const {
|| (lastMessage() != nullptr);
}
bool History::toImportant() const {
return !mute() || hasUnreadMentions();
}
void History::unknownMessageDeleted(MsgId messageId) {
if (_inboxReadBefore && messageId >= *_inboxReadBefore) {
owner().histories().requestDialogEntry(this);

View File

@ -331,7 +331,6 @@ public:
int fixedOnTopIndex() const override;
void updateChatListExistence() override;
bool shouldBeInChatList() const override;
bool toImportant() const override;
int chatListUnreadCount() const override;
bool chatListUnreadMark() const override;
bool chatListMutedBadge() const override;

View File

@ -2183,9 +2183,9 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
}
void MainWidget::repaintDialogRow(
Dialogs::Mode list,
FilterId filterId,
not_null<Dialogs::Row*> row) {
_dialogs->repaintDialogRow(list, row);
_dialogs->repaintDialogRow(filterId, row);
}
void MainWidget::repaintDialogRow(Dialogs::RowDescriptor row) {

View File

@ -44,7 +44,6 @@ struct RowDescriptor;
class Row;
class Key;
class Widget;
enum class Mode;
} // namespace Dialogs
namespace Media {
@ -136,7 +135,7 @@ public:
void refreshDialog(Dialogs::Key key);
void removeDialog(Dialogs::Key key);
void repaintDialogRow(Dialogs::Mode list, not_null<Dialogs::Row*> row);
void repaintDialogRow(FilterId filterId, not_null<Dialogs::Row*> row);
void repaintDialogRow(Dialogs::RowDescriptor row);
void windowShown();

View File

@ -70,7 +70,7 @@ auto GenerateCodes() {
Unexpected("Crashed in Settings!");
});
codes.emplace(qsl("workmode"), [](::Main::Session *session) {
auto text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?");
auto text = Global::DialogsFiltersEnabled() ? qsl("Disable filters?") : qsl("Enable filters?");
Ui::show(Box<ConfirmBox>(text, [] {
Core::App().switchWorkMode();
}));

View File

@ -613,7 +613,7 @@ enum {
dbiHiddenPinnedMessages = 0x39,
dbiRecentEmoji = 0x3a,
dbiEmojiVariants = 0x3b,
dbiDialogsMode = 0x40,
dbiDialogsFilters = 0x40,
dbiModerateMode = 0x41,
dbiVideoVolume = 0x42,
dbiStickersRecentLimit = 0x43,
@ -1167,20 +1167,20 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
}
} break;
case dbiDialogsMode: {
case dbiDialogsFilters: {
qint32 enabled, modeInt;
stream >> enabled >> modeInt;
if (!_checkStreamStatus(stream)) return false;
Global::SetDialogsModeEnabled(enabled == 1);
auto mode = Dialogs::Mode::All;
Global::SetDialogsFiltersEnabled(enabled == 1);
auto mode = FilterId(0);
if (enabled) {
mode = static_cast<Dialogs::Mode>(modeInt);
if (mode != Dialogs::Mode::All && mode != Dialogs::Mode::Important) {
mode = Dialogs::Mode::All;
mode = FilterId(modeInt);
if (mode == 1) { // #TODO filters
}
}
Global::SetDialogsMode(mode);
Global::SetDialogsFilterId(mode);
} break;
case dbiModerateMode: {
@ -2140,7 +2140,7 @@ void _writeUserSettings() {
data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
data.stream << quint32(dbiSongVolume) << qint32(qRound(Global::SongVolume() * 1e6));
data.stream << quint32(dbiVideoVolume) << qint32(qRound(Global::VideoVolume() * 1e6));
data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
data.stream << quint32(dbiDialogsFilters) << qint32(Global::DialogsFiltersEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsFilterId());
data.stream << quint32(dbiModerateMode) << qint32(Global::ModerateModeEnabled() ? 1 : 0);
data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer());
data.stream << quint32(dbiCacheSettings) << qint64(_cacheTotalSizeLimit) << qint32(_cacheTotalTimeLimit) << qint64(_cacheBigFileTotalSizeLimit) << qint32(_cacheBigFileTotalTimeLimit);

View File

@ -129,7 +129,7 @@ SessionController::SessionController(
) | rpl::filter([=](Data::Folder *folder) {
return (folder != nullptr)
&& (folder == _openedFolder.current())
&& folder->chatsList()->indexed(Global::DialogsMode())->empty();
&& folder->chatsList()->indexed()->empty();
}) | rpl::start_with_next([=](Data::Folder *folder) {
folder->updateChatListSortPosition();
closeFolder();