aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-04-13 09:09:30 +0200
committerdec05eba <dec05eba@protonmail.com>2021-04-14 15:00:12 +0200
commit4db0876f45533d3b55ee79df2d2bc78b789b5a28 (patch)
tree41f513c10462ba219c1df0481b221b97f016ea45
parentfc632e90d793babc47044ff87ab63a86211e0bd0 (diff)
Make search fuzzy, fix soundcloud next song when hitting user
Also some other misc changes
-rw-r--r--README.md1
-rw-r--r--include/Body.hpp4
-rw-r--r--include/DownloadUtils.hpp2
-rw-r--r--plugins/Soundcloud.hpp2
-rw-r--r--src/Body.cpp41
-rw-r--r--src/DownloadUtils.cpp1
-rw-r--r--src/QuickMedia.cpp13
-rw-r--r--src/SearchBar.cpp7
-rw-r--r--src/plugins/NyaaSi.cpp8
-rw-r--r--src/plugins/Youtube.cpp8
10 files changed, 66 insertions, 21 deletions
diff --git a/README.md b/README.md
index 6b43ead..cf874b0 100644
--- a/README.md
+++ b/README.md
@@ -31,6 +31,7 @@ Press `Home` to scroll to the top or `End` to scroll to the bottom.\
Press `Enter` (aka `Return`) to select the item.\
Press `ESC` to go back to the previous menu.\
Press `ESC` or `Backspace` to close the video.\
+Press `Ctrl + D` to clear the search input text.\
Press `Ctrl + F` to switch between window mode and fullscreen mode when watching a video.\
Press `Space` to pause/unpause a video.\
Press `Ctrl + R` to show video comments, related videos or video channel when watching a video (if supported).\
diff --git a/include/Body.hpp b/include/Body.hpp
index fb22a21..22d9ff9 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -230,12 +230,8 @@ namespace QuickMedia {
float get_item_height(BodyItem *item, float width, bool load_texture = true, bool include_embedded_item = true, bool merge_with_previous = false, int item_index = -1);
float get_spacing_y() const;
- static bool string_find_case_insensitive(const std::string &str, const std::string &substr);
- // TODO: Make this actually fuzzy... Right now it's just a case insensitive string find.
- // This would require reordering the body.
// TODO: Highlight the part of the text that matches the search.
- // TODO: Ignore dot, whitespace and special characters
void filter_search_fuzzy(const std::string &text);
void filter_search_fuzzy_item(const std::string &text, BodyItem *body_item);
diff --git a/include/DownloadUtils.hpp b/include/DownloadUtils.hpp
index 40ec12a..dd74f50 100644
--- a/include/DownloadUtils.hpp
+++ b/include/DownloadUtils.hpp
@@ -22,7 +22,9 @@ namespace QuickMedia {
using DownloadErrorHandler = std::function<bool(std::string&)>;
DownloadResult download_to_string(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false, bool fail_on_error = true);
+ // Note: This function saves the content to the file atomically
DownloadResult download_to_string_cache(const std::string &url, std::string &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false, DownloadErrorHandler error_handler = nullptr, Path cache_path = "");
+ // Note: This function saves the content to the file atomically
DownloadResult download_to_file(const std::string &url, const std::string &destination_filepath, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false);
DownloadResult download_to_json(const std::string &url, rapidjson::Document &result, const std::vector<CommandArg> &additional_args, bool use_browser_useragent = false, bool fail_on_error = true);
} \ No newline at end of file
diff --git a/plugins/Soundcloud.hpp b/plugins/Soundcloud.hpp
index 0d73d36..e04d409 100644
--- a/plugins/Soundcloud.hpp
+++ b/plugins/Soundcloud.hpp
@@ -52,7 +52,7 @@ namespace QuickMedia {
std::unique_ptr<LazyFetchPage> create_channels_page(Program *, const std::string &) override { return nullptr; }
std::string get_url() override { return url; }
std::string url_get_playable_url(const std::string &url) override;
- bool video_should_be_skipped(const std::string &url) override { return url == "track"; }
+ bool video_should_be_skipped(const std::string &url) override { return url == "track" || url.find("/stream/users/") != std::string::npos; }
private:
std::string url;
};
diff --git a/src/Body.cpp b/src/Body.cpp
index 5c40c96..6833134 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -1254,14 +1254,35 @@ namespace QuickMedia {
return spacing_y;
}
+ // Returns std::string::npos if not found
+ static size_t find_next_non_whitespace_character(const std::string &str, size_t start_index) {
+ for(size_t i = start_index; i < str.size(); ++i) {
+ char c = str[i];
+ if(c != ' ' && c != '\n' && c != '\t' && c != '\v')
+ return i;
+ }
+ return std::string::npos;
+ }
+
// TODO: Support utf-8 case insensitive find
- //static
- bool Body::string_find_case_insensitive(const std::string &str, const std::string &substr) {
- auto it = std::search(str.begin(), str.end(), substr.begin(), substr.end(),
- [](char c1, char c2) {
- return std::toupper(c1) == std::toupper(c2);
- });
- return it != str.end();
+ static bool string_find_fuzzy_case_insensitive(const std::string &str, const std::string &substr) {
+ size_t substr_index = find_next_non_whitespace_character(substr, 0);
+ if(substr_index == std::string::npos)
+ return true;
+
+ char substr_c = std::toupper(substr[substr_index]);
+ for(size_t i = 0; i < str.size(); ++i) {
+ char str_c = std::toupper(str[i]);
+ if(str_c == substr_c) {
+ substr_index = find_next_non_whitespace_character(substr, substr_index + 1);
+ if(substr_index == std::string::npos || substr_index == substr.size())
+ return true;
+ else
+ substr_c = std::toupper(substr[substr_index]);
+ }
+ }
+
+ return false;
}
void Body::filter_search_fuzzy(const std::string &text) {
@@ -1280,11 +1301,11 @@ namespace QuickMedia {
}
void Body::filter_search_fuzzy_item(const std::string &text, BodyItem *body_item) {
- body_item->visible = string_find_case_insensitive(body_item->get_title(), text);
+ body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_title(), text);
if(!body_item->visible && !body_item->get_description().empty())
- body_item->visible = string_find_case_insensitive(body_item->get_description(), text);
+ body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_description(), text);
if(!body_item->visible && !body_item->get_author().empty())
- body_item->visible = string_find_case_insensitive(body_item->get_author(), text);
+ body_item->visible = string_find_fuzzy_case_insensitive(body_item->get_author(), text);
}
bool Body::no_items_visible() const {
diff --git a/src/DownloadUtils.cpp b/src/DownloadUtils.cpp
index e83bced..4a35640 100644
--- a/src/DownloadUtils.cpp
+++ b/src/DownloadUtils.cpp
@@ -87,7 +87,6 @@ namespace QuickMedia {
}
}
- // TODO: Use this everywhere we want to save to file (such as manga download)
DownloadResult download_to_file(const std::string &url, const std::string &destination_filepath, const std::vector<CommandArg> &additional_args, bool use_browser_useragent) {
Path tmp_filepath = destination_filepath;
tmp_filepath.append(".tmp");
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index fad2b94..053c97f 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -685,6 +685,11 @@ namespace QuickMedia {
window.setTitle("QuickMedia - " + std::string(plugin_name));
no_video = force_no_video;
+ if(strcmp(plugin_name, "youtube-audio") == 0) {
+ plugin_name = "youtube";
+ no_video = true;
+ }
+
std::string plugin_logo_path;
const char *plugin_logo_name = get_plugin_logo_name(plugin_name);
if(plugin_logo_name)
@@ -710,6 +715,7 @@ namespace QuickMedia {
pipe_body->items.push_back(create_launcher_body_item("Soundcloud", "soundcloud", resources_root + "icons/soundcloud_launcher.png"));
pipe_body->items.push_back(create_launcher_body_item("Spotify", "spotify", resources_root + "icons/spotify_launcher.png"));
pipe_body->items.push_back(create_launcher_body_item("YouTube", "youtube", resources_root + "icons/yt_launcher.png"));
+ pipe_body->items.push_back(create_launcher_body_item("YouTube (audio only)", "youtube-audio", resources_root + "icons/yt_launcher.png"));
tabs.push_back(Tab{std::move(pipe_body), std::make_unique<PipePage>(this, "Select plugin to launch"), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "manganelo") == 0) {
auto search_body = create_body();
@@ -787,7 +793,7 @@ namespace QuickMedia {
tabs.push_back(Tab{std::move(search_body), std::make_unique<SpankbangSearchPage>(this), create_search_bar("Search...", 500)});
} else if(strcmp(plugin_name, "spotify") == 0) {
auto search_body = create_body();
- tabs.push_back(Tab{std::move(search_body), std::make_unique<SpotifyPodcastSearchPage>(this), create_search_bar("Search...", 250)});
+ tabs.push_back(Tab{std::move(search_body), std::make_unique<SpotifyPodcastSearchPage>(this), create_search_bar("Search...", 350)});
no_video = true;
} else if(strcmp(plugin_name, "soundcloud") == 0) {
auto search_body = create_body();
@@ -1482,6 +1488,9 @@ namespace QuickMedia {
update_idle_state();
handle_window_close();
+ if(!loop_running || !window.isOpen())
+ break;
+
if(redraw) {
redraw = false;
if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->onWindowResize(window_size);
@@ -1985,7 +1994,7 @@ namespace QuickMedia {
}
}
- fprintf(stderr, "event name: %s\n", event_name);
+ //fprintf(stderr, "event name: %s\n", event_name);
};
load_video_error_check(false);
diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp
index 676618a..7c20568 100644
--- a/src/SearchBar.cpp
+++ b/src/SearchBar.cpp
@@ -99,6 +99,12 @@ namespace QuickMedia {
append_text(std::string(clipboard.begin(), clipboard.end()));
}
+ if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::D && event.key.control) {
+ clear();
+ updated_search = true;
+ updated_autocomplete = true;
+ }
+
if(event.type == sf::Event::TextEntered && event.text.unicode != 8 && event.text.unicode != 127) // 8 = backspace, 127 = del
onTextEntered(event.text.unicode);
else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Backspace)
@@ -124,6 +130,7 @@ namespace QuickMedia {
if(backspace_pressed)
timeout = 750;
if(updated_search && elapsed_time >= timeout) {
+ fprintf(stderr, "update search!\n");
updated_search = false;
auto u8 = text.getString().toUtf8();
std::string *u8_str = (std::string*)&u8;
diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp
index c005b31..7a84346 100644
--- a/src/plugins/NyaaSi.cpp
+++ b/src/plugins/NyaaSi.cpp
@@ -288,7 +288,9 @@ namespace QuickMedia {
std::string *description = (std::string*)userdata;
const char *text = quickmedia_html_node_get_text(node);
if(description->empty() && text) {
- *description = strip(text);
+ std::string desc = strip(text);
+ html_unescape_sequences(desc);
+ *description = std::move(desc);
}
}, &description);
@@ -360,7 +362,9 @@ namespace QuickMedia {
auto *item_data = (BodyItemContext*)userdata;
const char *text = quickmedia_html_node_get_text(node);
if(text && item_data->index < item_data->body_items->size()) {
- (*item_data->body_items)[item_data->index]->set_description(strip(text));
+ std::string desc = strip(text);
+ html_unescape_sequences(desc);
+ (*item_data->body_items)[item_data->index]->set_description(std::move(desc));
item_data->index++;
}
}, &body_item_image_context);
diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp
index 4add02c..f7d38aa 100644
--- a/src/plugins/Youtube.cpp
+++ b/src/plugins/Youtube.cpp
@@ -734,7 +734,7 @@ namespace QuickMedia {
const Json::Value &author_is_channel_owner_json = comment_renderer_json["authorIsChannelOwner"];
if(author_is_channel_owner_json.isBool() && author_is_channel_owner_json.asBool())
- body_item->set_title_color(sf::Color(150, 255, 150));
+ body_item->set_author_color(sf::Color(150, 255, 150));
std::optional<std::string> comment = yt_json_get_text(comment_renderer_json, "contentText");
if(comment)
@@ -779,6 +779,9 @@ namespace QuickMedia {
}
PluginResult YoutubeCommentsPage::lazy_fetch(BodyItems &result_items) {
+ if(continuation_token.empty())
+ return PluginResult::OK;
+
std::string next_url = "https://www.youtube.com/comment_service_ajax?action_get_comments=1&pbj=1&ctoken=";
next_url += url_param_encode(continuation_token);
//next_url += "&continuation=";
@@ -858,6 +861,9 @@ namespace QuickMedia {
}
PluginResult YoutubeCommentRepliesPage::lazy_fetch(BodyItems &result_items) {
+ if(continuation_token.empty())
+ return PluginResult::OK;
+
std::string next_url = "https://www.youtube.com/comment_service_ajax?action_get_comment_replies=1&pbj=1&ctoken=";
next_url += url_param_encode(continuation_token);
//next_url += "&continuation=";