From 27e748dec4792ac8612fb77e21a6d857a41a816c Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 3 Oct 2020 09:49:25 +0200 Subject: Nyaa.si: fetch next page when reaching the bottom --- src/QuickMedia.cpp | 132 +++++++++++++++++++++++++++++++++++++++++-------- src/plugins/NyaaSi.cpp | 15 ++++-- 2 files changed, 123 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 782506d..64955dd 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -153,6 +153,18 @@ static bool enable_vsync(Display *disp, Window window) { return false; } +static sf::Color interpolate_colors(sf::Color source, sf::Color target, double progress) { + int diff_r = (int)target.r - (int)source.r; + int diff_g = (int)target.g - (int)source.g; + int diff_b = (int)target.b - (int)source.b; + int diff_a = (int)target.a - (int)source.a; + return sf::Color( + source.r + diff_r * progress, + source.g + diff_g * progress, + source.b + diff_b * progress, + source.a + diff_a * progress); +} + namespace QuickMedia { Program::Program() : disp(nullptr), @@ -2381,16 +2393,70 @@ namespace QuickMedia { return true; }; + int fetched_page = 0; + bool fetching_next_page_running = false; + double gradient_inc = 0; + const float gradient_height = 5.0f; + sf::Vertex gradient_points[4]; + std::future next_page_future; + sf::Vector2f body_pos; sf::Vector2f body_size; bool redraw = true; sf::Event event; + sf::Clock frame_timer; while (current_page == Page::CONTENT_LIST) { + sf::Int32 frame_time_ms = frame_timer.restart().asMilliseconds(); + while (window.pollEvent(event)) { - base_event_handler(event, Page::SEARCH_SUGGESTION); - if(event.type == sf::Event::Resized || event.type == sf::Event::GainedFocus) + base_event_handler(event, Page::SEARCH_SUGGESTION, false); + if(event.type == sf::Event::Resized || event.type == sf::Event::GainedFocus) { redraw = true; + } else if(event.type == sf::Event::KeyPressed) { + if(event.key.code == sf::Keyboard::Down || event.key.code == sf::Keyboard::PageDown || event.key.code == sf::Keyboard::End) { + bool hit_bottom = false; + switch(event.key.code) { + case sf::Keyboard::Down: + hit_bottom = !body->select_next_item(); + break; + case sf::Keyboard::PageDown: + hit_bottom = !body->select_next_page(); + break; + case sf::Keyboard::End: + body->select_last_item(); + hit_bottom = true; + break; + default: + hit_bottom = false; + break; + } + if(hit_bottom && !search_running && !fetching_next_page_running) { + gradient_inc = 0; + fetching_next_page_running = true; + int next_page = fetched_page + 1; + std::string content_list_url_copy = content_list_url; + std::string update_search_text_copy = update_search_text; + next_page_future = std::async(std::launch::async, [this, content_list_url_copy, update_search_text_copy, next_page]() { + BodyItems result_items; + if(current_plugin->content_list_search_page(content_list_url_copy, update_search_text_copy, next_page, result_items) != SearchResult::OK) + fprintf(stderr, "Failed to get next content list page (page %d)\n", next_page); + return result_items; + }); + } + } else if(event.key.code == sf::Keyboard::Up) { + body->select_previous_item(); + } else if(event.key.code == sf::Keyboard::PageUp) { + body->select_previous_page(); + } else if(event.key.code == sf::Keyboard::Home) { + body->select_first_item(); + } else if(event.key.code == sf::Keyboard::Escape) { + current_page = Page::SEARCH_SUGGESTION; + body->clear_items(); + body->reset_selected(); + search_bar->clear(); + } + } } // TODO: This code is duplicated in many places. Handle it in one place. @@ -2398,19 +2464,32 @@ namespace QuickMedia { redraw = false; search_bar->onWindowResize(window_size); get_body_dimensions(window_size, search_bar.get(), body_pos, body_size); + + gradient_points[0].position.x = 0.0f; + gradient_points[0].position.y = window_size.y - gradient_height; + + gradient_points[1].position.x = window_size.x; + gradient_points[1].position.y = window_size.y - gradient_height; + + gradient_points[2].position.x = window_size.x; + gradient_points[2].position.y = window_size.y; + + gradient_points[3].position.x = 0.0f; + gradient_points[3].position.y = window_size.y; } search_bar->update(); - if(search_text_updated && !search_running) { - search_future = std::async(std::launch::async, [this, update_search_text]() { + if(search_text_updated && !fetching_next_page_running && !search_running) { + std::string search_term = update_search_text; + search_future = std::async(std::launch::async, [this, search_term]() { BodyItems result; - if(current_plugin->content_list_search(content_list_url, update_search_text, result) != SearchResult::OK) { - show_notification("Search", "Search failed!", Urgency::CRITICAL); + if(current_plugin->content_list_search(content_list_url, search_term, result) != SearchResult::OK) { + // TODO: Show this? + //show_notification("Search", "Search failed!", Urgency::CRITICAL); } return result; }); - update_search_text.clear(); search_text_updated = false; search_running = true; } @@ -2423,11 +2502,34 @@ namespace QuickMedia { search_future.get(); } search_running = false; + fetched_page = 0; + } + + if(fetching_next_page_running && next_page_future.valid() && next_page_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { + BodyItems new_body_items = next_page_future.get(); + fprintf(stderr, "Finished fetching page %d, num new messages: %zu\n", fetched_page + 1, new_body_items.size()); + size_t num_new_messages = new_body_items.size(); + if(num_new_messages > 0) { + body->append_items(std::move(new_body_items)); + fetched_page++; + } + fetching_next_page_running = false; } window.clear(back_color); search_bar->draw(window); body->draw(window, body_pos, body_size); + if(fetching_next_page_running) { + double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5; + gradient_inc += (frame_time_ms * 0.5); + sf::Color bottom_color = interpolate_colors(back_color, sf::Color(175, 180, 188), progress); + + gradient_points[0].color = back_color; + gradient_points[1].color = back_color; + gradient_points[2].color = bottom_color; + gradient_points[3].color = bottom_color; + window.draw(gradient_points, 4, sf::Quads); // Note: sf::Quads doesn't work with egl + } window.display(); } @@ -3217,18 +3319,6 @@ namespace QuickMedia { sf::Text text; }; - static sf::Color interpolate_colors(sf::Color source, sf::Color target, double progress) { - int diff_r = (int)target.r - (int)source.r; - int diff_g = (int)target.g - (int)source.g; - int diff_b = (int)target.b - (int)source.b; - int diff_a = (int)target.a - (int)source.a; - return sf::Color( - source.r + diff_r * progress, - source.g + diff_g * progress, - source.b + diff_b * progress, - source.a + diff_a * progress); - } - static std::string extract_first_line(const std::string &str, size_t max_length) { size_t index = str.find('\n'); if(index == std::string::npos) { @@ -4078,8 +4168,8 @@ namespace QuickMedia { ++i; } - // TODO: Stop showing this when switching rooms, or have one for each room. Also add bottom one? for fetching new messages - if(fetching_previous_messages_running) { + // TODO: Have one for each room. Also add bottom one? for fetching new messages (currently not implemented, is it needed?) + if(fetching_previous_messages_running && tabs[selected_tab].type == ChatTabType::MESSAGES) { double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5; gradient_inc += (frame_time_ms * 0.5); sf::Color top_color = interpolate_colors(back_color, sf::Color(175, 180, 188), progress); diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp index 98c6eee..1cdfc5f 100644 --- a/src/plugins/NyaaSi.cpp +++ b/src/plugins/NyaaSi.cpp @@ -71,10 +71,19 @@ namespace QuickMedia { return PluginResult::OK; } + + SearchResult NyaaSi::content_list_search(const std::string &list_url, const std::string &text, BodyItems &result_items) { + return search_page(list_url, text, 1, result_items); + } + + SearchResult NyaaSi::content_list_search_page(const std::string &list_url, const std::string &text, int page, BodyItems &result_items) { + return search_page(list_url, text, 1 + page, result_items); + } + // TODO: Also show the number of comments for each torrent. TODO: Optimize? // TODO: Show each field as seperate columns instead of seperating by | - SearchResult NyaaSi::content_list_search(const std::string &list_url, const std::string &text, BodyItems &result_items) { - std::string full_url = "https://nyaa.si/?c=" + list_url + "&f=0&p=1&q="; + SearchResult NyaaSi::search_page(const std::string &list_url, const std::string &text, int page, BodyItems &result_items) { + std::string full_url = "https://nyaa.si/?c=" + list_url + "&f=0&p=" + std::to_string(page) + "&q="; full_url += url_param_encode(text); std::string website_data; @@ -218,7 +227,7 @@ namespace QuickMedia { } PluginResult NyaaSi::get_content_list(const std::string &url, BodyItems &result_items) { - return search_result_to_plugin_result(content_list_search(url, "", result_items)); + return search_result_to_plugin_result(search_page(url, "", 1, result_items)); } struct BodyItemImageContext { -- cgit v1.2.3