api_unread_things.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 "api/api_unread_things.h"
  8. #include "data/data_peer.h"
  9. #include "data/data_channel.h"
  10. #include "data/data_forum_topic.h"
  11. #include "data/data_session.h"
  12. #include "main/main_session.h"
  13. #include "history/history.h"
  14. #include "history/history_item.h"
  15. #include "history/history_unread_things.h"
  16. #include "apiwrap.h"
  17. namespace Api {
  18. namespace {
  19. constexpr auto kPreloadIfLess = 5;
  20. constexpr auto kFirstRequestLimit = 10;
  21. constexpr auto kNextRequestLimit = 100;
  22. } // namespace
  23. UnreadThings::UnreadThings(not_null<ApiWrap*> api) : _api(api) {
  24. }
  25. bool UnreadThings::trackMentions(Data::Thread *thread) const {
  26. const auto peer = thread ? thread->peer().get() : nullptr;
  27. return peer && (peer->isChat() || peer->isMegagroup());
  28. }
  29. bool UnreadThings::trackReactions(Data::Thread *thread) const {
  30. const auto peer = thread ? thread->peer().get() : nullptr;
  31. return peer && (peer->isUser() || peer->isChat() || peer->isMegagroup());
  32. }
  33. void UnreadThings::preloadEnough(Data::Thread *thread) {
  34. if (trackMentions(thread)) {
  35. preloadEnoughMentions(thread);
  36. }
  37. if (trackReactions(thread)) {
  38. preloadEnoughReactions(thread);
  39. }
  40. }
  41. void UnreadThings::mediaAndMentionsRead(
  42. const base::flat_set<MsgId> &readIds,
  43. ChannelData *channel) {
  44. for (const auto &msgId : readIds) {
  45. _api->requestMessageData(channel, msgId, [=] {
  46. const auto item = channel
  47. ? _api->session().data().message(channel->id, msgId)
  48. : _api->session().data().nonChannelMessage(msgId);
  49. if (item && item->mentionsMe()) {
  50. item->markMediaAndMentionRead();
  51. }
  52. });
  53. }
  54. }
  55. void UnreadThings::preloadEnoughMentions(not_null<Data::Thread*> thread) {
  56. const auto fullCount = thread->unreadMentions().count();
  57. const auto loadedCount = thread->unreadMentions().loadedCount();
  58. const auto allLoaded = (fullCount >= 0) && (loadedCount >= fullCount);
  59. if (fullCount >= 0 && loadedCount < kPreloadIfLess && !allLoaded) {
  60. requestMentions(thread, loadedCount);
  61. }
  62. }
  63. void UnreadThings::preloadEnoughReactions(not_null<Data::Thread*> thread) {
  64. const auto fullCount = thread->unreadReactions().count();
  65. const auto loadedCount = thread->unreadReactions().loadedCount();
  66. const auto allLoaded = (fullCount >= 0) && (loadedCount >= fullCount);
  67. if (fullCount >= 0 && loadedCount < kPreloadIfLess && !allLoaded) {
  68. requestReactions(thread, loadedCount);
  69. }
  70. }
  71. void UnreadThings::cancelRequests(not_null<Data::Thread*> thread) {
  72. if (const auto requestId = _mentionsRequests.take(thread)) {
  73. _api->request(*requestId).cancel();
  74. }
  75. if (const auto requestId = _reactionsRequests.take(thread)) {
  76. _api->request(*requestId).cancel();
  77. }
  78. }
  79. void UnreadThings::requestMentions(
  80. not_null<Data::Thread*> thread,
  81. int loaded) {
  82. if (_mentionsRequests.contains(thread)) {
  83. return;
  84. }
  85. const auto offsetId = std::max(
  86. thread->unreadMentions().maxLoaded(),
  87. MsgId(1));
  88. const auto limit = loaded ? kNextRequestLimit : kFirstRequestLimit;
  89. const auto addOffset = loaded ? -(limit + 1) : -limit;
  90. const auto maxId = 0;
  91. const auto minId = 0;
  92. const auto history = thread->owningHistory();
  93. const auto topic = thread->asTopic();
  94. using Flag = MTPmessages_GetUnreadMentions::Flag;
  95. const auto requestId = _api->request(MTPmessages_GetUnreadMentions(
  96. MTP_flags(topic ? Flag::f_top_msg_id : Flag()),
  97. history->peer->input,
  98. MTP_int(topic ? topic->rootId() : 0),
  99. MTP_int(offsetId),
  100. MTP_int(addOffset),
  101. MTP_int(limit),
  102. MTP_int(maxId),
  103. MTP_int(minId)
  104. )).done([=](const MTPmessages_Messages &result) {
  105. _mentionsRequests.remove(thread);
  106. thread->unreadMentions().addSlice(result, loaded);
  107. }).fail([=] {
  108. _mentionsRequests.remove(thread);
  109. }).send();
  110. _mentionsRequests.emplace(thread, requestId);
  111. }
  112. void UnreadThings::requestReactions(
  113. not_null<Data::Thread*> thread,
  114. int loaded) {
  115. if (_reactionsRequests.contains(thread)) {
  116. return;
  117. }
  118. const auto offsetId = loaded
  119. ? std::max(thread->unreadReactions().maxLoaded(), MsgId(1))
  120. : MsgId(1);
  121. const auto limit = loaded ? kNextRequestLimit : kFirstRequestLimit;
  122. const auto addOffset = loaded ? -(limit + 1) : -limit;
  123. const auto maxId = 0;
  124. const auto minId = 0;
  125. const auto history = thread->owningHistory();
  126. const auto topic = thread->asTopic();
  127. using Flag = MTPmessages_GetUnreadReactions::Flag;
  128. const auto requestId = _api->request(MTPmessages_GetUnreadReactions(
  129. MTP_flags(topic ? Flag::f_top_msg_id : Flag()),
  130. history->peer->input,
  131. MTP_int(topic ? topic->rootId() : 0),
  132. MTP_int(offsetId),
  133. MTP_int(addOffset),
  134. MTP_int(limit),
  135. MTP_int(maxId),
  136. MTP_int(minId)
  137. )).done([=](const MTPmessages_Messages &result) {
  138. _reactionsRequests.remove(thread);
  139. thread->unreadReactions().addSlice(result, loaded);
  140. }).fail([=] {
  141. _reactionsRequests.remove(thread);
  142. }).send();
  143. _reactionsRequests.emplace(thread, requestId);
  144. }
  145. } // namespace UnreadThings