flow improvements
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
@@ -38,8 +38,7 @@ EXEFS_SRC := exefs_src
|
||||
APP_TITLE := NXST
|
||||
APP_AUTHOR := DragonSpirit
|
||||
APP_VERSION := 04.24.2026
|
||||
ICON := icon.jpg
|
||||
|
||||
ICON := icon.png
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
@@ -51,7 +50,7 @@ CFLAGS += -g -O2 -ffunction-sections \
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__SWITCH__ -D_GNU_SOURCE=1
|
||||
|
||||
CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
|
||||
CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 -g
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
@@ -155,6 +154,8 @@ clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf $(TARGET).lst
|
||||
|
||||
cleanbuild: clean all
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
send: $(BUILD)
|
||||
@nxlink $(TARGET).nro
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#include <pu/Plutonium>
|
||||
#include <const.h>
|
||||
#include <title.hpp>
|
||||
#include <account.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ui {
|
||||
class TitlesLayout : public pu::ui::Layout {
|
||||
private:
|
||||
|
||||
pu::ui::elm::Menu::Ref titlesMenu;
|
||||
std::unordered_map<AccountUid, pu::ui::elm::Menu::Ref> menuCache;
|
||||
bool m_inputLocked = false;
|
||||
|
||||
public:
|
||||
|
||||
@@ -51,6 +51,20 @@ namespace ui {
|
||||
void SetProgress(double val) {
|
||||
progressBar->SetProgress(val);
|
||||
}
|
||||
|
||||
void SetProgressVisible(bool visible) {
|
||||
progressBar->SetVisible(visible);
|
||||
if (visible) {
|
||||
this->SetHeight(OvlH);
|
||||
this->SetY(OvlY);
|
||||
hintText->SetY(195);
|
||||
} else {
|
||||
static constexpr int SmallH = 160;
|
||||
this->SetHeight(SmallH);
|
||||
this->SetY((720 - SmallH) / 2);
|
||||
hintText->SetY(120);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace ui {
|
||||
private:
|
||||
|
||||
pu::ui::elm::Menu::Ref usersMenu;
|
||||
pu::ui::elm::Rectangle::Ref loadingBg;
|
||||
pu::ui::elm::TextBlock::Ref loadingText;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@ inline bool operator==(const AccountUid& x, u64 y)
|
||||
|
||||
inline bool operator<(const AccountUid& x, const AccountUid& y)
|
||||
{
|
||||
return x.uid[0] < y.uid[0] && x.uid[1] == y.uid[1];
|
||||
if (x.uid[0] != y.uid[0]) return x.uid[0] < y.uid[0];
|
||||
return x.uid[1] < y.uid[1];
|
||||
}
|
||||
|
||||
struct User {
|
||||
|
||||
@@ -5,6 +5,7 @@ int transfer_files(size_t index, AccountUid uid);
|
||||
bool isClientTransferDone();
|
||||
bool isClientTransferCancelled();
|
||||
bool isClientConnectionFailed();
|
||||
bool isClientProgressKnown();
|
||||
void cancelClientTransfer();
|
||||
double getClientProgress();
|
||||
std::string getClientStatusText();
|
||||
|
||||
+4
-3
@@ -48,9 +48,10 @@ public:
|
||||
template <typename... Args>
|
||||
void log(const std::string& level, const std::string& format = {}, Args... args)
|
||||
{
|
||||
// xcbuffer += StringUtils::format(("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
|
||||
printf("%s\n", format.c_str());
|
||||
// printf("%s\n",StringUtils::format("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
|
||||
// buffer += StringUtils::format(("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
|
||||
// buffer += StringUtils::format("%s\n", format.c_str());
|
||||
// buffer += StringUtils::format("%s\n",StringUtils::format("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
|
||||
printf(StringUtils::format("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
|
||||
}
|
||||
|
||||
void flush(void)
|
||||
|
||||
@@ -82,6 +82,7 @@ private:
|
||||
void getTitle(Title& dst, AccountUid uid, size_t i);
|
||||
size_t getTitleCount(AccountUid uid);
|
||||
void loadTitles(void);
|
||||
bool areTitlesLoaded(void);
|
||||
void sortTitles(void);
|
||||
void rotateSortMode(void);
|
||||
void refreshDirectories(u64 id);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ int main() {
|
||||
exit(res);
|
||||
}
|
||||
|
||||
loadTitles();
|
||||
printf("main");
|
||||
|
||||
// First create our renderer, where one can customize SDL or other stuff's
|
||||
// initialization.
|
||||
|
||||
+18
-2
@@ -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);
|
||||
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"));
|
||||
this->titlesMenu->AddItem(titleItem);
|
||||
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
@@ -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);
|
||||
}
|
||||
|
||||
+13
-3
@@ -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))) {
|
||||
if (R_SUCCEEDED(accountGetProfile(&profile, id))) {
|
||||
if (R_SUCCEEDED(accountProfileGet(&profile, NULL, &profilebase))) {
|
||||
user.name = std::string(profilebase.nickname);
|
||||
}
|
||||
|
||||
accountProfileClose(&profile);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -45,10 +45,9 @@ Directory::Directory(const std::string& root)
|
||||
struct DirectoryEntry de = {name, directory};
|
||||
mList.push_back(de);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
mGood = true;
|
||||
}
|
||||
}
|
||||
|
||||
Result Directory::error(void)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user