dialogs_pinned_list.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "dialogs/dialogs_pinned_list.h"
  8. #include "data/data_saved_messages.h"
  9. #include "dialogs/dialogs_key.h"
  10. #include "dialogs/dialogs_entry.h"
  11. #include "history/history.h"
  12. #include "data/data_session.h"
  13. #include "data/data_forum.h"
  14. namespace Dialogs {
  15. PinnedList::PinnedList(FilterId filterId, int limit)
  16. : _filterId(filterId)
  17. , _limit(limit) {
  18. Expects(limit > 0);
  19. }
  20. void PinnedList::setLimit(int limit) {
  21. Expects(limit > 0);
  22. if (_limit == limit) {
  23. return;
  24. }
  25. _limit = limit;
  26. applyLimit(_limit);
  27. }
  28. void PinnedList::addPinned(Key key) {
  29. Expects(key.entry()->folderKnown());
  30. addPinnedGetPosition(key);
  31. }
  32. int PinnedList::addPinnedGetPosition(Key key) {
  33. const auto already = ranges::find(_data, key);
  34. if (already != end(_data)) {
  35. return already - begin(_data);
  36. }
  37. applyLimit(_limit - 1);
  38. const auto position = int(_data.size());
  39. _data.push_back(key);
  40. key.entry()->cachePinnedIndex(_filterId, position + 1);
  41. return position;
  42. }
  43. void PinnedList::setPinned(Key key, bool pinned) {
  44. Expects(key.entry()->folderKnown() || _filterId != 0);
  45. if (pinned) {
  46. const int position = addPinnedGetPosition(key);
  47. if (position) {
  48. const auto begin = _data.begin();
  49. std::rotate(begin, begin + position, begin + position + 1);
  50. for (auto i = 0; i != position + 1; ++i) {
  51. _data[i].entry()->cachePinnedIndex(_filterId, i + 1);
  52. }
  53. }
  54. } else if (const auto it = ranges::find(_data, key); it != end(_data)) {
  55. const auto index = int(it - begin(_data));
  56. _data.erase(it);
  57. key.entry()->cachePinnedIndex(_filterId, 0);
  58. for (auto i = index, count = int(size(_data)); i != count; ++i) {
  59. _data[i].entry()->cachePinnedIndex(_filterId, i + 1);
  60. }
  61. }
  62. }
  63. void PinnedList::applyLimit(int limit) {
  64. Expects(limit >= 0);
  65. while (_data.size() > limit) {
  66. setPinned(_data.back(), false);
  67. }
  68. }
  69. void PinnedList::clear() {
  70. applyLimit(0);
  71. }
  72. void PinnedList::applyList(
  73. not_null<Data::Session*> owner,
  74. const QVector<MTPDialogPeer> &list) {
  75. Expects(this != owner->savedMessages().chatsList()->pinned());
  76. clear();
  77. for (const auto &peer : list) {
  78. peer.match([&](const MTPDdialogPeer &data) {
  79. if (const auto peerId = peerFromMTP(data.vpeer())) {
  80. addPinned(owner->history(peerId));
  81. }
  82. }, [&](const MTPDdialogPeerFolder &data) {
  83. addPinned(owner->folder(data.vfolder_id().v));
  84. });
  85. }
  86. }
  87. void PinnedList::applyList(
  88. not_null<Data::SavedMessages*> sublistsOwner,
  89. const QVector<MTPDialogPeer> &list) {
  90. Expects(this == sublistsOwner->chatsList()->pinned());
  91. clear();
  92. for (const auto &peer : list) {
  93. peer.match([&](const MTPDdialogPeer &data) {
  94. if (const auto peerId = peerFromMTP(data.vpeer())) {
  95. const auto peer = sublistsOwner->owner().peer(peerId);
  96. addPinned(sublistsOwner->sublist(peer));
  97. }
  98. }, [](const MTPDdialogPeerFolder &data) {
  99. });
  100. }
  101. }
  102. void PinnedList::applyList(
  103. not_null<Data::Forum*> forum,
  104. const QVector<MTPint> &list) {
  105. Expects(this == forum->topicsList()->pinned());
  106. clear();
  107. for (const auto &topicId : list) {
  108. addPinned(forum->topicFor(topicId.v));
  109. }
  110. }
  111. void PinnedList::applyList(const std::vector<not_null<History*>> &list) {
  112. Expects(_filterId != 0);
  113. const auto old = base::take(_data);
  114. const auto count = int(list.size());
  115. _data.reserve(count);
  116. for (auto i = 0; i != count; ++i) {
  117. const auto history = list[i];
  118. _data.emplace_back(history);
  119. history->cachePinnedIndex(_filterId, i + 1);
  120. }
  121. for (const auto &key : old) {
  122. const auto history = key.history();
  123. if (!history || !ranges::contains(_data, history, &Key::history)) {
  124. key.entry()->cachePinnedIndex(_filterId, 0);
  125. }
  126. }
  127. }
  128. void PinnedList::reorder(Key key1, Key key2) {
  129. const auto index1 = ranges::find(_data, key1) - begin(_data);
  130. const auto index2 = ranges::find(_data, key2) - begin(_data);
  131. Assert(index1 >= 0 && index1 < _data.size());
  132. Assert(index2 >= 0 && index2 < _data.size());
  133. Assert(index1 != index2);
  134. std::swap(_data[index1], _data[index2]);
  135. key1.entry()->cachePinnedIndex(_filterId, index2 + 1);
  136. key2.entry()->cachePinnedIndex(_filterId, index1 + 1);
  137. }
  138. } // namespace Dialogs