#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; class VideoPage; enum class ImageViewMode { SINGLE, SCROLL }; struct CopyOp { Path source; Path destination; }; enum class TaskResult { TRUE, FALSE, CANCEL }; 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(); void set_go_to_previous_page(); TaskResult run_task_with_loading_screen(std::function callback); const char* get_plugin_name() const; void manga_get_watch_history(const char *plugin_name, BodyItems &history_items); void youtube_get_watch_history(BodyItems &history_items); 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, int start_tab_index = 0, std::function after_submit_handler = nullptr); void video_content_page(VideoPage *video_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 *matrix_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(); 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 BodyItems &related_media_body_items); private: enum class UpscaleImageAction { NO, LOW_RESOLUTION, FORCE }; Display *disp; sf::RenderWindow window; Matrix *matrix = nullptr; bool is_login_sync = false; int monitor_hz; sf::Vector2f window_size; const char *plugin_name = nullptr; sf::Texture plugin_logo; sf::Texture loading_icon; sf::Sprite load_sprite; sf::Clock load_sprite_timer; 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; bool go_to_previous_page = false; std::thread::id main_thread_id; }; }