aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-10-30 16:47:40 +0100
committerdec05eba <dec05eba@protonmail.com>2020-10-30 18:30:46 +0100
commit928f2525c29929de0c2ab520f48c82b5cb882aa7 (patch)
treee97130909f65e7835e4740824e9f38f58e4c0fbe
parente422322650f9cb057937182987071438f9c79e84 (diff)
Matrix: re-add /logout, cancel task immediately
Cancel video download when pressing escape, other fixes..
-rw-r--r--README.md1
-rw-r--r--TODO7
-rw-r--r--images/matrix_logo.pngbin1199 -> 6323 bytes
-rw-r--r--include/AsyncTask.hpp9
-rw-r--r--include/Body.hpp3
-rw-r--r--include/Program.hpp (renamed from include/Program.h)16
-rw-r--r--include/QuickMedia.hpp1
-rw-r--r--plugins/Manga.hpp2
-rw-r--r--plugins/Page.hpp2
-rw-r--r--src/Body.cpp10
-rw-r--r--src/DownloadUtils.cpp3
-rw-r--r--src/FileAnalyzer.cpp2
-rw-r--r--src/Notification.cpp2
-rw-r--r--src/Program.cpp (renamed from src/Program.c)47
-rw-r--r--src/QuickMedia.cpp222
-rw-r--r--src/VideoPlayer.cpp2
-rw-r--r--src/plugins/Manga.cpp5
-rw-r--r--src/plugins/Matrix.cpp11
-rw-r--r--src/plugins/NyaaSi.cpp2
19 files changed, 222 insertions, 125 deletions
diff --git a/README.md b/README.md
index 1ee7f5e..53a2335 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,7 @@ Press `M` to begin writing a message in a matrix room, press `ESC` to cancel.\
Press `R` to reply to a message on matrix, press `ESC` to cancel.\
Press `E` to edit a message on matrix, press `ESC` to cancel. Currently only works for your own messages.\
Press `D` to delete a message on matrix. Currently deleting a message only deletes the event, so if you delete an edit then the original message wont be deleted.\
+Press `Ctrl + C` to copy the message of the selected item in matrix to the clipboard.\
Press `Ctrl + V` to upload media to room in matrix if the clipboard contains a valid absolute filepath.
In matrix you can select a message with enter to open the url in the message (or if there are multiple urls then a menu will appear for selecting which to open).
diff --git a/TODO b/TODO
index d87feb1..b7c43d2 100644
--- a/TODO
+++ b/TODO
@@ -55,7 +55,7 @@ Scroll to bottom when receiving a new message even if the selected message is no
Also add a tab for common directories and recently accessed files/directories (the directories would be the directory of used files).
Provide a way to go to the first unread message in matrix and also show a marker in the body (maybe a red line?) where the first unread message is.
Allow scrolling body item. A body item can be long and we wont be able to read all of it otherwise (such as a message on matrix). Pressing up/down should scroll such a large body item rather than moving to another one.
-Cleanup keybindings. Some require ctrl, some dont (4chan vs matrix for example).
+Cleanup keybindings. Some require ctrl, some dont.
Add room topic beside room name in matrix (in messages tab).
Move rooms in matrix to previous page instead, then messages can be beside users, pinned messages, settings, etc and they would all be connected to that one room, then beside rooms tab there would be a global settings tab.
Add /me to matrix, emoji, reactions...
@@ -123,4 +123,7 @@ Replying to edited message shows incorrect body in matrix.
Show in room tags list when there is a message in any of the rooms in the tag.
Apply current search filter when adding new rooms to the room list.
Cancel video download when pressing escape or closing window (important in matrix).
-Support webp. \ No newline at end of file
+Support webp.
+Reload history/recommendations after closing a video.
+Show images while they download by showing them as scanlines starting from the top. Needed for slow websites such as 4chan.
+Use curl parallel download instead of downloading with multiple threads. \ No newline at end of file
diff --git a/images/matrix_logo.png b/images/matrix_logo.png
index 055a9c7..29a2ee3 100644
--- a/images/matrix_logo.png
+++ b/images/matrix_logo.png
Binary files differ
diff --git a/include/AsyncTask.hpp b/include/AsyncTask.hpp
new file mode 100644
index 0000000..81be1ee
--- /dev/null
+++ b/include/AsyncTask.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <functional>
+#include <deque>
+#include <mutex>
+
+namespace QuickMedia {
+
+} \ No newline at end of file
diff --git a/include/Body.hpp b/include/Body.hpp
index 9cdcd7b..1dc1fe8 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -147,14 +147,13 @@ namespace QuickMedia {
// Select next item, ignoring invisible items. Returns true if the item was changed. This can be used to check if the bottom was hit when wrap_around is set to false
bool select_next_item();
- void set_selected_item(int item);
+ void set_selected_item(int item, bool reset_prev_selected_item = true);
// Returns -1 if item can't be found
int get_index_by_body_item(BodyItem *body_item);
void select_first_item();
void select_last_item();
- void reset_selected();
void clear_items();
void prepend_items(BodyItems new_items);
void append_items(BodyItems new_items);
diff --git a/include/Program.h b/include/Program.hpp
index cab8d26..8ac2d2d 100644
--- a/include/Program.h
+++ b/include/Program.hpp
@@ -1,11 +1,8 @@
-#ifndef QUICKMEDIA_PROGRAM_H
-#define QUICKMEDIA_PROGRAM_H
+#ifndef QUICKMEDIA_PROGRAM_HPP
+#define QUICKMEDIA_PROGRAM_HPP
#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <thread>
typedef struct {
pid_t pid;
@@ -41,8 +38,7 @@ int wait_program_non_blocking(pid_t process_id, int *status);
*/
int exec_program_async(const char **args, pid_t *result_process_id);
-#ifdef __cplusplus
-}
-#endif
+void program_clear_current_thread();
+void program_kill_in_thread(const std::thread::id &thread_id);
-#endif
+#endif /* QUICKMEDIA_PROGRAM_HPP */
diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp
index 99bab7a..6f8e3ff 100644
--- a/include/QuickMedia.hpp
+++ b/include/QuickMedia.hpp
@@ -63,6 +63,7 @@ namespace QuickMedia {
void image_board_thread_page(ImageBoardThreadPage *thread_page, Body *thread_body);
void chat_login_page();
void chat_page(MatrixChatPage *chat_page, RoomData *current_room);
+ void after_matrix_login_page();
enum class LoadImageResult {
OK,
diff --git a/plugins/Manga.hpp b/plugins/Manga.hpp
index d3725da..afd8a3c 100644
--- a/plugins/Manga.hpp
+++ b/plugins/Manga.hpp
@@ -53,7 +53,7 @@ namespace QuickMedia {
public:
MangaChaptersPage(Program *program, std::string manga_name, std::string manga_url) : TrackablePage(program, std::move(manga_name), std::move(manga_url)) {}
TrackResult track(const std::string &str) override;
- void on_navigate_to_page() override;
+ void on_navigate_to_page(BodyItems &body_items) override;
protected:
virtual bool extract_id_from_url(const std::string &url, std::string &manga_id) const = 0;
virtual const char* get_service_name() const = 0;
diff --git a/plugins/Page.hpp b/plugins/Page.hpp
index cc7dad6..db844c5 100644
--- a/plugins/Page.hpp
+++ b/plugins/Page.hpp
@@ -45,7 +45,7 @@ namespace QuickMedia {
virtual bool is_lazy_fetch_page() const { return false; }
// This is called both when first navigating to page and when going back to page
- virtual void on_navigate_to_page() {};
+ virtual void on_navigate_to_page(BodyItems &body_items) { (void)body_items; }
// Called periodically (every frame right now) if this page is the currently active one
virtual void update() {}
diff --git a/src/Body.cpp b/src/Body.cpp
index 7f96263..3f5c755 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -186,10 +186,11 @@ namespace QuickMedia {
return true;
}
- void Body::set_selected_item(int item) {
+ void Body::set_selected_item(int item, bool reset_prev_selected_item) {
//assert(item >= 0 && item < (int)items.size());
selected_item = item;
- prev_selected_item = selected_item;
+ if(reset_prev_selected_item)
+ prev_selected_item = selected_item;
clamp_selection();
//page_scroll = 0.0f;
}
@@ -216,10 +217,6 @@ namespace QuickMedia {
clamp_selection();
}
- void Body::reset_selected() {
- select_first_item();
- }
-
void Body::clear_items() {
items.clear();
selected_item = 0;
@@ -235,6 +232,7 @@ namespace QuickMedia {
items.insert(items.end(), std::make_move_iterator(new_items.begin()), std::make_move_iterator(new_items.end()));
}
+ // TODO: Binary search and use hint to start search from start or end (for example when adding "previous" items or "next" items)
void Body::insert_item_by_timestamp(std::shared_ptr<BodyItem> body_item) {
for(size_t i = 0; i < items.size(); ++i) {
if(body_item->get_timestamp() < items[i]->get_timestamp()) {
diff --git a/src/DownloadUtils.cpp b/src/DownloadUtils.cpp
index fd7e7d1..cbdded6 100644
--- a/src/DownloadUtils.cpp
+++ b/src/DownloadUtils.cpp
@@ -1,5 +1,5 @@
#include "../include/DownloadUtils.hpp"
-#include "../include/Program.h"
+#include "../include/Program.hpp"
#include "../include/Storage.hpp"
#include "../include/base64_url.hpp"
#include <SFML/System/Clock.hpp>
@@ -141,6 +141,7 @@ namespace QuickMedia {
char read_buffer[8192];
rapidjson::FileReadStream is(file, read_buffer, sizeof(read_buffer));
rapidjson::ParseResult parse_result = result.ParseStream(is);
+ program_clear_current_thread();
fclose(file);
wait_program(read_program.pid);
diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp
index 82d2c06..8d5eae8 100644
--- a/src/FileAnalyzer.cpp
+++ b/src/FileAnalyzer.cpp
@@ -1,5 +1,5 @@
#include "../include/FileAnalyzer.hpp"
-#include "../include/Program.h"
+#include "../include/Program.hpp"
#include <sys/stat.h>
#include <stdio.h>
#include <array>
diff --git a/src/Notification.cpp b/src/Notification.cpp
index 1201557..9ffbaac 100644
--- a/src/Notification.cpp
+++ b/src/Notification.cpp
@@ -1,5 +1,5 @@
#include "../include/Notification.hpp"
-#include "../include/Program.h"
+#include "../include/Program.hpp"
#include <assert.h>
#include <stdio.h>
diff --git a/src/Program.c b/src/Program.cpp
index a82bcd2..136a494 100644
--- a/src/Program.c
+++ b/src/Program.cpp
@@ -1,4 +1,4 @@
-#include "../include/Program.h"
+#include "../include/Program.hpp"
#include <unistd.h>
#include <sys/wait.h>
#include <sys/prctl.h>
@@ -7,10 +7,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <unordered_map>
+#include <mutex>
+#include <signal.h>
#define READ_END 0
#define WRITE_END 1
+class CurrentThreadProgram {
+public:
+ void set(ReadProgram read_program) {
+ std::lock_guard<std::mutex> lock(mutex);
+ thread_current_program[std::this_thread::get_id()] = read_program;
+ }
+
+ void clear() {
+ std::lock_guard<std::mutex> lock(mutex);
+ thread_current_program.erase(std::this_thread::get_id());
+ }
+
+ void kill_in_thread(const std::thread::id &thread_id) {
+ std::lock_guard<std::mutex> lock(mutex);
+ auto it = thread_current_program.find(thread_id);
+ if(it != thread_current_program.end()) {
+ close(it->second.read_fd);
+ kill(it->second.pid, SIGTERM);
+ }
+ }
+private:
+ std::unordered_map<std::thread::id, ReadProgram> thread_current_program;
+ std::mutex mutex;
+};
+
+static CurrentThreadProgram current_thread_program;
+
int exec_program_pipe(const char **args, ReadProgram *read_program) {
/* 1 arguments */
if(args[0] == NULL)
@@ -51,6 +81,7 @@ int exec_program_pipe(const char **args, ReadProgram *read_program) {
close(fd[WRITE_END]);
read_program->pid = pid;
read_program->read_fd = fd[READ_END];
+ current_thread_program.set(*read_program);
return 0;
}
}
@@ -63,6 +94,7 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
int result = 0;
int status;
+ int exit_status;
char buffer[4097];
@@ -77,6 +109,8 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
break;
}
+ //check if running. Also do the same in download_to_json
+
buffer[bytes_read] = '\0';
if(output_callback) {
result = output_callback(buffer, bytes_read, userdata);
@@ -84,6 +118,7 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
break;
}
}
+ program_clear_current_thread();
if(result != 0)
kill(read_program.pid, SIGTERM);
@@ -99,7 +134,7 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
goto cleanup;
}
- int exit_status = WEXITSTATUS(status);
+ exit_status = WEXITSTATUS(status);
if(exit_status != 0) {
fprintf(stderr, "Failed to execute program (");
const char **arg = args;
@@ -201,3 +236,11 @@ int exec_program_async(const char **args, pid_t *result_process_id) {
}
return 0;
}
+
+void program_clear_current_thread() {
+ current_thread_program.clear();
+}
+
+void program_kill_in_thread(const std::thread::id &thread_id) {
+ current_thread_program.kill_in_thread(thread_id);
+}
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index ba9a680..3b99d55 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -9,7 +9,7 @@
#include "../plugins/Matrix.hpp"
#include "../plugins/FileManager.hpp"
#include "../include/Scale.hpp"
-#include "../include/Program.h"
+#include "../include/Program.hpp"
#include "../include/VideoPlayer.hpp"
#include "../include/StringUtils.hpp"
#include "../include/GoogleCaptcha.hpp"
@@ -641,51 +641,7 @@ namespace QuickMedia {
chat_login_page();
}
- if(!window.isOpen())
- return exit_code;
-
- auto rooms_body = create_body();
- rooms_body->thumbnail_mask_shader = &circle_mask_shader;
- auto matrix_rooms_page = std::make_unique<MatrixRoomsPage>(this, rooms_body.get(), "All rooms");
-
- auto rooms_tags_body = create_body();
- rooms_tags_body->thumbnail_mask_shader = &circle_mask_shader;
- auto matrix_rooms_tag_page = std::make_unique<MatrixRoomTagsPage>(this, rooms_tags_body.get());
-
- MatrixQuickMedia matrix_handler(this, matrix, matrix_rooms_page.get(), matrix_rooms_tag_page.get());
- matrix->start_sync(&matrix_handler);
-
- tabs.push_back(Tab{std::move(rooms_body), std::move(matrix_rooms_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
- tabs.push_back(Tab{std::move(rooms_tags_body), std::move(matrix_rooms_tag_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
-
- sf::Sprite load_sprite(loading_icon);
- sf::Vector2u loading_icon_size = loading_icon.getSize();
- load_sprite.setOrigin(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f);
-
- sf::Clock timer;
- sf::Event event;
- while(window.isOpen() && !matrix->is_initial_sync_finished()) {
- while(window.pollEvent(event)) {
- if(event.type == sf::Event::Closed)
- window.close();
- else if(event.type == sf::Event::Resized) {
- window_size.x = event.size.width;
- window_size.y = event.size.height;
- sf::FloatRect visible_area(0, 0, window_size.x, window_size.y);
- window.setView(sf::View(visible_area));
- }
- }
- window.clear(back_color);
- load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f);
- load_sprite.setRotation(timer.getElapsedTime().asSeconds() * 400.0);
- window.draw(load_sprite);
- window.display();
- }
-
- while(window.isOpen()) {
- page_loop(tabs);
- }
-
+ after_matrix_login_page();
exit(exit_code); // Exit immediately without waiting for anything to finish
//matrix->stop_sync();
}
@@ -975,6 +931,16 @@ namespace QuickMedia {
return current_chat_room;
}
+ static void select_body_item_by_room(Body *body, RoomData *room) {
+ for(size_t i = 0; i < body->items.size(); ++i) {
+ auto &body_item = body->items[i];
+ if(body_item->userdata == room) {
+ body->set_selected_item(i, false);
+ return;
+ }
+ }
+ }
+
void Program::page_loop(std::vector<Tab> &tabs) {
if(tabs.empty()) {
show_notification("QuickMedia", "No tabs provided!", Urgency::CRITICAL);
@@ -983,7 +949,7 @@ namespace QuickMedia {
for(Tab &tab : tabs) {
tab.body->thumbnail_max_size = tab.page->get_thumbnail_max_size();
- tab.page->on_navigate_to_page();
+ tab.page->on_navigate_to_page(tab.body->items);
}
const Json::Value *json_chapters = &Json::Value::nullSingleton();
@@ -1106,11 +1072,12 @@ namespace QuickMedia {
current_page = PageType::CHAT;
current_chat_room = matrix->get_room_by_id(selected_item->url);
chat_page(static_cast<MatrixChatPage*>(new_tabs[0].page.get()), current_chat_room);
+ select_body_item_by_room(tabs[selected_tab].body.get(), current_chat_room);
current_chat_room = nullptr;
} else {
page_loop(new_tabs);
}
- tabs[selected_tab].page->on_navigate_to_page();
+ tabs[selected_tab].page->on_navigate_to_page(tabs[selected_tab].body->items);
if(content_storage_json.isObject()) {
const Json::Value &chapters_json = content_storage_json["chapters"];
if(chapters_json.isObject())
@@ -1614,9 +1581,11 @@ namespace QuickMedia {
video_url = std::move(video_path.data);
video_url_is_local = true;
} else {
- std::future<DownloadResult> download_future = std::async(std::launch::async, [this, &video_path, video_url]() {
- return download_to_file(video_url, video_path.data, {}, use_tor, true);
- });
+ std::promise<DownloadResult> download_result_promise;
+ std::future<DownloadResult> download_future = download_result_promise.get_future();
+ std::thread download_thread([this, &video_path, video_url](std::promise<DownloadResult> &&promise) {
+ promise.set_value(download_to_file(video_url, video_path.data, {}, use_tor, true));
+ }, std::move(download_result_promise));
window_size.x = window.getSize().x;
window_size.y = window.getSize().y;
@@ -1625,9 +1594,8 @@ namespace QuickMedia {
while(window.isOpen()) {
while(window.pollEvent(event)) {
if(event.type == sf::Event::Closed) {
- // TODO: Remove this
- if(download_future.valid())
- download_future.get();
+ program_kill_in_thread(download_thread.get_id());
+ download_thread.join();
current_page = previous_page;
window.close();
return;
@@ -1637,16 +1605,17 @@ namespace QuickMedia {
sf::FloatRect visible_area(0, 0, window_size.x, window_size.y);
window.setView(sf::View(visible_area));
} else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
- // TODO: Remove this
- if(download_future.valid())
- download_future.get();
+ program_kill_in_thread(download_thread.get_id());
+ download_thread.join();
current_page = previous_page;
return;
}
}
if(is_future_ready(download_future)) {
- if(download_future.get() != DownloadResult::OK) {
+ DownloadResult download_result = download_future.get();
+ download_thread.join();
+ if(download_result != DownloadResult::OK) {
show_notification("QuickMedia", "Failed to download " + video_url, Urgency::CRITICAL);
current_page = previous_page;
return;
@@ -3307,7 +3276,9 @@ namespace QuickMedia {
chat_state = ChatState::NAVIGATING;
return true;
} else if(text == "/logout") {
- show_notification("QuickMedia", "/logout command is temporary disabled. Delete " + get_storage_dir().join("matrix").join("session.json").data + " and restart QuickMedia to logout", Urgency::CRITICAL);
+ new_page = PageType::CHAT_LOGIN;
+ chat_input.set_editable(false);
+ chat_state = ChatState::NAVIGATING;
return true;
} else if(strncmp(text.c_str(), "/me ", 4) == 0) {
msgtype = "m.emote";
@@ -3460,14 +3431,20 @@ namespace QuickMedia {
float tab_vertical_offset = 0.0f;
- auto typing_async_func = [this](bool new_state, RoomData *room) {
- if(new_state) {
- matrix->on_start_typing(room);
- } else {
- matrix->on_stop_typing(room);
+ MessageQueue<bool> typing_state_queue;
+ std::thread typing_state_thread([this, &current_room, &typing_state_queue]() {
+ while(true) {
+ std::optional<bool> state_opt = typing_state_queue.pop_wait();
+ if(!state_opt)
+ break;
+
+ bool state = state_opt.value();
+ if(state)
+ matrix->on_start_typing(current_room);
+ else
+ matrix->on_stop_typing(current_room);
}
- };
- std::vector<std::future<void>> typing_futures;
+ });
sf::Clock frame_timer;
@@ -3638,7 +3615,7 @@ namespace QuickMedia {
if(typing && current_room) {
fprintf(stderr, "Stopped typing\n");
typing = false;
- typing_futures.push_back(std::async(typing_async_func, false, current_room));
+ typing_state_queue.push(false);
}
} else if((event.key.code == sf::Keyboard::Right) && selected_tab < (int)tabs.size() - 1) {
tabs[selected_tab].body->clear_cache();
@@ -3648,7 +3625,7 @@ namespace QuickMedia {
if(typing && current_room) {
fprintf(stderr, "Stopped typing\n");
typing = false;
- typing_futures.push_back(std::async(typing_async_func, false, current_room));
+ typing_state_queue.push(false);
}
} else if(event.key.code == sf::Keyboard::Escape) {
goto chat_page_end;
@@ -3662,6 +3639,14 @@ namespace QuickMedia {
}
}
+ if(current_room) {
+ if(event.key.control && event.key.code == sf::Keyboard::C) {
+ BodyItem *selected = tabs[selected_tab].body->get_selected();
+ if(selected)
+ sf::Clipboard::setString(selected->get_description());
+ }
+ }
+
if(selected_tab == MESSAGES_TAB_INDEX && current_room) {
if(event.key.code == sf::Keyboard::U) {
frame_skip_text_entry = true;
@@ -3783,7 +3768,7 @@ namespace QuickMedia {
start_typing_timer.restart();
if(!typing && current_room) {
fprintf(stderr, "Started typing\n");
- typing_futures.push_back(std::async(typing_async_func, true, current_room));
+ typing_state_queue.push(true);
}
typing = true;
}
@@ -3795,7 +3780,7 @@ namespace QuickMedia {
if(typing && current_room) {
fprintf(stderr, "Stopped typing\n");
typing = false;
- typing_futures.push_back(std::async(typing_async_func, false, current_room));
+ typing_state_queue.push(false);
}
}
//chat_input.on_event(event);
@@ -3840,7 +3825,30 @@ namespace QuickMedia {
break;
}
case PageType::CHAT_LOGIN: {
- abort();
+ // TODO: Cancel these instead
+ if(set_read_marker_future.valid())
+ set_read_marker_future.get();
+ if(previous_messages_future.valid())
+ previous_messages_future.get();
+ if(fetch_message_future.valid())
+ fetch_message_future.get();
+ typing_state_queue.close();
+ if(typing_state_thread.joinable())
+ typing_state_thread.join();
+ new_page = PageType::CHAT;
+ matrix->stop_sync();
+ matrix->logout();
+ tabs[MESSAGES_TAB_INDEX].body->clear_cache();
+ // TODO: Instead of doing this, exit this current function and navigate to chat login page instead.
+ // This doesn't currently work because at the end of this function there are futures that need to wait
+ // and one of them is /sync, which has a timeout of 30 seconds. That timeout has to be killed somehow.
+ //delete current_plugin;
+ //current_plugin = new Matrix();
+ current_page = PageType::CHAT_LOGIN;
+ chat_login_page();
+ if(current_page == PageType::CHAT)
+ after_matrix_login_page();
+ exit(0);
break;
}
default:
@@ -3850,22 +3858,7 @@ namespace QuickMedia {
if(typing && start_typing_timer.getElapsedTime().asSeconds() >= typing_timeout_seconds && current_room) {
fprintf(stderr, "Stopped typing\n");
typing = false;
- typing_futures.push_back(std::async(typing_async_func, false, current_room));
- }
-
- for(auto it = typing_futures.begin(); it != typing_futures.end(); ) {
- if(!it->valid()) {
- it = typing_futures.erase(it);
- continue;
- }
-
- if(it->wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
- it->get();
- it = typing_futures.erase(it);
- continue;
- }
-
- ++it;
+ typing_state_queue.push(false);
}
if(current_room && current_room->userdata && room_avatar_thumbnail_data->loading_state == LoadingState::NOT_LOADED)
@@ -4146,13 +4139,60 @@ namespace QuickMedia {
previous_messages_future.get();
if(fetch_message_future.valid())
fetch_message_future.get();
- for(auto &typing_future : typing_futures) {
- if(typing_future.valid())
- typing_future.get();
- }
+ typing_state_queue.close();
+ if(typing_state_thread.joinable())
+ typing_state_thread.join();
for(auto &body_item : tabs[PINNED_TAB_INDEX].body->items) {
delete (PinnedEventData*)body_item->userdata;
}
}
+
+ void Program::after_matrix_login_page() {
+ if(!window.isOpen())
+ exit(exit_code);
+
+ auto rooms_body = create_body();
+ rooms_body->thumbnail_mask_shader = &circle_mask_shader;
+ auto matrix_rooms_page = std::make_unique<MatrixRoomsPage>(this, rooms_body.get(), "All rooms");
+
+ auto rooms_tags_body = create_body();
+ rooms_tags_body->thumbnail_mask_shader = &circle_mask_shader;
+ auto matrix_rooms_tag_page = std::make_unique<MatrixRoomTagsPage>(this, rooms_tags_body.get());
+
+ MatrixQuickMedia matrix_handler(this, matrix, matrix_rooms_page.get(), matrix_rooms_tag_page.get());
+ matrix->start_sync(&matrix_handler);
+
+ std::vector<Tab> tabs;
+ tabs.push_back(Tab{std::move(rooms_body), std::move(matrix_rooms_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{std::move(rooms_tags_body), std::move(matrix_rooms_tag_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ sf::Sprite load_sprite(loading_icon);
+ sf::Vector2u loading_icon_size = loading_icon.getSize();
+ load_sprite.setOrigin(loading_icon_size.x * 0.5f, loading_icon_size.y * 0.5f);
+
+ sf::Clock timer;
+ sf::Event event;
+ while(window.isOpen() && !matrix->is_initial_sync_finished()) {
+ while(window.pollEvent(event)) {
+ if(event.type == sf::Event::Closed)
+ window.close();
+ else if(event.type == sf::Event::Resized) {
+ window_size.x = event.size.width;
+ window_size.y = event.size.height;
+ sf::FloatRect visible_area(0, 0, window_size.x, window_size.y);
+ window.setView(sf::View(visible_area));
+ }
+ }
+ window.clear(back_color);
+ load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f);
+ load_sprite.setRotation(timer.getElapsedTime().asSeconds() * 400.0);
+ window.draw(load_sprite);
+ window.display();
+ }
+
+ while(window.isOpen()) {
+ page_loop(tabs);
+ }
+ }
}
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index cbb9634..c7d2697 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -1,6 +1,6 @@
#include "../include/VideoPlayer.hpp"
#include "../include/Storage.hpp"
-#include "../include/Program.h"
+#include "../include/Program.hpp"
#include <string>
#include <json/reader.h>
#include <json/writer.h>
diff --git a/src/plugins/Manga.cpp b/src/plugins/Manga.cpp
index 323794c..4685cec 100644
--- a/src/plugins/Manga.cpp
+++ b/src/plugins/Manga.cpp
@@ -1,5 +1,5 @@
#include "../../plugins/Manga.hpp"
-#include "../../include/Program.h"
+#include "../../include/Program.hpp"
namespace QuickMedia {
TrackResult MangaChaptersPage::track(const std::string &str) {
@@ -10,7 +10,8 @@ namespace QuickMedia {
return TrackResult::ERR;
}
- void MangaChaptersPage::on_navigate_to_page() {
+ void MangaChaptersPage::on_navigate_to_page(BodyItems &body_items) {
+ (void)body_items;
std::string manga_id;
if(extract_id_from_url(content_url, manga_id))
load_manga_content_storage(get_service_name(), content_title, manga_id);
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index a702841..93eb1d6 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -3,6 +3,7 @@
#include "../../include/StringUtils.hpp"
#include "../../include/NetUtils.hpp"
#include "../../include/Notification.hpp"
+#include "../../include/Program.hpp"
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
@@ -521,8 +522,8 @@ namespace QuickMedia {
}
void Matrix::stop_sync() {
- // TODO: Kill the running download in |sync_thread| instead of waiting until sync returns (which can be up to 30 seconds)
sync_running = false;
+ program_kill_in_thread(sync_thread.get_id());
if(sync_thread.joinable())
sync_thread.join();
}
@@ -534,8 +535,12 @@ namespace QuickMedia {
void Matrix::get_room_sync_data(RoomData *room, SyncData &sync_data) {
room->acquire_room_lock();
auto &room_messages = room->get_messages_thread_unsafe();
- sync_data.messages.insert(sync_data.messages.end(), room_messages.begin() + room->messages_read_index, room_messages.end());
- room->messages_read_index = room_messages.size();
+ if(room->messages_read_index <= room_messages.size()) {
+ sync_data.messages.insert(sync_data.messages.end(), room_messages.begin() + room->messages_read_index, room_messages.end());
+ room->messages_read_index = room_messages.size();
+ } else {
+ fprintf(stderr, "Unexpected behavior!!!! get_room_sync_data said read index is %zu but we only have %zu messages\n", room->messages_read_index, room_messages.size());
+ }
if(room->pinned_events_updated) {
sync_data.pinned_events = room->get_pinned_events_unsafe();
room->pinned_events_updated = false;
diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp
index 8b1efc7..082aaa8 100644
--- a/src/plugins/NyaaSi.cpp
+++ b/src/plugins/NyaaSi.cpp
@@ -1,5 +1,5 @@
#include "../../plugins/NyaaSi.hpp"
-#include "../../include/Program.h"
+#include "../../include/Program.hpp"
#include "../../include/Storage.hpp"
#include "../../include/Notification.hpp"
#include "../../include/StringUtils.hpp"