diff options
author | dec05eba <dec05eba@protonmail.com> | 2020-10-26 09:48:25 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2020-10-29 04:21:15 +0100 |
commit | 620123fbd6c18dc48a25cc735565f6d8d85f8639 (patch) | |
tree | 1563c8d2867f80f7c5cf00c15c8a1b6612de9f67 /plugins | |
parent | 0d432776c13f7b7bfd94d8ea2a7a41be33f21c8d (diff) |
Matrix: add room tags
Fix pinned events that are added after starting QuickMedia
(before this change it adds all elements again to the list).
Add /me command.
Other fixes...
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/Matrix.hpp | 188 | ||||
-rw-r--r-- | plugins/Page.hpp | 6 |
2 files changed, 163 insertions, 31 deletions
diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp index f0ca4f5..281f5a8 100644 --- a/plugins/Matrix.hpp +++ b/plugins/Matrix.hpp @@ -5,24 +5,11 @@ #include "Page.hpp" #include <SFML/Graphics/Color.hpp> #include <unordered_map> +#include <set> #include <mutex> #include <rapidjson/fwd.h> namespace QuickMedia { - // Dummy, only play one video. TODO: Play all videos in room, as related videos? - class MatrixVideoPage : public Page { - public: - MatrixVideoPage(Program *program) : Page(program) {} - const char* get_title() const override { return ""; } - PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override { - (void)title; - (void)url; - (void)result_tabs; - return PluginResult::ERR; - } - PageTypez get_type() const override { return PageTypez::VIDEO; } - }; - struct RoomData; struct UserInfo { @@ -78,8 +65,6 @@ namespace QuickMedia { // Ignores duplicates void append_messages(const std::vector<std::shared_ptr<Message>> &new_messages); - void append_pinned_events(std::vector<std::string> new_pinned_events); - std::shared_ptr<Message> get_message_by_id(const std::string &id); std::vector<std::shared_ptr<UserInfo>> get_users_excluding_me(const std::string &my_user_id); @@ -96,12 +81,16 @@ namespace QuickMedia { bool has_name(); void set_name(const std::string &new_name); + // TODO: Remove this std::string get_name(); bool has_avatar_url(); void set_avatar_url(const std::string &new_avatar_url); std::string get_avatar_url(); + void set_pinned_events(std::vector<std::string> new_pinned_events); + std::set<std::string>& get_tags_unsafe(); + std::string id; bool initial_fetch_finished = false; @@ -116,6 +105,9 @@ namespace QuickMedia { // TODO: Verify if replied to messages are also part of /sync; then this is not needed. std::unordered_map<std::string, std::shared_ptr<Message>> fetched_messages_by_event_id; + size_t messages_read_index = 0; + bool pinned_events_updated = false; + size_t index; private: std::mutex user_mutex; @@ -131,6 +123,7 @@ namespace QuickMedia { std::vector<std::shared_ptr<Message>> messages; std::unordered_map<std::string, std::shared_ptr<Message>> message_by_event_id; std::vector<std::string> pinned_events; + std::set<std::string> tags; }; enum class MessageDirection { @@ -150,25 +143,158 @@ namespace QuickMedia { struct SyncData { Messages messages; - std::vector<std::string> pinned_events; + std::optional<std::vector<std::string>> pinned_events; + std::optional<std::vector<std::string>> tags; }; - using RoomSyncData = std::unordered_map<RoomData*, SyncData>; using Rooms = std::vector<RoomData*>; bool message_contains_user_mention(const std::string &msg, const std::string &username); + enum class MatrixPageType { + ROOM_LIST, + CHAT + }; + + class MatrixDelegate { + public: + virtual ~MatrixDelegate() = default; + + virtual void room_create(RoomData *room) = 0; + // Note: calling |room| methods inside this function is not allowed + virtual void room_add_tag(RoomData *room, const std::string &tag) = 0; + // Note: calling |room| methods inside this function is not allowed + virtual void room_remove_tag(RoomData *room, const std::string &tag) = 0; + virtual void room_add_new_messages(RoomData *room, const Messages &messages, bool is_initial_sync) = 0; + + virtual void update(MatrixPageType page_type) { (void)page_type; } + }; + + class Matrix; + class MatrixRoomsPage; + class MatrixRoomTagsPage; + + class MatrixQuickMedia : public MatrixDelegate { + public: + MatrixQuickMedia(Program *program, Matrix *matrix, MatrixRoomsPage *rooms_page, MatrixRoomTagsPage *room_tags_page); + + void room_create(RoomData *room) override; + void room_add_tag(RoomData *room, const std::string &tag) override; + void room_remove_tag(RoomData *room, const std::string &tag) override; + void room_add_new_messages(RoomData *room, const Messages &messages, bool is_initial_sync) override; + + void update(MatrixPageType page_type) override; + + Program *program; + Matrix *matrix; + MatrixRoomsPage *rooms_page; + MatrixRoomTagsPage *room_tags_page; + private: + struct RoomMessagesData { + Messages messages; + bool is_initial_sync; + }; + + std::vector<std::shared_ptr<BodyItem>> room_body_items; + std::map<RoomData*, std::shared_ptr<BodyItem>> room_body_item_by_room; + std::map<RoomData*, RoomMessagesData> pending_room_messages; + std::mutex pending_room_messages_mutex; + }; + + class MatrixRoomsPage : public Page { + public: + MatrixRoomsPage(Program *program, Body *body, std::string title, MatrixRoomTagsPage *room_tags_page = nullptr); + ~MatrixRoomsPage() override; + + const char* get_title() const override { return title.c_str(); } + PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override; + + void update() override; + void add_body_item(std::shared_ptr<BodyItem> body_item); + + void move_room_to_top(RoomData *room); + + MatrixQuickMedia *matrix_delegate = nullptr; + private: + std::mutex mutex; + std::vector<std::shared_ptr<BodyItem>> room_body_items; + Body *body; + std::string title; + MatrixRoomTagsPage *room_tags_page; + }; + + class MatrixRoomTagsPage : public Page { + public: + MatrixRoomTagsPage(Program *program, Body *body) : Page(program), body(body) {} + const char* get_title() const override { return "Tags"; } + PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override; + + void update() override; + void add_room_body_item_to_tag(std::shared_ptr<BodyItem> body_item, const std::string &tag); + void remove_room_body_item_from_tag(std::shared_ptr<BodyItem> body_item, const std::string &tag); + + void move_room_to_top(RoomData *room); + + MatrixQuickMedia *matrix_delegate = nullptr; + MatrixRoomsPage *current_rooms_page = nullptr; + private: + struct TagData { + std::shared_ptr<BodyItem> tag_item; + std::vector<std::shared_ptr<BodyItem>> room_body_items; + }; + + std::mutex mutex; + Body *body; + std::map<std::string, TagData> tag_body_items_by_name; + std::map<std::string, std::vector<std::shared_ptr<BodyItem>>> add_room_body_items_by_tags; + std::map<std::string, std::vector<std::shared_ptr<BodyItem>>> remove_room_body_items_by_tags; + }; + + // Dummy, only play one video. TODO: Play all videos in room, as related videos? + class MatrixVideoPage : public Page { + public: + MatrixVideoPage(Program *program) : Page(program) {} + const char* get_title() const override { return ""; } + PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override { + (void)title; + (void)url; + (void)result_tabs; + return PluginResult::ERR; + } + PageTypez get_type() const override { return PageTypez::VIDEO; } + }; + + class MatrixChatPage : public Page { + public: + MatrixChatPage(Program *program, std::string room_id) : Page(program), room_id(std::move(room_id)) {} + const char* get_title() const override { return ""; } + PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override { + (void)title; + (void)url; + (void)result_tabs; + return PluginResult::ERR; + } + PageTypez get_type() const override { return PageTypez::CHAT; } + void update() override; + + const std::string room_id; + MatrixQuickMedia *matrix_delegate = nullptr; + }; + class Matrix { public: - PluginResult sync(RoomSyncData &room_sync_data); - void get_room_join_updates(Rooms &new_rooms); + void start_sync(MatrixDelegate *delegate); + void stop_sync(); + bool is_initial_sync_finished() const; + void get_room_sync_data(RoomData *room, SyncData &sync_data); + void get_all_synced_room_messages(RoomData *room, Messages &messages); void get_all_pinned_events(RoomData *room, std::vector<std::string> &events); PluginResult get_previous_room_messages(RoomData *room, Messages &messages); // |url| should only be set when uploading media. // TODO: Make api better. - PluginResult post_message(RoomData *room, const std::string &body, const std::optional<UploadInfo> &file_info, const std::optional<UploadInfo> &thumbnail_info); + PluginResult post_message(RoomData *room, const std::string &body, const std::optional<UploadInfo> &file_info, const std::optional<UploadInfo> &thumbnail_info, const std::string &msgtype = ""); // |relates_to| is from |BodyItem.userdata| and is of type |Message*| PluginResult post_reply(RoomData *room, const std::string &body, void *relates_to); // |relates_to| is from |BodyItem.userdata| and is of type |Message*| @@ -201,28 +327,27 @@ namespace QuickMedia { // Returns nullptr if message cant be found. Note: cached std::shared_ptr<Message> get_message_by_id(RoomData *room, const std::string &event_id); + RoomData* get_room_by_id(const std::string &id); + bool use_tor = false; private: - PluginResult sync_response_to_body_items(const rapidjson::Document &root, RoomSyncData &room_sync_data); + PluginResult parse_sync_response(const rapidjson::Document &root, MatrixDelegate *delegate); + PluginResult parse_sync_account_data(const rapidjson::Value &account_data_json, std::optional<std::set<std::string>> &dm_rooms); + PluginResult parse_sync_room_data(const rapidjson::Value &rooms_json, MatrixDelegate *delegate); PluginResult get_previous_room_messages(RoomData *room_data); void events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data); void events_add_user_read_markers(const rapidjson::Value &events_json, RoomData *room_data); - void events_add_messages(const rapidjson::Value &events_json, RoomData *room_data, MessageDirection message_dir, RoomSyncData *room_sync_data, bool has_unread_notifications); + void events_add_messages(const rapidjson::Value &events_json, RoomData *room_data, MessageDirection message_dir, MatrixDelegate *delegate, bool has_unread_notifications); void events_set_room_name(const rapidjson::Value &events_json, RoomData *room_data); - void events_add_pinned_events(const rapidjson::Value &events_json, RoomData *room_data, RoomSyncData &room_sync_data); - void events_add_room_to_tags(const rapidjson::Value &events_json, RoomData *room_data); + void events_add_pinned_events(const rapidjson::Value &events_json, RoomData *room_data); + void events_add_room_to_tags(const rapidjson::Value &events_json, RoomData *room_data, MatrixDelegate *delegate); std::shared_ptr<Message> parse_message_event(const rapidjson::Value &event_item_json, RoomData *room_data); PluginResult upload_file(RoomData *room, const std::string &filepath, UploadInfo &file_info, UploadInfo &thumbnail_info, std::string &err_msg); - - std::shared_ptr<Message> get_edited_message_original_message(RoomData *room_data, std::shared_ptr<Message> message); - - RoomData* get_room_by_id(const std::string &id); void add_room(std::unique_ptr<RoomData> room); DownloadResult download_json(rapidjson::Document &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent = false, std::string *err_msg = nullptr) const; private: std::vector<std::unique_ptr<RoomData>> rooms; std::unordered_map<std::string, size_t> room_data_by_id; // value is an index into |rooms| - std::map<std::string, std::vector<size_t>> rooms_by_tag_name; // value is an index into |rooms| size_t room_list_read_index = 0; std::mutex room_data_mutex; std::string user_id; @@ -231,5 +356,8 @@ namespace QuickMedia { std::string homeserver; std::optional<int> upload_limit; std::string next_batch; + + std::thread sync_thread; + bool sync_running = false; }; }
\ No newline at end of file diff --git a/plugins/Page.hpp b/plugins/Page.hpp index de80b4f..cc7dad6 100644 --- a/plugins/Page.hpp +++ b/plugins/Page.hpp @@ -14,7 +14,8 @@ namespace QuickMedia { REGULAR, MANGA_IMAGES, IMAGE_BOARD_THREAD, - VIDEO + VIDEO, + CHAT }; class Page { @@ -46,6 +47,9 @@ namespace QuickMedia { // This is called both when first navigating to page and when going back to page virtual void on_navigate_to_page() {}; + // Called periodically (every frame right now) if this page is the currently active one + virtual void update() {} + bool is_tor_enabled(); std::unique_ptr<Body> create_body(); std::unique_ptr<SearchBar> create_search_bar(const std::string &placeholder_text, int search_delay); |