aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-11-04 01:30:38 +0100
committerdec05eba <dec05eba@protonmail.com>2020-11-04 01:30:38 +0100
commitb6b972e2dae816a8f0686f4986029a5ed50e592c (patch)
treeb7966625b8ad02628f053a7436c0dd39d8de8abd /src
parentae6fb457ca385540e0f9b1347ef9c3c84815b16d (diff)
Add channels page to related videos menu, fix related videos menu broken after video failing to load
Diffstat (limited to 'src')
-rw-r--r--src/QuickMedia.cpp378
-rw-r--r--src/plugins/ImageBoard.cpp6
-rw-r--r--src/plugins/Page.cpp5
-rw-r--r--src/plugins/Pornhub.cpp20
-rw-r--r--src/plugins/Youtube.cpp51
5 files changed, 263 insertions, 197 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 7d7e97f..bd19f2a 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -169,15 +169,35 @@ static sf::Color interpolate_colors(sf::Color source, sf::Color target, double p
}
namespace QuickMedia {
+ enum class HistoryType {
+ YOUTUBE,
+ MANGA
+ };
+
class HistoryPage : public Page {
public:
- HistoryPage(Program *program, Page *search_page) : Page(program), search_page(search_page) {}
+ HistoryPage(Program *program, Page *search_page, SearchBar *search_bar, HistoryType history_type) :
+ Page(program), search_page(search_page), search_bar(search_bar), history_type(history_type) {}
const char* get_title() const override { return "History"; }
PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override {
return search_page->submit(title, url, result_tabs);
}
+ void on_navigate_to_page(Body *body) override {
+ body->clear_items();
+ switch(history_type) {
+ case HistoryType::YOUTUBE:
+ program->youtube_get_watch_history(body->items);
+ break;
+ case HistoryType::MANGA:
+ program->manga_get_watch_history(program->get_plugin_name(), body->items);
+ break;
+ }
+ body->filter_search_fuzzy(search_bar->get_text());
+ }
private:
Page *search_page;
+ SearchBar *search_bar;
+ HistoryType history_type;
};
class RecommendedPage : public Page {
@@ -533,22 +553,25 @@ namespace QuickMedia {
tabs.push_back(Tab{std::move(search_body), std::make_unique<ManganeloSearchPage>(this), create_search_bar("Search...", 200)});
auto history_body = create_body();
- manga_get_watch_history(plugin_name, history_body->items);
- tabs.push_back(Tab{std::move(history_body), std::make_unique<HistoryPage>(this, tabs.front().page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
+ auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), search_bar.get(), HistoryType::MANGA);
+ tabs.push_back(Tab{std::move(history_body), std::move(history_page), std::move(search_bar)});
} else if(strcmp(plugin_name, "mangatown") == 0) {
auto search_body = create_body();
tabs.push_back(Tab{std::move(search_body), std::make_unique<MangatownSearchPage>(this), create_search_bar("Search...", 200)});
auto history_body = create_body();
- manga_get_watch_history(plugin_name, history_body->items);
- tabs.push_back(Tab{std::move(history_body), std::make_unique<HistoryPage>(this, tabs.front().page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
+ auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), search_bar.get(), HistoryType::MANGA);
+ tabs.push_back(Tab{std::move(history_body), std::move(history_page), std::move(search_bar)});
} else if(strcmp(plugin_name, "mangadex") == 0) {
auto search_body = create_body();
tabs.push_back(Tab{std::move(search_body), std::make_unique<MangadexSearchPage>(this), create_search_bar("Search...", 300)});
auto history_body = create_body();
- manga_get_watch_history(plugin_name, history_body->items);
- tabs.push_back(Tab{std::move(history_body), std::make_unique<HistoryPage>(this, tabs.front().page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
+ auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), search_bar.get(), HistoryType::MANGA);
+ tabs.push_back(Tab{std::move(history_body), std::move(history_page), std::move(search_bar)});
} else if(strcmp(plugin_name, "nyaa.si") == 0) {
auto category_page = std::make_unique<NyaaSiCategoryPage>(this);
auto categories_body = create_body();
@@ -573,8 +596,9 @@ namespace QuickMedia {
tabs.push_back(Tab{std::move(search_body), std::make_unique<YoutubeSearchPage>(this), create_search_bar("Search...", 350)});
auto history_body = create_body();
- youtube_get_watch_history(history_body->items);
- tabs.push_back(Tab{std::move(history_body), std::make_unique<HistoryPage>(this, tabs.front().page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
+ auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), search_bar.get(), HistoryType::YOUTUBE);
+ tabs.push_back(Tab{std::move(history_body), std::move(history_page), std::move(search_bar)});
auto recommended_body = create_body();
fill_recommended_items_from_json(plugin_name, load_recommended_json(), recommended_body->items);
@@ -890,7 +914,7 @@ namespace QuickMedia {
}
}
- void Program::page_loop(std::vector<Tab> &tabs) {
+ void Program::page_loop(std::vector<Tab> &tabs, int start_tab_index, std::function<void()> after_submit_handler) {
if(tabs.empty()) {
show_notification("QuickMedia", "No tabs provided!", Urgency::CRITICAL);
return;
@@ -947,96 +971,106 @@ namespace QuickMedia {
sf::Vertex gradient_points[4];
sf::Text tab_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), tab_text_size);
- int selected_tab = 0;
+ int selected_tab = std::min(std::max(0, start_tab_index), (int)tabs.size() - 1);
bool loop_running = true;
bool redraw = true;
- auto submit_handler = [this, &json_chapters, &tabs, &selected_tab, &loop_running, &redraw]() {
+ auto window_size_u = window.getSize();
+ window_size.x = window_size_u.x;
+ window_size.y = window_size_u.y;
+
+ auto submit_handler = [this, &after_submit_handler, &json_chapters, &tabs, &selected_tab, &loop_running, &redraw]() {
BodyItem *selected_item = tabs[selected_tab].body->get_selected();
if(!selected_item)
return;
std::vector<Tab> new_tabs;
PluginResult submit_result = tabs[selected_tab].page->submit(selected_item->get_title(), selected_item->url, new_tabs);
- if(submit_result == PluginResult::OK) {
- if(tabs[selected_tab].page->is_single_page()) {
- tabs[selected_tab].search_bar->clear();
- if(new_tabs.size() == 1)
- tabs[selected_tab].body = std::move(new_tabs[0].body);
- else
- loop_running = false;
- return;
- }
+ if(submit_result != PluginResult::OK) {
+ // TODO: Show the exact cause of error (get error message from curl).
+ show_notification("QuickMedia", std::string("Submit failed for page ") + tabs[selected_tab].page->get_title(), Urgency::CRITICAL);
+ return;
+ }
- if(new_tabs.empty())
- return;
+ if(after_submit_handler)
+ after_submit_handler();
- for(Tab &tab : tabs) {
- tab.body->clear_cache();
- }
+ if(tabs[selected_tab].page->is_single_page()) {
+ tabs[selected_tab].search_bar->clear();
+ if(new_tabs.size() == 1)
+ tabs[selected_tab].body = std::move(new_tabs[0].body);
+ else
+ loop_running = false;
+ return;
+ }
- if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::MANGA_IMAGES) {
- select_episode(selected_item, false);
- Body *chapters_body = tabs[selected_tab].body.get();
- chapters_body->filter_search_fuzzy(""); // Needed (or not really) to go to the next chapter when reaching the last page of a chapter
- MangaImagesPage *manga_images_page = static_cast<MangaImagesPage*>(new_tabs[0].page.get());
- window.setKeyRepeatEnabled(false);
- while(true) {
- if(current_page == PageType::IMAGES) {
- window.setFramerateLimit(20);
- while(current_page == PageType::IMAGES) {
- int page_navigation = image_page(manga_images_page, chapters_body);
- if(page_navigation == -1) {
- // TODO: Make this work if the list is sorted differently than from newest to oldest.
- chapters_body->select_next_item();
- select_episode(chapters_body->get_selected(), true);
- image_index = 99999; // Start at the page that shows we are at the end of the chapter
- manga_images_page->change_chapter(chapters_body->get_selected()->get_title(), chapters_body->get_selected()->url);
- } else if(page_navigation == 1) {
- // TODO: Make this work if the list is sorted differently than from newest to oldest.
- chapters_body->select_previous_item();
- select_episode(chapters_body->get_selected(), true);
- manga_images_page->change_chapter(chapters_body->get_selected()->get_title(), chapters_body->get_selected()->url);
- }
+ if(new_tabs.empty())
+ return;
+
+ for(Tab &tab : tabs) {
+ tab.body->clear_cache();
+ }
+
+ if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::MANGA_IMAGES) {
+ select_episode(selected_item, false);
+ Body *chapters_body = tabs[selected_tab].body.get();
+ chapters_body->filter_search_fuzzy(""); // Needed (or not really) to go to the next chapter when reaching the last page of a chapter
+ MangaImagesPage *manga_images_page = static_cast<MangaImagesPage*>(new_tabs[0].page.get());
+ window.setKeyRepeatEnabled(false);
+ while(true) {
+ if(current_page == PageType::IMAGES) {
+ window.setFramerateLimit(20);
+ while(current_page == PageType::IMAGES) {
+ int page_navigation = image_page(manga_images_page, chapters_body);
+ if(page_navigation == -1) {
+ // TODO: Make this work if the list is sorted differently than from newest to oldest.
+ chapters_body->select_next_item();
+ select_episode(chapters_body->get_selected(), true);
+ image_index = 99999; // Start at the page that shows we are at the end of the chapter
+ manga_images_page->change_chapter(chapters_body->get_selected()->get_title(), chapters_body->get_selected()->url);
+ } else if(page_navigation == 1) {
+ // TODO: Make this work if the list is sorted differently than from newest to oldest.
+ chapters_body->select_previous_item();
+ select_episode(chapters_body->get_selected(), true);
+ manga_images_page->change_chapter(chapters_body->get_selected()->get_title(), chapters_body->get_selected()->url);
}
- if(vsync_set)
- window.setFramerateLimit(0);
- else
- window.setFramerateLimit(monitor_hz);
- } else if(current_page == PageType::IMAGES_CONTINUOUS) {
- image_continuous_page(manga_images_page);
- } else {
- break;
}
+ if(vsync_set)
+ window.setFramerateLimit(0);
+ else
+ window.setFramerateLimit(monitor_hz);
+ } else if(current_page == PageType::IMAGES_CONTINUOUS) {
+ image_continuous_page(manga_images_page);
+ } else {
+ break;
}
- window.setKeyRepeatEnabled(true);
- } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::IMAGE_BOARD_THREAD) {
- current_page = PageType::IMAGE_BOARD_THREAD;
- image_board_thread_page(static_cast<ImageBoardThreadPage*>(new_tabs[0].page.get()), new_tabs[0].body.get());
- } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::VIDEO) {
- current_page = PageType::VIDEO_CONTENT;
- video_content_page(new_tabs[0].page.get(), selected_item->url, selected_item->get_title(), false);
- } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::CHAT) {
- 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].body.get());
- if(content_storage_json.isObject()) {
- const Json::Value &chapters_json = content_storage_json["chapters"];
- if(chapters_json.isObject())
- json_chapters = &chapters_json;
}
- redraw = true;
+ window.setKeyRepeatEnabled(true);
+ } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::IMAGE_BOARD_THREAD) {
+ current_page = PageType::IMAGE_BOARD_THREAD;
+ image_board_thread_page(static_cast<ImageBoardThreadPage*>(new_tabs[0].page.get()), new_tabs[0].body.get());
+ } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::VIDEO) {
+ current_page = PageType::VIDEO_CONTENT;
+ video_content_page(static_cast<VideoPage*>(new_tabs[0].page.get()), selected_item->url, selected_item->get_title(), false);
+ } else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::CHAT) {
+ 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 {
- // TODO: Show the exact cause of error (get error message from curl).
- show_notification("QuickMedia", std::string("Submit failed for page ") + tabs[selected_tab].page->get_title(), Urgency::CRITICAL);
+ page_loop(new_tabs);
+ }
+ for(Tab &tab : tabs) {
+ tab.page->on_navigate_to_page(tab.body.get());
}
+ if(content_storage_json.isObject()) {
+ const Json::Value &chapters_json = content_storage_json["chapters"];
+ if(chapters_json.isObject())
+ json_chapters = &chapters_json;
+ }
+ redraw = true;
};
for(size_t i = 0; i < tabs.size(); ++i) {
@@ -1121,7 +1155,12 @@ namespace QuickMedia {
hit_bottom = false;
break;
}
- if(hit_bottom && tab_associated_data[selected_tab].fetch_status == FetchStatus::NONE && !tab_associated_data[selected_tab].fetching_next_page_running && tabs[selected_tab].page) {
+ if(hit_bottom
+ && tab_associated_data[selected_tab].fetch_status == FetchStatus::NONE
+ && !tab_associated_data[selected_tab].fetching_next_page_running
+ && tabs[selected_tab].page
+ && (!tabs[selected_tab].page->is_lazy_fetch_page() || tab_associated_data[selected_tab].lazy_fetch_finished))
+ {
gradient_inc = 0.0;
tab_associated_data[selected_tab].fetching_next_page_running = true;
int next_page = tab_associated_data[selected_tab].fetched_page + 1;
@@ -1259,6 +1298,7 @@ namespace QuickMedia {
associated_data.lazy_fetch_finished = true;
FetchResult fetch_result = associated_data.fetch_future.get();
tabs[i].body->items = std::move(fetch_result.body_items);
+ tabs[i].body->filter_search_fuzzy(tabs[i].search_bar->get_text());
if(fetch_result.result != PluginResult::OK)
associated_data.search_result_text.setString("Failed to fetch page!");
else if(tabs[i].body->items.empty())
@@ -1433,7 +1473,7 @@ namespace QuickMedia {
return true;
}
- void Program::save_recommendations_from_related_videos(const std::string &video_url, const std::string &video_title, const Body *related_media_body) {
+ void Program::save_recommendations_from_related_videos(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 ";
@@ -1465,7 +1505,7 @@ namespace QuickMedia {
}
int saved_recommendation_count = 0;
- for(const auto &body_item : related_media_body->items) {
+ for(const auto &body_item : related_media_body_items) {
std::string recommended_video_id;
if(youtube_url_extract_id(body_item->url, recommended_video_id)) {
Json::Value &existing_recommendation = recommended_json[recommended_video_id];
@@ -1514,6 +1554,10 @@ namespace QuickMedia {
&& (memcmp(&result[36], "moov", 4) != 0);
}
+ const char* Program::get_plugin_name() const {
+ return plugin_name;
+ }
+
TaskResult Program::run_task_with_loading_screen(std::function<bool()> callback) {
assert(std::this_thread::get_id() == main_thread_id);
@@ -1567,17 +1611,13 @@ namespace QuickMedia {
#define CLEANMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask|Mod5Mask))
- void Program::video_content_page(Page *page, std::string video_url, std::string video_title, bool download_if_streaming_fails) {
+ void Program::video_content_page(VideoPage *video_page, std::string video_url, std::string video_title, bool download_if_streaming_fails) {
sf::Clock time_watched_timer;
bool added_recommendations = false;
bool video_loaded = false;
PageType previous_page = pop_page_stack();
- 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);
-
bool video_url_is_local = false;
if(download_if_streaming_fails) {
Path video_cache_dir = get_cache_dir().join("video");
@@ -1629,14 +1669,9 @@ namespace QuickMedia {
time_watched_timer.restart();
std::unique_ptr<VideoPlayer> video_player;
- std::unique_ptr<sf::RenderWindow> related_media_window;
- sf::Vector2f related_media_window_size;
- bool related_media_window_visible = false;
- sf::Text related_videos_text("Related videos", *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD), 20);
- const float related_videos_text_height = related_videos_text.getCharacterSize();
-
- auto related_media_body = create_body();
+ BodyItems related_videos;
+ std::string channel_url;
sf::WindowHandle video_player_window = None;
auto on_window_create = [this, &video_player_window](sf::WindowHandle _video_player_window) mutable {
@@ -1645,7 +1680,7 @@ namespace QuickMedia {
XSync(disp, False);
};
- auto load_video_error_check = [this, &related_media_body, &video_url, &video_title, &video_player, previous_page, &time_watched_timer, &video_loaded, &added_recommendations, page]() mutable {
+ auto load_video_error_check = [this, &related_videos, &channel_url, &video_url, &video_title, &video_player, previous_page, &time_watched_timer, &video_loaded, &added_recommendations, video_page]() mutable {
time_watched_timer.restart();
video_loaded = false;
added_recommendations = false;
@@ -1657,9 +1692,9 @@ namespace QuickMedia {
show_notification("QuickMedia", err_msg.c_str(), Urgency::CRITICAL);
current_page = previous_page;
} else {
- related_media_body->clear_items();
- related_media_body->clear_thumbnails();
- related_media_body->items = page->get_related_media(video_url);
+ channel_url.clear();
+ // TODO: Make async. What if the server is frozen?
+ related_videos = video_page->get_related_media(video_url, channel_url);
// TODO: Make this also work for other video plugins
if(strcmp(plugin_name, "youtube") != 0)
@@ -1698,7 +1733,7 @@ namespace QuickMedia {
};
bool has_video_started = true;
- auto video_event_callback = [this, &related_media_body, &video_url, &video_title, &video_player, &load_video_error_check, previous_page, &has_video_started, &time_watched_timer, &video_loaded](const char *event_name) mutable {
+ auto video_event_callback = [this, &related_videos, &video_url, &video_title, &video_player, &load_video_error_check, previous_page, &has_video_started, &time_watched_timer, &video_loaded](const char *event_name) mutable {
bool end_of_file = false;
if(strcmp(event_name, "pause") == 0) {
double time_remaining = 9999.0;
@@ -1720,7 +1755,7 @@ namespace QuickMedia {
std::string new_video_title;
// Find video that hasn't been played before in this video session
// TODO: Remove duplicates
- for(auto it = related_media_body->items.begin(), end = related_media_body->items.end(); it != end; ++it) {
+ for(auto it = related_videos.begin(), end = related_videos.end(); it != end; ++it) {
if(watched_videos.find((*it)->url) == watched_videos.end()) {
new_video_url = (*it)->url;
new_video_title = (*it)->get_title();
@@ -1776,62 +1811,20 @@ namespace QuickMedia {
while (current_page == PageType::VIDEO_CONTENT && window.isOpen()) {
while (window.pollEvent(event)) {
- base_event_handler(event, previous_page, related_media_body.get(), nullptr, true, false);
- if(event.type == sf::Event::Resized && related_media_window) {
- related_media_window_size.x = window_size.x * RELATED_MEDIA_WINDOW_WIDTH;
- related_media_window_size.y = window_size.y;
- related_media_window->setSize(sf::Vector2u(related_media_window_size.x, related_media_window_size.y));
- related_media_window->setPosition(sf::Vector2i(window_size.x - related_media_window_size.x, 0));
- sf::FloatRect visible_area(0, 0, related_media_window_size.x, related_media_window_size.y);
- related_media_window->setView(sf::View(visible_area));
- }
- }
-
- while(related_media_window && related_media_window->pollEvent(event)) {
- if(!related_media_window_visible)
- continue;
- if(event.type == sf::Event::KeyPressed) {
- if(event.key.code == sf::Keyboard::Up) {
- related_media_body->select_previous_item();
- } else if(event.key.code == sf::Keyboard::Down) {
- related_media_body->select_next_item();
- } else if(event.key.code == sf::Keyboard::PageUp) {
- related_media_body->select_previous_page();
- } else if(event.key.code == sf::Keyboard::PageDown) {
- related_media_body->select_next_page();
- } else if(event.key.code == sf::Keyboard::Home) {
- related_media_body->select_first_item();
- } else if(event.key.code == sf::Keyboard::End) {
- related_media_body->select_last_item();
- } else if(event.key.code == sf::Keyboard::Escape) {
- related_media_window_visible = false;
- related_media_window->setVisible(false);
- } else if(event.key.code == sf::Keyboard::R && event.key.control) {
- related_media_window_visible = false;
- related_media_window->setVisible(related_media_window_visible);
- related_media_body->clear_cache();
- } else if(event.key.code == sf::Keyboard::F && event.key.control) {
- window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE);
- fullscreen = !fullscreen;
- } else if(event.key.code == sf::Keyboard::Enter) {
- BodyItem *selected_item = related_media_body->get_selected();
- if(!selected_item)
- continue;
-
- related_media_window_visible = false;
- related_media_window->setVisible(false);
- has_video_started = false;
-
- video_url = selected_item->url;
- video_title = selected_item->get_title();
- load_video_error_check();
- } else if(event.key.code == sf::Keyboard::C && event.key.control) {
- save_video_url_to_clipboard();
- }
+ if (event.type == sf::Event::Closed) {
+ current_page = PageType::EXIT;
+ 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));
+ } else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
+ current_page = previous_page;
}
}
- if(video_player_window && XCheckTypedWindowEvent(disp, video_player_window, KeyPress, &xev)/* && xev.xkey.subwindow == video_player_window*/ && !related_media_window_visible) {
+ if(video_player_window && XCheckTypedWindowEvent(disp, video_player_window, KeyPress, &xev)/* && xev.xkey.subwindow == video_player_window*/) {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
KeySym pressed_keysym = XKeycodeToKeysym(disp, xev.xkey.keycode, 0);
@@ -1842,26 +1835,47 @@ namespace QuickMedia {
} else if(pressed_keysym == XK_f && pressing_ctrl) {
window_set_fullscreen(disp, window.getSystemHandle(), WindowFullscreenState::TOGGLE);
fullscreen = !fullscreen;
- } else if(pressed_keysym == XK_r && pressing_ctrl && strcmp(plugin_name, "4chan") != 0) {
- if(!related_media_window) {
- related_media_window_size.x = window_size.x * RELATED_MEDIA_WINDOW_WIDTH;
- related_media_window_size.y = window_size.y;
- related_media_window = std::make_unique<sf::RenderWindow>(sf::VideoMode(related_media_window_size.x, related_media_window_size.y), "", 0);
- related_media_window->setFramerateLimit(0);
- if(!enable_vsync(disp, related_media_window->getSystemHandle())) {
- fprintf(stderr, "Failed to enable vsync, fallback to frame limiting\n");
- related_media_window->setFramerateLimit(monitor_hz);
- }
- related_media_window->setVisible(false);
- XReparentWindow(disp, related_media_window->getSystemHandle(), video_player_window, window_size.x - related_media_window_size.x, 0);
- XSync(disp, False);
- }
-
- related_media_window_visible = true;
- related_media_window->setVisible(related_media_window_visible);
+ } else if(pressed_keysym == XK_r && pressing_ctrl) {
if(!cursor_visible)
window.setMouseCursorVisible(true);
cursor_visible = true;
+
+ int search_delay = 0;
+ auto search_page = video_page->create_search_page(this, search_delay);
+ auto related_videos_page = video_page->create_related_videos_page(this, video_url, video_title);
+ auto channels_page = video_page->create_channels_page(this, channel_url);
+ if(search_page || related_videos_page || channels_page) {
+ XUnmapWindow(disp, video_player_window);
+ XSync(disp, False);
+
+ std::vector<Tab> tabs;
+ if(search_page) {
+ tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", search_delay)});
+ }
+ if(related_videos_page) {
+ auto related_videos_body = create_body();
+ related_videos_body->items = related_videos;
+ tabs.push_back(Tab{std::move(related_videos_body), std::move(related_videos_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ }
+ if(channels_page) {
+ tabs.push_back(Tab{create_body(), std::move(channels_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ }
+
+ bool page_changed = false;
+ page_loop(tabs, 1, [this, &video_player, &page_changed]() {
+ window.setMouseCursorVisible(true);
+ video_player.reset();
+ page_changed = true;
+ });
+
+ if(page_changed) {
+ current_page = previous_page;
+ return;
+ } else {
+ XMapWindow(disp, video_player_window);
+ XSync(disp, False);
+ }
+ }
} else if(pressed_keysym == XK_c && pressing_ctrl) {
save_video_url_to_clipboard();
}
@@ -1893,7 +1907,7 @@ namespace QuickMedia {
if(!video_loaded) {
window.clear(back_color);
load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f);
- load_sprite.setRotation(time_watched_timer.getElapsedTime().asSeconds() * 400.0);
+ load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0);
window.draw(load_sprite);
window.display();
continue;
@@ -1902,22 +1916,11 @@ namespace QuickMedia {
/* Only save recommendations for the video if we have been watching it for 15 seconds */
if(is_youtube && video_loaded && !added_recommendations && time_watched_timer.getElapsedTime().asSeconds() >= 15) {
added_recommendations = true;
- save_recommendations_from_related_videos(video_url, video_title, related_media_body.get());
+ save_recommendations_from_related_videos(video_url, video_title, related_videos);
}
+#if 0
if(video_player_window) {
- if(related_media_window && related_media_window_visible) {
- sf::Vector2f body_pos, body_size;
- get_related_media_body_dimensions(window_size, body_pos, body_size, related_videos_text_height);
-
- related_media_window->clear(back_color);
- related_videos_text.setPosition(body_pos.x, 10.0f);
- related_media_window->draw(related_videos_text);
- related_media_body->draw(*related_media_window, body_pos, body_size);
- related_media_window->display();
- continue;
- }
-
if(!cursor_visible) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
continue;
@@ -1930,6 +1933,9 @@ namespace QuickMedia {
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ #endif
+ window.clear(back_color);
+ window.display();
}
window.setMouseCursorVisible(true);
diff --git a/src/plugins/ImageBoard.cpp b/src/plugins/ImageBoard.cpp
index ac05f80..6f97082 100644
--- a/src/plugins/ImageBoard.cpp
+++ b/src/plugins/ImageBoard.cpp
@@ -1,7 +1,7 @@
#include "../../plugins/ImageBoard.hpp"
namespace QuickMedia {
- BodyItems ImageBoardThreadPage::get_related_media(const std::string &url) {
+ BodyItems ImageBoardThreadPage::get_related_media(const std::string &url, std::string&) {
BodyItems body_items;
auto it = std::find(cached_media_urls.begin(), cached_media_urls.end(), url);
if(it == cached_media_urls.end())
@@ -16,6 +16,10 @@ namespace QuickMedia {
return body_items;
}
+ std::unique_ptr<RelatedVideosPage> ImageBoardThreadPage::create_related_videos_page(Program*, const std::string&, const std::string&) {
+ return nullptr;
+ }
+
PluginResult ImageBoardThreadPage::login(const std::string &token, const std::string &pin, std::string &response_msg) {
(void)token;
(void)pin;
diff --git a/src/plugins/Page.cpp b/src/plugins/Page.cpp
index e444ecd..9e0e97a 100644
--- a/src/plugins/Page.cpp
+++ b/src/plugins/Page.cpp
@@ -3,11 +3,6 @@
#include <json/reader.h>
namespace QuickMedia {
- BodyItems Page::get_related_media(const std::string &url) {
- (void)url;
- return {};
- }
-
DownloadResult Page::download_json(Json::Value &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent, std::string *err_msg) {
std::string server_response;
if(download_to_string(url, server_response, std::move(additional_args), is_tor_enabled(), use_browser_useragent, err_msg == nullptr) != DownloadResult::OK) {
diff --git a/src/plugins/Pornhub.cpp b/src/plugins/Pornhub.cpp
index f527e76..1f0840e 100644
--- a/src/plugins/Pornhub.cpp
+++ b/src/plugins/Pornhub.cpp
@@ -138,16 +138,28 @@ namespace QuickMedia {
return search_result_to_plugin_result(get_videos_in_page(url, is_tor_enabled(), result_items));
}
- PluginResult PornhubSearchPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
- (void)title;
- (void)url;
+ PluginResult PornhubSearchPage::submit(const std::string&, const std::string&, std::vector<Tab> &result_tabs) {
result_tabs.push_back(Tab{nullptr, std::make_unique<PornhubVideoPage>(program), nullptr});
return PluginResult::OK;
}
- BodyItems PornhubVideoPage::get_related_media(const std::string &url) {
+ PluginResult PornhubRelatedVideosPage::submit(const std::string&, const std::string&, std::vector<Tab> &result_tabs) {
+ result_tabs.push_back(Tab{nullptr, std::make_unique<PornhubVideoPage>(program), nullptr});
+ return PluginResult::OK;
+ }
+
+ BodyItems PornhubVideoPage::get_related_media(const std::string &url, std::string&) {
BodyItems result_items;
get_videos_in_page(url, is_tor_enabled(), result_items);
return result_items;
}
+
+ std::unique_ptr<Page> PornhubVideoPage::create_search_page(Program *program, int &search_delay) {
+ search_delay = 500;
+ return std::make_unique<PornhubSearchPage>(program);
+ }
+
+ std::unique_ptr<RelatedVideosPage> PornhubVideoPage::create_related_videos_page(Program *program, const std::string&, const std::string&) {
+ return std::make_unique<PornhubRelatedVideosPage>(program);
+ }
} \ No newline at end of file
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index 1ca25a3..2418073 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -647,9 +647,33 @@ namespace QuickMedia {
return PluginResult::OK;
}
+ PluginResult YoutubeChannelPage::lazy_fetch(BodyItems &result_items) {
+ std::vector<CommandArg> additional_args = {
+ { "-H", "x-spf-referer: " + url },
+ { "-H", "x-youtube-client-name: 1" },
+ { "-H", "x-spf-previous: " + url },
+ { "-H", "x-youtube-client-version: 2.20200626.03.00" },
+ { "-H", "referer: " + url }
+ };
+
+ //std::vector<CommandArg> cookies = get_cookies();
+ //additional_args.insert(additional_args.end(), cookies.begin(), cookies.end());
+
+ Json::Value json_root;
+ DownloadResult result = download_json(json_root, url + "/videos?pbj=1", std::move(additional_args), true);
+ if(result != DownloadResult::OK) return download_result_to_plugin_result(result);
+ result_items = parse_channel_videos(json_root, continuation_token, added_videos);
+ return PluginResult::OK;
+ }
+
+ PluginResult YoutubeRelatedVideosPage::submit(const std::string&, const std::string&, std::vector<Tab> &result_tabs) {
+ result_tabs.push_back(Tab{nullptr, std::make_unique<YoutubeVideoPage>(program), nullptr});
+ return PluginResult::OK;
+ }
+
// TODO: Make this faster by using string search instead of parsing html.
// TODO: If the result is a play
- BodyItems YoutubeVideoPage::get_related_media(const std::string &url) {
+ BodyItems YoutubeVideoPage::get_related_media(const std::string &url, std::string &channel_url) {
BodyItems result_items;
std::string modified_url = remove_index_from_playlist_url(url);
@@ -677,6 +701,18 @@ namespace QuickMedia {
if(!json_item.isObject())
continue;
+ if(channel_url.empty()) {
+ const Json::Value &player_response_json = json_item["playerResponse"];
+ if(player_response_json.isObject()) {
+ const Json::Value &video_details_json = player_response_json["videoDetails"];
+ if(video_details_json.isObject()) {
+ const Json::Value &channel_id_json = video_details_json["channelId"];
+ if(channel_id_json.isString())
+ channel_url = "https://www.youtube.com/channel/" + channel_id_json.asString();
+ }
+ }
+ }
+
const Json::Value &response_json = json_item["response"];
if(!response_json.isObject())
continue;
@@ -730,4 +766,17 @@ namespace QuickMedia {
return result_items;
}
+
+ std::unique_ptr<Page> YoutubeVideoPage::create_search_page(Program *program, int &search_delay) {
+ search_delay = 350;
+ return std::make_unique<YoutubeSearchPage>(program);
+ }
+
+ std::unique_ptr<RelatedVideosPage> YoutubeVideoPage::create_related_videos_page(Program *program, const std::string&, const std::string&) {
+ return std::make_unique<YoutubeRelatedVideosPage>(program);
+ }
+
+ std::unique_ptr<LazyFetchPage> YoutubeVideoPage::create_channels_page(Program *program, const std::string &channel_url) {
+ return std::make_unique<YoutubeChannelPage>(program, channel_url, "", "Channel videos");
+ }
} \ No newline at end of file