1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
#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
};
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 std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
(void)title;
(void)url;
(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 std::string &title, const std::string &url, BodyItems &result_items) {
(void)title;
(void)url;
(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<CommandArg> 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
virtual std::shared_ptr<BodyItem> get_bookmark_body_item() { return nullptr; }
virtual bool is_bookmark_page() const { return false; }
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() {}
std::unique_ptr<Body> create_body(bool plain_text_list = false, bool prefer_card_view = false);
std::unique_ptr<SearchBar> 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);
Program *program;
std::shared_ptr<BodyItem> submit_body_item; // TODO: Remove this
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; }
};
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 bool create_search_page(Program *program, Tab &tab) { (void)program; (void)tab; return false; }
virtual std::unique_ptr<Page> create_comments_page(Program *program) { (void)program; return nullptr; }
// Return nullptr if the service doesn't support related videos page
virtual std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program) = 0;
// Return nullptr if the service doesn't support channels page
virtual std::unique_ptr<Page> create_channels_page(Program *program, const std::string &channel_url) = 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 ""; }
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(std::string &title, std::string &channel_url, std::vector<MediaChapter> &chapters, std::string &err_str) {
(void)title; (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; }
protected:
std::string url;
};
class BookmarksPage : public LazyFetchPage {
public:
BookmarksPage(Program *program, Page *redirect_page) : LazyFetchPage(program), redirect_page(redirect_page) {}
const char* get_title() const override { return "Bookmarks"; }
PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &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; }
private:
Page *redirect_page;
};
}
|