themeze: prompt user to install theme after installing.

This commit is contained in:
ITotalJustice
2025-08-02 17:47:09 +01:00
parent 40e4616520
commit ab5c54b47a
2 changed files with 65 additions and 8 deletions

View File

@@ -44,10 +44,6 @@ struct FsPath {
return s; return s;
} }
constexpr auto starts_with(std::string_view str) const -> bool {
return !strncasecmp(s, str.data(), str.length());
}
constexpr auto empty() const { constexpr auto empty() const {
return s[0] == '\0'; return s[0] == '\0';
} }
@@ -64,6 +60,19 @@ struct FsPath {
s[0] = '\0'; s[0] = '\0';
} }
constexpr auto starts_with(std::string_view str) const -> bool {
return !strncasecmp(s, str.data(), str.length());
}
constexpr auto ends_with(std::string_view str) const -> bool {
const auto len = length();
if (len < str.length()) {
return false;
}
return !strncasecmp(s + len - str.length(), str.data(), str.length());
}
constexpr operator const char*() const { return s; } constexpr operator const char*() const { return s; }
constexpr operator char*() { return s; } constexpr operator char*() { return s; }
constexpr operator std::string() { return s; } constexpr operator std::string() { return s; }

View File

@@ -15,6 +15,7 @@
#include "threaded_file_transfer.hpp" #include "threaded_file_transfer.hpp"
#include "image.hpp" #include "image.hpp"
#include "title_info.hpp" #include "title_info.hpp"
#include "nro.hpp"
#include <minIni.h> #include <minIni.h>
#include <stb_image.h> #include <stb_image.h>
@@ -62,15 +63,19 @@ constexpr const char* REQUEST_ORDER[]{
// https://api.themezer.net/?query=query($nsfw:Boolean,$target:String,$page:Int,$limit:Int,$sort:String,$order:String,$query:String,$creators:[String!]){themeList(nsfw:$nsfw,target:$target,page:$page,limit:$limit,sort:$sort,order:$order,query:$query,creators:$creators){id,creator{id,display_name},details{name,description},last_updated,dl_count,like_count,target,preview{original,thumb}}}&variables={"nsfw":false,"target":null,"page":1,"limit":10,"sort":"updated","order":"desc","query":null,"creators":["695065006068334622"]} // https://api.themezer.net/?query=query($nsfw:Boolean,$target:String,$page:Int,$limit:Int,$sort:String,$order:String,$query:String,$creators:[String!]){themeList(nsfw:$nsfw,target:$target,page:$page,limit:$limit,sort:$sort,order:$order,query:$query,creators:$creators){id,creator{id,display_name},details{name,description},last_updated,dl_count,like_count,target,preview{original,thumb}}}&variables={"nsfw":false,"target":null,"page":1,"limit":10,"sort":"updated","order":"desc","query":null,"creators":["695065006068334622"]}
// https://api.themezer.net/?query=query($nsfw:Boolean,$page:Int,$limit:Int,$sort:String,$order:String,$query:String,$creators:[String!]){packList(nsfw:$nsfw,page:$page,limit:$limit,sort:$sort,order:$order,query:$query,creators:$creators){id,creator{id,display_name},details{name,description},last_updated,dl_count,like_count,themes{id,creator{display_name},details{name,description},last_updated,dl_count,like_count,target,preview{original,thumb}}}}&variables={"nsfw":false,"page":1,"limit":10,"sort":"updated","order":"desc","query":null,"creators":["695065006068334622"]} // https://api.themezer.net/?query=query($nsfw:Boolean,$page:Int,$limit:Int,$sort:String,$order:String,$query:String,$creators:[String!]){packList(nsfw:$nsfw,page:$page,limit:$limit,sort:$sort,order:$order,query:$query,creators:$creators){id,creator{id,display_name},details{name,description},last_updated,dl_count,like_count,themes{id,creator{display_name},details{name,description},last_updated,dl_count,like_count,target,preview{original,thumb}}}}&variables={"nsfw":false,"page":1,"limit":10,"sort":"updated","order":"desc","query":null,"creators":["695065006068334622"]}
auto HasNro() -> bool { auto GetNroPath() -> const char* {
fs::FsNativeSd fs; fs::FsNativeSd fs;
for (auto& path : NRO_PATHS) { for (auto& path : NRO_PATHS) {
if (fs.FileExists(path)) { if (fs.FileExists(path)) {
return true; return path;
} }
} }
return false; return nullptr;
}
auto HasNro() -> bool {
return GetNroPath() != nullptr;
} }
// i know, this is cursed // i know, this is cursed
@@ -294,8 +299,51 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> Result {
fs.CreateDirectoryRecursively(dir_path); fs.CreateDirectoryRecursively(dir_path);
// 3. extract the zip // 3. extract the zip
std::vector<std::string> nxtheme_paths;
if (!pbox->ShouldExit()) { if (!pbox->ShouldExit()) {
R_TRY(thread::TransferUnzipAll(pbox, zip_out, &fs, dir_path)); R_TRY(thread::TransferUnzipAll(pbox, zip_out, &fs, dir_path, [&nxtheme_paths](const fs::FsPath& name, fs::FsPath& path){
// just in case theme packs start adding invalid entries.
if (!path.ends_with(".nxtheme")) {
return false;
}
// store path for later.
nxtheme_paths.emplace_back(path);
return true;
}));
}
// ensure that we actually downloaded the theme.
// todo: add new error for this.
R_UNLESS(!nxtheme_paths.empty(), Result_ThemezerFailedToDownloadTheme);
// if we have nxtheme installed, prompt the user to install the theme now.
if (HasNro()) {
App::Push<OptionBox>(
"Theme downloaded, install now?"_i18n,
"Back"_i18n, "Install"_i18n, 1, [nxtheme_paths](auto op_index){
if (op_index && *op_index) {
std::string args;
for (const auto& paths : nxtheme_paths) {
// add space between each arg.
if (!args.empty()) {
args += ' ';
}
// converts path to sdmc:/path.
args += nro_add_arg_file(paths);
}
log_write("themezer nro: %s\n", GetNroPath());
log_write("themezer args: %s\n", args.c_str());
// launch nro with args to the nxthemes.
const auto rc = nro_launch(GetNroPath(), args);
App::PushErrorBox(rc, "Failed to launch NXthemes_Installer.nro"_i18n);
}
}
);
} }
log_write("finished install :)\n"); log_write("finished install :)\n");