diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-05-31 04:33:28 +0200 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-05-31 04:33:28 +0200 |
commit | 3586e3b510ef6828ab44dad1467f18ef4f2d7e2b (patch) | |
tree | 5e9eed17378fe65ef594cdac55acd5899b66ae8a | |
parent | 6e9bfd6571adf151e4e7fe4cb63f731314ebeff6 (diff) |
Youtube: merge search page and recommended page (show recommended if search field empty)
-rw-r--r-- | include/QuickMedia.hpp | 5 | ||||
-rw-r--r-- | plugins/Youtube.hpp | 3 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 56 | ||||
-rw-r--r-- | src/plugins/Youtube.cpp | 15 |
4 files changed, 42 insertions, 37 deletions
diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp index c1df4ed..b5570da 100644 --- a/include/QuickMedia.hpp +++ b/include/QuickMedia.hpp @@ -69,6 +69,7 @@ namespace QuickMedia { bool fetching_next_page_running = false; bool fetching_next_page_failed = false; bool search_suggestion_submitted = false; + bool card_view = false; int fetched_page = 0; mgl::Text search_result_text; AsyncTask<FetchResult> fetch_future; @@ -110,6 +111,10 @@ namespace QuickMedia { Json::Value load_history_json(); + Json::Value load_recommended_json(const char *plugin_name); + void fill_recommended_items_from_json(const char *plugin_name, const Json::Value &recommended_json, BodyItems &body_items); + void save_recommendations_from_related_videos(const char *plugin_name, const std::string &video_url, const std::string &video_title, const BodyItems &related_media_body_items); + void set_clipboard(const std::string &str); private: void init(mgl::WindowHandle parent_window, std::string &program_path); diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp index 8844c5b..78fc40f 100644 --- a/plugins/Youtube.hpp +++ b/plugins/Youtube.hpp @@ -39,6 +39,8 @@ namespace QuickMedia { // If false is returned from |active_handler|, then this function is cancelled. bool youtube_custom_redirect(std::string &video_url, std::string &audio_url, int64_t &video_content_length, int64_t &audio_content_length, std::function<bool()> active_handler); + // fill_recommended_items_from_json(plugin_name, load_recommended_json(plugin_name), result_items); + class YoutubeSearchPage : public LazyFetchPage { public: YoutubeSearchPage(Program *program, std::string video_id = "") : LazyFetchPage(program), video_id(std::move(video_id)) {} @@ -51,6 +53,7 @@ namespace QuickMedia { PluginResult submit_suggestion(const SubmitArgs &args, BodyItems &result_items) override; PluginResult lazy_fetch(BodyItems &result_items) override; bool lazy_fetch_is_loader() override { return true; } + bool reload_on_page_change() override { return true; } private: PluginResult search_get_continuation(const std::string &url, const std::string &continuation_token, BodyItems &result_items); private: diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index e8fee28..494e03d 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -52,6 +52,7 @@ #include <limits.h> #include <sys/stat.h> #include <cmath> +#include <random> #include <mglpp/graphics/Rectangle.hpp> #include <mglpp/graphics/Sprite.hpp> @@ -227,9 +228,6 @@ static void set_window_icon(Display *display, Window window, const std::string & } namespace QuickMedia { - static Json::Value load_recommended_json(const char *plugin_name); - static void fill_recommended_items_from_json(const char *plugin_name, const Json::Value &recommended_json, BodyItems &body_items); - enum class HistoryType { YOUTUBE, MANGA @@ -266,28 +264,6 @@ namespace QuickMedia { bool local_thumbnail; }; - class RecommendedPage : public LazyFetchPage { - public: - RecommendedPage(Program *program, Page *search_page, const char *plugin_name) : - LazyFetchPage(program), search_page(search_page), plugin_name(plugin_name) {} - - const char* get_title() const override { return "Recommended"; } - - PluginResult submit(const SubmitArgs &args, std::vector<Tab> &result_tabs) override { - return search_page->submit(args, result_tabs); - } - - PluginResult lazy_fetch(BodyItems &result_items) override { - fill_recommended_items_from_json(plugin_name, load_recommended_json(plugin_name), result_items); - return PluginResult::OK; - } - - bool reload_on_page_change() override { return true; } - private: - Page *search_page; - const char *plugin_name; - }; - using OptionsPageHandler = std::function<void()>; class OptionsPage : public Page { @@ -1275,10 +1251,7 @@ namespace QuickMedia { if(youtube_url.empty()) { start_tab_index = 1; tabs.push_back(Tab{create_body(false, true), std::make_unique<YoutubeSubscriptionsPage>(this), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); - tabs.push_back(Tab{create_body(false, false), std::make_unique<YoutubeSearchPage>(this), create_search_bar("Search...", 100)}); - - auto recommended_page = std::make_unique<RecommendedPage>(this, tabs.back().page.get(), plugin_name); - tabs.push_back(Tab{create_body(false, true), std::move(recommended_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); + tabs.push_back(Tab{create_body(false, true), std::make_unique<YoutubeSearchPage>(this), create_search_bar("Search...", 100)}); auto history_body = create_body(false, true); auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::YOUTUBE); @@ -1475,7 +1448,7 @@ namespace QuickMedia { return video_history_filepath.join(plugin_name).append(".json"); } - Json::Value load_recommended_json(const char *plugin_name) { + Json::Value Program::load_recommended_json(const char *plugin_name) { Path recommended_filepath = get_recommended_filepath(plugin_name); Json::Value json_result; if(!read_file_as_json(recommended_filepath, json_result) || !json_result.isObject()) @@ -1483,7 +1456,7 @@ namespace QuickMedia { return json_result; } - void fill_recommended_items_from_json(const char *plugin_name, const Json::Value &recommended_json, BodyItems &body_items) { + void Program::fill_recommended_items_from_json(const char *plugin_name, const Json::Value &recommended_json, BodyItems &body_items) { assert(recommended_json.isObject()); const int64_t recommendations_autodelete_period = 60*60*24*20; // 20 days @@ -1574,10 +1547,11 @@ namespace QuickMedia { break; } - std::random_shuffle(body_items.begin(), body_items.end()); + const auto seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::shuffle(body_items.begin(), body_items.end(), std::default_random_engine(seed)); } - static void save_recommendations_from_related_videos(const char *plugin_name, const std::string &video_url, const std::string &video_title, const BodyItems &related_media_body_items) { + void Program::save_recommendations_from_related_videos(const char *plugin_name, const std::string &video_url, const std::string &video_title, const BodyItems &related_media_body_items) { std::string video_id; if(!youtube_url_extract_id(video_url, video_id)) { std::string err_msg = "Failed to extract id of youtube url "; @@ -2044,6 +2018,7 @@ namespace QuickMedia { if(tab.body->attach_side == AttachSide::BOTTOM) tab.body->select_last_item(); tab.page->on_navigate_to_page(tab.body.get()); + } Tabs ui_tabs(&rounded_rectangle_shader); @@ -2063,6 +2038,7 @@ namespace QuickMedia { for(size_t i = 0; i < tabs.size(); ++i) { TabAssociatedData data; data.search_result_text = mgl::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN, 30 * get_config().scale * get_config().font_scale)); + data.card_view = tabs[i].body ? tabs[i].body->card_view : false; tab_associated_data.push_back(std::move(data)); } @@ -2103,7 +2079,7 @@ namespace QuickMedia { tab_associated_data[selected_tab].search_text_updated = false; } - auto plugin_submit_handler = [&tabs, selected_tab, &selected_item, &search_text, &new_tabs, &new_body_items, search_suggestion_submitted]() { + auto plugin_submit_handler = [&]() { SubmitArgs submit_args; submit_args.title = selected_item ? selected_item->get_title() : search_text; submit_args.url = selected_item ? selected_item->url : search_text; @@ -2112,6 +2088,7 @@ namespace QuickMedia { submit_args.extra = selected_item ? selected_item->extra : nullptr; if(tabs[selected_tab].page->search_is_suggestion() && !search_suggestion_submitted) { + tabs[selected_tab].body->card_view = tab_associated_data[selected_tab].card_view; PluginResult plugin_result = tabs[selected_tab].page->submit_suggestion(submit_args, new_body_items); return plugin_result == PluginResult::OK; } else { @@ -2176,7 +2153,8 @@ namespace QuickMedia { for(size_t i = 0; i < tabs.size(); ++i) { tabs[i].body->clear_cache(); - if(tabs[i].page->is_lazy_fetch_page() && static_cast<LazyFetchPage*>(tabs[i].page.get())->reload_on_page_change()) { + const bool lazy_update = tabs[i].page->search_is_filter() || (tabs[i].search_bar && tabs[i].search_bar->get_text().empty()); + if(tabs[i].page->is_lazy_fetch_page() && static_cast<LazyFetchPage*>(tabs[i].page.get())->reload_on_page_change() && lazy_update) { tab_associated_data[i].lazy_fetch_finished = false; tab_associated_data[i].fetched_page = 0; const BodyItem *selected_item = tabs[i].body->get_selected(); @@ -2636,6 +2614,14 @@ namespace QuickMedia { std::string update_search_text = associated_data.update_search_text; if(!tabs[i].page->search_is_suggestion() || associated_data.search_suggestion_submitted) tabs[i].body->clear_items(); + + if(tabs[i].page->search_is_suggestion() && tabs[i].body) { + if(update_search_text.empty()) + tabs[i].body->card_view = tab_associated_data[selected_tab].card_view; + else + tabs[i].body->card_view = false; + } + associated_data.search_text_updated = false; associated_data.fetch_status = FetchStatus::LOADING; associated_data.fetch_type = FetchType::SEARCH; diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index 3177f4d..65db3b1 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -9,6 +9,7 @@ #include "../../include/Theme.hpp" #include "../../include/Config.hpp" #include "../../plugins/WatchProgress.hpp" +#include "../../include/QuickMedia.hpp" #include <optional> #include <json/reader.h> extern "C" { @@ -784,8 +785,14 @@ namespace QuickMedia { } SearchResult YoutubeSearchPage::search(const std::string &str, BodyItems &result_items) { - if(str.empty()) + continuation_token.clear(); + current_page = 0; + added_videos.clear(); + + if(str.empty()) { + program->fill_recommended_items_from_json("youtube", program->load_recommended_json("youtube"), result_items); return SearchResult::OK; + } // TODO: Find this search url from youtube.com/... searchbox.js, and the url to that script from youtube.com/ html std::string url = "https://suggestqueries-clients6.youtube.com/complete/search?client=youtube&hl=en&gl=us&sugexp=rdcfrc%2Ccfro%3D1%2Cfp.cfr%3D1&gs_rn=64&gs_ri=youtube&ds=yt&cp=34&gs_id=f&xhr=t&xssi=t&q="; @@ -929,7 +936,11 @@ namespace QuickMedia { return PluginResult::OK; } - PluginResult YoutubeSearchPage::lazy_fetch(BodyItems&) { + PluginResult YoutubeSearchPage::lazy_fetch(BodyItems &result_items) { + continuation_token.clear(); + current_page = 0; + added_videos.clear(); + program->fill_recommended_items_from_json("youtube", program->load_recommended_json("youtube"), result_items); get_cookies(); return PluginResult::OK; } |