2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-30 22:16:14 +00:00

Show emoji interaction seen status.

This commit is contained in:
John Preston
2021-09-17 00:14:53 +03:00
parent 4b7f594b0e
commit 34c0d97c54
7 changed files with 215 additions and 20 deletions

View File

@@ -33,6 +33,7 @@ namespace {
constexpr auto kMinDelay = crl::time(200);
constexpr auto kAccumulateDelay = crl::time(1000);
constexpr auto kAccumulateSeenRequests = kAccumulateDelay;
constexpr auto kAcceptSeenSinceRequest = 3 * crl::time(1000);
constexpr auto kMaxDelay = 2 * crl::time(1000);
constexpr auto kTimeNever = std::numeric_limits<crl::time>::max();
constexpr auto kJsonVersion = 1;
@@ -177,6 +178,21 @@ void EmojiInteractions::startIncoming(
}
}
void EmojiInteractions::seenOutgoing(
not_null<PeerData*> peer,
const QString &emoticon) {
if (const auto i = _playsSent.find(peer); i != end(_playsSent)) {
if (const auto emoji = Ui::Emoji::Find(emoticon)) {
if (const auto j = i->second.find(emoji); j != end(i->second)) {
const auto last = j->second.lastDoneReceivedAt;
if (!last || last + kAcceptSeenSinceRequest > crl::now()) {
_seen.fire({ peer, emoji });
}
}
}
}
}
auto EmojiInteractions::checkAnimations(crl::time now) -> CheckResult {
return Combine(
checkAnimations(now, _outgoing),
@@ -254,15 +270,26 @@ void EmojiInteractions::sendAccumulatedOutgoing(
if (bunch.interactions.empty()) {
return;
}
_session->api().request(MTPmessages_SetTyping(
const auto peer = item->history()->peer;
const auto emoji = from->emoji;
const auto requestId = _session->api().request(MTPmessages_SetTyping(
MTP_flags(0),
item->history()->peer->input,
peer->input,
MTPint(), // top_msg_id
MTP_sendMessageEmojiInteraction(
MTP_string(from->emoji->text()),
MTP_string(emoji->text()),
MTP_int(item->id),
MTP_dataJSON(MTP_bytes(ToJson(bunch))))
)).send();
)).done([=](const MTPBool &result, mtpRequestId requestId) {
auto &sent = _playsSent[peer][emoji];
if (sent.lastRequestId == requestId) {
sent.lastDoneReceivedAt = crl::now();
if (!_checkTimer.isActive()) {
_checkTimer.callOnce(kAcceptSeenSinceRequest);
}
}
}).send();
_playsSent[peer][emoji] = PlaySent{ .lastRequestId = requestId };
animations.erase(from, till);
}
@@ -315,6 +342,7 @@ void EmojiInteractions::check(crl::time now) {
now = crl::now();
}
checkSeenRequests(now);
checkSentRequests(now);
const auto result1 = checkAnimations(now);
const auto result2 = checkAccumulated(now);
const auto result = Combine(result1, result2);
@@ -323,6 +351,8 @@ void EmojiInteractions::check(crl::time now) {
_checkTimer.callOnce(result.nextCheckAt - now);
} else if (!_playStarted.empty()) {
_checkTimer.callOnce(kAccumulateSeenRequests);
} else if (!_playsSent.empty()) {
_checkTimer.callOnce(kAcceptSeenSinceRequest);
}
setWaitingForDownload(result.waitingForDownload);
}
@@ -344,6 +374,24 @@ void EmojiInteractions::checkSeenRequests(crl::time now) {
}
}
void EmojiInteractions::checkSentRequests(crl::time now) {
for (auto i = begin(_playsSent); i != end(_playsSent);) {
for (auto j = begin(i->second); j != end(i->second);) {
const auto last = j->second.lastDoneReceivedAt;
if (last && last + kAcceptSeenSinceRequest <= now) {
j = i->second.erase(j);
} else {
++j;
}
}
if (i->second.empty()) {
i = _playsSent.erase(i);
} else {
++i;
}
}
}
void EmojiInteractions::setWaitingForDownload(bool waiting) {
if (_waitingForDownload == waiting) {
return;

View File

@@ -43,6 +43,11 @@ struct EmojiInteractionsBunch {
std::vector<Single> interactions;
};
struct EmojiInteractionSeen {
not_null<PeerData*> peer;
not_null<EmojiPtr> emoji;
};
class EmojiInteractions final {
public:
explicit EmojiInteractions(not_null<Main::Session*> session);
@@ -57,6 +62,11 @@ public:
const QString &emoticon,
EmojiInteractionsBunch &&bunch);
void seenOutgoing(not_null<PeerData*> peer, const QString &emoticon);
[[nodiscard]] rpl::producer<EmojiInteractionSeen> seen() const {
return _seen.events();
}
[[nodiscard]] rpl::producer<PlayRequest> playRequests() const {
return _playRequests.events();
}
@@ -68,7 +78,7 @@ public:
private:
struct Animation {
EmojiPtr emoji;
not_null<EmojiPtr> emoji;
not_null<DocumentData*> document;
std::shared_ptr<Data::DocumentMedia> media;
crl::time scheduledAt = 0;
@@ -76,6 +86,10 @@ private:
bool incoming = false;
int index = 0;
};
struct PlaySent {
mtpRequestId lastRequestId = 0;
crl::time lastDoneReceivedAt = 0;
};
struct CheckResult {
crl::time nextCheckAt = 0;
bool waitingForDownload = false;
@@ -98,6 +112,7 @@ private:
void setWaitingForDownload(bool waiting);
void checkSeenRequests(crl::time now);
void checkSentRequests(crl::time now);
void checkEdition(
not_null<HistoryItem*> item,
base::flat_map<not_null<HistoryItem*>, std::vector<Animation>> &map);
@@ -111,6 +126,10 @@ private:
base::flat_map<
not_null<PeerData*>,
base::flat_map<QString, crl::time>> _playStarted;
base::flat_map<
not_null<PeerData*>,
base::flat_map<not_null<EmojiPtr>, PlaySent>> _playsSent;
rpl::event_stream<EmojiInteractionSeen> _seen;
bool _waitingForDownload = false;
rpl::lifetime _downloadCheckLifetime;