flow improvements

This commit is contained in:
2026-04-25 16:02:39 +03:00
parent 22b669fae0
commit 4ffa6ed970
21 changed files with 150 additions and 59 deletions
+13 -13
View File
@@ -41,25 +41,25 @@ int main() {
exit(res);
}
loadTitles();
printf("main");
// First create our renderer, where one can customize SDL or other stuff's
// initialization.
auto renderer_opts = pu::ui::render::RendererInitOptions(
SDL_INIT_EVERYTHING, pu::ui::render::RendererHardwareFlags);
renderer_opts.UseImage(pu::ui::render::IMGAllFlags);
renderer_opts.UseAudio(pu::ui::render::MixerAllFlags);
renderer_opts.UseTTF();
// First create our renderer, where one can customize SDL or other stuff's
// initialization.
auto renderer_opts = pu::ui::render::RendererInitOptions(
SDL_INIT_EVERYTHING, pu::ui::render::RendererHardwareFlags);
renderer_opts.UseImage(pu::ui::render::IMGAllFlags);
renderer_opts.UseAudio(pu::ui::render::MixerAllFlags);
renderer_opts.UseTTF();
auto renderer = pu::ui::render::Renderer::New(renderer_opts);
// Create our main application from the renderer
auto main = ui::MainApplication::New(renderer);
// Create our main application from the renderer
auto main = ui::MainApplication::New(renderer);
main->Prepare();
main->Prepare();
main->Show();
main->Show();
servicesExit();
servicesExit();
return 0;
}
+23 -7
View File
@@ -11,15 +11,25 @@ static std::vector<uint64_t> accSids, devSids, bcatSids, cacheSids;
namespace ui {
extern MainApplication *mainApp;
void TitlesLayout::InitTitles() {
this->titlesMenu = pu::ui::elm::Menu::New(0, 0, 1280, COLOR("#67000000"), COLOR("#170909FF"), 94, 7);
for (size_t i = 0; i < getTitleCount(g_currentUId); i++) {
Title title;
getTitle(title, g_currentUId, i);
auto titleItem = pu::ui::elm::MenuItem::New(title.name().c_str());
titleItem->SetColor(COLOR("#FFFFFFFF"));
this->titlesMenu->AddItem(titleItem);
Logger::getInstance().log(Logger::INFO, "InitTitles");
auto it = this->menuCache.find(g_currentUId);
if (it != this->menuCache.end()) {
this->titlesMenu = it->second;
} else {
auto menu = pu::ui::elm::Menu::New(0, 0, 1280, COLOR("#67000000"), COLOR("#170909FF"), 94, 7);
for (size_t i = 0; i < getTitleCount(g_currentUId); i++) {
Title title;
getTitle(title, g_currentUId, i);
auto titleItem = pu::ui::elm::MenuItem::New(title.name().c_str());
titleItem->SetColor(COLOR("#FFFFFFFF"));
menu->AddItem(titleItem);
}
this->menuCache.emplace(g_currentUId, menu);
this->titlesMenu = menu;
}
this->Clear();
this->Add(this->titlesMenu);
this->SetBackgroundColor(BACKGROUND_COLOR);
@@ -28,6 +38,11 @@ namespace ui {
void TitlesLayout::onInput(u64 Down, u64 Up, u64 Held, pu::ui::TouchPoint Pos) {
if (m_inputLocked) return;
if (Down & HidNpadButton_B) {
mainApp->LoadLayout(mainApp->usersLayout);
return;
}
if (Down & HidNpadButton_Plus) {
cancelClientTransfer();
cancelServerTransfer();
@@ -60,6 +75,7 @@ namespace ui {
}
while (!isClientTransferDone()) {
ovl->SetStatus(getClientStatusText());
ovl->SetProgressVisible(isClientProgressKnown());
ovl->SetProgress(getClientProgress());
mainApp->CallForRender();
if (mainApp->GetButtonsDown() & HidNpadButton_B) {
+27 -4
View File
@@ -10,12 +10,22 @@ namespace ui {
this->usersMenu->SetScrollbarColor(COLOR("#170909FF"));
for (AccountUid const& uid : Account::ids()) {
auto username = pu::ui::elm::MenuItem::New(Account::username(uid) + ": " + std::to_string(getTitleCount(uid)));
username->SetColor(COLOR("#FFFFFFFF"));
this->usersMenu->AddItem(username);
auto item = pu::ui::elm::MenuItem::New(Account::username(uid));
item->SetColor(COLOR("#FFFFFFFF"));
this->usersMenu->AddItem(item);
}
this->loadingBg = pu::ui::elm::Rectangle::New(0, 0, 1280, 720, pu::ui::Color(30, 30, 30, 220));
this->loadingBg->SetVisible(false);
this->loadingText = pu::ui::elm::TextBlock::New(480, 340, "Reading game list...");
this->loadingText->SetColor(pu::ui::Color(255, 255, 255, 255));
this->loadingText->SetVisible(false);
this->SetBackgroundColor(BACKGROUND_COLOR);
this->Add(this->usersMenu);
this->Add(this->loadingBg);
this->Add(this->loadingText);
}
int32_t UsersLayout::GetCurrentIndex() {
@@ -29,8 +39,21 @@ namespace ui {
}
if (Down & HidNpadButton_A) {
printf("current index is %i\n", this->usersMenu->GetSelectedIndex());
g_currentUId = Account::ids().at(this->usersMenu->GetSelectedIndex());
if (!areTitlesLoaded()) {
this->usersMenu->SetVisible(false);
this->loadingBg->SetVisible(true);
this->loadingText->SetVisible(true);
mainApp->CallForRender();
loadTitles();
this->loadingBg->SetVisible(false);
this->loadingText->SetVisible(false);
this->usersMenu->SetVisible(true);
}
mainApp->titlesLayout->InitTitles();
mainApp->LoadLayout(mainApp->titlesLayout);
}
+15 -5
View File
@@ -31,7 +31,16 @@ static std::map<AccountUid, User> mUsers;
Result Account::init(void)
{
return accountInitialize(AccountServiceType_Application);
Result res = accountInitialize(AccountServiceType_Application);
if (R_FAILED(res)) return res;
AccountUid uids[8];
s32 count = 0;
accountListAllUsers(uids, 8, &count);
for (s32 i = 0; i < count; i++) {
Account::username(uids[i]); // populates mUsers as side effect
}
return 0;
}
void Account::exit(void)
@@ -55,11 +64,12 @@ static User getUser(AccountUid id)
AccountProfileBase profilebase;
memset(&profilebase, 0, sizeof(profilebase));
if (R_SUCCEEDED(accountGetProfile(&profile, id)) && R_SUCCEEDED(accountProfileGet(&profile, NULL, &profilebase))) {
user.name = std::string(profilebase.nickname);
if (R_SUCCEEDED(accountGetProfile(&profile, id))) {
if (R_SUCCEEDED(accountProfileGet(&profile, NULL, &profilebase))) {
user.name = std::string(profilebase.nickname);
}
accountProfileClose(&profile);
}
accountProfileClose(&profile);
return user;
}
+1
View File
@@ -30,6 +30,7 @@ static TransferState g_client_state;
bool isClientTransferDone() { return g_client_state.done.load(); }
bool isClientTransferCancelled() { return g_client_state.cancelled.load(); }
bool isClientConnectionFailed() { return g_client_state.connection_failed.load(); }
bool isClientProgressKnown() { return g_client_state.bytes_total.load() > 0; }
void cancelClientTransfer() { g_client_state.cancelled.store(true); }
double getClientProgress() { return g_client_state.progress(); }
std::string getClientStatusText() { return g_client_state.getStatus(); }
+2 -3
View File
@@ -45,10 +45,9 @@ Directory::Directory(const std::string& root)
struct DirectoryEntry de = {name, directory};
mList.push_back(de);
}
closedir(dir);
mGood = true;
}
closedir(dir);
mGood = true;
}
Result Directory::error(void)
+6
View File
@@ -62,6 +62,10 @@ void io::copyFile(const std::string& srcPath, const std::string& dstPath)
while (offset < sz) {
u32 count = fread((char*)buf, 1, BUFFER_SIZE, src);
if (count == 0) {
Logger::getInstance().log(Logger::ERROR, "fread returned 0 for file {} at offset {}/{} with errno {}. Aborting copy.", srcPath, offset, sz, errno);
break;
}
fwrite((char*)buf, 1, count, dst);
offset += count;
}
@@ -161,6 +165,7 @@ std::tuple<bool, Result, std::string> io::backup(size_t index, AccountUid uid)
if (R_SUCCEEDED(res)) {
int rc = FileSystem::mount(fileSystem);
if (rc == -1) {
fsFsClose(&fileSystem);
FileSystem::unmount();
Logger::getInstance().log(Logger::ERROR, "Failed to mount filesystem during backup. Title id: 0x%016lX; User id: 0x%lX%lX.", title.id(),
title.userId().uid[1], title.userId().uid[0]);
@@ -257,6 +262,7 @@ std::tuple<bool, Result, std::string> io::restore(size_t index, AccountUid uid,
if (R_SUCCEEDED(res)) {
int rc = FileSystem::mount(fileSystem);
if (rc == -1) {
fsFsClose(&fileSystem);
FileSystem::unmount();
Logger::getInstance().log(Logger::ERROR, "Failed to mount filesystem during restore. Title id: 0x%016lX; User id: 0x%lX%lX.", title.id(),
uid.uid[1], uid.uid[0]);
+9 -2
View File
@@ -123,7 +123,7 @@ static void receive_file(int sock, const std::string& relative_path, uint64_t fi
static void* handle_client(void* socket_desc) {
int client_socket = *(int*)socket_desc;
free(socket_desc);
delete static_cast<int*>(socket_desc);
while (true) {
uint32_t filename_len = 0;
@@ -186,7 +186,11 @@ static void* accept_and_handle(void* arg) {
if (client_socket >= 0) {
g_server_client_sock.store(client_socket);
int* pclient = new (std::nothrow) int(client_socket);
if (pclient) handle_client(pclient);
if (pclient) {
handle_client(pclient);
} else {
close(client_socket);
}
g_server_client_sock.store(-1);
}
@@ -203,6 +207,9 @@ static void* broadcast_listener(void* arg) {
g_broadcast_sock.store(udp.fd);
struct timeval tv{0, 100000}; // 100ms poll so cancel is detected quickly
setsockopt(udp, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
+9 -15
View File
@@ -28,6 +28,12 @@
#include "main.hpp"
static std::unordered_map<AccountUid, std::vector<Title>> titles;
static bool s_titlesLoaded = false;
bool areTitlesLoaded(void)
{
return s_titlesLoaded;
}
void Title::init(u8 saveDataType, u64 id, AccountUid userID, const std::string& name, const std::string& author)
{
@@ -176,25 +182,13 @@ void Title::refreshDirectories(void)
else {
Logger::getInstance().log(Logger::ERROR, "Couldn't retrieve the extdata directory list for the title " + name());
}
// save backups from configuration
// std::vector<std::string> additionalFolders = Configuration::getInstance().additionalSaveFolders(mId);
// for (std::vector<std::string>::const_iterator it = additionalFolders.begin(); it != additionalFolders.end(); ++it) {
// we have other folders to parse
// Directory list(*it);
// if (list.good()) {
// for (size_t i = 0, sz = list.size(); i < sz; i++) {
// if (list.folder(i)) {
// mSaves.push_back(list.entry(i));
// mFullSavePaths.push_back(*it + "/" + list.entry(i));
// }
// }
// }
// }
}
void loadTitles(void)
{
if (s_titlesLoaded) return;
s_titlesLoaded = true;
titles.clear();
FsSaveDataInfoReader reader;
+14 -3
View File
@@ -43,10 +43,8 @@ Result servicesInit(void)
io::createDirectory("sdmc:/switch/NXST");
io::createDirectory("sdmc:/switch/NXST/saves");
Logger::getInstance().log(Logger::INFO, "Starting Checkpoint loading...");
if (appletGetAppletType() != AppletType_Application) {
Logger::getInstance().log(Logger::WARN, "Please do not run Checkpoint in applet mode.");
Logger::getInstance().log(Logger::WARN, "Please do not run NXST in applet mode.");
}
// Result socinit = 0;
@@ -76,6 +74,19 @@ Result servicesInit(void)
return res;
}
if (R_FAILED(res = nsInitialize())) {
Logger::getInstance().log(Logger::ERROR, "nsInitialize failed. Result code 0x{:08X}.", res);
return res;
}
if (R_SUCCEEDED(res = hidsysInitialize())) {
g_notificationLedAvailable = true;
}
else {
Logger::getInstance().log(Logger::INFO, "Notification led not available. Result code 0x{:08X}.", res);
}
Logger::getInstance().log(Logger::INFO, "NXST loading completed!");
return 0;