add support for finding daybreak in non-standard paths (#62)
This commit is contained in:
@@ -76,4 +76,10 @@ auto nro_add_arg_file(std::string arg) -> std::string;
|
||||
// strips sdmc:
|
||||
auto nro_normalise_path(const std::string& p) -> std::string;
|
||||
|
||||
// helpers to find nro entry, will be made methods soon once i convert vector into a struct.
|
||||
auto nro_find(std::span<const NroEntry> array, std::string_view name, std::string_view author, const fs::FsPath& path) -> std::optional<NroEntry>;
|
||||
auto nro_find_name(std::span<const NroEntry> array, std::string_view name) -> std::optional<NroEntry>;
|
||||
auto nro_find_author(std::span<const NroEntry> array, std::string_view author) -> std::optional<NroEntry>;
|
||||
auto nro_find_path(std::span<const NroEntry> array, const fs::FsPath& path) -> std::optional<NroEntry>;
|
||||
|
||||
} // namespace sphaira
|
||||
|
||||
@@ -203,6 +203,7 @@ private:
|
||||
void OnDeleteCallback();
|
||||
void OnPasteCallback();
|
||||
void OnRenameCallback();
|
||||
auto CheckIfUpdateFolder() -> Result;
|
||||
|
||||
private:
|
||||
static constexpr inline const char* INI_SECTION = "filebrowser";
|
||||
@@ -215,6 +216,8 @@ private:
|
||||
std::vector<u32> m_entries_index_search; // files found via search
|
||||
std::span<u32> m_entries_current;
|
||||
|
||||
std::optional<fs::FsPath> m_daybreak_path;
|
||||
|
||||
// search options
|
||||
// show files [X]
|
||||
// show folders [X]
|
||||
|
||||
@@ -309,4 +309,37 @@ auto nro_normalise_path(const std::string& p) -> std::string {
|
||||
return p;
|
||||
}
|
||||
|
||||
auto nro_find(std::span<const NroEntry> array, std::string_view name, std::string_view author, const fs::FsPath& path) -> std::optional<NroEntry> {
|
||||
const auto it = std::find_if(array.cbegin(), array.cend(), [name, author, path](auto& e){
|
||||
if (!name.empty() && !author.empty() && !path.empty()) {
|
||||
return e.GetName() == name && e.GetAuthor() == author && e.path == path;
|
||||
} else if (!name.empty()) {
|
||||
return e.GetName() == name;
|
||||
} else if (!author.empty()) {
|
||||
return e.GetAuthor() == author;
|
||||
} else if (!path.empty()) {
|
||||
return e.path == path;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (it == array.cend()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return *it;
|
||||
}
|
||||
|
||||
auto nro_find_name(std::span<const NroEntry> array, std::string_view name) -> std::optional<NroEntry> {
|
||||
return nro_find(array, name, {}, {});
|
||||
}
|
||||
|
||||
auto nro_find_author(std::span<const NroEntry> array, std::string_view author) -> std::optional<NroEntry> {
|
||||
return nro_find(array, {}, author, {});
|
||||
}
|
||||
|
||||
auto nro_find_path(std::span<const NroEntry> array, const fs::FsPath& path) -> std::optional<NroEntry> {
|
||||
return nro_find(array, {}, {}, path);
|
||||
}
|
||||
|
||||
} // namespace sphaira
|
||||
|
||||
@@ -248,36 +248,6 @@ auto GetRomIcon(ProgressBox* pbox, std::string filename, std::string extension,
|
||||
return nro_get_icon(nro.path, nro.icon_size, nro.icon_offset);
|
||||
}
|
||||
|
||||
// returns 0 if true
|
||||
auto CheckIfUpdateFolder(const fs::FsPath& path, std::span<FileEntry> entries) -> Result {
|
||||
fs::FsNativeSd fs;
|
||||
R_TRY(fs.GetFsOpenResult());
|
||||
|
||||
// check that we have daybreak installed
|
||||
R_UNLESS(fs.FileExists(DAYBREAK_PATH), FsError_FileNotFound);
|
||||
|
||||
FsDir d;
|
||||
R_TRY(fs.OpenDirectory(path, FsDirOpenMode_ReadDirs, &d));
|
||||
ON_SCOPE_EXIT(fs.DirClose(&d));
|
||||
|
||||
s64 count;
|
||||
R_TRY(fs.DirGetEntryCount(&d, &count));
|
||||
|
||||
// check that we are at the bottom level
|
||||
R_UNLESS(count == 0, 0x1);
|
||||
// check that we have enough ncas and not too many
|
||||
R_UNLESS(entries.size() > 150 && entries.size() < 300, 0x1);
|
||||
|
||||
// check that all entries end in .nca
|
||||
const auto nca_ext = std::string_view{".nca"};
|
||||
for (auto& e : entries) {
|
||||
const auto ext = std::strrchr(e.name, '.');
|
||||
R_UNLESS(ext && ext == nca_ext, 0x1);
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
auto get_collection(fs::FsNative& fs, const fs::FsPath& path, const fs::FsPath& parent_name, FsDirCollection& out, bool inc_file, bool inc_dir, bool inc_size) -> Result {
|
||||
out.path = path;
|
||||
out.parent_name = parent_name;
|
||||
@@ -376,12 +346,12 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_is_update_folder) {
|
||||
if (m_is_update_folder && m_daybreak_path.has_value()) {
|
||||
App::Push(std::make_shared<OptionBox>("Open with DayBreak?"_i18n, "No"_i18n, "Yes"_i18n, 1, [this](auto op_index){
|
||||
if (op_index && *op_index) {
|
||||
// daybreak uses native fs so do not use nro_add_arg_file
|
||||
// otherwise it'll fail to open the folder...
|
||||
nro_launch(DAYBREAK_PATH, nro_add_arg(m_path));
|
||||
nro_launch(m_daybreak_path.value(), nro_add_arg(m_path));
|
||||
}
|
||||
}));
|
||||
return;
|
||||
@@ -956,7 +926,7 @@ auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result {
|
||||
Sort();
|
||||
|
||||
// quick check to see if this is an update folder
|
||||
m_is_update_folder = R_SUCCEEDED(CheckIfUpdateFolder(new_path, m_entries));
|
||||
m_is_update_folder = R_SUCCEEDED(CheckIfUpdateFolder());
|
||||
|
||||
SetIndex(0);
|
||||
|
||||
@@ -1462,6 +1432,53 @@ void Menu::OnRenameCallback() {
|
||||
|
||||
}
|
||||
|
||||
auto Menu::CheckIfUpdateFolder() -> Result {
|
||||
// check if we have already tried to find daybreak
|
||||
if (m_daybreak_path.has_value() && m_daybreak_path.value().empty()) {
|
||||
return FsError_FileNotFound;
|
||||
}
|
||||
|
||||
fs::FsNativeSd fs;
|
||||
R_TRY(fs.GetFsOpenResult());
|
||||
|
||||
// check that we have daybreak installed
|
||||
if (!m_daybreak_path.has_value()) {
|
||||
auto daybreak_path = DAYBREAK_PATH;
|
||||
if (!fs.FileExists(DAYBREAK_PATH)) {
|
||||
if (auto e = nro_find(m_nro_entries, "Daybreak", "Atmosphere-NX", {}); e.has_value()) {
|
||||
daybreak_path = e.value().path;
|
||||
} else {
|
||||
log_write("failed to find daybreak\n");
|
||||
m_daybreak_path = "";
|
||||
return FsError_FileNotFound;
|
||||
}
|
||||
}
|
||||
m_daybreak_path = daybreak_path;
|
||||
log_write("found daybreak in: %s\n", m_daybreak_path.value().s);
|
||||
}
|
||||
|
||||
FsDir d;
|
||||
R_TRY(fs.OpenDirectory(m_path, FsDirOpenMode_ReadDirs, &d));
|
||||
ON_SCOPE_EXIT(fs.DirClose(&d));
|
||||
|
||||
s64 count;
|
||||
R_TRY(fs.DirGetEntryCount(&d, &count));
|
||||
|
||||
// check that we are at the bottom level
|
||||
R_UNLESS(count == 0, 0x1);
|
||||
// check that we have enough ncas and not too many
|
||||
R_UNLESS(m_entries.size() > 150 && m_entries.size() < 300, 0x1);
|
||||
|
||||
// check that all entries end in .nca
|
||||
const auto nca_ext = std::string_view{".nca"};
|
||||
for (auto& e : m_entries) {
|
||||
const auto ext = std::strrchr(e.name, '.');
|
||||
R_UNLESS(ext && ext == nca_ext, 0x1);
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace sphaira::ui::menu::filebrowser
|
||||
|
||||
// options
|
||||
|
||||
Reference in New Issue
Block a user