#pragma once #include "Plugin.hpp" #include "../include/Tab.hpp" #include "../include/SearchBar.hpp" #include "../include/Body.hpp" #include "../include/MediaChapter.hpp" namespace QuickMedia { class Program; constexpr int SEARCH_DELAY_FILTER = 50; // TODO: Rename to PageType when the other PageType is removed enum class PageTypez { REGULAR, MANGA_IMAGES, IMAGE_BOARD_THREAD, VIDEO, CHAT }; struct SubmitArgs { std::string title; std::string url; std::string thumbnail_url; void *userdata = nullptr; std::shared_ptr extra; }; class Page { public: Page(Program *program) : program(program) {} virtual ~Page() = default; virtual const char* get_title() const = 0; virtual bool search_is_filter() { return true; } // This show be overriden if search_is_filter is overriden to return false virtual SearchResult search(const std::string &str, BodyItems &result_items) { (void)str; (void)result_items; return SearchResult::ERR; } // If this returns true then |submit_suggestion| is called when submitting the selected item instead of |submit| // and |submit| is called when submitting the response of |submit_suggestion| virtual bool search_is_suggestion() { return false; } // Return empty |result_tabs| and PluginResult::OK to do nothing; which is useful for implementing custom actions on item submit virtual PluginResult submit(const SubmitArgs &args, std::vector &result_tabs) { (void)args; (void)result_tabs; return PluginResult::ERR; } // Override and return false to make submit run in the main (ui) thread virtual bool submit_is_async() const { return true; } virtual bool clear_search_after_submit() { return false; } virtual PluginResult submit_suggestion(const SubmitArgs &args, BodyItems &result_items) { (void)args; (void)result_items; return PluginResult::ERR; } // Note: If pagination is done by fetching the next page until we get to |page|, then the "current page" should be reset everytime |search| is called. // Note: the first page fetched is 1 (search/lazy fetch page is 0) virtual PluginResult get_page(const std::string &str, int page, BodyItems &result_items) { (void)str; (void)page; (void)result_items; return PluginResult::OK; } DownloadResult download_json(Json::Value &result, const std::string &url, std::vector additional_args, bool use_browser_useragent = false, std::string *err_msg = nullptr); virtual PageTypez get_type() const { return PageTypez::REGULAR; } // Mutually exclusive with |get_type| when |get_type| is not PageTypez::REGULAR virtual bool is_single_page() const { return false; } virtual bool is_trackable() const { return false; } // Return nullptr if bookmark is not supported by this page virtual const char* get_bookmark_name() const { return nullptr; } // If this returns nullptr then the currently selected body item is used instead. // |selected_item| may be nullptr. virtual std::shared_ptr get_bookmark_body_item(BodyItem *selected_item) { (void)selected_item; return nullptr; } virtual bool is_bookmark_page() const { return false; } // |selected_item| may be nullptr. virtual void toggle_read(BodyItem *selected_item) { (void)selected_item; } virtual bool is_lazy_fetch_page() const { return false; } // Note: If submit is done without any selection, then the search term is sent as the |title| and |url|. Submit will only be sent if the input text is not empty or if an item is selected virtual bool allow_submit_no_selection() const { return false; } // This is used to delay loading of the page. For example if the page relies on an external factor to start loading virtual bool is_ready() { return true; } // This is called both when first navigating to page and when going back to page virtual void on_navigate_to_page(Body *body) { (void)body; } virtual void cancel_operation() {} virtual void copy_to_clipboard(const BodyItem *body_item); std::unique_ptr create_body(bool plain_text_list = false, bool prefer_card_view = false); std::unique_ptr create_search_bar(const std::string &placeholder_text, int search_delay); bool load_manga_content_storage(const char *service_name, const std::string &manga_title, const std::string &manga_url, const std::string &manga_id); void set_clipboard(const std::string &str); Program *program; bool needs_refresh = false; // Set to true to refresh the page. Note: only works for search pages and lazy fetch pages }; enum class TrackResult { OK, ERR }; class TrackablePage { public: TrackablePage(std::string content_title, std::string content_url) : content_title(std::move(content_title)), content_url(std::move(content_url)) {} virtual ~TrackablePage() = default; virtual TrackResult track(const std::string &str) = 0; const std::string content_title; const std::string content_url; }; class LazyFetchPage : public Page { public: LazyFetchPage(Program *program) : Page(program) {} virtual bool search_is_filter() override { return true; } bool is_lazy_fetch_page() const override { return true; } virtual PluginResult lazy_fetch(BodyItems &result_items) = 0; // If this returns true then |lazy_fetch| is not meant to return results but async background load the page. This can be used to fetch API keys for example virtual bool lazy_fetch_is_loader() { return false; } virtual bool reload_on_page_change() { return false; } virtual bool reseek_to_body_item_by_url() { return false; } }; class RelatedVideosPage : public Page { public: RelatedVideosPage(Program *program) : Page(program) {} const char* get_title() const override { return "Related videos"; } }; struct SubtitleData { std::string url; std::string title; }; class VideoPage : public Page { public: VideoPage(Program *program, std::string url) : Page(program), url(std::move(url)) {} virtual PageTypez get_type() const override { return PageTypez::VIDEO; } virtual bool autoplay_next_item() { return false; } virtual BodyItems get_related_media(const std::string &url) { (void)url; return {}; } virtual PluginResult get_related_pages(const BodyItems &related_videos, const std::string &channel_url, std::vector &result_tabs) { (void)related_videos; (void)channel_url; (void)result_tabs; return PluginResult::OK; } virtual int get_related_pages_first_tab() { return 0; } virtual void set_url(std::string new_url) { url = std::move(new_url); } std::string get_url() { return url; } virtual std::string get_download_url(int max_height) { (void)max_height; return url; } // Returns empty string for no timestamp or if the video doesn't support timestamps. // Timestamp is in seconds. virtual std::string get_url_timestamp() { return ""; } // Falls back to |get_url| if this and |get_audio_url| returns empty strings. // Might do a network request. virtual std::string get_video_url(int max_height, bool &has_embedded_audio, std::string &ext) { (void)max_height; (void)ext; has_embedded_audio = true; return ""; } // Only used if |get_video_url| sets |has_embedded_audio| to false. // Might do a network request. virtual std::string get_audio_url(std::string &ext) { (void)ext; return ""; } // Might do a network request virtual std::string url_get_playable_url(const std::string &url) { return url; } virtual bool video_should_be_skipped(const std::string &url) { (void)url; return false; } // This needs to be called before the other functions are called virtual PluginResult load(const SubmitArgs &args, std::string &title, std::string &channel_url, double &duration, std::vector &chapters, std::string &err_str) { (void)args; (void)title; (void)duration; (void)channel_url; (void)chapters; (void)err_str; return PluginResult::OK; } virtual void mark_watched() {}; // Should not do any network request to not slow down video loading virtual void get_subtitles(SubtitleData &subtitle_data) { (void)subtitle_data; } virtual bool is_local() const { return false; } virtual void set_watch_progress(int64_t time_pos_sec, int64_t duration_sec) { (void)time_pos_sec; (void)duration_sec; } protected: std::string url; }; class BookmarksPage : public LazyFetchPage { public: BookmarksPage(Program *program, Page *redirect_page, bool local_thumbnail = false) : LazyFetchPage(program), redirect_page(redirect_page), local_thumbnail(local_thumbnail) {} const char* get_title() const override { return "Bookmarks"; } PluginResult submit(const SubmitArgs &args, std::vector &result_tabs) override; PluginResult lazy_fetch(BodyItems &result_items) override; bool reload_on_page_change() override { return true; } const char* get_bookmark_name() const override { return redirect_page->get_bookmark_name(); } bool is_bookmark_page() const override { return true; } mgl::vec2i thumbnail_size = {101, 141}; private: Page *redirect_page; bool local_thumbnail; }; class LoginPage : public Page { public: LoginPage(Program *program) : Page(program) {} bool submit_is_async() const override { return true; } bool allow_submit_no_selection() const override { return true; } void login_finish(); bool logged_in() const; private: bool login_finished = false; }; }