aboutsummaryrefslogtreecommitdiff
path: root/src/QuickMedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/QuickMedia.cpp')
-rw-r--r--src/QuickMedia.cpp165
1 files changed, 128 insertions, 37 deletions
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 1bc260c..acc1770 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -293,6 +293,7 @@ namespace QuickMedia {
return PluginResult::OK;
}
bool reload_on_page_change() override { return true; }
+ const char* get_bookmark_name() const override { return search_page->get_bookmark_name(); }
private:
Page *search_page;
HistoryType history_type;
@@ -1118,51 +1119,81 @@ namespace QuickMedia {
});
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) {
- tabs.push_back(Tab{create_body(false, true), std::make_unique<ManganeloSearchPage>(this), create_search_bar("Search...", 400)});
+ auto search_page = std::make_unique<ManganeloSearchPage>(this);
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "manganelos") == 0) {
auto search_page = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "http://manganelos.com/");
add_manganelos_handlers(search_page.get());
- tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 400)});
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "mangatown") == 0) {
auto search_page = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "https://www.mangatown.com/");
add_mangatown_handlers(search_page.get());
- tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 400)});
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "mangakatana") == 0) {
auto search_page = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "https://mangakatana.com/", false);
add_mangakatana_handlers(search_page.get());
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "mangadex") == 0) {
- tabs.push_back(Tab{create_body(), std::make_unique<MangadexSearchPage>(this), create_search_bar("Search...", 400)});
- upgrade_legacy_mangadex_ids(this, tabs.back().page.get());
+ auto search_page = std::make_unique<MangadexSearchPage>(this);
+ upgrade_legacy_mangadex_ids(this, search_page.get());
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "readm") == 0) {
auto search_page = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "https://readm.org/");
add_readm_handlers(search_page.get());
- tabs.push_back(Tab{create_body(false, true), std::move(search_page), create_search_bar("Search...", 400)});
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+ tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "onimanga") == 0) {
auto search_page = std::make_unique<MangaGenericSearchPage>(this, plugin_name, "https://onimanga.com/");
add_onimanga_handlers(search_page.get());
+
+ tabs.push_back(Tab{create_body(), std::make_unique<BookmarksPage>(this, search_page.get()), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
tabs.push_back(Tab{create_body(), std::move(search_page), create_search_bar("Search...", 400)});
auto history_page = std::make_unique<HistoryPage>(this, tabs.front().page.get(), HistoryType::MANGA);
tabs.push_back(Tab{create_body(), std::move(history_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
+
+ start_tab_index = 1;
} else if(strcmp(plugin_name, "manga") == 0) {
auto mangadex = std::make_unique<MangadexSearchPage>(this);
upgrade_legacy_mangadex_ids(this, mangadex.get());
@@ -1349,35 +1380,9 @@ namespace QuickMedia {
LOGIN
};
- // Returns relative time as a string (approximation)
- static std::string seconds_to_relative_time_str(time_t seconds) {
- seconds = std::max(0L, seconds);
-
- time_t minutes = seconds / 60;
- time_t hours = minutes / 60;
- time_t days = hours / 24;
- time_t months = days / 30;
- time_t years = days / 365;
-
- if(years >= 1)
- return std::to_string(years) + " year" + (years == 1 ? "" : "s") + " ago";
- else if(months >= 1)
- return std::to_string(months) + " month" + (months == 1 ? "" : "s") + " ago";
- else if(days >= 1)
- return std::to_string(days) + " day" + (days == 1 ? "" : "s") + " ago";
- else if(hours >= 1)
- return std::to_string(hours) + " hour" + (hours == 1 ? "" : "s") + " ago";
- else if(minutes >= 1)
- return std::to_string(minutes) + " minute" + (minutes == 1 ? "" : "s") + " ago";
- else
- return std::to_string(seconds) + " second" + (seconds == 1 ? "" : "s") + " ago";
- }
-
static void fill_history_items_from_json(const Json::Value &history_json, BodyItems &history_items) {
assert(history_json.isArray());
- BodyItems body_items;
-
time_t time_now = time(NULL);
for(const Json::Value &item : history_json) {
if(!item.isObject())
@@ -1403,12 +1408,10 @@ namespace QuickMedia {
body_item->set_description("Watched " + seconds_to_relative_time_str(time_now - timestamp.asInt64()));
body_item->set_description_color(get_current_theme().faded_text_color);
body_item->thumbnail_size = sf::Vector2i(192, 108);
- body_items.push_back(std::move(body_item));
+ history_items.push_back(std::move(body_item));
}
- for(auto it = body_items.rbegin(), end = body_items.rend(); it != end; ++it) {
- history_items.push_back(std::move(*it));
- }
+ std::reverse(history_items.begin(), history_items.end());
}
static Path get_video_history_filepath(const char *plugin_name) {
@@ -1626,6 +1629,81 @@ namespace QuickMedia {
return true;
}
+ // Returns -1 if not found
+ int bookmark_find_item(Json::Value &root, const std::string &title, const std::string &author, const std::string &url) {
+ if(!root.isArray())
+ return false;
+
+ int index = -1;
+ for(const Json::Value &item_json : root) {
+ ++index;
+ if(!item_json.isObject())
+ continue;
+
+ const Json::Value &title_json = item_json["title"];
+ const Json::Value &author_json = item_json["author"];
+ const Json::Value &url_json = item_json["url"];
+ if((!title.empty() && title_json.isString() && strcmp(title.c_str(), title_json.asCString()) == 0)
+ || (!author.empty() && author_json.isString() && strcmp(author.c_str(), author_json.asCString()) == 0)
+ || (!url.empty() && url_json.isString() && strcmp(url.c_str(), url_json.asCString()) == 0))
+ {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+
+ bool Program::toggle_bookmark(BodyItem *body_item, const char *bookmark_name) {
+ assert(bookmark_name);
+ Path bookmark_path = get_storage_dir().join("bookmarks");
+ if(create_directory_recursive(bookmark_path) != 0) {
+ show_notification("QuickMedia", "Failed to update bookmark", Urgency::CRITICAL);
+ return false;
+ }
+
+ bookmark_path.join(bookmark_name);
+ Json::Value json_root;
+ if(!read_file_as_json(bookmark_path, json_root) || !json_root.isArray())
+ json_root = Json::Value(Json::arrayValue);
+
+ const int existing_index = bookmark_find_item(json_root, body_item->get_title(), body_item->get_author(), body_item->url);
+ if(existing_index != -1) {
+ Json::Value removed;
+ json_root.removeIndex(existing_index, &removed);
+ if(!save_json_to_file_atomic(bookmark_path, json_root)) {
+ show_notification("QuickMedia", "Failed to update bookmark", Urgency::CRITICAL);
+ return false;
+ }
+
+ std::string bookmark_title = body_item->get_title();
+ if(bookmark_title.empty()) bookmark_title = body_item->get_author();
+ show_notification("QuickMedia", "Removed " + bookmark_title + " from bookmarks");
+ removed = true;
+ return true;
+ }
+
+ Json::Value new_item(Json::objectValue);
+ if(!body_item->get_title().empty())
+ new_item["title"] = body_item->get_title();
+ if(!body_item->get_author().empty())
+ new_item["author"] = body_item->get_author();
+ if(!body_item->url.empty())
+ new_item["url"] = body_item->url;
+ new_item["timestamp"] = (int64_t)time(nullptr);
+
+ json_root.append(std::move(new_item));
+ if(!save_json_to_file_atomic(bookmark_path, json_root)) {
+ show_notification("QuickMedia", "Failed to update bookmark", Urgency::CRITICAL);
+ return false;
+ }
+
+ std::string bookmark_title = body_item->get_title();
+ if(bookmark_title.empty()) bookmark_title = body_item->get_author();
+ show_notification("QuickMedia", "Added " + bookmark_title + " to bookmarks");
+ return true;
+ }
+
void Program::page_loop_render(sf::RenderWindow &window, std::vector<Tab> &tabs, int selected_tab, TabAssociatedData &tab_associated_data, const Json::Value *json_chapters, Tabs &ui_tabs) {
if(tabs[selected_tab].search_bar) tabs[selected_tab].search_bar->draw(window, window_size, true);
@@ -2053,6 +2131,19 @@ namespace QuickMedia {
return trackable_page->track(selected_item->get_title()) == TrackResult::OK;
});
}
+ } else if(event.key.code == sf::Keyboard::B && event.key.control) {
+ BodyItem *selected_item = tabs[selected_tab].body->get_selected();
+ if(selected_item) {
+ const char *bookmark_name = tabs[selected_tab].page->get_bookmark_name();
+ if(bookmark_name) {
+ if(toggle_bookmark(selected_item, bookmark_name)) {
+ for(Tab &tab : tabs) {
+ if(tab.page && tab.page->is_bookmark_page())
+ tab.page->needs_refresh = true;
+ }
+ }
+ }
+ }
} else if(event.key.code == sf::Keyboard::C && event.key.control) {
BodyItem *selected_item = tabs[selected_tab].body->get_selected();
if(selected_item) {
@@ -7422,7 +7513,7 @@ namespace QuickMedia {
redraw = true;
} else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Tab) {
file_name_entry.set_editable(!file_name_entry.is_editable());
- search_bar->set_editable(!file_name_entry.is_editable());
+ search_bar->set_editable(!search_bar->is_editable());
} else if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Enter && event.key.control) {
std::string save_path = save_file();
if(!save_path.empty())