enable warning flags, fix all warning, default init all vars, bump stb libs used in nanovg

fixes #98
This commit is contained in:
ITotalJustice
2025-01-16 21:01:17 +00:00
parent f66494aeb5
commit 657c160599
36 changed files with 351 additions and 480 deletions

View File

@@ -81,12 +81,54 @@ target_compile_definitions(sphaira PRIVATE
-DAPP_VERSION_HASH="${sphaira_VERSION_HASH}" -DAPP_VERSION_HASH="${sphaira_VERSION_HASH}"
) )
target_compile_options(sphaira PRIVATE
-Wall
-Wextra
# unsure if it's a good idea to enable these by default as
# it may cause breakage upon compiler updates.
# -Werror
# -Wfatal-errors
# disabled as nx uses s64 for size and offset, however stl uses size_t instead, thus
# there being a lot of warnings.
-Wno-sign-compare
# disabled as many overriden methods don't use the params.
-Wno-unused-parameter
# pedantic warning, missing fields are set to 0.
-Wno-missing-field-initializers
# disabled as it warns for strcat 2 paths together, but it will never
# overflow due to fs enforcing a max path len anyway.
-Wno-format-truncation
# the below are taken from my gba emulator, they've served me well ;)
-Wformat-overflow=2
-Wundef
-Wmissing-include-dirs
-fstrict-aliasing
-Wstrict-overflow=2
-Walloca
-Wduplicated-cond
-Wwrite-strings
-Wdate-time
-Wlogical-op
-Wpacked
-Wcast-qual
-Wcast-align
-Wimplicit-fallthrough=5
-Wsuggest-final-types
-Wuninitialized
-fimplicit-constexpr
-Wmissing-requires
)
include(FetchContent) include(FetchContent)
set(FETCHCONTENT_QUIET FALSE) set(FETCHCONTENT_QUIET FALSE)
FetchContent_Declare(ftpsrv FetchContent_Declare(ftpsrv
GIT_REPOSITORY https://github.com/ITotalJustice/ftpsrv.git GIT_REPOSITORY https://github.com/ITotalJustice/ftpsrv.git
GIT_TAG 1.2.1 GIT_TAG 1.2.1
SOURCE_SUBDIR NONE
) )
FetchContent_Declare(libhaze FetchContent_Declare(libhaze
@@ -101,7 +143,7 @@ FetchContent_Declare(libpulsar
FetchContent_Declare(nanovg FetchContent_Declare(nanovg
GIT_REPOSITORY https://github.com/ITotalJustice/nanovg-deko3d.git GIT_REPOSITORY https://github.com/ITotalJustice/nanovg-deko3d.git
GIT_TAG 1902b38 GIT_TAG 845c9fc
) )
FetchContent_Declare(stb FetchContent_Declare(stb
@@ -136,8 +178,6 @@ set(NANOVG_NO_GIF ON)
set(NANOVG_NO_HDR ON) set(NANOVG_NO_HDR ON)
set(NANOVG_NO_PIC ON) set(NANOVG_NO_PIC ON)
set(NANOVG_NO_PNM ON) set(NANOVG_NO_PNM ON)
set(NANOVG_STBI_STATIC OFF)
set(NANOVG_STBTT_STATIC ON)
set(YYJSON_DISABLE_READER OFF) set(YYJSON_DISABLE_READER OFF)
set(YYJSON_DISABLE_WRITER OFF) set(YYJSON_DISABLE_WRITER OFF)
@@ -148,7 +188,7 @@ set(YYJSON_DISABLE_UTF8_VALIDATION ON)
set(YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS OFF) set(YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS OFF)
FetchContent_MakeAvailable( FetchContent_MakeAvailable(
# ftpsrv ftpsrv
libhaze libhaze
libpulsar libpulsar
nanovg nanovg
@@ -157,11 +197,6 @@ FetchContent_MakeAvailable(
yyjson yyjson
) )
FetchContent_GetProperties(ftpsrv)
if (NOT ftpsrv_POPULATED)
FetchContent_Populate(ftpsrv)
endif()
set(FTPSRV_LIB_BUILD TRUE) set(FTPSRV_LIB_BUILD TRUE)
set(FTPSRV_LIB_SOCK_UNISTD TRUE) set(FTPSRV_LIB_SOCK_UNISTD TRUE)
set(FTPSRV_LIB_VFS_CUSTOM ${ftpsrv_SOURCE_DIR}/src/platform/nx/vfs_nx.h) set(FTPSRV_LIB_VFS_CUSTOM ${ftpsrv_SOURCE_DIR}/src/platform/nx/vfs_nx.h)
@@ -178,6 +213,7 @@ set(FTPSRV_LIB_CUSTOM_DEFINES
USE_VFS_SAVE=$<BOOL:TRUE> USE_VFS_SAVE=$<BOOL:TRUE>
USE_VFS_STORAGE=$<BOOL:TRUE> USE_VFS_STORAGE=$<BOOL:TRUE>
USE_VFS_GC=$<BOOL:${USE_VFS_GC}> USE_VFS_GC=$<BOOL:${USE_VFS_GC}>
USE_VFS_USBHSFS=$<BOOL:FALSE>
VFS_NX_BUFFER_IO=$<BOOL:TRUE> VFS_NX_BUFFER_IO=$<BOOL:TRUE>
) )

View File

@@ -166,7 +166,6 @@ public:
// todo: move this into it's own menu // todo: move this into it's own menu
option::OptionLong m_text_scroll_speed{"accessibility", "text_scroll_speed", 1}; // normal option::OptionLong m_text_scroll_speed{"accessibility", "text_scroll_speed", 1}; // normal
PLSR_BFSAR m_qlaunch_bfsar{};
PLSR_PlayerSoundId m_sound_ids[SoundEffect_MAX]{}; PLSR_PlayerSoundId m_sound_ids[SoundEffect_MAX]{};
private: // from nanovg decko3d example by adubbz private: // from nanovg decko3d example by adubbz

View File

@@ -13,10 +13,10 @@ public:
auto Draw(NVGcontext* vg, Theme* theme) -> void override; auto Draw(NVGcontext* vg, Theme* theme) -> void override;
private: private:
Result m_code; Result m_code{};
std::string m_message; std::string m_message{};
std::string m_module_str; std::string m_module_str{};
std::string m_description_str; std::string m_description_str{};
}; };
} // namespace sphaira::ui } // namespace sphaira::ui

View File

@@ -43,8 +43,8 @@ private:
const s64 m_row; const s64 m_row;
const s64 m_page; const s64 m_page;
Vec4 m_v; Vec4 m_v{};
Vec2 m_pad; Vec2 m_pad{};
Vec4 m_scrollbar{}; Vec4 m_scrollbar{};

View File

@@ -42,26 +42,26 @@ enum class EntryStatus {
}; };
struct Entry { struct Entry {
std::string category; // todo: lable std::string category{}; // todo: lable
std::string binary; // optional, only valid for .nro std::string binary{}; // optional, only valid for .nro
std::string updated; // date of update std::string updated{}; // date of update
std::string name; std::string name{};
std::string license; // optional std::string license{}; // optional
std::string title; // same as name but with spaces std::string title{}; // same as name but with spaces
std::string url; // url of repo (optional?) std::string url{}; // url of repo (optional?)
std::string description; std::string description{};
std::string author; std::string author{};
std::string changelog; // optional std::string changelog{}; // optional
u64 screens; // number of screenshots u64 screens{}; // number of screenshots
u64 extracted; // extracted size in KiB u64 extracted{}; // extracted size in KiB
std::string version; std::string version{};
u64 filesize; // compressed size in KiB u64 filesize{}; // compressed size in KiB
std::string details; std::string details{};
u64 app_dls; u64 app_dls{};
std::string md5; // md5 of the zip std::string md5{}; // md5 of the zip
LazyImage image; LazyImage image{};
u32 updated_num; u32 updated_num{};
EntryStatus status{EntryStatus::Get}; EntryStatus status{EntryStatus::Get};
}; };
@@ -99,13 +99,13 @@ private:
Menu& m_menu; Menu& m_menu;
s64 m_index{}; // where i am in the array s64 m_index{}; // where i am in the array
std::vector<Option> m_options; std::vector<Option> m_options{};
LazyImage m_banner; LazyImage m_banner{};
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
std::shared_ptr<ScrollableText> m_details; std::shared_ptr<ScrollableText> m_details{};
std::shared_ptr<ScrollableText> m_changelog; std::shared_ptr<ScrollableText> m_changelog{};
std::shared_ptr<ScrollableText> m_detail_changelog; std::shared_ptr<ScrollableText> m_detail_changelog{};
bool m_show_changlog{}; bool m_show_changlog{};
}; };
@@ -134,34 +134,6 @@ enum OrderType {
OrderType_Ascending, OrderType_Ascending,
}; };
struct FeedbackEntry {
u32 id;
u64 time;
std::string package; // name of package
std::string content; // the feedback message that was sent
std::string reply; // the reply, "" if no reply yet :)
};
struct FeedbackMenu final : MenuBase {
FeedbackMenu(const std::vector<Entry>& package_entries, LazyImage& default_image);
~FeedbackMenu();
void Update(Controller* controller, TouchInfo* touch) override;
void Draw(NVGcontext* vg, Theme* theme) override;
void OnFocusGained() override;
void SetIndex(s64 index);
void ScanHomebrew();
void Sort();
private:
const std::vector<Entry>& m_package_entries;
LazyImage& m_default_image;
std::vector<FeedbackEntry> m_entries;
s64 m_index{}; // where i am in the array
ImageDownloadState m_repo_download_state{ImageDownloadState::None};
};
struct Menu final : MenuBase { struct Menu final : MenuBase {
Menu(const std::vector<NroEntry>& nro_entries); Menu(const std::vector<NroEntry>& nro_entries);
~Menu(); ~Menu();
@@ -191,27 +163,27 @@ struct Menu final : MenuBase {
private: private:
const std::vector<NroEntry>& m_nro_entries; const std::vector<NroEntry>& m_nro_entries;
std::vector<Entry> m_entries; std::vector<Entry> m_entries{};
std::vector<EntryMini> m_entries_index[Filter_MAX]; std::vector<EntryMini> m_entries_index[Filter_MAX]{};
std::vector<EntryMini> m_entries_index_author; std::vector<EntryMini> m_entries_index_author{};
std::vector<EntryMini> m_entries_index_search; std::vector<EntryMini> m_entries_index_search{};
std::span<EntryMini> m_entries_current; std::span<EntryMini> m_entries_current{};
Filter m_filter{Filter::Filter_All}; Filter m_filter{Filter::Filter_All};
SortType m_sort{SortType::SortType_Updated}; SortType m_sort{SortType::SortType_Updated};
OrderType m_order{OrderType::OrderType_Descending}; OrderType m_order{OrderType::OrderType_Descending};
s64 m_index{}; // where i am in the array s64 m_index{}; // where i am in the array
LazyImage m_default_image; LazyImage m_default_image{};
LazyImage m_update; LazyImage m_update{};
LazyImage m_get; LazyImage m_get{};
LazyImage m_local; LazyImage m_local{};
LazyImage m_installed; LazyImage m_installed{};
ImageDownloadState m_repo_download_state{ImageDownloadState::None}; ImageDownloadState m_repo_download_state{ImageDownloadState::None};
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
std::string m_search_term; std::string m_search_term{};
std::string m_author_term; std::string m_author_term{};
s64 m_entry_search_jump_back{}; s64 m_entry_search_jump_back{};
s64 m_entry_author_jump_back{}; s64 m_entry_author_jump_back{};
bool m_is_search{}; bool m_is_search{};

View File

@@ -16,12 +16,12 @@ struct Menu final : MenuBase {
private: private:
const fs::FsPath m_path; const fs::FsPath m_path;
fs::FsNativeSd m_fs; fs::FsNativeSd m_fs{};
FsFile m_file; FsFile m_file{};
s64 m_file_size{}; s64 m_file_size{};
s64 m_file_offset{}; s64 m_file_offset{};
std::unique_ptr<ScrollableText> m_scroll_text; std::unique_ptr<ScrollableText> m_scroll_text{};
s64 m_start{}; s64 m_start{};
s64 m_index{}; // where i am in the array s64 m_index{}; // where i am in the array

View File

@@ -86,23 +86,23 @@ struct FileEntry : FsDirectoryEntry {
struct FileAssocEntry { struct FileAssocEntry {
fs::FsPath path{}; // ini name fs::FsPath path{}; // ini name
std::string name; // ini name std::string name{}; // ini name
std::vector<std::string> ext; // list of ext std::vector<std::string> ext{}; // list of ext
std::vector<std::string> database; // list of systems std::vector<std::string> database{}; // list of systems
}; };
struct LastFile { struct LastFile {
fs::FsPath name; fs::FsPath name{};
s64 index; s64 index{};
float offset; float offset{};
s64 entries_count; s64 entries_count{};
}; };
struct FsDirCollection { struct FsDirCollection {
fs::FsPath path; fs::FsPath path{};
fs::FsPath parent_name; fs::FsPath parent_name{};
std::vector<FsDirectoryEntry> files; std::vector<FsDirectoryEntry> files{};
std::vector<FsDirectoryEntry> dirs; std::vector<FsDirectoryEntry> dirs{};
}; };
using FsDirCollections = std::vector<FsDirCollection>; using FsDirCollections = std::vector<FsDirCollection>;
@@ -231,32 +231,32 @@ private:
static constexpr inline const char* INI_SECTION = "filebrowser"; static constexpr inline const char* INI_SECTION = "filebrowser";
const std::vector<NroEntry>& m_nro_entries; const std::vector<NroEntry>& m_nro_entries;
std::unique_ptr<fs::FsNative> m_fs; std::unique_ptr<fs::FsNative> m_fs{};
FsType m_fs_type; FsType m_fs_type{};
fs::FsPath m_path; fs::FsPath m_path{};
std::vector<FileEntry> m_entries; std::vector<FileEntry> m_entries{};
std::vector<u32> m_entries_index; // files not including hidden std::vector<u32> m_entries_index{}; // files not including hidden
std::vector<u32> m_entries_index_hidden; // includes hidden files std::vector<u32> m_entries_index_hidden{}; // includes hidden files
std::vector<u32> m_entries_index_search; // files found via search std::vector<u32> m_entries_index_search{}; // files found via search
std::span<u32> m_entries_current; std::span<u32> m_entries_current{};
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
std::optional<fs::FsPath> m_daybreak_path; std::optional<fs::FsPath> m_daybreak_path{};
// search options // search options
// show files [X] // show files [X]
// show folders [X] // show folders [X]
// recursive (slow) [ ] // recursive (slow) [ ]
std::vector<FileAssocEntry> m_assoc_entries; std::vector<FileAssocEntry> m_assoc_entries{};
std::vector<FileEntry> m_selected_files; std::vector<FileEntry> m_selected_files{};
// this keeps track of the highlighted file before opening a folder // this keeps track of the highlighted file before opening a folder
// if the user presses B to go back to the previous dir // if the user presses B to go back to the previous dir
// this vector is popped, then, that entry is checked if it still exists // this vector is popped, then, that entry is checked if it still exists
// if it does, the index becomes that file. // if it does, the index becomes that file.
std::vector<LastFile> m_previous_highlighted_file; std::vector<LastFile> m_previous_highlighted_file{};
fs::FsPath m_selected_path; fs::FsPath m_selected_path{};
s64 m_index{}; s64 m_index{};
s64 m_selected_count{}; s64 m_selected_count{};
SelectedType m_selected_type{SelectedType::None}; SelectedType m_selected_type{SelectedType::None};

View File

@@ -10,35 +10,35 @@
namespace sphaira::ui::menu::gh { namespace sphaira::ui::menu::gh {
struct AssetEntry { struct AssetEntry {
std::string name; std::string name{};
std::string path; std::string path{};
std::string pre_install_message; std::string pre_install_message{};
std::string post_install_message; std::string post_install_message{};
}; };
struct Entry { struct Entry {
fs::FsPath json_path; fs::FsPath json_path{};
std::string url; std::string url{};
std::string owner; std::string owner{};
std::string repo; std::string repo{};
std::string tag; std::string tag{};
std::string pre_install_message; std::string pre_install_message{};
std::string post_install_message; std::string post_install_message{};
std::vector<AssetEntry> assets; std::vector<AssetEntry> assets{};
}; };
struct GhApiAsset { struct GhApiAsset {
std::string name; std::string name{};
std::string content_type; std::string content_type{};
u64 size; u64 size{};
u64 download_count; u64 download_count{};
std::string browser_download_url; std::string browser_download_url{};
}; };
struct GhApiEntry { struct GhApiEntry {
std::string tag_name; std::string tag_name{};
std::string name; std::string name{};
std::vector<GhApiAsset> assets; std::vector<GhApiAsset> assets{};
}; };
struct Menu final : MenuBase { struct Menu final : MenuBase {
@@ -66,9 +66,9 @@ private:
void UpdateSubheading(); void UpdateSubheading();
private: private:
std::vector<Entry> m_entries; std::vector<Entry> m_entries{};
s64 m_index{}; s64 m_index{};
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
}; };
} // namespace sphaira::ui::menu::gh } // namespace sphaira::ui::menu::gh

View File

@@ -50,9 +50,9 @@ struct Menu final : MenuBase {
private: private:
static constexpr inline const char* INI_SECTION = "homebrew"; static constexpr inline const char* INI_SECTION = "homebrew";
std::vector<NroEntry> m_entries; std::vector<NroEntry> m_entries{};
s64 m_index{}; // where i am in the array s64 m_index{}; // where i am in the array
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_AlphabeticalStar}; option::OptionLong m_sort{INI_SECTION, "sort", SortType::SortType_AlphabeticalStar};
option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending}; option::OptionLong m_order{INI_SECTION, "order", OrderType::OrderType_Descending};

View File

@@ -25,9 +25,9 @@ private:
void UpdateVars(); void UpdateVars();
private: private:
std::string m_title; std::string m_title{};
std::string m_title_sub_heading; std::string m_title_sub_heading{};
std::string m_sub_heading; std::string m_sub_heading{};
struct tm m_tm{}; struct tm m_tm{};
TimeStamp m_poll_timestamp{}; TimeStamp m_poll_timestamp{};

View File

@@ -42,79 +42,50 @@ enum class PageLoadState {
Error, Error,
}; };
// all commented out entries are those that we don't query for.
// this saves time not only processing the json, but also the download
// of said json.
// by reducing the fields to only what we need, the size is 4-5x smaller.
struct Creator { struct Creator {
std::string id; std::string id{};
std::string display_name; std::string display_name{};
}; };
struct Details { struct Details {
std::string name; std::string name{};
// std::string description;
}; };
struct Preview { struct Preview {
// std::string original; std::string thumb{};
std::string thumb; LazyImage lazy_image{};
LazyImage lazy_image;
}; };
struct DownloadPack { struct DownloadPack {
std::string filename; std::string filename{};
std::string url; std::string url{};
std::string mimetype; std::string mimetype{};
}; };
using DownloadTheme = DownloadPack; using DownloadTheme = DownloadPack;
struct ThemeEntry { struct ThemeEntry {
std::string id; std::string id{};
// Creator creator; Preview preview{};
// Details details;
// std::string last_updated;
// u64 dl_count;
// u64 like_count;
// std::vector<std::string> categories;
// std::string target;
Preview preview;
}; };
// struct Pack {
// std::string id;
// Creator creator;
// Details details;
// std::string last_updated;
// std::vector<std::string> categories;
// u64 dl_count;
// u64 like_count;
// std::vector<ThemeEntry> themes;
// };
struct PackListEntry { struct PackListEntry {
std::string id; std::string id{};
Creator creator; Creator creator{};
Details details; Details details{};
// std::string last_updated; std::vector<ThemeEntry> themes{};
// std::vector<std::string> categories;
// u64 dl_count;
// u64 like_count;
std::vector<ThemeEntry> themes;
}; };
struct Pagination { struct Pagination {
u64 page; u64 page{};
u64 limit; u64 limit{};
u64 page_count; u64 page_count{};
u64 item_count; u64 item_count{};
}; };
struct PackList { struct PackList {
std::vector<PackListEntry> packList; std::vector<PackListEntry> packList{};
Pagination pagination; Pagination pagination{};
}; };
struct Config { struct Config {
@@ -123,10 +94,10 @@ struct Config {
u32 sort_index{}; u32 sort_index{};
u32 order_index{}; u32 order_index{};
// search query, if empty, its not used // search query, if empty, its not used
std::string query; std::string query{};
// this is actually an array of creator ids, but we don't support that feature // this is actually an array of creator ids, but we don't support that feature
// if empty, its not used // if empty, its not used
std::string creator; std::string creator{};
// defaults // defaults
u32 page{1}; u32 page{1};
u32 limit{18}; u32 limit{18};
@@ -152,7 +123,7 @@ struct Config {
struct Menu; // fwd struct Menu; // fwd
struct PageEntry { struct PageEntry {
std::vector<PackListEntry> m_packList; std::vector<PackListEntry> m_packList{};
Pagination m_pagination{}; Pagination m_pagination{};
PageLoadState m_ready{PageLoadState::None}; PageLoadState m_ready{PageLoadState::None};
}; };
@@ -172,9 +143,6 @@ struct Menu final : MenuBase {
} }
} }
// void SetSearch(const std::string& term);
// void SetAuthor();
void InvalidateAllPages(); void InvalidateAllPages();
void PackListDownload(); void PackListDownload();
void OnPackListDownload(); void OnPackListDownload();
@@ -183,14 +151,14 @@ private:
static constexpr inline const char* INI_SECTION = "themezer"; static constexpr inline const char* INI_SECTION = "themezer";
static constexpr inline u32 MAX_ON_PAGE = 16; // same as website static constexpr inline u32 MAX_ON_PAGE = 16; // same as website
std::vector<PageEntry> m_pages; std::vector<PageEntry> m_pages{};
s64 m_page_index{}; s64 m_page_index{};
s64 m_page_index_max{1}; s64 m_page_index_max{1};
std::string m_search{}; std::string m_search{};
s64 m_index{}; // where i am in the array s64 m_index{}; // where i am in the array
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
// options // options
option::OptionLong m_sort{INI_SECTION, "sort", 0}; option::OptionLong m_sort{INI_SECTION, "sort", 0};

View File

@@ -22,9 +22,9 @@ private:
void Draw(NVGcontext* vg, Theme* theme) override; void Draw(NVGcontext* vg, Theme* theme) override;
private: private:
std::string m_text; std::string m_text{};
std::size_t m_count{180}; // count down to zero std::size_t m_count{180}; // count down to zero
Side m_side; Side m_side{};
bool m_bounds_measured{}; bool m_bounds_measured{};
}; };
@@ -47,8 +47,8 @@ private:
void Draw(NVGcontext* vg, Theme* theme, Entries& entries); void Draw(NVGcontext* vg, Theme* theme, Entries& entries);
private: private:
Entries m_entries_left; Entries m_entries_left{};
Entries m_entries_right; Entries m_entries_right{};
Mutex m_mutex{}; Mutex m_mutex{};
}; };

View File

@@ -18,7 +18,7 @@ public:
private: private:
private: private:
std::string m_text; std::string m_text{};
Vec2 m_text_pos{}; Vec2 m_text_pos{};
bool m_selected{false}; bool m_selected{false};
}; };
@@ -48,13 +48,13 @@ private:
void SetIndex(s64 index); void SetIndex(s64 index);
private: private:
std::string m_message; std::string m_message{};
Callback m_callback; Callback m_callback{};
Vec4 m_spacer_line{}; Vec4 m_spacer_line{};
s64 m_index{}; s64 m_index{};
std::vector<OptionBoxEntry> m_entries; std::vector<OptionBoxEntry> m_entries{};
}; };
} // namespace sphaira::ui } // namespace sphaira::ui

View File

@@ -32,12 +32,12 @@ private:
static constexpr float m_text_xoffset{15.f}; static constexpr float m_text_xoffset{15.f};
static constexpr float m_line_width{1220.f}; static constexpr float m_line_width{1220.f};
std::string m_title; std::string m_title{};
Items m_items; Items m_items{};
Callback m_callback; Callback m_callback{};
s64 m_index; // index in list array s64 m_index{}; // index in list array
std::unique_ptr<List> m_list; std::unique_ptr<List> m_list{};
float m_yoff{}; float m_yoff{};
float m_line_top{}; float m_line_top{};

View File

@@ -42,9 +42,9 @@ struct ProgressBox final : Widget {
public: public:
struct ThreadData { struct ThreadData {
ProgressBox* pbox; ProgressBox* pbox{};
ProgressBoxCallback callback; ProgressBoxCallback callback{};
bool result; bool result{};
}; };
private: private:

View File

@@ -14,15 +14,15 @@ struct ScrollableText final : Widget {
// float m_y_off = m_y_off_base; // float m_y_off = m_y_off_base;
// static constexpr float m_clip_y = 250.0F; // static constexpr float m_clip_y = 250.0F;
static constexpr inline float m_step = 30;
const float m_font_size;
const float m_y_off_base; const float m_y_off_base;
float m_y_off;
const float m_clip_y; const float m_clip_y;
const float m_end_w; const float m_end_w;
static constexpr float m_step = 30;
int m_index = 0; float m_y_off{};
const float m_font_size; int m_index{};
float m_bounds[4]; float m_bounds[4]{};
}; };
} // namespace sphaira::ui } // namespace sphaira::ui

View File

@@ -323,37 +323,36 @@ inline ActionType operator|(ActionType a, ActionType b) {
} }
struct Action final { struct Action final {
using CallbackEmpty = std::function<void()>;
using CallbackWithBool = std::function<void(bool)>;
using Callback = std::variant< using Callback = std::variant<
std::function<void()>, CallbackEmpty,
std::function<void(bool)> CallbackWithBool
>; >;
Action(Callback cb) : m_type{ActionType::DOWN}, m_hint{""}, m_callback{cb}, m_hidden{true} {} Action(Callback cb) : Action{ActionType::DOWN, "", cb} {}
Action(std::string hint, Callback cb) : m_type{ActionType::DOWN}, m_hint{hint}, m_callback{cb} {} Action(std::string hint, Callback cb) : Action{ActionType::DOWN, hint, cb} {}
Action(u8 type, Callback cb) : m_type{type}, m_hint{""}, m_callback{cb}, m_hidden{true} {} Action(u8 type, Callback cb) : Action{type, "", cb} {}
Action(u8 type, std::string hint, Callback cb) : m_type{type}, m_hint{hint}, m_callback{cb} {} Action(u8 type, std::string hint, Callback cb) : m_type{type}, m_callback{cb}, m_hint{hint} {}
auto IsHidden() const noexcept { return m_hidden; } auto IsHidden() const noexcept { return m_hint.empty(); }
auto Invoke(bool down) const { auto Invoke(bool down) const {
// todo: make this a visit std::visit([down](auto&& arg){
switch (m_callback.index()) { using T = std::decay_t<decltype(arg)>;
case 0: if constexpr(std::is_same_v<T, CallbackEmpty>) {
std::get<0>(m_callback)(); arg();
break; } else if constexpr(std::is_same_v<T, CallbackWithBool>) {
case 1: arg(down);
std::get<1>(m_callback)(down); } else {
break; static_assert(false, "non-exhaustive visitor!");
} }
// std::visit([down, this](auto& cb){ }, m_callback);
// cb(down);
// }), m_callback;
} }
u8 m_type; u8 m_type{};
std::string m_hint; // todo: make optional Callback m_callback{};
Callback m_callback; std::string m_hint{};
bool m_hidden{false}; // replace this optional text
}; };
struct Controller { struct Controller {

View File

@@ -78,7 +78,7 @@ struct Widget : public Object {
auto GetUiButtons() const -> uiButtons; auto GetUiButtons() const -> uiButtons;
Actions m_actions; Actions m_actions{};
Vec2 m_button_pos{1220, 675}; Vec2 m_button_pos{1220, 675};
bool m_focus{false}; bool m_focus{false};
bool m_pop{false}; bool m_pop{false};

View File

@@ -327,7 +327,7 @@ void LoadThemeInternal(ThemeMeta meta, ThemeData& theme_data, int inherit_level
if (!ini_browse(cb, &theme_data, meta.ini_path)) { if (!ini_browse(cb, &theme_data, meta.ini_path)) {
log_write("failed to open ini: %s\n", meta.ini_path.s); log_write("failed to open ini: %s\n", meta.ini_path.s);
} else { } else {
log_write("opened ini: %s\n", meta.ini_path); log_write("opened ini: %s\n", meta.ini_path.s);
} }
} }
} }
@@ -666,7 +666,7 @@ void App::SetReplaceHbmenuEnable(bool enable) {
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) { if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
if (std::strcmp(sphaira_nacp.display_version, hbmenu_nacp.display_version) < 0) { if (std::strcmp(sphaira_nacp.display_version, hbmenu_nacp.display_version) < 0) {
if (R_FAILED(rc = fs.copy_entire_file(sphaira_path, "/hbmenu.nro"))) { if (R_FAILED(rc = fs.copy_entire_file(sphaira_path, "/hbmenu.nro"))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc)); log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path.s, rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else { } else {
log_write("success with updating hbmenu!\n"); log_write("success with updating hbmenu!\n");
} }
@@ -872,23 +872,26 @@ void App::Poll() {
} }
auto gesture = gestures[i]; auto gesture = gestures[i];
if (gesture_count && gesture.type == HidGestureType_Swipe) { if (gesture_count && gesture.type == HidGestureType_Touch) {
log_write("[SWIPE] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number); log_write("[TOUCH] got gesture attr: %u direction: %u sampling_number: %zu context_number: %zu\n", gesture.attributes, gesture.direction, gesture.sampling_number, gesture.context_number);
}
else if (gesture_count && gesture.type == HidGestureType_Swipe) {
log_write("[SWIPE] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
} }
else if (gesture_count && gesture.type == HidGestureType_Tap) { else if (gesture_count && gesture.type == HidGestureType_Tap) {
log_write("[TAP] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number); log_write("[TAP] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
} }
else if (gesture_count && gesture.type == HidGestureType_Press) { else if (gesture_count && gesture.type == HidGestureType_Press) {
log_write("[PRESS] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number); log_write("[PRESS] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
} }
else if (gesture_count && gesture.type == HidGestureType_Cancel) { else if (gesture_count && gesture.type == HidGestureType_Cancel) {
log_write("[CANCEL] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number); log_write("[CANCEL] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
} }
else if (gesture_count && gesture.type == HidGestureType_Complete) { else if (gesture_count && gesture.type == HidGestureType_Complete) {
log_write("[COMPLETE] got gesture type: %d direction: %d sampling_number: %d context_number: %d\n", gesture.type, gesture.direction, gesture.sampling_number, gesture.context_number); log_write("[COMPLETE] got gesture direction: %u sampling_number: %zu context_number: %zu\n", gesture.direction, gesture.sampling_number, gesture.context_number);
} }
else if (gesture_count && gesture.type == HidGestureType_Pan) { else if (gesture_count && gesture.type == HidGestureType_Pan) {
log_write("[PAN] got gesture sampling_number: %d context_number: %d x: %d y: %d dx: %d dy: %d vx: %.2f vy: %.2f count: %d\n", gesture.sampling_number, gesture.context_number, gesture.x, gesture.y, gesture.delta_x, gesture.delta_y, gesture.velocity_x, gesture.velocity_y, gesture.point_count); log_write("[PAN] got gesture direction: %u sampling_number: %zu context_number: %zu x: %d y: %d dx: %d dy: %d vx: %.2f vy: %.2f count: %d\n", gesture.direction, gesture.sampling_number, gesture.context_number, gesture.x, gesture.y, gesture.delta_x, gesture.delta_y, gesture.velocity_x, gesture.velocity_y, gesture.point_count);
} }
} }
@@ -1265,19 +1268,21 @@ App::App(const char* argv0) {
if (R_SUCCEEDED(romfsMountDataStorageFromProgram(0x0100000000001000, "qlaunch"))) { if (R_SUCCEEDED(romfsMountDataStorageFromProgram(0x0100000000001000, "qlaunch"))) {
ON_SCOPE_EXIT(romfsUnmount("qlaunch")); ON_SCOPE_EXIT(romfsUnmount("qlaunch"));
plsrPlayerInit(); plsrPlayerInit();
plsrBFSAROpen("qlaunch:/sound/qlaunch.bfsar", &m_qlaunch_bfsar); PLSR_BFSAR qlaunch_bfsar;
ON_SCOPE_EXIT(plsrBFSARClose(&m_qlaunch_bfsar)); if (R_SUCCEEDED(plsrBFSAROpen("qlaunch:/sound/qlaunch.bfsar", &qlaunch_bfsar))) {
ON_SCOPE_EXIT(plsrBFSARClose(&qlaunch_bfsar));
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconFocus", &m_sound_ids[SoundEffect_Focus]); plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconFocus", &m_sound_ids[SoundEffect_Focus]);
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconScroll", &m_sound_ids[SoundEffect_Scroll]); plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconScroll", &m_sound_ids[SoundEffect_Scroll]);
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconLimit", &m_sound_ids[SoundEffect_Limit]); plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconLimit", &m_sound_ids[SoundEffect_Limit]);
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeStartupMenu_game", &m_sound_ids[SoundEffect_Startup]); plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeStartupMenu_game", &m_sound_ids[SoundEffect_Startup]);
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeGameIconAdd", &m_sound_ids[SoundEffect_Install]); plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeGameIconAdd", &m_sound_ids[SoundEffect_Install]);
plsrPlayerLoadSoundByName(&m_qlaunch_bfsar, "SeInsertError", &m_sound_ids[SoundEffect_Error]); plsrPlayerLoadSoundByName(&qlaunch_bfsar, "SeInsertError", &m_sound_ids[SoundEffect_Error]);
plsrPlayerSetVolume(m_sound_ids[SoundEffect_Limit], 2.0f); plsrPlayerSetVolume(m_sound_ids[SoundEffect_Limit], 2.0f);
plsrPlayerSetVolume(m_sound_ids[SoundEffect_Focus], 0.5f); plsrPlayerSetVolume(m_sound_ids[SoundEffect_Focus], 0.5f);
PlaySoundEffect(SoundEffect_Startup); PlaySoundEffect(SoundEffect_Startup);
}
} else { } else {
log_write("failed to mount romfs 0x0100000000001000\n"); log_write("failed to mount romfs 0x0100000000001000\n");
} }
@@ -1335,7 +1340,7 @@ App::App(const char* argv0) {
log_write("launching from sphaira created forwarder\n"); log_write("launching from sphaira created forwarder\n");
m_is_launched_via_sphaira_forwader = true; m_is_launched_via_sphaira_forwader = true;
} else { } else {
log_write("launching from unknown forwader: %.*s size: %zu\n", loader_info_size, envGetLoaderInfo(), loader_info_size); log_write("launching from unknown forwader: %.*s size: %zu\n", (int)loader_info_size, envGetLoaderInfo(), loader_info_size);
} }
} else { } else {
log_write("not launching from forwarder\n"); log_write("not launching from forwarder\n");
@@ -1409,9 +1414,6 @@ App::~App() {
} }
} }
// Close the archive
plsrBFSARClose(&m_qlaunch_bfsar);
// De-initialize our player // De-initialize our player
plsrPlayerExit(); plsrPlayerExit();
@@ -1435,7 +1437,7 @@ App::~App() {
} }
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath()))) { if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath()))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath(), rc, R_MODULE(rc), R_DESCRIPTION(rc)); log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath().s, rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else { } else {
log_write("success with copying over root file!\n"); log_write("success with copying over root file!\n");
} }
@@ -1460,7 +1462,7 @@ App::~App() {
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) { if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
if (std::strcmp(hbmenu_nacp.display_version, sphaira_nacp.display_version) < 0) { if (std::strcmp(hbmenu_nacp.display_version, sphaira_nacp.display_version) < 0) {
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path))) { if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc)); log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path.s, rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else { } else {
log_write("success with updating hbmenu!\n"); log_write("success with updating hbmenu!\n");
} }

View File

@@ -462,12 +462,12 @@ auto DownloadInternal(CURL* curl, const Api& e) -> ApiResult {
fs.CreateDirectoryRecursivelyWithPath(tmp_buf); fs.CreateDirectoryRecursivelyWithPath(tmp_buf);
if (auto rc = fs.CreateFile(tmp_buf, 0, 0); R_FAILED(rc) && rc != FsError_PathAlreadyExists) { if (auto rc = fs.CreateFile(tmp_buf, 0, 0); R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
log_write("failed to create file: %s\n", tmp_buf); log_write("failed to create file: %s\n", tmp_buf.s);
return {}; return {};
} }
if (R_FAILED(fs.OpenFile(tmp_buf, FsOpenMode_Write|FsOpenMode_Append, &chunk.f))) { if (R_FAILED(fs.OpenFile(tmp_buf, FsOpenMode_Write|FsOpenMode_Append, &chunk.f))) {
log_write("failed to open file: %s\n", tmp_buf); log_write("failed to open file: %s\n", tmp_buf.s);
return {}; return {};
} }
@@ -553,7 +553,7 @@ auto DownloadInternal(CURL* curl, const Api& e) -> ApiResult {
if (http_code == 304) { if (http_code == 304) {
log_write("cached download: %s\n", e.GetUrl().c_str()); log_write("cached download: %s\n", e.GetUrl().c_str());
} else { } else {
log_write("un-cached download: %s code: %u\n", e.GetUrl().c_str(), http_code); log_write("un-cached download: %s code: %lu\n", e.GetUrl().c_str(), http_code);
if (e.GetFlags() & Flag_Cache) { if (e.GetFlags() & Flag_Cache) {
g_cache.set(e.GetPath(), header_out); g_cache.set(e.GetPath(), header_out);
} }

View File

@@ -135,7 +135,7 @@ Result CreateDirectoryRecursively(FsFileSystem* fs, const FsPath& _path, bool ig
} }
if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
log_write("failed to create folder: %s\n", path); log_write("failed to create folder: %s\n", path.s);
return rc; return rc;
} }
@@ -167,7 +167,7 @@ Result CreateDirectoryRecursivelyWithPath(FsFileSystem* fs, const FsPath& _path,
} }
if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc) && rc != FsError_PathAlreadyExists) {
log_write("failed to create folder recursively: %s\n", path); log_write("failed to create folder recursively: %s\n", path.s);
return rc; return rc;
} }

View File

@@ -92,6 +92,7 @@ bool init(long index) {
case SetLanguage_PT: lang_name = "pt"; break; case SetLanguage_PT: lang_name = "pt"; break;
case SetLanguage_RU: lang_name = "ru"; break; case SetLanguage_RU: lang_name = "ru"; break;
case SetLanguage_ZHTW: lang_name = "zh"; break; case SetLanguage_ZHTW: lang_name = "zh"; break;
default: break;
} }
const fs::FsPath sdmc_path = "/config/sphaira/i18n/" + lang_name + ".json"; const fs::FsPath sdmc_path = "/config/sphaira/i18n/" + lang_name + ".json";

View File

@@ -4,14 +4,19 @@
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Warray-bounds=" #pragma GCC diagnostic ignored "-Warray-bounds="
#include "nanovg/stb_image.h" #pragma GCC diagnostic ignored "-Wcast-qual"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION
#define STB_IMAGE_WRITE_STATIC #define STB_IMAGE_WRITE_STATIC
#define STBI_WRITE_NO_STDIO #define STBI_WRITE_NO_STDIO
#include "stb_image_write.h" #include <stb_image_write.h>
#define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_IMAGE_RESIZE_IMPLEMENTATION
#define STB_IMAGE_RESIZE_STATIC #define STB_IMAGE_RESIZE_STATIC
#include "stb_image_resize2.h" #include <stb_image_resize2.h>
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@@ -124,7 +124,7 @@ auto nro_scan_internal(const fs::FsPath& path, std::vector<NroEntry>& nros, bool
if (e.type == FsDirEntryType_Dir) { if (e.type == FsDirEntryType_Dir) {
// assert(!root && "dir should only be scanned on non-root!"); // assert(!root && "dir should only be scanned on non-root!");
fs::FsPath fullpath; fs::FsPath fullpath;
std::snprintf(fullpath, sizeof(fullpath), "%s/%s/%s.nro", path, e.name, e.name); std::snprintf(fullpath, sizeof(fullpath), "%s/%s/%s.nro", path.s, e.name, e.name);
// fast path for detecting an nro in a folder // fast path for detecting an nro in a folder
NroEntry entry; NroEntry entry;
@@ -133,12 +133,12 @@ auto nro_scan_internal(const fs::FsPath& path, std::vector<NroEntry>& nros, bool
nros.emplace_back(entry); nros.emplace_back(entry);
} else { } else {
// slow path... // slow path...
std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path, e.name); std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path.s, e.name);
nro_scan_internal(fullpath, nros, hide_sphaira, nested, scan_all_dir, false); nro_scan_internal(fullpath, nros, hide_sphaira, nested, scan_all_dir, false);
} }
} else if (e.type == FsDirEntryType_File && std::string_view{e.name}.ends_with(".nro")) { } else if (e.type == FsDirEntryType_File && std::string_view{e.name}.ends_with(".nro")) {
fs::FsPath fullpath; fs::FsPath fullpath;
std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path, e.name); std::snprintf(fullpath, sizeof(fullpath), "%s/%s", path.s, e.name);
NroEntry entry; NroEntry entry;
if (R_SUCCEEDED(nro_parse_internal(fs, fullpath, entry))) { if (R_SUCCEEDED(nro_parse_internal(fs, fullpath, entry))) {
@@ -148,7 +148,7 @@ auto nro_scan_internal(const fs::FsPath& path, std::vector<NroEntry>& nros, bool
R_SUCCEED(); R_SUCCEED();
} }
} else { } else {
log_write("error when trying to parse %s\n", fullpath); log_write("error when trying to parse %s\n", fullpath.s);
} }
} }
} }

View File

@@ -301,7 +301,7 @@ void loop(void* args) {
continue; continue;
} }
log_write("got name: %s\n", name); log_write("got name: %s\n", name.s);
u32 filesize{}; u32 filesize{};
if (!recvall(connfd, &filesize, sizeof(filesize))) { if (!recvall(connfd, &filesize, sizeof(filesize))) {

View File

@@ -18,7 +18,7 @@
#include <string> #include <string>
#include <cstring> #include <cstring>
#include <yyjson.h> #include <yyjson.h>
#include <nanovg/stb_image.h> #include <stb_image.h>
#include <minizip/unzip.h> #include <minizip/unzip.h>
#include <mbedtls/md5.h> #include <mbedtls/md5.h>
#include <ranges> #include <ranges>
@@ -65,60 +65,27 @@ auto BuildIconUrl(const Entry& e) -> std::string {
return out; return out;
} }
#if 0
auto BuildInfoUrl(const Entry& e) -> std::string {
char out[0x100];
std::snprintf(out, sizeof(out), "%s/packages/%s/info.json", URL_BASE, e.name.c_str());
return out;
}
#endif
auto BuildBannerUrl(const Entry& e) -> std::string { auto BuildBannerUrl(const Entry& e) -> std::string {
char out[0x100]; char out[0x100];
std::snprintf(out, sizeof(out), "%s/packages/%s/screen.png", URL_BASE, e.name.c_str()); std::snprintf(out, sizeof(out), "%s/packages/%s/screen.png", URL_BASE, e.name.c_str());
return out; return out;
} }
#if 0
auto BuildScreensUrl(const Entry& e, u8 num) -> std::string {
char out[0x100];
std::snprintf(out, sizeof(out), "%s/packages/%s/screen%u.png", URL_BASE, e.name.c_str(), num+1);
return out;
}
#endif
auto BuildMainifestUrl(const Entry& e) -> std::string {
char out[0x100];
std::snprintf(out, sizeof(out), "%s/packages/%s/manifest.install", URL_BASE, e.name.c_str());
return out;
}
auto BuildZipUrl(const Entry& e) -> std::string { auto BuildZipUrl(const Entry& e) -> std::string {
char out[0x100]; char out[0x100];
std::snprintf(out, sizeof(out), "%s/zips/%s.zip", URL_BASE, e.name.c_str()); std::snprintf(out, sizeof(out), "%s/zips/%s.zip", URL_BASE, e.name.c_str());
return out; return out;
} }
auto BuildFeedbackUrl(std::span<u32> ids) -> std::string {
std::string out{"https://wiiubru.com/feedback/messages?ids="};
for (u32 i = 0; i < ids.size(); i++) {
if (i != 0) {
out.push_back(',');
}
out += std::to_string(ids[i]);
}
return out;
}
auto BuildIconCachePath(const Entry& e) -> fs::FsPath { auto BuildIconCachePath(const Entry& e) -> fs::FsPath {
fs::FsPath out; fs::FsPath out;
std::snprintf(out, sizeof(out), "%s/icons/%s.png", CACHE_PATH, e.name.c_str()); std::snprintf(out, sizeof(out), "%s/icons/%s.png", CACHE_PATH.s, e.name.c_str());
return out; return out;
} }
auto BuildBannerCachePath(const Entry& e) -> fs::FsPath { auto BuildBannerCachePath(const Entry& e) -> fs::FsPath {
fs::FsPath out; fs::FsPath out;
std::snprintf(out, sizeof(out), "%s/banners/%s.png", CACHE_PATH, e.name.c_str()); std::snprintf(out, sizeof(out), "%s/banners/%s.png", CACHE_PATH.s, e.name.c_str());
return out; return out;
} }
@@ -302,7 +269,6 @@ auto AppDlToStr(u32 value) -> std::string {
void ReadFromInfoJson(Entry& e) { void ReadFromInfoJson(Entry& e) {
const auto info_path = BuildInfoCachePath(e); const auto info_path = BuildInfoCachePath(e);
const auto manifest_path = BuildManifestCachePath(e);
yyjson_read_err err; yyjson_read_err err;
auto doc = yyjson_read_file(info_path, YYJSON_READ_NOFLAG, nullptr, &err); auto doc = yyjson_read_file(info_path, YYJSON_READ_NOFLAG, nullptr, &err);
@@ -340,9 +306,9 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
const auto safe_buf = fs::AppendPath("/", e.path); const auto safe_buf = fs::AppendPath("/", e.path);
// this will handle read only files, ie, hbmenu.nro // this will handle read only files, ie, hbmenu.nro
if (R_FAILED(fs.DeleteFile(safe_buf))) { if (R_FAILED(fs.DeleteFile(safe_buf))) {
log_write("failed to delete file: %s\n", safe_buf); log_write("failed to delete file: %s\n", safe_buf.s);
} else { } else {
log_write("deleted file: %s\n", safe_buf); log_write("deleted file: %s\n", safe_buf.s);
// todo: delete empty directories! // todo: delete empty directories!
// fs::delete_directory(safe_buf); // fs::delete_directory(safe_buf);
} }
@@ -353,9 +319,9 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
const auto dir = BuildPackageCachePath(entry); const auto dir = BuildPackageCachePath(entry);
pbox->NewTransfer("Removing "_i18n + dir); pbox->NewTransfer("Removing "_i18n + dir);
if (R_FAILED(fs.DeleteDirectoryRecursively(dir))) { if (R_FAILED(fs.DeleteDirectoryRecursively(dir))) {
log_write("failed to delete folder: %s\n", dir); log_write("failed to delete folder: %s\n", dir.s);
} else { } else {
log_write("deleted: %s\n", dir); log_write("deleted: %s\n", dir.s);
} }
return true; return true;
} }
@@ -458,7 +424,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
if (!pbox->ShouldExit()) { if (!pbox->ShouldExit()) {
auto zfile = unzOpen64(zip_out); auto zfile = unzOpen64(zip_out);
if (!zfile) { if (!zfile) {
log_write("failed to open zip: %s\n", zip_out); log_write("failed to open zip: %s\n", zip_out.s);
return false; return false;
} }
ON_SCOPE_EXIT(unzClose(zfile)); ON_SCOPE_EXIT(unzClose(zfile));
@@ -501,7 +467,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
pbox->NewTransfer(inzip); pbox->NewTransfer(inzip);
if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) { if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) {
log_write("failed to find %s\n", inzip); log_write("failed to find %s\n", inzip.s);
return false; return false;
} }
@@ -526,19 +492,19 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
Result rc; Result rc;
if (R_FAILED(rc = fs.CreateFile(output, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateFile(output, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create file: %s 0x%04X\n", output, rc); log_write("failed to create file: %s 0x%04X\n", output.s, rc);
return false; return false;
} }
FsFile f; FsFile f;
if (R_FAILED(rc = fs.OpenFile(output, FsOpenMode_Write, &f))) { if (R_FAILED(rc = fs.OpenFile(output, FsOpenMode_Write, &f))) {
log_write("failed to open file: %s 0x%04X\n", output, rc); log_write("failed to open file: %s 0x%04X\n", output.s, rc);
return false; return false;
} }
ON_SCOPE_EXIT(fsFileClose(&f)); ON_SCOPE_EXIT(fsFileClose(&f));
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
log_write("failed to set file size: %s 0x%04X\n", output, rc); log_write("failed to set file size: %s 0x%04X\n", output.s, rc);
return false; return false;
} }
@@ -551,12 +517,12 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size()); const auto bytes_read = unzReadCurrentFile(zfile, buf.data(), buf.size());
if (bytes_read <= 0) { if (bytes_read <= 0) {
log_write("failed to read zip file: %s\n", inzip); log_write("failed to read zip file: %s\n", inzip.s);
return false; return false;
} }
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
log_write("failed to write file: %s 0x%04X\n", output, rc); log_write("failed to write file: %s 0x%04X\n", output.s, rc);
return false; return false;
} }
@@ -615,9 +581,9 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> bool {
const auto safe_buf = fs::AppendPath("/", old_entry.path); const auto safe_buf = fs::AppendPath("/", old_entry.path);
// std::strcat(safe_buf, old_entry.path); // std::strcat(safe_buf, old_entry.path);
if (R_FAILED(fs.DeleteFile(safe_buf))) { if (R_FAILED(fs.DeleteFile(safe_buf))) {
log_write("failed to delete: %s\n", safe_buf); log_write("failed to delete: %s\n", safe_buf.s);
} else { } else {
log_write("deleted file: %s\n", safe_buf); log_write("deleted file: %s\n", safe_buf.s);
} }
} }
} }
@@ -761,13 +727,9 @@ void EntryMenu::Draw(NVGcontext* vg, Theme* theme) {
gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "app_dls: %s"_i18n.c_str(), AppDlToStr(m_entry.app_dls).c_str()); gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "app_dls: %s"_i18n.c_str(), AppDlToStr(m_entry.app_dls).c_str());
text_start_y += text_inc_y; text_start_y += text_inc_y;
// for (const auto& option : m_options) {
const auto& text_col = theme->GetColour(ThemeEntryID_TEXT);
// todo: rewrite this mess and use list // todo: rewrite this mess and use list
constexpr float mm = 0;//20; constexpr float mm = 0;//20;
constexpr Vec4 block{968.f + mm, 110.f, 256.f - mm*2, 60.f}; constexpr Vec4 block{968.f + mm, 110.f, 256.f - mm*2, 60.f};
constexpr float text_xoffset{15.f};
const float x = block.x; const float x = block.x;
float y = 1.f + text_start_y + (text_inc_y * 3) ; float y = 1.f + text_start_y + (text_inc_y * 3) ;
const float h = block.h; const float h = block.h;
@@ -781,7 +743,7 @@ void EntryMenu::Draw(NVGcontext* vg, Theme* theme) {
gfx::drawRectOutline(vg, theme, 4.f, Vec4{x, y, w, h}); gfx::drawRectOutline(vg, theme, 4.f, Vec4{x, y, w, h});
} }
gfx::drawTextArgs(vg, x + w / 2, y + h / 2, 22, NVG_ALIGN_MIDDLE | NVG_ALIGN_CENTER, theme->GetColour(ThemeEntryID_TEXT), option.display_text.c_str()); gfx::drawTextArgs(vg, x + w / 2, y + h / 2, 22, NVG_ALIGN_MIDDLE | NVG_ALIGN_CENTER, theme->GetColour(text_id), option.display_text.c_str());
y -= block.h + 18; y -= block.h + 18;
} }

View File

@@ -128,7 +128,7 @@ auto GetRomDatabaseFromPath(std::string_view path) -> int {
if (( if ((
p.folder.length() == db_name.length() && !strncasecmp(p.folder.data(), db_name.data(), p.folder.length())) || p.folder.length() == db_name.length() && !strncasecmp(p.folder.data(), db_name.data(), p.folder.length())) ||
(p.database.length() == db_name.length() && !strncasecmp(p.database.data(), db_name.data(), p.database.length()))) { (p.database.length() == db_name.length() && !strncasecmp(p.database.data(), db_name.data(), p.database.length()))) {
log_write("found it :) %.*s\n", p.database.length(), p.database.data()); log_write("found it :) %.*s\n", (int)p.database.length(), p.database.data());
return i; return i;
} }
} }
@@ -144,7 +144,7 @@ auto GetRomDatabaseFromPath(std::string_view path) -> int {
if (( if ((
p.folder.length() == db_name2.length() && !strcasecmp(p.folder.data(), db_name2.data())) || p.folder.length() == db_name2.length() && !strcasecmp(p.folder.data(), db_name2.data())) ||
(p.database.length() == db_name2.length() && !strcasecmp(p.database.data(), db_name2.data()))) { (p.database.length() == db_name2.length() && !strcasecmp(p.database.data(), db_name2.data()))) {
log_write("found it :) %.*s\n", p.database.length(), p.database.data()); log_write("found it :) %.*s\n", (int)p.database.length(), p.database.data());
return i; return i;
} }
} }
@@ -452,9 +452,8 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
Scan(m_path); Scan(m_path);
} else { } else {
char msg[FS_MAX_PATH]; const auto msg = std::string("Failed to rename file: ") + entry.name;
std::snprintf(msg, sizeof(msg), "Failed to rename file: %s", entry.name); App::Push(std::make_shared<ErrorBox>(rc, msg.c_str()));
App::Push(std::make_shared<ErrorBox>(rc, msg));
} }
} }
})); }));
@@ -478,10 +477,10 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
m_fs->CreateDirectoryRecursivelyWithPath(full_path); m_fs->CreateDirectoryRecursivelyWithPath(full_path);
if (R_SUCCEEDED(m_fs->CreateFile(full_path, 0, 0))) { if (R_SUCCEEDED(m_fs->CreateFile(full_path, 0, 0))) {
log_write("created file: %s\n", full_path); log_write("created file: %s\n", full_path.s);
Scan(m_path); Scan(m_path);
} else { } else {
log_write("failed to create file: %s\n", full_path); log_write("failed to create file: %s\n", full_path.s);
} }
} }
})); }));
@@ -499,10 +498,10 @@ Menu::Menu(const std::vector<NroEntry>& nro_entries) : MenuBase{"FileBrowser"_i1
} }
if (R_SUCCEEDED(m_fs->CreateDirectoryRecursively(full_path))) { if (R_SUCCEEDED(m_fs->CreateDirectoryRecursively(full_path))) {
log_write("created dir: %s\n", full_path); log_write("created dir: %s\n", full_path.s);
Scan(m_path); Scan(m_path);
} else { } else {
log_write("failed to create dir: %s\n", full_path); log_write("failed to create dir: %s\n", full_path.s);
} }
} }
})); }));
@@ -777,7 +776,7 @@ void Menu::InstallForwarder() {
} }
auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result { auto Menu::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result {
log_write("new scan path: %s\n", new_path); log_write("new scan path: %s\n", new_path.s);
if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) { if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) {
const LastFile f(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size()); const LastFile f(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size());
m_previous_highlighted_file.emplace_back(f); m_previous_highlighted_file.emplace_back(f);
@@ -868,7 +867,7 @@ auto Menu::FindFileAssocFor() -> std::vector<FileAssocEntry> {
if (assoc_db == PATHS[db_idx].folder || assoc_db == PATHS[db_idx].database) { if (assoc_db == PATHS[db_idx].folder || assoc_db == PATHS[db_idx].database) {
for (const auto& assoc_ext : assoc.ext) { for (const auto& assoc_ext : assoc.ext) {
if (assoc_ext == extension) { if (assoc_ext == extension) {
log_write("found ext: %s assoc_ext: %s assoc.ext: %s\n", assoc.path, assoc_ext.c_str(), extension.c_str()); log_write("found ext: %s assoc_ext: %s assoc.ext: %s\n", assoc.path.s, assoc_ext.c_str(), extension.c_str());
out_entries.emplace_back(assoc); out_entries.emplace_back(assoc);
} }
} }
@@ -886,7 +885,7 @@ auto Menu::FindFileAssocFor() -> std::vector<FileAssocEntry> {
if (assoc.database.empty()) { if (assoc.database.empty()) {
for (const auto& assoc_ext : assoc.ext) { for (const auto& assoc_ext : assoc.ext) {
if (assoc_ext == extension) { if (assoc_ext == extension) {
log_write("found ext: %s\n", assoc.path); log_write("found ext: %s\n", assoc.path.s);
out_entries.emplace_back(assoc); out_entries.emplace_back(assoc);
} }
} }
@@ -1099,7 +1098,6 @@ void Menu::SetIndexFromLastFile(const LastFile& last_file) {
} }
} }
SetIndex(index); SetIndex(index);
log_write("\nnew index: %zu %zu mod: %zu\n", m_index, index % 8);
} }
} }
@@ -1148,7 +1146,7 @@ void Menu::OnDeleteCallback() {
if (p.IsDir()) { if (p.IsDir()) {
pbox->NewTransfer("Scanning "_i18n + full_path); pbox->NewTransfer("Scanning "_i18n + full_path);
if (R_FAILED(get_collections(full_path, p.name, collections))) { if (R_FAILED(get_collections(full_path, p.name, collections))) {
log_write("failed to get dir collection: %s\n", full_path); log_write("failed to get dir collection: %s\n", full_path.s);
return false; return false;
} }
} }
@@ -1166,10 +1164,10 @@ void Menu::OnDeleteCallback() {
const auto full_path = GetNewPath(c.path, p.name); const auto full_path = GetNewPath(c.path, p.name);
pbox->NewTransfer("Deleting "_i18n + full_path); pbox->NewTransfer("Deleting "_i18n + full_path);
if (p.type == FsDirEntryType_Dir) { if (p.type == FsDirEntryType_Dir) {
log_write("deleting dir: %s\n", full_path); log_write("deleting dir: %s\n", full_path.s);
m_fs->DeleteDirectory(full_path); m_fs->DeleteDirectory(full_path);
} else { } else {
log_write("deleting file: %s\n", full_path); log_write("deleting file: %s\n", full_path.s);
m_fs->DeleteFile(full_path); m_fs->DeleteFile(full_path);
} }
} }
@@ -1194,10 +1192,10 @@ void Menu::OnDeleteCallback() {
pbox->NewTransfer("Deleting "_i18n + full_path); pbox->NewTransfer("Deleting "_i18n + full_path);
if (p.IsDir()) { if (p.IsDir()) {
log_write("deleting dir: %s\n", full_path); log_write("deleting dir: %s\n", full_path.s);
m_fs->DeleteDirectory(full_path); m_fs->DeleteDirectory(full_path);
} else { } else {
log_write("deleting file: %s\n", full_path); log_write("deleting file: %s\n", full_path.s);
m_fs->DeleteFile(full_path); m_fs->DeleteFile(full_path);
} }
} }
@@ -1212,8 +1210,6 @@ void Menu::OnDeleteCallback() {
} }
void Menu::OnPasteCallback() { void Menu::OnPasteCallback() {
bool use_progress_box{true};
// check if we only have 1 file / folder and is cut (rename) // check if we only have 1 file / folder and is cut (rename)
if (m_selected_files.size() == 1 && m_selected_type == SelectedType::Cut) { if (m_selected_files.size() == 1 && m_selected_type == SelectedType::Cut) {
const auto& entry = m_selected_files[0]; const auto& entry = m_selected_files[0];
@@ -1263,7 +1259,7 @@ void Menu::OnPasteCallback() {
if (p.IsDir()) { if (p.IsDir()) {
pbox->NewTransfer("Scanning "_i18n + full_path); pbox->NewTransfer("Scanning "_i18n + full_path);
if (R_FAILED(get_collections(full_path, p.name, collections))) { if (R_FAILED(get_collections(full_path, p.name, collections))) {
log_write("failed to get dir collection: %s\n", full_path); log_write("failed to get dir collection: %s\n", full_path.s);
return false; return false;
} }
} }
@@ -1300,7 +1296,7 @@ void Menu::OnPasteCallback() {
const auto src_path = GetNewPath(c.path, p.name); const auto src_path = GetNewPath(c.path, p.name);
const auto dst_path = GetNewPath(base_dst_path, p.name); const auto dst_path = GetNewPath(base_dst_path, p.name);
log_write("creating: %s to %s\n", src_path, dst_path); log_write("creating: %s to %s\n", src_path.s, dst_path.s);
pbox->NewTransfer("Creating "_i18n + dst_path); pbox->NewTransfer("Creating "_i18n + dst_path);
m_fs->CreateDirectory(dst_path); m_fs->CreateDirectory(dst_path);
} }
@@ -1315,7 +1311,7 @@ void Menu::OnPasteCallback() {
const auto dst_path = GetNewPath(base_dst_path, p.name); const auto dst_path = GetNewPath(base_dst_path, p.name);
pbox->NewTransfer("Copying "_i18n + src_path); pbox->NewTransfer("Copying "_i18n + src_path);
log_write("copying: %s to %s\n", src_path, dst_path); log_write("copying: %s to %s\n", src_path.s, dst_path.s);
R_TRY_RESULT(pbox->CopyFile(src_path, dst_path), false); R_TRY_RESULT(pbox->CopyFile(src_path, dst_path), false);
} }
} }
@@ -1415,7 +1411,7 @@ auto Menu::get_collections(const fs::FsPath& path, const fs::FsPath& parent_name
// get a list of all the files / dirs // get a list of all the files / dirs
FsDirCollection collection; FsDirCollection collection;
R_TRY(get_collection(path, parent_name, collection, true, true, false)); R_TRY(get_collection(path, parent_name, collection, true, true, false));
log_write("got collection: %s parent_name: %s files: %zu dirs: %zu\n", path, parent_name, collection.files.size(), collection.dirs.size()); log_write("got collection: %s parent_name: %s files: %zu dirs: %zu\n", path.s, parent_name.s, collection.files.size(), collection.dirs.size());
out.emplace_back(collection); out.emplace_back(collection);
// for (size_t i = 0; i < collection.dirs.size(); i++) { // for (size_t i = 0; i < collection.dirs.size(); i++) {
@@ -1423,7 +1419,7 @@ auto Menu::get_collections(const fs::FsPath& path, const fs::FsPath& parent_name
// use heap as to not explode the stack // use heap as to not explode the stack
const auto new_path = std::make_unique<fs::FsPath>(Menu::GetNewPath(path, p.name)); const auto new_path = std::make_unique<fs::FsPath>(Menu::GetNewPath(path, p.name));
const auto new_parent_name = std::make_unique<fs::FsPath>(Menu::GetNewPath(parent_name, p.name)); const auto new_parent_name = std::make_unique<fs::FsPath>(Menu::GetNewPath(parent_name, p.name));
log_write("trying to get nested collection: %s parent_name: %s\n", *new_path, *new_parent_name); log_write("trying to get nested collection: %s parent_name: %s\n", new_path->s, new_parent_name->s);
R_TRY(get_collections(*new_path, *new_parent_name, out)); R_TRY(get_collections(*new_path, *new_parent_name, out));
} }

View File

@@ -119,7 +119,7 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry
log_write("found zip\n"); log_write("found zip\n");
auto zfile = unzOpen64(temp_file); auto zfile = unzOpen64(temp_file);
if (!zfile) { if (!zfile) {
log_write("failed to open zip: %s\n", temp_file); log_write("failed to open zip: %s\n", temp_file.s);
return false; return false;
} }
ON_SCOPE_EXIT(unzClose(zfile)); ON_SCOPE_EXIT(unzClose(zfile));
@@ -155,29 +155,29 @@ auto DownloadApp(ProgressBox* pbox, const GhApiAsset& gh_asset, const AssetEntry
Result rc; Result rc;
if (file_path[strlen(file_path) -1] == '/') { if (file_path[strlen(file_path) -1] == '/') {
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create folder: %s 0x%04X\n", file_path, rc); log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
} else { } else {
if (R_FAILED(rc = fs.CreateDirectoryRecursivelyWithPath(file_path)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateDirectoryRecursivelyWithPath(file_path)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create folder: %s 0x%04X\n", file_path, rc); log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create file: %s 0x%04X\n", file_path, rc); log_write("failed to create file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
FsFile f; FsFile f;
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
log_write("failed to open file: %s 0x%04X\n", file_path, rc); log_write("failed to open file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
ON_SCOPE_EXIT(fsFileClose(&f)); ON_SCOPE_EXIT(fsFileClose(&f));
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
log_write("failed to set file size: %s 0x%04X\n", file_path, rc); log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }

View File

@@ -20,7 +20,7 @@ namespace {
auto GenerateStarPath(const fs::FsPath& nro_path) -> fs::FsPath { auto GenerateStarPath(const fs::FsPath& nro_path) -> fs::FsPath {
fs::FsPath out{}; fs::FsPath out{};
const auto dilem = std::strrchr(nro_path.s, '/'); const auto dilem = std::strrchr(nro_path.s, '/');
std::snprintf(out, sizeof(out), "%.*s.%s.star", dilem - nro_path.s + 1, nro_path.s, dilem + 1); std::snprintf(out, sizeof(out), "%.*s.%s.star", int(dilem - nro_path.s + 1), nro_path.s, dilem + 1);
return out; return out;
} }
@@ -237,8 +237,6 @@ void Menu::SetIndex(s64 index) {
m_list->SetYoff(0); m_list->SetYoff(0);
} }
const auto& e = m_entries[m_index];
if (IsStarEnabled()) { if (IsStarEnabled()) {
const auto star_path = GenerateStarPath(m_entries[m_index].path); const auto star_path = GenerateStarPath(m_entries[m_index].path);
if (fs::FsNativeSd().FileExists(star_path)) { if (fs::FsNativeSd().FileExists(star_path)) {
@@ -279,8 +277,8 @@ void Menu::ScanHomebrew() {
struct IniUser { struct IniUser {
std::vector<NroEntry>& entires; std::vector<NroEntry>& entires;
Hbini* ini; Hbini* ini{};
std::string last_section; std::string last_section{};
} ini_user{ m_entries }; } ini_user{ m_entries };
ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int { ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int {
@@ -331,9 +329,9 @@ void Menu::Sort() {
const auto name_cmp = [order](const NroEntry& lhs, const NroEntry& rhs) -> bool { const auto name_cmp = [order](const NroEntry& lhs, const NroEntry& rhs) -> bool {
auto r = strcasecmp(lhs.GetName(), rhs.GetName()); auto r = strcasecmp(lhs.GetName(), rhs.GetName());
if (!r) { if (!r) {
auto r = strcasecmp(lhs.GetAuthor(), rhs.GetAuthor()); r = strcasecmp(lhs.GetAuthor(), rhs.GetAuthor());
if (!r) { if (!r) {
auto r = strcasecmp(lhs.path, rhs.path); r = strcasecmp(lhs.path, rhs.path);
} }
} }
@@ -351,6 +349,7 @@ void Menu::Sort() {
} else if (!lhs.has_star.value() && rhs.has_star.value()) { } else if (!lhs.has_star.value() && rhs.has_star.value()) {
return false; return false;
} }
[[fallthrough]];
case SortType_Updated: { case SortType_Updated: {
auto lhs_timestamp = lhs.hbini.timestamp; auto lhs_timestamp = lhs.hbini.timestamp;
auto rhs_timestamp = rhs.hbini.timestamp; auto rhs_timestamp = rhs.hbini.timestamp;
@@ -376,6 +375,7 @@ void Menu::Sort() {
} else if (!lhs.has_star.value() && rhs.has_star.value()) { } else if (!lhs.has_star.value() && rhs.has_star.value()) {
return false; return false;
} }
[[fallthrough]];
case SortType_Size: { case SortType_Size: {
if (lhs.size == rhs.size) { if (lhs.size == rhs.size) {
return name_cmp(lhs, rhs); return name_cmp(lhs, rhs);
@@ -392,6 +392,7 @@ void Menu::Sort() {
} else if (!lhs.has_star.value() && rhs.has_star.value()) { } else if (!lhs.has_star.value() && rhs.has_star.value()) {
return false; return false;
} }
[[fallthrough]];
case SortType_Alphabetical: { case SortType_Alphabetical: {
return name_cmp(lhs, rhs); return name_cmp(lhs, rhs);
} break; } break;

View File

@@ -258,8 +258,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
const auto scale = std::min(scale_x, scale_y); const auto scale = std::min(scale_x, scale_y);
w = m_irs_width * scale; w = m_irs_width * scale;
h = m_irs_height * scale; h = m_irs_height * scale;
cx = (m_pos.x + m_pos.w / 2.0) - w / 2.0; cx = (m_pos.x + m_pos.w / 2.F) - w / 2.F;
cy = (m_pos.y + m_pos.h / 2.0) - h / 2.0; cy = (m_pos.y + m_pos.h / 2.F) - h / 2.F;
angle = 0; angle = 0;
} break; } break;
case Rotation_90: { case Rotation_90: {
@@ -268,8 +268,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
const auto scale = std::min(scale_x, scale_y); const auto scale = std::min(scale_x, scale_y);
w = m_irs_width * scale; w = m_irs_width * scale;
h = m_irs_height * scale; h = m_irs_height * scale;
cx = (m_pos.x + m_pos.w / 2.0) + h / 2.0; cx = (m_pos.x + m_pos.w / 2.F) + h / 2.F;
cy = (m_pos.y + m_pos.h / 2.0) - w / 2.0; cy = (m_pos.y + m_pos.h / 2.F) - w / 2.F;
angle = 90; angle = 90;
} break; } break;
case Rotation_180: { case Rotation_180: {
@@ -278,8 +278,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
const auto scale = std::min(scale_x, scale_y); const auto scale = std::min(scale_x, scale_y);
w = m_irs_width * scale; w = m_irs_width * scale;
h = m_irs_height * scale; h = m_irs_height * scale;
cx = (m_pos.x + m_pos.w / 2.0) + w / 2.0; cx = (m_pos.x + m_pos.w / 2.F) + w / 2.F;
cy = (m_pos.y + m_pos.h / 2.0) + h / 2.0; cy = (m_pos.y + m_pos.h / 2.F) + h / 2.F;
angle = 180; angle = 180;
} break; } break;
case Rotation_270: { case Rotation_270: {
@@ -288,8 +288,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
const auto scale = std::min(scale_x, scale_y); const auto scale = std::min(scale_x, scale_y);
w = m_irs_width * scale; w = m_irs_width * scale;
h = m_irs_height * scale; h = m_irs_height * scale;
cx = (m_pos.x + m_pos.w / 2.0) - h / 2.0; cx = (m_pos.x + m_pos.w / 2.F) - h / 2.F;
cy = (m_pos.y + m_pos.h / 2.0) + w / 2.0; cy = (m_pos.y + m_pos.h / 2.F) + w / 2.F;
angle = 270; angle = 270;
} break; } break;
} }
@@ -382,7 +382,7 @@ void Menu::LoadDefaultConfig() {
irsGetClusteringProcessorDefaultConfig(&m_clustering_config); irsGetClusteringProcessorDefaultConfig(&m_clustering_config);
irsGetIrLedProcessorDefaultConfig(&m_led_config); irsGetIrLedProcessorDefaultConfig(&m_led_config);
m_tera_config; m_tera_config = {};
m_adaptive_config = {}; m_adaptive_config = {};
m_hand_config = {}; m_hand_config = {};

View File

@@ -54,7 +54,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
if (!pbox->ShouldExit()) { if (!pbox->ShouldExit()) {
auto zfile = unzOpen64(zip_out); auto zfile = unzOpen64(zip_out);
if (!zfile) { if (!zfile) {
log_write("failed to open zip: %s\n", zip_out); log_write("failed to open zip: %s\n", zip_out.s);
return false; return false;
} }
ON_SCOPE_EXIT(unzClose(zfile)); ON_SCOPE_EXIT(unzClose(zfile));
@@ -96,25 +96,25 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
Result rc; Result rc;
if (file_path[strlen(file_path) -1] == '/') { if (file_path[strlen(file_path) -1] == '/') {
if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateDirectoryRecursively(file_path)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create folder: %s 0x%04X\n", file_path, rc); log_write("failed to create folder: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
} else { } else {
Result rc; Result rc;
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create file: %s 0x%04X\n", file_path, rc); log_write("failed to create file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
FsFile f; FsFile f;
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
log_write("failed to open file: %s 0x%04X\n", file_path, rc); log_write("failed to open file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
ON_SCOPE_EXIT(fsFileClose(&f)); ON_SCOPE_EXIT(fsFileClose(&f));
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
log_write("failed to set file size: %s 0x%04X\n", file_path, rc); log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
@@ -128,7 +128,7 @@ auto InstallUpdate(ProgressBox* pbox, const std::string url, const std::string v
} }
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
log_write("failed to write file: %s 0x%04X\n", file_path, rc); log_write("failed to write file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }

View File

@@ -13,7 +13,7 @@
#include "i18n.hpp" #include "i18n.hpp"
#include <minIni.h> #include <minIni.h>
#include <nanovg/stb_image.h> #include <stb_image.h>
#include <cstring> #include <cstring>
#include <minizip/unzip.h> #include <minizip/unzip.h>
#include <yyjson.h> #include <yyjson.h>
@@ -102,32 +102,10 @@ auto apiBuildUrlDownloadInternal(const std::string& id, bool is_pack) -> std::st
// https://api.themezer.net/?query=query{downloadPack(id:"11"){filename,url,mimetype}} // https://api.themezer.net/?query=query{downloadPack(id:"11"){filename,url,mimetype}}
} }
auto apiBuildUrlDownloadTheme(const ThemeEntry& e) -> std::string {
return apiBuildUrlDownloadInternal(e.id, false);
}
auto apiBuildUrlDownloadPack(const PackListEntry& e) -> std::string { auto apiBuildUrlDownloadPack(const PackListEntry& e) -> std::string {
return apiBuildUrlDownloadInternal(e.id, true); return apiBuildUrlDownloadInternal(e.id, true);
} }
auto apiBuildFilePack(const PackListEntry& e) -> fs::FsPath {
fs::FsPath path;
std::snprintf(path, sizeof(path), "%s/%s By %s/", THEME_FOLDER, e.details.name.c_str(), e.creator.display_name.c_str());
return path;
}
#if 0
auto apiBuildUrlPack(const PackListEntry& e) -> std::string {
char url[2048];
std::snprintf(url, sizeof(url), "https://api.themezer.net/?query=query($id:String!){pack(id:$id){id,creator{display_name},details{name,description},last_updated,categories,dl_count,like_count,themes{id,details{name},layout{id,details{name}},categories,target,preview{original,thumb},last_updated,dl_count,like_count}}}&variables={\"id\":\"%s\"}", e.id.c_str());
return url;
}
#endif
auto apiBuildUrlThemeList(const Config& e) -> std::string {
return apiBuildUrlListInternal(e, false);
}
auto apiBuildUrlListPacks(const Config& e) -> std::string { auto apiBuildUrlListPacks(const Config& e) -> std::string {
return apiBuildUrlListInternal(e, true); return apiBuildUrlListInternal(e, true);
} }
@@ -171,7 +149,6 @@ auto loadThemeImage(ThemeEntry& e) -> bool {
if (!image.image) { if (!image.image) {
log_write("failed to load image from file: %s\n", path.s); log_write("failed to load image from file: %s\n", path.s);
log_write("failed to load image from file: %s\n", path);
return false; return false;
} else { } else {
// log_write("loaded image from file: %s\n", path); // log_write("loaded image from file: %s\n", path);
@@ -189,35 +166,18 @@ void from_json(yyjson_val* json, Creator& e) {
void from_json(yyjson_val* json, Details& e) { void from_json(yyjson_val* json, Details& e) {
JSON_OBJ_ITR( JSON_OBJ_ITR(
JSON_SET_STR(name); JSON_SET_STR(name);
// JSON_SET_STR(description);
); );
} }
void from_json(yyjson_val* json, Preview& e) { void from_json(yyjson_val* json, Preview& e) {
JSON_OBJ_ITR( JSON_OBJ_ITR(
// JSON_SET_STR(original);
JSON_SET_STR(thumb); JSON_SET_STR(thumb);
); );
} }
void from_json(yyjson_val* json, DownloadPack& e) {
JSON_OBJ_ITR(
JSON_SET_STR(filename);
JSON_SET_STR(url);
JSON_SET_STR(mimetype);
);
}
void from_json(yyjson_val* json, ThemeEntry& e) { void from_json(yyjson_val* json, ThemeEntry& e) {
JSON_OBJ_ITR( JSON_OBJ_ITR(
JSON_SET_STR(id); JSON_SET_STR(id);
// JSON_SET_OBJ(creator);
// JSON_SET_OBJ(details);
// JSON_SET_STR(last_updated);
// JSON_SET_UINT(dl_count);
// JSON_SET_UINT(like_count);
// JSON_SET_ARR_STR(categories);
// JSON_SET_STR(target);
JSON_SET_OBJ(preview); JSON_SET_OBJ(preview);
); );
} }
@@ -227,10 +187,6 @@ void from_json(yyjson_val* json, PackListEntry& e) {
JSON_SET_STR(id); JSON_SET_STR(id);
JSON_SET_OBJ(creator); JSON_SET_OBJ(creator);
JSON_SET_OBJ(details); JSON_SET_OBJ(details);
// JSON_SET_STR(last_updated);
// JSON_SET_ARR_STR(categories);
// JSON_SET_UINT(dl_count);
// JSON_SET_UINT(like_count);
JSON_SET_ARR_OBJ(themes); JSON_SET_ARR_OBJ(themes);
); );
} }
@@ -246,7 +202,6 @@ void from_json(yyjson_val* json, Pagination& e) {
void from_json(const std::vector<u8>& data, DownloadPack& e) { void from_json(const std::vector<u8>& data, DownloadPack& e) {
JSON_INIT_VEC(data, "data"); JSON_INIT_VEC(data, "data");
// JSON_GET_OBJ("downloadTheme");
JSON_GET_OBJ("downloadPack"); JSON_GET_OBJ("downloadPack");
JSON_OBJ_ITR( JSON_OBJ_ITR(
JSON_SET_STR(filename); JSON_SET_STR(filename);
@@ -310,14 +265,14 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
// create directories // create directories
fs::FsPath dir_path; fs::FsPath dir_path;
std::snprintf(dir_path, sizeof(dir_path), "%s/%s - By %s", THEME_FOLDER, entry.details.name.c_str(), entry.creator.display_name.c_str()); std::snprintf(dir_path, sizeof(dir_path), "%s/%s - By %s", THEME_FOLDER.s, entry.details.name.c_str(), entry.creator.display_name.c_str());
fs.CreateDirectoryRecursively(dir_path); fs.CreateDirectoryRecursively(dir_path);
// 3. extract the zip // 3. extract the zip
if (!pbox->ShouldExit()) { if (!pbox->ShouldExit()) {
auto zfile = unzOpen64(zip_out); auto zfile = unzOpen64(zip_out);
if (!zfile) { if (!zfile) {
log_write("failed to open zip: %s\n", zip_out); log_write("failed to open zip: %s\n", zip_out.s);
return false; return false;
} }
ON_SCOPE_EXIT(unzClose(zfile)); ON_SCOPE_EXIT(unzClose(zfile));
@@ -352,19 +307,19 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
Result rc; Result rc;
if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) { if (R_FAILED(rc = fs.CreateFile(file_path, info.uncompressed_size, 0)) && rc != FsError_PathAlreadyExists) {
log_write("failed to create file: %s 0x%04X\n", file_path, rc); log_write("failed to create file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
FsFile f; FsFile f;
if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) { if (R_FAILED(rc = fs.OpenFile(file_path, FsOpenMode_Write, &f))) {
log_write("failed to open file: %s 0x%04X\n", file_path, rc); log_write("failed to open file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
ON_SCOPE_EXIT(fsFileClose(&f)); ON_SCOPE_EXIT(fsFileClose(&f));
if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) { if (R_FAILED(rc = fsFileSetSize(&f, info.uncompressed_size))) {
log_write("failed to set file size: %s 0x%04X\n", file_path, rc); log_write("failed to set file size: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
@@ -382,7 +337,7 @@ auto InstallTheme(ProgressBox* pbox, const PackListEntry& entry) -> bool {
} }
if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) { if (R_FAILED(rc = fsFileWrite(&f, offset, buf.data(), bytes_read, FsWriteOption_None))) {
log_write("failed to write file: %s 0x%04X\n", file_path, rc); log_write("failed to write file: %s 0x%04X\n", file_path.s, rc);
return false; return false;
} }
@@ -618,7 +573,6 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
} }
const float xoff = (350 - 320) / 2; const float xoff = (350 - 320) / 2;
const float yoff = (350 - 320) / 2;
// lazy load image // lazy load image
if (e.themes.size()) { if (e.themes.size()) {
@@ -638,7 +592,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) {
switch (image.state) { switch (image.state) {
case ImageDownloadState::None: { case ImageDownloadState::None: {
const auto path = apiBuildIconCache(theme); const auto path = apiBuildIconCache(theme);
log_write("downloading theme!: %s\n", path); log_write("downloading theme!: %s\n", path.s);
const auto url = theme.preview.thumb; const auto url = theme.preview.thumb;
log_write("downloading url: %s\n", url.c_str()); log_write("downloading url: %s\n", url.c_str());
@@ -759,8 +713,8 @@ void Menu::PackListDownload() {
std::snprintf(subheading, sizeof(subheading), "Page %zu / %zu"_i18n.c_str(), m_page_index+1, m_page_index_max); std::snprintf(subheading, sizeof(subheading), "Page %zu / %zu"_i18n.c_str(), m_page_index+1, m_page_index_max);
SetSubHeading(subheading); SetSubHeading(subheading);
log_write("a.pagination.page: %u\n", a.pagination.page); log_write("a.pagination.page: %zu\n", a.pagination.page);
log_write("a.pagination.page_count: %u\n", a.pagination.page_count); log_write("a.pagination.page_count: %zu\n", a.pagination.page_count);
} }
}); });
} }

View File

@@ -10,7 +10,7 @@
namespace sphaira::ui::gfx { namespace sphaira::ui::gfx {
namespace { namespace {
static constexpr std::array buttons = { constexpr std::array buttons = {
std::pair{Button::A, "\uE0E0"}, std::pair{Button::A, "\uE0E0"},
std::pair{Button::B, "\uE0E1"}, std::pair{Button::B, "\uE0E1"},
std::pair{Button::X, "\uE0E2"}, std::pair{Button::X, "\uE0E2"},
@@ -60,18 +60,18 @@ void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, con
float gradientX, gradientY, color; float gradientX, gradientY, color;
getHighlightAnimation(&gradientX, &gradientY, &color); getHighlightAnimation(&gradientX, &gradientY, &color);
const auto strokeWidth = 5.0; const auto strokeWidth = 5.F;
auto v2 = v; auto v2 = v;
v2.x -= strokeWidth / 2.0; v2.x -= strokeWidth / 2.F;
v2.y -= strokeWidth / 2.0; v2.y -= strokeWidth / 2.F;
v2.w += strokeWidth; v2.w += strokeWidth;
v2.h += strokeWidth; v2.h += strokeWidth;
const auto corner_radius = 0.5; const auto corner_radius = 0.5F;
const auto shadow_width = 2.0f; const auto shadow_width = 2.F;
const auto shadow_offset = 10.0f; const auto shadow_offset = 10.F;
const auto shadow_feather = 10.0f; const auto shadow_feather = 10.F;
const auto shadow_opacity = 128.0f; const auto shadow_opacity = 128.F;
// Shadow // Shadow
NVGpaint shadowPaint = nvgBoxGradient(vg, NVGpaint shadowPaint = nvgBoxGradient(vg,
@@ -136,15 +136,6 @@ void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, con
nvgFill(vg); nvgFill(vg);
} }
void drawRectOutlineInternal(NVGcontext* vg, const Theme* theme, float size, const Vec4& v, const NVGpaint& p) {
const auto corner_radius = 0.5;
drawRectOutlineInternal(vg, theme, size, v);
nvgBeginPath(vg);
nvgRoundedRect(vg, v.x, v.y, v.w, v.h, corner_radius);
nvgFillPaint(vg, p);
nvgFill(vg);
}
void drawTextIntenal(NVGcontext* vg, const Vec2& v, float size, const char* str, const char* end, int align, const NVGcolor& c) { void drawTextIntenal(NVGcontext* vg, const Vec2& v, float size, const char* str, const char* end, int align, const NVGcolor& c) {
nvgBeginPath(vg); nvgBeginPath(vg);
nvgFontSize(vg, size); nvgFontSize(vg, size);
@@ -173,20 +164,6 @@ void drawTextArgs(NVGcontext* vg, float x, float y, float size, int align, const
drawText(vg, x, y, size, buffer, nullptr, align, c); drawText(vg, x, y, size, buffer, nullptr, align, c);
} }
static void drawImageInternal(NVGcontext* vg, const Vec4& v, int texture, int rounded = 0) {
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f);
// drawRect(vg, x, y, w, h, paint);
nvgBeginPath(vg);
// nvgRect(vg, x, y, w, h);
if (rounded == 0) {
nvgRect(vg, v.x, v.y, v.w, v.h);
} else {
nvgRoundedRect(vg, v.x, v.y, v.w, v.h, rounded);
}
nvgFillPaint(vg, paint);
nvgFill(vg);
}
void drawImage(NVGcontext* vg, const Vec4& v, int texture) { void drawImage(NVGcontext* vg, const Vec4& v, int texture) {
const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f); const auto paint = nvgImagePattern(vg, v.x, v.y, v.w, v.h, 0, texture, 1.f);
drawRect(vg, v, paint, false); drawRect(vg, v, paint, false);

View File

@@ -31,7 +31,6 @@ ProgressBox::ProgressBox(const std::string& title, ProgressBoxCallback callback,
m_pos.h = 430.f; m_pos.h = 430.f;
m_pos.x = 255; m_pos.x = 255;
m_pos.y = 145; m_pos.y = 145;
145 + 430; // 575, 200, 420
m_pos.w = 770.f; m_pos.w = 770.f;
m_pos.h = 295.f; m_pos.h = 295.f;
@@ -99,7 +98,7 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void {
gfx::drawTextArgs(vg, center_x, m_pos.y + 60, 25, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), title.c_str()); gfx::drawTextArgs(vg, center_x, m_pos.y + 60, 25, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), title.c_str());
if (!transfer.empty()) { if (!transfer.empty()) {
gfx::drawTextArgs(vg, center_x, prog_bar.y - 15 - 20 * 1.5, 20, NVG_ALIGN_CENTER, theme->GetColour(ThemeEntryID_TEXT), "%s", transfer.c_str()); gfx::drawTextArgs(vg, center_x, prog_bar.y - 15 - 20 * 1.5F, 20, NVG_ALIGN_CENTER, theme->GetColour(ThemeEntryID_TEXT), "%s", transfer.c_str());
} }
} }

View File

@@ -9,9 +9,9 @@ namespace sphaira::ui {
ScrollableText::ScrollableText(const std::string& text, float x, float y, float y_clip, float w, float font_size) ScrollableText::ScrollableText(const std::string& text, float x, float y, float y_clip, float w, float font_size)
: m_font_size{font_size} : m_font_size{font_size}
, m_y_off_base{y} , m_y_off_base{y}
, m_y_off{y}
, m_clip_y{y_clip} , m_clip_y{y_clip}
, m_end_w{w} , m_end_w{w}
, m_y_off{y}
{ {
SetActions( SetActions(
std::make_pair(Button::LS_DOWN, Action{[this](){ std::make_pair(Button::LS_DOWN, Action{[this](){

View File

@@ -274,7 +274,7 @@ auto Sidebar::Draw(NVGcontext* vg, Theme* theme) -> void {
gfx::drawRect(vg, m_pos, theme->GetColour(ThemeEntryID_SIDEBAR)); gfx::drawRect(vg, m_pos, theme->GetColour(ThemeEntryID_SIDEBAR));
gfx::drawText(vg, m_title_pos, m_title_size, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str()); gfx::drawText(vg, m_title_pos, m_title_size, theme->GetColour(ThemeEntryID_TEXT), m_title.c_str());
if (!m_sub.empty()) { if (!m_sub.empty()) {
gfx::drawTextArgs(vg, m_pos.x + m_pos.w - 30.f, m_title_pos.y + 10.f, 18, NVG_ALIGN_TOP | NVG_ALIGN_RIGHT, theme->GetColour(ThemeEntryID_TEXT), m_sub.c_str()); gfx::drawTextArgs(vg, m_pos.x + m_pos.w - 30.f, m_title_pos.y + 10.f, 16, NVG_ALIGN_TOP | NVG_ALIGN_RIGHT, theme->GetColour(ThemeEntryID_TEXT_INFO), m_sub.c_str());
} }
gfx::drawRect(vg, m_top_bar, theme->GetColour(ThemeEntryID_LINE)); gfx::drawRect(vg, m_top_bar, theme->GetColour(ThemeEntryID_LINE));
gfx::drawRect(vg, m_bottom_bar, theme->GetColour(ThemeEntryID_LINE)); gfx::drawRect(vg, m_bottom_bar, theme->GetColour(ThemeEntryID_LINE));