recent_peers.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 "data/components/recent_peers.h"
  8. #include "main/main_session.h"
  9. #include "storage/serialize_common.h"
  10. #include "storage/serialize_peer.h"
  11. #include "storage/storage_account.h"
  12. namespace Data {
  13. namespace {
  14. constexpr auto kLimit = 48;
  15. } // namespace
  16. RecentPeers::RecentPeers(not_null<Main::Session*> session)
  17. : _session(session) {
  18. }
  19. RecentPeers::~RecentPeers() = default;
  20. const std::vector<not_null<PeerData*>> &RecentPeers::list() const {
  21. _session->local().readSearchSuggestions();
  22. return _list;
  23. }
  24. rpl::producer<> RecentPeers::updates() const {
  25. return _updates.events();
  26. }
  27. void RecentPeers::remove(not_null<PeerData*> peer) {
  28. const auto i = ranges::find(_list, peer);
  29. if (i != end(_list)) {
  30. _list.erase(i);
  31. _updates.fire({});
  32. }
  33. _session->local().writeSearchSuggestionsDelayed();
  34. }
  35. void RecentPeers::bump(not_null<PeerData*> peer) {
  36. _session->local().readSearchSuggestions();
  37. if (!_list.empty() && _list.front() == peer) {
  38. return;
  39. }
  40. auto i = ranges::find(_list, peer);
  41. if (i == end(_list)) {
  42. _list.push_back(peer);
  43. i = end(_list) - 1;
  44. }
  45. ranges::rotate(begin(_list), i, i + 1);
  46. _updates.fire({});
  47. _session->local().writeSearchSuggestionsDelayed();
  48. }
  49. void RecentPeers::clear() {
  50. _session->local().readSearchSuggestions();
  51. _list.clear();
  52. _updates.fire({});
  53. _session->local().writeSearchSuggestionsDelayed();
  54. }
  55. QByteArray RecentPeers::serialize() const {
  56. _session->local().readSearchSuggestions();
  57. if (_list.empty()) {
  58. return {};
  59. }
  60. auto size = 2 * sizeof(quint32); // AppVersion, count
  61. const auto count = std::min(int(_list.size()), kLimit);
  62. auto &&list = _list | ranges::views::take(count);
  63. for (const auto &peer : list) {
  64. size += Serialize::peerSize(peer);
  65. }
  66. auto stream = Serialize::ByteArrayWriter(size);
  67. stream
  68. << quint32(AppVersion)
  69. << quint32(count);
  70. for (const auto &peer : list) {
  71. Serialize::writePeer(stream, peer);
  72. }
  73. return std::move(stream).result();
  74. }
  75. void RecentPeers::applyLocal(QByteArray serialized) {
  76. _list.clear();
  77. if (serialized.isEmpty()) {
  78. DEBUG_LOG(("Suggestions: Bad RecentPeers local, empty."));
  79. return;
  80. }
  81. auto stream = Serialize::ByteArrayReader(serialized);
  82. auto streamAppVersion = quint32();
  83. auto count = quint32();
  84. stream >> streamAppVersion >> count;
  85. if (!stream.ok()) {
  86. DEBUG_LOG(("Suggestions: Bad RecentPeers local, not ok."));
  87. return;
  88. }
  89. DEBUG_LOG(("Suggestions: "
  90. "Start RecentPeers read, count: %1, version: %2."
  91. ).arg(count
  92. ).arg(streamAppVersion));
  93. _list.reserve(count);
  94. for (auto i = 0; i != int(count); ++i) {
  95. const auto streamPosition = stream.underlying().device()->pos();
  96. const auto peer = Serialize::readPeer(
  97. _session,
  98. streamAppVersion,
  99. stream);
  100. if (stream.ok() && peer) {
  101. _list.push_back(peer);
  102. } else {
  103. _list.clear();
  104. DEBUG_LOG(("Suggestions: Failed RecentPeers reading %1 / %2."
  105. ).arg(i + 1
  106. ).arg(count));
  107. DEBUG_LOG(("Failed bytes: %1.").arg(
  108. QString::fromUtf8(serialized.mid(streamPosition).toHex())));
  109. return;
  110. }
  111. }
  112. DEBUG_LOG(
  113. ("Suggestions: RecentPeers read OK, count: %1").arg(_list.size()));
  114. }
  115. } // namespace Data