Page.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #pragma once
  2. #include "Plugin.hpp"
  3. #include "../include/Tab.hpp"
  4. #include "../include/SearchBar.hpp"
  5. #include "../include/Body.hpp"
  6. #include "../include/MediaChapter.hpp"
  7. namespace QuickMedia {
  8. class Program;
  9. constexpr int SEARCH_DELAY_FILTER = 50;
  10. // TODO: Rename to PageType when the other PageType is removed
  11. enum class PageTypez {
  12. REGULAR,
  13. MANGA_IMAGES,
  14. IMAGE_BOARD_THREAD,
  15. VIDEO,
  16. CHAT
  17. };
  18. struct SubmitArgs {
  19. std::string title;
  20. std::string url;
  21. std::string thumbnail_url;
  22. void *userdata = nullptr;
  23. std::shared_ptr<BodyItemExtra> extra;
  24. };
  25. class Page {
  26. public:
  27. Page(Program *program) : program(program) {}
  28. virtual ~Page() = default;
  29. virtual const char* get_title() const = 0;
  30. virtual bool search_is_filter() { return true; }
  31. // This show be overriden if search_is_filter is overriden to return false
  32. virtual SearchResult search(const std::string &str, BodyItems &result_items) { (void)str; (void)result_items; return SearchResult::ERR; }
  33. // If this returns true then |submit_suggestion| is called when submitting the selected item instead of |submit|
  34. // and |submit| is called when submitting the response of |submit_suggestion|
  35. virtual bool search_is_suggestion(bool empty_search) { (void)empty_search; return false; }
  36. // Return empty |result_tabs| and PluginResult::OK to do nothing; which is useful for implementing custom actions on item submit
  37. virtual PluginResult submit(const SubmitArgs &args, std::vector<Tab> &result_tabs) {
  38. (void)args;
  39. (void)result_tabs;
  40. return PluginResult::ERR;
  41. }
  42. // Override and return false to make submit run in the main (ui) thread
  43. virtual bool submit_is_async() const { return true; }
  44. virtual bool clear_search_after_submit() { return false; }
  45. virtual PluginResult submit_suggestion(const SubmitArgs &args, BodyItems &result_items) {
  46. (void)args;
  47. (void)result_items;
  48. return PluginResult::ERR;
  49. }
  50. // 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.
  51. // Note: the first page fetched is 1 (search/lazy fetch page is 0)
  52. virtual PluginResult get_page(const std::string &str, int page, BodyItems &result_items) { (void)str; (void)page; (void)result_items; return PluginResult::OK; }
  53. DownloadResult download_json(Json::Value &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent = false, std::string *err_msg = nullptr);
  54. virtual PageTypez get_type() const { return PageTypez::REGULAR; }
  55. // Mutually exclusive with |get_type| when |get_type| is not PageTypez::REGULAR
  56. virtual bool is_single_page() const { return false; }
  57. virtual bool is_trackable() const { return false; }
  58. // Return nullptr if bookmark is not supported by this page
  59. virtual const char* get_bookmark_name() const { return nullptr; }
  60. // If this returns nullptr then the currently selected body item is used instead.
  61. // |selected_item| may be nullptr.
  62. virtual std::shared_ptr<BodyItem> get_bookmark_body_item(BodyItem *selected_item) { (void)selected_item; return nullptr; }
  63. virtual bool is_bookmark_page() const { return false; }
  64. // |selected_item| may be nullptr.
  65. virtual void toggle_read(BodyItem *selected_item) { (void)selected_item; }
  66. virtual bool is_lazy_fetch_page() const { return false; }
  67. // 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
  68. virtual bool allow_submit_no_selection() const { return false; }
  69. // This is used to delay loading of the page. For example if the page relies on an external factor to start loading
  70. virtual bool is_ready() { return true; }
  71. // This is called both when first navigating to page and when going back to page
  72. virtual void on_navigate_to_page(Body *body) { (void)body; }
  73. virtual void cancel_operation() {}
  74. virtual void copy_to_clipboard(const BodyItem *body_item);
  75. std::unique_ptr<Body> create_body(bool plain_text_list = false, bool prefer_card_view = false);
  76. std::unique_ptr<SearchBar> create_search_bar(const std::string &placeholder_text, int search_delay);
  77. bool load_manga_content_storage(const char *service_name, const std::string &manga_title, const std::string &manga_url, const std::string &manga_id);
  78. void set_clipboard(const std::string &str);
  79. Program *program;
  80. bool needs_refresh = false; // Set to true to refresh the page. Note: only works for search pages and lazy fetch pages
  81. };
  82. enum class TrackResult {
  83. OK,
  84. ERR
  85. };
  86. class TrackablePage {
  87. public:
  88. TrackablePage(std::string content_title, std::string content_url) : content_title(std::move(content_title)), content_url(std::move(content_url)) {}
  89. virtual ~TrackablePage() = default;
  90. virtual TrackResult track(const std::string &str) = 0;
  91. const std::string content_title;
  92. const std::string content_url;
  93. };
  94. class LazyFetchPage : public Page {
  95. public:
  96. LazyFetchPage(Program *program) : Page(program) {}
  97. virtual bool search_is_filter() override { return true; }
  98. bool is_lazy_fetch_page() const override { return true; }
  99. virtual PluginResult lazy_fetch(BodyItems &result_items) = 0;
  100. // 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
  101. virtual bool lazy_fetch_is_loader() { return false; }
  102. virtual bool reload_on_page_change() { return false; }
  103. virtual bool reseek_to_body_item_by_url() { return false; }
  104. };
  105. class RelatedVideosPage : public Page {
  106. public:
  107. RelatedVideosPage(Program *program) : Page(program) {}
  108. const char* get_title() const override { return "Related videos"; }
  109. };
  110. struct SubtitleData {
  111. std::string url;
  112. std::string title;
  113. };
  114. struct SponsorSegment {
  115. double start_seconds;
  116. double end_seconds;
  117. };
  118. struct VideoInfo {
  119. std::string title;
  120. std::string channel_url;
  121. double duration = 0.0;
  122. std::vector<MediaChapter> chapters;
  123. std::string referer;
  124. std::vector<SponsorSegment> sponsor_segments;
  125. };
  126. class VideoPage : public Page {
  127. public:
  128. VideoPage(Program *program, std::string url, bool autoplay = true) : Page(program), url(std::move(url)), autoplay(autoplay) {}
  129. virtual PageTypez get_type() const override { return PageTypez::VIDEO; }
  130. virtual bool autoplay_next_item() { return false; }
  131. bool should_autoplay() const { return autoplay; }
  132. virtual BodyItems get_related_media(const std::string &url) { (void)url; return {}; }
  133. virtual PluginResult get_related_pages(const BodyItems &related_videos, const std::string &channel_url, std::vector<Tab> &result_tabs) {
  134. (void)related_videos;
  135. (void)channel_url;
  136. (void)result_tabs;
  137. return PluginResult::OK;
  138. }
  139. virtual int get_related_pages_first_tab() { return 0; }
  140. virtual void set_url(std::string new_url) { url = std::move(new_url); }
  141. std::string get_url() { return url; }
  142. virtual std::string get_download_url(int max_height) { (void)max_height; return url; }
  143. // Returns empty string for no timestamp or if the video doesn't support timestamps.
  144. // Timestamp is in seconds.
  145. virtual std::string get_url_timestamp() { return ""; }
  146. // Falls back to |get_url| if this and |get_audio_url| returns empty strings.
  147. // Might do a network request.
  148. virtual std::string get_video_url(int max_height, bool &has_embedded_audio, std::string &ext) {
  149. (void)max_height;
  150. (void)ext;
  151. has_embedded_audio = true;
  152. return "";
  153. }
  154. // Only used if |get_video_url| sets |has_embedded_audio| to false.
  155. // Might do a network request.
  156. virtual std::string get_audio_url(std::string &ext) { (void)ext; return ""; }
  157. // Might do a network request
  158. virtual std::string url_get_playable_url(const std::string &url) { return url; }
  159. virtual bool video_should_be_skipped(const std::string &url) { (void)url; return false; }
  160. // This needs to be called before the other functions are called
  161. virtual PluginResult load(const SubmitArgs &args, VideoInfo &video_info, std::string &err_str) {
  162. (void)args; (void)video_info; (void)err_str;
  163. return PluginResult::OK;
  164. }
  165. virtual void mark_watched() {};
  166. // Should not do any network request to not slow down video loading
  167. virtual void get_subtitles(SubtitleData &subtitle_data) { (void)subtitle_data; }
  168. virtual std::string get_filename() { return ""; }
  169. virtual bool is_local() const { return false; }
  170. virtual void set_watch_progress(int64_t time_pos_sec, int64_t duration_sec) { (void)time_pos_sec; (void)duration_sec; }
  171. protected:
  172. std::string url;
  173. bool autoplay;
  174. };
  175. class BookmarksPage : public LazyFetchPage {
  176. public:
  177. BookmarksPage(Program *program, Page *redirect_page, bool local_thumbnail = false) : LazyFetchPage(program), redirect_page(redirect_page), local_thumbnail(local_thumbnail) {}
  178. const char* get_title() const override { return "Bookmarks"; }
  179. PluginResult submit(const SubmitArgs &args, std::vector<Tab> &result_tabs) override;
  180. PluginResult lazy_fetch(BodyItems &result_items) override;
  181. bool reload_on_page_change() override { return true; }
  182. const char* get_bookmark_name() const override { return redirect_page->get_bookmark_name(); }
  183. bool is_bookmark_page() const override { return true; }
  184. mgl::vec2i thumbnail_size = {101, 141};
  185. private:
  186. Page *redirect_page;
  187. bool local_thumbnail;
  188. };
  189. class LoginPage : public Page {
  190. public:
  191. LoginPage(Program *program) : Page(program) {}
  192. bool submit_is_async() const override { return true; }
  193. bool allow_submit_no_selection() const override { return true; }
  194. void login_finish();
  195. bool logged_in() const;
  196. private:
  197. bool login_finished = false;
  198. };
  199. }