/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/timer.h" class PeerData; class HistoryItem; class DocumentData; namespace Data { class DocumentMedia; } // namespace Data namespace Main { class Session; } // namespace Main namespace HistoryView { class Element; } // namespace HistoryView namespace ChatHelpers { struct EmojiInteractionPlayRequest { QString emoticon; not_null item; std::shared_ptr media; crl::time shouldHaveStartedAt = 0; bool incoming = false; }; struct EmojiInteractionsBunch { struct Single { int index = 0; double time = 0; }; std::vector interactions; }; struct EmojiInteractionSeen { not_null peer; QString emoticon; }; class EmojiInteractions final { public: explicit EmojiInteractions(not_null session); ~EmojiInteractions(); using PlayRequest = EmojiInteractionPlayRequest; void startOutgoing(not_null view); void startIncoming( not_null peer, MsgId messageId, const QString &emoticon, EmojiInteractionsBunch &&bunch); void seenOutgoing(not_null peer, const QString &emoticon); [[nodiscard]] rpl::producer seen() const { return _seen.events(); } [[nodiscard]] rpl::producer playRequests() const { return _playRequests.events(); } void playStarted(not_null peer, QString emoji); [[nodiscard]] static EmojiInteractionsBunch Parse(const QByteArray &json); [[nodiscard]] static QByteArray ToJson( const EmojiInteractionsBunch &bunch); private: struct Animation { QString emoticon; not_null emoji; not_null document; std::shared_ptr media; crl::time scheduledAt = 0; crl::time startedAt = 0; bool incoming = false; int index = 0; }; struct PlaySent { mtpRequestId lastRequestId = 0; crl::time lastDoneReceivedAt = 0; }; struct CheckResult { crl::time nextCheckAt = 0; bool waitingForDownload = false; }; [[nodiscard]] static CheckResult Combine(CheckResult a, CheckResult b); [[nodiscard]] EmojiPtr chooseInteractionEmoji( not_null item) const; [[nodiscard]] EmojiPtr chooseInteractionEmoji( const QString &emoticon) const; void check(crl::time now = 0); [[nodiscard]] CheckResult checkAnimations(crl::time now); [[nodiscard]] CheckResult checkAnimations( crl::time now, base::flat_map, std::vector> &map); [[nodiscard]] CheckResult checkAccumulated(crl::time now); void sendAccumulatedOutgoing( crl::time now, not_null item, std::vector &animations); void clearAccumulatedIncoming( crl::time now, std::vector &animations); void setWaitingForDownload(bool waiting); void checkSeenRequests(crl::time now); void checkSentRequests(crl::time now); void checkEdition( not_null item, base::flat_map, std::vector> &map); const not_null _session; base::flat_map, std::vector> _outgoing; base::flat_map, std::vector> _incoming; base::Timer _checkTimer; rpl::event_stream _playRequests; base::flat_map< not_null, base::flat_map> _playStarted; base::flat_map< not_null, base::flat_map, PlaySent>> _playsSent; rpl::event_stream _seen; bool _waitingForDownload = false; rpl::lifetime _downloadCheckLifetime; rpl::lifetime _lifetime; }; } // namespace ChatHelpers