mirror of
https://github.com/J-D-K/JKSV.git
synced 2026-04-24 07:17:11 -05:00
File mode progress.
This commit is contained in:
parent
75303dcebb
commit
a072c28dfb
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -16,3 +16,4 @@ JKSV.pfs0
|
|||
|
||||
#sometimes I give jksv to people and forget about this.
|
||||
JKSV.zip
|
||||
JKSV.nro.zip
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f948cecb43c4f1e089442a8c0fd58df7deefb955
|
||||
Subproject commit 7156c8a8828096205cecc3421413bda75987fe78
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit fa7d0f456c78d7f94b8519260978419b564610b8
|
||||
Subproject commit 779fc5bd8aa4782e376fbce3baa146837f7d4825
|
||||
5
Makefile
5
Makefile
|
|
@ -51,7 +51,7 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
|||
# NOTE: For some reason, devkitpro no longer has freetype-config included? Also, using pkg-config causes conflicts with
|
||||
# my local pkg-config and I don't feel like dealing with CMake for all of this right now.
|
||||
CFLAGS := $(INCLUDE) -D__SWITCH__ `sdl2-config --cflags` `curl-config --cflags`\
|
||||
-g -Wall -O2 -ffunction-sections -ffast-math -fmax-errors=1 \
|
||||
-g -Wall -O3 -ffunction-sections -ffast-math -fmax-errors=1 \
|
||||
$(ARCH) $(DEFINES)
|
||||
|
||||
CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=c++23
|
||||
|
|
@ -172,11 +172,12 @@ clean:
|
|||
@$(MAKE) -C ./Libraries/SDLLib/SDL clean
|
||||
@rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
send: $(BUILD)
|
||||
@nxlink $(TARGET).nro
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
debug: $(BUILD)
|
||||
@nxlink -s $(TARGET).nro
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ class BaseState
|
|||
/// @brief Every derived class is required to have this function.
|
||||
virtual void update() = 0;
|
||||
|
||||
/// @brief Sub update routine. Meant to handle minor background tasks. Not meant for full update routines.
|
||||
virtual void sub_update() {};
|
||||
|
||||
/// @brief Every derived class is required to have this function.
|
||||
virtual void render() = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,4 +34,22 @@ class ExtrasMenuState final : public BaseState
|
|||
|
||||
/// @brief This function is called when Reinitialize data is selected.
|
||||
void reinitialize_data();
|
||||
|
||||
/// @brief Opens an SD to SD file browser.
|
||||
void sd_to_sd_browser();
|
||||
|
||||
/// @brief Opens the prodinfo-f to sd.
|
||||
void prodinfof_to_sd();
|
||||
|
||||
/// @brief Opens the safe partition to SD.
|
||||
void safe_to_sd();
|
||||
|
||||
/// @brief Opens the system partition to SD.
|
||||
void system_to_sd();
|
||||
|
||||
/// @brief Opens the user partition to SD.
|
||||
void user_to_sd();
|
||||
|
||||
/// @brief Terminates a process.
|
||||
void terminate_process();
|
||||
};
|
||||
|
|
|
|||
172
include/appstates/FileModeState.hpp
Normal file
172
include/appstates/FileModeState.hpp
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
#pragma once
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/BaseState.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "ui/ui.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
class FileModeState final : public BaseState
|
||||
{
|
||||
public:
|
||||
/// @brief Constructs a new FileModeState.
|
||||
FileModeState(std::string_view mountA, std::string_view mountB, int64_t journalSize = 0);
|
||||
|
||||
/// @brief Destructor. Closes the filesystems passed.
|
||||
~FileModeState() {};
|
||||
|
||||
static inline std::shared_ptr<FileModeState> create(std::string_view mountA,
|
||||
std::string_view mountB,
|
||||
int64_t journalSize = 0)
|
||||
{
|
||||
return std::make_shared<FileModeState>(mountA, mountB, journalSize);
|
||||
}
|
||||
|
||||
static inline std::shared_ptr<FileModeState> create_and_push(std::string_view mountA,
|
||||
std::string_view mountB,
|
||||
int64_t journalSize = 0)
|
||||
{
|
||||
auto newState = std::make_shared<FileModeState>(mountA, mountB, journalSize);
|
||||
StateManager::push_state(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
/// @brief Update override.
|
||||
void update() override;
|
||||
|
||||
/// @brief Render override.
|
||||
void render() override;
|
||||
|
||||
/// @brief Returns the target/active bool.
|
||||
bool get_target() const noexcept;
|
||||
|
||||
/// @brief Returns the source path. This is used with the FileOptionState.
|
||||
fslib::Path get_source();
|
||||
|
||||
/// @brief Returns the destination path. This is used with the FileOptionState.
|
||||
fslib::Path get_destination();
|
||||
|
||||
/// @brief Returns whether or not committing the transfer is required to FileOptionState.
|
||||
bool commit_required() const noexcept;
|
||||
|
||||
/// @brief Returns the journaling size passed to this for FileOptionState.
|
||||
int64_t get_journal_size() const noexcept;
|
||||
|
||||
/// @brief Renders the control guide in the bottom right.
|
||||
void render_control_guide() noexcept;
|
||||
|
||||
private:
|
||||
/// @brief These store the mount points to close the filesystems upon construction.
|
||||
std::string m_mountA;
|
||||
std::string m_mountB;
|
||||
|
||||
/// @brief These are the actual target paths.
|
||||
fslib::Path m_pathA{};
|
||||
fslib::Path m_pathB{};
|
||||
|
||||
/// @brief Directory listings for each respective path.
|
||||
fslib::Directory m_dirA{};
|
||||
fslib::Directory m_dirB{};
|
||||
|
||||
/// @brief Menus for the directory listings.
|
||||
std::shared_ptr<ui::Menu> m_dirMenuA{};
|
||||
std::shared_ptr<ui::Menu> m_dirMenuB{};
|
||||
|
||||
/// @brief Controls which menu/filesystem is currently targetted.
|
||||
bool m_target{};
|
||||
|
||||
/// @brief Stores the size for committing data (if needed) to mountA.
|
||||
int64_t m_journalSize{};
|
||||
|
||||
/// @brief The beginning Y coord of the dialog.
|
||||
double m_y{720.0f};
|
||||
|
||||
/// @brief This is the targetY. Used for the opening and hiding effect.
|
||||
double m_targetY{91.0f};
|
||||
|
||||
/// @brief Config scaling for the "transition"
|
||||
double m_scaling{};
|
||||
|
||||
/// @brief Stores whether or not the dialog has reached its targetted position.
|
||||
bool m_inPlace{};
|
||||
|
||||
/// @brief Frame shared by all instances.
|
||||
static inline std::shared_ptr<ui::Frame> sm_frame{};
|
||||
|
||||
/// @brief This is the render target the browsers are rendered to.
|
||||
static inline sdl::SharedTexture sm_renderTarget{};
|
||||
|
||||
/// @brief Stores a pointer to the guide in the bottom-right corner.
|
||||
static inline const char *sm_controlGuide{};
|
||||
|
||||
/// @brief Calculated X coordinate of the control guide text.
|
||||
static inline int sm_controlGuideX{};
|
||||
|
||||
/// @brief Initializes the members shared by all instances of FileModeState.
|
||||
void initialize_static_members();
|
||||
|
||||
/// @brief Creates valid paths with the mounts passed.
|
||||
void initialize_paths();
|
||||
|
||||
/// @brief Ensures the menus are allocated and setup properly.
|
||||
void initialize_menus();
|
||||
|
||||
/// @brief Loads the current directory listings and menus.
|
||||
void initialize_directory_menu(const fslib::Path &path, fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Updates the dialog's coordinates in the beginning.
|
||||
void update_y_coord() noexcept;
|
||||
|
||||
/// @brief Starts the dialog hiding process.
|
||||
void hide_dialog() noexcept;
|
||||
|
||||
/// @brief Returns whether or not the dialog is hidden.
|
||||
bool is_hidden() noexcept;
|
||||
|
||||
/// @brief Handles changing the current directory or opening the options.
|
||||
void enter_selected(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Opens the little option pop-up thingy.
|
||||
void open_option_menu(fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Changes the current target/controllable menu.
|
||||
void change_target() noexcept;
|
||||
|
||||
/// @brief Function executed when '..' is selected.
|
||||
void up_one_directory(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu);
|
||||
|
||||
/// @brief Appends the entry passed to the path passed and "enters" the directory.
|
||||
/// @param path Working path.
|
||||
/// @param directory Working directory.
|
||||
/// @param menu Working menu.
|
||||
/// @param entry Target entry.
|
||||
void enter_directory(fslib::Path &path,
|
||||
fslib::Directory &directory,
|
||||
ui::Menu &menu,
|
||||
const fslib::DirectoryEntry &entry);
|
||||
|
||||
/// @brief Returns a reference to the currently active menu.
|
||||
ui::Menu &get_source_menu() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the currently inactive menu.
|
||||
ui::Menu &get_destination_menu() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the current "active" path.
|
||||
fslib::Path &get_source_path() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the currently "inactive" path.
|
||||
fslib::Path &get_destination_path() noexcept;
|
||||
|
||||
/// @brief Returns a reference to the "active" directory.
|
||||
fslib::Directory &get_source_directory() noexcept;
|
||||
|
||||
/// @brief Returns a reference ot the currently "inactive" directory.
|
||||
fslib::Directory &get_destination_directory() noexcept;
|
||||
|
||||
/// @brief Returns whether or not a path is at the root.
|
||||
inline bool path_is_root(fslib::Path &path) const { return std::char_traits<char>::length(path.get_path()) <= 1; }
|
||||
|
||||
/// @brief Closes the filesystems passed and deactivates the state.
|
||||
void deactivate_state() noexcept;
|
||||
};
|
||||
110
include/appstates/FileOptionState.hpp
Normal file
110
include/appstates/FileOptionState.hpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/BaseState.hpp"
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "ui/ui.hpp"
|
||||
|
||||
class FileOptionState final : public BaseState
|
||||
{
|
||||
public:
|
||||
/// @brief FileOptionState.
|
||||
/// @param spawningState Pointer to spawning state to grab its goodies.
|
||||
FileOptionState(FileModeState *spawningState);
|
||||
|
||||
~FileOptionState() {};
|
||||
|
||||
/// @brief Inline creation function.
|
||||
static inline std::shared_ptr<FileOptionState> create(FileModeState *spawningState)
|
||||
{
|
||||
return std::make_shared<FileOptionState>(spawningState);
|
||||
}
|
||||
|
||||
/// @brief Same as above. Pushes state before returning it.
|
||||
static inline std::shared_ptr<FileOptionState> create_and_push(FileModeState *spawningState)
|
||||
{
|
||||
auto newState = FileOptionState::create(spawningState);
|
||||
StateManager::push_state(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
/// @brief Update routine.
|
||||
void update() override;
|
||||
|
||||
/// @brief Render routine.
|
||||
void render() override;
|
||||
|
||||
// clang-format off
|
||||
struct DataStruct
|
||||
{
|
||||
fslib::Path sourcePath{};
|
||||
fslib::Path destPath{};
|
||||
int64_t journalSize{};
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
/// @brief This makes some other stuff easier to read and type.
|
||||
using TaskData = std::shared_ptr<FileOptionState::DataStruct>;
|
||||
|
||||
private:
|
||||
/// @brief Pointer to spawning FileMode state.
|
||||
FileModeState *m_spawningState{};
|
||||
|
||||
/// @brief Stores whether or not tasks require committing data and changes to the target.
|
||||
bool m_commitData{};
|
||||
|
||||
/// @brief Journal size for when committing is required.
|
||||
int64_t m_journalSize{};
|
||||
|
||||
/// @brief X coordinate. This is set at construction according to the target from the spawning state.
|
||||
int m_x{};
|
||||
|
||||
/// @brief X coordinate for the target to reach.
|
||||
int m_targetX{};
|
||||
|
||||
/// @brief Whether or not the dialog/menu is in place.
|
||||
bool m_inPlace{};
|
||||
|
||||
/// @brief Whether or not the state should be closed.
|
||||
bool m_close{};
|
||||
|
||||
/// @brief This holds the scaling in config.
|
||||
double m_scaling{};
|
||||
|
||||
/// @brief This is the data struct passed to tasks.
|
||||
std::shared_ptr<FileOptionState::DataStruct> m_dataStruct{};
|
||||
|
||||
/// @brief This is shared by all instances.
|
||||
static inline std::shared_ptr<ui::Menu> sm_copyMenu{};
|
||||
|
||||
/// @brief This is shared by all instances.
|
||||
static inline std::shared_ptr<ui::DialogBox> sm_dialog{};
|
||||
|
||||
/// @brief Ensures static members of all instances are allocated.
|
||||
void initialize_static_members();
|
||||
|
||||
/// @brief Sets whether the dialog/menu are positioned left or right depending on the menu active in the spawning state.
|
||||
void set_menu_side();
|
||||
|
||||
/// @brief Updates the Y coordinate
|
||||
void update_x_coord();
|
||||
|
||||
void copy_target();
|
||||
|
||||
void delete_target();
|
||||
|
||||
void rename_target();
|
||||
|
||||
void create_directory();
|
||||
|
||||
void get_show_target_properties();
|
||||
|
||||
/// @brief Closes and hides the state.
|
||||
void close();
|
||||
|
||||
/// @brief Returns whether or not the state is closed.
|
||||
bool is_closed();
|
||||
|
||||
/// @brief Sets the menu index back to 0 and deactivates the state.
|
||||
void deactivate_state();
|
||||
};
|
||||
|
|
@ -39,6 +39,9 @@ class TitleOptionState final : public BaseState
|
|||
/// @brief Runs update routine.
|
||||
void update() override;
|
||||
|
||||
/// @brief Handles hiding the panel.
|
||||
void sub_update() override;
|
||||
|
||||
/// @brief Runs the render routine.
|
||||
void render() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class UserOptionState final : public BaseState
|
|||
/// @brief Runs the render routine.
|
||||
void update() override;
|
||||
|
||||
/// @brief Handles hiding the panel.
|
||||
void sub_update() override;
|
||||
|
||||
/// @brief Runs the render routine.
|
||||
void render() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,34 +1,31 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
|
||||
namespace config
|
||||
namespace config::keys
|
||||
{
|
||||
namespace keys
|
||||
{
|
||||
inline constexpr std::string_view WORKING_DIRECTORY = "WorkingDirectory";
|
||||
inline constexpr std::string_view INCLUDE_DEVICE_SAVES = "IncludeDeviceSaves";
|
||||
inline constexpr std::string_view AUTO_BACKUP_ON_RESTORE = "AutoBackupOnRestore";
|
||||
inline constexpr std::string_view AUTO_NAME_BACKUPS = "AutoNameBackups";
|
||||
inline constexpr std::string_view AUTO_UPLOAD = "AutoUploadToRemote";
|
||||
inline constexpr std::string_view USE_TITLE_IDS = "AlwaysUseTitleID";
|
||||
inline constexpr std::string_view HOLD_FOR_DELETION = "HoldForDeletion";
|
||||
inline constexpr std::string_view HOLD_FOR_RESTORATION = "HoldForRestoration";
|
||||
inline constexpr std::string_view HOLD_FOR_OVERWRITE = "HoldForOverWrite";
|
||||
inline constexpr std::string_view ONLY_LIST_MOUNTABLE = "OnlyListMountable";
|
||||
inline constexpr std::string_view LIST_ACCOUNT_SYS_SAVES = "ListAccountSystemSaves";
|
||||
inline constexpr std::string_view ALLOW_WRITING_TO_SYSTEM = "AllowSystemSaveWriting";
|
||||
inline constexpr std::string_view EXPORT_TO_ZIP = "ExportToZip";
|
||||
inline constexpr std::string_view ZIP_COMPRESSION_LEVEL = "ZipCompressionLevel";
|
||||
inline constexpr std::string_view TITLE_SORT_TYPE = "TitleSortType";
|
||||
inline constexpr std::string_view JKSM_TEXT_MODE = "JKSMTextMode";
|
||||
inline constexpr std::string_view FORCE_ENGLISH = "ForceEnglish";
|
||||
inline constexpr std::string_view SHOW_DEVICE_USER = "ShowDevice";
|
||||
inline constexpr std::string_view SHOW_BCAT_USER = "ShowBCAT";
|
||||
inline constexpr std::string_view SHOW_CACHE_USER = "ShowCache";
|
||||
inline constexpr std::string_view SHOW_SYSTEM_USER = "ShowSystem";
|
||||
inline constexpr std::string_view ENABLE_TRASH_BIN = "EnableTrash";
|
||||
inline constexpr std::string_view UI_ANIMATION_SCALE = "UIAnimationScaling";
|
||||
inline constexpr std::string_view FAVORITES = "Favorites";
|
||||
inline constexpr std::string_view BLACKLIST = "BlackList";
|
||||
} // namespace keys
|
||||
inline constexpr std::string_view WORKING_DIRECTORY = "WorkingDirectory";
|
||||
inline constexpr std::string_view INCLUDE_DEVICE_SAVES = "IncludeDeviceSaves";
|
||||
inline constexpr std::string_view AUTO_BACKUP_ON_RESTORE = "AutoBackupOnRestore";
|
||||
inline constexpr std::string_view AUTO_NAME_BACKUPS = "AutoNameBackups";
|
||||
inline constexpr std::string_view AUTO_UPLOAD = "AutoUploadToRemote";
|
||||
inline constexpr std::string_view USE_TITLE_IDS = "AlwaysUseTitleID";
|
||||
inline constexpr std::string_view HOLD_FOR_DELETION = "HoldForDeletion";
|
||||
inline constexpr std::string_view HOLD_FOR_RESTORATION = "HoldForRestoration";
|
||||
inline constexpr std::string_view HOLD_FOR_OVERWRITE = "HoldForOverWrite";
|
||||
inline constexpr std::string_view ONLY_LIST_MOUNTABLE = "OnlyListMountable";
|
||||
inline constexpr std::string_view LIST_ACCOUNT_SYS_SAVES = "ListAccountSystemSaves";
|
||||
inline constexpr std::string_view ALLOW_WRITING_TO_SYSTEM = "AllowSystemSaveWriting";
|
||||
inline constexpr std::string_view EXPORT_TO_ZIP = "ExportToZip";
|
||||
inline constexpr std::string_view ZIP_COMPRESSION_LEVEL = "ZipCompressionLevel";
|
||||
inline constexpr std::string_view TITLE_SORT_TYPE = "TitleSortType";
|
||||
inline constexpr std::string_view JKSM_TEXT_MODE = "JKSMTextMode";
|
||||
inline constexpr std::string_view FORCE_ENGLISH = "ForceEnglish";
|
||||
inline constexpr std::string_view SHOW_DEVICE_USER = "ShowDevice";
|
||||
inline constexpr std::string_view SHOW_BCAT_USER = "ShowBCAT";
|
||||
inline constexpr std::string_view SHOW_CACHE_USER = "ShowCache";
|
||||
inline constexpr std::string_view SHOW_SYSTEM_USER = "ShowSystem";
|
||||
inline constexpr std::string_view ENABLE_TRASH_BIN = "EnableTrash";
|
||||
inline constexpr std::string_view UI_ANIMATION_SCALE = "UIAnimationScaling";
|
||||
inline constexpr std::string_view FAVORITES = "Favorites";
|
||||
inline constexpr std::string_view BLACKLIST = "BlackList";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,10 @@ namespace data
|
|||
/// @brief Initializes a TitleInfo instance using external (cached) NsApplicationControlData
|
||||
/// @param applicationID Application ID of the title loaded from cache.
|
||||
/// @param controlData Reference to the control data to init from.
|
||||
TitleInfo(uint64_t applicationID, std::unique_ptr<NsApplicationControlData> &controlData);
|
||||
TitleInfo(uint64_t applicationID, NsApplicationControlData &controlData);
|
||||
|
||||
/// @brief Move constructor and operator.
|
||||
TitleInfo(TitleInfo &&titleInfo);
|
||||
TitleInfo &operator=(TitleInfo &&TitleInfo);
|
||||
|
||||
// None of this nonesense around these parts.TitleInfo(const TitleInfo &) = delete;
|
||||
// None of this nonesense around these parts.
|
||||
TitleInfo(const TitleInfo &) = delete;
|
||||
TitleInfo &operator=(const TitleInfo &) = delete;
|
||||
|
||||
/// @brief Returns the application ID of the title.
|
||||
|
|
@ -104,8 +101,8 @@ namespace data
|
|||
/// @brief Stores application ID for easier grabbing since JKSV is all pointers.
|
||||
uint64_t m_applicationID{};
|
||||
|
||||
/// @brief This contains the NACP and the icon.
|
||||
std::unique_ptr<NsApplicationControlData> m_data{};
|
||||
/// @brief Where all the good stuff is.
|
||||
NsApplicationControlData m_data{};
|
||||
|
||||
/// @brief Saves whether or not the title has control data.
|
||||
bool m_hasData{};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
class MiniUnzip
|
||||
class MiniUnzip final
|
||||
{
|
||||
public:
|
||||
MiniUnzip() = default;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
class MiniZip
|
||||
class MiniZip final
|
||||
{
|
||||
public:
|
||||
MiniZip() = default;
|
||||
|
|
@ -41,6 +41,9 @@ namespace fs
|
|||
/// @brief Stores whether or not the zipFile was opened successfully.
|
||||
bool m_isOpen{};
|
||||
|
||||
/// @brief Stores the compression level from config to avoid repeated calls.
|
||||
int m_level{};
|
||||
|
||||
/// @brief Underlying ZIP file.
|
||||
zipFile m_zip{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ namespace fs
|
|||
|
||||
private:
|
||||
/// @brief Vector of paths to filter from deletion and backup.
|
||||
std::vector<std::string> m_paths{};
|
||||
std::vector<fslib::Path> m_paths{};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ namespace fs
|
|||
} __attribute__((packed));
|
||||
// clang-format on
|
||||
|
||||
// I didn't want a separate file for this.
|
||||
bool read_save_data_extra_info(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &dataOut);
|
||||
|
||||
/// @brief Didn't feel like a whole new file just for this. Fills an fs::SaveMetaData struct.
|
||||
bool fill_save_meta_data(const FsSaveDataInfo *saveInfo, SaveMetaData &meta);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ namespace fs
|
|||
/// @param journalSize Size of the journal area of the save data.
|
||||
void copy_file_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task = nullptr);
|
||||
|
||||
|
|
@ -36,7 +35,6 @@ namespace fs
|
|||
/// @param journalSize Size of the journaling area of the save.
|
||||
void copy_directory_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task = nullptr);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "data/data.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace fs
|
||||
|
|
@ -27,4 +28,10 @@ namespace fs
|
|||
/// @return True if it is. False if it isn't.
|
||||
/// @note The config setting overrides this.
|
||||
bool is_system_save_data(const FsSaveDataInfo *saveInfo);
|
||||
|
||||
/// @brief Reads the extra info of the save container according to the FsSaveDataInfo passed.
|
||||
/// @param saveInfo Pointer to the save info to read.
|
||||
/// @param extraOut Reference to the FsSaveDataExtraData to read to.
|
||||
/// @return True on success. False on failure.
|
||||
bool read_save_extra_data(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &extraOut);
|
||||
} // namespace fs
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ namespace fs
|
|||
void copy_zip_to_directory(fs::MiniUnzip &source,
|
||||
const fslib::Path &dest,
|
||||
int64_t journalSize,
|
||||
std::string_view commitDevice,
|
||||
sys::ProgressTask *Task = nullptr);
|
||||
|
||||
/// @brief Returns whether or not zip has files inside besides the save meta.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace colors
|
|||
inline constexpr sdl::Color PINK = {0xFF4444FF};
|
||||
inline constexpr sdl::Color BLUE_GREEN = {0x00FFC5FF};
|
||||
inline constexpr sdl::Color CLEAR_COLOR = {0x2D2D2DFF};
|
||||
inline constexpr sdl::Color CLEAR_PANEL = {0x0D0D0DFF};
|
||||
inline constexpr sdl::Color DIALOG_DARK = {0x505050FF};
|
||||
inline constexpr sdl::Color DIALOG_LIGHT = {0xDCDCDCFF};
|
||||
inline constexpr sdl::Color DIM_BACKGROUND = {0x00000088};
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
|
||||
namespace strings
|
||||
namespace strings::names
|
||||
{
|
||||
namespace names
|
||||
{
|
||||
inline constexpr std::string_view BACKUPMENU_MENU = "BackupMenu";
|
||||
inline constexpr std::string_view BACKUPMENU_CONFS = "BackupMenuConfirmations";
|
||||
inline constexpr std::string_view BACKUPMENU_POPS = "BackupMenuPops";
|
||||
inline constexpr std::string_view BACKUPMENU_STATUS = "BackupMenuStatus";
|
||||
inline constexpr std::string_view CONTROL_GUIDES = "ControlGuides";
|
||||
inline constexpr std::string_view DATA_LOADING_STATUS = "DataLoadingStatus";
|
||||
inline constexpr std::string_view EXTRASMENU_MENU = "ExtrasMenu";
|
||||
inline constexpr std::string_view EXTRASMENU_POPS = "ExtrasPops";
|
||||
inline constexpr std::string_view GENERAL_POPS = "GeneralPops";
|
||||
inline constexpr std::string_view GOOGLE_DRIVE = "GoogleDriveStrings";
|
||||
inline constexpr std::string_view HOLDING_STRINGS = "HoldingStrings";
|
||||
inline constexpr std::string_view IO_STATUSES = "IOStatuses";
|
||||
inline constexpr std::string_view IO_POPS = "IOPops";
|
||||
inline constexpr std::string_view KEYBOARD = "KeyboardStrings";
|
||||
inline constexpr std::string_view MAINMENU_CONFS = "MainMenuConfs";
|
||||
inline constexpr std::string_view MAINMENU_POPS = "MainMenuPops";
|
||||
inline constexpr std::string_view ON_OFF = "OnOff";
|
||||
inline constexpr std::string_view REMOTE_POPS = "RemotePops";
|
||||
inline constexpr std::string_view SAVECREATE_POPS = "SaveCreatePops";
|
||||
inline constexpr std::string_view SAVE_DATA_TYPES = "SaveDataTypes";
|
||||
inline constexpr std::string_view SETTINGS_DESCRIPTIONS = "SettingsDescriptions";
|
||||
inline constexpr std::string_view SETTINGS_MENU = "SettingsMenu";
|
||||
inline constexpr std::string_view SETTINGS_POPS = "SettingsPops";
|
||||
inline constexpr std::string_view SORT_TYPES = "SortTypes";
|
||||
inline constexpr std::string_view TITLEINFO = "TitleInfo";
|
||||
inline constexpr std::string_view TITLEOPTION_CONFS = "TitleOptionConfirmations";
|
||||
inline constexpr std::string_view TITLEOPTION_POPS = "TitleOptionPops";
|
||||
inline constexpr std::string_view TITLEOPTION_STATUS = "TitleOptionStatus";
|
||||
inline constexpr std::string_view TITLEOPTION = "TitleOptions";
|
||||
inline constexpr std::string_view TRANSLATION = "TranslationInfo";
|
||||
inline constexpr std::string_view USEROPTION_CONFS = "UserOptionConfirmations";
|
||||
inline constexpr std::string_view USEROPTION_STATUS = "UserOptionStatus";
|
||||
inline constexpr std::string_view USEROPTION_MENU = "UserOptions";
|
||||
inline constexpr std::string_view WEBDAV = "WebDavStrings";
|
||||
inline constexpr std::string_view YES_NO_OK = "YesNoOK";
|
||||
}
|
||||
inline constexpr std::string_view BACKUPMENU_MENU = "BackupMenu";
|
||||
inline constexpr std::string_view BACKUPMENU_CONFS = "BackupMenuConfirmations";
|
||||
inline constexpr std::string_view BACKUPMENU_POPS = "BackupMenuPops";
|
||||
inline constexpr std::string_view BACKUPMENU_STATUS = "BackupMenuStatus";
|
||||
inline constexpr std::string_view CONTROL_GUIDES = "ControlGuides";
|
||||
inline constexpr std::string_view DATA_LOADING_STATUS = "DataLoadingStatus";
|
||||
inline constexpr std::string_view EXTRASMENU_MENU = "ExtrasMenu";
|
||||
inline constexpr std::string_view EXTRASMENU_POPS = "ExtrasPops";
|
||||
inline constexpr std::string_view FILEOPTION_MENU = "FileOptionMenu";
|
||||
inline constexpr std::string_view FILEOPTION_CONFS = "FileOptionConfs";
|
||||
inline constexpr std::string_view FILEMODE_POPS = "FileModePops";
|
||||
inline constexpr std::string_view GENERAL_POPS = "GeneralPops";
|
||||
inline constexpr std::string_view GOOGLE_DRIVE = "GoogleDriveStrings";
|
||||
inline constexpr std::string_view HOLDING_STRINGS = "HoldingStrings";
|
||||
inline constexpr std::string_view IO_STATUSES = "IOStatuses";
|
||||
inline constexpr std::string_view IO_POPS = "IOPops";
|
||||
inline constexpr std::string_view KEYBOARD = "KeyboardStrings";
|
||||
inline constexpr std::string_view MAINMENU_CONFS = "MainMenuConfs";
|
||||
inline constexpr std::string_view MAINMENU_POPS = "MainMenuPops";
|
||||
inline constexpr std::string_view ON_OFF = "OnOff";
|
||||
inline constexpr std::string_view REMOTE_POPS = "RemotePops";
|
||||
inline constexpr std::string_view SAVECREATE_POPS = "SaveCreatePops";
|
||||
inline constexpr std::string_view SAVE_DATA_TYPES = "SaveDataTypes";
|
||||
inline constexpr std::string_view SETTINGS_DESCRIPTIONS = "SettingsDescriptions";
|
||||
inline constexpr std::string_view SETTINGS_MENU = "SettingsMenu";
|
||||
inline constexpr std::string_view SETTINGS_POPS = "SettingsPops";
|
||||
inline constexpr std::string_view SORT_TYPES = "SortTypes";
|
||||
inline constexpr std::string_view TITLEINFO = "TitleInfo";
|
||||
inline constexpr std::string_view TITLEOPTION_CONFS = "TitleOptionConfirmations";
|
||||
inline constexpr std::string_view TITLEOPTION_POPS = "TitleOptionPops";
|
||||
inline constexpr std::string_view TITLEOPTION_STATUS = "TitleOptionStatus";
|
||||
inline constexpr std::string_view TITLEOPTION = "TitleOptions";
|
||||
inline constexpr std::string_view TRANSLATION = "TranslationInfo";
|
||||
inline constexpr std::string_view USEROPTION_CONFS = "UserOptionConfirmations";
|
||||
inline constexpr std::string_view USEROPTION_STATUS = "UserOptionStatus";
|
||||
inline constexpr std::string_view USEROPTION_MENU = "UserOptions";
|
||||
inline constexpr std::string_view WEBDAV = "WebDavStrings";
|
||||
inline constexpr std::string_view YES_NO_OK = "YesNoOK";
|
||||
}
|
||||
|
|
|
|||
18
include/sys/DataTask.hpp
Normal file
18
include/sys/DataTask.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
#include "sys/Task.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
namespace sys
|
||||
{
|
||||
class DataTask final : public sys::Task
|
||||
{
|
||||
public:
|
||||
DataTask(ThreadFunc function, bool clearCache);
|
||||
|
||||
~DataTask();
|
||||
|
||||
private
|
||||
Thread m_thread{};
|
||||
}
|
||||
}
|
||||
|
|
@ -4,40 +4,37 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::backup
|
||||
{
|
||||
namespace backup
|
||||
{
|
||||
/// @brief Task/thread function executed when a new backup is created.
|
||||
void create_new_backup_local(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
fslib::Path target,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
void create_new_backup_remote(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
std::string remoteName,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
/// @brief Task/thread function executed when a new backup is created.
|
||||
void create_new_backup_local(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
fslib::Path target,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
void create_new_backup_remote(sys::ProgressTask *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
std::string remoteName,
|
||||
BackupMenuState *spawningState,
|
||||
bool killTask = true);
|
||||
|
||||
/// @brief Overwrites a pre-existing backup.
|
||||
void overwrite_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void overwrite_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Overwrites a pre-existing backup.
|
||||
void overwrite_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void overwrite_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Restores a backup
|
||||
void restore_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void restore_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Restores a backup
|
||||
void restore_backup_local(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
void restore_backup_remote(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes a backup
|
||||
void delete_backup_local(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
void delete_backup_remote(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Deletes a backup
|
||||
void delete_backup_local(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
void delete_backup_remote(sys::Task *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Uploads a backup
|
||||
void upload_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
/// @brief Uploads a backup
|
||||
void upload_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
|
||||
/// @brief Patches a pre-existing backup on the remote storage.
|
||||
void patch_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
}
|
||||
/// @brief Patches a pre-existing backup on the remote storage.
|
||||
void patch_backup(sys::ProgressTask *task, BackupMenuState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
12
include/tasks/fileoptions.hpp
Normal file
12
include/tasks/fileoptions.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
#include "appstates/FileOptionState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks::fileoptions
|
||||
{
|
||||
/// @brief Copies the source to destination passed through taskData.
|
||||
void copy_source_to_destination(sys::ProgressTask *task, FileOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes the source path passed through taskData
|
||||
void delete_target(sys::Task *task, FileOptionState::TaskData taskData);
|
||||
}
|
||||
|
|
@ -2,11 +2,8 @@
|
|||
#include "appstates/MainMenuState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::mainmenu
|
||||
{
|
||||
namespace mainmenu
|
||||
{
|
||||
void backup_all_for_all_local(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
void backup_all_for_all_remote(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
}
|
||||
void backup_all_for_all_local(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
void backup_all_for_all_remote(sys::ProgressTask *task, MainMenuState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,7 @@
|
|||
#include "data/data.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::savecreate
|
||||
{
|
||||
namespace savecreate
|
||||
{
|
||||
void create_save_data_for(sys::Task *task,
|
||||
data::User *user,
|
||||
data::TitleInfo *titleInfo,
|
||||
SaveCreateState *spawningState);
|
||||
}
|
||||
void create_save_data_for(sys::Task *task, data::User *user, data::TitleInfo *titleInfo, SaveCreateState *spawningState);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,26 +3,23 @@
|
|||
#include "appstates/TitleOptionState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::titleoptions
|
||||
{
|
||||
namespace titleoptions
|
||||
{
|
||||
/// @brief Adds a title to the blacklist. Needs to be task formatted to work with confirmations.
|
||||
void blacklist_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Adds a title to the blacklist. Needs to be task formatted to work with confirmations.
|
||||
void blacklist_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Wipes deletes all local backups for the current title.
|
||||
void delete_all_local_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Wipes deletes all local backups for the current title.
|
||||
void delete_all_local_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes all backups found on the remote storage service.
|
||||
void delete_all_remote_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Deletes all backups found on the remote storage service.
|
||||
void delete_all_remote_backups_for_title(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Resets save data for the current title.
|
||||
void reset_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Resets save data for the current title.
|
||||
void reset_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Deletes the save data from the system the same way Data Management does.
|
||||
void delete_save_data_from_system(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
/// @brief Deletes the save data from the system the same way Data Management does.
|
||||
void delete_save_data_from_system(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
|
||||
/// @brief Extends the save container for the current save info.
|
||||
void extend_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
}
|
||||
/// @brief Extends the save container for the current save info.
|
||||
void extend_save_data(sys::Task *task, TitleOptionState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,10 @@
|
|||
#include "appstates/UserOptionState.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
||||
namespace tasks
|
||||
namespace tasks::useroptions
|
||||
{
|
||||
namespace useroptions
|
||||
{
|
||||
void backup_all_for_user_local(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void backup_all_for_user_remote(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void create_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
void delete_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
}
|
||||
void backup_all_for_user_local(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void backup_all_for_user_remote(sys::ProgressTask *task, UserOptionState::TaskData taskData);
|
||||
void create_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
void delete_all_save_data_for_user(sys::Task *task, UserOptionState::TaskData taskData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,14 +43,17 @@ namespace ui
|
|||
/// @param hasFocus This is ignored.
|
||||
void render(sdl::SharedTexture &target, bool hasFocus) override;
|
||||
|
||||
/// @brief Sets the X and coords for the dialog box.
|
||||
void set_xy(int x, int y);
|
||||
/// @brief Sets the X render coord.
|
||||
void set_x(int x);
|
||||
|
||||
/// @brief Sets the width and height of the dialog.
|
||||
void set_width_height(int width, int height);
|
||||
/// @brief Sets the X render coord.
|
||||
void set_y(int y);
|
||||
|
||||
/// @brief Pass with the set functions to not change.
|
||||
static inline constexpr int NO_SET = -1;
|
||||
/// @brief Sets the width.
|
||||
void set_width(int width);
|
||||
|
||||
/// @brief Sets the height.
|
||||
void set_height(int height);
|
||||
|
||||
private:
|
||||
/// @brief X render coord.
|
||||
|
|
|
|||
61
include/ui/Frame.hpp
Normal file
61
include/ui/Frame.hpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
#include "sdl.hpp"
|
||||
#include "ui/Element.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class Frame final : public ui::Element
|
||||
{
|
||||
public:
|
||||
/// @brief Constructs a new frame.
|
||||
Frame(int x, int y, int width, int height);
|
||||
|
||||
/// @brief Doesn't need to do anything because modern C++.
|
||||
~Frame() {};
|
||||
|
||||
/// @brief Inline function to make constructing nicer.
|
||||
static inline std::shared_ptr<ui::Frame> create(int x, int y, int width, int height)
|
||||
{
|
||||
return std::make_shared<ui::Frame>(x, y, width, height);
|
||||
}
|
||||
|
||||
/// @brief Doesn't need to do anything for this.
|
||||
void update(bool hasFocus) override {};
|
||||
|
||||
/// @brief Renders the frame to the target passed.
|
||||
void render(sdl::SharedTexture &target, bool hasFocus) override;
|
||||
|
||||
/// @brief Sets the X coord.
|
||||
void set_x(int x);
|
||||
|
||||
/// @brief Sets the Y coord.
|
||||
void set_y(int y);
|
||||
|
||||
/// @brief Sets the width of the frame.
|
||||
void set_width(int width);
|
||||
|
||||
/// @brief Sets the height of the frame.
|
||||
void set_height(int height);
|
||||
|
||||
private:
|
||||
/// @brief X rendering coord.
|
||||
int m_x{};
|
||||
|
||||
/// @brief Y rendering coord.
|
||||
int m_y{};
|
||||
|
||||
/// @brief Rendering width.
|
||||
int m_width{};
|
||||
|
||||
/// @brief Rendering height.
|
||||
int m_height{};
|
||||
|
||||
/// @brief This texture is shared by all instances.
|
||||
static inline sdl::SharedTexture sm_frameCorners{};
|
||||
|
||||
/// @brief Ensures the texture is loading if it hasn't been.
|
||||
void initialize_static_members();
|
||||
};
|
||||
}
|
||||
|
|
@ -61,6 +61,15 @@ namespace ui
|
|||
/// @param width New width of the menu in pixels.
|
||||
void set_width(int width);
|
||||
|
||||
/// @brief Updates the X render coordinate.
|
||||
void set_x(int x);
|
||||
|
||||
/// @brief Updates the Y render coordinate.
|
||||
void set_y(int y);
|
||||
|
||||
/// @brief Returns if the menu has no options.
|
||||
bool is_empty() const;
|
||||
|
||||
/// @brief Resets the menu and returns it to an empty, default state.
|
||||
void reset();
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ namespace ui
|
|||
/// @param hasFocus Whether or not the calling state has focus.
|
||||
void update(bool hasFocus) override;
|
||||
|
||||
/// @brief Sub update routine. Allows the panel to hide and unhide itself even when not in focus.
|
||||
void sub_update();
|
||||
|
||||
/// @brief Runs the render routine.
|
||||
/// @param target Target to render to.
|
||||
/// @param hasFocus Whether or the the calling state has focus.
|
||||
|
|
@ -49,6 +52,12 @@ namespace ui
|
|||
/// @brief Closes the panel.
|
||||
void close();
|
||||
|
||||
/// @brief Hides the panel temporarily.
|
||||
void hide();
|
||||
|
||||
/// @brief Unhides the panel.
|
||||
void unhide();
|
||||
|
||||
/// @brief Returns if the panel is fully open.
|
||||
/// @return If the panel is fully open.
|
||||
bool is_open() const;
|
||||
|
|
@ -57,6 +66,9 @@ namespace ui
|
|||
/// @return If the panel is fully closed.
|
||||
bool is_closed();
|
||||
|
||||
/// @brief Returns whether or not the panel is hidden.
|
||||
bool is_hidden() const;
|
||||
|
||||
/// @brief Pushes a new element to the element vector.
|
||||
/// @param newElement New element to push.
|
||||
void push_new_element(std::shared_ptr<ui::Element> newElement);
|
||||
|
|
@ -75,6 +87,9 @@ namespace ui
|
|||
/// @brief Whether or not to close panel.
|
||||
bool m_closePanel{};
|
||||
|
||||
/// @brief Whether or not to hide the panel.
|
||||
bool m_hidePanel{};
|
||||
|
||||
/// @brief Current X coordinate to render to. Panels are always 720 pixels in height so no Y is required.
|
||||
double m_x{};
|
||||
|
||||
|
|
@ -93,10 +108,16 @@ namespace ui
|
|||
/// @brief Vector of elements.
|
||||
std::vector<std::shared_ptr<ui::Element>> m_elements{};
|
||||
|
||||
/// @brief Handles sliding out logic.
|
||||
void slide_out();
|
||||
|
||||
/// @brief Slides the panel out from the left side.
|
||||
void slide_out_left();
|
||||
|
||||
/// @brief Slides the panel out from the right side.
|
||||
void slide_out_right();
|
||||
|
||||
int get_absolute_x_distance();
|
||||
/// @brief Contains the logic for hiding/closing the panel.
|
||||
void close_hide_panel();
|
||||
};
|
||||
} // namespace ui
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "ui/ColorMod.hpp"
|
||||
#include "ui/DialogBox.hpp"
|
||||
#include "ui/Element.hpp"
|
||||
#include "ui/Frame.hpp"
|
||||
#include "ui/IconMenu.hpp"
|
||||
#include "ui/Menu.hpp"
|
||||
#include "ui/PopMessageManager.hpp"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@
|
|||
"0: [A] Select [Y] Dump All Saves [X] User Options",
|
||||
"1: [A] Select [L] [R] Jump [Y] Favorite [X] Title Options [B] Back",
|
||||
"2: [A] Select [Y] Restore [X] Delete [ZR] Upload [B] Close",
|
||||
"3: [A] Toggle [-] Description [X] Defaults [B] Back"
|
||||
"3: [A] Toggle [-] Description [X] Defaults [B] Back",
|
||||
"4: [A] Enter [B] Back/Up [X] Options [ZL]/[ZR] Change Target [-] Close"
|
||||
],
|
||||
"DataLoadingStatus": [
|
||||
"0: Loading user accounts from system...",
|
||||
|
|
@ -58,6 +59,28 @@
|
|||
"0: Data reinitialized!",
|
||||
"1: Data reinitialization failed!"
|
||||
],
|
||||
"FileOptionMenu": [
|
||||
"0: Copy",
|
||||
"1: Delete",
|
||||
"2: Rename",
|
||||
"3: Create Folder",
|
||||
"4: Properties",
|
||||
"5: Close"
|
||||
],
|
||||
"FileOptionConfs": [
|
||||
"0: Are you sure you want to copy #%s# to #%s#?",
|
||||
"1: Are you sure you want to delete #%s#?",
|
||||
],
|
||||
"FileModePops": [
|
||||
"0: Copied #%s#!",
|
||||
"1: Failed to copy #%s#!",
|
||||
"2: Deleted #%s#!",
|
||||
"3: Failed to delete #%s#!",
|
||||
"4: Renamed #%s# to #%s#!",
|
||||
"5: Failed to rename #%s#!",
|
||||
"6: Created #%s#!",
|
||||
"7: Failed to create #%s#!"
|
||||
],
|
||||
"GeneralPops": [
|
||||
"0: Unable to exit JKSV while tasks are running!"
|
||||
],
|
||||
|
|
@ -92,7 +115,8 @@
|
|||
"5: Enter a new name for the target item.",
|
||||
"6: Enter a name for the new folder.",
|
||||
"7: Enter a new output folder name for %s.",
|
||||
"8: Enter how much to expand (in MB)."
|
||||
"8: Enter how much to expand (in MB).",
|
||||
"9: Enter a new name for %s."
|
||||
],
|
||||
"MainMenuConfs": [
|
||||
"0: Are you sure you want to backup the save data for every user on this system? This can take an *extremely* long time!"
|
||||
|
|
@ -258,4 +282,4 @@
|
|||
"1: No [B]",
|
||||
"2: OK [A]"
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
romfs/Textures/Frame.png
Normal file
BIN
romfs/Textures/Frame.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 312 B |
|
|
@ -1,15 +1,16 @@
|
|||
#include "JKSV.hpp"
|
||||
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "appstates/MainMenuState.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "curl/curl.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "sdl.hpp"
|
||||
|
|
@ -30,9 +31,21 @@ namespace
|
|||
/// @brief Build month.
|
||||
constexpr uint8_t BUILD_MON = 8;
|
||||
/// @brief Build day.
|
||||
constexpr uint8_t BUILD_DAY = 25;
|
||||
constexpr uint8_t BUILD_DAY = 29;
|
||||
/// @brief Year.
|
||||
constexpr uint16_t BUILD_YEAR = 2025;
|
||||
|
||||
/// @brief Config for socket.
|
||||
constexpr SocketInitConfig SOCKET_INIT_CONFIG = {.tcp_tx_buf_size = 0x20000,
|
||||
.tcp_rx_buf_size = 0x20000,
|
||||
.tcp_tx_buf_max_size = 0x80000,
|
||||
.tcp_rx_buf_max_size = 0x80000,
|
||||
.udp_tx_buf_size = 0x2400,
|
||||
.udp_rx_buf_size = 0xA500,
|
||||
.sb_efficiency = 8,
|
||||
.num_bsd_sessions = 3,
|
||||
.bsd_service_type = BsdServiceType_User};
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename... Args>
|
||||
|
|
@ -47,12 +60,30 @@ static bool initialize_service(Result (*function)(Args...), const char *serviceN
|
|||
return true;
|
||||
}
|
||||
|
||||
class BootTimer final
|
||||
{
|
||||
public:
|
||||
BootTimer()
|
||||
: m_start(std::chrono::high_resolution_clock::now()) {};
|
||||
|
||||
~BootTimer()
|
||||
{
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto microSeconds = std::chrono::duration_cast<std::chrono::microseconds>(end - m_start);
|
||||
logger::log("Boot time: %llu microseconds", microSeconds);
|
||||
}
|
||||
|
||||
private:
|
||||
std::chrono::system_clock::time_point m_start{};
|
||||
};
|
||||
|
||||
// Definition at bottom.
|
||||
static void finish_initialization();
|
||||
|
||||
// This can't really have an initializer list since it sets everything up.
|
||||
JKSV::JKSV()
|
||||
{
|
||||
BootTimer timer{};
|
||||
appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad);
|
||||
ABORT_ON_FAILURE(JKSV::initialize_services());
|
||||
ABORT_ON_FAILURE(JKSV::initialize_filesystem());
|
||||
|
|
@ -86,7 +117,7 @@ JKSV::~JKSV()
|
|||
JKSV::exit_services();
|
||||
sdl::text::exit();
|
||||
sdl::exit();
|
||||
fslib::exit();
|
||||
|
||||
appletSetCpuBoostMode(ApmCpuBoostMode_Normal);
|
||||
}
|
||||
|
||||
|
|
@ -133,10 +164,11 @@ void JKSV::render()
|
|||
bool JKSV::initialize_filesystem()
|
||||
{
|
||||
// This needs to be in this specific order
|
||||
const bool fslib = fslib::initialize();
|
||||
const bool fslib = fslib::is_initialized();
|
||||
const bool romfs = initialize_service(romfsInit, "RomFS");
|
||||
const bool fslibDev = fslib && fslib::dev::initialize_sdmc();
|
||||
if (!fslib || !romfs || !fslibDev) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +182,7 @@ bool JKSV::initialize_services()
|
|||
serviceInit = serviceInit && initialize_service(pmshellInitialize, "PMShell");
|
||||
serviceInit = serviceInit && initialize_service(setInitialize, "Set");
|
||||
serviceInit = serviceInit && initialize_service(setsysInitialize, "SetSys");
|
||||
serviceInit = serviceInit && initialize_service(socketInitializeDefault, "Socket");
|
||||
serviceInit = serviceInit && initialize_service(socketInitialize, "Socket", &SOCKET_INIT_CONFIG);
|
||||
serviceInit = serviceInit && initialize_service(nifmInitialize, "NIFM", NifmServiceType_User);
|
||||
return serviceInit;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ void StateManager::update()
|
|||
|
||||
if (stateVector.empty()) { return; }
|
||||
|
||||
// Run sub update routines.
|
||||
for (auto &state : stateVector) { state->sub_update(); }
|
||||
|
||||
std::shared_ptr<BaseState> &back = stateVector.back();
|
||||
if (!back->has_focus()) { back->give_focus(); }
|
||||
back->update();
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
#include "appstates/FadeState.hpp"
|
||||
#include "appstates/ProgressState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -127,7 +127,7 @@ void BackupMenuState::refresh()
|
|||
}
|
||||
|
||||
int index{};
|
||||
for (const fslib::DirectoryEntry &entry : m_directoryListing.list())
|
||||
for (const fslib::DirectoryEntry &entry : m_directoryListing)
|
||||
{
|
||||
sm_backupMenu->add_option(entry.get_filename());
|
||||
m_menuEntries.push_back({MenuEntryType::Local, index++});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "appstates/BaseState.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
#include "appstates/MainMenuState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
|
||||
BlacklistEditState::BlacklistEditState()
|
||||
: BaseState()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include "appstates/ExtrasMenuState.hpp"
|
||||
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "appstates/MainMenuState.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
|
|
@ -50,7 +52,13 @@ void ExtrasMenuState::update()
|
|||
{
|
||||
switch (m_extrasMenu.get_selected())
|
||||
{
|
||||
case REINIT_DATA: ExtrasMenuState::reinitialize_data(); break;
|
||||
case REINIT_DATA: ExtrasMenuState::reinitialize_data(); break;
|
||||
case SD_TO_SD_BROWSER: ExtrasMenuState::sd_to_sd_browser(); break;
|
||||
case BIS_PRODINFO_F: ExtrasMenuState::prodinfof_to_sd(); break;
|
||||
case BIS_SAFE: ExtrasMenuState::safe_to_sd(); break;
|
||||
case BIS_SYSTEM: ExtrasMenuState::system_to_sd(); break;
|
||||
case BIS_USER: ExtrasMenuState::user_to_sd(); break;
|
||||
case TERMINATE_PROCESS: ExtrasMenuState::terminate_process(); break;
|
||||
}
|
||||
}
|
||||
else if (bPressed) { BaseState::deactivate(); }
|
||||
|
|
@ -75,6 +83,42 @@ void ExtrasMenuState::initialize_menu()
|
|||
|
||||
void ExtrasMenuState::reinitialize_data() { data::launch_initialization(true, finish_reinitialization); }
|
||||
|
||||
void ExtrasMenuState::sd_to_sd_browser() { FileModeState::create_and_push("sdmc", "sdmc", false); }
|
||||
|
||||
void ExtrasMenuState::prodinfof_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("prodinfo-f", FsBisPartitionId_CalibrationFile));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("prodinfo-f", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::safe_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("safe", FsBisPartitionId_SafeMode));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("safe", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::system_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("system", FsBisPartitionId_System));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("system", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::user_to_sd()
|
||||
{
|
||||
const bool mountError = error::fslib(fslib::open_bis_filesystem("user", FsBisPartitionId_User));
|
||||
if (mountError) { return; }
|
||||
|
||||
FileModeState::create_and_push("user", "sdmc", false);
|
||||
}
|
||||
|
||||
void ExtrasMenuState::terminate_process() {}
|
||||
|
||||
static void finish_reinitialization()
|
||||
{
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
|
|
|
|||
261
source/appstates/FileModeState.cpp
Normal file
261
source/appstates/FileModeState.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
#include "appstates/FileModeState.hpp"
|
||||
|
||||
#include "appstates/FileOptionState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
FileModeState::FileModeState(std::string_view mountA, std::string_view mountB, int64_t journalSize)
|
||||
: m_mountA(mountA)
|
||||
, m_mountB(mountB)
|
||||
, m_journalSize(journalSize)
|
||||
, m_y(720.f)
|
||||
, m_targetY(91.0f)
|
||||
, m_scaling(config::get_animation_scaling())
|
||||
{
|
||||
FileModeState::initialize_static_members();
|
||||
FileModeState::initialize_paths();
|
||||
FileModeState::initialize_menus();
|
||||
}
|
||||
|
||||
void FileModeState::update()
|
||||
{
|
||||
FileModeState::update_y_coord();
|
||||
if (!m_inPlace) { return; }
|
||||
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
ui::Menu &menu = FileModeState::get_source_menu();
|
||||
fslib::Path &path = FileModeState::get_source_path();
|
||||
fslib::Directory &directory = FileModeState::get_source_directory();
|
||||
|
||||
const bool aPressed = input::button_pressed(HidNpadButton_A);
|
||||
const bool bPressed = input::button_pressed(HidNpadButton_B);
|
||||
const bool xPressed = input::button_pressed(HidNpadButton_X);
|
||||
const bool zlZRPressed = input::button_pressed(HidNpadButton_ZL) || input::button_pressed(HidNpadButton_ZR);
|
||||
const bool minusPressed = input::button_pressed(HidNpadButton_Minus);
|
||||
|
||||
if (aPressed) { FileModeState::enter_selected(path, directory, menu); }
|
||||
else if (bPressed) { FileModeState::up_one_directory(path, directory, menu); }
|
||||
else if (xPressed) { FileModeState::open_option_menu(directory, menu); }
|
||||
else if (zlZRPressed) { FileModeState::change_target(); }
|
||||
else if (minusPressed) { FileModeState::hide_dialog(); }
|
||||
else if (FileModeState::is_hidden()) { FileModeState::deactivate_state(); }
|
||||
|
||||
menu.update(hasFocus);
|
||||
}
|
||||
|
||||
void FileModeState::render()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
sm_renderTarget->clear(colors::TRANSPARENT);
|
||||
|
||||
// This is here so it's rendered underneath the pop-up frame.
|
||||
if (hasFocus) { FileModeState::render_control_guide(); }
|
||||
|
||||
sdl::render_line(sm_renderTarget, 617, 0, 617, 538, colors::WHITE);
|
||||
sdl::render_line(sm_renderTarget, 618, 0, 618, 538, colors::DIALOG_DARK);
|
||||
|
||||
m_dirMenuA->render(sm_renderTarget, hasFocus && m_target == false);
|
||||
m_dirMenuB->render(sm_renderTarget, hasFocus && m_target);
|
||||
|
||||
sm_frame->render(sdl::Texture::Null, true);
|
||||
sm_renderTarget->render(sdl::Texture::Null, 23, m_y + 12);
|
||||
}
|
||||
|
||||
bool FileModeState::get_target() const noexcept { return m_target; }
|
||||
|
||||
fslib::Path FileModeState::get_source()
|
||||
{
|
||||
const fslib::Path &sourcePath = FileModeState::get_source_path();
|
||||
const fslib::Directory &sourceDir = FileModeState::get_source_directory();
|
||||
const ui::Menu &sourceMenu = FileModeState::get_source_menu();
|
||||
|
||||
const int selected = sourceMenu.get_selected();
|
||||
|
||||
// If 0, the current path is our target.
|
||||
if (selected == 0) { return sourcePath; }
|
||||
|
||||
const int dirIndex = selected - 2;
|
||||
const fslib::DirectoryEntry &entry = sourceDir[dirIndex];
|
||||
|
||||
return sourcePath / entry;
|
||||
}
|
||||
|
||||
fslib::Path FileModeState::get_destination()
|
||||
{
|
||||
const fslib::Path &destPath = FileModeState::get_destination_path();
|
||||
const fslib::Directory &destDir = FileModeState::get_destination_directory();
|
||||
const ui::Menu &destMenu = FileModeState::get_destination_menu();
|
||||
|
||||
const int selected = destMenu.get_selected();
|
||||
|
||||
if (selected == 0) { return destPath; }
|
||||
|
||||
const int dirIndex = selected - 1;
|
||||
const fslib::DirectoryEntry &entry = destDir[dirIndex];
|
||||
|
||||
return destPath / entry;
|
||||
}
|
||||
|
||||
bool FileModeState::commit_required() const noexcept { return m_target == false && m_journalSize > 0; }
|
||||
|
||||
int64_t FileModeState::get_journal_size() const noexcept { return m_journalSize; }
|
||||
|
||||
void FileModeState::render_control_guide() noexcept
|
||||
{
|
||||
sdl::text::render(sdl::Texture::Null, sm_controlGuideX, 673, 22, sdl::text::NO_WRAP, colors::WHITE, sm_controlGuide);
|
||||
}
|
||||
|
||||
void FileModeState::initialize_static_members()
|
||||
{
|
||||
static constexpr std::string_view RENDER_TARGET_NAME = "FMRenderTarget";
|
||||
|
||||
static constexpr int CONTROL_GUIDE_START_X = 1220;
|
||||
|
||||
if (sm_frame && sm_renderTarget) { return; }
|
||||
|
||||
sm_frame = ui::Frame::create(15, 720, 1250, 555);
|
||||
sm_renderTarget = sdl::TextureManager::load(RENDER_TARGET_NAME, 1234, 538, SDL_TEXTUREACCESS_TARGET);
|
||||
sm_controlGuide = strings::get_by_name(strings::names::CONTROL_GUIDES, 4);
|
||||
sm_controlGuideX = CONTROL_GUIDE_START_X - sdl::text::get_width(22, sm_controlGuide);
|
||||
}
|
||||
|
||||
void FileModeState::initialize_paths()
|
||||
{
|
||||
const std::string pathA = m_mountA + ":/";
|
||||
const std::string pathB = m_mountB + ":/";
|
||||
|
||||
m_pathA = pathA;
|
||||
m_pathB = pathB;
|
||||
}
|
||||
|
||||
void FileModeState::initialize_menus()
|
||||
{
|
||||
m_dirMenuA = ui::Menu::create(8, 8, 594, 22, 538);
|
||||
m_dirMenuB = ui::Menu::create(626, 8, 594, 22, 538);
|
||||
|
||||
FileModeState::initialize_directory_menu(m_pathA, m_dirA, *m_dirMenuA.get());
|
||||
FileModeState::initialize_directory_menu(m_pathB, m_dirB, *m_dirMenuB.get());
|
||||
}
|
||||
|
||||
void FileModeState::initialize_directory_menu(const fslib::Path &path, fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
static constexpr const char *DIR_PREFIX = "[D] ";
|
||||
static constexpr const char *FILE_PREFIX = "[F] ";
|
||||
|
||||
directory.open(path);
|
||||
if (!directory.is_open()) { return; }
|
||||
|
||||
menu.reset();
|
||||
menu.add_option(".");
|
||||
menu.add_option("..");
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : directory)
|
||||
{
|
||||
std::string option{};
|
||||
if (entry.is_directory()) { option = DIR_PREFIX; }
|
||||
else { option = FILE_PREFIX; }
|
||||
|
||||
option += entry.get_filename();
|
||||
menu.add_option(option);
|
||||
}
|
||||
}
|
||||
|
||||
void FileModeState::update_y_coord() noexcept
|
||||
{
|
||||
if (m_y == m_targetY) { return; }
|
||||
|
||||
const double add = (m_targetY - m_y) / m_scaling;
|
||||
const double distance = math::Util<double>::absolute_distance(m_targetY, m_y);
|
||||
m_y += std::round(add);
|
||||
|
||||
if (distance <= 4)
|
||||
{
|
||||
m_y = m_targetY;
|
||||
m_inPlace = true;
|
||||
}
|
||||
|
||||
sm_frame->set_y(m_y);
|
||||
}
|
||||
|
||||
void FileModeState::hide_dialog() noexcept
|
||||
{
|
||||
if (!m_inPlace) { return; }
|
||||
m_targetY = 720;
|
||||
}
|
||||
|
||||
bool FileModeState::is_hidden() noexcept { return m_inPlace && m_targetY == 720; }
|
||||
|
||||
void FileModeState::enter_selected(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
const int selected = menu.get_selected();
|
||||
|
||||
if (selected == 1) { FileModeState::up_one_directory(path, directory, menu); }
|
||||
else
|
||||
{
|
||||
const int dirIndex = selected - 2;
|
||||
const fslib::DirectoryEntry &entry = directory[dirIndex];
|
||||
if (entry.is_directory()) { FileModeState::enter_directory(path, directory, menu, entry); }
|
||||
}
|
||||
}
|
||||
|
||||
void FileModeState::open_option_menu(fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
const int selected = menu.get_selected();
|
||||
|
||||
if (selected == 0 || selected > 1) { FileOptionState::create_and_push(this); }
|
||||
}
|
||||
|
||||
void FileModeState::change_target() { m_target = m_target ? false : true; }
|
||||
|
||||
void FileModeState::up_one_directory(fslib::Path &path, fslib::Directory &directory, ui::Menu &menu)
|
||||
{
|
||||
if (FileModeState::path_is_root(path)) { return; }
|
||||
|
||||
size_t lastSlash = path.find_last_of('/');
|
||||
if (lastSlash == path.NOT_FOUND) { return; }
|
||||
else if (lastSlash <= 0) { lastSlash = 1; }
|
||||
|
||||
fslib::Path newPath{path.sub_path(lastSlash)};
|
||||
path = std::move(newPath);
|
||||
FileModeState::initialize_directory_menu(path, directory, menu);
|
||||
}
|
||||
|
||||
void FileModeState::enter_directory(fslib::Path &path,
|
||||
fslib::Directory &directory,
|
||||
ui::Menu &menu,
|
||||
const fslib::DirectoryEntry &entry)
|
||||
{
|
||||
if (!entry.is_directory()) { return; }
|
||||
|
||||
path /= entry.get_filename();
|
||||
FileModeState::initialize_directory_menu(path, directory, menu);
|
||||
}
|
||||
|
||||
ui::Menu &FileModeState::get_source_menu() noexcept { return m_target ? *m_dirMenuB.get() : *m_dirMenuA.get(); }
|
||||
|
||||
ui::Menu &FileModeState::get_destination_menu() noexcept { return m_target ? *m_dirMenuA.get() : *m_dirMenuB.get(); }
|
||||
|
||||
fslib::Path &FileModeState::get_source_path() noexcept { return m_target ? m_pathB : m_pathA; }
|
||||
|
||||
fslib::Path &FileModeState::get_destination_path() noexcept { return m_target ? m_pathA : m_pathB; }
|
||||
|
||||
fslib::Directory &FileModeState::get_source_directory() noexcept { return m_target ? m_dirB : m_dirA; }
|
||||
|
||||
fslib::Directory &FileModeState::get_destination_directory() noexcept { return m_target ? m_dirA : m_dirB; }
|
||||
|
||||
void FileModeState::deactivate_state() noexcept
|
||||
{
|
||||
sm_frame->set_y(720);
|
||||
fslib::close_file_system(m_mountA);
|
||||
fslib::close_file_system(m_mountB);
|
||||
BaseState::deactivate();
|
||||
}
|
||||
199
source/appstates/FileOptionState.cpp
Normal file
199
source/appstates/FileOptionState.cpp
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
#include "appstates/FileOptionState.hpp"
|
||||
|
||||
#include "appstates/ConfirmState.hpp"
|
||||
#include "appstates/ProgressState.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "mathutil.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "tasks/fileoptions.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
enum
|
||||
{
|
||||
COPY,
|
||||
DELETE,
|
||||
RENAME,
|
||||
CREATE_DIR,
|
||||
PROPERTIES,
|
||||
CLOSE
|
||||
};
|
||||
|
||||
// These make things easier to read and type.
|
||||
using TaskConfirm = ConfirmState<sys::Task, TaskState, FileOptionState::DataStruct>;
|
||||
using ProgressConfirm = ConfirmState<sys::ProgressTask, ProgressState, FileOptionState::DataStruct>;
|
||||
}
|
||||
|
||||
FileOptionState::FileOptionState(FileModeState *spawningState)
|
||||
: m_spawningState(spawningState)
|
||||
, m_commitData(m_spawningState->commit_required())
|
||||
, m_scaling(config::get_animation_scaling())
|
||||
, m_dataStruct(std::make_shared<FileOptionState::DataStruct>())
|
||||
{
|
||||
FileOptionState::initialize_static_members();
|
||||
FileOptionState::set_menu_side();
|
||||
}
|
||||
|
||||
void FileOptionState::update()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
FileOptionState::update_x_coord();
|
||||
if (!m_inPlace) { return; }
|
||||
|
||||
sm_copyMenu->update(hasFocus);
|
||||
const int selected = sm_copyMenu->get_selected();
|
||||
const bool aPressed = input::button_pressed(HidNpadButton_A);
|
||||
const bool bPressed = input::button_pressed(HidNpadButton_B);
|
||||
|
||||
if (aPressed)
|
||||
{
|
||||
switch (selected)
|
||||
{
|
||||
case COPY: FileOptionState::copy_target(); break;
|
||||
case DELETE: FileOptionState::delete_target(); break;
|
||||
case RENAME: FileOptionState::rename_target(); break;
|
||||
}
|
||||
}
|
||||
else if (bPressed) { FileOptionState::close(); }
|
||||
else if (FileOptionState::is_closed()) { FileOptionState::deactivate_state(); }
|
||||
}
|
||||
|
||||
void FileOptionState::render()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
sm_dialog->render(sdl::Texture::Null, hasFocus);
|
||||
sm_copyMenu->render(sdl::Texture::Null, hasFocus);
|
||||
|
||||
// I just didn't like this disappearing.
|
||||
m_spawningState->render_control_guide();
|
||||
}
|
||||
|
||||
void FileOptionState::initialize_static_members()
|
||||
{
|
||||
if (sm_copyMenu && sm_dialog) { return; }
|
||||
|
||||
sm_copyMenu = ui::Menu::create(0, 236, 234, 20, 720); // High target height is a workaround.
|
||||
sm_dialog = ui::DialogBox::create(520, 218, 256, 256);
|
||||
|
||||
// This never changes, so...
|
||||
for (int i = 0; const char *menuOption = strings::get_by_name(strings::names::FILEOPTION_MENU, i); i++)
|
||||
{
|
||||
sm_copyMenu->add_option(menuOption);
|
||||
}
|
||||
}
|
||||
|
||||
void FileOptionState::set_menu_side()
|
||||
{
|
||||
const bool target = m_spawningState->get_target();
|
||||
m_x = target ? 1280 : -240;
|
||||
|
||||
m_targetX = target ? 840 : 200;
|
||||
sm_dialog->set_x(m_x);
|
||||
sm_copyMenu->set_x(m_x + 9);
|
||||
}
|
||||
|
||||
void FileOptionState::update_x_coord()
|
||||
{
|
||||
if (m_x == m_targetX) { return; }
|
||||
|
||||
const int add = (m_targetX - m_x) / m_scaling;
|
||||
m_x += add;
|
||||
|
||||
const int distance = math::Util<int>::absolute_distance(m_x, m_targetX);
|
||||
if (distance <= 4)
|
||||
{
|
||||
m_x = m_targetX;
|
||||
m_inPlace = true;
|
||||
}
|
||||
sm_dialog->set_x(m_x);
|
||||
sm_copyMenu->set_x(m_x + 9);
|
||||
}
|
||||
|
||||
void FileOptionState::copy_target()
|
||||
{
|
||||
fslib::Path source = m_spawningState->get_source();
|
||||
fslib::Path dest = m_spawningState->get_destination();
|
||||
|
||||
const char *copyFormat = strings::get_by_name(strings::names::FILEOPTION_CONFS, 0);
|
||||
const std::string query = stringutil::get_formatted_string(copyFormat, source.string().c_str(), dest.string().c_str());
|
||||
|
||||
m_dataStruct->sourcePath = std::move(source);
|
||||
m_dataStruct->destPath = std::move(dest);
|
||||
m_dataStruct->journalSize = m_journalSize;
|
||||
|
||||
ProgressConfirm::create_push_fade(query, false, tasks::fileoptions::copy_source_to_destination, m_dataStruct);
|
||||
}
|
||||
|
||||
void FileOptionState::delete_target()
|
||||
{
|
||||
fslib::Path source = m_spawningState->get_source();
|
||||
|
||||
const char *deleteFormat = strings::get_by_name(strings::names::FILEOPTION_CONFS, 1);
|
||||
const std::string query = stringutil::get_formatted_string(deleteFormat, source.string().c_str());
|
||||
|
||||
m_dataStruct->sourcePath = std::move(source);
|
||||
m_dataStruct->journalSize = m_journalSize;
|
||||
|
||||
TaskConfirm::create_push_fade(query, true, tasks::fileoptions::delete_target, m_dataStruct);
|
||||
}
|
||||
|
||||
void FileOptionState::rename_target()
|
||||
{
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
const bool target = m_spawningState->get_target();
|
||||
const fslib::Path targetPath = target ? m_spawningState->get_destination() : m_spawningState->get_source();
|
||||
|
||||
char nameBuffer[FS_MAX_PATH] = {0};
|
||||
const char *filename = targetPath.get_filename();
|
||||
const char *keyboardFormat = strings::get_by_name(strings::names::KEYBOARD, 9);
|
||||
const std::string keyboardHeader = stringutil::get_formatted_string(keyboardFormat, filename);
|
||||
const bool validInput = keyboard::get_input(SwkbdType_QWERTY, filename, keyboardHeader, nameBuffer, FS_MAX_PATH);
|
||||
if (validInput) { return; }
|
||||
|
||||
size_t folderBegin = targetPath.find_last_of('/');
|
||||
if (folderBegin == targetPath.NOT_FOUND) { return; }
|
||||
else if (folderBegin < 1) { folderBegin = 1; }
|
||||
|
||||
fslib::Path newPath{targetPath.sub_path(folderBegin) / nameBuffer};
|
||||
|
||||
const bool isDir = fslib::directory_exists(targetPath);
|
||||
const bool renameDir = isDir && error::fslib(fslib::rename_directory(targetPath, newPath));
|
||||
const bool renameFile = !isDir && error::fslib(fslib::rename_file(targetPath, newPath));
|
||||
if (!renameDir && !renameFile)
|
||||
{
|
||||
const char *popFormat = strings::get_by_name(strings::names::FILEMODE_POPS, 5);
|
||||
const std::string pop = stringutil::get_formatted_string(popFormat, filename);
|
||||
ui::PopMessageManager::push_message(popTicks, pop);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *popFormat = strings::get_by_name(strings::names::FILEMODE_POPS, 4);
|
||||
const std::string pop = stringutil::get_formatted_string(popFormat, filename, nameBuffer);
|
||||
ui::PopMessageManager::push_message(popTicks, pop);
|
||||
}
|
||||
}
|
||||
|
||||
void FileOptionState::close()
|
||||
{
|
||||
const bool target = m_spawningState->get_target();
|
||||
|
||||
m_close = true;
|
||||
m_targetX = target ? 1280 : -240;
|
||||
}
|
||||
|
||||
bool FileOptionState::is_closed() { return m_close && m_x == m_targetX; }
|
||||
|
||||
void FileOptionState::deactivate_state()
|
||||
{
|
||||
sm_copyMenu->set_selected(0);
|
||||
BaseState::deactivate();
|
||||
}
|
||||
|
|
@ -3,9 +3,9 @@
|
|||
#include "StateManager.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
#include "appstates/MessageState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -157,10 +157,10 @@ void SettingsState::change_working_directory()
|
|||
const char *popSuccessFormat = strings::get_by_name(strings::names::SETTINGS_POPS, 1);
|
||||
const char *popFailed = strings::get_by_name(strings::names::SETTINGS_POPS, 2);
|
||||
|
||||
const fslib::Path oldPath{config::get_working_directory()};
|
||||
const std::string oldPath = config::get_working_directory().string();
|
||||
std::array<char, FS_MAX_PATH> pathBuffer = {0};
|
||||
|
||||
const bool input = keyboard::get_input(SwkbdType_Normal, oldPath.full_path(), inputHeader, pathBuffer.data(), FS_MAX_PATH);
|
||||
const bool input = keyboard::get_input(SwkbdType_Normal, oldPath, inputHeader, pathBuffer.data(), FS_MAX_PATH);
|
||||
if (!input) { return; }
|
||||
|
||||
const fslib::Path newPath{pathBuffer.data()};
|
||||
|
|
@ -179,7 +179,8 @@ void SettingsState::change_working_directory()
|
|||
return;
|
||||
}
|
||||
|
||||
const std::string popMessage = stringutil::get_formatted_string(popSuccessFormat, newPath.full_path());
|
||||
const std::string newPathString = newPath.string();
|
||||
const std::string popMessage = stringutil::get_formatted_string(popSuccessFormat, newPathString);
|
||||
ui::PopMessageManager::push_message(popTicks, popMessage);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "appstates/TitleInfoState.hpp"
|
||||
|
||||
#include "StateManager.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/ConfirmState.hpp"
|
||||
#include "appstates/FileModeState.hpp"
|
||||
#include "appstates/MainMenuState.hpp"
|
||||
#include "appstates/TitleInfoState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
@ -57,25 +58,20 @@ void TitleOptionState::update()
|
|||
const bool hasFocus = BaseState::has_focus();
|
||||
|
||||
sm_slidePanel->update(hasFocus);
|
||||
const bool isOpen = sm_slidePanel->is_open();
|
||||
if (!isOpen) { return; }
|
||||
|
||||
const bool isOpen = sm_slidePanel->is_open();
|
||||
const bool aPressed = input::button_pressed(HidNpadButton_A);
|
||||
const bool bPressed = input::button_pressed(HidNpadButton_B);
|
||||
const int selected = sm_titleOptionMenu->get_selected();
|
||||
|
||||
// This is kind of tricky to handle, because the blacklist function uses both.
|
||||
if (m_refreshRequired)
|
||||
{
|
||||
// Refresh the views.
|
||||
MainMenuState::refresh_view_states();
|
||||
m_refreshRequired = false;
|
||||
// Return so nothing else happens. Not sure I like this, but w/e.
|
||||
return;
|
||||
}
|
||||
if (m_exitRequired) { sm_slidePanel->close(); }
|
||||
|
||||
if (aPressed)
|
||||
if (aPressed && isOpen)
|
||||
{
|
||||
switch (selected)
|
||||
{
|
||||
|
|
@ -91,10 +87,16 @@ void TitleOptionState::update()
|
|||
case EXPORT_SVI: TitleOptionState::export_svi_file(); break;
|
||||
}
|
||||
}
|
||||
else if (bPressed) { sm_slidePanel->close(); }
|
||||
else if (bPressed || m_exitRequired)
|
||||
{
|
||||
sm_slidePanel->close();
|
||||
m_exitRequired = false;
|
||||
}
|
||||
else if (sm_slidePanel->is_closed()) { TitleOptionState::deactivate_state(); }
|
||||
}
|
||||
|
||||
void TitleOptionState::sub_update() { sm_slidePanel->sub_update(); }
|
||||
|
||||
void TitleOptionState::render()
|
||||
{
|
||||
const bool hasFocus = BaseState::has_focus();
|
||||
|
|
@ -131,6 +133,7 @@ void TitleOptionState::initialize_data_struct()
|
|||
|
||||
void TitleOptionState::create_push_info_state()
|
||||
{
|
||||
sm_slidePanel->hide();
|
||||
auto titleInfoState = TitleInfoState::create(m_user, m_titleInfo);
|
||||
StateManager::push_state(titleInfoState);
|
||||
}
|
||||
|
|
@ -194,7 +197,18 @@ void TitleOptionState::change_output_directory()
|
|||
ui::PopMessageManager::push_message(popTicks, popSuccess);
|
||||
}
|
||||
|
||||
void TitleOptionState::create_push_file_mode() {}
|
||||
void TitleOptionState::create_push_file_mode()
|
||||
{
|
||||
const uint64_t applicationID = m_titleInfo->get_application_id();
|
||||
const FsSaveDataInfo *saveInfo = m_user->get_save_info_by_id(applicationID);
|
||||
if (error::is_null(saveInfo)) { return; }
|
||||
|
||||
const bool saveOpened = fslib::open_save_data_with_save_info(fs::DEFAULT_SAVE_MOUNT, *saveInfo);
|
||||
if (!saveOpened) { return; }
|
||||
|
||||
sm_slidePanel->hide();
|
||||
FileModeState::create_and_push(fs::DEFAULT_SAVE_MOUNT, "sdmc", true);
|
||||
}
|
||||
|
||||
void TitleOptionState::delete_all_local_backups()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
#include "appstates/TaskState.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
@ -78,6 +78,8 @@ void UserOptionState::update()
|
|||
else if (sm_menuPanel->is_closed()) { UserOptionState::deactivate_state(); }
|
||||
}
|
||||
|
||||
void UserOptionState::sub_update() { sm_menuPanel->sub_update(); }
|
||||
|
||||
void UserOptionState::render()
|
||||
{
|
||||
// Render target user's title selection screen.
|
||||
|
|
@ -131,7 +133,11 @@ void UserOptionState::backup_all()
|
|||
else { ProgressConfirm::create_and_push(query, true, tasks::useroptions::backup_all_for_user_local, m_dataStruct); }
|
||||
}
|
||||
|
||||
void UserOptionState::create_save_create() { SaveCreateState::create_and_push(m_user, m_titleSelect); }
|
||||
void UserOptionState::create_save_create()
|
||||
{
|
||||
sm_menuPanel->hide();
|
||||
SaveCreateState::create_and_push(m_user, m_titleSelect);
|
||||
}
|
||||
|
||||
void UserOptionState::create_all_save_data()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include "JSON.hpp"
|
||||
#include "config/keys.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
|
|
@ -181,7 +180,7 @@ bool config::ConfigContext::load_config_file()
|
|||
const bool exists = fslib::file_exists(configPath);
|
||||
if (!exists) { return false; }
|
||||
|
||||
json::Object configJSON = json::new_object(json_object_from_file, configPath.full_path());
|
||||
json::Object configJSON = json::new_object(json_object_from_file, PATH_CONFIG_FILE.data());
|
||||
if (!configJSON) { return false; }
|
||||
|
||||
json_object_iterator configIter = json::iter_begin(configJSON);
|
||||
|
|
@ -212,7 +211,8 @@ void config::ConfigContext::save_config_file()
|
|||
json::Object configJSON = json::new_object(json_object_new_object);
|
||||
if (!configJSON) { return; }
|
||||
|
||||
json_object *workDir = json_object_new_string(m_workingDirectory.full_path());
|
||||
const std::string workDirString = m_workingDirectory.string();
|
||||
json_object *workDir = json_object_new_string(workDirString.c_str());
|
||||
json::add_object(configJSON, config::keys::WORKING_DIRECTORY, workDir);
|
||||
|
||||
for (const auto &[key, value] : m_configMap)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "curl/curl.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "data/DataContext.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -128,7 +128,7 @@ bool data::DataContext::title_is_loaded(uint64_t applicationID)
|
|||
void data::DataContext::load_title(uint64_t applicationID)
|
||||
{
|
||||
std::scoped_lock titleGuard{m_titleMutex, m_iconQueueMutex};
|
||||
m_titleInfo.emplace(applicationID, applicationID);
|
||||
m_titleInfo.try_emplace(applicationID, applicationID);
|
||||
m_iconQueue.push_back(&m_titleInfo.at(applicationID));
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,8 @@ void data::DataContext::import_svi_files(sys::Task *task)
|
|||
|
||||
task->set_status(statusLoadingSvi);
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sviDir.list())
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
for (const fslib::DirectoryEntry &entry : sviDir)
|
||||
{
|
||||
const fslib::Path target{sviPath / entry};
|
||||
fslib::File sviFile{target, FsOpenMode_Read};
|
||||
|
|
@ -180,7 +181,6 @@ void data::DataContext::import_svi_files(sys::Task *task)
|
|||
|
||||
uint32_t magic{};
|
||||
uint64_t applicationID{};
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
const bool magicRead = sviFile.read(&magic, SIZE_UINT32) == SIZE_UINT32;
|
||||
const bool idRead = sviFile.read(&applicationID, SIZE_UINT64) == SIZE_UINT64;
|
||||
const bool exists = DataContext::title_is_loaded(applicationID);
|
||||
|
|
@ -190,8 +190,7 @@ void data::DataContext::import_svi_files(sys::Task *task)
|
|||
if (!dataRead) { continue; }
|
||||
|
||||
std::scoped_lock multiGuard{m_iconQueueMutex, m_titleMutex};
|
||||
data::TitleInfo newTitle{applicationID, controlData};
|
||||
m_titleInfo.emplace(applicationID, std::move(newTitle));
|
||||
m_titleInfo.try_emplace(applicationID, applicationID, *controlData);
|
||||
m_iconQueue.push_back(&m_titleInfo.at(applicationID));
|
||||
}
|
||||
}
|
||||
|
|
@ -214,8 +213,8 @@ bool data::DataContext::read_cache(sys::Task *task)
|
|||
const char *statusLoadingCache = strings::get_by_name(strings::names::DATA_LOADING_STATUS, 4);
|
||||
task->set_status(statusLoadingCache);
|
||||
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
do {
|
||||
auto controlData = std::make_unique<NsApplicationControlData>();
|
||||
const bool dataRead = cacheZip.read(controlData.get(), SIZE_CTRL_DATA) == SIZE_CTRL_DATA;
|
||||
if (!dataRead) { continue; }
|
||||
|
||||
|
|
@ -228,8 +227,7 @@ bool data::DataContext::read_cache(sys::Task *task)
|
|||
|
||||
std::scoped_lock multiGuard{m_iconQueueMutex, m_titleMutex};
|
||||
|
||||
data::TitleInfo newTitle{applicationID, controlData};
|
||||
m_titleInfo.emplace(applicationID, std::move(newTitle));
|
||||
m_titleInfo.try_emplace(applicationID, applicationID, *controlData);
|
||||
m_iconQueue.push_back(&m_titleInfo.at(applicationID));
|
||||
} while (cacheZip.next_file());
|
||||
m_cacheIsValid = true;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "data/TitleInfo.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "graphics/gfxutil.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
|
|
@ -11,28 +11,25 @@
|
|||
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID)
|
||||
: m_applicationID(applicationID)
|
||||
, m_data(std::make_unique<NsApplicationControlData>())
|
||||
{
|
||||
static constexpr size_t SIZE_CTRL_DATA = sizeof(NsApplicationControlData);
|
||||
|
||||
uint64_t controlSize{};
|
||||
NacpLanguageEntry *entry{};
|
||||
NsApplicationControlData *data = m_data.get();
|
||||
|
||||
// This will filter from even trying to fetch control data for system titles.
|
||||
const bool isSystem = applicationID & 0x8000000000000000;
|
||||
const bool getError = !isSystem && error::libnx(nsGetApplicationControlData(NsApplicationControlSource_Storage,
|
||||
m_applicationID,
|
||||
data,
|
||||
&m_data,
|
||||
SIZE_CTRL_DATA,
|
||||
&controlSize));
|
||||
const bool entryError = !getError && error::libnx(nacpGetLanguageEntry(&data->nacp, &entry));
|
||||
const bool entryError = !getError && error::libnx(nacpGetLanguageEntry(&m_data.nacp, &entry));
|
||||
if (isSystem || getError)
|
||||
{
|
||||
const std::string appIDHex = stringutil::get_formatted_string("%04X", m_applicationID & 0xFFFF);
|
||||
char *name = data->nacp.lang[SetLanguage_ENUS].name; // I'm hoping this is enough?
|
||||
char *name = m_data.nacp.lang[SetLanguage_ENUS].name; // I'm hoping this is enough?
|
||||
|
||||
std::memset(data, 0x00, SIZE_CTRL_DATA);
|
||||
std::snprintf(name, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID);
|
||||
TitleInfo::get_create_path_safe_title();
|
||||
}
|
||||
|
|
@ -44,48 +41,29 @@ data::TitleInfo::TitleInfo(uint64_t applicationID)
|
|||
}
|
||||
|
||||
// To do: Make this safer...
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID, std::unique_ptr<NsApplicationControlData> &controlData)
|
||||
data::TitleInfo::TitleInfo(uint64_t applicationID, NsApplicationControlData &controlData)
|
||||
: m_applicationID(applicationID)
|
||||
, m_data(std::move(controlData))
|
||||
{
|
||||
m_hasData = true;
|
||||
m_data = controlData;
|
||||
|
||||
NacpLanguageEntry *entry{};
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data.nacp, &entry));
|
||||
if (entryError) { std::snprintf(entry->name, TitleInfo::SIZE_PATH_SAFE, "%016lX", m_applicationID); }
|
||||
|
||||
TitleInfo::get_create_path_safe_title();
|
||||
}
|
||||
|
||||
data::TitleInfo::TitleInfo(data::TitleInfo &&titleInfo) { *this = std::move(titleInfo); }
|
||||
|
||||
data::TitleInfo &data::TitleInfo::operator=(data::TitleInfo &&titleInfo)
|
||||
{
|
||||
m_applicationID = titleInfo.m_applicationID;
|
||||
m_data = std::move(titleInfo.m_data);
|
||||
m_hasData = titleInfo.m_hasData;
|
||||
std::memcpy(m_pathSafeTitle, titleInfo.m_pathSafeTitle, TitleInfo::SIZE_PATH_SAFE);
|
||||
m_icon = titleInfo.m_icon;
|
||||
|
||||
titleInfo.m_applicationID = 0;
|
||||
titleInfo.m_data = nullptr;
|
||||
titleInfo.m_hasData = false;
|
||||
std::memset(titleInfo.m_pathSafeTitle, 0x00, TitleInfo::SIZE_PATH_SAFE);
|
||||
titleInfo.m_icon = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint64_t data::TitleInfo::get_application_id() const { return m_applicationID; }
|
||||
|
||||
NsApplicationControlData *data::TitleInfo::get_control_data() { return m_data.get(); }
|
||||
NsApplicationControlData *data::TitleInfo::get_control_data() { return &m_data; }
|
||||
|
||||
bool data::TitleInfo::has_control_data() const { return m_hasData; }
|
||||
|
||||
const char *data::TitleInfo::get_title()
|
||||
{
|
||||
NacpLanguageEntry *entry{};
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data.nacp, &entry));
|
||||
if (entryError) { return nullptr; }
|
||||
return entry->name;
|
||||
}
|
||||
|
|
@ -95,16 +73,16 @@ const char *data::TitleInfo::get_path_safe_title() const { return m_pathSafeTitl
|
|||
const char *data::TitleInfo::get_publisher()
|
||||
{
|
||||
NacpLanguageEntry *entry{};
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
const bool entryError = error::libnx(nacpGetLanguageEntry(&m_data.nacp, &entry));
|
||||
if (entryError) { return nullptr; }
|
||||
return entry->author;
|
||||
}
|
||||
|
||||
uint64_t data::TitleInfo::get_save_data_owner_id() const { return m_data->nacp.save_data_owner_id; }
|
||||
uint64_t data::TitleInfo::get_save_data_owner_id() const { return m_data.nacp.save_data_owner_id; }
|
||||
|
||||
int64_t data::TitleInfo::get_save_data_size(uint8_t saveType) const
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return nacp.user_account_save_data_size;
|
||||
|
|
@ -118,7 +96,7 @@ int64_t data::TitleInfo::get_save_data_size(uint8_t saveType) const
|
|||
|
||||
int64_t data::TitleInfo::get_save_data_size_max(uint8_t saveType) const
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return std::max(nacp.user_account_save_data_size, nacp.user_account_save_data_size_max);
|
||||
|
|
@ -132,7 +110,7 @@ int64_t data::TitleInfo::get_save_data_size_max(uint8_t saveType) const
|
|||
|
||||
int64_t data::TitleInfo::get_journal_size(uint8_t saveType) const
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return nacp.user_account_save_data_journal_size;
|
||||
|
|
@ -146,7 +124,7 @@ int64_t data::TitleInfo::get_journal_size(uint8_t saveType) const
|
|||
|
||||
int64_t data::TitleInfo::get_journal_size_max(uint8_t saveType) const
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account:
|
||||
|
|
@ -162,7 +140,7 @@ int64_t data::TitleInfo::get_journal_size_max(uint8_t saveType) const
|
|||
|
||||
bool data::TitleInfo::has_save_data_type(uint8_t saveType) const
|
||||
{
|
||||
const NacpStruct &nacp = m_data->nacp;
|
||||
const NacpStruct &nacp = m_data.nacp;
|
||||
switch (saveType)
|
||||
{
|
||||
case FsSaveDataType_Account: return nacp.user_account_save_data_size > 0 || nacp.user_account_save_data_size_max > 0;
|
||||
|
|
@ -197,7 +175,7 @@ void data::TitleInfo::get_create_path_safe_title()
|
|||
}
|
||||
|
||||
const bool useTitleId = config::get_by_key(config::keys::USE_TITLE_IDS);
|
||||
const bool entryError = !useTitleId && error::libnx(nacpGetLanguageEntry(&m_data->nacp, &entry));
|
||||
const bool entryError = !useTitleId && error::libnx(nacpGetLanguageEntry(&m_data.nacp, &entry));
|
||||
const bool sanitized =
|
||||
!useTitleId && !entryError && stringutil::sanitize_string_for_path(entry->name, m_pathSafeTitle, SIZE_PATH_SAFE);
|
||||
if (useTitleId || entryError || !sanitized)
|
||||
|
|
@ -214,7 +192,7 @@ void data::TitleInfo::load_icon()
|
|||
if (m_hasData)
|
||||
{
|
||||
const std::string textureName = stringutil::get_formatted_string("%016llX", m_applicationID);
|
||||
m_icon = sdl::TextureManager::load(textureName, m_data->icon, SIZE_ICON);
|
||||
m_icon = sdl::TextureManager::load(textureName, m_data.icon, SIZE_ICON);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "graphics/gfxutil.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "sdl.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -164,15 +164,12 @@ void data::User::load_user_data()
|
|||
|
||||
while (infoReader.read())
|
||||
{
|
||||
const int64_t readCount = infoReader.get_read_count();
|
||||
|
||||
for (int64_t i = 0; i < readCount; i++)
|
||||
for (const FsSaveDataInfo &saveInfo : infoReader)
|
||||
{
|
||||
const FsSaveDataInfo &saveInfo = infoReader[i];
|
||||
const uint64_t saveInfoAppID = saveInfo.application_id;
|
||||
const uint64_t saveInfoSysID = saveInfo.system_save_data_id;
|
||||
const uint64_t applicationID = saveInfoAppID != 0 ? saveInfoAppID : saveInfoSysID;
|
||||
const uint8_t saveDataType = saveInfo.save_data_type;
|
||||
const uint64_t saveInfoAppID = saveInfo.application_id;
|
||||
const uint64_t saveInfoSysID = saveInfo.system_save_data_id;
|
||||
const uint64_t applicationID = saveInfoAppID != 0 ? saveInfoAppID : saveInfoSysID;
|
||||
const uint8_t saveDataType = saveInfo.save_data_type;
|
||||
const bool isSystemSave = saveDataType == FsSaveDataType_System || saveDataType == FsSaveDataType_SystemBcat;
|
||||
|
||||
const bool isBlacklisted = config::is_blacklisted(applicationID);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include "appstates/DataLoadingState.hpp"
|
||||
#include "data/DataContext.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
||||
#include <switch.h>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include "fslib.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "fs/MiniUnzip.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
fs::MiniUnzip::MiniUnzip(const fslib::Path &path) { MiniUnzip::open(path); }
|
||||
|
|
@ -12,7 +12,9 @@ bool fs::MiniUnzip::is_open() const { return m_isOpen; }
|
|||
bool fs::MiniUnzip::open(const fslib::Path &path)
|
||||
{
|
||||
MiniUnzip::close();
|
||||
m_unz = unzOpen64(path.full_path());
|
||||
|
||||
const std::string pathString = path.string();
|
||||
m_unz = unzOpen64(pathString.c_str());
|
||||
if (error::is_null(m_unz) || !MiniUnzip::reset()) { return false; }
|
||||
m_isOpen = true;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
#include "fs/MiniZip.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
// Definition at bottom.
|
||||
static zip_fileinfo create_zip_file_info();
|
||||
|
||||
fs::MiniZip::MiniZip(const fslib::Path &path) { MiniZip::open(path); }
|
||||
fs::MiniZip::MiniZip(const fslib::Path &path)
|
||||
: m_level(config::get_by_key(config::keys::ZIP_COMPRESSION_LEVEL))
|
||||
{
|
||||
MiniZip::open(path);
|
||||
}
|
||||
|
||||
fs::MiniZip::~MiniZip() { MiniZip::close(); }
|
||||
|
||||
|
|
@ -17,7 +22,9 @@ bool fs::MiniZip::is_open() const { return m_isOpen; }
|
|||
bool fs::MiniZip::open(const fslib::Path &path)
|
||||
{
|
||||
MiniZip::close();
|
||||
m_zip = zipOpen64(path.full_path(), APPEND_STATUS_CREATE);
|
||||
|
||||
const std::string pathString = path.string();
|
||||
m_zip = zipOpen64(pathString.c_str(), APPEND_STATUS_CREATE);
|
||||
if (error::is_null(m_zip)) { return false; }
|
||||
m_isOpen = true;
|
||||
return true;
|
||||
|
|
@ -32,19 +39,21 @@ void fs::MiniZip::close()
|
|||
|
||||
bool fs::MiniZip::open_new_file(std::string_view filename, bool trimPath, size_t trimPlaces)
|
||||
{
|
||||
const uint8_t zipLevel = config::get_by_key(config::keys::ZIP_COMPRESSION_LEVEL);
|
||||
|
||||
const size_t pathBegin = filename.find_first_of('/');
|
||||
if (pathBegin != filename.npos) { filename = filename.substr(pathBegin + 1); }
|
||||
|
||||
const zip_fileinfo fileInfo = create_zip_file_info();
|
||||
return zipOpenNewFileInZip64(m_zip, filename.data(), &fileInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, zipLevel, 0) ==
|
||||
return zipOpenNewFileInZip64(m_zip, filename.data(), &fileInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, m_level, 0) ==
|
||||
ZIP_OK;
|
||||
}
|
||||
|
||||
bool fs::MiniZip::close_current_file() { return zipCloseFileInZip(m_zip) == ZIP_OK; }
|
||||
|
||||
bool fs::MiniZip::write(const void *buffer, size_t dataSize) { return zipWriteInFileInZip(m_zip, buffer, dataSize) == ZIP_OK; }
|
||||
bool fs::MiniZip::write(const void *buffer, size_t dataSize)
|
||||
{
|
||||
if (!m_isOpen) { return false; }
|
||||
return zipWriteInFileInZip(m_zip, buffer, dataSize) == ZIP_OK;
|
||||
}
|
||||
|
||||
static zip_fileinfo create_zip_file_info()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
fs::PathFilter::PathFilter(const fslib::Path &filePath)
|
||||
{
|
||||
json::Object filterJSON = json::new_object(json_object_from_file, filePath.full_path());
|
||||
const std::string pathString = filePath.string();
|
||||
json::Object filterJSON = json::new_object(json_object_from_file, pathString.c_str());
|
||||
if (!filterJSON) { return; }
|
||||
|
||||
json_object *filter = json::get_object(filterJSON, "filters");
|
||||
|
|
@ -25,5 +26,5 @@ bool fs::PathFilter::has_paths() const { return !m_paths.empty(); }
|
|||
|
||||
bool fs::PathFilter::is_filtered(const fslib::Path &path)
|
||||
{
|
||||
return std::find(m_paths.begin(), m_paths.end(), path.full_path()) != m_paths.end();
|
||||
return std::find(m_paths.begin(), m_paths.end(), path) != m_paths.end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,20 @@
|
|||
#include "fs/SaveMetaData.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/directory_functions.hpp"
|
||||
#include "fs/save_data_functions.hpp"
|
||||
#include "fs/save_mount.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr size_t SIZE_EXTRA_DATA = sizeof(FsSaveDataExtraData);
|
||||
}
|
||||
|
||||
bool fs::read_save_data_extra_info(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &dataOut)
|
||||
{
|
||||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
const uint64_t saveDataID = saveInfo->save_data_id;
|
||||
|
||||
const bool readError =
|
||||
error::libnx(fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(&dataOut, SIZE_EXTRA_DATA, spaceID, saveDataID));
|
||||
if (readError) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fs::fill_save_meta_data(const FsSaveDataInfo *saveInfo, fs::SaveMetaData &meta)
|
||||
{
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool extraRead = fs::read_save_data_extra_info(saveInfo, extraData);
|
||||
const bool extraRead = fs::read_save_extra_data(saveInfo, extraData);
|
||||
if (!extraRead) { return false; }
|
||||
|
||||
meta = {.magic = fs::SAVE_META_MAGIC,
|
||||
|
|
@ -49,7 +38,7 @@ bool fs::fill_save_meta_data(const FsSaveDataInfo *saveInfo, fs::SaveMetaData &m
|
|||
bool fs::process_save_meta_data(const FsSaveDataInfo *saveInfo, const SaveMetaData &meta)
|
||||
{
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool extraRead = fs::read_save_data_extra_info(saveInfo, extraData);
|
||||
const bool extraRead = fs::read_save_extra_data(saveInfo, extraData);
|
||||
if (!extraRead) { return false; }
|
||||
|
||||
const bool needsExtend = extraData.data_size < meta.saveDataSize;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "fs/ScopedSaveMount.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
|
||||
fs::ScopedSaveMount::ScopedSaveMount(std::string_view mount, const FsSaveDataInfo *saveInfo, bool log)
|
||||
: m_mountPoint(mount)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ uint64_t fs::get_directory_total_size(const fslib::Path &targetPath)
|
|||
if (!targetDir.is_open()) { return 0; }
|
||||
|
||||
uint64_t directorySize = 0;
|
||||
for (const fslib::DirectoryEntry &entry : targetDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : targetDir)
|
||||
{
|
||||
if (entry.is_directory())
|
||||
{
|
||||
|
|
@ -26,7 +26,7 @@ bool fs::directory_has_contents(const fslib::Path &directoryPath)
|
|||
fslib::Directory testDir{directoryPath};
|
||||
if (!testDir.is_open()) { return false; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : testDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : testDir)
|
||||
{
|
||||
if (entry.get_filename() != fs::NAME_SAVE_META) { return true; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "fs/io.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/SaveMetaData.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "sys/sys.hpp"
|
||||
|
|
@ -70,7 +70,8 @@ void fs::copy_file(const fslib::Path &source, const fslib::Path &destination, sy
|
|||
const int64_t sourceSize = sourceFile.get_size();
|
||||
if (task)
|
||||
{
|
||||
const std::string status = stringutil::get_formatted_string(statusTemplate, source.full_path());
|
||||
const std::string sourceString = source.string();
|
||||
const std::string status = stringutil::get_formatted_string(statusTemplate, sourceString.c_str());
|
||||
task->set_status(status);
|
||||
task->reset(static_cast<double>(sourceSize));
|
||||
}
|
||||
|
|
@ -111,7 +112,6 @@ void fs::copy_file(const fslib::Path &source, const fslib::Path &destination, sy
|
|||
|
||||
void fs::copy_file_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task)
|
||||
{
|
||||
|
|
@ -126,7 +126,8 @@ void fs::copy_file_commit(const fslib::Path &source,
|
|||
const int64_t sourceSize = sourceFile.get_size();
|
||||
if (task)
|
||||
{
|
||||
const std::string status = stringutil::get_formatted_string(copyingStatus, source.full_path());
|
||||
const std::string sourceString = source.string();
|
||||
const std::string status = stringutil::get_formatted_string(copyingStatus, sourceString.c_str());
|
||||
task->set_status(status);
|
||||
task->reset(static_cast<double>(sourceSize));
|
||||
}
|
||||
|
|
@ -163,7 +164,7 @@ void fs::copy_file_commit(const fslib::Path &source,
|
|||
if (needsCommit)
|
||||
{
|
||||
destFile.close();
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(device));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(destination.get_device_name()));
|
||||
// To do: Handle this better. Threads current have no way of communicating errors.
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
|
||||
|
|
@ -180,7 +181,7 @@ void fs::copy_file_commit(const fslib::Path &source,
|
|||
readThread.join();
|
||||
destFile.close();
|
||||
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(device));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(destination.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +190,7 @@ void fs::copy_directory(const fslib::Path &source, const fslib::Path &destinatio
|
|||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const char *filename = entry.get_filename();
|
||||
if (filename == fs::NAME_SAVE_META) { continue; }
|
||||
|
|
@ -210,14 +211,13 @@ void fs::copy_directory(const fslib::Path &source, const fslib::Path &destinatio
|
|||
|
||||
void fs::copy_directory_commit(const fslib::Path &source,
|
||||
const fslib::Path &destination,
|
||||
std::string_view device,
|
||||
int64_t journalSize,
|
||||
sys::ProgressTask *task)
|
||||
{
|
||||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const char *filename = entry.get_filename();
|
||||
if (filename == fs::NAME_SAVE_META) { continue; }
|
||||
|
|
@ -230,8 +230,8 @@ void fs::copy_directory_commit(const fslib::Path &source,
|
|||
const bool createError = !destExists && error::fslib(fslib::create_directory(fullDest));
|
||||
if (!destExists && createError) { continue; }
|
||||
|
||||
fs::copy_directory_commit(fullSource, fullDest, device, journalSize, task);
|
||||
fs::copy_directory_commit(fullSource, fullDest, journalSize, task);
|
||||
}
|
||||
else { fs::copy_file_commit(fullSource, fullDest, device, journalSize, task); }
|
||||
else { fs::copy_file_commit(fullSource, fullDest, journalSize, task); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "fs/save_data_functions.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
bool fs::create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo)
|
||||
|
|
@ -29,8 +29,7 @@ bool fs::create_save_data_for(data::User *targetUser, data::TitleInfo *titleInfo
|
|||
.save_data_space_id = FsSaveDataSpaceId_User};
|
||||
|
||||
// I want this recorded.
|
||||
const bool createError = error::libnx(fsCreateSaveDataFileSystem(&saveAttributes, &saveCreation, &saveMeta));
|
||||
return createError == false;
|
||||
return error::libnx(fsCreateSaveDataFileSystem(&saveAttributes, &saveCreation, &saveMeta)) == false;
|
||||
}
|
||||
|
||||
bool fs::delete_save_data(const FsSaveDataInfo *saveInfo)
|
||||
|
|
@ -47,8 +46,7 @@ bool fs::delete_save_data(const FsSaveDataInfo *saveInfo)
|
|||
.save_data_rank = saveInfo->save_data_rank,
|
||||
.save_data_index = saveInfo->save_data_index};
|
||||
|
||||
const bool deleteError = error::libnx(fsDeleteSaveDataFileSystemBySaveDataAttribute(spaceID, &saveAttributes));
|
||||
return deleteError == false;
|
||||
return error::libnx(fsDeleteSaveDataFileSystemBySaveDataAttribute(spaceID, &saveAttributes)) == false;
|
||||
}
|
||||
|
||||
bool fs::extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t journalSize)
|
||||
|
|
@ -56,11 +54,22 @@ bool fs::extend_save_data(const FsSaveDataInfo *saveInfo, int64_t size, int64_t
|
|||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
const uint64_t saveID = saveInfo->save_data_id;
|
||||
|
||||
const bool extendError = error::libnx(fsExtendSaveDataFileSystem(spaceID, saveID, size, journalSize));
|
||||
return extendError == false;
|
||||
return error::libnx(fsExtendSaveDataFileSystem(spaceID, saveID, size, journalSize)) == false;
|
||||
}
|
||||
|
||||
bool fs::is_system_save_data(const FsSaveDataInfo *saveInfo)
|
||||
{
|
||||
return saveInfo->save_data_type == FsSaveDataType_System || saveInfo->save_data_type == FsSaveDataType_SystemBcat;
|
||||
}
|
||||
|
||||
bool fs::read_save_extra_data(const FsSaveDataInfo *saveInfo, FsSaveDataExtraData &extraOut)
|
||||
{
|
||||
static constexpr size_t EXTRA_SIZE = sizeof(FsSaveDataExtraData);
|
||||
|
||||
const FsSaveDataSpaceId spaceID = static_cast<FsSaveDataSpaceId>(saveInfo->save_data_space_id);
|
||||
|
||||
const bool readError = error::libnx(
|
||||
fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(&extraOut, EXTRA_SIZE, spaceID, saveInfo->save_data_id));
|
||||
|
||||
return !readError;
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "fs/zip.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/SaveMetaData.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
@ -100,14 +100,15 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
fslib::Directory sourceDir{source};
|
||||
if (error::fslib(sourceDir.is_open())) { return; }
|
||||
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir.list())
|
||||
for (const fslib::DirectoryEntry &entry : sourceDir)
|
||||
{
|
||||
const fslib::Path fullSource{source / entry};
|
||||
if (entry.is_directory()) { fs::copy_directory_to_zip(fullSource, dest, task); }
|
||||
else
|
||||
{
|
||||
fslib::File sourceFile{fullSource, FsOpenMode_Read};
|
||||
const bool newZipFile = dest.open_new_file(fullSource.full_path());
|
||||
const std::string sourceString = fullSource.string();
|
||||
const bool newZipFile = dest.open_new_file(sourceString);
|
||||
if (error::fslib(sourceFile.is_open()) || !newZipFile) { continue; }
|
||||
|
||||
const int64_t fileSize = sourceFile.get_size();
|
||||
|
|
@ -117,7 +118,7 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
|
||||
if (task)
|
||||
{
|
||||
const std::string status = stringutil::get_formatted_string(ioStatus, fullSource.full_path());
|
||||
const std::string status = stringutil::get_formatted_string(ioStatus, sourceString.c_str());
|
||||
task->set_status(status);
|
||||
task->reset(static_cast<double>(fileSize));
|
||||
}
|
||||
|
|
@ -158,17 +159,13 @@ void fs::copy_directory_to_zip(const fslib::Path &source, fs::MiniZip &dest, sys
|
|||
}
|
||||
}
|
||||
|
||||
void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
||||
const fslib::Path &dest,
|
||||
int64_t journalSize,
|
||||
std::string_view commitDevice,
|
||||
sys::ProgressTask *task)
|
||||
void fs::copy_zip_to_directory(fs::MiniUnzip &unzip, const fslib::Path &dest, int64_t journalSize, sys::ProgressTask *task)
|
||||
{
|
||||
if (!unzip.reset()) { return; }
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
const char *popCommitFailed = strings::get_by_name(strings::names::IO_POPS, 0);
|
||||
const char *statusTemplate = strings::get_by_name(strings::names::IO_STATUSES, 2);
|
||||
const bool needCommits = journalSize > 0 && !commitDevice.empty();
|
||||
const bool needCommits = journalSize > 0;
|
||||
|
||||
do {
|
||||
if (unzip.get_filename() == fs::NAME_SAVE_META) { continue; }
|
||||
|
|
@ -178,9 +175,10 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
if (lastDir == fullDest.NOT_FOUND) { continue; }
|
||||
|
||||
const fslib::Path dirPath{fullDest.sub_path(lastDir)};
|
||||
const bool exists = dirPath.is_valid() && fslib::directory_exists(dirPath);
|
||||
const bool createError = dirPath.is_valid() && !exists && error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
if (dirPath.is_valid() && !exists && createError) { continue; }
|
||||
const bool isValid = dirPath.is_valid();
|
||||
const bool exists = isValid && fslib::directory_exists(dirPath);
|
||||
const bool createError = isValid && !exists && error::fslib(fslib::create_directories_recursively(dirPath));
|
||||
if (isValid && !exists && createError) { continue; }
|
||||
|
||||
const int64_t fileSize = unzip.get_uncompressed_size();
|
||||
fslib::File destFile{fullDest, FsOpenMode_Create | FsOpenMode_Write, fileSize};
|
||||
|
|
@ -203,8 +201,8 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
bool &bufferReady = sharedData->bufferReady;
|
||||
std::unique_ptr<sys::byte[]> &sharedBuffer = sharedData->sharedBuffer;
|
||||
|
||||
std::thread readThread(unzipReadThreadFunction, std::ref(unzip), sharedData);
|
||||
int64_t journalCount{};
|
||||
std::thread readThread(unzipReadThreadFunction, std::ref(unzip), sharedData);
|
||||
for (int64_t i = 0; i < fileSize;)
|
||||
{
|
||||
ssize_t localRead{};
|
||||
|
|
@ -223,7 +221,7 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
if (commitNeeded)
|
||||
{
|
||||
destFile.close();
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(commitDevice));
|
||||
const bool commitError = error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); } // To do: How to recover?
|
||||
|
||||
destFile.open(fullDest, FsOpenMode_Write);
|
||||
|
|
@ -240,7 +238,7 @@ void fs::copy_zip_to_directory(fs::MiniUnzip &unzip,
|
|||
readThread.join();
|
||||
destFile.close();
|
||||
|
||||
const bool commitError = needCommits && error::fslib(fslib::commit_data_to_file_system(commitDevice));
|
||||
const bool commitError = needCommits && error::fslib(fslib::commit_data_to_file_system(dest.get_device_name()));
|
||||
if (commitError) { ui::PopMessageManager::push_message(popTicks, popCommitFailed); }
|
||||
} while (unzip.next_file());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "keyboard.hpp"
|
||||
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "JSON.hpp"
|
||||
#include "curl/curl.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "StateManager.hpp"
|
||||
#include "appstates/TaskState.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/GoogleDrive.hpp"
|
||||
#include "remote/WebDav.hpp"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include "JSON.hpp"
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fslib.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
||||
|
|
@ -15,6 +15,7 @@ namespace
|
|||
{
|
||||
// This is the actual map where the strings are.
|
||||
std::map<std::pair<std::string, int>, std::string> s_stringMap;
|
||||
|
||||
// This map is for matching files to the language value
|
||||
std::unordered_map<SetLanguage, std::string_view> s_fileMap = {{SetLanguage_JA, "JA.json"},
|
||||
{SetLanguage_ENUS, "ENUS.json"},
|
||||
|
|
@ -42,8 +43,8 @@ static void replace_buttons_in_string(std::string &target);
|
|||
|
||||
bool strings::initialize()
|
||||
{
|
||||
const fslib::Path filePath = get_file_path();
|
||||
json::Object stringJSON = json::new_object(json_object_from_file, filePath.full_path());
|
||||
const std::string stringPath = get_file_path().string();
|
||||
json::Object stringJSON = json::new_object(json_object_from_file, stringPath.c_str());
|
||||
if (!stringJSON) { return false; }
|
||||
|
||||
json_object_iterator stringIterator = json::iter_begin(stringJSON);
|
||||
|
|
|
|||
|
|
@ -59,12 +59,12 @@ bool stringutil::sanitize_string_for_path(const char *stringIn, char *stringOut,
|
|||
const bool countCheck = count <= 0 || i + count >= stringOutSize;
|
||||
const bool codeCheck = codepoint < 0x20 || codepoint > 0x7E;
|
||||
if (countCheck) { break; }
|
||||
else if (codepoint == L'é') { stringOut[offset++] = 'e'; }
|
||||
else if (codeCheck) { return false; }
|
||||
|
||||
const bool forbidden = std::find(FORBIDDEN_PATH_CHARACTERS.begin(), FORBIDDEN_PATH_CHARACTERS.end(), codepoint) !=
|
||||
FORBIDDEN_PATH_CHARACTERS.end();
|
||||
if (forbidden) { stringOut[offset++] = 0x20; }
|
||||
else if (codepoint == L'é') { stringOut[offset++] = 'e'; }
|
||||
else
|
||||
{
|
||||
std::memcpy(&stringOut[offset], &stringIn[i], static_cast<size_t>(count));
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "tasks/backup.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
@ -36,7 +36,8 @@ void tasks::backup::create_new_backup_local(sys::ProgressTask *task,
|
|||
if (error::is_null(task)) { return; }
|
||||
if (error::is_null(user) || error::is_null(titleInfo)) { TASK_FINISH_RETURN(task); }
|
||||
|
||||
const bool hasZipExt = std::strstr(target.full_path(), STRING_ZIP_EXT);
|
||||
const std::string targetString = target.string();
|
||||
const bool hasZipExt = std::strstr(targetString.c_str(), STRING_ZIP_EXT);
|
||||
const uint64_t applicationID = titleInfo->get_application_id();
|
||||
const FsSaveDataInfo *saveInfo = user->get_save_info_by_id(applicationID);
|
||||
if (error::is_null(saveInfo)) { TASK_FINISH_RETURN(task); }
|
||||
|
|
@ -198,12 +199,16 @@ void tasks::backup::restore_backup_local(sys::ProgressTask *task, BackupMenuStat
|
|||
const uint64_t applicationID = titleInfo->get_application_id();
|
||||
const FsSaveDataInfo *saveInfo = user->get_save_info_by_id(applicationID);
|
||||
const uint8_t saveType = user->get_account_save_type();
|
||||
const uint64_t journalSize = titleInfo->get_journal_size(saveType);
|
||||
if (error::is_null(saveInfo)) { TASK_FINISH_RETURN(task); }
|
||||
|
||||
const bool autoBackup = config::get_by_key(config::keys::AUTO_BACKUP_ON_RESTORE);
|
||||
const bool isDir = fslib::directory_exists(target);
|
||||
const bool hasZipExt = std::strstr(target.full_path(), STRING_ZIP_EXT);
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool readExtra = fs::read_save_extra_data(saveInfo, extraData);
|
||||
const int64_t journalSize = readExtra ? extraData.journal_size : titleInfo->get_journal_size(saveType);
|
||||
|
||||
const std::string targetString = target.string();
|
||||
const bool autoBackup = config::get_by_key(config::keys::AUTO_BACKUP_ON_RESTORE);
|
||||
const bool isDir = fslib::directory_exists(target);
|
||||
const bool hasZipExt = std::strstr(targetString.c_str(), STRING_ZIP_EXT);
|
||||
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
if (autoBackup) { auto_backup(task, taskData); }
|
||||
|
|
@ -226,18 +231,18 @@ void tasks::backup::restore_backup_local(sys::ProgressTask *task, BackupMenuStat
|
|||
|
||||
read_and_process_meta(unzip, taskData, task);
|
||||
auto scopedMount = create_scoped_mount(saveInfo);
|
||||
fs::copy_zip_to_directory(unzip, fs::DEFAULT_SAVE_ROOT, journalSize, fs::DEFAULT_SAVE_MOUNT, task);
|
||||
fs::copy_zip_to_directory(unzip, fs::DEFAULT_SAVE_ROOT, journalSize, task);
|
||||
}
|
||||
else if (isDir)
|
||||
{
|
||||
read_and_process_meta(target, taskData, task);
|
||||
auto scopedMount = create_scoped_mount(saveInfo);
|
||||
fs::copy_directory_commit(target, fs::DEFAULT_SAVE_ROOT, fs::DEFAULT_SAVE_MOUNT, journalSize, task);
|
||||
fs::copy_directory_commit(target, fs::DEFAULT_SAVE_ROOT, journalSize, task);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto scopedMount = create_scoped_mount(saveInfo);
|
||||
fs::copy_file_commit(target, fs::DEFAULT_SAVE_ROOT, fs::DEFAULT_SAVE_MOUNT, journalSize, task);
|
||||
fs::copy_file_commit(target, fs::DEFAULT_SAVE_ROOT, journalSize, task);
|
||||
}
|
||||
|
||||
spawningState->refresh();
|
||||
|
|
@ -306,10 +311,12 @@ void tasks::backup::restore_backup_remote(sys::ProgressTask *task, BackupMenuSta
|
|||
|
||||
read_and_process_meta(backup, taskData, task);
|
||||
{
|
||||
const uint8_t saveType = user->get_account_save_type();
|
||||
const uint64_t journalSize = titleInfo->get_journal_size(saveType);
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool readExtra = fs::read_save_extra_data(saveInfo, extraData);
|
||||
const uint8_t saveType = user->get_account_save_type();
|
||||
const int64_t journalSize = readExtra ? extraData.journal_size : titleInfo->get_journal_size(saveType);
|
||||
fs::ScopedSaveMount saveMount{fs::DEFAULT_SAVE_MOUNT, saveInfo};
|
||||
fs::copy_zip_to_directory(backup, fs::DEFAULT_SAVE_ROOT, journalSize, fs::DEFAULT_SAVE_MOUNT, task);
|
||||
fs::copy_zip_to_directory(backup, fs::DEFAULT_SAVE_ROOT, journalSize, task);
|
||||
}
|
||||
backup.close();
|
||||
|
||||
|
|
@ -333,8 +340,9 @@ void tasks::backup::delete_backup_local(sys::Task *task, BackupMenuState::TaskDa
|
|||
|
||||
const int popTicks = ui::PopMessageManager::DEFAULT_TICKS;
|
||||
{
|
||||
const char *statusFormat = strings::get_by_name(strings::names::IO_STATUSES, 3);
|
||||
const std::string status = stringutil::get_formatted_string(statusFormat, path.full_path());
|
||||
const std::string pathString = path.string();
|
||||
const char *statusFormat = strings::get_by_name(strings::names::IO_STATUSES, 3);
|
||||
const std::string status = stringutil::get_formatted_string(statusFormat, pathString.c_str());
|
||||
task->set_status(status);
|
||||
}
|
||||
|
||||
|
|
|
|||
42
source/tasks/fileoptions.cpp
Normal file
42
source/tasks/fileoptions.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#include "tasks/fileoptions.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "fslib.hpp"
|
||||
|
||||
void tasks::fileoptions::copy_source_to_destination(sys::ProgressTask *task, FileOptionState::TaskData taskData)
|
||||
{
|
||||
if (error::is_null(task)) { return; }
|
||||
|
||||
fslib::Path &source = taskData->sourcePath;
|
||||
fslib::Path &dest = taskData->destPath;
|
||||
int64_t journalSpace = taskData->journalSize;
|
||||
|
||||
const bool isDir = fslib::directory_exists(source);
|
||||
const bool needsCommit = journalSpace > 0;
|
||||
|
||||
if (isDir && needsCommit) { fs::copy_directory_commit(source, dest, journalSpace, task); }
|
||||
else if (!isDir && needsCommit) { fs::copy_file_commit(source, dest, journalSpace, task); }
|
||||
else if (isDir && !needsCommit) { fs::copy_directory(source, dest, task); }
|
||||
else if (!isDir && !needsCommit) { fs::copy_file(source, dest, task); }
|
||||
|
||||
task->complete();
|
||||
}
|
||||
|
||||
void tasks::fileoptions::delete_target(sys::Task *task, FileOptionState::TaskData taskData)
|
||||
{
|
||||
if (error::is_null(task)) { return; }
|
||||
|
||||
fslib::Path target = taskData->sourcePath;
|
||||
int64_t journalSpace = taskData->journalSize;
|
||||
|
||||
const bool isDir = fslib::directory_exists(target);
|
||||
bool needsCommit = journalSpace > 0;
|
||||
|
||||
if (isDir) { fslib::delete_directory_recursively(target); }
|
||||
else { fslib::delete_file(target); }
|
||||
|
||||
if (needsCommit) { fslib::commit_data_to_file_system(target.get_device_name()); }
|
||||
|
||||
task->complete();
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "tasks/backup.hpp"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#include "tasks/savecreate.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
#include "ui/PopMessageManager.hpp"
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "config/config.hpp"
|
||||
#include "data/data.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "keyboard.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
|
|
@ -208,7 +208,7 @@ void tasks::titleoptions::extend_save_data(sys::Task *task, TitleOptionState::Ta
|
|||
|
||||
std::array<char, 5> sizeBuffer = {0};
|
||||
FsSaveDataExtraData extraData{};
|
||||
const bool readExtra = fs::read_save_data_extra_info(saveInfo, extraData);
|
||||
const bool readExtra = fs::read_save_extra_data(saveInfo, extraData);
|
||||
|
||||
const int sizeMB = extraData.data_size / SIZE_MB;
|
||||
const char *keyboardHeader = strings::get_by_name(strings::names::KEYBOARD, 8);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include "tasks/useroptions.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs/fs.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "remote/remote.hpp"
|
||||
#include "strings/strings.hpp"
|
||||
#include "stringutil.hpp"
|
||||
|
|
|
|||
|
|
@ -49,17 +49,13 @@ void ui::DialogBox::render(sdl::SharedTexture &target, bool hasFocus)
|
|||
CORNER_HEIGHT);
|
||||
}
|
||||
|
||||
void ui::DialogBox::set_xy(int x, int y)
|
||||
{
|
||||
if (x != DialogBox::NO_SET) { m_x = x; }
|
||||
if (y != DialogBox::NO_SET) { m_y = y; }
|
||||
}
|
||||
void ui::DialogBox::set_x(int x) { m_x = x; }
|
||||
|
||||
void ui::DialogBox::set_width_height(int width, int height)
|
||||
{
|
||||
if (width != DialogBox::NO_SET) { m_width = width; }
|
||||
if (height != DialogBox::NO_SET) { m_height = height; }
|
||||
}
|
||||
void ui::DialogBox::set_y(int y) { m_y = y; }
|
||||
|
||||
void ui::DialogBox::set_width(int width) { m_width = width; }
|
||||
|
||||
void ui::DialogBox::set_height(int height) { m_height = height; }
|
||||
|
||||
void ui::DialogBox::initialize_static_members()
|
||||
{
|
||||
|
|
|
|||
56
source/ui/Frame.cpp
Normal file
56
source/ui/Frame.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include "ui/Frame.hpp"
|
||||
|
||||
#include "graphics/colors.hpp"
|
||||
|
||||
ui::Frame::Frame(int x, int y, int width, int height)
|
||||
: m_x(x)
|
||||
, m_y(y)
|
||||
, m_width(width)
|
||||
, m_height(height)
|
||||
{
|
||||
Frame::initialize_static_members();
|
||||
}
|
||||
|
||||
void ui::Frame::render(sdl::SharedTexture &target, bool hasFocus)
|
||||
{
|
||||
// This is the size of one of the "tiles" of the frame.
|
||||
static constexpr int TILE = 16;
|
||||
|
||||
const int midWidth = m_width - (TILE * 2);
|
||||
const int midHeight = m_height - (TILE * 2);
|
||||
const int rightEdge = (m_x + m_width) - TILE;
|
||||
const int bottomEdge = (m_y + m_height) - TILE;
|
||||
const int textureCorner = TILE * 2;
|
||||
|
||||
// Top.
|
||||
sm_frameCorners->render_part(target, m_x, m_y, 0, 0, TILE, TILE);
|
||||
sm_frameCorners->render_part_stretched(target, TILE, 0, TILE, TILE, m_x + TILE, m_y, midWidth, TILE);
|
||||
sm_frameCorners->render_part(target, rightEdge, m_y, 32, 0, TILE, TILE);
|
||||
|
||||
// Middle
|
||||
sm_frameCorners->render_part_stretched(target, 0, TILE, TILE, TILE, m_x, m_y + TILE, TILE, midHeight);
|
||||
sdl::render_rect_fill(target, m_x + TILE, m_y + TILE, midWidth, midHeight, colors::SLIDE_PANEL_CLEAR);
|
||||
sm_frameCorners->render_part_stretched(target, textureCorner, TILE, TILE, TILE, rightEdge, m_y + TILE, TILE, midHeight);
|
||||
|
||||
// Bottom
|
||||
sm_frameCorners->render_part(target, m_x, bottomEdge, 0, textureCorner, TILE, TILE);
|
||||
sm_frameCorners->render_part_stretched(target, TILE, textureCorner, TILE, TILE, m_x + TILE, bottomEdge, midWidth, TILE);
|
||||
sm_frameCorners->render_part(target, rightEdge, bottomEdge, textureCorner, textureCorner, TILE, TILE);
|
||||
}
|
||||
|
||||
void ui::Frame::set_x(int x) { m_x = x; }
|
||||
|
||||
void ui::Frame::set_y(int y) { m_y = y; }
|
||||
|
||||
void ui::Frame::set_width(int width) { m_width = width; }
|
||||
|
||||
void ui::Frame::set_height(int height) { m_height = height; }
|
||||
|
||||
void ui::Frame::initialize_static_members()
|
||||
{
|
||||
static constexpr std::string_view FRAME_NAME = "FrameCorners";
|
||||
static constexpr const char *FRAME_PATH = "romfs:/Textures/Frame.png";
|
||||
|
||||
if (sm_frameCorners) { return; }
|
||||
sm_frameCorners = sdl::TextureManager::load(FRAME_NAME, FRAME_PATH);
|
||||
}
|
||||
|
|
@ -99,6 +99,10 @@ void ui::Menu::set_selected(int selected)
|
|||
|
||||
void ui::Menu::set_width(int width) { m_width = width; }
|
||||
|
||||
void ui::Menu::set_x(int x) { m_x = x; }
|
||||
|
||||
void ui::Menu::set_y(int y) { m_y = y; }
|
||||
|
||||
void ui::Menu::reset()
|
||||
{
|
||||
m_selected = 0;
|
||||
|
|
@ -106,6 +110,8 @@ void ui::Menu::reset()
|
|||
m_options.clear();
|
||||
}
|
||||
|
||||
bool ui::Menu::is_empty() const { return m_options.empty(); }
|
||||
|
||||
void ui::Menu::update_scroll_text()
|
||||
{
|
||||
const std::string_view text = m_optionScroll->get_text();
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ void ui::PopMessage::update_y(double targetY)
|
|||
m_yMet = true;
|
||||
m_typeTimer.start(5);
|
||||
}
|
||||
m_dialog->set_xy(m_dialog->NO_SET, m_y - 6);
|
||||
m_dialog->set_y(m_y - 6);
|
||||
}
|
||||
|
||||
void ui::PopMessage::update_text_offset()
|
||||
|
|
@ -76,7 +76,7 @@ void ui::PopMessage::update_text_offset()
|
|||
const int dialogX = m_textX - 16;
|
||||
const int dialogWidth = stringWidth + 32;
|
||||
|
||||
m_dialog->set_xy(dialogX, m_dialog->NO_SET);
|
||||
m_dialog->set_width_height(dialogWidth, m_dialog->NO_SET);
|
||||
m_dialog->set_x(dialogX);
|
||||
m_dialog->set_width(dialogWidth);
|
||||
if (m_substrOffset >= messageLength) { m_displayTimer.start(m_ticks); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,9 @@ ui::SlideOutPanel::SlideOutPanel(int width, Side side)
|
|||
|
||||
void ui::SlideOutPanel::update(bool hasFocus)
|
||||
{
|
||||
const bool openingFromLeft = !m_isOpen && m_side == Side::Left && m_x < m_targetX;
|
||||
const bool openingFromRight = !m_isOpen && m_side == Side::Right && m_x > m_targetX;
|
||||
if (hasFocus && SlideOutPanel::is_hidden()) { SlideOutPanel::unhide(); }
|
||||
|
||||
if (openingFromLeft) { SlideOutPanel::slide_out_left(); }
|
||||
else if (openingFromRight) { SlideOutPanel::slide_out_right(); }
|
||||
slide_out();
|
||||
|
||||
if (m_isOpen)
|
||||
{
|
||||
|
|
@ -37,6 +35,8 @@ void ui::SlideOutPanel::update(bool hasFocus)
|
|||
}
|
||||
}
|
||||
|
||||
void ui::SlideOutPanel::sub_update() { SlideOutPanel::close_hide_panel(); }
|
||||
|
||||
void ui::SlideOutPanel::render(sdl::SharedTexture &target, bool hasFocus)
|
||||
{
|
||||
for (auto ¤tElement : m_elements) { currentElement->render(m_renderTarget, hasFocus); }
|
||||
|
|
@ -55,27 +55,39 @@ void ui::SlideOutPanel::reset()
|
|||
|
||||
void ui::SlideOutPanel::close() { m_closePanel = true; }
|
||||
|
||||
void ui::SlideOutPanel::hide() { m_hidePanel = true; }
|
||||
|
||||
void ui::SlideOutPanel::unhide() { m_hidePanel = false; }
|
||||
|
||||
bool ui::SlideOutPanel::is_open() const { return m_isOpen; }
|
||||
|
||||
bool ui::SlideOutPanel::is_closed()
|
||||
{
|
||||
// I'm assuming this is going to be called, waiting for the panel to close so.
|
||||
const double scaling = config::get_animation_scaling();
|
||||
const bool closeToLeft = m_closePanel && m_side == Side::Left && m_x > -m_width;
|
||||
const bool closeToRight = m_closePanel && m_side == Side::Right && m_x < SCREEN_WIDTH;
|
||||
if (closeToLeft) { m_x += -(m_width - m_x) / scaling; }
|
||||
else if (closeToRight) { m_x += m_x / scaling; }
|
||||
|
||||
close_hide_panel();
|
||||
const bool closed = m_side == Side::Left ? m_x <= -m_width : m_x >= SCREEN_WIDTH;
|
||||
return m_closePanel && closed;
|
||||
}
|
||||
|
||||
bool ui::SlideOutPanel::is_hidden() const { return m_hidePanel; }
|
||||
|
||||
void ui::SlideOutPanel::push_new_element(std::shared_ptr<ui::Element> newElement) { m_elements.push_back(newElement); }
|
||||
|
||||
void ui::SlideOutPanel::clear_elements() { m_elements.clear(); }
|
||||
|
||||
sdl::SharedTexture &ui::SlideOutPanel::get_target() { return m_renderTarget; }
|
||||
|
||||
void ui::SlideOutPanel::slide_out()
|
||||
{
|
||||
const bool needsSlideOut = !m_isOpen && !m_closePanel && !m_hidePanel;
|
||||
if (!needsSlideOut) { return; }
|
||||
|
||||
const bool slideRight = m_side == SlideOutPanel::Side::Left && m_x < 0;
|
||||
const bool slideLeft = m_side == SlideOutPanel::Side::Right && m_x > SCREEN_WIDTH - m_width;
|
||||
|
||||
if (slideRight) { SlideOutPanel::slide_out_left(); }
|
||||
else if (slideLeft) { SlideOutPanel::slide_out_right(); }
|
||||
}
|
||||
|
||||
void ui::SlideOutPanel::slide_out_left()
|
||||
{
|
||||
const double scaling = config::get_animation_scaling();
|
||||
|
|
@ -106,3 +118,16 @@ void ui::SlideOutPanel::slide_out_right()
|
|||
m_isOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ui::SlideOutPanel::close_hide_panel()
|
||||
{
|
||||
const double scaling = config::get_animation_scaling();
|
||||
const bool closeHide = m_closePanel || m_hidePanel;
|
||||
const bool closeToLeft = closeHide && m_side == Side::Left && m_x > -m_width;
|
||||
const bool closeToRight = closeHide && m_side == Side::Right && m_x < SCREEN_WIDTH;
|
||||
if (closeToLeft) { m_x += -((m_width - m_x) / scaling); }
|
||||
else if (closeToRight) { m_x += m_x / scaling; }
|
||||
|
||||
const bool closedOrHidden = (m_x <= -m_width) || (m_x >= SCREEN_WIDTH);
|
||||
if (closedOrHidden) { m_isOpen = false; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#include "ui/TitleView.hpp"
|
||||
|
||||
#include "config/config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "graphics/colors.hpp"
|
||||
#include "input.hpp"
|
||||
#include "logging/error.hpp"
|
||||
#include "logging/logger.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user