#pragma once #include "StateManager.hpp" #include "appstates/BaseState.hpp" #include "data/data.hpp" #include "fslib.hpp" #include "remote/remote.hpp" #include "sdl.hpp" #include "sys/sys.hpp" #include "ui/ui.hpp" #include #include /// @brief This is the state where the user can backup and restore saves. class BackupMenuState final : public BaseState { public: /// @brief Creates a new backup selection state. /// @param user Pointer to currently selected user. /// @param titleInfo Pointer to titleInfo of selected title. /// @param saveType Save data type we're working with. BackupMenuState(data::User *user, data::TitleInfo *titleInfo); /// @brief Creates and returns a new BackupMenuState. static inline std::shared_ptr create(data::User *user, data::TitleInfo *titleInfo) { return std::make_shared(user, titleInfo); } /// @brief Creates and pushes a new BackupMenuState to the vector. static inline std::shared_ptr create_and_push(data::User *user, data::TitleInfo *titleInfo) { auto newState = BackupMenuState::create(user, titleInfo); StateManager::push_state(newState); return newState; } /// @brief Required. Inherited virtual function from AppState. void update() override; /// @brief Required. Inherited virtual function from AppState. void render() override; /// @brief Refreshes the directory listing and menu. void refresh(); /// @brief Allows a spawned task to tell this class that it wrote save data to the system. void save_data_written(); // clang-format off enum class MenuEntryType { Null, Local, Remote }; struct MenuEntry { MenuEntryType type{}; int index{}; }; struct DataStruct : sys::Task::DataStruct { data::User *user{}; data::TitleInfo *titleInfo{}; fslib::Path path{}; // This and std::string remoteName{}; // and this and remote::Item *remoteItem{}; // this are set when needed. BackupMenuState *spawningState{}; bool killTask = false; // Some tasks use other tasks instead of repeating code. }; // clang-format on using TaskData = std::shared_ptr; private: /// @brief Pointer to current user. data::User *m_user{}; /// @brief Pointer to data for selected title. data::TitleInfo *m_titleInfo{}; /// @brief Save data type we're working with. FsSaveDataType m_saveType{}; /// @brief Path to the target directory of the title. fslib::Path m_directoryPath{}; /// @brief Directory listing of the above. fslib::Directory m_directoryListing{}; /// @brief Remote storage listing of the current parent. remote::Storage::DirectoryListing m_remoteListing{}; /// @brief This is the scrolling text at the top. std::shared_ptr m_titleScroll{}; /// @brief Variable that saves whether or not the filesystem has data in it. bool m_saveHasData{}; /// @brief Data struct passed to functions. std::shared_ptr m_dataStruct{}; /// @brief This keeps track of the properties of the entries in the menu. std::vector m_menuEntries{}; /// @brief This is a pointer to the control guide string. const char *m_controlGuide{}; /// @brief The width of the panels. This is set according to the control guide text. static inline int sm_panelWidth{}; /// @brief The menu used by all instances of BackupMenuState. static inline std::shared_ptr sm_backupMenu{}; /// @brief Prevents this and threads calling refresh() from causing races. static inline std::mutex sm_menuMutex{}; /// @brief The slide out panel used by all instances of BackupMenuState. static inline std::shared_ptr sm_slidePanel{}; /// @brief Inner render target so the menu only renders to a certain area. static inline sdl::SharedTexture sm_menuRenderTarget{}; /// @brief Initializes the static members all instances share if they haven't been already. void initialize_static_members(); /// @brief Checks for and tries to create the target directory if it hasn't been already. void ensure_target_directory(); /// @brief Initializes the struct passed to tasks. void initialize_task_data(); /// @brief Init's the string at the top of the backupmenu. void initialize_info_string(); /// @brief Checks to see if the save data is empty. void save_data_check(); /// @brief Ensures the remote storage is initalized and pointing to the right place. void initialize_remote_storage(); /// @brief This is the function called when New Backup is selected. void name_and_create_backup(); /// @brief This is the function called when a backup is selected to be overwritten. void confirm_overwrite(); /// @brief This function is called to confirm restoring a backup. void confirm_restore(); /// @brief Function called to confirm deleting a backup. void confirm_delete(); /// @brief Uploads the currently selected backup to the remote storage. void upload_backup(); /// @brief Just creates the pop-up that says Save is empty or w/e. void pop_save_empty(); /// @brief Performs some operations and then marks the state for purging. void deactivate_state(); inline bool user_is_system() { const uint8_t saveType = m_user->get_account_save_type(); return saveType == FsSaveDataType_System || saveType == FsSaveDataType_SystemBcat; } };