swkdb: add support for setting the header. save: add support for setting the name for the save file.
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace sphaira::swkbd {
|
namespace sphaira::swkbd {
|
||||||
|
|
||||||
Result ShowText(std::string& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = PATH_MAX);
|
Result ShowText(std::string& out, const char* header = nullptr, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = PATH_MAX);
|
||||||
Result ShowNumPad(s64& out, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = PATH_MAX);
|
Result ShowNumPad(s64& out, const char* header = nullptr, const char* guide = nullptr, const char* initial = nullptr, s64 len_min = -1, s64 len_max = PATH_MAX);
|
||||||
|
|
||||||
} // namespace sphaira::swkbd
|
} // namespace sphaira::swkbd
|
||||||
|
|||||||
@@ -12,6 +12,14 @@
|
|||||||
|
|
||||||
namespace sphaira::ui::menu::save {
|
namespace sphaira::ui::menu::save {
|
||||||
|
|
||||||
|
enum BackupFlag {
|
||||||
|
BackupFlag_None = 0,
|
||||||
|
// option to allow the user to set the save file name.
|
||||||
|
BackupFlag_SetName = 1 << 0,
|
||||||
|
// set if this is a auto backup (on restore).
|
||||||
|
BackupFlag_IsAuto = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct Entry final : FsSaveDataInfo {
|
struct Entry final : FsSaveDataInfo {
|
||||||
NacpLanguageEntry lang{};
|
NacpLanguageEntry lang{};
|
||||||
int image{};
|
int image{};
|
||||||
@@ -82,13 +90,13 @@ private:
|
|||||||
|
|
||||||
void DisplayOptions();
|
void DisplayOptions();
|
||||||
|
|
||||||
void BackupSaves(std::vector<std::reference_wrapper<Entry>>& entries);
|
void BackupSaves(std::vector<std::reference_wrapper<Entry>>& entries, u32 flags);
|
||||||
void RestoreSave();
|
void RestoreSave();
|
||||||
|
|
||||||
auto BuildSavePath(const Entry& e, bool is_auto) const -> fs::FsPath;
|
auto BuildSavePath(const Entry& e, u32 flags) const -> fs::FsPath;
|
||||||
Result RestoreSaveInternal(ProgressBox* pbox, const Entry& e, const fs::FsPath& path) const;
|
Result RestoreSaveInternal(ProgressBox* pbox, const Entry& e, const fs::FsPath& path);
|
||||||
Result BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, Entry& e, bool compressed, bool is_auto = false) const;
|
Result BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, Entry& e, u32 flags);
|
||||||
Result BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, std::span<const std::reference_wrapper<Entry>> entries, bool compressed, bool is_auto = false) const;
|
Result BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, std::span<const std::reference_wrapper<Entry>> entries, u32 flags);
|
||||||
|
|
||||||
Result MountSaveFs();
|
Result MountSaveFs();
|
||||||
|
|
||||||
|
|||||||
@@ -188,9 +188,9 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// uses normal keyboard.
|
// uses normal keyboard.
|
||||||
explicit SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide = {}, s64 len_min = -1, s64 len_max = PATH_MAX, const std::string& info = "", const Callback& callback = nullptr);
|
explicit SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& header = {}, const std::string& guide = {}, s64 len_min = -1, s64 len_max = PATH_MAX, const std::string& info = "", const Callback& callback = nullptr);
|
||||||
// uses numpad.
|
// uses numpad.
|
||||||
explicit SidebarEntryTextInput(const std::string& title, s64 value, const std::string& guide = {}, s64 len_min = -1, s64 len_max = PATH_MAX, const std::string& info = "", const Callback& callback = nullptr);
|
explicit SidebarEntryTextInput(const std::string& title, s64 value, const std::string& header = {}, const std::string& guide = {}, s64 len_min = -1, s64 len_max = PATH_MAX, const std::string& info = "", const Callback& callback = nullptr);
|
||||||
|
|
||||||
auto GetNumValue() const -> s64 {
|
auto GetNumValue() const -> s64 {
|
||||||
return std::stoul(GetValue());
|
return std::stoul(GetValue());
|
||||||
@@ -200,6 +200,7 @@ public:
|
|||||||
SetValue(std::to_string(value));
|
SetValue(std::to_string(value));
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
const std::string m_header;
|
||||||
const std::string m_guide;
|
const std::string m_guide;
|
||||||
const s64 m_len_min;
|
const s64 m_len_min;
|
||||||
const s64 m_len_max;
|
const s64 m_len_max;
|
||||||
|
|||||||
@@ -2338,7 +2338,7 @@ void App::DisplayFtpOptions(bool left_side) {
|
|||||||
}, "Enable FTP server to run in the background."_i18n);
|
}, "Enable FTP server to run in the background."_i18n);
|
||||||
|
|
||||||
options->Add<ui::SidebarEntryTextInput>(
|
options->Add<ui::SidebarEntryTextInput>(
|
||||||
"Port", App::GetApp()->m_ftp_port.Get(), "Port number", 1, 5,
|
"Port", App::GetApp()->m_ftp_port.Get(), "", "", 1, 5,
|
||||||
"Opens the FTP server on this port."_i18n,
|
"Opens the FTP server on this port."_i18n,
|
||||||
[](auto* input){
|
[](auto* input){
|
||||||
App::GetApp()->m_ftp_port.Set(input->GetNumValue());
|
App::GetApp()->m_ftp_port.Set(input->GetNumValue());
|
||||||
@@ -2352,7 +2352,7 @@ void App::DisplayFtpOptions(bool left_side) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
options->Add<ui::SidebarEntryTextInput>(
|
options->Add<ui::SidebarEntryTextInput>(
|
||||||
"User", App::GetApp()->m_ftp_user.Get(), "Username", -1, 64,
|
"User", App::GetApp()->m_ftp_user.Get(), "", "", -1, 64,
|
||||||
"Sets the username, must be set if anon is disabled."_i18n,
|
"Sets the username, must be set if anon is disabled."_i18n,
|
||||||
[](auto* input){
|
[](auto* input){
|
||||||
App::GetApp()->m_ftp_user.Set(input->GetValue());
|
App::GetApp()->m_ftp_user.Set(input->GetValue());
|
||||||
@@ -2360,7 +2360,7 @@ void App::DisplayFtpOptions(bool left_side) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
options->Add<ui::SidebarEntryTextInput>(
|
options->Add<ui::SidebarEntryTextInput>(
|
||||||
"Pass", App::GetApp()->m_ftp_pass.Get(), "Password", -1, 64,
|
"Pass", App::GetApp()->m_ftp_pass.Get(), "", "", -1, 64,
|
||||||
"Sets the password, must be set if anon is disabled."_i18n,
|
"Sets the password, must be set if anon is disabled."_i18n,
|
||||||
[](auto* input){
|
[](auto* input){
|
||||||
App::GetApp()->m_ftp_pass.Set(input->GetValue());
|
App::GetApp()->m_ftp_pass.Set(input->GetValue());
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ struct Config {
|
|||||||
bool numpad{};
|
bool numpad{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Result ShowInternal(Config& cfg, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
Result ShowInternal(Config& cfg, const char* header, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
||||||
SwkbdConfig c;
|
SwkbdConfig c;
|
||||||
R_TRY(swkbdCreate(&c, 0));
|
R_TRY(swkbdCreate(&c, 0));
|
||||||
swkbdConfigMakePresetDefault(&c);
|
swkbdConfigMakePresetDefault(&c);
|
||||||
@@ -20,7 +20,17 @@ Result ShowInternal(Config& cfg, const char* guide, const char* initial, s64 len
|
|||||||
swkbdConfigSetType(&c, SwkbdType_NumPad);
|
swkbdConfigSetType(&c, SwkbdType_NumPad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only works if len_max <= 32.
|
||||||
|
if (header) {
|
||||||
|
swkbdConfigSetHeaderText(&c, header);
|
||||||
|
}
|
||||||
|
|
||||||
if (guide) {
|
if (guide) {
|
||||||
|
// only works if len_max <= 32.
|
||||||
|
if (header) {
|
||||||
|
swkbdConfigSetSubText(&c, guide);
|
||||||
|
}
|
||||||
|
|
||||||
swkbdConfigSetGuideText(&c, guide);
|
swkbdConfigSetGuideText(&c, guide);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,17 +51,17 @@ Result ShowInternal(Config& cfg, const char* guide, const char* initial, s64 len
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Result ShowText(std::string& out, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
Result ShowText(std::string& out, const char* header, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
||||||
Config cfg{};
|
Config cfg{};
|
||||||
R_TRY(ShowInternal(cfg, guide, initial, len_min, len_max));
|
R_TRY(ShowInternal(cfg, header, guide, initial, len_min, len_max));
|
||||||
out = cfg.out_text;
|
out = cfg.out_text;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ShowNumPad(s64& out, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
Result ShowNumPad(s64& out, const char* header, const char* guide, const char* initial, s64 len_min, s64 len_max) {
|
||||||
Config cfg{};
|
Config cfg{};
|
||||||
cfg.numpad = true;
|
cfg.numpad = true;
|
||||||
R_TRY(ShowInternal(cfg, guide, initial, len_min, len_max));
|
R_TRY(ShowInternal(cfg, header, guide, initial, len_min, len_max));
|
||||||
out = std::atoll(cfg.out_text);
|
out = std::atoll(cfg.out_text);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -599,7 +599,8 @@ EntryMenu::EntryMenu(Entry& entry, const LazyImage& default_icon, Menu& menu)
|
|||||||
|
|
||||||
options->Add<SidebarEntryCallback>("Leave Feedback"_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Leave Feedback"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out)) && !out.empty()) {
|
std::string header = "Leave feedback for " + m_entry.title;
|
||||||
|
if (R_SUCCEEDED(swkbd::ShowText(out, header.c_str())) && !out.empty()) {
|
||||||
const auto post = "name=" "switch_user" "&package=" + m_entry.name + "&message=" + out;
|
const auto post = "name=" "switch_user" "&package=" + m_entry.name + "&message=" + out;
|
||||||
const auto file = BuildFeedbackCachePath(m_entry);
|
const auto file = BuildFeedbackCachePath(m_entry);
|
||||||
|
|
||||||
@@ -970,7 +971,7 @@ Menu::Menu(u32 flags) : grid::Menu{"AppStore"_i18n, flags} {
|
|||||||
|
|
||||||
options->Add<SidebarEntryCallback>("Search"_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Search"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out)) && !out.empty()) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, "Search for app")) && !out.empty()) {
|
||||||
SetSearch(out);
|
SetSearch(out);
|
||||||
log_write("got %s\n", out.c_str());
|
log_write("got %s\n", out.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,17 +315,17 @@ ForwarderForm::ForwarderForm(const FileAssocEntry& assoc, const RomDatabaseIndex
|
|||||||
const auto icon = m_assoc.path;
|
const auto icon = m_assoc.path;
|
||||||
|
|
||||||
m_name = this->Add<SidebarEntryTextInput>(
|
m_name = this->Add<SidebarEntryTextInput>(
|
||||||
"Name", name, "", -1, sizeof(NacpLanguageEntry::name) - 1,
|
"Name", name, "", "", -1, sizeof(NacpLanguageEntry::name) - 1,
|
||||||
"Set the name of the application"_i18n
|
"Set the name of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
m_author = this->Add<SidebarEntryTextInput>(
|
m_author = this->Add<SidebarEntryTextInput>(
|
||||||
"Author", author, "", -1, sizeof(NacpLanguageEntry::author) - 1,
|
"Author", author, "", "", -1, sizeof(NacpLanguageEntry::author) - 1,
|
||||||
"Set the author of the application"_i18n
|
"Set the author of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
m_version = this->Add<SidebarEntryTextInput>(
|
m_version = this->Add<SidebarEntryTextInput>(
|
||||||
"Version", version, "", -1, sizeof(NacpStruct::display_version) - 1,
|
"Version", version, "", "", -1, sizeof(NacpStruct::display_version) - 1,
|
||||||
"Set the display version of the application"_i18n
|
"Set the display version of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1711,7 +1711,8 @@ void FsView::DisplayOptions() {
|
|||||||
std::string out;
|
std::string out;
|
||||||
const auto& entry = GetEntry();
|
const auto& entry = GetEntry();
|
||||||
const auto name = entry.GetName();
|
const auto name = entry.GetName();
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Set New File Name"_i18n.c_str(), name.c_str())) && !out.empty() && out != name) {
|
const auto header = "Set new name"_i18n;
|
||||||
|
if (R_SUCCEEDED(swkbd::ShowText(out, header.c_str(), header.c_str(), name.c_str())) && !out.empty() && out != name) {
|
||||||
App::PopToMenu();
|
App::PopToMenu();
|
||||||
|
|
||||||
const auto src_path = GetNewPath(entry);
|
const auto src_path = GetNewPath(entry);
|
||||||
@@ -1804,7 +1805,7 @@ void FsView::DisplayOptions() {
|
|||||||
|
|
||||||
options->Add<SidebarEntryCallback>("Extract to..."_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Extract to..."_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Enter the path to the folder to extract into", fs::AppendPath(m_path, ""))) && !out.empty()) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, "Extract path", "Enter the path to the folder to extract into", fs::AppendPath(m_path, ""))) && !out.empty()) {
|
||||||
UnzipFiles(out);
|
UnzipFiles(out);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1822,7 +1823,7 @@ void FsView::DisplayOptions() {
|
|||||||
|
|
||||||
options->Add<SidebarEntryCallback>("Compress to..."_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Compress to..."_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Enter the path to the folder to extract into", m_path)) && !out.empty()) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, "Compress path", "Enter the path to the folder to compress into", m_path)) && !out.empty()) {
|
||||||
ZipFiles(out);
|
ZipFiles(out);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1842,7 +1843,8 @@ void FsView::DisplayAdvancedOptions() {
|
|||||||
if (!m_fs_entry.IsReadOnly()) {
|
if (!m_fs_entry.IsReadOnly()) {
|
||||||
options->Add<SidebarEntryCallback>("Create File"_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Create File"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Set File Name"_i18n.c_str(), fs::AppendPath(m_path, ""))) && !out.empty()) {
|
const auto header = "Set File Name"_i18n;
|
||||||
|
if (R_SUCCEEDED(swkbd::ShowText(out, header.c_str(), header.c_str(), fs::AppendPath(m_path, ""))) && !out.empty()) {
|
||||||
App::PopToMenu();
|
App::PopToMenu();
|
||||||
|
|
||||||
fs::FsPath full_path;
|
fs::FsPath full_path;
|
||||||
@@ -1864,7 +1866,8 @@ void FsView::DisplayAdvancedOptions() {
|
|||||||
|
|
||||||
options->Add<SidebarEntryCallback>("Create Folder"_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Create Folder"_i18n, [this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, "Set Folder Name"_i18n.c_str(), fs::AppendPath(m_path, ""))) && !out.empty()) {
|
const auto header = "Set Folder Name"_i18n;
|
||||||
|
if (R_SUCCEEDED(swkbd::ShowText(out, header.c_str(), header.c_str(), fs::AppendPath(m_path, ""))) && !out.empty()) {
|
||||||
App::PopToMenu();
|
App::PopToMenu();
|
||||||
|
|
||||||
fs::FsPath full_path;
|
fs::FsPath full_path;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "threaded_file_transfer.hpp"
|
#include "threaded_file_transfer.hpp"
|
||||||
#include "minizip_helper.hpp"
|
#include "minizip_helper.hpp"
|
||||||
#include "dumper.hpp"
|
#include "dumper.hpp"
|
||||||
|
#include "swkbd.hpp"
|
||||||
|
|
||||||
#include "utils/devoptab.hpp"
|
#include "utils/devoptab.hpp"
|
||||||
|
|
||||||
@@ -689,13 +690,38 @@ void Menu::DisplayOptions() {
|
|||||||
entries.emplace_back(m_entries[m_index]);
|
entries.emplace_back(m_entries[m_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupSaves(entries);
|
BackupSaves(entries, BackupFlag_None);
|
||||||
}, true);
|
}, true,
|
||||||
|
"Backup the selected save(s) to a location of your choice."_i18n
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!m_selected_count || m_selected_count == 1) {
|
||||||
|
options->Add<SidebarEntryCallback>("Backup to..."_i18n, [this](){
|
||||||
|
std::vector<std::reference_wrapper<Entry>> entries;
|
||||||
|
if (m_selected_count) {
|
||||||
|
for (auto& e : m_entries) {
|
||||||
|
if (e.selected) {
|
||||||
|
entries.emplace_back(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entries.emplace_back(m_entries[m_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
BackupSaves(entries, BackupFlag_SetName);
|
||||||
|
}, true,
|
||||||
|
"Backup the selected save(s) to a location of your choice, and set the name of the backup."_i18n
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_entries[m_index].save_data_type == FsSaveDataType_Account || m_entries[m_index].save_data_type == FsSaveDataType_Bcat) {
|
if (m_entries[m_index].save_data_type == FsSaveDataType_Account || m_entries[m_index].save_data_type == FsSaveDataType_Bcat) {
|
||||||
options->Add<SidebarEntryCallback>("Restore"_i18n, [this](){
|
options->Add<SidebarEntryCallback>("Restore"_i18n, [this](){
|
||||||
RestoreSave();
|
RestoreSave();
|
||||||
}, true);
|
}, true,
|
||||||
|
"Restore the save for the current title.\n"
|
||||||
|
"if \"Auto backup\" is enabled, the save will first be backed up and then restored. "
|
||||||
|
"Saves that are auto backed up will have \"Auto\" in their name."_i18n
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,18 +731,21 @@ void Menu::DisplayOptions() {
|
|||||||
|
|
||||||
options->Add<SidebarEntryBool>("Auto backup on restore"_i18n, m_auto_backup_on_restore.Get(), [this](bool& v_out){
|
options->Add<SidebarEntryBool>("Auto backup on restore"_i18n, m_auto_backup_on_restore.Get(), [this](bool& v_out){
|
||||||
m_auto_backup_on_restore.Set(v_out);
|
m_auto_backup_on_restore.Set(v_out);
|
||||||
});
|
}, "If enabled, when restoring a save, the current save will first be backed up."_i18n);
|
||||||
|
|
||||||
options->Add<SidebarEntryBool>("Compress backup"_i18n, m_compress_save_backup.Get(), [this](bool& v_out){
|
options->Add<SidebarEntryBool>("Compress backup"_i18n, m_compress_save_backup.Get(), [this](bool& v_out){
|
||||||
m_compress_save_backup.Set(v_out);
|
m_compress_save_backup.Set(v_out);
|
||||||
});
|
}, "If enabled, backups will be compressed to a zip file.\n\n"
|
||||||
|
"NOTE: Disabling this option does not disable the zip file, it only disables compressing "
|
||||||
|
"the files stored in the zip.\n"
|
||||||
|
"Disabling will result in a much faster backup, at the cost of the file size."_i18n);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::BackupSaves(std::vector<std::reference_wrapper<Entry>>& entries) {
|
void Menu::BackupSaves(std::vector<std::reference_wrapper<Entry>>& entries, u32 flags) {
|
||||||
dump::DumpGetLocation("Select backup location"_i18n, dump::DumpLocationFlag_SdCard|dump::DumpLocationFlag_Stdio|dump::DumpLocationFlag_Usb, [this, entries](const dump::DumpLocation& location){
|
dump::DumpGetLocation("Select backup location"_i18n, dump::DumpLocationFlag_SdCard|dump::DumpLocationFlag_Stdio|dump::DumpLocationFlag_Usb, [this, entries, flags](const dump::DumpLocation& location){
|
||||||
App::Push<ProgressBox>(0, "Backup"_i18n, "", [this, entries, location](auto pbox) -> Result {
|
App::Push<ProgressBox>(0, "Backup"_i18n, "", [this, entries, location, flags](auto pbox) -> Result {
|
||||||
return BackupSaveInternal(pbox, location, entries, m_compress_save_backup.Get());
|
return BackupSaveInternal(pbox, location, entries, flags);
|
||||||
}, [](Result rc){
|
}, [](Result rc){
|
||||||
App::PushErrorBox(rc, "Backup failed!"_i18n);
|
App::PushErrorBox(rc, "Backup failed!"_i18n);
|
||||||
|
|
||||||
@@ -794,7 +823,7 @@ void Menu::RestoreSave() {
|
|||||||
|
|
||||||
if (m_auto_backup_on_restore.Get()) {
|
if (m_auto_backup_on_restore.Get()) {
|
||||||
pbox->SetActionName("Auto backup"_i18n);
|
pbox->SetActionName("Auto backup"_i18n);
|
||||||
R_TRY(BackupSaveInternal(pbox, location, m_entries[m_index], m_compress_save_backup.Get(), true));
|
R_TRY(BackupSaveInternal(pbox, location, m_entries[m_index], BackupFlag_IsAuto));
|
||||||
}
|
}
|
||||||
|
|
||||||
pbox->SetActionName("Restore"_i18n);
|
pbox->SetActionName("Restore"_i18n);
|
||||||
@@ -814,7 +843,7 @@ void Menu::RestoreSave() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Menu::BuildSavePath(const Entry& e, bool is_auto) const -> fs::FsPath {
|
auto Menu::BuildSavePath(const Entry& e, u32 flags) const -> fs::FsPath {
|
||||||
const auto t = std::time(NULL);
|
const auto t = std::time(NULL);
|
||||||
const auto tm = std::localtime(&t);
|
const auto tm = std::localtime(&t);
|
||||||
const auto base = BuildSaveBasePath(e);
|
const auto base = BuildSaveBasePath(e);
|
||||||
@@ -822,27 +851,39 @@ auto Menu::BuildSavePath(const Entry& e, bool is_auto) const -> fs::FsPath {
|
|||||||
char time[64];
|
char time[64];
|
||||||
std::snprintf(time, sizeof(time), "%u.%02u.%02u @ %02u.%02u.%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
std::snprintf(time, sizeof(time), "%u.%02u.%02u @ %02u.%02u.%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
|
|
||||||
fs::FsPath path;
|
fs::FsPath name;
|
||||||
if (e.save_data_type == FsSaveDataType_Account) {
|
if (e.save_data_type == FsSaveDataType_Account) {
|
||||||
const auto acc = m_accounts[m_account_index];
|
const auto acc = m_accounts[m_account_index];
|
||||||
|
|
||||||
fs::FsPath name_buf;
|
fs::FsPath name_buf;
|
||||||
if (is_auto) {
|
if (flags & BackupFlag_IsAuto) {
|
||||||
std::snprintf(name_buf, sizeof(name_buf), "AUTO - %s", acc.nickname);
|
std::snprintf(name_buf, sizeof(name_buf), "AUTO - %s", acc.nickname);
|
||||||
} else {
|
} else {
|
||||||
std::snprintf(name_buf, sizeof(name_buf), "%s", acc.nickname);
|
std::snprintf(name_buf, sizeof(name_buf), "%s", acc.nickname);
|
||||||
}
|
}
|
||||||
|
|
||||||
title::utilsReplaceIllegalCharacters(name_buf, true);
|
title::utilsReplaceIllegalCharacters(name_buf, true);
|
||||||
std::snprintf(path, sizeof(path), "%s/%s - %s.zip", base.s, name_buf.s, time);
|
std::snprintf(name, sizeof(name), "%s - %s.zip", name_buf.s, time);
|
||||||
} else {
|
} else {
|
||||||
std::snprintf(path, sizeof(path), "%s/%s.zip", base.s, time);
|
std::snprintf(name, sizeof(name), "%s.zip", time);
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
if (flags & BackupFlag_SetName) {
|
||||||
|
std::string out;
|
||||||
|
while (out.empty()) {
|
||||||
|
const auto header = "Set name for "_i18n + e.GetName();
|
||||||
|
if (R_FAILED(swkbd::ShowText(out, header.c_str(), "Set backup name", name, 1, 128))) {
|
||||||
|
out.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs::AppendPath(base, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Menu::RestoreSaveInternal(ProgressBox* pbox, const Entry& e, const fs::FsPath& path) const {
|
Result Menu::RestoreSaveInternal(ProgressBox* pbox, const Entry& e, const fs::FsPath& path) {
|
||||||
pbox->SetTitle(e.GetName());
|
pbox->SetTitle(e.GetName());
|
||||||
if (e.image) {
|
if (e.image) {
|
||||||
pbox->SetImage(e.image);
|
pbox->SetImage(e.image);
|
||||||
@@ -960,14 +1001,15 @@ Result Menu::RestoreSaveInternal(ProgressBox* pbox, const Entry& e, const fs::Fs
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Menu::BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, std::span<const std::reference_wrapper<Entry>> entries, bool compressed, bool is_auto) const {
|
Result Menu::BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, std::span<const std::reference_wrapper<Entry>> entries, u32 flags) {
|
||||||
std::vector<fs::FsPath> paths;
|
std::vector<fs::FsPath> paths;
|
||||||
for (auto& e : entries) {
|
for (auto& e : entries) {
|
||||||
// ensure that we have title name and icon loaded.
|
// ensure that we have title name and icon loaded.
|
||||||
LoadControlEntry(e);
|
LoadControlEntry(e);
|
||||||
paths.emplace_back(BuildSavePath(e, is_auto));
|
paths.emplace_back(BuildSavePath(e, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto compressed = m_compress_save_backup.Get();
|
||||||
auto source = std::make_shared<DumpSource>(entries, paths);
|
auto source = std::make_shared<DumpSource>(entries, paths);
|
||||||
|
|
||||||
return dump::Dump(pbox, source, location, paths, [&](ui::ProgressBox* pbox, dump::BaseSource* _source, dump::WriteSource* writer, const fs::FsPath& path) -> Result {
|
return dump::Dump(pbox, source, location, paths, [&](ui::ProgressBox* pbox, dump::BaseSource* _source, dump::WriteSource* writer, const fs::FsPath& path) -> Result {
|
||||||
@@ -1116,11 +1158,11 @@ Result Menu::BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& loc
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Menu::BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, Entry& e, bool compressed, bool is_auto) const {
|
Result Menu::BackupSaveInternal(ProgressBox* pbox, const dump::DumpLocation& location, Entry& e, u32 flags) {
|
||||||
std::vector<std::reference_wrapper<Entry>> entries;
|
std::vector<std::reference_wrapper<Entry>> entries;
|
||||||
entries.emplace_back(e);
|
entries.emplace_back(e);
|
||||||
|
|
||||||
return BackupSaveInternal(pbox, location, entries, compressed, is_auto);
|
return BackupSaveInternal(pbox, location, entries, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Menu::MountSaveFs() {
|
Result Menu::MountSaveFs() {
|
||||||
|
|||||||
@@ -309,16 +309,17 @@ void SidebarEntryTextBase::Draw(NVGcontext* vg, Theme* theme, const Vec4& root_p
|
|||||||
SidebarEntryBase::DrawEntry(vg, theme, m_title, m_value, true);
|
SidebarEntryBase::DrawEntry(vg, theme, m_title, m_value, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& guide, s64 len_min, s64 len_max, const std::string& info, const Callback& callback)
|
SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, const std::string& value, const std::string& header, const std::string& guide, s64 len_min, s64 len_max, const std::string& info, const Callback& callback)
|
||||||
: SidebarEntryTextBase{title, value, {}, info}
|
: SidebarEntryTextBase{title, value, {}, info}
|
||||||
, m_guide{guide}
|
, m_header{header.empty() ? title : header}
|
||||||
|
, m_guide{guide.empty() ? title : guide}
|
||||||
, m_len_min{len_min}
|
, m_len_min{len_min}
|
||||||
, m_len_max{len_max}
|
, m_len_max{len_max}
|
||||||
, m_callback{callback} {
|
, m_callback{callback} {
|
||||||
|
|
||||||
SetCallback([this](){
|
SetCallback([this](){
|
||||||
std::string out;
|
std::string out;
|
||||||
if (R_SUCCEEDED(swkbd::ShowText(out, m_guide.c_str(), GetValue().c_str(), m_len_min, m_len_max))) {
|
if (R_SUCCEEDED(swkbd::ShowText(out, m_header.c_str(), m_guide.c_str(), GetValue().c_str(), m_len_min, m_len_max))) {
|
||||||
SetValue(out);
|
SetValue(out);
|
||||||
|
|
||||||
if (m_callback) {
|
if (m_callback) {
|
||||||
@@ -328,11 +329,11 @@ SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, const std
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, s64 value, const std::string& guide, s64 len_min, s64 len_max, const std::string& info, const Callback& callback)
|
SidebarEntryTextInput::SidebarEntryTextInput(const std::string& title, s64 value, const std::string& header, const std::string& guide, s64 len_min, s64 len_max, const std::string& info, const Callback& callback)
|
||||||
: SidebarEntryTextInput{title, std::to_string(value), guide, len_min, len_max, info, callback} {
|
: SidebarEntryTextInput{title, std::to_string(value), header, guide, len_min, len_max, info, callback} {
|
||||||
SetCallback([this](){
|
SetCallback([this](){
|
||||||
s64 out = std::stoul(GetValue());
|
s64 out = std::stoul(GetValue());
|
||||||
if (R_SUCCEEDED(swkbd::ShowNumPad(out, m_guide.c_str(), GetValue().c_str(), m_len_min, m_len_max))) {
|
if (R_SUCCEEDED(swkbd::ShowNumPad(out, m_header.c_str(), m_guide.c_str(), GetValue().c_str(), m_len_min, m_len_max))) {
|
||||||
SetValue(std::to_string(out));
|
SetValue(std::to_string(out));
|
||||||
|
|
||||||
if (m_callback) {
|
if (m_callback) {
|
||||||
|
|||||||
@@ -167,17 +167,17 @@ void DevoptabForm::SetupButtons(bool type_change) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_name = this->Add<SidebarEntryTextInput>(
|
m_name = this->Add<SidebarEntryTextInput>(
|
||||||
"Name", m_config.name, "", -1, 32,
|
"Name", m_config.name, "", "", -1, 32,
|
||||||
"Set the name of the application"_i18n
|
"Set the name of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
m_url = this->Add<SidebarEntryTextInput>(
|
m_url = this->Add<SidebarEntryTextInput>(
|
||||||
"URL", m_config.url, "", -1, PATH_MAX,
|
"URL", m_config.url, "", "", -1, PATH_MAX,
|
||||||
"Set the URL of the application"_i18n
|
"Set the URL of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
m_port = this->Add<SidebarEntryTextInput>(
|
m_port = this->Add<SidebarEntryTextInput>(
|
||||||
"Port", m_config.port, "Port number", 1, 5,
|
"Port", m_config.port, "", "", 1, 5,
|
||||||
"Optional: Set the port of the server. If left empty, the default port for the protocol will be used."_i18n
|
"Optional: Set the port of the server. If left empty, the default port for the protocol will be used."_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -189,17 +189,17 @@ void DevoptabForm::SetupButtons(bool type_change) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_user = this->Add<SidebarEntryTextInput>(
|
m_user = this->Add<SidebarEntryTextInput>(
|
||||||
"User", m_config.user, "", -1, PATH_MAX,
|
"User", m_config.user, "", "", -1, PATH_MAX,
|
||||||
"Optional: Set the username of the application"_i18n
|
"Optional: Set the username of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
m_pass = this->Add<SidebarEntryTextInput>(
|
m_pass = this->Add<SidebarEntryTextInput>(
|
||||||
"Pass", m_config.pass, "", -1, PATH_MAX,
|
"Pass", m_config.pass, "", "", -1, PATH_MAX,
|
||||||
"Optional: Set the password of the application"_i18n
|
"Optional: Set the password of the application"_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
m_dump_path = this->Add<SidebarEntryTextInput>(
|
m_dump_path = this->Add<SidebarEntryTextInput>(
|
||||||
"Dump path", m_config.dump_path, "", -1, PATH_MAX,
|
"Dump path", m_config.dump_path, "", "", -1, PATH_MAX,
|
||||||
"Optional: Set the dump path used when exporting games and saves."_i18n
|
"Optional: Set the dump path used when exporting games and saves."_i18n
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user