Tons of small fixes, proper HOME menu press handling

This commit is contained in:
XorTroll 2020-02-09 00:07:32 +01:00
parent 5b6d37645d
commit 2439c9045e
36 changed files with 1460 additions and 1587 deletions

View file

@ -2,7 +2,7 @@
#include <am/am_DaemonMenuInteraction.hpp>
extern ams::os::Mutex g_last_menu_msg_lock;
extern am::MenuMessage g_last_menu_msg;
extern am::MenuMessage g_last_menu_msg = am::MenuMessage::Invalid;
namespace ipc
{

View file

@ -34,11 +34,6 @@ namespace am
LaunchHomebrewApplication,
OpenWebPage,
GetSelectedUser,
UserHasPassword,
TryLogUser,
RegisterUserPassword,
ChangeUserPassword,
RemoveUserPassword,
OpenAlbum,
};
@ -51,11 +46,6 @@ namespace am
ResultWith<MenuStartMode> Menu_ProcessInput();
Result Menu_InitializeDaemonService();
ResultWith<MenuMessage> Menu_GetLatestMenuMessage();
bool MenuIsHomePressed();
void Menu_FinalizeDaemonService();
Result Daemon_MenuWriteImpl(void *data, size_t size, bool wait);
Result Daemon_MenuReadImpl(void *data, size_t size, bool wait);

View file

@ -41,20 +41,6 @@ namespace am
Result LibraryAppletSend(void *data, size_t size);
Result LibraryAppletRead(void *data, size_t size);
Result WebAppletStart(WebCommonConfig *web);
Result LibraryAppletDaemonLaunchWith(AppletId id, u32 la_version, std::function<void(AppletHolder*)> on_prepare, std::function<void(AppletHolder*)> on_finish, std::function<bool()> on_wait);
inline Result LibraryAppletDaemonLaunchWithSimple(AppletId id, u32 la_version, void *in_data, size_t in_size, void *out_data, size_t out_size, std::function<bool()> on_wait)
{
return LibraryAppletDaemonLaunchWith(id, la_version,
[&](AppletHolder *h)
{
if(in_size > 0) libappletPushInData(h, in_data, in_size);
},
[&](AppletHolder *h)
{
if(out_size > 0) libappletPopOutData(h, out_data, out_size, nullptr);
}, on_wait);
}
u64 LibraryAppletGetProgramIdForAppletId(AppletId id);
AppletId LibraryAppletGetAppletIdForProgramId(u64 id);

View file

@ -5,23 +5,8 @@
namespace db
{
static constexpr u64 HomeMenuSaveDataId = 0x8000000000001010;
struct PassBlock
{
AccountUid uid;
char pass_sha[0x20]; // Password is stored as its SHA256
} PACKED;
static_assert(sizeof(PassBlock) == 0x30, "Password block must be size 0x40!");
Result Mount();
void Unmount();
void Commit();
ResultWith<PassBlock> PackPassword(AccountUid uid, const std::string &pass);
ResultWith<PassBlock> AccessPassword(AccountUid user_id);
std::string GetUserPasswordFilePath(AccountUid user_id);
Result RegisterUserPassword(PassBlock password);
Result TryLogUser(PassBlock password);
Result RemoveUserPassword(AccountUid uid);
}

View file

@ -75,6 +75,8 @@ inline constexpr ResultWith<Args...> SuccessResultWith(Args &&...args)
return MakeResultWith(0, args...);
}
static constexpr Mutex EmptyMutex = (Mutex)0;
#include <ul_Results.hpp>
// Console (debug)

View file

@ -38,20 +38,11 @@ namespace res
RES_BLOCK_BEGIN
RES_MODULE_BEGIN(Db, 1)
RES_DEFINE(InvalidPasswordLength, 1)
RES_DEFINE(PasswordNotFound, 2)
RES_DEFINE(PasswordAlreadyExists, 3)
RES_DEFINE(PasswordWriteFail, 4)
RES_DEFINE(PasswordUserMismatch, 5)
RES_DEFINE(PasswordMismatch, 6)
RES_MODULE_END
RES_MODULE_BEGIN(Misc, 2)
RES_MODULE_BEGIN(Misc, 1)
RES_DEFINE(InvalidJSONFile, 1)
RES_MODULE_END
RES_MODULE_BEGIN(Daemon, 3)
RES_MODULE_BEGIN(Daemon, 2)
RES_DEFINE(ApplicationActive, 1)
RES_DEFINE(InvalidSelectedUser, 2)
RES_DEFINE(AlreadyQueued, 3)

View file

@ -35,31 +35,6 @@ namespace am
return MakeResultWith(rc, (MenuStartMode)in_args.LaVersion);
}
Result Menu_InitializeDaemonService()
{
if(serviceIsActive(&g_daemon_private_srv)) return 0;
return smGetService(&g_daemon_private_srv, AM_DAEMON_PRIVATE_SERVICE_NAME);
}
ResultWith<MenuMessage> Menu_GetLatestMenuMessage()
{
u32 outmsg = 0;
auto rc = serviceDispatchOut(&g_daemon_private_srv, 0, outmsg);
return MakeResultWith(rc, (MenuMessage)outmsg);
}
bool MenuIsHomePressed()
{
auto [rc, msg] = Menu_GetLatestMenuMessage();
if(R_FAILED(rc)) return false;
return (msg == MenuMessage::HomeRequest);
}
void Menu_FinalizeDaemonService()
{
serviceClose(&g_daemon_private_srv);
}
Result Daemon_MenuWriteImpl(void *data, size_t size, bool wait)
UL_AM_WAIT(LibraryAppletSend(data, size))

View file

@ -26,65 +26,4 @@ namespace db
{
fsdevCommitDevice(UL_DB_MOUNT_NAME);
}
ResultWith<PassBlock> PackPassword(AccountUid uid, const std::string &pass)
{
PassBlock pb = {};
if((pass.length() > 15) || (pass.empty())) return MakeResultWith(RES_VALUE(Db, InvalidPasswordLength), pb);
memcpy(&pb.uid, &uid, sizeof(AccountUid));
char passbuf[0x10] = {0};
strcpy(passbuf, pass.c_str());
sha256CalculateHash(pb.pass_sha, passbuf, 0x10);
return SuccessResultWith(pb);
}
ResultWith<PassBlock> AccessPassword(AccountUid user_id)
{
PassBlock pb = {};
auto filename = GetUserPasswordFilePath(user_id);
if(fs::ExistsFile(filename))
{
if(fs::ReadFile(filename, &pb, sizeof(pb))) return SuccessResultWith(pb);
}
return MakeResultWith(RES_VALUE(Db, PasswordNotFound), pb);
}
std::string GetUserPasswordFilePath(AccountUid user_id)
{
auto uidstr = util::Format128NintendoStyle(user_id);
return UL_BASE_DB_DIR "/user/" + uidstr + ".pass";
}
Result RegisterUserPassword(PassBlock password)
{
std::string pwd;
auto filename = GetUserPasswordFilePath(password.uid);
if(fs::ExistsFile(filename)) return RES_VALUE(Db, PasswordAlreadyExists);
if(fs::WriteFile(filename, &password, sizeof(password), true))
{
db::Commit();
return 0;
}
return RES_VALUE(Db, PasswordWriteFail);
}
Result RemoveUserPassword(AccountUid uid)
{
auto passfile = GetUserPasswordFilePath(uid);
if(!fs::ExistsFile(passfile)) return RES_VALUE(Db, PasswordNotFound);
fs::DeleteFile(passfile);
db::Commit();
return 0;
}
Result TryLogUser(PassBlock password)
{
auto [rc, pwd] = AccessPassword(password.uid);
if(R_SUCCEEDED(rc))
{
if(memcmp(&password.uid, &pwd.uid, sizeof(AccountUid)) != 0) return RES_VALUE(Db, PasswordUserMismatch);
if(memcmp(password.pass_sha, pwd.pass_sha, 0x20) != 0) return RES_VALUE(Db, PasswordMismatch);
}
return rc;
}
}

View file

@ -27,7 +27,7 @@ EXEFS_SRC := exefs_src
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $(UL_APM_WRAPS)
ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE $(UL_APM_WRAPS) -Wl,-wrap,libappletStart -Wl,-wrap,libappletLaunch
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)

View file

@ -0,0 +1,13 @@
#pragma once
#include <am/am_DaemonMenuInteraction.hpp>
#include <functional>
namespace am
{
using MessageDetectCallback = std::function<void()>;
Result InitializeDaemonMessageHandler();
void ExitDaemonMessageHandler();
void RegisterOnMessageDetect(MessageDetectCallback callback, MenuMessage desired_msg);
}

View file

@ -0,0 +1,7 @@
#pragma once
namespace am
{
void RegisterLibAppletHomeMenuDetection();
}

View file

@ -0,0 +1,18 @@
#pragma once
#include <ul_Include.hpp>
#include <cfg/cfg_Config.hpp>
namespace ui::actions {
void ShowAboutDialog();
void ShowSettingsMenu();
void ShowThemesMenu();
void ShowUserMenu();
void ShowControllerSupport();
void ShowWebPage();
void ShowHelpDialog();
void ShowAlbumApplet();
void ShowPowerDialog();
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <pu/Plutonium>
#include <ul_Include.hpp>
namespace ui
{
class IMenuLayout : public pu::ui::Layout
{
private:
Mutex home_press_lock;
bool home_pressed;
public:
IMenuLayout();
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
virtual void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) = 0;
void DoOnHomeButtonPress();
virtual void OnHomeButtonPress() = 0;
};
}

View file

@ -1,17 +1,20 @@
#pragma once
#include <ul_Include.hpp>
#include <pu/Plutonium>
#include <ui/ui_IMenuLayout.hpp>
#include <cfg/cfg_Config.hpp>
namespace ui
{
class LanguagesMenuLayout : public pu::ui::Layout
class LanguagesMenuLayout : public IMenuLayout
{
public:
LanguagesMenuLayout();
PU_SMART_CTOR(LanguagesMenuLayout)
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) override;
void OnHomeButtonPress() override;
void Reload();
void lang_Click(u32 idx);
private:

View file

@ -8,6 +8,15 @@
namespace ui
{
enum class MenuType
{
Startup,
Main,
Settings,
Theme,
Languages,
};
class MenuApplication : public pu::ui::Application
{
public:
@ -27,20 +36,20 @@ namespace ui
bool IsSuspended();
bool IsTitleSuspended();
bool IsHomebrewSuspended();
bool EqualsSuspendedHomebrewPath(std::string path);
bool EqualsSuspendedHomebrewPath(const std::string &path);
u64 GetSuspendedApplicationId();
void NotifyEndSuspended();
bool LaunchFailed();
void ShowNotification(std::string text, u64 timeout = 1500);
void ShowNotification(const std::string &text, u64 timeout = 1500);
template<typename T>
T GetUIConfigValue(std::string name, T def)
T GetUIConfigValue(const std::string &name, T def)
{
return this->uijson.value<T>(name, def);
}
template<typename Elem>
void ApplyConfigForElement(std::string menu, std::string name, std::shared_ptr<Elem> &Ref, bool also_visible = true)
void ApplyConfigForElement(const std::string &menu, const std::string &name, std::shared_ptr<Elem> &Ref, bool also_visible = true)
{
if(this->uijson.count(menu))
{
@ -76,10 +85,15 @@ namespace ui
void StartPlayBGM();
void StopPlayBGM();
StartupLayout::Ref &GetStartupLayout();
MenuLayout::Ref &GetMenuLayout();
ThemeMenuLayout::Ref &GetThemeMenuLayout();
SettingsMenuLayout::Ref &GetSettingsMenuLayout();
LanguagesMenuLayout::Ref &GetLanguagesMenuLayout();
void SetSelectedUser(AccountUid user_id);
AccountUid GetSelectedUser();
void CommonMenuOnLoop();
MenuType GetCurrentLoadedMenu();
private:
am::MenuStartMode stmode;
StartupLayout::Ref startupLayout;
@ -89,6 +103,7 @@ namespace ui
LanguagesMenuLayout::Ref languagesMenuLayout;
pu::ui::extras::Toast::Ref notifToast;
am::DaemonStatus status;
MenuType loaded_menu;
JSON uijson;
JSON bgmjson;
bool bgm_loop;
@ -97,8 +112,5 @@ namespace ui
pu::audio::Music bgm;
};
inline void MenuApplication::CommonMenuOnLoop() // Stuff all menus should handle (currently just connected controllers)
{
if(!hidIsControllerConnected(CONTROLLER_HANDHELD) && !hidIsControllerConnected(CONTROLLER_PLAYER_1)) this->menuLayout->HandleControllerAppletOpen();
}
void UiOnHomeButtonDetection();
}

View file

@ -1,45 +1,36 @@
#pragma once
#include <ul_Include.hpp>
#include <pu/Plutonium>
#include <ui/ui_IMenuLayout.hpp>
#include <ui/ui_SideMenu.hpp>
#include <ui/ui_RawData.hpp>
#include <ui/ui_ClickableImage.hpp>
#include <ui/ui_QuickMenu.hpp>
#include <ui/ui_Actions.hpp>
#include <cfg/cfg_Config.hpp>
namespace ui
{
class MenuLayout : public pu::ui::Layout
class MenuLayout : public IMenuLayout
{
public:
MenuLayout(void *raw, u8 min_alpha);
~MenuLayout();
PU_SMART_CTOR(MenuLayout)
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) override;
void OnHomeButtonPress() override;
void menu_Click(u64 down, u32 index);
void menu_OnSelected(u32 index);
void menuToggle_Click();
void logo_Click();
void settings_Click();
void themes_Click();
void users_Click();
void controller_Click();
void MoveFolder(std::string name, bool fade);
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
void MoveFolder(const std::string &name, bool fade);
void SetUser(AccountUid user);
void HandleCloseSuspended();
void HandleHomebrewLaunch(cfg::TitleRecord &rec);
void HandleUserMenu();
void HandleWebPageOpen();
void HandleSettingsMenu();
void HandleThemesMenu();
void HandleControllerAppletOpen();
void HandleShowHelp();
void HandleOpenAlbum();
void HandlePowerDialog();
void HandleMultiselectMoveToFolder(std::string folder);
void HandleMultiselectMoveToFolder(const std::string &folder);
void StopMultiselect();
void DoTerminateApplication();
private:
void *susptr;
bool last_hasconn;

View file

@ -34,12 +34,8 @@ namespace ui
static constexpr s32 MainItemY = (720 - MainItemSize) / 2;
public:
QuickMenu(std::string main_icon);
QuickMenu(const std::string &main_icon);
PU_SMART_CTOR(QuickMenu)
~QuickMenu();
void SetEntry(QuickMenuDirection direction, std::string icon, std::function<void()> on_selected);
void RemoveEntry(QuickMenuDirection direction);
s32 GetX();
s32 GetY();
@ -53,14 +49,8 @@ namespace ui
void OnInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos);
private:
QuickMenuDirection GetCurrentDirection();
std::tuple<s32, s32> ComputePositionForDirection(QuickMenuDirection direction);
bool on;
s64 off_wait;
pu::ui::render::NativeTexture nmain;
u64 lastheld;
s32 bgalpha;
s32 fgalpha;
std::map<QuickMenuDirection, QuickMenuSubItem> item_map;
pu::ui::elm::Menu::Ref dev_opt_menu;
};
}

View file

@ -1,19 +1,22 @@
#pragma once
#include <ul_Include.hpp>
#include <pu/Plutonium>
#include <ui/ui_IMenuLayout.hpp>
#include <cfg/cfg_Config.hpp>
namespace ui
{
class SettingsMenuLayout : public pu::ui::Layout
class SettingsMenuLayout : public IMenuLayout
{
public:
SettingsMenuLayout();
PU_SMART_CTOR(SettingsMenuLayout)
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) override;
void OnHomeButtonPress() override;
void Reload();
void PushSettingItem(std::string name, std::string value_display, int id);
void PushSettingItem(const std::string &name, const std::string &value_display, int id);
void setting_Click(u32 id);
private:
pu::ui::elm::TextBlock::Ref infoText;

View file

@ -15,7 +15,7 @@ namespace ui
static constexpr u32 ExtraIconSize = ItemSize + (Margin * 2);
public:
SideMenu(pu::ui::Color SuspendedColor, std::string CursorPath, std::string SuspendedImagePath, std::string MultiselectImagePath, u32 TextX, u32 TextY, u32 TextSize, pu::ui::Color TextColor, s32 y);
SideMenu(pu::ui::Color suspended_clr, std::string cursor_path, std::string suspended_img_path, std::string multiselect_img_path, u32 txt_x, u32 txt_y, u32 txt_sz, pu::ui::Color txt_clr, s32 y);
PU_SMART_CTOR(SideMenu)
~SideMenu();
@ -25,27 +25,27 @@ namespace ui
void SetY(s32 y);
s32 GetWidth() override;
s32 GetHeight() override;
void OnRender(pu::ui::render::Renderer::Ref &Drawer, s32 X, s32 Y) override;
void OnInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Touch) override;
void SetOnItemSelected(std::function<void(u64, u32)> Fn);
void SetOnSelectionChanged(std::function<void(u32)> Fn);
void OnRender(pu::ui::render::Renderer::Ref &drawer, s32 x, s32 y) override;
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) override;
void SetOnItemSelected(std::function<void(u64, u32)> fn);
void SetOnSelectionChanged(std::function<void(u32)> fn);
void ClearItems();
void AddItem(std::string Icon, std::string Text = "");
void SetSuspendedItem(u32 Index);
void AddItem(const std::string &icon, const std::string &txt = "");
void SetSuspendedItem(u32 idx);
void UnsetSuspendedItem();
void SetSelectedItem(u32 Index);
void SetSelectedItem(u32 idx);
void HandleMoveLeft();
void HandleMoveRight();
int GetSuspendedItem();
u32 GetSelectedItem();
u32 GetBaseItemIndex();
void SetBaseItemIndex(u32 index);
void SetBasePositions(u32 SelectedIdx, u32 BaseIdx);
void SetBaseItemIndex(u32 idx);
void SetBasePositions(u32 selected_idx, u32 base_idx);
void ClearBorderIcons();
void UpdateBorderIcons();
void ResetMultiselections();
void SetItemMultiselected(u32 index, bool selected);
bool IsItemMultiselected(u32 index);
void SetItemMultiselected(u32 idx, bool selected);
bool IsItemMultiselected(u32 idx);
bool IsAnyMultiselected();
void SetEnabled(bool enabled);
private:
@ -81,6 +81,6 @@ namespace ui
u32 scrollcount;
bool IsLeftFirst();
bool IsRightLast();
void ReloadIcons(u32 Direction);
void ReloadIcons(u32 dir);
};
}

View file

@ -3,17 +3,20 @@
#include <ul_Include.hpp>
#include <am/am_DaemonMenuInteraction.hpp>
#include <db/db_Save.hpp>
#include <pu/Plutonium>
#include <ui/ui_IMenuLayout.hpp>
namespace ui
{
class StartupLayout : public pu::ui::Layout
class StartupLayout : public IMenuLayout
{
public:
StartupLayout();
PU_SMART_CTOR(StartupLayout)
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
void user_Click(AccountUid uid, bool has_password);
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) override;
void OnHomeButtonPress() override;
void user_Click(AccountUid uid);
void create_Click();
void ReloadMenu();
private:

View file

@ -1,17 +1,20 @@
#pragma once
#include <ul_Include.hpp>
#include <pu/Plutonium>
#include <ui/ui_IMenuLayout.hpp>
#include <cfg/cfg_Config.hpp>
namespace ui
{
class ThemeMenuLayout : public pu::ui::Layout
class ThemeMenuLayout : public IMenuLayout
{
public:
ThemeMenuLayout();
PU_SMART_CTOR(ThemeMenuLayout)
void OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos);
void OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos) override;
void OnHomeButtonPress() override;
void Reload();
void theme_Click();
private:

View file

@ -12,6 +12,8 @@
#include <os/os_HomeMenu.hpp>
#include <util/util_Convert.hpp>
#include <am/am_LibraryApplet.hpp>
#include <am_DaemonMessages.hpp>
#include <am_LibAppletWrap.hpp>
extern "C"
{
@ -24,11 +26,11 @@ extern "C"
// Some global vars
ui::MenuApplication::Ref qapp;
cfg::TitleList list;
std::vector<cfg::TitleRecord> homebrew;
cfg::Config config;
cfg::Theme theme;
ui::MenuApplication::Ref g_menu_app_instance;
cfg::TitleList g_entry_list;
std::vector<cfg::TitleRecord> g_homebrew_records;
cfg::Config g_ul_config;
cfg::Theme g_ul_theme;
u8 *app_buf;
namespace qmenu
@ -42,16 +44,22 @@ namespace qmenu
UL_R_TRY(setsysInitialize())
UL_R_TRY(setInitialize())
UL_R_TRY(am::Menu_InitializeDaemonService())
// Register handlers for detection
am::RegisterLibAppletHomeMenuDetection();
am::RegisterOnMessageDetect(&ui::UiOnHomeButtonDetection, am::MenuMessage::HomeRequest);
// Load menu config and theme
config = cfg::EnsureConfig();
theme = cfg::LoadTheme(config.theme_name);
// Initialize Daemon message handling
UL_R_TRY(am::InitializeDaemonMessageHandler())
// Load menu g_ul_config and theme
g_ul_config = cfg::EnsureConfig();
g_ul_theme = cfg::LoadTheme(g_ul_config.theme_name);
}
void Exit()
{
am::Menu_FinalizeDaemonService();
am::ExitDaemonMessageHandler();
setExit();
setsysExit();
@ -86,7 +94,7 @@ int main()
app_buf = new u8[RawRGBAScreenBufferSize]();
qmenu::Initialize();
list = cfg::LoadTitleList();
g_entry_list = cfg::LoadTitleList();
// Get system language and load translations (default one if not present)
u64 lcode = 0;
@ -96,12 +104,12 @@ int main()
auto [rc1, defjson] = util::LoadJSONFromFile(CFG_LANG_DEFAULT);
if(R_SUCCEEDED(rc1))
{
config.default_lang = defjson;
config.main_lang = defjson;
g_ul_config.default_lang = defjson;
g_ul_config.main_lang = defjson;
if(fs::ExistsFile(lpath))
{
auto [rc2, ljson] = util::LoadJSONFromFile(lpath);
if(R_SUCCEEDED(rc2)) config.main_lang = ljson;
if(R_SUCCEEDED(rc2)) g_ul_config.main_lang = ljson;
}
}
@ -109,13 +117,13 @@ int main()
renderoptions.InitRomFs = false; // We have loaded RomFs from an external file, so :P
auto renderer = pu::ui::render::Renderer::New(SDL_INIT_EVERYTHING, renderoptions, pu::ui::render::RendererHardwareFlags);
qapp = ui::MenuApplication::New(renderer);
g_menu_app_instance = ui::MenuApplication::New(renderer);
qapp->SetInformation(smode, status);
qapp->Prepare();
g_menu_app_instance->SetInformation(smode, status);
g_menu_app_instance->Prepare();
if(smode == am::MenuStartMode::MenuApplicationSuspended) qapp->Show();
else qapp->ShowWithFadeIn();
if(smode == am::MenuStartMode::MenuApplicationSuspended) g_menu_app_instance->Show();
else g_menu_app_instance->ShowWithFadeIn();
// Exit RomFs manually, Plutonium won't do it for us since we're initializing it manually
romfsExit();

View file

@ -0,0 +1,75 @@
#include <am_DaemonMessages.hpp>
#include <thread>
#include <map>
namespace am
{
static Mutex g_receiver_lock = EmptyMutex;
static Service g_daemon_srv;
static bool g_init = false;
static bool g_thr_should_stop = false;
static Thread g_receiver_thr;
static std::vector<std::pair<MessageDetectCallback, MenuMessage>> g_callback_table;
static void DaemonMessageReceiveThread(void *arg)
{
while(true)
{
mutexLock(&g_receiver_lock);
auto should_stop = g_thr_should_stop;
mutexUnlock(&g_receiver_lock);
if(should_stop) break;
MenuMessage tmp_msg = MenuMessage::Invalid;
auto rc = serviceDispatchOut(&g_daemon_srv, 0, tmp_msg);
if(R_SUCCEEDED(rc))
{
mutexLock(&g_receiver_lock);
for(auto &[cb, msg] : g_callback_table)
{
if(msg == tmp_msg)
{
cb();
}
}
mutexUnlock(&g_receiver_lock);
}
svcSleepThread(10'000'000ul);
}
}
Result InitializeDaemonMessageHandler()
{
if(g_init) return 0;
auto rc = smGetService(&g_daemon_srv, AM_DAEMON_PRIVATE_SERVICE_NAME);
if(R_SUCCEEDED(rc))
{
g_thr_should_stop = false;
rc = threadCreate(&g_receiver_thr, &DaemonMessageReceiveThread, nullptr, nullptr, 0x4000, 0x2b, -2);
if(R_SUCCEEDED(rc))
{
rc = threadStart(&g_receiver_thr);
if(R_SUCCEEDED(rc)) g_init = true;
}
}
return rc;
}
void ExitDaemonMessageHandler()
{
if(!g_init) return;
mutexLock(&g_receiver_lock);
g_thr_should_stop = true;
mutexUnlock(&g_receiver_lock);
threadWaitForExit(&g_receiver_thr);
serviceClose(&g_daemon_srv);
g_init = false;
}
void RegisterOnMessageDetect(MessageDetectCallback callback, MenuMessage desired_msg)
{
mutexLock(&g_receiver_lock);
g_callback_table.push_back(std::make_pair(callback, desired_msg));
mutexUnlock(&g_receiver_lock);
}
}

View file

@ -0,0 +1,95 @@
#include <am/am_DaemonMenuInteraction.hpp>
#include <am_LibAppletWrap.hpp>
#include <am_DaemonMessages.hpp>
static Mutex g_amwrap_detection_lock = EmptyMutex;
static bool g_is_applet_running = false;
static bool g_detection_home_pressed = false;
namespace am
{
void OnHomeButtonDetection()
{
mutexLock(&g_amwrap_detection_lock);
if(g_is_applet_running) g_detection_home_pressed = true;
mutexUnlock(&g_amwrap_detection_lock);
}
void RegisterLibAppletHomeMenuDetection()
{
RegisterOnMessageDetect(&OnHomeButtonDetection, am::MenuMessage::HomeRequest);
}
}
extern "C"
{
// Wrap libappletStart and libappletLaunch to use our custom waiting system
Result __wrap_libappletStart(AppletHolder *h)
{
Result rc = appletHolderStart(h);
mutexLock(&g_amwrap_detection_lock);
g_is_applet_running = true;
mutexUnlock(&g_amwrap_detection_lock);
if(R_SUCCEEDED(rc))
{
while(true)
{
if(appletHolderCheckFinished(h)) break;
if(!serviceIsActive(&h->s)) break;
mutexLock(&g_amwrap_detection_lock);
auto home_pressed = g_detection_home_pressed;
g_detection_home_pressed = false;
mutexUnlock(&g_amwrap_detection_lock);
if(home_pressed)
{
appletHolderRequestExitOrTerminate(h, 15'000'000'000ul);
break;
}
svcSleepThread(10'000'000ul);
}
appletHolderJoin(h);
LibAppletExitReason reason = appletHolderGetExitReason(h);
if(reason == LibAppletExitReason_Canceled || reason == LibAppletExitReason_Abnormal || reason == LibAppletExitReason_Unexpected)
{
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
}
}
mutexLock(&g_amwrap_detection_lock);
g_is_applet_running = false;
mutexUnlock(&g_amwrap_detection_lock);
return rc;
}
Result __wrap_libappletLaunch(AppletId id, LibAppletArgs *commonargs, const void* arg, size_t arg_size, void* reply, size_t reply_size, size_t *out_reply_size)
{
Result rc=0;
AppletHolder holder;
rc = appletCreateLibraryApplet(&holder, id, LibAppletMode_AllForeground);
if (R_FAILED(rc)) return rc;
rc = libappletArgsPush(commonargs, &holder);
if (R_SUCCEEDED(rc) && arg && arg_size) rc = libappletPushInData(&holder, arg, arg_size);
if (R_SUCCEEDED(rc)) rc = __wrap_libappletStart(&holder);
if (R_SUCCEEDED(rc) && reply && reply_size) rc = libappletPopOutData(&holder, reply, reply_size, out_reply_size);
appletHolderClose(&holder);
return rc;
}
}

View file

@ -0,0 +1,147 @@
#include <ui/ui_Actions.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <ui/ui_MenuLayout.hpp>
#include <os/os_Titles.hpp>
#include <os/os_Account.hpp>
#include <util/util_Convert.hpp>
#include <util/util_Misc.hpp>
#include <os/os_Misc.hpp>
#include <am/am_LibraryApplet.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <os/os_HomeMenu.hpp>
#include <fs/fs_Stdio.hpp>
#include <net/net_Service.hpp>
extern ui::MenuApplication::Ref g_menu_app_instance;
extern cfg::Config g_ul_config;
namespace ui::actions
{
void ShowAboutDialog()
{
g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "ulaunch_about"), "uLaunch v" + std::string(UL_VERSION) + "\n\n" + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "ulaunch_desc") + ":\nhttps://github.com/XorTroll/uLaunch", { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "ok") }, true, "romfs:/LogoLarge.png");
}
void ShowSettingsMenu()
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadSettingsMenu();
g_menu_app_instance->FadeIn();
}
void ShowThemesMenu()
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadThemeMenu();
g_menu_app_instance->FadeIn();
}
void ShowUserMenu()
{
auto uid = g_menu_app_instance->GetSelectedUser();
auto [_rc, name] = os::GetAccountName(uid);
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "user_settings"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "user_selected") + ": " + name + "\n" + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "user_option"), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "user_view_page"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "user_logoff"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true, os::GetIconCacheImagePath(uid));
if(sopt == 0) friendsLaShowMyProfileForHomeMenu(uid);
else if(sopt == 1)
{
u32 logoff = 0;
if(g_menu_app_instance->IsSuspended())
{
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "suspended_app"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "user_logoff_app_suspended"), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "yes"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true);
if(sopt == 0) logoff = 2;
}
else logoff = 1;
if(logoff > 0)
{
auto &menu_lyt = g_menu_app_instance->GetMenuLayout();
if(logoff == 2) menu_lyt->DoTerminateApplication();
g_menu_app_instance->FadeOut();
menu_lyt->MoveFolder("", false);
g_menu_app_instance->LoadStartupMenu();
g_menu_app_instance->FadeIn();
}
}
}
void ShowControllerSupport()
{
HidLaControllerSupportArg arg = {};
hidLaCreateControllerSupportArg(&arg);
for(u32 i = 0; i < 8; i++) strcpy(arg.explain_text[i], "Demo explain text");
hidLaShowControllerSupportForSystem(nullptr, &arg, true);
}
void ShowWebPage() {
SwkbdConfig swkbd;
swkbdCreate(&swkbd, 0);
swkbdConfigSetGuideText(&swkbd, cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "swkbd_webpage_guide").c_str());
char url[500] = {0};
auto rc = swkbdShow(&swkbd, url, 500);
swkbdClose(&swkbd);
if(R_SUCCEEDED(rc))
{
WebCommonConfig web = {};
webPageCreate(&web, url);
webConfigSetWhitelist(&web, ".*");
am::MenuCommandWriter writer(am::DaemonMessage::OpenWebPage);
writer.Write<WebCommonConfig>(web);
writer.FinishWrite();
g_menu_app_instance->StopPlayBGM();
g_menu_app_instance->CloseWithFadeOut();
}
}
void ShowHelpDialog()
{
std::string msg;
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_launch") + "\n";
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_close") + "\n";
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_quick") + "\n";
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_multiselect") + "\n";
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_back") + "\n";
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_minus") + "\n";
msg += " - " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_plus") + "\n";
g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "help_title"), msg, { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "ok") }, true);
}
void ShowAlbumApplet()
{
am::MenuCommandWriter writer(am::DaemonMessage::OpenAlbum);
writer.FinishWrite();
g_menu_app_instance->StopPlayBGM();
g_menu_app_instance->CloseWithFadeOut();
}
void ShowPowerDialog()
{
auto msg = os::GeneralChannelMessage::Invalid;
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "power_dialog"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "power_dialog_info"), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "power_sleep"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "power_power_off"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "power_reboot"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true);
if(sopt == 0) msg = os::GeneralChannelMessage::Sleep;
else if(sopt == 1) msg = os::GeneralChannelMessage::Shutdown;
else if(sopt == 2) msg = os::GeneralChannelMessage::Reboot;
if(msg != os::GeneralChannelMessage::Invalid)
{
// Fade out on all cases
g_menu_app_instance->FadeOut();
os::SystemAppletMessage smsg = {};
smsg.magic = os::SAMSMagic;
smsg.message = (u32)msg;
os::PushSystemAppletMessage(smsg);
svcSleepThread(1'500'000'000L);
// When we get back after sleep we will do a cool fade in, whereas wuth the other options the console will be already off/rebooted
g_menu_app_instance->FadeIn();
}
}
}

View file

@ -12,7 +12,7 @@ namespace ui
this->y = Y;
this->w = 0;
this->h = 0;
this->ntex = NULL;
this->ntex = nullptr;
this->touched = false;
this->cb = [&](){};
this->SetImage(Image);
@ -20,10 +20,10 @@ namespace ui
ClickableImage::~ClickableImage()
{
if(this->ntex != NULL)
if(this->ntex != nullptr)
{
pu::ui::render::DeleteTexture(this->ntex);
this->ntex = NULL;
this->ntex = nullptr;
}
}
@ -74,8 +74,8 @@ namespace ui
void ClickableImage::SetImage(pu::String Image)
{
if(this->ntex != NULL) pu::ui::render::DeleteTexture(this->ntex);
this->ntex = NULL;
if(this->ntex != nullptr) pu::ui::render::DeleteTexture(this->ntex);
this->ntex = nullptr;
if(fs::ExistsFile(Image.AsUTF8()))
{
this->img = Image;
@ -87,7 +87,7 @@ namespace ui
bool ClickableImage::IsImageValid()
{
return ((ntex != NULL) && this->img.HasAny());
return ((ntex != nullptr) && this->img.HasAny());
}
void ClickableImage::SetOnClick(std::function<void()> Callback)

View file

@ -0,0 +1,28 @@
#include <ui/ui_IMenuLayout.hpp>
#include <ui/ui_Actions.hpp>
namespace ui
{
IMenuLayout::IMenuLayout() : home_press_lock(EmptyMutex), home_pressed(false)
{
this->SetOnInput(std::bind(&IMenuLayout::OnInput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}
void IMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
mutexLock(&this->home_press_lock);
auto home_press = this->home_pressed;
this->home_pressed = false;
mutexUnlock(&this->home_press_lock);
if(home_press) this->OnHomeButtonPress();
if(!hidIsControllerConnected(CONTROLLER_HANDHELD) && !hidIsControllerConnected(CONTROLLER_PLAYER_1)) actions::ShowControllerSupport();
this->OnMenuInput(down, up, held, pos);
}
void IMenuLayout::DoOnHomeButtonPress()
{
mutexLock(&this->home_press_lock);
this->home_pressed = true;
mutexUnlock(&this->home_press_lock);
}
}

View file

@ -8,32 +8,47 @@
#include <net/net_Service.hpp>
#include <am/am_LibraryApplet.hpp>
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
extern ui::MenuApplication::Ref g_menu_app_instance;
extern cfg::Theme g_ul_theme;
extern cfg::Config g_ul_config;
namespace ui
{
LanguagesMenuLayout::LanguagesMenuLayout()
{
this->SetBackgroundImage(cfg::GetAssetByTheme(theme, "ui/Background.png"));
this->SetBackgroundImage(cfg::GetAssetByTheme(g_ul_theme, "ui/Background.png"));
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
this->infoText = pu::ui::elm::TextBlock::New(0, 100, cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_info_text"));
this->infoText = pu::ui::elm::TextBlock::New(0, 100, cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_info_text"));
this->infoText->SetColor(textclr);
this->infoText->SetHorizontalAlign(pu::ui::elm::HorizontalAlign::Center);
qapp->ApplyConfigForElement("languages_menu", "info_text", this->infoText);
g_menu_app_instance->ApplyConfigForElement("languages_menu", "info_text", this->infoText);
this->Add(this->infoText);
this->langsMenu = pu::ui::elm::Menu::New(200, 160, 880, menubgclr, 100, 4);
this->langsMenu->SetOnFocusColor(menufocusclr);
qapp->ApplyConfigForElement("languages_menu", "languages_menu_item", this->langsMenu);
g_menu_app_instance->ApplyConfigForElement("languages_menu", "languages_menu_item", this->langsMenu);
this->Add(this->langsMenu);
}
this->SetOnInput(std::bind(&LanguagesMenuLayout::OnInput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
void LanguagesMenuLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
if(down & KEY_B)
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadSettingsMenu();
g_menu_app_instance->FadeIn();
}
}
void LanguagesMenuLayout::OnHomeButtonPress()
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadMenu();
g_menu_app_instance->FadeIn();
}
void LanguagesMenuLayout::Reload()
@ -41,7 +56,7 @@ namespace ui
this->langsMenu->ClearItems();
this->langsMenu->SetSelectedIndex(0);
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
u64 lcode = 0;
SetLanguage ilang = SetLanguage_ENUS;
setGetLanguageCode(&lcode);
@ -51,7 +66,7 @@ namespace ui
for(auto &lang: os::GetLanguageNameList())
{
auto name = lang;
if((u32)ilang == idx) name += " " + cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_selected");
if((u32)ilang == idx) name += " " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_selected");
auto litm = pu::ui::elm::MenuItem::New(name);
litm->SetColor(textclr);
litm->AddOnClick(std::bind(&LanguagesMenuLayout::lang_Click, this, idx));
@ -67,10 +82,10 @@ namespace ui
setGetLanguageCode(&lcode);
setMakeLanguage(lcode, &ilang);
if((u32)ilang == idx) qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_active_this"));
if((u32)ilang == idx) g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_active_this"));
else
{
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_set"), cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_set_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "no") }, true);
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_set"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_set_conf"), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "yes"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "no") }, true);
if(sopt == 0)
{
u64 codes[16] = {0};
@ -79,10 +94,10 @@ namespace ui
u64 code = codes[this->langsMenu->GetSelectedIndex()];
auto rc = setsysSetLanguageCode(code);
qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_set"), R_SUCCEEDED(rc) ? cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_set_ok") : cfg::GetLanguageString(config.main_lang, config.default_lang, "lang_set_error") + ": " + util::FormatResult(rc), { cfg::GetLanguageString(config.main_lang, config.default_lang, "ok") }, true);
g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_set"), R_SUCCEEDED(rc) ? cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_set_ok") : cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "lang_set_error") + ": " + util::FormatResult(rc), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "ok") }, true);
if(R_SUCCEEDED(rc))
{
qapp->FadeOut();
g_menu_app_instance->FadeOut();
os::SystemAppletMessage smsg = {};
smsg.magic = os::SAMSMagic;
smsg.message = (u32)os::GeneralChannelMessage::Reboot;
@ -93,23 +108,4 @@ namespace ui
}
}
}
void LanguagesMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
qapp->CommonMenuOnLoop();
bool ret = am::MenuIsHomePressed();
if(down & KEY_B)
{
qapp->FadeOut();
qapp->LoadSettingsMenu();
qapp->FadeIn();
}
if(ret)
{
qapp->FadeOut();
qapp->LoadMenu();
qapp->FadeIn();
}
}
}

View file

@ -2,10 +2,43 @@
#include <util/util_Misc.hpp>
extern u8 *app_buf;
extern cfg::Theme theme;
extern cfg::Theme g_ul_theme;
extern ui::MenuApplication::Ref g_menu_app_instance;
namespace ui
{
void UiOnHomeButtonDetection()
{
switch(g_menu_app_instance->GetCurrentLoadedMenu())
{
case MenuType::Startup:
{
g_menu_app_instance->GetStartupLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Main:
{
g_menu_app_instance->GetMenuLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Settings:
{
g_menu_app_instance->GetSettingsMenuLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Theme:
{
g_menu_app_instance->GetThemeMenuLayout()->DoOnHomeButtonPress();
break;
}
case MenuType::Languages:
{
g_menu_app_instance->GetLanguagesMenuLayout()->DoOnHomeButtonPress();
break;
}
}
}
MenuApplication::~MenuApplication()
{
pu::audio::Delete(this->bgm);
@ -13,7 +46,7 @@ namespace ui
void MenuApplication::OnLoad()
{
pu::ui::render::SetDefaultFont(cfg::GetAssetByTheme(theme, "ui/Font.ttf"));
pu::ui::render::SetDefaultFont(cfg::GetAssetByTheme(g_ul_theme, "ui/Font.ttf"));
if(this->IsSuspended())
{
@ -21,9 +54,9 @@ namespace ui
appletGetLastApplicationCaptureImageEx(app_buf, RawRGBAScreenBufferSize, &flag);
}
auto [_rc, jui] = util::LoadJSONFromFile(cfg::GetAssetByTheme(theme, "ui/UI.json"));
auto [_rc, jui] = util::LoadJSONFromFile(cfg::GetAssetByTheme(g_ul_theme, "ui/UI.json"));
this->uijson = jui;
auto [_rc2, jbgm] = util::LoadJSONFromFile(cfg::GetAssetByTheme(theme, "sound/BGM.json"));
auto [_rc2, jbgm] = util::LoadJSONFromFile(cfg::GetAssetByTheme(g_ul_theme, "sound/BGM.json"));
this->bgmjson = jbgm;
this->bgm_loop = this->bgmjson.value("loop", true);
this->bgm_fade_in_ms = this->bgmjson.value("fade_in_ms", 1500);
@ -33,7 +66,7 @@ namespace ui
pu::ui::Color toastbaseclr = pu::ui::Color::FromHex(GetUIConfigValue<std::string>("toast_base_color", "#282828ff"));
this->notifToast = pu::ui::extras::Toast::New("...", 20, toasttextclr, toastbaseclr);
this->bgm = pu::audio::Open(cfg::GetAssetByTheme(theme, "sound/BGM.mp3"));
this->bgm = pu::audio::Open(cfg::GetAssetByTheme(g_ul_theme, "sound/BGM.mp3"));
this->startupLayout = StartupLayout::New();
this->menuLayout = MenuLayout::New(app_buf, this->uijson.value("suspended_final_alpha", 80));
@ -63,6 +96,7 @@ namespace ui
{
this->menuLayout->SetUser(this->status.selected_user);
this->LoadLayout(this->menuLayout);
this->loaded_menu = MenuType::Main;
}
void MenuApplication::LoadStartupMenu()
@ -70,24 +104,28 @@ namespace ui
this->StopPlayBGM();
this->startupLayout->ReloadMenu();
this->LoadLayout(this->startupLayout);
this->loaded_menu = MenuType::Startup;
}
void MenuApplication::LoadThemeMenu()
{
this->themeMenuLayout->Reload();
this->LoadLayout(this->themeMenuLayout);
this->loaded_menu = MenuType::Theme;
}
void MenuApplication::LoadSettingsMenu()
{
this->settingsMenuLayout->Reload();
this->LoadLayout(this->settingsMenuLayout);
this->loaded_menu = MenuType::Settings;
}
void MenuApplication::LoadSettingsLanguagesMenu()
{
this->languagesMenuLayout->Reload();
this->LoadLayout(this->languagesMenuLayout);
this->loaded_menu = MenuType::Languages;
}
bool MenuApplication::IsSuspended()
@ -105,7 +143,7 @@ namespace ui
return strlen(this->status.params.nro_path);
}
bool MenuApplication::EqualsSuspendedHomebrewPath(std::string path)
bool MenuApplication::EqualsSuspendedHomebrewPath(const std::string &path)
{
return this->status.params.nro_path == path;
}
@ -127,7 +165,7 @@ namespace ui
return (this->stmode == am::MenuStartMode::MenuLaunchFailure);
}
void MenuApplication::ShowNotification(std::string text, u64 timeout)
void MenuApplication::ShowNotification(const std::string &text, u64 timeout)
{
this->EndOverlay();
this->notifToast->SetText(text);
@ -136,7 +174,7 @@ namespace ui
void MenuApplication::StartPlayBGM()
{
if(this->bgm != NULL)
if(this->bgm != nullptr)
{
int loops = this->bgm_loop ? -1 : 1;
if(this->bgm_fade_in_ms > 0) pu::audio::PlayWithFadeIn(this->bgm, loops, this->bgm_fade_in_ms);
@ -149,6 +187,31 @@ namespace ui
if(this->bgm_fade_out_ms > 0) pu::audio::FadeOut(this->bgm_fade_out_ms);
else pu::audio::Stop();
}
StartupLayout::Ref &MenuApplication::GetStartupLayout()
{
return this->startupLayout;
}
MenuLayout::Ref &MenuApplication::GetMenuLayout()
{
return this->menuLayout;
}
ThemeMenuLayout::Ref &MenuApplication::GetThemeMenuLayout()
{
return this->themeMenuLayout;
}
SettingsMenuLayout::Ref &MenuApplication::GetSettingsMenuLayout()
{
return this->settingsMenuLayout;
}
LanguagesMenuLayout::Ref &MenuApplication::GetLanguagesMenuLayout()
{
return this->languagesMenuLayout;
}
void MenuApplication::SetSelectedUser(AccountUid user_id)
{
@ -163,4 +226,9 @@ namespace ui
{
return this->status.selected_user;
}
MenuType MenuApplication::GetCurrentLoadedMenu()
{
return this->loaded_menu;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,32 +1,29 @@
#include <ui/ui_QuickMenu.hpp>
#include <ui/ui_MenuApplication.hpp>
#include <cfg/cfg_Config.hpp>
extern cfg::Theme g_ul_theme;
extern ui::MenuApplication::Ref g_menu_app_instance;
namespace ui
{
QuickMenu::QuickMenu(std::string main_icon)
QuickMenu::QuickMenu(const std::string &main_icon)
{
this->on = false;
this->lastheld = 0;
this->nmain = pu::ui::render::LoadImage(main_icon);
this->bgalpha = 0;
this->fgalpha = 0;
this->off_wait = -1;
}
QuickMenu::~QuickMenu()
{
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
}
void QuickMenu::SetEntry(QuickMenuDirection direction, std::string icon, std::function<void()> on_selected)
{
this->RemoveEntry(direction);
this->item_map[direction] = { on_selected, pu::ui::render::LoadImage(icon) };
}
void QuickMenu::RemoveEntry(QuickMenuDirection direction)
{
if(this->item_map.count(direction)) this->item_map.erase(direction);
this->dev_opt_menu = pu::ui::elm::Menu::New(200, 160, 880, pu::ui::Color{ 0xff, 0xff, 0xff, 0x10 }, 100, 4);
this->dev_opt_menu->SetOnFocusColor(menufocusclr);
this->dev_opt_menu->SetColor({ 0, 0, 0, 0 });
g_menu_app_instance->ApplyConfigForElement("quick_menu", "quick_menu_item", this->dev_opt_menu);
auto controller_item = pu::ui::elm::MenuItem::New("Controller");
controller_item->SetIcon(cfg::GetAssetByTheme(g_ul_theme, "ui/ControllerIcon.png"));
controller_item->AddOnClick(&actions::ShowControllerSupport);
this->dev_opt_menu->AddItem(controller_item);
}
s32 QuickMenu::GetX()
@ -56,162 +53,52 @@ namespace ui
bool QuickMenu::IsOn()
{
return this->on;
return this->on && (this->bgalpha > 0);
}
void QuickMenu::OnRender(pu::ui::render::Renderer::Ref &Drawer, s32 X, s32 Y)
{
if(!this->on)
{
if(this->off_wait >= 0)
if(this->bgalpha > 0)
{
if(bgalpha > 0)
{
bgalpha -= 20;
if(bgalpha < 0) bgalpha = 0;
}
if(fgalpha > 0)
{
fgalpha -= 20;
if(fgalpha < 0) fgalpha = 0;
}
this->bgalpha -= 20;
if(this->bgalpha < 0) this->bgalpha = 0;
}
else return;
}
else
{
if(bgalpha < 220)
if(this->bgalpha < 220)
{
bgalpha += 20;
if(bgalpha > 220) bgalpha = 220;
}
if(fgalpha < 255)
{
fgalpha += 20;
if(fgalpha > 255) fgalpha = 255;
this->bgalpha += 20;
if(this->bgalpha > 220) this->bgalpha = 220;
}
}
this->dev_opt_menu->SetVisible(this->bgalpha != 0);
Drawer->RenderRectangleFill({ 50, 50, 50, (u8)bgalpha }, 0, 0, 1280, 720);
Drawer->RenderRectangleFill({ 50, 50, 50, (u8)this->bgalpha }, 0, 0, 1280, 720);
auto dir = this->GetCurrentDirection();
Drawer->RenderTexture(this->nmain, MainItemX, MainItemY, { fgalpha, MainItemSize, MainItemSize, -1 });
for(auto &[direction, subitem]: this->item_map)
{
auto [x, y] = this->ComputePositionForDirection(direction);
auto tex = subitem.nicon;
auto texw = pu::ui::render::GetTextureWidth(tex);
auto texh = pu::ui::render::GetTextureHeight(tex);
x += (SubItemsSize - texw) / 2;
y += (SubItemsSize - texh) / 2;
if(direction == dir) SDL_SetTextureColorMod(tex, 150, 150, 200);
else SDL_SetTextureColorMod(tex, 255, 255, 255);
Drawer->RenderTexture(tex, x, y, { fgalpha, texw, texh, -1 });
if(this->bgalpha > 0) {
Drawer->SetBaseRenderAlpha((u8)this->bgalpha);
this->dev_opt_menu->OnRender(Drawer, this->dev_opt_menu->GetProcessedX(), this->dev_opt_menu->GetProcessedY());
Drawer->UnsetBaseRenderAlpha();
}
}
void QuickMenu::OnInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Pos)
{
auto prevheld = this->lastheld;
this->lastheld = Held;
if(this->off_wait >= 0)
{
if((this->fgalpha == 0) && (this->bgalpha == 0))
{
this->lastheld = (u64)this->off_wait;
auto dir = this->GetCurrentDirection();
this->lastheld = Held;
this->off_wait = -1;
if(this->on) {
this->dev_opt_menu->OnInput(Down, Up, Held, Pos);
}
if(this->item_map.count(dir))
{
auto itm = this->item_map[dir];
(itm.on_select)();
}
if((Down & KEY_L) || (Down & KEY_R) || (Down & KEY_ZL) || (Down & KEY_ZR)) {
this->Toggle();
}
else if(Down & KEY_B) {
// B only valid for toggling off
if(this->on) {
this->Toggle();
}
}
else
{
if(this->on)
{
if(Down & KEY_A) this->Toggle();
else if(Down & KEY_B)
{
prevheld = 0;
this->Toggle();
}
}
if(!this->on && (this->bgalpha > 0) && (this->fgalpha > 0)) this->off_wait = prevheld;
}
}
QuickMenuDirection QuickMenu::GetCurrentDirection()
{
QuickMenuDirection dir = QuickMenuDirection::None;
if(this->lastheld & KEY_UP)
{
dir = QuickMenuDirection::Up;
if(this->lastheld & KEY_LEFT) dir = QuickMenuDirection::UpLeft;
else if(this->lastheld & KEY_RIGHT) dir = QuickMenuDirection::UpRight;
}
else if(this->lastheld & KEY_DOWN)
{
dir = QuickMenuDirection::Down;
if(this->lastheld & KEY_LEFT) dir = QuickMenuDirection::DownLeft;
else if(this->lastheld & KEY_RIGHT) dir = QuickMenuDirection::DownRight;
}
else if(this->lastheld & KEY_LEFT) dir = QuickMenuDirection::Left;
else if(this->lastheld & KEY_RIGHT) dir = QuickMenuDirection::Right;
return dir;
}
std::tuple<s32, s32> QuickMenu::ComputePositionForDirection(QuickMenuDirection direction)
{
s32 x = MainItemX;
s32 y = MainItemY;
switch(direction)
{
case QuickMenuDirection::Up:
x += ((MainItemSize - SubItemsSize) / 2);
y -= SubItemsSize;
break;
case QuickMenuDirection::Down:
x += ((MainItemSize - SubItemsSize) / 2);
y += MainItemSize;
break;
case QuickMenuDirection::Left:
x -= SubItemsSize;
y += ((MainItemSize - SubItemsSize) / 2);
break;
case QuickMenuDirection::Right:
x += MainItemSize;
y += ((MainItemSize - SubItemsSize) / 2);
break;
case QuickMenuDirection::UpLeft:
x -= (SubItemsSize - CommonAreaSize);
y -= (SubItemsSize - CommonAreaSize);
break;
case QuickMenuDirection::UpRight:
x += (MainItemSize - CommonAreaSize);
y -= (SubItemsSize - CommonAreaSize);
break;
case QuickMenuDirection::DownLeft:
x -= (SubItemsSize - CommonAreaSize);
y += (MainItemSize - CommonAreaSize);
break;
case QuickMenuDirection::DownRight:
x += (MainItemSize - CommonAreaSize);
y += (MainItemSize - CommonAreaSize);
break;
default:
break;
}
return std::make_tuple(x, y);
}
}

View file

@ -11,22 +11,22 @@ namespace ui
this->pitch = Width * PixNum;
this->ptr = raw;
this->falpha = 255;
if(raw != NULL)
if(raw != nullptr)
{
this->ntex = SDL_CreateTexture(pu::ui::render::GetMainRenderer(), SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, Width, Height);
if(this->ntex != NULL)
if(this->ntex != nullptr)
{
SDL_UpdateTexture(this->ntex, NULL, raw, this->pitch);
SDL_UpdateTexture(this->ntex, nullptr, raw, this->pitch);
}
}
}
RawData::~RawData()
{
if(this->ntex != NULL)
if(this->ntex != nullptr)
{
pu::ui::render::DeleteTexture(this->ntex);
this->ntex = NULL;
this->ntex = nullptr;
}
}
@ -77,7 +77,7 @@ namespace ui
void RawData::OnRender(pu::ui::render::Renderer::Ref &Drawer, s32 X, s32 Y)
{
if(this->ntex != NULL)
if(this->ntex != nullptr)
{
Drawer->SetBaseRenderAlpha(this->falpha);
Drawer->RenderTexture(this->ntex, X, Y, { -1, this->w, this->h, -1 });

View file

@ -7,16 +7,16 @@
#include <net/net_Service.hpp>
#include <am/am_LibraryApplet.hpp>
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
extern ui::MenuApplication::Ref g_menu_app_instance;
extern cfg::Theme g_ul_theme;
extern cfg::Config g_ul_config;
namespace ui
{
template<typename T>
std::string EncodeForSettings(T t)
{
return cfg::GetLanguageString(config.main_lang, config.default_lang, "set_unknown_value");
return cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_unknown_value");
}
template<>
@ -34,29 +34,44 @@ namespace ui
template<>
std::string EncodeForSettings<bool>(bool t)
{
return t ? cfg::GetLanguageString(config.main_lang, config.default_lang, "set_true_value") : cfg::GetLanguageString(config.main_lang, config.default_lang, "set_false_value");
return t ? cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_true_value") : cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_false_value");
}
SettingsMenuLayout::SettingsMenuLayout()
{
this->SetBackgroundImage(cfg::GetAssetByTheme(theme, "ui/Background.png"));
this->SetBackgroundImage(cfg::GetAssetByTheme(g_ul_theme, "ui/Background.png"));
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
this->infoText = pu::ui::elm::TextBlock::New(0, 100, cfg::GetLanguageString(config.main_lang, config.default_lang, "set_info_text"));
this->infoText = pu::ui::elm::TextBlock::New(0, 100, cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_info_text"));
this->infoText->SetColor(textclr);
this->infoText->SetHorizontalAlign(pu::ui::elm::HorizontalAlign::Center);
qapp->ApplyConfigForElement("settings_menu", "info_text", this->infoText);
g_menu_app_instance->ApplyConfigForElement("settings_menu", "info_text", this->infoText);
this->Add(this->infoText);
this->settingsMenu = pu::ui::elm::Menu::New(200, 160, 880, menubgclr, 100, 4);
this->settingsMenu->SetOnFocusColor(menufocusclr);
qapp->ApplyConfigForElement("settings_menu", "settings_menu_item", this->settingsMenu);
g_menu_app_instance->ApplyConfigForElement("settings_menu", "settings_menu_item", this->settingsMenu);
this->Add(this->settingsMenu);
}
this->SetOnInput(std::bind(&SettingsMenuLayout::OnInput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
void SettingsMenuLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
if(down & KEY_B)
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadMenu();
g_menu_app_instance->FadeIn();
}
}
void SettingsMenuLayout::OnHomeButtonPress()
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadMenu();
g_menu_app_instance->FadeIn();
}
void SettingsMenuLayout::Reload()
@ -66,62 +81,62 @@ namespace ui
char consolename[SET_MAX_NICKNAME_SIZE] = {};
setsysGetDeviceNickname(consolename);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_console_nickname"), EncodeForSettings<std::string>(consolename), 0);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_console_nickname"), EncodeForSettings<std::string>(consolename), 0);
TimeLocationName loc = {};
timeGetDeviceLocationName(&loc);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_console_timezone"), EncodeForSettings<std::string>(loc.name), -1);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_viewer_enabled"), EncodeForSettings(config.viewer_usb_enabled), 1);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_flog_enabled"), EncodeForSettings(config.system_title_override_enabled), 2);
std::string connectednet = cfg::GetLanguageString(config.main_lang, config.default_lang, "set_wifi_none");
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_console_timezone"), EncodeForSettings<std::string>(loc.name), -1);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_viewer_enabled"), EncodeForSettings(g_ul_config.viewer_usb_enabled), 1);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_flog_enabled"), EncodeForSettings(g_ul_config.system_title_override_enabled), 2);
std::string connectednet = cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_wifi_none");
if(net::HasConnection())
{
net::NetworkProfileData data = {};
net::GetCurrentNetworkProfile(&data);
connectednet = data.wifi_name;
}
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_wifi_name"), EncodeForSettings(connectednet), 3);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_wifi_name"), EncodeForSettings(connectednet), 3);
u64 lcode = 0;
SetLanguage ilang = SetLanguage_ENUS;
setGetLanguageCode(&lcode);
setMakeLanguage(lcode, &ilang);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_console_lang"), EncodeForSettings(os::GetLanguageName(ilang)), 4);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_console_lang"), EncodeForSettings(os::GetLanguageName(ilang)), 4);
bool console_info_upload = false;
setsysGetConsoleInformationUploadFlag(&console_info_upload);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_console_info_upload"), EncodeForSettings(console_info_upload), 5);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_console_info_upload"), EncodeForSettings(console_info_upload), 5);
bool auto_titles_dl = false;
setsysGetAutomaticApplicationDownloadFlag(&auto_titles_dl);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_auto_titles_dl"), EncodeForSettings(auto_titles_dl), 6);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_auto_titles_dl"), EncodeForSettings(auto_titles_dl), 6);
bool auto_update = false;
setsysGetAutoUpdateEnableFlag(&auto_update);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_auto_update"), EncodeForSettings(auto_update), 7);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_auto_update"), EncodeForSettings(auto_update), 7);
bool wireless_lan = false;
setsysGetWirelessLanEnableFlag(&wireless_lan);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_wireless_lan"), EncodeForSettings(wireless_lan), 8);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_wireless_lan"), EncodeForSettings(wireless_lan), 8);
bool bluetooth = false;
setsysGetBluetoothEnableFlag(&bluetooth);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_bluetooth"), EncodeForSettings(bluetooth), 9);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_bluetooth"), EncodeForSettings(bluetooth), 9);
bool usb_30 = false;
setsysGetUsb30EnableFlag(&usb_30);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_usb_30"), EncodeForSettings(usb_30), 10);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_usb_30"), EncodeForSettings(usb_30), 10);
bool nfc = false;
setsysGetNfcEnableFlag(&nfc);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_nfc"), EncodeForSettings(nfc), 11);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_nfc"), EncodeForSettings(nfc), 11);
char serial[0x20] = {0};
setsysGetSerialNumber(serial);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_serial_no"), EncodeForSettings<std::string>(serial), -1);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_serial_no"), EncodeForSettings<std::string>(serial), -1);
u64 mac = 0;
net::GetMACAddress(&mac);
auto strmac = net::FormatMACAddress(mac);
this->PushSettingItem(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_mac_addr"), EncodeForSettings(strmac), -1);
this->PushSettingItem(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_mac_addr"), EncodeForSettings(strmac), -1);
}
void SettingsMenuLayout::PushSettingItem(std::string name, std::string value_display, int id)
void SettingsMenuLayout::PushSettingItem(const std::string &name, const std::string &value_display, int id)
{
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
auto itm = pu::ui::elm::MenuItem::New(name + ": " + value_display);
itm->AddOnClick(std::bind(&SettingsMenuLayout::setting_Click, this, id));
itm->SetIcon(cfg::GetAssetByTheme(theme, "ui/Setting" + std::string((id < 0) ? "No" : "") + "Editable.png"));
itm->SetIcon(cfg::GetAssetByTheme(g_ul_theme, "ui/Setting" + std::string((id < 0) ? "No" : "") + "Editable.png"));
itm->SetColor(textclr);
this->settingsMenu->AddItem(itm);
}
@ -135,7 +150,7 @@ namespace ui
{
SwkbdConfig swkbd;
swkbdCreate(&swkbd, 0);
swkbdConfigSetGuideText(&swkbd, cfg::GetLanguageString(config.main_lang, config.default_lang, "swkbd_console_nick_guide").c_str());
swkbdConfigSetGuideText(&swkbd, cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "swkbd_console_nick_guide").c_str());
char consolename[SET_MAX_NICKNAME_SIZE] = {};
setsysGetDeviceNickname(consolename);
swkbdConfigSetInitialText(&swkbd, consolename);
@ -152,21 +167,21 @@ namespace ui
}
case 1:
{
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_viewer_enabled"), cfg::GetLanguageString(config.main_lang, config.default_lang, "set_viewer_info") + "\n" + (config.viewer_usb_enabled ? cfg::GetLanguageString(config.main_lang, config.default_lang, "set_disable_conf") : cfg::GetLanguageString(config.main_lang, config.default_lang, "set_enable_conf")), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_viewer_enabled"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_viewer_info") + "\n" + (g_ul_config.viewer_usb_enabled ? cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_disable_conf") : cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_enable_conf")), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "yes"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true);
if(sopt == 0)
{
config.viewer_usb_enabled = !config.viewer_usb_enabled;
g_ul_config.viewer_usb_enabled = !g_ul_config.viewer_usb_enabled;
reload_need = true;
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_changed_reboot"));
g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_changed_reboot"));
}
break;
}
case 2:
{
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "set_flog_enabled"), cfg::GetLanguageString(config.main_lang, config.default_lang, "set_flog_info") + "\n" + (config.viewer_usb_enabled ? cfg::GetLanguageString(config.main_lang, config.default_lang, "set_disable_conf") : cfg::GetLanguageString(config.main_lang, config.default_lang, "set_enable_conf")), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_flog_enabled"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_flog_info") + "\n" + (g_ul_config.viewer_usb_enabled ? cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_disable_conf") : cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "set_enable_conf")), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "yes"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true);
if(sopt == 0)
{
config.system_title_override_enabled = !config.system_title_override_enabled;
g_ul_config.system_title_override_enabled = !g_ul_config.system_title_override_enabled;
reload_need = true;
}
break;
@ -177,21 +192,22 @@ namespace ui
*(u32*)in = 1; // 0 = normal, 1 = qlaunch, 2 = starter?
u8 out[8] = {0};
am::LibraryAppletDaemonLaunchWithSimple(AppletId_netConnect, 0, in, sizeof(in), out, sizeof(out), [&]() -> bool
{
return !am::MenuIsHomePressed();
});
auto rc = *(u32*)in;
LibAppletArgs netargs;
libappletArgsCreate(&netargs, 0);
// Apparently 0 is returned when user connects to/selects a different WiFi network
if(R_SUCCEEDED(rc)) reload_need = true;
auto rc = libappletLaunch(AppletId_netConnect, &netargs, in, sizeof(in), out, sizeof(out), nullptr);
if(R_SUCCEEDED(rc))
{
rc = *(u32*)out;
if(R_SUCCEEDED(rc)) reload_need = true;
}
break;
}
case 4:
{
qapp->FadeOut();
qapp->LoadSettingsLanguagesMenu();
qapp->FadeIn();
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadSettingsLanguagesMenu();
g_menu_app_instance->FadeIn();
break;
}
@ -261,22 +277,8 @@ namespace ui
}
if(reload_need)
{
cfg::SaveConfig(config);
cfg::SaveConfig(g_ul_config);
this->Reload();
}
}
void SettingsMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
qapp->CommonMenuOnLoop();
bool ret = am::MenuIsHomePressed();
if(down & KEY_B) ret = true;
if(ret)
{
qapp->FadeOut();
qapp->LoadMenu();
qapp->FadeIn();
}
}
}

View file

@ -2,25 +2,25 @@
namespace ui
{
SideMenu::SideMenu(pu::ui::Color SuspendedColor, std::string CursorPath, std::string SuspendedImagePath, std::string MultiselectImagePath, u32 TextX, u32 TextY, u32 TextSize, pu::ui::Color TextColor, s32 y)
SideMenu::SideMenu(pu::ui::Color suspended_clr, std::string cursor_path, std::string suspended_img_path, std::string multiselect_img_path, u32 txt_x, u32 txt_y, u32 txt_sz, pu::ui::Color txt_clr, s32 y)
{
this->selitm = 0;
this->suspitm = -1;
this->suspclr = SuspendedColor;
this->suspclr = suspended_clr;
this->baseiconidx = 0;
this->scrollflag = 0;
this->movalpha = 0;
this->leftbicon = NULL;
this->rightbicon = NULL;
this->cursoricon = pu::ui::render::LoadImage(CursorPath);
this->suspicon = pu::ui::render::LoadImage(SuspendedImagePath);
this->mselicon = pu::ui::render::LoadImage(MultiselectImagePath);
this->textfont = pu::ui::render::LoadDefaultFont(TextSize);
this->textx = TextX;
this->texty = TextY;
this->textclr = TextColor;
this->onselect = [&](u32,u64){};
this->onselch = [&](u32){};
this->leftbicon = nullptr;
this->rightbicon = nullptr;
this->cursoricon = pu::ui::render::LoadImage(cursor_path);
this->suspicon = pu::ui::render::LoadImage(suspended_img_path);
this->mselicon = pu::ui::render::LoadImage(multiselect_img_path);
this->textfont = pu::ui::render::LoadDefaultFont(txt_sz);
this->textx = txt_x;
this->texty = txt_y;
this->textclr = txt_clr;
this->onselect = [](u32,u64){};
this->onselch = [](u32){};
this->scrolltpvalue = 50;
this->scrollcount = 0;
this->enabled = true;
@ -29,15 +29,15 @@ namespace ui
SideMenu::~SideMenu()
{
if(this->cursoricon != NULL)
if(this->cursoricon != nullptr)
{
pu::ui::render::DeleteTexture(this->cursoricon);
this->cursoricon = NULL;
this->cursoricon = nullptr;
}
if(this->suspicon != NULL)
if(this->suspicon != nullptr)
{
pu::ui::render::DeleteTexture(this->suspicon);
this->suspicon = NULL;
this->suspicon = nullptr;
}
this->ClearItems();
}
@ -70,7 +70,7 @@ namespace ui
return ItemSize + FocusSize + FocusMargin;
}
void SideMenu::OnRender(pu::ui::render::Renderer::Ref &Drawer, s32 X, s32 Y)
void SideMenu::OnRender(pu::ui::render::Renderer::Ref &drawer, s32 x, s32 y)
{
if(this->icons.empty()) return;
if(this->ricons.empty())
@ -80,7 +80,7 @@ namespace ui
auto icon = pu::ui::render::LoadImage(this->icons[this->baseiconidx + i]);
auto text = this->icons_texts[this->baseiconidx + i];
this->ricons.push_back(icon);
pu::ui::render::NativeTexture ntext = NULL;
pu::ui::render::NativeTexture ntext = nullptr;
if(!text.empty()) ntext = pu::ui::render::RenderText(this->textfont, text, this->textclr);
this->ricons_texts.push_back(ntext);
}
@ -88,44 +88,44 @@ namespace ui
(this->onselch)(this->selitm);
}
u32 basex = X;
u32 basex = x;
for(u32 i = 0; i < this->ricons.size(); i++)
{
auto ricon = this->ricons[i];
Drawer->RenderTexture(ricon, basex, Y, { -1, ItemSize, ItemSize, -1 });
drawer->RenderTexture(ricon, basex, y, { -1, ItemSize, ItemSize, -1 });
auto ntext = this->ricons_texts[i];
if(ntext != NULL) Drawer->RenderTexture(ntext, basex + this->textx, Y + this->texty);
if(this->IsItemMultiselected(this->baseiconidx + i)) Drawer->RenderTexture(this->mselicon, basex - Margin, Y - Margin, { -1, ExtraIconSize, ExtraIconSize, -1 });
if(ntext != nullptr) drawer->RenderTexture(ntext, basex + this->textx, y + this->texty);
if(this->IsItemMultiselected(this->baseiconidx + i)) drawer->RenderTexture(this->mselicon, basex - Margin, y - Margin, { -1, ExtraIconSize, ExtraIconSize, -1 });
if(this->suspitm >= 0)
{
if((this->baseiconidx + i) == (u32)suspitm)
{
if(this->suspicon != NULL) Drawer->RenderTexture(this->suspicon, basex - Margin, Y - Margin, { -1, ExtraIconSize, ExtraIconSize, -1 });
if(this->suspicon != nullptr) drawer->RenderTexture(this->suspicon, basex - Margin, y - Margin, { -1, ExtraIconSize, ExtraIconSize, -1 });
}
}
if(this->cursoricon != NULL)
if(this->cursoricon != nullptr)
{
if((this->baseiconidx + i) == selitm)
{
Drawer->RenderTexture(this->cursoricon, basex - Margin, Y - Margin, { 255 - movalpha, ExtraIconSize, ExtraIconSize, -1 });
drawer->RenderTexture(this->cursoricon, basex - Margin, y - Margin, { 255 - movalpha, ExtraIconSize, ExtraIconSize, -1 });
}
else if((this->baseiconidx + i) == preselitm)
{
Drawer->RenderTexture(this->cursoricon, basex - Margin, Y - Margin, { movalpha, ExtraIconSize, ExtraIconSize, -1 });
drawer->RenderTexture(this->cursoricon, basex - Margin, y - Margin, { movalpha, ExtraIconSize, ExtraIconSize, -1 });
}
}
basex += ItemSize + Margin;
}
if(leftbicon != NULL)
if(leftbicon != nullptr)
{
Drawer->RenderTexture(leftbicon, X - ItemSize - Margin, Y, { -1, ItemSize, ItemSize, -1 });
drawer->RenderTexture(leftbicon, x - ItemSize - Margin, y, { -1, ItemSize, ItemSize, -1 });
}
if(rightbicon != NULL)
if(rightbicon != nullptr)
{
Drawer->RenderTexture(rightbicon, X + ((ItemSize + Margin) * 4), Y, { -1, ItemSize, ItemSize, -1 });
drawer->RenderTexture(rightbicon, x + ((ItemSize + Margin) * 4), y, { -1, ItemSize, ItemSize, -1 });
}
if(movalpha > 0)
@ -136,23 +136,23 @@ namespace ui
}
}
void SideMenu::OnInput(u64 Down, u64 Up, u64 Held, pu::ui::Touch Touch)
void SideMenu::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
if(this->ricons.empty()) return;
if(!this->enabled) return;
if(Down & KEY_LEFT) HandleMoveLeft();
else if(Down & KEY_RIGHT) HandleMoveRight();
else if(!Touch.IsEmpty())
if(down & KEY_LEFT) HandleMoveLeft();
else if(down & KEY_RIGHT) HandleMoveRight();
else if(!pos.IsEmpty())
{
s32 basex = this->GetProcessedX();
s32 basey = this->GetProcessedY();
if(this->cursoricon != NULL)
if(this->cursoricon != nullptr)
{
for(u32 i = 0; i < this->ricons.size(); i++)
{
if((Touch.X >= basex) && (Touch.X < (basex + (s32)ItemSize)) && (Touch.Y >= basey) && (Touch.Y < (basey + (s32)ItemSize)))
if((pos.X >= basex) && (pos.X < (basex + (s32)ItemSize)) && (pos.Y >= basey) && (pos.Y < (basey + (s32)ItemSize)))
{
if((this->baseiconidx + i) == selitm) (this->onselect)(KEY_A, this->selitm);
else
@ -168,9 +168,9 @@ namespace ui
}
}
}
else (this->onselect)(Down, this->selitm);
else (this->onselect)(down, this->selitm);
if(Held & KEY_LEFT)
if(held & KEY_LEFT)
{
if(this->scrollflag == 1)
{
@ -206,7 +206,7 @@ namespace ui
this->scrolltp = std::chrono::steady_clock::now();
}
}
else if(Held & KEY_RIGHT)
else if(held & KEY_RIGHT)
{
if(this->scrollflag == 2)
{
@ -250,14 +250,14 @@ namespace ui
}
}
void SideMenu::SetOnItemSelected(std::function<void(u64, u32)> Fn)
void SideMenu::SetOnItemSelected(std::function<void(u64, u32)> fn)
{
this->onselect = Fn;
this->onselect = fn;
}
void SideMenu::SetOnSelectionChanged(std::function<void(u32)> Fn)
void SideMenu::SetOnSelectionChanged(std::function<void(u32)> fn)
{
this->onselch = Fn;
this->onselch = fn;
}
void SideMenu::ClearItems()
@ -267,12 +267,12 @@ namespace ui
this->icons_mselected.clear();
for(auto ricon: this->ricons)
{
if(ricon != NULL) pu::ui::render::DeleteTexture(ricon);
if(ricon != nullptr) pu::ui::render::DeleteTexture(ricon);
}
this->ricons.clear();
for(auto rtext: this->ricons_texts)
{
if(rtext != NULL) pu::ui::render::DeleteTexture(rtext);
if(rtext != nullptr) pu::ui::render::DeleteTexture(rtext);
}
this->ricons_texts.clear();
this->selitm = 0;
@ -281,10 +281,10 @@ namespace ui
this->ClearBorderIcons();
}
void SideMenu::AddItem(std::string Icon, std::string Text)
void SideMenu::AddItem(const std::string &icon, const std::string &txt)
{
this->icons.push_back(Icon);
this->icons_texts.push_back(Text);
this->icons.push_back(icon);
this->icons_texts.push_back(txt);
this->icons_mselected.push_back(false);
}
@ -298,9 +298,9 @@ namespace ui
this->suspitm = -1;
}
void SideMenu::SetSelectedItem(u32 Index)
void SideMenu::SetSelectedItem(u32 idx)
{
if(Index < this->icons.size()) this->selitm = Index;
if(idx < this->icons.size()) this->selitm = idx;
}
void SideMenu::HandleMoveLeft()
@ -362,16 +362,16 @@ namespace ui
return false;
}
void SideMenu::ReloadIcons(u32 Direction)
void SideMenu::ReloadIcons(u32 dir)
{
switch(Direction)
switch(dir)
{
case 1: // Left
{
auto icon = pu::ui::render::LoadImage(this->icons[this->selitm]);
this->ricons.insert(this->ricons.begin(), icon);
auto text = this->icons_texts[this->selitm];
pu::ui::render::NativeTexture ntext = NULL;
pu::ui::render::NativeTexture ntext = nullptr;
if(!text.empty()) ntext = pu::ui::render::RenderText(this->textfont, text, this->textclr);
this->ricons_texts.insert(this->ricons_texts.begin(), ntext);
this->baseiconidx--;
@ -380,7 +380,7 @@ namespace ui
pu::ui::render::DeleteTexture(this->ricons.back());
this->ricons.pop_back();
auto ntext = this->ricons_texts.back();
if(ntext != NULL) pu::ui::render::DeleteTexture(ntext);
if(ntext != nullptr) pu::ui::render::DeleteTexture(ntext);
this->ricons_texts.pop_back();
}
break;
@ -396,7 +396,7 @@ namespace ui
pu::ui::render::DeleteTexture(this->ricons.front());
this->ricons.erase(this->ricons.begin());
auto ntext = this->ricons_texts.front();
if(ntext != NULL) pu::ui::render::DeleteTexture(ntext);
if(ntext != nullptr) pu::ui::render::DeleteTexture(ntext);
this->ricons_texts.erase(this->ricons_texts.begin());
this->baseiconidx++;
}
@ -416,34 +416,28 @@ namespace ui
this->baseiconidx = index;
}
void SideMenu::SetBasePositions(u32 SelectedIdx, u32 BaseIdx)
void SideMenu::SetBasePositions(u32 selected_idx, u32 base_idx)
{
if(SelectedIdx < this->icons.size())
if(selected_idx < this->icons.size())
{
this->SetSelectedItem(SelectedIdx);
this->SetBaseItemIndex(BaseIdx);
this->SetSelectedItem(selected_idx);
this->SetBaseItemIndex(base_idx);
}
}
void SideMenu::ClearBorderIcons()
{
if(leftbicon != NULL) pu::ui::render::DeleteTexture(leftbicon);
leftbicon = NULL;
if(rightbicon != NULL) pu::ui::render::DeleteTexture(rightbicon);
rightbicon = NULL;
if(this->leftbicon != nullptr) pu::ui::render::DeleteTexture(this->leftbicon);
this->leftbicon = nullptr;
if(this->rightbicon != nullptr) pu::ui::render::DeleteTexture(this->rightbicon);
this->rightbicon = nullptr;
}
void SideMenu::UpdateBorderIcons()
{
this->ClearBorderIcons();
if(baseiconidx > 0)
{
leftbicon = pu::ui::render::LoadImage(icons[baseiconidx - 1]);
}
if((baseiconidx + 4) < icons.size())
{
rightbicon = pu::ui::render::LoadImage(icons[baseiconidx + 4]);
}
if(this->baseiconidx > 0) this->leftbicon = pu::ui::render::LoadImage(this->icons[this->baseiconidx - 1]);
if((this->baseiconidx + 4) < this->icons.size()) this->rightbicon = pu::ui::render::LoadImage(this->icons[this->baseiconidx + 4]);
}
void SideMenu::ResetMultiselections()
@ -454,10 +448,7 @@ namespace ui
void SideMenu::SetItemMultiselected(u32 index, bool selected)
{
if(index < this->icons_mselected.size())
{
this->icons_mselected[index] = selected;
}
if(index < this->icons_mselected.size()) this->icons_mselected[index] = selected;
}
bool SideMenu::IsItemMultiselected(u32 index)

View file

@ -4,103 +4,64 @@
#include <ui/ui_MenuApplication.hpp>
#include <fs/fs_Stdio.hpp>
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
extern ui::MenuApplication::Ref g_menu_app_instance;
extern cfg::Theme g_ul_theme;
extern cfg::Config g_ul_config;
namespace ui
{
StartupLayout::StartupLayout()
{
this->SetBackgroundImage(cfg::GetAssetByTheme(theme, "ui/Background.png"));
this->SetBackgroundImage(cfg::GetAssetByTheme(g_ul_theme, "ui/Background.png"));
this->loadmenu = false;
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
this->infoText = pu::ui::elm::TextBlock::New(35, 635, cfg::GetLanguageString(config.main_lang, config.default_lang, "startup_welcome_info") + "\n" + cfg::GetLanguageString(config.main_lang, config.default_lang, "startup_control_info"));
this->infoText = pu::ui::elm::TextBlock::New(35, 635, cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "startup_welcome_info") + "\n" + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "startup_control_info"));
this->infoText->SetColor(textclr);
qapp->ApplyConfigForElement("startup_menu", "info_text", this->infoText);
g_menu_app_instance->ApplyConfigForElement("startup_menu", "info_text", this->infoText);
this->Add(this->infoText);
this->usersMenu = pu::ui::elm::Menu::New(200, 60, 880, menubgclr, 100, 5);
this->usersMenu->SetOnFocusColor(menufocusclr);
qapp->ApplyConfigForElement("startup_menu", "users_menu_item", this->usersMenu);
g_menu_app_instance->ApplyConfigForElement("startup_menu", "users_menu_item", this->usersMenu);
this->Add(this->usersMenu);
this->SetOnInput(std::bind(&StartupLayout::OnInput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
}
void StartupLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
void StartupLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
qapp->CommonMenuOnLoop();
if(this->loadmenu)
{
this->loadmenu = false;
qapp->StartPlayBGM();
qapp->FadeOut();
qapp->LoadMenu();
qapp->FadeIn();
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "menu_quick_info"), 3000); // Show for 3s
g_menu_app_instance->StartPlayBGM();
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadMenu();
g_menu_app_instance->FadeIn();
g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "menu_quick_info"), 3000); // Show for 3s
}
}
void StartupLayout::user_Click(AccountUid uid, bool has_password)
void StartupLayout::OnHomeButtonPress()
{
bool login_ok = false;
if(has_password)
{
SwkbdConfig swkbd;
swkbdCreate(&swkbd, 0);
swkbdConfigMakePresetPassword(&swkbd);
swkbdConfigSetStringLenMax(&swkbd, 15);
swkbdConfigSetGuideText(&swkbd, cfg::GetLanguageString(config.main_lang, config.default_lang, "swkbd_user_pass_guide").c_str());
char inpass[0x10] = {0};
auto rc = swkbdShow(&swkbd, inpass, 0x10);
swkbdClose(&swkbd);
if(R_SUCCEEDED(rc))
{
auto [rc2, pass] = db::PackPassword(uid, inpass);
rc = rc2;
if(R_SUCCEEDED(rc))
{
am::MenuCommandWriter writer(am::DaemonMessage::TryLogUser);
writer.Write<db::PassBlock>(pass);
writer.FinishWrite();
// ...
}
am::MenuCommandResultReader reader;
rc = reader.GetReadResult();
reader.FinishRead();
if(R_FAILED(rc)) qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "startup_login_error"));
else login_ok = true;
}
}
}
else login_ok = true;
this->loadmenu = login_ok;
if(login_ok) qapp->SetSelectedUser(uid);
void StartupLayout::user_Click(AccountUid uid)
{
this->loadmenu = true;
g_menu_app_instance->SetSelectedUser(uid);
}
void StartupLayout::create_Click()
{
u8 in[0xa0] = {0};
u8 out[0x18] = {0};
*(u32*)in = 1; // PselUiMode_UserCreation
LibAppletArgs args;
libappletArgsCreate(&args, 0);
auto rc = libappletLaunch(AppletId_playerSelect, &args, in, 0xa0, out, 0x18, NULL);
auto rc = pselShowUserCreator();
if(R_SUCCEEDED(rc))
{
rc = *(u32*)out;
if(R_SUCCEEDED(rc))
{
qapp->FadeOut();
this->ReloadMenu();
qapp->FadeIn();
}
g_menu_app_instance->FadeOut();
this->ReloadMenu();
g_menu_app_instance->FadeIn();
}
}
@ -109,7 +70,7 @@ namespace ui
this->usersMenu->ClearItems();
this->usersMenu->SetSelectedIndex(0);
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
auto [rc, users] = os::QuerySystemAccounts(true);
if(R_SUCCEEDED(rc))
@ -119,27 +80,17 @@ namespace ui
auto [rc, name] = os::GetAccountName(user);
if(R_FAILED(rc)) continue;
am::MenuCommandWriter writer(am::DaemonMessage::UserHasPassword);
writer.Write<AccountUid>(user);
writer.FinishWrite();
am::MenuCommandResultReader res;
res.FinishRead();
bool has_pass = R_SUCCEEDED(res.GetReadResult());
if(has_pass) name += " " + cfg::GetLanguageString(config.main_lang, config.default_lang, "startup_password");
auto path = os::GetIconCacheImagePath(user);
auto uitm = pu::ui::elm::MenuItem::New(name);
uitm->SetIcon(path);
uitm->AddOnClick(std::bind(&StartupLayout::user_Click, this, user, has_pass));
uitm->AddOnClick(std::bind(&StartupLayout::user_Click, this, user));
uitm->SetColor(textclr);
this->usersMenu->AddItem(uitm);
}
}
auto citm = pu::ui::elm::MenuItem::New(cfg::GetLanguageString(config.main_lang, config.default_lang, "startup_new_user"));
auto citm = pu::ui::elm::MenuItem::New(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "startup_new_user"));
citm->SetColor(textclr);
citm->AddOnClick(std::bind(&StartupLayout::create_Click, this));
this->usersMenu->AddItem(citm);

View file

@ -4,61 +4,76 @@
#include <ui/ui_MenuApplication.hpp>
#include <fs/fs_Stdio.hpp>
extern ui::MenuApplication::Ref qapp;
extern cfg::Theme theme;
extern cfg::Config config;
extern ui::MenuApplication::Ref g_menu_app_instance;
extern cfg::Theme g_ul_theme;
extern cfg::Config g_ul_config;
namespace ui
{
ThemeMenuLayout::ThemeMenuLayout()
{
this->SetBackgroundImage(cfg::GetAssetByTheme(theme, "ui/Background.png"));
this->SetBackgroundImage(cfg::GetAssetByTheme(g_ul_theme, "ui/Background.png"));
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
pu::ui::Color menufocusclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_focus_color", "#5ebcffff"));
pu::ui::Color menubgclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("menu_bg_color", "#0094ffff"));
this->curThemeBanner = pu::ui::elm::Image::New(0, 585, cfg::GetAssetByTheme(theme, "ui/BannerTheme.png"));
qapp->ApplyConfigForElement("themes_menu", "banner_image", this->curThemeBanner);
this->curThemeBanner = pu::ui::elm::Image::New(0, 585, cfg::GetAssetByTheme(g_ul_theme, "ui/BannerTheme.png"));
g_menu_app_instance->ApplyConfigForElement("themes_menu", "banner_image", this->curThemeBanner);
this->Add(this->curThemeBanner);
this->themesMenu = pu::ui::elm::Menu::New(200, 60, 880, menubgclr, 100, 5);
this->themesMenu->SetOnFocusColor(menufocusclr);
qapp->ApplyConfigForElement("themes_menu", "themes_menu_item", this->themesMenu);
g_menu_app_instance->ApplyConfigForElement("themes_menu", "themes_menu_item", this->themesMenu);
this->Add(this->themesMenu);
this->curThemeText = pu::ui::elm::TextBlock::New(20, 540, cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_current") + ":", 30);
this->curThemeText = pu::ui::elm::TextBlock::New(20, 540, cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_current") + ":", 30);
this->curThemeText->SetColor(textclr);
qapp->ApplyConfigForElement("themes_menu", "current_theme_text", this->curThemeText);
g_menu_app_instance->ApplyConfigForElement("themes_menu", "current_theme_text", this->curThemeText);
this->Add(this->curThemeText);
this->curThemeName = pu::ui::elm::TextBlock::New(40, 610, "", 30);
this->curThemeName->SetColor(textclr);
qapp->ApplyConfigForElement("themes_menu", "current_theme_name_text", this->curThemeName);
g_menu_app_instance->ApplyConfigForElement("themes_menu", "current_theme_name_text", this->curThemeName);
this->Add(this->curThemeName);
this->curThemeAuthor = pu::ui::elm::TextBlock::New(45, 650, "", 20);
this->curThemeAuthor->SetColor(textclr);
qapp->ApplyConfigForElement("themes_menu", "current_theme_author_text", this->curThemeAuthor);
g_menu_app_instance->ApplyConfigForElement("themes_menu", "current_theme_author_text", this->curThemeAuthor);
this->Add(this->curThemeAuthor);
this->curThemeVersion = pu::ui::elm::TextBlock::New(45, 675, "", 20);
this->curThemeVersion->SetColor(textclr);
qapp->ApplyConfigForElement("themes_menu", "current_theme_version_text", this->curThemeVersion);
g_menu_app_instance->ApplyConfigForElement("themes_menu", "current_theme_version_text", this->curThemeVersion);
this->Add(this->curThemeVersion);
this->curThemeIcon = pu::ui::elm::Image::New(1000, 605, "");
this->curThemeIcon->SetWidth(100);
this->curThemeIcon->SetHeight(100);
qapp->ApplyConfigForElement("themes_menu", "current_theme_icon", this->curThemeIcon);
g_menu_app_instance->ApplyConfigForElement("themes_menu", "current_theme_icon", this->curThemeIcon);
this->Add(this->curThemeIcon);
}
this->SetOnInput(std::bind(&ThemeMenuLayout::OnInput, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
void ThemeMenuLayout::OnMenuInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
if(down & KEY_B)
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadMenu();
g_menu_app_instance->FadeIn();
}
}
void ThemeMenuLayout::OnHomeButtonPress()
{
g_menu_app_instance->FadeOut();
g_menu_app_instance->LoadMenu();
g_menu_app_instance->FadeIn();
}
void ThemeMenuLayout::Reload()
{
pu::ui::Color textclr = pu::ui::Color::FromHex(qapp->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
if(cfg::ThemeIsDefault(theme))
pu::ui::Color textclr = pu::ui::Color::FromHex(g_menu_app_instance->GetUIConfigValue<std::string>("text_color", "#e1e1e1ff"));
if(cfg::ThemeIsDefault(g_ul_theme))
{
this->curThemeText->SetText(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_no_custom"));
this->curThemeText->SetText(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_no_custom"));
this->curThemeName->SetVisible(false);
this->curThemeAuthor->SetVisible(false);
this->curThemeVersion->SetVisible(false);
@ -67,16 +82,16 @@ namespace ui
}
else
{
this->curThemeText->SetText(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_current") + ":");
this->curThemeText->SetText(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_current") + ":");
this->curThemeName->SetVisible(true);
this->curThemeName->SetText(theme.manifest.name);
this->curThemeName->SetText(g_ul_theme.manifest.name);
this->curThemeAuthor->SetVisible(true);
this->curThemeAuthor->SetText(theme.manifest.author);
this->curThemeAuthor->SetText(g_ul_theme.manifest.author);
this->curThemeVersion->SetVisible(true);
this->curThemeVersion->SetText("v" + theme.manifest.release);
this->curThemeVersion->SetText("v" + g_ul_theme.manifest.release);
this->curThemeBanner->SetVisible(true);
this->curThemeIcon->SetVisible(true);
this->curThemeIcon->SetImage(theme.path + "/theme/Icon.png");
this->curThemeIcon->SetImage(g_ul_theme.path + "/theme/Icon.png");
this->curThemeIcon->SetWidth(100);
this->curThemeIcon->SetHeight(100);
}
@ -86,7 +101,7 @@ namespace ui
this->loadedThemes.clear();
this->loadedThemes = cfg::LoadThemes();
auto ditm = pu::ui::elm::MenuItem::New(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_reset"));
auto ditm = pu::ui::elm::MenuItem::New(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_reset"));
ditm->AddOnClick(std::bind(&ThemeMenuLayout::theme_Click, this));
ditm->SetColor(textclr);
ditm->SetIcon("romfs:/Logo.png");
@ -94,7 +109,7 @@ namespace ui
for(auto &ltheme: this->loadedThemes)
{
auto itm = pu::ui::elm::MenuItem::New(ltheme.manifest.name + " (v" + ltheme.manifest.release + ", " + cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_by") + " " + ltheme.manifest.author + ")");
auto itm = pu::ui::elm::MenuItem::New(ltheme.manifest.name + " (v" + ltheme.manifest.release + ", " + cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_by") + " " + ltheme.manifest.author + ")");
itm->AddOnClick(std::bind(&ThemeMenuLayout::theme_Click, this));
itm->SetColor(textclr);
auto iconpath = ltheme.path + "/theme/Icon.png";
@ -103,32 +118,20 @@ namespace ui
}
}
void ThemeMenuLayout::OnInput(u64 down, u64 up, u64 held, pu::ui::Touch pos)
{
bool ret = am::MenuIsHomePressed();
if(down & KEY_B) ret = true;
if(ret)
{
qapp->FadeOut();
qapp->LoadMenu();
qapp->FadeIn();
}
}
void ThemeMenuLayout::theme_Click()
{
auto idx = this->themesMenu->GetSelectedIndex();
if(idx == 0)
{
if(cfg::ThemeIsDefault(theme)) qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_no_custom"));
if(cfg::ThemeIsDefault(g_ul_theme)) g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_no_custom"));
else
{
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_reset"), cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_reset_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true);
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_reset"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_reset_conf"), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "yes"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true);
if(sopt == 0)
{
config.theme_name = "";
cfg::SaveConfig(config);
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_changed"));
g_ul_config.theme_name = "";
cfg::SaveConfig(g_ul_config);
g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_changed"));
}
}
}
@ -137,15 +140,15 @@ namespace ui
idx--;
auto seltheme = this->loadedThemes[idx];
auto iconpath = seltheme.path + "/theme/Icon.png";
if(seltheme.base_name == theme.base_name) qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_active_this"));
if(seltheme.base_name == g_ul_theme.base_name) g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_active_this"));
else
{
auto sopt = qapp->CreateShowDialog(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_set"), cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_set_conf"), { cfg::GetLanguageString(config.main_lang, config.default_lang, "yes"), cfg::GetLanguageString(config.main_lang, config.default_lang, "cancel") }, true, iconpath);
auto sopt = g_menu_app_instance->CreateShowDialog(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_set"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_set_conf"), { cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "yes"), cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "cancel") }, true, iconpath);
if(sopt == 0)
{
config.theme_name = seltheme.base_name;
cfg::SaveConfig(config);
qapp->ShowNotification(cfg::GetLanguageString(config.main_lang, config.default_lang, "theme_changed"));
g_ul_config.theme_name = seltheme.base_name;
cfg::SaveConfig(g_ul_config);
g_menu_app_instance->ShowNotification(cfg::GetLanguageString(g_ul_config.main_lang, g_ul_config.default_lang, "theme_changed"));
}
}
}