From 928f2525c29929de0c2ab520f48c82b5cb882aa7 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 30 Oct 2020 16:47:40 +0100 Subject: Matrix: re-add /logout, cancel task immediately Cancel video download when pressing escape, other fixes.. --- src/QuickMedia.cpp | 222 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 131 insertions(+), 91 deletions(-) (limited to 'src/QuickMedia.cpp') 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(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(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 &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(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 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 download_result_promise; + std::future download_future = download_result_promise.get_future(); + std::thread download_thread([this, &video_path, video_url](std::promise &&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 typing_state_queue; + std::thread typing_state_thread([this, ¤t_room, &typing_state_queue]() { + while(true) { + std::optional 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> 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(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(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 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); + } + } } -- cgit v1.2.3