#pragma once #include "Body.hpp" #include "SearchBar.hpp" #include "Page.hpp" #include "Storage.hpp" #include "Tab.hpp" #include "MessageQueue.hpp" #include #include #include #include #include #include #include #include #include #include #include #include namespace QuickMedia { class Matrix; class FileManager; class MangaImagesPage; class ImageBoardThreadPage; class RoomData; class MatrixChatPage; enum class ImageViewMode { SINGLE, SCROLL }; struct CopyOp { Path source; Path destination; }; class Program { public: Program(); ~Program(); int run(int argc, char **argv); bool is_tor_enabled(); std::unique_ptr create_body(); std::unique_ptr create_search_bar(const std::string &placeholder, int search_delay); bool load_manga_content_storage(const char *service_name, const std::string &manga_title, const std::string &manga_id); void select_file(const std::string &filepath); bool is_window_focused(); RoomData* get_current_chat_room(); private: void base_event_handler(sf::Event &event, PageType previous_page, Body *body, SearchBar *search_bar, bool handle_key_press = true, bool handle_searchbar = true); void page_loop(std::vector &tabs); void video_content_page(Page *page, std::string video_url, std::string video_title, bool download_if_streaming_fails); // Returns -1 to go to previous chapter, 0 to stay on same chapter and 1 to go to next chapter int image_page(MangaImagesPage *images_page, Body *chapters_body); void image_continuous_page(MangaImagesPage *images_page); void image_board_thread_page(ImageBoardThreadPage *thread_page, Body *thread_body); void chat_login_page(); void chat_page(MatrixChatPage *chat_page, RoomData *current_room); void after_matrix_login_page(); enum class LoadImageResult { OK, FAILED, DOWNLOAD_IN_PROGRESS }; LoadImageResult load_image_by_index(int image_index, sf::Texture &image_texture, sf::String &error_message); void download_chapter_images_if_needed(MangaImagesPage *images_page); void select_episode(BodyItem *item, bool start_from_beginning); // Returns PageType::EXIT if empty PageType pop_page_stack(); void manga_get_watch_history(const char *plugin_name, BodyItems &history_items); void youtube_get_watch_history(BodyItems &history_items); Json::Value load_video_history_json(); Json::Value load_recommended_json(); void save_recommendations_from_related_videos(const std::string &video_url, const std::string &video_title, const Body *related_media_body); private: enum class UpscaleImageAction { NO, LOW_RESOLUTION, FORCE }; Display *disp; sf::RenderWindow window; Matrix *matrix = nullptr; int monitor_hz; sf::Vector2f window_size; std::unique_ptr font; std::unique_ptr bold_font; std::unique_ptr cjk_font; const char *plugin_name = nullptr; sf::Texture plugin_logo; sf::Texture loading_icon; PageType current_page; std::stack page_stack; int image_index; Path content_storage_file; Path content_cache_dir; std::string manga_id_base64; Json::Value content_storage_json; std::unordered_set watched_videos; std::future search_suggestion_future; std::future autocomplete_future; std::future image_download_future; std::thread image_upscale_thead; MessageQueue images_to_upscale_queue; std::vector image_upscale_status; std::string downloading_chapter_url; bool image_download_cancel = false; int exit_code = 0; std::string resources_root; sf::Shader circle_mask_shader; bool use_tor = false; bool no_video = false; bool use_system_mpv_config = false; UpscaleImageAction upscale_image_action = UpscaleImageAction::NO; // TODO: Save this to config file when switching modes ImageViewMode image_view_mode = ImageViewMode::SINGLE; std::vector selected_files; bool fit_image_to_window = false; RoomData *current_chat_room = nullptr; }; }