mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 06:35:14 +00:00
Show emoji interaction seen status.
This commit is contained in:
@@ -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;
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user