Reenable Applet Mode, add boot warning instead.

This commit is contained in:
J-D-K
2025-11-28 12:58:58 -05:00
parent 84535f7238
commit 3f55bf8ef9
20 changed files with 53 additions and 100 deletions

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV unterstützt das Ausführen in Applets wie dem Album nicht mehr.\n\nStarte JKSV erneut, nachdem du ein Spiel oder eine Anwendung mit gedrückter [R]-Taste gestartet hast.\n\nDrücke [+], um zu beenden."
"0: *Warnung*: Applet-Modus erkannt. Unerwartetes Verhalten kann auftreten!"
],
"BackupMenu": [
"0: Neues Backup"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV no longer supports running under applets such as the album.\n\nRun JKSV again after starting a game or application while holding [R].\n\nPress [+] to exit."
"0: *Warning*: Applet mode detected. Unexpected behavior may occur!"
],
"BackupMenu": [
"0: New Backup"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV no longer supports running under applets such as the album.\n\nRun JKSV again after starting a game or application while holding [R].\n\nPress [+] to exit."
"0: *Warning*: Applet mode detected. Unexpected behavior may occur!"
],
"BackupMenu": [
"0: New Backup"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV ya no es compatible con la ejecución en applets como el álbum.\n\nEjecuta JKSV nuevamente después de iniciar un juego o aplicación mientras mantienes presionado [R].\n\nPulsa [+] para salir."
"0: *Advertencia*: Modo applet detectado. ¡Puede ocurrir un comportamiento inesperado!"
],
"BackupMenu": [
"0: Nueva copia de seguridad"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV ya no es compatible con ejecutarse en applets como el álbum.\n\nInicia JKSV de nuevo después de abrir un juego o aplicación manteniendo presionado [R].\n\nPresiona [+] para salir."
"0: *Advertencia*: Modo applet detectado. ¡Puede ocurrir un comportamiento inesperado!"
],
"BackupMenu": [
"0: Nueva copia de seguridad"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV ne prend plus en charge lexécution dans des applets comme lalbum.\n\nRelancez JKSV après avoir démarré un jeu ou une application en maintenant [R].\n\nAppuyez sur [+] pour quitter."
"0: *Attention* : Mode applet détecté. Un comportement inattendu peut se produire !"
],
"BackupMenu": [
"0: Nouvelle sauvegarde"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV ne prend plus en charge lexécution dans des applets comme lalbum.\n\nRelancez JKSV après avoir démarré un jeu ou une application en maintenant [R].\n\nAppuyez sur [+] pour quitter."
"0: *Attention* : Mode applet détecté. Un comportement inattendu peut se produire !"
],
"BackupMenu": [
"0: Nouvelle sauvegarde"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV non supporta più lesecuzione in applet come lalbum.\n\nAvvia di nuovo JKSV dopo aver avviato un gioco o un'applicazione tenendo premuto [R].\n\nPremi [+] per uscire."
"0: *Attenzione*: Modalità applet rilevata. Potrebbero verificarsi comportamenti imprevisti!"
],
"BackupMenu": [
"0: Nuovo backup"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV はアルバムなどのアプレットでの実行をサポートしなくなりました。\n\n[R] を押しながらゲームまたはアプリケーションを起動した後、もう一度 JKSV を起動してください。\n\n終了するには [+] を押してください."
"0: *警告*: アプレットモードが検出されました。予期しない動作が発生する可能性があります!"
],
"BackupMenu": [
"0: 新しい バックアップ"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV는 앨범과 같은 애플릿에서의 실행을 더 이상 지원하지 않습니다.\n\n[R]을 누른 상태로 게임 또는 애플리케이션을 실행한 후 JKSV를 다시 실행하세요.\n\n종료하려면 [+]를 누르세요."
"0: *경고*: 앱렛 모드가 감지되었습니다. 예상치 못한 동작이 발생할 수 있습니다!"
],
"BackupMenu": [
"0: 새 백업"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV ondersteunt het uitvoeren onder applets zoals het album niet meer.\n\nStart JKSV opnieuw nadat je een spel of applicatie hebt gestart terwijl je [R] ingedrukt houdt.\n\nDruk op [+] om af te sluiten."
"0: *Waarschuwing*: Applet-modus gedetecteerd. Onverwacht gedrag kan optreden!"
],
"BackupMenu": [
"0: Nieuwe back-up"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: O JKSV já não suporta ser executado em applets como o álbum.\n\nExecute novamente o JKSV depois de iniciar um jogo ou aplicação enquanto mantém [R] pressionado.\n\nPrima [+] para sair."
"0: *Aviso*: Modo applet detectado. Comportamento inesperado pode ocorrer!"
],
"BackupMenu": [
"0: Novo Backup"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: O JKSV não oferece mais suporte para execução em applets como o álbum.\n\nExecute o JKSV novamente após iniciar um jogo ou aplicativo enquanto mantém [R] pressionado.\n\nPressione [+] para sair."
"0: *Aviso*: Modo applet detectado. Comportamento inesperado pode ocorrer!"
],
"BackupMenu": [
"0: Novo Backup"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV больше не поддерживает запуск в апплетах, таких как Альбом.\n\nЗапустите JKSV снова после запуска игры или приложения, удерживая [R].\n\nНажмите [+], чтобы выйти."
"0: *Внимание*: Обнаружен режим апплета. Возможны непредвиденные действия!"
],
"BackupMenu": [
"0: Новый бэкап"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV 不再支持在相册等小程序模式下运行。\n\n请在按住 [R] 启动游戏或应用后重新运行 JKSV。\n\n按 [+] 退出。"
"0: *警告*: 检测到小程序模式。可能会发生意外行为!"
],
"BackupMenu": [
"0: 新备份"

View File

@@ -1,6 +1,6 @@
{
"AppletMode": [
"0: JKSV 不再支援在相簿等小程式中執行。\n\n請在按住 [R] 啟動遊戲或應用程式後重新啟動 JKSV。\n\n按下 [+] 以退出。"
"0: *警告*: 偵測到小程式模式。可能會發生意外行為!"
],
"BackupMenu": [
"0: 新備份"

View File

@@ -60,15 +60,15 @@ class JKSV
// Creates the needed directories on SD.
bool create_directories();
/// @brief Checks for and pushes the applet mode state. Returns true if applet type is applet.
bool applet_mode_check() noexcept;
/// @brief Adds the text color changing characters.
void add_color_chars();
/// @brief Retrieves the strings from the map and sets them up for printing.
void setup_translation_info_strings();
/// @brief Pushed the applet mode warning pop-up if needed.
void applet_mode_warning() noexcept;
/// @brief Renders the base UI.
void render_base();

View File

@@ -1,7 +1,6 @@
#include "JKSV.hpp"
#include "StateManager.hpp"
#include "appstates/AppletModeState.hpp"
#include "appstates/FileModeState.hpp"
#include "appstates/MainMenuState.hpp"
#include "appstates/TaskState.hpp"
@@ -91,9 +90,6 @@ JKSV::JKSV()
JKSV::create_directories();
sys::threadpool::initialize(); // This is the thread pool so JKSV isn't constantly creating and destroying threads.
// To do: Rearrange init so JKSV doesn't init so much.
if (JKSV::applet_mode_check()) { return; }
// Push the remote init.
sys::threadpool::push_job(remote::initialize, nullptr);
@@ -104,6 +100,9 @@ JKSV::JKSV()
// This isn't required, but why not?
FadeState::create_and_push(colors::BLACK, 0xFF, 0x00, nullptr);
// Push this warning so people can't complain if JKSV runs out of RAM.
JKSV::applet_mode_warning();
// JKSV is now running.
sm_isRunning = true;
}
@@ -221,21 +220,6 @@ bool JKSV::create_directories()
return true;
}
bool JKSV::applet_mode_check() noexcept
{
// Determine whether or not we're running as and application. If we are, return false.
const bool appletMode = appletGetAppletType() != AppletType_Application;
if (!appletMode) { return false; }
// We are running as an applet. Push the state.
StateManager::push_state(AppletModeState::create());
// Set this to running.
sm_isRunning = true;
return true;
}
void JKSV::add_color_chars()
{
sdl::text::add_color_character(L'#', colors::BLUE);
@@ -256,6 +240,20 @@ void JKSV::setup_translation_info_strings()
m_buildString = stringutil::get_formatted_string("v. %02d.%02d.%04d", builddate::MONTH, builddate::DAY, builddate::YEAR);
}
void JKSV::applet_mode_warning() noexcept
{
// This hangs longer than other pop messages.
static constexpr int APPLET_TICKS = 5000;
// Anything that doesn't register as an application is an applet as far as I'm concerned.
const bool isApplet = appletGetAppletType() != AppletType_Application;
if (!isApplet) { return; }
// Get the string and push the pop message.
const char *appletString = strings::get_by_name(strings::names::APPLET_MODE, 0);
ui::PopMessageManager::push_message(APPLET_TICKS, appletString);
}
void JKSV::render_base()
{
// These are the same for both.

View File

@@ -1,34 +0,0 @@
#include "appstates/AppletModeState.hpp"
#include "graphics/colors.hpp"
#include "sdl.hpp"
#include "strings/strings.hpp"
// ---- Construction ----
AppletModeState::AppletModeState() { AppletModeState::get_applet_mode_string(); }
// ---- Public functions / overrides ----
void AppletModeState::update()
{
// This serves no purpose other that to allow the user to exit.
}
void AppletModeState::render()
{
// Coordinates for rendering.
static constexpr int RENDER_X = 48;
static constexpr int RENDER_Y = 112;
static constexpr int FONT_SIZE = 24;
static constexpr int WRAP_WIDTH = 1154;
sdl::text::render(sdl::Texture::Null, RENDER_X, RENDER_Y, FONT_SIZE, WRAP_WIDTH, colors::WHITE, m_appletModeString);
}
// ---- Private functions ----
void AppletModeState::get_applet_mode_string() noexcept
{
m_appletModeString = strings::get_by_name(strings::names::APPLET_MODE, 0);
}

View File

@@ -1,5 +1,6 @@
#include "remote/GoogleDrive.hpp"
#include "error.hpp"
#include "logging/logger.hpp"
#include "remote/Form.hpp"
#include "remote/URL.hpp"
@@ -54,33 +55,21 @@ remote::GoogleDrive::GoogleDrive()
// Load the json file.
json::Object clientJson = json::new_object(json_object_from_file, remote::PATH_GOOGLE_DRIVE_CONFIG.data());
if (!clientJson)
{
logger::log(STRING_ERROR_READING_CONFIG, "Error reading configuration file!");
return;
}
if (!clientJson) { return; }
json_object *installed = json::get_object(clientJson, JSON_KEY_INSTALLED);
if (!installed)
{
logger::log(STRING_ERROR_READING_CONFIG, "Configuration file is malformed!");
return;
}
if (error::is_null(installed)) { return; }
json_object *clientId = json_object_object_get(installed, JSON_KEY_CLIENT_ID);
json_object *clientSecret = json_object_object_get(installed, JSON_KEY_CLIENT_SECRET);
json_object *refreshToken = json_object_object_get(installed, JSON_KEY_REFRESH_TOKEN);
if (!clientId || !clientSecret)
{
logger::log(STRING_ERROR_READING_CONFIG, "Configuration file is missing required data!");
return;
}
if (error::is_null({clientId, clientSecret})) { return; }
// Grab them.
m_clientId = json_object_get_string(clientId);
m_clientSecret = json_object_get_string(clientSecret);
// Returning here will make is_initialized return false.
if (!refreshToken) { return; }
if (error::is_null(refreshToken)) { return; }
m_refreshToken = json_object_get_string(refreshToken);
if (!GoogleDrive::refresh_token())
@@ -134,7 +123,7 @@ bool remote::GoogleDrive::create_directory(std::string_view name)
// This is all I really need from the response.
json_object *id = json::get_object(parser, JSON_KEY_ID);
if (!id)
if (error::is_null(id))
{
// This doesn't really mean the request wasn't successful. It just means the new directory couldn't be appended
// to the list...
@@ -220,7 +209,7 @@ bool remote::GoogleDrive::upload_file(const fslib::Path &source, std::string_vie
json_object *id = json::get_object(responseParser, JSON_KEY_ID);
json_object *filename = json::get_object(responseParser, JSON_KEY_NAME);
if (!id || !filename)
if (error::is_null({id, filename}))
{
logger::log("Error uploading file: server response is missing data required.");
return false;
@@ -441,7 +430,7 @@ bool remote::GoogleDrive::get_sign_in_data(std::string &message, std::string &co
json_object *expiresIn = json::get_object(parser, "expires_in");
json_object *interval = json::get_object(parser, "interval");
// These are required and fatal.
if (!deviceCode || !userCode || !verificationUrl || !expiresIn || !interval)
if (error::is_null({deviceCode, userCode, verificationUrl, expiresIn, interval}))
{
logger::log(STRING_SIGN_IN_ERROR, "Malformed response.");
return false;
@@ -492,7 +481,7 @@ bool remote::GoogleDrive::poll_sign_in(std::string_view code)
json_object *expiresIn = json::get_object(parser, JSON_KEY_EXPIRES_IN);
json_object *refreshToken = json::get_object(parser, JSON_KEY_REFRESH_TOKEN);
// All of these are required.
if (!accessToken || !expiresIn || !refreshToken)
if (error::is_null({accessToken, expiresIn, refreshToken}))
{
logger::log(STRING_ERROR_POLLING, "Malformed response or missing data!");
return false;
@@ -512,8 +501,8 @@ bool remote::GoogleDrive::poll_sign_in(std::string_view code)
json_object *refreshToken = json_object_new_string(m_refreshToken.c_str());
json_object_object_add(installed, JSON_KEY_REFRESH_TOKEN, refreshToken);
fslib::File configFile(remote::PATH_GOOGLE_DRIVE_CONFIG, FsOpenMode_Create | FsOpenMode_Write);
if (configFile) { configFile << json_object_get_string(config.get()); }
fslib::File configFile{remote::PATH_GOOGLE_DRIVE_CONFIG, FsOpenMode_Create | FsOpenMode_Write};
if (configFile.is_open()) { configFile << json_object_get_string(config.get()); }
}
if (!GoogleDrive::get_root_id()) { return false; }
@@ -548,7 +537,7 @@ bool remote::GoogleDrive::get_root_id()
if (!parser) { return false; }
json_object *rootId = json::get_object(parser, "rootFolderId");
if (!rootId)
if (error::is_null(rootId))
{
logger::log("Error getting drive root directory ID!");
return false;
@@ -594,7 +583,7 @@ bool remote::GoogleDrive::refresh_token()
// These are the only things I care about.
json_object *accessToken = json::get_object(parser, JSON_KEY_ACCESS_TOKEN);
json_object *expiresIn = json::get_object(parser, JSON_KEY_EXPIRES_IN);
if (!accessToken || !expiresIn) { return false; }
if (error::is_null({accessToken, expiresIn})) { return false; }
m_token = json_object_get_string(accessToken);
m_tokenExpires = std::time(NULL) + json_object_get_uint64(expiresIn);
@@ -614,7 +603,7 @@ bool remote::GoogleDrive::request_listing()
url.append_parameter("fields", "nextPageToken,files(name,id,size,parents,mimeType)")
.append_parameter("orderBy", "name_natural")
.append_parameter("pageSize", "256")
.append_parameter("q", "trashed%3Dfalse"); // This might not be the best way to do this...
.append_parameter("q", "trashed%3Dfalse"); // This works, but could get messy if more parameters are added.
std::string response;
curl::prepare_get(m_curl);
@@ -633,7 +622,7 @@ bool remote::GoogleDrive::request_listing()
json::Object parser = json::new_object(json_tokener_parse, response.c_str());
if (!parser || GoogleDrive::error_occurred(parser) || !GoogleDrive::process_listing(parser))
{
logger::log("Error while parseing Google Drive response!");
logger::log("Error while parsing Google Drive response!");
return false;
}
@@ -667,7 +656,7 @@ bool remote::GoogleDrive::process_listing(json::Object &json)
json_object *id = json_object_object_get(currentFile, JSON_KEY_ID);
json_object *name = json_object_object_get(currentFile, JSON_KEY_NAME);
json_object *size = json_object_object_get(currentFile, "size");
if (!mimeType || !parents || !id || !name)
if (error::is_null({mimeType, parents, id, name}))
{
logger::log(STRING_ERROR_PROCESSING, "Malformed or missing data!");
continue;
@@ -675,7 +664,7 @@ bool remote::GoogleDrive::process_listing(json::Object &json)
// I still think it's stupid this is an array when there can only be one...
json_object *parent = json_object_array_get_idx(parents, 0);
if (!parent)
if (error::is_null(parent))
{
logger::log(STRING_ERROR_PROCESSING, "Missing parent ID!");
continue;