2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-09-02 23:55:12 +00:00

Save info members list state to memento.

This commit is contained in:
John Preston
2017-10-24 20:11:35 +03:00
parent fb46c33d7f
commit b51f865c54
29 changed files with 875 additions and 220 deletions

View File

@@ -586,8 +586,8 @@ void PeerListContent::addToSearchIndex(not_null<PeerListRow*> row) {
}
removeFromSearchIndex(row);
row->setNameFirstChars(row->peer()->chars);
for_const (auto ch, row->nameFirstChars()) {
row->setNameFirstChars(row->peer()->nameFirstChars());
for (auto ch : row->nameFirstChars()) {
_searchIndex[ch].push_back(row);
}
}
@@ -595,7 +595,7 @@ void PeerListContent::addToSearchIndex(not_null<PeerListRow*> row) {
void PeerListContent::removeFromSearchIndex(not_null<PeerListRow*> row) {
auto &nameFirstChars = row->nameFirstChars();
if (!nameFirstChars.empty()) {
for_const (auto ch, row->nameFirstChars()) {
for (auto ch : row->nameFirstChars()) {
auto it = _searchIndex.find(ch);
if (it != _searchIndex.cend()) {
auto &entry = it->second;
@@ -605,7 +605,7 @@ void PeerListContent::removeFromSearchIndex(not_null<PeerListRow*> row) {
}
}
}
row->setNameFirstChars(OrderedSet<QChar>());
row->setNameFirstChars({});
}
}
@@ -644,7 +644,9 @@ void PeerListContent::refreshIndices() {
}
}
void PeerListContent::removeRowAtIndex(std::vector<std::unique_ptr<PeerListRow>> &from, int index) {
void PeerListContent::removeRowAtIndex(
std::vector<std::unique_ptr<PeerListRow>> &from,
int index) {
from.erase(from.begin() + index);
for (auto i = index, count = int(from.size()); i != count; ++i) {
from[i]->setAbsoluteIndex(i);
@@ -664,17 +666,40 @@ void PeerListContent::removeRow(not_null<PeerListRow*> row) {
Assert(index >= 0 && index < eraseFrom.size());
Assert(eraseFrom[index].get() == row);
auto pressedData = saveSelectedData(_pressed);
auto contextedData = saveSelectedData(_contexted);
setSelected(Selected());
setPressed(Selected());
setContexted(Selected());
_rowsById.erase(row->id());
auto &byPeer = _rowsByPeer[row->peer()];
byPeer.erase(std::remove(byPeer.begin(), byPeer.end(), row), byPeer.end());
removeFromSearchIndex(row);
_filterResults.erase(std::find(_filterResults.begin(), _filterResults.end(), row), _filterResults.end());
_filterResults.erase(
std::find(_filterResults.begin(), _filterResults.end(), row),
_filterResults.end());
removeRowAtIndex(eraseFrom, index);
restoreSelection();
setPressed(restoreSelectedData(pressedData));
setContexted(restoreSelectedData(contextedData));
}
void PeerListContent::clearAllContent() {
setSelected(Selected());
setPressed(Selected());
setContexted(Selected());
_rowsById.clear();
_rowsByPeer.clear();
_filterResults.clear();
_searchIndex.clear();
_rows.clear();
_searchRows.clear();
_searchQuery
= _normalizedSearchQuery
= _mentionHighlight
= QString();
}
void PeerListContent::convertRowToSearchResult(not_null<PeerListRow*> row) {
@@ -926,28 +951,23 @@ void PeerListContent::contextMenuEvent(QContextMenuEvent *e) {
_menu->deleteLater();
_menu = nullptr;
}
if (_context.index.value >= 0) {
updateRow(_context.index);
_context = Selected();
}
setContexted(Selected());
if (e->reason() == QContextMenuEvent::Mouse) {
handleMouseMove(e->globalPos());
}
_context = _selected;
setContexted(_selected);
if (_pressButton != Qt::LeftButton) {
mousePressReleased(_pressButton);
}
if (auto row = getRow(_context.index)) {
if (auto row = getRow(_contexted.index)) {
_menu = _controller->rowContextMenu(row);
if (_menu) {
_menu->setDestroyedCallback(base::lambda_guarded(
this,
[this] {
updateRow(_context.index);
_context = Selected();
setContexted(Selected());
handleMouseMove(QCursor::pos());
}));
_menu->popup(e->globalPos());
@@ -977,8 +997,8 @@ TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) {
auto peer = row->peer();
auto user = peer->asUser();
auto active = (_context.index.value >= 0)
? _context
auto active = (_contexted.index.value >= 0)
? _contexted
: (_pressed.index.value >= 0)
? _pressed
: _selected;
@@ -1155,7 +1175,7 @@ void PeerListContent::checkScrollForPreload() {
void PeerListContent::searchQueryChanged(QString query) {
auto searchWordsList = TextUtilities::PrepareSearchWords(query);
auto normalizedQuery = searchWordsList.isEmpty() ? QString() : searchWordsList.join(' ');
auto normalizedQuery = searchWordsList.join(' ');
if (_normalizedSearchQuery != normalizedQuery) {
setSearchQuery(query, normalizedQuery);
if (_controller->searchInLocal() && !searchWordsList.isEmpty()) {
@@ -1172,15 +1192,18 @@ void PeerListContent::searchQueryChanged(QString query) {
}
}
if (minimalList) {
auto searchWordInNames = [](PeerData *peer, const QString &searchWord) {
for_const (auto &nameWord, peer->names) {
auto searchWordInNames = [](
not_null<PeerData*> peer,
const QString &searchWord) {
for (auto &nameWord : peer->nameWords()) {
if (nameWord.startsWith(searchWord)) {
return true;
}
}
return false;
};
auto allSearchWordsInNames = [searchWordInNames, &searchWordsList](PeerData *peer) {
auto allSearchWordsInNames = [&](
not_null<PeerData*> peer) {
for_const (auto &searchWord, searchWordsList) {
if (!searchWordInNames(peer, searchWord)) {
return false;
@@ -1205,12 +1228,58 @@ void PeerListContent::searchQueryChanged(QString query) {
}
}
void PeerListContent::setSearchQuery(const QString &query, const QString &normalizedQuery) {
std::unique_ptr<PeerListState> PeerListContent::saveState() const {
auto result = std::make_unique<PeerListState>();
result->controllerState = EmptyControllerState();
result->list.reserve(_rows.size());
for (auto &row : _rows) {
result->list.push_back(row->peer());
}
result->filterResults.reserve(_filterResults.size());
for (auto &row : _filterResults) {
result->filterResults.push_back(row->peer());
}
result->searchQuery = _searchQuery;
return result;
}
void PeerListContent::restoreState(
std::unique_ptr<PeerListState> state) {
if (!state || !state->controllerState.has_value()) {
return;
}
clearAllContent();
for (auto peer : state->list) {
if (auto row = _controller->createRestoredRow(peer)) {
appendRow(std::move(row));
}
}
auto query = state->searchQuery;
auto searchWords = TextUtilities::PrepareSearchWords(query);
setSearchQuery(query, searchWords.join(' '));
for (auto peer : state->filterResults) {
if (auto existingRow = findRow(peer->id)) {
_filterResults.push_back(existingRow);
} else if (auto row = _controller->createSearchRow(peer)) {
appendSearchRow(std::move(row));
}
}
refreshRows();
}
void PeerListContent::setSearchQuery(
const QString &query,
const QString &normalizedQuery) {
setSelected(Selected());
setPressed(Selected());
setContexted(Selected());
_searchQuery = query;
_normalizedSearchQuery = normalizedQuery;
_mentionHighlight = _searchQuery.startsWith('@') ? _searchQuery.mid(1) : _searchQuery;
_mentionHighlight = _searchQuery.startsWith('@')
? _searchQuery.mid(1)
: _searchQuery;
_filterResults.clear();
clearSearchRows();
}
@@ -1239,11 +1308,38 @@ void PeerListContent::setSelected(Selected selected) {
}
}
void PeerListContent::setContexted(Selected contexted) {
updateRow(_contexted.index);
if (_contexted != contexted) {
_contexted = contexted;
updateRow(_contexted.index);
}
}
void PeerListContent::restoreSelection() {
_lastMousePosition = QCursor::pos();
updateSelection();
}
auto PeerListContent::saveSelectedData(Selected from)
-> SelectedSaved {
if (auto row = getRow(from.index)) {
return { row->id(), from };
}
return { PeerListRowId(0), from };
}
auto PeerListContent::restoreSelectedData(SelectedSaved from)
-> Selected {
auto result = from.old;
if (auto row = findRow(from.id)) {
result.index = findRowIndex(row, result.index);
} else {
result.index.value = -1;
}
return result;
}
void PeerListContent::updateSelection() {
if (!_mouseSelection) return;
@@ -1305,6 +1401,9 @@ void PeerListContent::updateRow(RowIndex index) {
if (index == _pressed.index) {
setPressed(Selected());
}
if (index == _contexted.index) {
setContexted(Selected());
}
}
update(0, getRowTop(index), width(), _rowHeight);
}
@@ -1349,7 +1448,9 @@ PeerListRow *PeerListContent::getRow(RowIndex index) {
return nullptr;
}
PeerListContent::RowIndex PeerListContent::findRowIndex(not_null<PeerListRow*> row, RowIndex hint) {
PeerListContent::RowIndex PeerListContent::findRowIndex(
not_null<PeerListRow*> row,
RowIndex hint) {
if (!showingSearch()) {
Assert(!row->isSearchResult());
return RowIndex(row->absoluteIndex());

View File

@@ -161,10 +161,10 @@ public:
int outerWidth);
float64 checkedRatio();
void setNameFirstChars(const OrderedSet<QChar> &nameFirstChars) {
void setNameFirstChars(const base::flat_set<QChar> &nameFirstChars) {
_nameFirstChars = nameFirstChars;
}
const OrderedSet<QChar> &nameFirstChars() const {
const base::flat_set<QChar> &nameFirstChars() const {
return _nameFirstChars;
}
@@ -202,7 +202,7 @@ private:
Text _status;
StatusType _statusType = StatusType::Online;
TimeMs _statusValidTill = 0;
OrderedSet<QChar> _nameFirstChars;
base::flat_set<QChar> _nameFirstChars;
int _absoluteIndex = -1;
State _disabledState = State::Active;
bool _initialized : 1;
@@ -215,6 +215,17 @@ enum class PeerListSearchMode {
Enabled,
};
struct PeerListState {
PeerListState() = default;
PeerListState(PeerListState &&other) = delete;
PeerListState &operator=(PeerListState &&other) = delete;
base::unique_any controllerState;
std::vector<not_null<PeerData*>> list;
std::vector<not_null<PeerData*>> filterResults;
QString searchQuery;
};
class PeerListDelegate {
public:
virtual void peerListSetTitle(base::lambda<QString()> title) = 0;
@@ -252,6 +263,9 @@ public:
virtual int peerListSelectedRowsCount() = 0;
virtual std::vector<not_null<PeerData*>> peerListCollectSelectedRows() = 0;
virtual std::unique_ptr<PeerListState> peerListSaveState() = 0;
virtual void peerListRestoreState(
std::unique_ptr<PeerListState> state) = 0;
virtual ~PeerListDelegate() = default;
private:
@@ -279,6 +293,12 @@ public:
_delegate = delegate;
}
virtual base::unique_any saveState() {
return {};
}
virtual void restoreState(base::unique_any &&state) {
}
protected:
not_null<PeerListSearchDelegate*> delegate() const {
return _delegate;
@@ -314,9 +334,22 @@ public:
bool isSearchLoading() const {
return _searchController ? _searchController->isLoading() : false;
}
virtual std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData*> peer) {
virtual std::unique_ptr<PeerListRow> createSearchRow(
not_null<PeerData*> peer) {
return nullptr;
}
virtual std::unique_ptr<PeerListRow> createRestoredRow(
not_null<PeerData*> peer) {
return nullptr;
}
virtual std::unique_ptr<PeerListState> saveState() {
return delegate()->peerListSaveState();
}
virtual void restoreState(
std::unique_ptr<PeerListState> state) {
delegate()->peerListRestoreState(std::move(state));
}
bool isRowSelected(not_null<PeerData*> peer) {
return delegate()->peerListIsRowSelected(peer);
@@ -418,6 +451,9 @@ public:
update();
}
std::unique_ptr<PeerListState> saveState() const;
void restoreState(std::unique_ptr<PeerListState> state);
auto scrollToRequests() const {
return _scrollToRequests.events();
}
@@ -473,10 +509,23 @@ private:
friend inline bool operator!=(Selected a, Selected b) {
return !(a == b);
}
struct SelectedSaved {
SelectedSaved(PeerListRowId id, Selected old)
: id(id), old(old) {
}
PeerListRowId id = 0;
Selected old;
};
struct EmptyControllerState {
};
void setSelected(Selected selected);
void setPressed(Selected pressed);
void setContexted(Selected contexted);
void restoreSelection();
SelectedSaved saveSelectedData(Selected from);
Selected restoreSelectedData(SelectedSaved from);
void updateSelection();
void loadProfilePhotos();
@@ -511,6 +560,7 @@ private:
int labelHeight() const;
void clearSearchRows();
void clearAllContent();
void handleMouseMove(QPoint position);
void mousePressReleased(Qt::MouseButton button);
@@ -524,7 +574,7 @@ private:
Selected _selected;
Selected _pressed;
Selected _context;
Selected _contexted;
bool _mouseSelection = false;
Qt::MouseButton _pressButton = Qt::LeftButton;
@@ -649,6 +699,13 @@ public:
});
return result;
}
std::unique_ptr<PeerListState> peerListSaveState() override {
return _content->saveState();
}
void peerListRestoreState(
std::unique_ptr<PeerListState> state) override {
_content->restoreState(std::move(state));
}
protected:
not_null<PeerListContent*> content() const {
@@ -660,7 +717,9 @@ private:
};
class PeerListBox : public BoxContent, public PeerListContentDelegate {
class PeerListBox
: public BoxContent
, public PeerListContentDelegate {
public:
PeerListBox(
QWidget*,
@@ -670,7 +729,8 @@ public:
void peerListSetTitle(base::lambda<QString()> title) override {
setTitle(std::move(title));
}
void peerListSetAdditionalTitle(base::lambda<QString()> title) override {
void peerListSetAdditionalTitle(
base::lambda<QString()> title) override {
setAdditionalTitle(std::move(title));
}
void peerListSetSearchMode(PeerListSearchMode mode) override;
@@ -691,12 +751,15 @@ protected:
void paintEvent(QPaintEvent *e) override;
private:
void peerListAddSelectedRowInBunch(not_null<PeerData*> peer) override {
void peerListAddSelectedRowInBunch(
not_null<PeerData*> peer) override {
addSelectItem(peer, PeerListRow::SetStyle::Fast);
}
void peerListFinishSelectedRowsBunch() override;
void addSelectItem(not_null<PeerData*> peer, PeerListRow::SetStyle style);
void addSelectItem(
not_null<PeerData*> peer,
PeerListRow::SetStyle style);
void createMultiSelect();
int getTopScrollSkip() const;
void updateScrollSkips();

View File

@@ -349,7 +349,7 @@ void ShareBox::Inner::activateSkipPage(int pageHeight, int direction) {
void ShareBox::Inner::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.flags & Notify::PeerUpdate::Flag::NameChanged) {
_chatsIndexed->peerNameChanged(update.peer, update.oldNames, update.oldNameFirstChars);
_chatsIndexed->peerNameChanged(update.peer, update.oldNameFirstChars);
}
updateChat(update.peer);
@@ -635,7 +635,10 @@ void ShareBox::Inner::changeCheckState(Chat *chat) {
if (!_filter.isEmpty()) {
auto row = _chatsIndexed->getRow(chat->peer->id);
if (!row) {
row = _chatsIndexed->addToEnd(App::history(chat->peer)).value(0);
auto rowsByLetter = _chatsIndexed->addToEnd(App::history(chat->peer));
auto it = rowsByLetter.find(0);
Assert(it != rowsByLetter.cend());
row = it->second;
}
chat = getChat(row);
if (!chat->checkbox.checked()) {
@@ -712,8 +715,8 @@ void ShareBox::Inner::updateFilter(QString filter) {
if (toFilter) {
_filtered.reserve(toFilter->size());
for_const (auto row, *toFilter) {
auto &names = row->history()->peer->names;
PeerData::Names::const_iterator nb = names.cbegin(), ne = names.cend(), ni;
auto &nameWords = row->history()->peer->nameWords();
auto nb = nameWords.cbegin(), ne = nameWords.cend(), ni = nb;
for (fi = fb; fi != fe; ++fi) {
auto filterName = *fi;
for (ni = nb; ni != ne; ++ni) {