mirror of https://github.com/procxx/kepka.git
Make filtered lists independent from folders.
This commit is contained in:
parent
c305246d21
commit
ca3419ef24
|
@ -13,6 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_chat.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "dialogs/dialogs_main_list.h"
|
||||
#include "main/main_session.h"
|
||||
#include "apiwrap.h"
|
||||
|
||||
|
@ -179,6 +181,18 @@ ChatFilters::ChatFilters(not_null<Session*> owner) : _owner(owner) {
|
|||
ChatFilter(2, "Unread", all | Flag::NoRead, {}, {}));
|
||||
}
|
||||
|
||||
ChatFilters::~ChatFilters() = default;
|
||||
|
||||
not_null<Dialogs::MainList*> ChatFilters::chatsList(FilterId filterId) {
|
||||
auto &pointer = _chatsLists[filterId];
|
||||
if (!pointer) {
|
||||
pointer = std::make_unique<Dialogs::MainList>(
|
||||
filterId,
|
||||
rpl::single(1));
|
||||
}
|
||||
return pointer.get();
|
||||
}
|
||||
|
||||
void ChatFilters::load() {
|
||||
load(false);
|
||||
}
|
||||
|
@ -285,21 +299,31 @@ void ChatFilters::applyRemove(int position) {
|
|||
|
||||
bool ChatFilters::applyChange(ChatFilter &filter, ChatFilter &&updated) {
|
||||
const auto rulesChanged = (filter.flags() != updated.flags())
|
||||
|| (filter.always() != updated.always());
|
||||
|| (filter.always() != updated.always())
|
||||
|| (filter.never() != updated.never());
|
||||
if (rulesChanged) {
|
||||
const auto list = _owner->chatsList()->indexed();
|
||||
for (const auto &entry : *list) {
|
||||
if (const auto history = entry->history()) {
|
||||
const auto now = updated.contains(history);
|
||||
const auto was = filter.contains(history);
|
||||
if (now != was) {
|
||||
if (now) {
|
||||
history->addToChatList(filter.id());
|
||||
} else {
|
||||
history->removeFromChatList(filter.id());
|
||||
}
|
||||
const auto feedHistory = [&](not_null<History*> history) {
|
||||
const auto now = updated.contains(history);
|
||||
const auto was = filter.contains(history);
|
||||
if (now != was) {
|
||||
if (now) {
|
||||
history->addToChatList(filter.id());
|
||||
} else {
|
||||
history->removeFromChatList(filter.id());
|
||||
}
|
||||
}
|
||||
};
|
||||
const auto feedList = [&](not_null<const Dialogs::MainList*> list) {
|
||||
for (const auto &entry : *list->indexed()) {
|
||||
if (const auto history = entry->history()) {
|
||||
feedHistory(history);
|
||||
}
|
||||
}
|
||||
};
|
||||
feedList(_owner->chatsList());
|
||||
const auto id = Data::Folder::kId;
|
||||
if (const auto folder = _owner->folderLoaded(id)) {
|
||||
feedList(folder->chatsList());
|
||||
}
|
||||
} else if (filter.title() == updated.title()) {
|
||||
return false;
|
||||
|
|
|
@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class History;
|
||||
|
||||
namespace Dialogs {
|
||||
class MainList;
|
||||
} // namespace Dialogs
|
||||
|
||||
namespace Data {
|
||||
|
||||
class Session;
|
||||
|
@ -63,6 +67,7 @@ private:
|
|||
class ChatFilters final {
|
||||
public:
|
||||
explicit ChatFilters(not_null<Session*> owner);
|
||||
~ChatFilters();
|
||||
|
||||
void load();
|
||||
void apply(const MTPUpdate &update);
|
||||
|
@ -75,6 +80,8 @@ public:
|
|||
[[nodiscard]] auto refreshHistoryRequests() const
|
||||
-> rpl::producer<not_null<History*>>;
|
||||
|
||||
[[nodiscard]] not_null<Dialogs::MainList*> chatsList(FilterId filterId);
|
||||
|
||||
private:
|
||||
void load(bool force);
|
||||
bool applyOrder(const QVector<MTPint> &order);
|
||||
|
@ -85,6 +92,7 @@ private:
|
|||
const not_null<Session*> _owner;
|
||||
|
||||
std::vector<ChatFilter> _list;
|
||||
base::flat_map<FilterId, std::unique_ptr<Dialogs::MainList>> _chatsLists;
|
||||
rpl::event_stream<> _listChanged;
|
||||
rpl::event_stream<not_null<History*>> _refreshHistoryRequests;
|
||||
mtpRequestId _loadRequestId = 0;
|
||||
|
|
|
@ -57,7 +57,7 @@ rpl::producer<int> PinnedDialogsInFolderMaxValue(
|
|||
Folder::Folder(not_null<Data::Session*> owner, FolderId id)
|
||||
: Entry(owner, this)
|
||||
, _id(id)
|
||||
, _chatsList(PinnedDialogsInFolderMaxValue(&owner->session()))
|
||||
, _chatsList(FilterId(), PinnedDialogsInFolderMaxValue(&owner->session()))
|
||||
, _name(tr::lng_archived_name(tr::now)) {
|
||||
indexNameParts();
|
||||
|
||||
|
|
|
@ -139,8 +139,8 @@ int ScheduledMessages::count(not_null<History*> history) const {
|
|||
}
|
||||
|
||||
void ScheduledMessages::sendNowSimpleMessage(
|
||||
const MTPDupdateShortSentMessage &update,
|
||||
not_null<HistoryItem*> local) {
|
||||
const MTPDupdateShortSentMessage &update,
|
||||
not_null<HistoryItem*> local) {
|
||||
Expects(local->isSending());
|
||||
Expects(local->isScheduled());
|
||||
Expects(local->date() == kScheduledUntilOnlineTimestamp);
|
||||
|
|
|
@ -184,7 +184,7 @@ Session::Session(not_null<Main::Session*> session)
|
|||
, _bigFileCache(Core::App().databases().get(
|
||||
Local::cacheBigFilePath(),
|
||||
Local::cacheBigFileSettings()))
|
||||
, _chatsList(PinnedDialogsCountMaxValue(session))
|
||||
, _chatsList(FilterId(), PinnedDialogsCountMaxValue(session))
|
||||
, _contactsList(Dialogs::SortMode::Name)
|
||||
, _contactsNoChatsList(Dialogs::SortMode::Name)
|
||||
, _selfDestructTimer([=] { checkSelfDestructItems(); })
|
||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "dialogs/dialogs_indexed_list.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "mainwidget.h"
|
||||
#include "main/main_session.h"
|
||||
#include "history/history_item.h"
|
||||
|
@ -92,16 +93,17 @@ void Entry::updateChatListSortPosition() {
|
|||
updateChatListEntry();
|
||||
return;
|
||||
}
|
||||
_sortKeyByDate = DialogPosFromDate(adjustedChatListTimeId());
|
||||
const auto fixedIndex = fixedOnTopIndex();
|
||||
_sortKeyInChatList = fixedIndex
|
||||
? FixedOnTopDialogPos(fixedIndex)
|
||||
: isPinnedDialog()
|
||||
? PinnedDialogPos(_pinnedIndex)
|
||||
: DialogPosFromDate(adjustedChatListTimeId());
|
||||
: _sortKeyByDate;
|
||||
if (needUpdateInChatList()) {
|
||||
setChatListExistence(true);
|
||||
} else {
|
||||
_sortKeyInChatList = 0;
|
||||
_sortKeyInChatList = _sortKeyByDate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,7 +231,9 @@ void Entry::updateChatListEntry() const {
|
|||
}
|
||||
|
||||
not_null<IndexedList*> Entry::myChatsList(FilterId filterId) const {
|
||||
return owner().chatsList(folder())->indexed(filterId);
|
||||
return filterId
|
||||
? owner().chatsFilters().chatsList(filterId)->indexed()
|
||||
: owner().chatsList(folder())->indexed();
|
||||
}
|
||||
|
||||
} // namespace Dialogs
|
||||
|
|
|
@ -31,9 +31,10 @@ struct RowsByLetter {
|
|||
};
|
||||
|
||||
enum class SortMode {
|
||||
Date = 0x00,
|
||||
Name = 0x01,
|
||||
Add = 0x02,
|
||||
Complex = 0x00,
|
||||
Date = 0x01,
|
||||
Name = 0x02,
|
||||
Add = 0x04,
|
||||
};
|
||||
|
||||
struct PositionChange {
|
||||
|
@ -120,6 +121,9 @@ public:
|
|||
uint64 sortKeyInChatList() const {
|
||||
return _sortKeyInChatList;
|
||||
}
|
||||
uint64 sortKeyByDate() const {
|
||||
return _sortKeyByDate;
|
||||
}
|
||||
void updateChatListSortPosition();
|
||||
void setChatListTimeId(TimeId date);
|
||||
virtual void updateChatListExistence();
|
||||
|
@ -199,6 +203,7 @@ private:
|
|||
Dialogs::Key _key;
|
||||
base::flat_map<FilterId, RowsByLetter> _chatListLinks;
|
||||
uint64 _sortKeyInChatList = 0;
|
||||
uint64 _sortKeyByDate = 0;
|
||||
int _pinnedIndex = 0;
|
||||
bool _isProxyPromoted = false;
|
||||
TimeId _timeId = 0;
|
||||
|
|
|
@ -87,7 +87,7 @@ void IndexedList::movePinned(Row *row, int deltaSign) {
|
|||
void IndexedList::peerNameChanged(
|
||||
not_null<PeerData*> peer,
|
||||
const base::flat_set<QChar> &oldLetters) {
|
||||
Expects(_sortMode != SortMode::Date);
|
||||
Expects(_sortMode != SortMode::Date && _sortMode != SortMode::Complex);
|
||||
|
||||
if (const auto history = peer->owner().historyLoaded(peer)) {
|
||||
if (_sortMode == SortMode::Name) {
|
||||
|
@ -102,7 +102,7 @@ void IndexedList::peerNameChanged(
|
|||
FilterId filterId,
|
||||
not_null<PeerData*> peer,
|
||||
const base::flat_set<QChar> &oldLetters) {
|
||||
Expects(_sortMode == SortMode::Date);
|
||||
Expects(_sortMode == SortMode::Date || _sortMode == SortMode::Complex);
|
||||
|
||||
if (const auto history = peer->owner().historyLoaded(peer)) {
|
||||
adjustNames(filterId, history, oldLetters);
|
||||
|
@ -165,7 +165,7 @@ void IndexedList::adjustNames(
|
|||
}
|
||||
}
|
||||
for (auto ch : toRemove) {
|
||||
if (_sortMode == SortMode::Date) {
|
||||
if (_sortMode == SortMode::Date || _sortMode == SortMode::Complex) {
|
||||
history->removeChatListEntryByLetter(filterId, ch);
|
||||
}
|
||||
if (auto it = _index.find(ch); it != _index.cend()) {
|
||||
|
@ -178,7 +178,7 @@ void IndexedList::adjustNames(
|
|||
j = _index.emplace(ch, _sortMode).first;
|
||||
}
|
||||
auto row = j->second.addToEnd(key);
|
||||
if (_sortMode == SortMode::Date) {
|
||||
if (_sortMode == SortMode::Date || _sortMode == SortMode::Complex) {
|
||||
history->addChatListEntryByLetter(filterId, ch, row);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,12 +26,12 @@ public:
|
|||
// row must belong to this indexed list all().
|
||||
void movePinned(Row *row, int deltaSign);
|
||||
|
||||
// For sortMode != SortMode::Date
|
||||
// For sortMode != SortMode::Date && != Complex
|
||||
void peerNameChanged(
|
||||
not_null<PeerData*> peer,
|
||||
const base::flat_set<QChar> &oldChars);
|
||||
|
||||
//For sortMode == SortMode::Date
|
||||
//For sortMode == SortMode::Date || == Complex
|
||||
void peerNameChanged(
|
||||
FilterId filterId,
|
||||
not_null<PeerData*> peer,
|
||||
|
|
|
@ -440,6 +440,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
Layout::RowPainter::paint(
|
||||
p,
|
||||
row,
|
||||
_filterId,
|
||||
fullWidth,
|
||||
isActive,
|
||||
isSelected,
|
||||
|
@ -565,6 +566,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
Layout::RowPainter::paint(
|
||||
p,
|
||||
_filterResults[from],
|
||||
_filterId,
|
||||
fullWidth,
|
||||
active,
|
||||
selected,
|
||||
|
@ -1680,7 +1682,9 @@ void InnerWidget::updateSelectedRow(Key key) {
|
|||
}
|
||||
|
||||
not_null<IndexedList*> InnerWidget::shownDialogs() const {
|
||||
return session().data().chatsList(_openedFolder)->indexed(_filterId);
|
||||
return _filterId
|
||||
? session().data().chatsFilters().chatsList(_filterId)->indexed()
|
||||
: session().data().chatsList(_openedFolder)->indexed();
|
||||
}
|
||||
|
||||
void InnerWidget::leaveEventHook(QEvent *e) {
|
||||
|
|
|
@ -613,6 +613,7 @@ void paintUnreadCount(
|
|||
void RowPainter::paint(
|
||||
Painter &p,
|
||||
not_null<const Row*> row,
|
||||
int filterId,
|
||||
int fullWidth,
|
||||
bool active,
|
||||
bool selected,
|
||||
|
@ -668,6 +669,7 @@ void RowPainter::paint(
|
|||
const auto displayPinnedIcon = !displayUnreadCounter
|
||||
&& !displayMentionBadge
|
||||
&& !displayUnreadMark
|
||||
&& !filterId
|
||||
&& entry->isPinnedDialog()
|
||||
&& !entry->fixedOnTopIndex();
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
static void paint(
|
||||
Painter &p,
|
||||
not_null<const Row*> row,
|
||||
int filterId,
|
||||
int fullWidth,
|
||||
bool active,
|
||||
bool selected,
|
||||
|
|
|
@ -32,7 +32,7 @@ not_null<Row*> List::addToEnd(Key key) {
|
|||
std::make_unique<Row>(key, _rows.size())
|
||||
).first->second.get();
|
||||
_rows.emplace_back(result);
|
||||
if (_sortMode == SortMode::Date) {
|
||||
if (_sortMode == SortMode::Date || _sortMode == SortMode::Complex) {
|
||||
adjustByDate(result);
|
||||
}
|
||||
return result;
|
||||
|
@ -82,20 +82,20 @@ void List::adjustByName(not_null<Row*> row) {
|
|||
}
|
||||
|
||||
void List::adjustByDate(not_null<Row*> row) {
|
||||
Expects(_sortMode == SortMode::Date);
|
||||
Expects(_sortMode == SortMode::Date || _sortMode == SortMode::Complex);
|
||||
|
||||
const auto key = row->sortKey();
|
||||
const auto key = row->sortKey(_sortMode);
|
||||
const auto index = row->pos();
|
||||
const auto i = _rows.begin() + index;
|
||||
const auto before = std::find_if(i + 1, _rows.end(), [&](Row *row) {
|
||||
return (row->sortKey() <= key);
|
||||
return (row->sortKey(_sortMode) <= key);
|
||||
});
|
||||
if (before != i + 1) {
|
||||
rotate(i, i + 1, before);
|
||||
} else {
|
||||
const auto from = std::make_reverse_iterator(i);
|
||||
const auto after = std::find_if(from, _rows.rend(), [&](Row *row) {
|
||||
return (row->sortKey() >= key);
|
||||
return (row->sortKey(_sortMode) >= key);
|
||||
}).base();
|
||||
if (after != i) {
|
||||
rotate(after, i, i + 1);
|
||||
|
|
|
@ -12,8 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace Dialogs {
|
||||
|
||||
MainList::MainList(rpl::producer<int> pinnedLimit)
|
||||
: _all(SortMode::Date)
|
||||
MainList::MainList(FilterId filterId, rpl::producer<int> pinnedLimit)
|
||||
: _filterId(filterId)
|
||||
, _all(filterId ? SortMode::Date : SortMode::Complex)
|
||||
, _pinned(1) {
|
||||
_unreadState.known = true;
|
||||
|
||||
|
@ -28,10 +29,7 @@ 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(FilterId(), peer, oldLetters);
|
||||
for (auto &[filterId, list] : _other) {
|
||||
list.peerNameChanged(filterId, peer, oldLetters);
|
||||
}
|
||||
_all.peerNameChanged(_filterId, peer, oldLetters);
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
|
@ -49,7 +47,6 @@ void MainList::setLoaded(bool loaded) {
|
|||
|
||||
void MainList::clear() {
|
||||
_all.clear();
|
||||
_other.clear();
|
||||
_unreadState = UnreadState();
|
||||
}
|
||||
|
||||
|
@ -73,15 +70,8 @@ UnreadState MainList::unreadState() const {
|
|||
return _unreadState;
|
||||
}
|
||||
|
||||
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<IndexedList*> MainList::indexed() {
|
||||
return &_all;
|
||||
}
|
||||
|
||||
not_null<const IndexedList*> MainList::indexed() const {
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Dialogs {
|
|||
|
||||
class MainList final {
|
||||
public:
|
||||
explicit MainList(rpl::producer<int> pinnedLimit);
|
||||
MainList(FilterId filterId, rpl::producer<int> pinnedLimit);
|
||||
|
||||
bool empty() const;
|
||||
bool loaded() const;
|
||||
|
@ -29,14 +29,14 @@ public:
|
|||
bool added);
|
||||
[[nodiscard]] UnreadState unreadState() const;
|
||||
|
||||
not_null<IndexedList*> indexed(FilterId filterId = 0);
|
||||
not_null<IndexedList*> indexed();
|
||||
not_null<const IndexedList*> indexed() const;
|
||||
not_null<PinnedList*> pinned();
|
||||
not_null<const PinnedList*> pinned() const;
|
||||
|
||||
private:
|
||||
FilterId _filterId = 0;
|
||||
IndexedList _all;
|
||||
base::flat_map<FilterId, IndexedList> _other;
|
||||
PinnedList _pinned;
|
||||
UnreadState _unreadState;
|
||||
|
||||
|
|
|
@ -220,8 +220,10 @@ Row::Row(Key key, int pos) : _id(key), _pos(pos) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64 Row::sortKey() const {
|
||||
return _id.entry()->sortKeyInChatList();
|
||||
uint64 Row::sortKey(SortMode mode) const {
|
||||
return (mode == SortMode::Complex)
|
||||
? _id.entry()->sortKeyInChatList()
|
||||
: _id.entry()->sortKeyByDate();
|
||||
}
|
||||
|
||||
void Row::validateListEntryCache() const {
|
||||
|
|
|
@ -23,6 +23,8 @@ namespace Layout {
|
|||
class RowPainter;
|
||||
} // namespace Layout
|
||||
|
||||
enum class SortMode;
|
||||
|
||||
class BasicRow {
|
||||
public:
|
||||
BasicRow();
|
||||
|
@ -88,7 +90,7 @@ public:
|
|||
int pos() const {
|
||||
return _pos;
|
||||
}
|
||||
uint64 sortKey() const;
|
||||
uint64 sortKey(SortMode mode) const;
|
||||
|
||||
void validateListEntryCache() const;
|
||||
const Ui::Text::String &listEntryCache() const {
|
||||
|
|
Loading…
Reference in New Issue