aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-10-26 09:48:25 +0100
committerdec05eba <dec05eba@protonmail.com>2020-10-29 04:21:15 +0100
commit620123fbd6c18dc48a25cc735565f6d8d85f8639 (patch)
tree1563c8d2867f80f7c5cf00c15c8a1b6612de9f67 /plugins
parent0d432776c13f7b7bfd94d8ea2a7a41be33f21c8d (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.hpp188
-rw-r--r--plugins/Page.hpp6
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);