#pragma once #include #include #include #include #include #include #include #include namespace erebos { using std::mutex; using std::unique_ptr; class Contact; class Identity; struct DirectMessageState; class DirectMessage { public: const std::optional & from() const; const std::optional & time() const; std::string text() const; private: friend class DirectMessageThread; friend class DirectMessageService; struct Priv; DirectMessage(Priv *); std::shared_ptr p; }; class DirectMessageThread { public: class Iterator { struct Priv; Iterator(Priv *); public: using iterator_category = std::forward_iterator_tag; using value_type = DirectMessage; using difference_type = ssize_t; using pointer = const DirectMessage *; using reference = const DirectMessage &; Iterator(const Iterator &); ~Iterator(); Iterator & operator=(const Iterator &); Iterator & operator++(); value_type operator*() const; bool operator==(const Iterator &) const; bool operator!=(const Iterator &) const; private: friend DirectMessageThread; std::unique_ptr p; }; Iterator begin() const; Iterator end() const; size_t size() const; DirectMessage at(size_t) const; const Identity & peer() const; private: friend class DirectMessageService; friend class DirectMessageThreads; struct Priv; DirectMessageThread(Priv *); std::shared_ptr p; }; class DirectMessageThreads { public: DirectMessageThreads(); DirectMessageThreads(Stored); DirectMessageThreads(vector>); static DirectMessageThreads load(const vector & refs); vector store() const; vector> data() const; bool operator==(const DirectMessageThreads &) const; bool operator!=(const DirectMessageThreads &) const; DirectMessageThread thread(const Identity &) const; private: vector> state; friend class DirectMessageService; }; DECLARE_SHARED_TYPE(DirectMessageThreads) template<> struct Mergeable { using Component = DirectMessageState; static vector> components(const DirectMessageThreads &); static Contact merge(vector>); }; class DirectMessageService : public Service { public: using ThreadWatcher = std::function; class Config { public: Config & onUpdate(ThreadWatcher); private: friend class DirectMessageService; vector watchers; }; DirectMessageService(Config &&, const Server &); virtual ~DirectMessageService(); UUID uuid() const override; void handle(Context &) override; DirectMessageThread thread(const Identity &); DirectMessage send(const Identity &, const std::string &); DirectMessage send(const Contact &, const std::string &); DirectMessage send(const Peer &, const std::string &); private: void updateHandler(const DirectMessageThreads &); const Config config; const Server & server; vector> prevState; mutex stateMutex; Watched watched; }; }